Solution: Exercise 01

The following is the solution for Exercise 01.

For this exercise, make sure you run all commands from the directory:

  /path/to/cbat_tools/docs/exercises/01

Task 1

Find out if it is possible to trip the assert in the function is_valid_ID.

First, run wp on the is_valid_ID function in ./binary/main using --trip-asserts:

    $ bap wp \
          --func=is_valid_ID \
          --trip-asserts \
          binary/main

In response, wp says SAT, which means that wp did find a way to trip the assert. Hence, the solution to the first task is: yes, it is possible to trip the assert in the is_valid_ID function.

Task 2

If it is possible to try the assert, use wp's output to determine an example of an argument that will trip the assert.

When you ran the above command, wp provides an example of an argument that will trip the assert. Your output should look something like this (it may not be identical, but it should be very close):

SAT!

Model:
	ZF  |->  0x0
	SF  |->  0x0
	RSP |->  0x000000003f800084
	RSI |->  0x0000000000000000
	RDX |->  0x0000000000000000
	RDI |->  0x00000000dde4ddef  <-- An argument to trip the assert
	RCX |->  0x0000000000000000
	RBP |->  0x0000000000000000
	RAX |->  0x0000000000000000
	R9  |->  0x0000000000000000
	R8  |->  0x0000000000000000
	PF  |->  0x0
	OF  |->  0x0
	CF  |->  0x0
	AF  |->  0x0
	mem_orig |-> [
		else |-> 0x00]
	mem_mod = mem_orig

The argument to the function is always placed in RDI, so look at the value that wp suggests for RDI. In my case, it is 0x00000000dde4ddef, but yours may be different. Whatever value you see there is an example of a number that will trip the assert. Try it from the command line:

    $ ./binary/main 0x00000000dde4ddef

The output shows that the assertion does indeed get triggered:

main: main.c:10: is_valid_ID: Assertion `0' failed.
Aborted

So, an example of an argument that will trip the assert is the value suggested by wp for RDI (which in my case is 0x00000000dde4ddef).

Task 3

Use bildb to step through the program line-by-line, and replicate the behavior of tripping the assert.

You know a value to put in RDI at the beginning of is_valid_ID that will trip the assert. In my case, it was 0x00000000dde4ddef.

Start up bildb at the is_valid_ID function:

    $ bap binary/main \
          --pass=run \
          --run-entry-point=is_valid_ID \
          --bildb-debug

You will see bildb start up, and stop at the first instruction in the is_valid_ID function:

BIL Debugger
Starting up...

Architecture
Type: x86_64
Address size: 64
Registers:
R10    R11    R12    R13    R14    R15    R8     R9     RAX    RBP    RBX    
RCX    RDI    RDX    RSI    RSP    YMM0   YMM1   YMM10  YMM11  YMM12  YMM13  
YMM14  YMM15  YMM2   YMM3   YMM4   YMM5   YMM6   YMM7   YMM8   YMM9   

Entering subroutine: [%000009e9] is_valid_ID
00000a16: is_valid_ID_result :: out u32 = RAX
Entering block %0000042d
00000434: #47 := RBP

Now, set RDI to the value wp suggested earlier, by typing set RDI=VAL, where VAL is the value wp suggested. In my case:

>>> (h for help) set RDI=0x00000000dde4ddef
RDI   : 0xDDE4DDEF

Next, let bildb run the function. Type n (followed by enter) to tell bildb to run to the next block. It will stop at the next block:

>>> (h for help) n
Entering block %0000087a
0000087f: RCX := 0x4006B8

Type n (followed by enter) again, to tell bildb to run forward again. This time, it will enter the __assert_fail function:

>>> (h for help) n
Entering subroutine: [%000009d3] __assert_fail
00000a07: __assert_fail_result :: out u32 = RAX
Entering block %000000bc
000000c2: call mem[0x601018, el]:u64 with noreturn

So, you have triggered the assert. You can now quite bildb by typing q (followed by enter):

>>> (h for help) q
Goodbye

Go back to the list of exercises.