DVLに収録されているcrackmeのリバースエンジニアリング

DVLには色々なソフトウェアが収録されているので飽きずに遊べます。
今日やったのはcrackmeというソフトをリバースエンジニアリングしてパスワードを当てるといったものです。

まずはどんなものか確認

bt Cyrex_LinuxCrackme1 # ./crackme 
-[ Linux CrackMe (Level:2) by cyrex ]-
-[ TODO: You have to get the valid Password ]-
Enter Password: aaa
-[ Ohhhh, your skills are bad try again later ]-

いつもながらgdbを使って実行していく。

bt Cyrex_LinuxCrackme1 # gdb crackme                  
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

一旦main()に入ったところにブレークポイントを張る。
gdb $ b main
Breakpoint 1 at 0x8048456
gdb $ r
-------------------------------------------------------------------------[ regs]
     eax:BF8FE0EC ebx:B7FC9FFC  ecx:B7FCC19C  edx:00000001     eflags:00000286
     esi:BF8FE0E4 edi:BF8FE070  esp:BF8FE030  ebp:BF8FE058     eip:08048456
     cs:0073  ds:007B  es:007B  fs:0000  gs:0033  ss:007B    o d I t S z a P c 
[007B:BF8FE030]---------------------------------------------------------[stack]
BF8FE060 : 01 00 00 00  E4 E0 8F BF - EC E0 8F BF  6C 1B FF B7 ............l...
BF8FE050 : 00 00 00 00  E0 CC FF B7 - B8 E0 8F BF  14 3E EB B7 .............>..
BF8FE040 : FC 9F FC B7  FC 9F FC B7 - 50 85 04 08  FC 9F FC B7 ........P.......
BF8FE030 : 00 00 00 00  00 00 00 00 - 58 E0 8F BF  0B 85 04 08 ........X.......
[007B:BF8FE0E4]---------------------------------------------------------[ data]
BF8FE0E4 : 64 E6 8F BF  00 00 00 00 - 9F E6 8F BF  ED E6 8F BF d...............
BF8FE0F4 : F4 E6 8F BF  01 E7 8F BF - 0C E7 8F BF  1C E7 8F BF ................
[0073:08048456]---------------------------------------------------------[ code]
0x8048456 <main+6>:     add    esp,0xfffffff4
0x8048459 <main+9>:     push   0x8048620
0x804845e <main+14>:    call   0x804835c <printf@plt>
0x8048463 <main+19>:    add    esp,0x10
0x8048466 <main+22>:    add    esp,0xfffffff4
0x8048469 <main+25>:    push   0x8048660
-------------------------------------------------------------------------------

ブレークポイントで止まったらeipを表示。iを使うことでアセンブラコードを表示できる。
文字列比較にはstrcmp/strncmp辺りを使っていると思うのでそれらしい所を探す。
Breakpoint 1, 0x08048456 in main ()
gdb $ x/50i $eip
0x8048456 <main+6>:     add    esp,0xfffffff4
0x8048459 <main+9>:     push   0x8048620
0x804845e <main+14>:    call   0x804835c <printf@plt>
0x8048463 <main+19>:    add    esp,0x10
0x8048466 <main+22>:    add    esp,0xfffffff4
0x8048469 <main+25>:    push   0x8048660
0x804846e <main+30>:    call   0x804835c <printf@plt>
0x8048473 <main+35>:    add    esp,0x10
0x8048476 <main+38>:    add    esp,0xfffffff4
0x8048479 <main+41>:    push   0x8048690
0x804847e <main+46>:    call   0x804835c <printf@plt>
0x8048483 <main+51>:    add    esp,0x10
0x8048486 <main+54>:    add    esp,0xfffffff8
0x8048489 <main+57>:    lea    eax,[ebp-32]
0x804848c <main+60>:    push   eax
0x804848d <main+61>:    push   0x80486a1
0x8048492 <main+66>:    call   0x804832c <scanf@plt>
0x8048497 <main+71>:    add    esp,0x10
0x804849a <main+74>:    add    esp,0xfffffff8
0x804849d <main+77>:    push   0x80486a4               <---- ここはstrcmpに渡している引数っぽい(こっちは期待するパスワードの文字列のアドレス)
0x80484a2 <main+82>:    lea    eax,[ebp-32]
0x80484a5 <main+85>:    push   eax                     <---- ここはstrcmpに渡している引数っぽい(こっちは入力された文字列)
0x80484a6 <main+86>:    call   0x804831c <strcmp@plt>  <---- ここがパスワードを比較している箇所だろう。
0x80484ab <main+91>:    add    esp,0x10
0x80484ae <main+94>:    mov    eax,eax
0x80484b0 <main+96>:    test   eax,eax
0x80484b2 <main+98>:    jne    0x80484c6 <main+118>
0x80484b4 <main+100>:   add    esp,0xfffffff4
0x80484b7 <main+103>:   push   0x80486c0
0x80484bc <main+108>:   call   0x804835c <printf@plt>
0x80484c1 <main+113>:   add    esp,0x10
0x80484c4 <main+116>:   jmp    0x80484d6 <main+134>
0x80484c6 <main+118>:   add    esp,0xfffffff4
0x80484c9 <main+121>:   push   0x8048700
0x80484ce <main+126>:   call   0x804835c <printf@plt>
0x80484d3 <main+131>:   add    esp,0x10
0x80484d6 <main+134>:   xor    eax,eax
0x80484d8 <main+136>:   jmp    0x80484e0 <main+144>
0x80484da <main+138>:   lea    esi,[esi]
0x80484e0 <main+144>:   leave  
0x80484e1 <main+145>:   ret    
0x80484e2 <main+146>:   lea    esi,[esi]
0x80484e9 <main+153>:   lea    edi,[edi]
0x80484f0 <__libc_csu_init>:    push   ebp
0x80484f1 <__libc_csu_init+1>:  mov    ebp,esp
0x80484f3 <__libc_csu_init+3>:  push   edi
0x80484f4 <__libc_csu_init+4>:  push   esi
0x80484f5 <__libc_csu_init+5>:  xor    esi,esi
0x80484f7 <__libc_csu_init+7>:  push   ebx
0x80484f8 <__libc_csu_init+8>:  sub    esp,0xc

ではスタックにpushしているアドレスの内容を表示してみる。
gdb $ x/s 0x80486a4
0x80486a4 <_IO_stdin_used+160>:  "47ghf6fh37fbgbgj"
あー。なにやら怪しい文字列が見えたのでこれをパスワードとして入力してみる。

gdb $ c
-[ Linux CrackMe (Level:2) by cyrex ]-
-[ TODO: You have to get the valid Password ]-
Enter Password: 47ghf6fh37fbgbgj
-[ Good, You're ready to begin linux reversing ]-

Program exited normally.
-------------------------------------------------------------------------[ regs]
Error while running hook_stop:
No registers.
gdb $ q
bt Cyrex_LinuxCrackme1 # 

というわけで、0x80486a4のアドレスの内容が見事にパスワードだったというわけです。