概要
- バイナリファイルを自作して解析する。
- バイナリファイルに隠れている FLAG を手に入れる。
使用ツール
- Visual Studio Code
- objdump
- GHex
手順
1.プログラムを書く
# include <stdio.h>
# include <string.h>
int main() {
char buf[32];
char key[] = "password";
puts("input the password:");
fgets(buf, sizeof(buf), stdin);
strtok(buf, "\n");
if(!strcmp(buf, key)) {
puts("FLAG{ctf_binary}");
} else {
puts("miss");
}
return 0;
}
2.コンパイルしてバイナリファイルを作成する
gcc binary.c -o binary
"binary" というバイナリファイルが生成される。試しに実行してみる。パスワードを聞かれるので、適当に "hogehoge" と入力する。そうすると、"miss" と表示される(間違っているよーと)。
binary
input the password:
hogehoge
miss
3.objdump でバイナリファイルを逆アセンブルする
objdump -D banary
とすると、
<省略>
00000000004006a6 <main>:
4006a6: 55 push rbp
4006a7: 48 89 e5 mov rbp,rsp
4006aa: 48 83 ec 40 sub rsp,0x40
4006ae: 64 48 8b 04 25 28 00 mov rax,QWORD PTR fs:0x28
4006b5: 00 00
4006b7: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
4006bb: 31 c0 xor eax,eax
4006bd: 48 b8 32 30 31 38 5f movabs rax,0x5f34305f38313032
4006c4: 30 34 5f
4006c7: 48 89 45 c0 mov QWORD PTR [rbp-0x40],rax
4006cb: 66 c7 45 c8 32 35 mov WORD PTR [rbp-0x38],0x3532
4006d1: c6 45 ca 00 mov BYTE PTR [rbp-0x36],0x0
4006d5: bf d8 07 40 00 mov edi,0x4007d8
4006da: e8 61 fe ff ff call 400540 <puts@plt>
4006df: 48 8b 15 7a 09 20 00 mov rdx,QWORD PTR [rip+0x20097a] # 601060 <stdin@@GLIBC_2.2.5>
4006e6: 48 8d 45 d0 lea rax,[rbp-0x30]
4006ea: be 20 00 00 00 mov esi,0x20
4006ef: 48 89 c7 mov rdi,rax
4006f2: e8 79 fe ff ff call 400570 <fgets@plt>
4006f7: 48 8d 45 d0 lea rax,[rbp-0x30]
4006fb: be 00 08 40 00 mov esi,0x400800
400700: 48 89 c7 mov rdi,rax
400703: e8 88 fe ff ff call 400590 <strtok@plt>
400708: 48 8d 55 c0 lea rdx,[rbp-0x40]
40070c: 48 8d 45 d0 lea rax,[rbp-0x30]
400710: 48 89 d6 mov rsi,rdx
400713: 48 89 c7 mov rdi,rax
400716: e8 65 fe ff ff call 400580 <strcmp@plt>
40071b: 85 c0 test eax,eax
40071d: 75 0c jne 40072b <main+0x85>
40071f: bf 08 08 40 00 mov edi,0x400808
400724: e8 17 fe ff ff call 400540 <puts@plt>
400729: eb 0a jmp 400735 <main+0x8f>
40072b: bf 51 08 40 00 mov edi,0x400851
400730: e8 0b fe ff ff call 400540 <puts@plt>
400735: b8 00 00 00 00 mov eax,0x0
40073a: 48 8b 4d f8 mov rcx,QWORD PTR [rbp-0x8]
40073e: 64 48 33 0c 25 28 00 xor rcx,QWORD PTR fs:0x28
400745: 00 00
400747: 74 05 je 40074e <main+0xa8>
400749: e8 02 fe ff ff call 400550 <__stack_chk_fail@plt>
40074e: c9 leave
40074f: c3 ret
<省略>
と出力される。注目したいのは、400716 で strcmp が呼ばれていて、少しすると 40071d jne が呼ばれる。この jne 命令(分岐命令)を無効にすることで、パスワードが間違っていても FLAG が手に入るかも。jne を無効にするには、75 0c → 90 90 に書き換える。
4.GHex でバイナリファイルを書き換える
objdump で確認した jne 命令のアドレスは 40071d だから GHex も 700 行目あたりにあるのかな? あったので、75 0c → 90 90 に書き換えてみる。
書き換えたら、名前をつけて保存する。
5.書き換えたバイナリを実行する。
binary
input the password:
hogehoge
FLAG{ctf_binary}
パスワードを聞かれるので、適当に "hogehoge" って入力してみる。2.のときは "miss" と表示されていたが、今度はフラグを見つけることができた!