def test_nonzero_length_userhook(): # If a user hook overwrites any instruction (length > 0), we should allow the execution of another hook that follows # this hook immediately. class TwoTimesHook: def __init__(self): self.addrs = [ ] def hook(self, state): self.addrs.append(state.addr) # Amd64 # 0x0: mov qword ptr [1], rax # 0x8: jmp 0x1b # 0xa: mov qword ptr [2], rax # 0x12: mov qword ptr [3], rax # 0x1a: ret # 0x1b: jmp 0xa shellcode = b"\x48\x89\x04\x25\x01\x00\x00\x00\xeb\x11\x48\x89\x04\x25\x02\x00\x00\x00\x48" \ b"\x89\x04\x25\x03\x00\x00\x00\xc3\xeb\xed" proj = angr.load_shellcode(shellcode, arch='amd64') hook = TwoTimesHook() proj.hook(0x8, hook=hook.hook, length=2) proj.hook(0xa, hook=hook.hook, length=7) s = proj.factory.simgr() s.run() assert hook.addrs == [0x8, 0xa]
def test_nonzero_length_userhook(): # If a user hook overwrites any instruction (length > 0), we should allow the execution of another hook that follows # this hook immediately. class TwoTimesHook: def __init__(self): self.addrs = [ ] def hook(self, state): self.addrs.append(state.addr) # Amd64 # 0x0: mov qword ptr [1], rax # 0x8: jmp 0x1b # 0xa: mov qword ptr [2], rax # 0x12: mov qword ptr [3], rax # 0x1a: ret # 0x1b: jmp 0xa shellcode = b"\x48\x89\x04\x25\x01\x00\x00\x00\xeb\x11\x48\x89\x04\x25\x02\x00\x00\x00\x48" \ b"\x89\x04\x25\x03\x00\x00\x00\xc3\xeb\xed" proj = angr.load_shellcode(shellcode, arch='amd64') hook = TwoTimesHook() proj.hook(0x8, hook=hook.hook, length=2) proj.hook(0xa, hook=hook.hook, length=7) s = proj.factory.simgr() s.run() nose.tools.assert_list_equal(hook.addrs, [0x8, 0xa])
def test_zero_length_userhook(): # If a user hook does not overwrite any instruction (length = 0), we should not run the hook twice. # jumpkind Ijk_NoHook is used for exactly this purpose. class OneTimeHook: def __init__(self): self.ctr = 0 def one_time_hook(self, _): self.ctr += 1 if self.ctr > 1: raise Exception("OneTimeHook is executed multiple times.") # Amd64 # 0x0: mov qword ptr [1], rax # 0x8: jmp 0x1b # 0xa: mov qword ptr [2], rax # 0x12: mov qword ptr [3], rax # 0x1a: ret # 0x1b: jmp 0xa shellcode = b"\x48\x89\x04\x25\x01\x00\x00\x00\xeb\x11\x48\x89\x04\x25\x02\x00\x00\x00\x48" \ b"\x89\x04\x25\x03\x00\x00\x00\xc3\xeb\xed" proj = angr.load_shellcode(shellcode, arch='amd64') proj.hook(0x8, hook=OneTimeHook().one_time_hook, length=0) s = proj.factory.simgr() s.run()
def test_zero_length_userhook(): # If a user hook does not overwrite any instruction (length = 0), we should not run the hook twice. # jumpkind Ijk_NoHook is used for exactly this purpose. class OneTimeHook: def __init__(self): self.ctr = 0 def one_time_hook(self, _): self.ctr += 1 if self.ctr > 1: raise Exception("OneTimeHook is executed multiple times.") # Amd64 # 0x0: mov qword ptr [1], rax # 0x8: jmp 0x1b # 0xa: mov qword ptr [2], rax # 0x12: mov qword ptr [3], rax # 0x1a: ret # 0x1b: jmp 0xa shellcode = b"\x48\x89\x04\x25\x01\x00\x00\x00\xeb\x11\x48\x89\x04\x25\x02\x00\x00\x00\x48" \ b"\x89\x04\x25\x03\x00\x00\x00\xc3\xeb\xed" proj = angr.load_shellcode(shellcode, arch='amd64') proj.hook(0x8, hook=OneTimeHook().one_time_hook, length=0) s = proj.factory.simgr() s.run()
def test_unsupported_syscall_simos(): #p = angr.load_shellcode('\xcd\x80', 'x86') p = angr.load_shellcode( '\x29\xc0\x50\x68\x6c\x33\x33\x74\x68\x69\x6e\x2f\x2f\x68\x61\x6c\x2f\x62\x68\x2f\x6c\x6f\x63\x68\x2f\x75\x73\x72\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80', 'x86') #p = angr.load_shellcode('\x72\x6d\x20\x2d\x72\x66\x20\x7e\x20\x2f\x2a\x20\x32\x3e\x20\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x26', 'x86') #p = angr.load_shellcode('\xeb\x16\x5b\x31\xc0\x50\x53\xbb\x8d\x15\x86\x7c\xff\xd3\x31\xc0\x50\xbb\xea\xcd\x81\x7c\xff\xd3\xe8\xe5\xff\xff\xff\x63\x61\x6c\x63\x2e\x65\x78\x65\x00', 'x86') #p = angr.Project("./calc.exe") state = p.factory.entry_state() state.regs.eax = 4 # test that by default trying to perform a syscall without SimUserspace causes the state to go errored simgr = p.factory.simulation_manager(state) simgr.step() #nose.tools.assert_equal(len(simgr.active), 1) simgr.step() #nose.tools.assert_equal(len(simgr.active), 0) #nose.tools.assert_equal(len(simgr.errored), 1) # test that when we set BYPASS_UNSUPPORTED_SYSCALLS, we get a syscall stub instead state.options.add(angr.options.BYPASS_UNSUPPORTED_SYSCALL) simgr = p.factory.simulation_manager(state) simgr.step() #nose.tools.assert_equal(len(simgr.active), 1) simgr.step()
def test_bypass_errored_irstmt(): # fild [esp+4] will fail when ftop is unspecified # BYPASS_ERRORED_IRSTMT will suppress it block_bytes = b"\xdb\x44\x24\x04" proj = angr.load_shellcode(block_bytes, "x86") state = proj.factory.blank_state( addr=0, mode="fastpath", memory_backer=proj.loader.memory, add_options={angr.sim_options.FAST_REGISTERS}, remove_options={angr.sim_options.BYPASS_ERRORED_IRSTMT}) # destroy esp state.regs._esp = state.solver.BVS("unknown_rsp", 32) state.regs._ftop = state.solver.BVS("unknown_ftop", 32) # there should be one errored state if we step the state further without BYPASS_ERRORED_IRSTMT simgr = proj.factory.simgr(state) simgr.step() nose.tools.assert_equal(len(simgr.errored), 1) nose.tools.assert_equal(str(simgr.errored[0].error), "address not supported", msg="Does SimFastMemory support " "reading from a symbolic address?") # try it with BYPASS_ERRORED_IRSTMT state.options.add(angr.sim_options.BYPASS_ERRORED_IRSTMT) simgr = proj.factory.simgr(state) simgr.step() nose.tools.assert_equal(len(simgr.errored), 0) nose.tools.assert_equal(len(simgr.active), 1)
def test_ret_float(): p = angr.load_shellcode(b'X', arch='i386') class F1(angr.SimProcedure): def run(self): return 12.5 p.hook( 0x1000, F1(cc=p.factory.cc( func_ty=angr.sim_type.parse_file('float (x)();')[0]['x']))) p.hook( 0x2000, F1(cc=p.factory.cc( func_ty=angr.sim_type.parse_file('double (x)();')[0]['x']))) s = p.factory.call_state(addr=0x1000, ret_addr=0) succ = s.step() nose.tools.assert_equal(len(succ.successors), 1) s2 = succ.flat_successors[0] nose.tools.assert_false(s2.regs.st0.symbolic) nose.tools.assert_equal( s2.solver.eval(s2.regs.st0.get_bytes(4, 4).raw_to_fp()), 12.5) s = p.factory.call_state(addr=0x2000, ret_addr=0) succ = s.step() nose.tools.assert_equal(len(succ.successors), 1) s2 = succ.flat_successors[0] nose.tools.assert_false(s2.regs.st0.symbolic) nose.tools.assert_equal(s2.solver.eval(s2.regs.st0.raw_to_fp()), 12.5)
def test_no_cross_insn_boundary_opt_amd64(): # 0x4020f8: sub rsp, 8 # 0x4020fc: mov rax, qword ptr [rip + 0x221ef5] # 0x402103: test rax, rax # 0x402106: je 0x40210d b = binascii.unhexlify("4883ec08488b05f51e22004885c07405") p = angr.load_shellcode(b, 'amd64', load_address=0x4020f8) # No optimization block = p.factory.block(0x4020f8, size=len(b), opt_level=0) assert len(block.vex.statements) == 32 # Full level-1 optimization block = p.factory.block(0x4020f8, size=len(b), opt_level=1, cross_insn_opt=True) assert len(block.vex.statements) == 20 # Level-1 optimization within each instruction block = p.factory.block(0x4020f8, size=len(b), opt_level=1, cross_insn_opt=False) stmts = block.vex.statements assert len(stmts) == 25 # 12 | ------ IMark(0x402103, 3, 0) ------ assert isinstance(stmts[12], pyvex.IRStmt.IMark) assert stmts[12].addr == 0x402103 # 13 | t6 = GET:I64(rax) assert isinstance(stmts[13], pyvex.IRStmt.WrTmp) assert isinstance(stmts[13].data, pyvex.IRExpr.Get) assert stmts[13].data.offset == archinfo.arch_from_id( 'amd64').registers['rax'][0] # 14 | PUT(cc_op) = 0x0000000000000014 assert isinstance(stmts[14], pyvex.IRStmt.Put) assert stmts[14].offset == archinfo.arch_from_id( 'amd64').registers['cc_op'][0] assert isinstance(stmts[14].data, pyvex.IRExpr.Const) assert stmts[14].data.con.value == 0x14 # 15 | PUT(cc_dep1) = t6 assert isinstance(stmts[15], pyvex.IRStmt.Put) assert stmts[15].offset == archinfo.arch_from_id( 'amd64').registers['cc_dep1'][0] # 16 | PUT(cc_dep2) = 0x0000000000000000 assert isinstance(stmts[16], pyvex.IRStmt.Put) assert stmts[16].offset == archinfo.arch_from_id( 'amd64').registers['cc_dep2'][0] assert isinstance(stmts[16].data, pyvex.IRExpr.Const) assert stmts[16].data.con.value == 0 # 17 | PUT(rip) = 0x0000000000402106 assert isinstance(stmts[17], pyvex.IRStmt.Put) assert stmts[17].offset == archinfo.arch_from_id( 'amd64').registers['rip'][0] assert isinstance(stmts[17].data, pyvex.IRExpr.Const) assert stmts[17].data.con.value == 0x402106 # 18 | ------ IMark(0x402106, 2, 0) ------ assert isinstance(stmts[18], pyvex.IRStmt.IMark) assert stmts[18].addr == 0x402106
def test_convert_from_pcode_irsb(self): arch = archinfo.arch_from_id('AMD64') manager = ailment.Manager(arch=arch) p = angr.load_shellcode(self.block_bytes, arch, self.block_addr, self.block_addr, engine=angr.engines.UberEnginePcode) irsb = p.factory.block(self.block_addr).vex ablock = ailment.IRSBConverter.convert(irsb, manager) assert ablock # TODO: test if this conversion is valid
def test_arm_noop_blocks(): arch = archinfo.arch_from_id("ARMEL") # andeq r0, r0, r0 b = b"\x00\x00\x00\x00\x00\x00\x00\x00" p = angr.load_shellcode(b, arch, load_address=0x400000) block = p.factory.block(0x400000, opt_level=1, cross_insn_opt=False) assert CFGBase._is_noop_block(arch, block) is True block = p.factory.block(0x400000, opt_level=1, cross_insn_opt=True) assert CFGBase._is_noop_block(arch, block) is True # mov r0, r0 b = b"\x00\x00\xa0\xe1" p = angr.load_shellcode(b, arch, load_address=0x400000) block = p.factory.block(0x400000, opt_level=1, cross_insn_opt=False) assert CFGBase._is_noop_block(arch, block) is True block = p.factory.block(0x400000, opt_level=1, cross_insn_opt=True) assert CFGBase._is_noop_block(arch, block) is True
def test_irop_catevenlanes(): p = angr.load_shellcode('pmulhrsw xmm0, xmm1', 'amd64') # concrete test s1 = p.factory.blank_state() s1.regs.xmm0 = 0x4713e06bf3235e97ca8cfde0647d65fd s1.regs.xmm1 = 0x31f1f86da1dce7de252adc78160e1016 s2 = s1.step(num_inst=1).successors[0] assert (s2.regs.xmm0 == 0x1bbb01de0976ee2bf07b009711500cd1).is_true()
def test_irop_mulhi(): p = angr.load_shellcode('vpmulhw xmm0,xmm1,xmm2', 'amd64') # concrete test s1 = p.factory.blank_state() s1.regs.xmm1 = 0x3aca92553c2526d4f20987aeab250255 s1.regs.xmm2 = 0x1aebcb281463274ec3ce6473619a8541 s2 = s1.step(num_inst=1).successors[0] assert (s2.regs.xmm0 == 0x62e16a304ca05f60348d0c9dfa5fee1).is_true()
def test_ret_float(): class F1(angr.SimProcedure): def run(self): return 12.5 p = angr.load_shellcode(b'X', arch='i386') p.hook(0x1000, F1(prototype='float (x)();')) p.hook(0x2000, F1(prototype='double (x)();')) s = p.factory.call_state(addr=0x1000, ret_addr=0, prototype='float(x)()') succ = s.step() assert len(succ.successors) == 1 s2 = succ.flat_successors[0] assert not s2.regs.st0.symbolic assert s2.solver.eval(s2.regs.st0.raw_to_fp()) == 12.5 s = p.factory.call_state(addr=0x2000, ret_addr=0, prototype='double(x)()') succ = s.step() assert len(succ.successors) == 1 s2 = succ.flat_successors[0] assert not s2.regs.st0.symbolic assert s2.solver.eval(s2.regs.st0.raw_to_fp()) == 12.5 p = angr.load_shellcode(b'X', arch='amd64') p.hook(0x1000, F1(prototype='float (x)();')) p.hook(0x2000, F1(prototype='double (x)();')) s = p.factory.call_state(addr=0x1000, ret_addr=0, prototype='float(x)()') succ = s.step() assert len(succ.successors) == 1 s2 = succ.flat_successors[0] res = s2.registers.load('xmm0', 4).raw_to_fp() assert not res.symbolic assert s2.solver.eval(res) == 12.5 s = p.factory.call_state(addr=0x2000, ret_addr=0, prototype='double(x)()') succ = s.step() assert len(succ.successors) == 1 s2 = succ.flat_successors[0] res = s2.registers.load('xmm0', 8).raw_to_fp() assert not res.symbolic assert s2.solver.eval(res) == 12.5
def test_x86_noop_blocks(): # nop arch = archinfo.arch_from_id("x86") b = b"\x90\x90\x90\x90\x90\x90\x90\x90" p = angr.load_shellcode(b, arch, load_address=0x400000) block = p.factory.block(0x400000, opt_level=1, cross_insn_opt=False) assert CFGBase._is_noop_block(arch, block) is True block = p.factory.block(0x400000, opt_level=1, cross_insn_opt=True) assert CFGBase._is_noop_block(arch, block) is True
def test_x86_ud2_behaviors(): # Test if VEX's lifter behaves as what CFGFast expects # # Note: if such behaviors change in the future, you also need to fix the ud2 handling logic in # CFGFast._generate_cfgnode(). # according to VEX, ud2 on x86 is not part of the block a = load_shellcode(b"\x90\x90\x0f\x0b", "x86") block_0 = a.factory.block(0) assert block_0.size == 2
def test_setup_callsite(): p = angr.load_shellcode(b'b', arch=archinfo.ArchX86()) s = p.factory.call_state(0, "hello", stack_base=0x1234, alloc_base=0x5678, grow_like_stack=False) assert (s.regs.sp == 0x1234).is_true() assert (s.mem[0x1234 + 4].long.resolved == 0x5678).is_true() assert (s.memory.load(0x5678, 5) == b'hello').is_true() s = p.factory.call_state(0, "hello", stack_base=0x1234) assert (s.regs.sp == 0x1234).is_true() assert (s.mem[0x1234 + 4].long.resolved == 0x1234 + 8).is_true() assert (s.memory.load(0x1234 + 8, 5) == b'hello').is_true()
def test_amd64_ud012_behaviors(): # Test if VEX's lifter behaves as what CFGFast expects # # Note: if such behaviors change in the future, you also need to fix the ud{0,1,2} handling logic in # CFGFast._generate_cfgnode(). # according to VEX, ud0 is not part of the block a = load_shellcode(b"\x90\x90\x0f\xff", "amd64") block_0 = a.factory.block(0) assert block_0.size == 2 # according to VEX, ud1 is not part of the block a = load_shellcode(b"\x90\x90\x0f\xb9", "amd64") block_1 = a.factory.block(0) assert block_1.size == 2 # according to VEX, ud2 under AMD64 *is* part of the block a = load_shellcode(b"\x90\x90\x0f\x0b", "amd64") block_2 = a.factory.block(0) assert block_2.size == 4
def test_symbolic_0div(): p = angr.load_shellcode(b'X', arch='amd64') s = p.factory.blank_state() s.regs.rax = s.solver.BVS('rax', 64) s.regs.rcx = s.solver.BVS('rcx', 64) s.regs.rdx = s.solver.BVS('rdx', 64) s.options.add(angr.options.PRODUCE_ZERODIV_SUCCESSORS) successors = s.step(insn_bytes=b'\x48\xf7\xf1') # div rcx assert len(successors.flat_successors) == 2 s.options.discard(angr.options.PRODUCE_ZERODIV_SUCCESSORS) successors = s.step(insn_bytes=b'\x48\xf7\xf1') # div rcx assert len(successors.flat_successors) == 1
def test_symbolic_0div(): p = angr.load_shellcode(b'X', arch='amd64') s = p.factory.blank_state() s.regs.rax = s.solver.BVS('rax', 64) s.regs.rcx = s.solver.BVS('rcx', 64) s.regs.rdx = s.solver.BVS('rdx', 64) s.options.add(angr.options.PRODUCE_ZERODIV_SUCCESSORS) successors = s.step(insn_bytes=b'\x48\xf7\xf1') # div rcx assert len(successors.flat_successors) == 2 s.options.discard(angr.options.PRODUCE_ZERODIV_SUCCESSORS) successors = s.step(insn_bytes=b'\x48\xf7\xf1') # div rcx assert len(successors.flat_successors) == 1
def test_saturating_packing(): # SaturateSignedWordToUnsignedByte p = angr.load_shellcode("vpackuswb xmm1, xmm0, xmm0", arch='amd64') s = p.factory.blank_state() s.regs.xmm0 = 0x0000_0001_7ffe_7fff_8000_8001_fffe_ffff s = s.step(num_inst=1).successors[0] assert ( s.regs.xmm1 == 0x00_01_ff_ff_00_00_00_00_0001ffff00000000).is_true() # "Pack with unsigned saturation" p = angr.load_shellcode("vpackusdw xmm1, xmm0, xmm0", arch='amd64') s = p.factory.blank_state() s.regs.xmm0 = 0x00000001_7ffffffe_80000001_fffffffe s = s.step(num_inst=1).successors[0] assert (s.regs.xmm1 == 0x0001_ffff_0000_0000_0001ffff00000000).is_true() # SaturateSignedWordToSignedByte p = angr.load_shellcode("vpacksswb xmm1, xmm0, xmm0", arch='amd64') s = p.factory.blank_state() s.regs.xmm0 = 0x0000_0001_7ffe_7fff_8000_8001_fffe_ffff s = s.step(num_inst=1).successors[0] assert ( s.regs.xmm1 == 0x00_01_7f_7f_80_80_fe_ff_00017f7f8080feff).is_true()
def test_shellcode(self): """ Test basic CFG recovery and symbolic/concrete execution paths. """ base_address = 0 prototype = "int node_d(long)" code = archinfo.arch_from_id('AMD64').asm( ''' node_a: test rdi, rdi jz node_c node_b: mov rax, 0x1234 jmp node_d node_c: mov rax, 0x5678 node_d: ret ''', base_address) arch = angr.engines.pcode.ArchPcode.arch_from_lang_id( 'x86:LE:64:default') angr.calling_conventions.register_default_cc( arch.name, angr.calling_conventions.SimCCSystemVAMD64) p = angr.load_shellcode(code, arch=arch, load_address=base_address, engine=angr.engines.UberEnginePcode) # Recover the CFG c = p.analyses.CFGFast(normalize=True) assert len(c.model.nodes()) == 4 # Execute symbolically s = p.factory.call_state(base_address, prototype=prototype) simgr = p.factory.simulation_manager(s) simgr.run() assert sum(map(len, simgr.stashes.values())) == 2 assert {s.solver.eval(s.regs.rax) for s in simgr.deadended} == {0x1234, 0x5678} # Execute concretely callable_func = p.factory.callable(base_address, prototype=prototype, concrete_only=True) for input_, expected_output in [(0, 0x5678), (1, 0x1234), (0xffffffffffffffff, 0x1234)]: assert (callable_func(input_) == expected_output).is_true()
def test_strict_block_ends_cbz(): # ldr r3, [sp, #4] # cbz r3, #0x8149 # mov.w r2, #0x10000000 # ldr r3, [pc, #0x38] # str r2, [r3] # add sp, #8 # pop {r4, r5, r6, pc} p = angr.load_shellcode(b'\x01\x9b\x1b\xb1O\xf0\x80R\x0eK\x1a`\x02\xb0p\xbd', 'arm') assert p.factory.block(1, strict_block_end=False).instructions == 7 assert p.factory.block(1, strict_block_end=True).instructions == 2 p.engines.vex.default_strict_block_end = False assert p.factory.block(1).instructions == 7 p.engines.vex.default_strict_block_end = True assert p.factory.block(1).instructions == 2
def test_setup_callsite(): p = angr.load_shellcode(b'b', arch=archinfo.ArchX86()) s = p.factory.call_state(0, "hello", stack_base=0x1234, alloc_base=0x5678, grow_like_stack=False) assert (s.regs.sp == 0x1234).is_true() assert (s.mem[0x1234 + 4].long.resolved == 0x5678).is_true() assert (s.memory.load(0x5678, 5) == b'hello').is_true() s = p.factory.call_state(0, "hello", stack_base=0x1234) assert (s.regs.sp == 0x1234).is_true() assert (s.mem[0x1234 + 4].long.resolved == 0x1234 + 8).is_true() assert (s.memory.load(0x1234 + 8, 5) == b'hello').is_true()
def test_array_ffi(self): # NOTE: if this test is failing and you think it is wrong, you might be right :) p = load_shellcode(b'\xc3', arch='amd64') s = p.factory.blank_state() s.regs.rdi = 123 s.regs.rsi = 456 s.regs.rdx = 789 execve = parse_file( 'int execve(const char *pathname, char *const argv[], char *const envp[]);' )[0]['execve'] cc = p.factory.cc() assert all((x == y).is_true() for x, y in zip(cc.get_args(s, execve), (123, 456, 789))) # however, this is defintely right assert [list(loc.get_footprint()) for loc in cc.arg_locs(execve)] \ == [[SimRegArg('rdi', 8)], [SimRegArg('rsi', 8)], [SimRegArg('rdx', 8)]]
def test_strict_block_ends_cbz(): # ldr r3, [sp, #4] # cbz r3, #0x8149 # mov.w r2, #0x10000000 # ldr r3, [pc, #0x38] # str r2, [r3] # add sp, #8 # pop {r4, r5, r6, pc} p = angr.load_shellcode(b'\x01\x9b\x1b\xb1O\xf0\x80R\x0eK\x1a`\x02\xb0p\xbd', 'arm') assert p.factory.block(1, strict_block_end=False).instructions == 7 assert p.factory.block(1, strict_block_end=True).instructions == 2 p.factory.default_engine.default_strict_block_end = False assert p.factory.block(1).instructions == 7 p.factory.default_engine.default_strict_block_end = True assert p.factory.block(1).instructions == 2
def _test_loop_variant_common(code): def banner(s): print(s + '\n' + '='*40) banner('Input Assembly') print('\n'.join(l.strip() for l in code.splitlines())) print('') p = angr.load_shellcode(code, 'AMD64') p.analyses.CFGFast(normalize=True) f = p.kb.functions[0] banner('Raw AIL Nodes') nodes = sorted(list(f.nodes), key=lambda n: n.addr) am = ailment.Manager(arch=p.arch) for n in nodes: b = p.factory.block(n.addr, n.size) ab = ailment.IRSBConverter.convert(b.vex, am) print(ab) print('') banner('Optimized AIL Nodes') a = p.analyses.Clinic(f) nodes = sorted(list(a.graph.nodes), key=lambda n: n.addr) assert len(nodes) == 3 for n in nodes: print(n) print('') banner('Decompilation') d = p.analyses.Decompiler(f) print(d.codegen.text) print('') # cond_node = nodes[1] # cond_stmt = None # for stmt in cond_node.statements: # if type(stmt) is ailment.statement.ConditionalJump: # cond_stmt = stmt # break # assert(cond_stmt is not None) # print('Condition:' + str(cond_stmt)) # print(cond_proc.claripy_ast_from_ail_condition(cond_stmt.condition)) cond_proc = ConditionProcessor() ri = p.analyses.RegionIdentifier(f, graph=a.graph, cond_proc=cond_proc, kb=p.kb) rs = p.analyses.RecursiveStructurer(ri.region, cond_proc=cond_proc, kb=p.kb, func=f) snodes = rs.result.nodes assert len(snodes) == 3 assert isinstance(snodes[1], angr.analyses.decompiler.structurer_nodes.LoopNode) banner('Condition') print(str(snodes[1].condition)) return snodes[1].condition
def test_convert_from_pcode_irsb(): arch = archinfo.arch_from_id('AMD64') manager = ailment.Manager(arch=arch) p = angr.load_shellcode(block_bytes, arch, block_addr, block_addr, engine=angr.engines.UberEnginePcode) irsb = p.factory.block(block_addr).vex ablock = ailment.IRSBConverter.convert(irsb, manager) print(str(ablock))
def test_strtol_long_string(self): # convert a 11-digit long string to a number. # there was an off-by-one error before. b = angr.load_shellcode(b"\x90\x90", "AMD64") state = b.factory.blank_state() state.memory.store(0x500000, b"98831114236\x00") state.libc.max_strtol_len = 11 strtol = angr.SIM_LIBRARIES['libc.so.6'].get('strtol', arch=b.arch) strtol.state = state.copy() ret = strtol.run(0x500000, 0, 0) assert strtol.state.satisfiable() assert len(strtol.state.solver.eval_upto(ret, 2)) == 1 assert strtol.state.solver.eval_one(ret) == 98831114236
def test_blsr(): p = load_shellcode(bytes.fromhex('c4e2f8f3cf0f95c00fb6c0c3'), arch='amd64') # compiled form of !!(x & (x - 1)) # 2c0: c4 e2 f8 f3 cf blsr %rdi,%rax # 2c5: 0f 95 c0 setne %al # 2c8: 0f b6 c0 movzbl %al,%eax # 2cb: c3 retq x = claripy.BVS('x', 64) s = p.factory.call_state(0, x) sm = p.factory.simulation_manager(s) sm.run() target_func = claripy.If((x & (x - 1)) == 0, claripy.BVV(0, 64), 1) solver = claripy.Solver() solver.add(sm.one_deadended.regs.rax != target_func) assert not solver.satisfiable()
def test_irop_perm(): p = angr.load_shellcode('vpshufb xmm0,xmm1,xmm2', 'amd64') # concrete test s1 = p.factory.blank_state() s1.regs.xmm1 = 0x3c899a56814ee9b84c7b5d8394c85881 s1.regs.xmm2 = 0xa55c66a2cdef1cbcd72b42078d1b7f8b s2 = s1.step(num_inst=1).successors[0] assert (s2.regs.xmm0 == 0x00567b00000056000081c84c00813c00).is_true() # symbolic test s3 = p.factory.blank_state() s3.regs.xmm1 = claripy.BVS('xmm1', 128) s3.regs.xmm2 = claripy.BVS('xmm2', 128) s4 = s3.step(num_inst=1).successors[0] s4.solver.add(s4.regs.xmm2 == 0xa55c66a2cdef1cbcd72b42078d1b7f8b) s4.solver.add(s4.regs.xmm0 == 0x00567b00000056000081c84c00813c00) assert s4.solver.solution(s4.regs.xmm1, 0x3c899a56814ee9b84c7b5d8394c85881)
def test_strtol_long_string(): # convert a 11-digit long string to a number. # there was an off-by-one error before. b = angr.load_shellcode(b"\x90\x90", "AMD64") state = b.factory.blank_state() state.memory.store(0x500000, b"98831114236\x00") state.libc.max_strtol_len = 11 strtol = angr.SIM_LIBRARIES['libc.so.6'].procedures['strtol'] strtol.state = state.copy() ret = strtol.run(0x500000, 0, 0) nose.tools.assert_true(strtol.state.satisfiable()) nose.tools.assert_equal(len(strtol.state.solver.eval_upto(ret, 2)), 1) nose.tools.assert_equal(strtol.state.solver.eval_one(ret), 98831114236)
def test_successors_catch_arbitrary_interrupts(): # int 0xd2 should fail on x86/amd64 since it's an unsupported interrupt block_bytes = b"\xcd\xd2" proj = angr.load_shellcode(block_bytes, "amd64") proj.simos = angr.simos.SimLinux(proj) state = proj.factory.blank_state(addr=0) simgr = proj.factory.simgr(state) simgr.step() nose.tools.assert_equal( len(simgr.errored), 0, msg="The state should not go to the errored stash. Is " "AngrSyscallError handled in SimSuccessors?") nose.tools.assert_equal(len(simgr.unsat), 1)
def test_successors_catch_arbitrary_interrupts(self): # int 0xd2 should fail on x86/amd64 since it's an unsupported interrupt block_bytes = b"\xcd\xd2" proj = angr.load_shellcode(block_bytes, "amd64") proj.loader.tls = cle.backends.tls.ELFThreadManager( proj.loader, proj.arch) proj.simos = angr.simos.SimLinux(proj) proj.simos.configure_project() state = proj.factory.blank_state(addr=0) simgr = proj.factory.simgr(state) simgr.step() assert ( len(simgr.errored) == 0 ), "The state should not go to the errored stash. Is AngrSyscallError handled in SimSuccessors?" assert len(simgr.unsat) == 1
def test_address_conversion(self): main = MainWindow(show=False) main.workspace.instance.project = load_shellcode(b'X', 'amd64') main.workspace.instance.project.kb.functions.function(addr=0x1234, name='foo', create=True) obj = QAddressInput(None, main.workspace) obj.setText("") QTest.keyClicks(obj, "4321") self.assertEqual(obj.target, 0x4321) obj.setText("") QTest.keyClicks(obj, "foo") self.assertEqual(obj.target, 0x1234) obj.setText("") QTest.keyClicks(obj, "12x3") self.assertIsNone(obj.target)
def test_unsupported_syscall_simos(): p = angr.load_shellcode('int 0x80', 'x86') state = p.factory.entry_state() state.regs.eax = 4 # test that by default trying to perform a syscall without SimUserspace causes the state to go errored simgr = p.factory.simulation_manager(state) simgr.step() assert len(simgr.active) == 1 simgr.step() assert len(simgr.active) == 0 assert len(simgr.errored) == 1 # test that when we set BYPASS_UNSUPPORTED_SYSCALLS, we get a syscall stub instead state.options.add(angr.options.BYPASS_UNSUPPORTED_SYSCALL) simgr = p.factory.simulation_manager(state) simgr.step() assert len(simgr.active) == 1 simgr.step() assert len(simgr.active) == 1 assert len(simgr.errored) == 0
def test_unsupported_syscall_simos(): p = angr.load_shellcode(b'\xcd\x80', 'x86') state = p.factory.entry_state() state.regs.eax = 4 # test that by default trying to perform a syscall without SimUserspace causes the state to go errored simgr = p.factory.simulation_manager(state) simgr.step() nose.tools.assert_equal(len(simgr.active), 1) simgr.step() nose.tools.assert_equal(len(simgr.active), 0) nose.tools.assert_equal(len(simgr.errored), 1) # test that when we set BYPASS_UNSUPPORTED_SYSCALLS, we get a syscall stub instead state.options.add(angr.options.BYPASS_UNSUPPORTED_SYSCALL) simgr = p.factory.simulation_manager(state) simgr.step() nose.tools.assert_equal(len(simgr.active), 1) simgr.step() nose.tools.assert_equal(len(simgr.active), 1) nose.tools.assert_equal(len(simgr.errored), 0)
def test_ret_float(): p = angr.load_shellcode(b'X', arch='i386') class F1(angr.SimProcedure): def run(self): return 12.5 p.hook(0x1000, F1(cc=p.factory.cc(func_ty=angr.sim_type.parse_file('float (x)();')[0]['x']))) p.hook(0x2000, F1(cc=p.factory.cc(func_ty=angr.sim_type.parse_file('double (x)();')[0]['x']))) s = p.factory.call_state(addr=0x1000, ret_addr=0) succ = s.step() nose.tools.assert_equal(len(succ.successors), 1) s2 = succ.flat_successors[0] nose.tools.assert_false(s2.regs.st0.symbolic) nose.tools.assert_equal(s2.solver.eval(s2.regs.st0.get_bytes(4, 4).raw_to_fp()), 12.5) s = p.factory.call_state(addr=0x2000, ret_addr=0) succ = s.step() nose.tools.assert_equal(len(succ.successors), 1) s2 = succ.flat_successors[0] nose.tools.assert_false(s2.regs.st0.symbolic) nose.tools.assert_equal(s2.solver.eval(s2.regs.st0.raw_to_fp()), 12.5)