Doing the bomb lab with r2 phase 1.

6 minute read

In this sequence of tutorials I am going to discuss bomb lab. I got this from Xeno Kovah’s IntoX86 course. This particular ‘crack me’ is composed of six phases plus one hidden phase that you have to figure out how to find before you go ahead and crack it.

First of all, it is a 32 bit non-stripped binary, this means that it contains lots of symbols and may contain debug information. The binary is also protected against buffer overflow (at least it looks so).

Basic testing

so lets run the program in r2:

  ~ r2 bomb
 -- Control the height of the terminal on serial consoles with e scr.height
 [0x080488e0]> aa
 [x] Analyze all flags starting with sym. and entry0 (aa)
 [0x080488e0]> 	afl
 0x080486e0    3 47           sym._init
 0x08048720    2 16   -> 32   sym.imp.__register_frame_info
 0x08048730    2 16   -> 48   sym.imp.close
 0x08048740    2 16   -> 48   sym.imp.fprintf
 0x08048750    2 16   -> 48   sym.imp.tmpfile
 0x08048760    2 16   -> 48   sym.imp.getenv
 0x08048770    2 16   -> 48   sym.imp.signal
 0x08048780    2 16   -> 48   sym.imp.fflush
 0x08048790    2 16   -> 48   sym.imp.bcopy
 0x080487a0    2 16   -> 48   sym.imp.rewind
 0x080487b0    2 16   -> 48   sym.imp.system
 0x080487c0    2 16   -> 48   sym.imp.__deregister_frame_info
 0x080487d0    2 16   -> 48   sym.imp.fgets
 0x080487e0    2 16   -> 48   sym.imp.sleep
 0x080487f0    2 16   -> 48   sym.imp.__strtol_internal
 0x08048800    2 16   -> 48   sym.imp.__libc_start_main
 0x08048810    2 16   -> 48   sym.imp.printf
 0x08048820    2 16   -> 48   sym.imp.fclose
 0x08048830    2 16   -> 48   sym.imp.gethostbyname
 0x08048840    2 16   -> 48   sym.imp.bzero
 0x08048850    2 16   -> 48   sym.imp.exit
 0x08048860    2 16   -> 48   sym.imp.sscanf
 0x08048870    2 16   -> 48   sym.imp.connect
 0x08048880    2 16   -> 48   sym.imp.fopen
 0x08048890    2 16   -> 48   sym.imp.dup
 0x080488a0    2 16   -> 48   sym.imp.sprintf
 0x080488b0    2 16   -> 48   sym.imp.socket
 0x080488c0    2 16   -> 48   sym.imp.cuserid
 0x080488d0    2 16   -> 48   sym.imp.strcpy
 0x080488e0    1 34           entry0
 0x08048910    8 81           sym.__do_global_dtors_aux
 0x08048964    1 10           sym.fini_dummy
 0x08048970    3 37           sym.frame_dummy
 0x08048998    1 10           sym.init_dummy
 0x080489b0    7 365  -> 357  sym.main
 0x08048b20    3 39           sym.phase_1
 0x08048b48    7 79           sym.phase_2
 0x08048b98    7 264  -> 93   sym.phase_3
 0x08048ca0    4 62   -> 60   sym.func4
 0x08048ce0    6 75           sym.phase_4
 0x08048d2c    7 105          sym.phase_5
 0x08048d98   21 249          sym.phase_6
 0x08048e94    8 82   -> 72   sym.fun7
 0x08048ee8    5 96           sym.secret_phase
 0x08048f50    1 98           sym.sig_handler
 0x08048fb4    1 33           sym.invalid_phase
 0x08048fd8    3 61           sym.read_six_numbers
 0x08049018    3 24           sym.string_length
 0x08049030    8 89   -> 87   sym.strings_not_equal
 0x0804908c    7 212  -> 210  sym.open_clientfd
 0x08049160    1 25           sym.initialize_bomb
 0x0804917c    7 50   -> 49   sym.blank_line
 0x080491b0    4 74           sym.skip
 0x080491fc    9 193          sym.read_line
 0x080492c0   22 570  -> 552  sym.send_msg
 0x080494fc    1 45           sym.explode_bomb
 0x0804952c    6 122          sym.phase_defused
 0x080495b0    3 38           sym.__do_global_ctors_aux
 0x080495d8    1 10           sym.init_dummy_1
 0x080495e4    1 26           obj._etext
 [0x080489b0]> 

The afl commmand is used to list all the available functions. This will be usefull for a couple of reasons: First of all, if there are a few functions or no functions except for entry0 availabe, then it is a strong indication that the binary is packed. In addition, function names in “non stripped binaries” always give good stating point for where to go and reverse engineer. In our case hopefully the binary file is not packed, and as you can notice the functions named sym.phase_1 up to sym.phase_6, so apparently they will be our target for now. Lets start by seeking to sym.phase_1 and disassembling there:

[0x080488e0]> s sym.phase_1
[0x08048b20]> pdf
            ;-- gcc2_compiled._5:
	    / (fcn) sym.phase_1 39
	    |           ; arg int arg_8h @ ebp+0x8
	    |           ; CALL XREF from 0x08048a5b (sym.main)
	    |           0x08048b20      55             push ebp
	    |           0x08048b21      89e5           mov ebp, esp
	    |           0x08048b23      83ec08         sub esp, 8
	    |           0x08048b26      8b4508         mov eax, dword [ebp + arg_8h] ; [0x8:4]=0
	    |           0x08048b29      83c4f8         add esp, -8
	    |           0x08048b2c      68c0970408     push str.Public_speaking_is_very_easy. ; @ 0x80497c0
	    |           0x08048b31      50             push eax
	    |           0x08048b32      e8f9040000     call sym.strings_not_equal
	    |           0x08048b37      83c410         add esp, 0x10
	    |           0x08048b3a      85c0           test eax, eax
	    |       ,=< 0x08048b3c      7405           je 0x8048b43
	    |       |   0x08048b3e      e8b9090000     call sym.explode_bomb
	    |       `-> 0x08048b43      89ec           mov esp, ebp
	    |           0x08048b45      5d             pop ebp
	    \           0x08048b46      c3             ret
[0x08048b20]>

This function takes one argument arg_8h, then passes it with str.Public_speaking_is_very_easy to the function, sym.string_not_equal. Then call the function, sym.explode_bomb if they are not equal. So that string is the password. ps will print string at the current seek (that number inside those square brackets), and the @ symbol will change the current seek temporarily till the end of the current command.

[0x08048b20]> ps @ str.Public_speaking_is_very_easy.
Public speaking is very easy.
[0x08048b20]> 

And that was the first key. phase 1 defused

Leave a Comment