CODEGATE 2014 dodoCrackme writeup

Reversingカテゴリ。
200点。
このエントリ無駄に縦に長くなった。

crackme_d079a0af0b01789c01d5755c885da4f6を取得。
とりあえず file コマンド。

tkito@Ubuntu1204_x64:~$ file crackme_d079a0af0b01789c01d5755c885da4f6
crackme_d079a0af0b01789c01d5755c885da4f6: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=0xb300ef9227a8911db0d6aea538fe03fe4dfb20fe, stripped

64bit Linux用のバイナリらしい。ちょうど手元の環境が64bitだったので実行。

tkito@Ubuntu1204_x64:~$ chmod +x crackme_d079a0af0b01789c01d5755c885da4f6
tkito@Ubuntu1204_x64:~$ ./crackme_d079a0af0b01789c01d5755c885da4f6
root@localhost's password:

何か聞かれたので適当に入力する。

root@localhost's password: hogehoge
Permission denied (password).

ですよねー。
このパターンは正解がKeyか、正解を入れるとKeyが出て来るかのどちらかだと推測。
では中で何やってるのか確認するためにstraceしてみる。

tkito@Ubuntu1204_x64:~$ strace -o output.txt ./crackme_d079a0af0b01789c01d5755c885da4f6
root@localhost's password: hogehoge
Permission denied (password).
tkito@Ubuntu1204_x64:~$ cat output.txt
execve("./crackme_d079a0af0b01789c01d5755c885da4f6", ["./crackme_d079a0af0b01789c01d575"...], [/* 40 vars */]) = 0
mmap(NULL, 30000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f041f21e000
write(1, "r", 1)                        = 1
write(1, "o", 1)                        = 1
write(1, "o", 1)                        = 1
write(1, "t", 1)                        = 1
write(1, "@", 1)                        = 1
write(1, "l", 1)                        = 1
write(1, "o", 1)                        = 1
write(1, "c", 1)                        = 1
write(1, "a", 1)                        = 1
write(1, "l", 1)                        = 1
write(1, "h", 1)                        = 1
write(1, "o", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, "t", 1)                        = 1
write(1, "'", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, " ", 1)                        = 1
write(1, "p", 1)                        = 1
write(1, "a", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, "w", 1)                        = 1
write(1, "o", 1)                        = 1
write(1, "r", 1)                        = 1
write(1, "d", 1)                        = 1
write(1, ":", 1)                        = 1
write(1, " ", 1)                        = 1
read(0, "h", 1)                         = 1
read(0, "o", 1)                         = 1
read(0, "g", 1)                         = 1
read(0, "e", 1)                         = 1
read(0, "h", 1)                         = 1
read(0, "o", 1)                         = 1
read(0, "g", 1)                         = 1
read(0, "e", 1)                         = 1
read(0, "\n", 1)                        = 1
write(1, "P", 1)                        = 1
write(1, "e", 1)                        = 1
write(1, "r", 1)                        = 1
write(1, "m", 1)                        = 1
write(1, "i", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, "i", 1)                        = 1
write(1, "o", 1)                        = 1
write(1, "n", 1)                        = 1
write(1, " ", 1)                        = 1
write(1, "d", 1)                        = 1
write(1, "e", 1)                        = 1
write(1, "n", 1)                        = 1
write(1, "i", 1)                        = 1
write(1, "e", 1)                        = 1
write(1, "d", 1)                        = 1
write(1, " ", 1)                        = 1
write(1, "(", 1)                        = 1
write(1, "p", 1)                        = 1
write(1, "a", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, "s", 1)                        = 1
write(1, "w", 1)                        = 1
write(1, "o", 1)                        = 1
write(1, "r", 1)                        = 1
write(1, "d", 1)                        = 1
write(1, ")", 1)                        = 1
write(1, ".", 1)                        = 1
write(1, "\n", 1)                       = 1
_exit(0)                                = ?

mmapしてメモリ領域確保した後は標準出力に出して標準入力から読んで結果を出力する、しかしていない。
ファイルアクセス一切なし。すべてはメモリ内で完結している。

バイナリを見てみる。手元に64bitバイナリ読めるIDAがなかったのでobjdumpで。

tkito@Ubuntu1204_x64:~$ objdump -M intel -d crackme_d079a0af0b01789c01d5755c885da4f6
crackme_d079a0af0b01789c01d5755c885da4f6:     file format elf64-x86-64

Disassembly of section .text:

00000000004000e0 <.text>:
4000e0:    b8 3c 00 00 00           mov    eax,0x3c
4000e5:    bf 00 00 00 00           mov    edi,0x0
4000ea:    0f 05                    syscall
4000ec:    41 b9 00 00 00 00        mov    r9d,0x0
4000f2:    49 c7 c0 ff ff ff ff     mov    r8,0xffffffffffffffff
4000f9:    41 ba 22 00 00 00        mov    r10d,0x22
4000ff:    ba 03 00 00 00           mov    edx,0x3
400104:    be 30 75 00 00           mov    esi,0x7530
400109:    bf 00 00 00 00           mov    edi,0x0
40010e:    b8 09 00 00 00           mov    eax,0x9
400113:    0f 05                    syscall
400115:    48 83 f8 00              cmp    rax,0x0
400119:    7e c5                    jle    0x4000e0
40011b:    48 89 c5                 mov    rbp,rax
40011e:    48 81 c5 98 3a 00 00     add    rbp,0x3a98
400125:    48 8d 0c 25 03 c3 40     lea    rcx,ds:0x40c303
40012c:    00
40012d:    48 8d 14 25 0b c3 40     lea    rdx,ds:0x40c30b
400134:    00
400135:    8a 45 00                 mov    al,BYTE PTR [rbp+0x0]
400138:    84 c0                    test   al,al
40013a:    74 1f                    je     0x40015b
40013c:    eb 00                    jmp    0x40013e

syscall命令は、eaxの値に応じたシステムコールを実行する。9はmmapである。0がreadで1がwrite。
少し下を見ると、rbpに8を足したり8を引いたりしつつ、rbpが指すメモリアドレスの値をインクリメントしたりデクリメントしたりしている。
なお、rbpの値はmmapで確保されたメモリ内部のアドレスになっている。

40015b:       48 8d 6d 08             lea    rbp,[rbp+0x8]
40015f:       fe 45 00                inc    BYTE PTR [rbp+0x0]
400162:       48 8d 6d f8             lea    rbp,[rbp-0x8]
400166:       fe 45 00                inc    BYTE PTR [rbp+0x0]
400169:       8a 45 00                mov    al,BYTE PTR [rbp+0x0]
40016c:       84 c0                   test   al,al
40016e:       0f 84 8a c1 00 00       je     0x40c2fe
400174:       eb 00                   jmp    0x400176
400176:       48 8d 6d 08             lea    rbp,[rbp+0x8]
40017a:       8a 45 00                mov    al,BYTE PTR [rbp+0x0]
40017d:       84 c0                   test   al,al
40017f:       74 2e                   je     0x4001af
400181:       eb 00                   jmp    0x400183
400183:       48 8d 6d 08             lea    rbp,[rbp+0x8]
400187:       8a 45 00                mov    al,BYTE PTR [rbp+0x0]
40018a:       84 c0                   test   al,al
40018c:       74 0e                   je     0x40019c
40018e:       eb 00                   jmp    0x400190
400190:       fe 4d 00                dec    BYTE PTR [rbp+0x0]
400193:       8a 45 00                mov    al,BYTE PTR [rbp+0x0]
400196:       84 c0                   test   al,al
400198:       74 02                   je     0x40019c
40019a:       eb f4                   jmp    0x400190

この少し下でwriteを行って”root@localhost’s password:”を出力して、ひたすらインクリメントとデクリメントを繰り返している。
readを実行するのは大分下、アドレス0x4065aeである。
この処理をずっと追うのも大変なのでデバッガで実行する。

tkito@Ubuntu1204_x64:~$ gdb ./crackme_d079a0af0b01789c01d5755c885da4f6
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/tkito/crackme_d079a0af0b01789c01d5755c885da4f6...(no debugging symbols found)...done.
(gdb) set pagination 0
(gdb) b *0x400125
Breakpoint 1 at 0x400125
(gdb) b *0x4065ae
Breakpoint 2 at 0x4065ae
(gdb) r
Starting program: /home/tkito/crackme_d079a0af0b01789c01d5755c885da4f6
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffd000

Breakpoint 1, 0x0000000000400125 in ?? ()
(gdb) i r rbp
rbp            0x7ffff7ff8a98    0x7ffff7ff8a98
(gdb) c
Continuing.
root@localhost's password:
Breakpoint 2, 0x00000000004065ae in ?? ()
(gdb) x/88xg 0x7ffff7ff8a98
0x7ffff7ff8a98:    0x0000000000000001    0x0000000000000001
0x7ffff7ff8aa8:    0x0000000000000001    0x0000000000000000
0x7ffff7ff8ab8:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8ac8:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8ad8:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8ae8:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8af8:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8b08:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8b18:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8b28:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8b38:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8b48:    0x0000000000000000    0x0000000000000000
0x7ffff7ff8b58:    0x0000000000000048    0x0000000000000000
0x7ffff7ff8b68:    0x0000000000000034    0x0000000000000000
0x7ffff7ff8b78:    0x0000000000000050    0x0000000000000000
0x7ffff7ff8b88:    0x0000000000000050    0x0000000000000000
0x7ffff7ff8b98:    0x0000000000000059    0x0000000000000000
0x7ffff7ff8ba8:    0x000000000000005f    0x0000000000000000
0x7ffff7ff8bb8:    0x0000000000000043    0x0000000000000000
0x7ffff7ff8bc8:    0x0000000000000030    0x0000000000000000
0x7ffff7ff8bd8:    0x0000000000000044    0x0000000000000000
0x7ffff7ff8be8:    0x0000000000000045    0x0000000000000000
0x7ffff7ff8bf8:    0x0000000000000047    0x0000000000000000
0x7ffff7ff8c08:    0x0000000000000061    0x0000000000000000
0x7ffff7ff8c18:    0x0000000000000054    0x0000000000000000
0x7ffff7ff8c28:    0x0000000000000045    0x0000000000000000
0x7ffff7ff8c38:    0x000000000000005f    0x0000000000000000
0x7ffff7ff8c48:    0x0000000000000032    0x0000000000000000
0x7ffff7ff8c58:    0x0000000000000030    0x0000000000000000
0x7ffff7ff8c68:    0x0000000000000031    0x0000000000000000
0x7ffff7ff8c78:    0x0000000000000034    0x0000000000000000
0x7ffff7ff8c88:    0x000000000000005f    0x0000000000000000
0x7ffff7ff8c98:    0x0000000000000043    0x0000000000000000
0x7ffff7ff8ca8:    0x0000000000000055    0x0000000000000000
0x7ffff7ff8cb8:    0x000000000000005f    0x0000000000000000
0x7ffff7ff8cc8:    0x0000000000000031    0x0000000000000000
0x7ffff7ff8cd8:    0x000000000000004e    0x0000000000000000
0x7ffff7ff8ce8:    0x000000000000005f    0x0000000000000000
0x7ffff7ff8cf8:    0x000000000000004b    0x0000000000000000
0x7ffff7ff8d08:    0x0000000000000030    0x0000000000000000
0x7ffff7ff8d18:    0x0000000000000052    0x0000000000000000
0x7ffff7ff8d28:    0x0000000000000045    0x0000000000000000
0x7ffff7ff8d38:    0x0000000000000034    0x0000000000000000
0x7ffff7ff8d48:    0x0000000000000000    0x0000000000000000

0x400125まで実行してrbpの値をメモし、0x4065ae(readのところ)まで実行して先ほどメモした値周辺のメモリを表示する。
すると、0x7ffff7ff8b58あたりから文字っぽいデータが16バイトごとに1バイトずつ存在しているのが見える。
これを並べると、以下の文字列になる。

H4PPY_C0DEGaTE_2014_CU_1N_K0RE4

これをパスワードとして入力してみる。

tkito@Ubuntu1204_x64:~$ ./crackme_d079a0af0b01789c01d5755c885da4f6
root@localhost's password: H4PPY_C0DEGaTE_2014_CU_1N_K0RE4
SUCCESS

というわけでこれがKeyでした。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください