.first_steps

OK, enough of praising r2, lets start reversing this stuff. First, you have to know your enemy:

  1. [0x00 avatao]$ rabin2 -I reverse4
  2. pic false
  3. canary true
  4. nx true
  5. crypto false
  6. va true
  7. intrp /lib64/ld-linux-x86-64.so.2
  8. bintype elf
  9. class ELF64
  10. lang c
  11. arch x86
  12. bits 64
  13. machine AMD x86-64 architecture
  14. os linux
  15. subsys linux
  16. endian little
  17. stripped true
  18. static false
  19. linenum false
  20. lsyms false
  21. relocs false
  22. rpath NONE
  23. binsz 8620

r2 tip: rabin2 is one of the handy tools that comes with radare2. It can be used to extract information (imports, symbols, libraries, etc.) about binary executables. As always, check the help (rabin2 -h)!

So, its a dynamically linked, stripped, 64bit Linux executable - nothing fancy here. Let’s try to run it:

  1. [0x00 avatao]$ ./reverse4
  2. ?
  3. Size of data: 2623
  4. pamparam
  5. Wrong!
  6. [0x00 avatao]$ "\x01\x00\x00\x00" | ./reverse4
  7. Size of data: 1

OK, so it reads a number as a size from the standard input first, than reads further, probably “size” bytes/characters, processes this input, and outputs either “Wrong!”, nothing or something else, presumably our flag. But do not waste any more time monkeyfuzzing the executable, let’s fire up r2, because in asm we trust!

  1. [0x00 avatao]$ r2 -A reverse4
  2. -- Heisenbug: A bug that disappears or alters its behavior when one attempts to probe or isolate it.
  3. [0x00400720]>

r2 tip: The -A switch runs aaa command at start to analyze all referenced code, so we will have functions, strings, XREFS, etc. right at the beginning. As usual, you can get help with ?.

It is a good practice to create a project, so we can save our progress, and we can come back at a later time:

  1. [0x00400720]> Ps avatao_reverse4
  2. avatao_reverse4
  3. [0x00400720]>

r2 tip: You can save a project using Ps [file], and load one using Po [file]. With the -p option, you can load a project when starting r2.

We can list all the strings r2 found:

  1. [0x00400720]> fs strings
  2. [0x00400720]> f
  3. 0x00400e98 7 str.Wrong_
  4. 0x00400e9f 27 str.We_are_in_the_outer_space_
  5. 0x00400f80 18 str.Size_of_data:__u_n
  6. 0x00400f92 23 str.Such_VM__MuCH_reV3rse_
  7. 0x00400fa9 16 str.Use_everything_
  8. 0x00400fbb 9 str.flag.txt
  9. 0x00400fc7 26 str.You_won__The_flag_is:__s_n
  10. 0x00400fe1 21 str.Your_getting_closer_
  11. [0x00400720]>

r2 tip: r2 puts so called flags on important/interesting offsets, and organizes these flags into flagspaces (strings, functions, symbols, etc.) You can list all flagspaces using fs, and switch the current one using fs [flagspace] (the default is *, which means all the flagspaces). The command f prints all flags from the currently selected flagspace(s).

OK, the strings looks interesting, especially the one at 0x00400f92. It seems to hint that this crackme is based on a virtual machine. Keep that in mind!

These strings could be a good starting point if we were talking about a real-life application with many-many features. But we are talking about a crackme, and they tend to be small and simple, and focused around the problem to be solved. So I usually just take a look at the entry point(s) and see if I can figure out something from there. Nevertheless, I’ll show you how to find where these strings are used:

  1. [0x00400720]> axt @@=`f~[0]`
  2. d 0x400cb5 mov edi, str.Size_of_data:__u_n
  3. d 0x400d1d mov esi, str.Such_VM__MuCH_reV3rse_
  4. d 0x400d4d mov edi, str.Use_everything_
  5. d 0x400d85 mov edi, str.flag.txt
  6. d 0x400db4 mov edi, str.You_won__The_flag_is:__s_n
  7. d 0x400dd2 mov edi, str.Your_getting_closer_

r2 tip: We can list crossreferences to addresses using the axt [addr] command (similarly, we can use axf to list references from the address). The @@ is an iterator, it just runs the command once for every arguments listed.

The argument list in this case comes from the command f~[0]. It lists the strings from the executable with f, and uses the internal grep command ~ to select only the first column ([0]) that contains the strings’ addresses.