import sys import struct import time import os import textwrap import random from contextlib import contextmanager sys.path.append(".") import unittest import windows import windows.debug import windows.native_exec.simple_x86 as x86 import windows.native_exec.simple_x64 as x64 import windows.native_exec.nativeutils as nativeutils from windows.generated_def.winstructs import * from windows.native_exec.nativeutils import GetProcAddress64, GetProcAddress32 is_process_32_bits = windows.current_process.bitness == 32 is_process_64_bits = windows.current_process.bitness == 64 is_windows_32_bits = windows.system.bitness == 32 is_windows_64_bits = windows.system.bitness == 64 windows_32bit_only = unittest.skipIf(not is_windows_32_bits, "Test for 32bits Kernel only") windows_64bit_only = unittest.skipIf(not is_windows_64_bits, "Test for 64bits Kernel only") process_32bit_only = unittest.skipIf(not is_process_32_bits, "Test for 32bits process only") process_64bit_only = unittest.skipIf(not is_process_64_bits, "Test for 64bits process only") if is_windows_32_bits: def pop_calc_32(dwCreationFlags=0): return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True) def pop_calc_64(dwCreationFlags=0): raise WindowsError("Cannot create calc64 in 32bits system") else: def pop_calc_32(dwCreationFlags=0): return windows.utils.create_process(r"C:\Windows\syswow64\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True) if is_process_32_bits: def pop_calc_64(dwCreationFlags=0): with windows.utils.DisableWow64FsRedirection(): return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True) else: def pop_calc_64(dwCreationFlags=0): return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True) @contextmanager def Calc64(dwCreationFlags=0, exit_code=0): try: calc = pop_calc_64(dwCreationFlags) yield calc finally: if "calc" in locals(): calc.exit(exit_code) @contextmanager def Calc32(dwCreationFlags=0, exit_code=0): try: calc = pop_calc_32(dwCreationFlags) yield calc finally: if "calc" in locals(): calc.exit(exit_code) class SystemTestCase(unittest.TestCase): def test_version(self): return windows.system.version def test_version_name(self): return windows.system.version_name def test_computer_name(self): return windows.system.computer_name def test_services(self): return windows.system.services def test_logicaldrives(self): return windows.system.logicaldrives def test_processes(self): return windows.system.processes def test_threads(self): return windows.system.threads def test_wmi(self): return windows.system.wmi.select("Win32_Process", "*") def test_processes(self): procs = windows.system.processes self.assertIn(windows.current_process.pid, [p.pid for p in procs]) class WindowsTestCase(unittest.TestCase): def setUp(self): pass def test_pop_calc_32(self): with Calc32() as calc: self.assertEqual(calc.bitness, 32) @windows_64bit_only def test_pop_calc_64(self): with Calc64() as calc: self.assertEqual(calc.bitness, 64) def test_get_current_process_peb(self): return windows.current_process.peb def test_get_current_process_modules(self): self.assertIn("python", windows.current_process.peb.modules[0].name) def test_local_process_pe_imports(self): python_module = windows.current_process.peb.modules[0] imp = python_module.pe.imports self.assertIn("kernel32.dll", imp.keys(), 'Kernel32.dll not in python imports') current_proc_id_iat = [f for f in imp["kernel32.dll"] if f.name == "GetCurrentProcessId"][0] k32_base = windows.winproxy.LoadLibraryA("kernel32.dll") self.assertEqual(windows.winproxy.GetProcAddress(k32_base, "GetCurrentProcessId"), current_proc_id_iat.value) def test_local_process_pe_exports(self): mods = [m for m in windows.current_process.peb.modules if m.name == "kernel32.dll"] self.assertTrue(mods, 'Could not find "kernel32.dll" in current process modules') k32 = mods[0] get_current_proc_id = k32.pe.exports['GetCurrentProcessId'] k32_base = windows.winproxy.LoadLibraryA("kernel32.dll") self.assertEqual(windows.winproxy.GetProcAddress(k32_base, "GetCurrentProcessId"), get_current_proc_id) def test_local_process_pe_sections(self): mods = [m for m in windows.current_process.peb.modules if m.name == "kernel32.dll"] self.assertTrue(mods, 'Could not find "kernel32.dll" in current process modules') k32 = mods[0] sections = k32.pe.sections all_sections_name = [s.name for s in sections] self.assertIn(".text", all_sections_name) sections[0].start sections[0].size # Read / write def test_read_memory_32(self): with Calc32() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] self.assertEqual(calc.read_memory(k32.baseaddr, 2), "MZ") @windows_64bit_only def test_read_memory_64(self): with Calc64() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] self.assertEqual(calc.read_memory(k32.baseaddr, 2), "MZ") def test_write_memory_32(self): with Calc32() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] with calc.virtual_protected(k32.baseaddr, 2, PAGE_EXECUTE_READWRITE): calc.write_memory(k32.baseaddr, "XD") self.assertEqual(calc.read_memory(k32.baseaddr, 2), "XD") @windows_64bit_only def test_write_memory_64(self): with Calc64() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] with calc.virtual_protected(k32.baseaddr, 2, PAGE_EXECUTE_READWRITE): calc.write_memory(k32.baseaddr, "XD") self.assertEqual(calc.read_memory(k32.baseaddr, 2), "XD") # Native execution def test_execute_to_32(self): with Calc32() as calc: data = calc.virtual_alloc(0x1000) shellcode = x86.MultipleInstr() shellcode += x86.Mov('EAX', 0x42424242) shellcode += x86.Mov(x86.create_displacement(disp=data), 'EAX') shellcode += x86.Ret() calc.execute(shellcode.get_code()) time.sleep(0.1) dword = struct.unpack("32 injection for now) #if is_process_64_bits: # raise NotImplementedError("Python execution 64->32") data = calc.virtual_alloc(0x1000) remote_python_code = """ import ctypes import windows # windows.utils.create_console() # remove comment for debug k32 = [m for m in windows.current_process.peb.modules if m.name == "kernel32.dll"][0] GetCurrentProcessId = k32.pe.exports['GetCurrentProcessId'] ctypes.c_uint.from_address({1}).value = GetCurrentProcessId """.format(os.getcwd(), data) calc.execute_python(textwrap.dedent(remote_python_code)) #time.sleep(0.5) dword = struct.unpack("> 12 for page_info in calc.query_working_set(): if page_info.virtualpage == page_target: self.assertEqual(page_info.shared, True) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) data = calc.write_memory(api_addr, data) for page_info in calc.query_working_set(): if page_info.virtualpage == page_target: self.assertEqual(page_info.shared, False) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) @windows_64bit_only def test_get_working_set_64(self): with Calc64() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] api_addr = k32.pe.exports["CreateFileA"] data = calc.read_memory(api_addr, 5) page_target = api_addr >> 12 for page_info in calc.query_working_set(): if page_info.virtualpage == page_target: self.assertEqual(page_info.shared, True) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) with calc.virtual_protected(api_addr, 5, PAGE_EXECUTE_READWRITE): data = calc.write_memory(api_addr, data) for page_info in calc.query_working_set(): if page_info.virtualpage == page_target: self.assertEqual(page_info.shared, False) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) def test_get_working_setex_32(self): with Calc32() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] text = [s for s in k32.pe.sections if s.name == ".text"][0] pages = [text.start + off for off in range(0, text.size, 0x1000)] api_addr = k32.pe.exports["CreateFileA"] data = calc.read_memory(api_addr, 5) page_target = (api_addr >> 12) << 12 for page_info in calc.query_working_setex(pages): self.assertIn(page_info.VirtualAddress, pages) if page_info.VirtualAddress == page_target: self.assertEqual(page_info.VirtualAttributes.shared, True) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) with calc.virtual_protected(api_addr, 5, PAGE_EXECUTE_READWRITE): data = calc.write_memory(api_addr, data) for page_info in calc.query_working_setex(pages): self.assertIn(page_info.VirtualAddress, pages) if page_info.VirtualAddress == page_target: self.assertEqual(page_info.VirtualAttributes.shared, False) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) @windows_64bit_only def test_get_working_setex_64(self): with Calc64() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] text = [s for s in k32.pe.sections if s.name == ".text"][0] pages = [text.start + off for off in range(0, text.size, 0x1000)] api_addr = k32.pe.exports["CreateFileA"] data = calc.read_memory(api_addr, 5) page_target = (api_addr >> 12) << 12 for page_info in calc.query_working_setex(pages): self.assertIn(page_info.VirtualAddress, pages) if page_info.VirtualAddress == page_target: self.assertEqual(page_info.VirtualAttributes.shared, True) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) with calc.virtual_protected(api_addr, 5, PAGE_EXECUTE_READWRITE): data = calc.write_memory(api_addr, data) for page_info in calc.query_working_setex(pages): self.assertIn(page_info.VirtualAddress, pages) if page_info.VirtualAddress == page_target: self.assertEqual(page_info.VirtualAttributes.shared, False) break else: raise ValueError("query_working_set page info for <0x{0:x}> not found".format(page_target)) def test_mapped_filename_32(self): with Calc32() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] mapped_filname = calc.get_mapped_filename(k32.baseaddr) self.assertTrue(mapped_filname.endswith("kernel32.dll")) @windows_64bit_only def test_mapped_filename_64(self): with Calc64() as calc: k32 = [m for m in calc.peb.modules if m.name == "kernel32.dll"][0] mapped_filname = calc.get_mapped_filename(k32.baseaddr) self.assertTrue(mapped_filname.endswith("kernel32.dll")) def test_thread_teb_base_32(self): with Calc32() as calc: t = calc.threads[0] self.assertNotEqual(t.teb_base, 0) @windows_64bit_only def test_thread_teb_base_64(self): with Calc64() as calc: t = calc.threads[0] self.assertNotEqual(t.teb_base, 0) class WindowsAPITestCase(unittest.TestCase): def test_createfileA_fail(self): with self.assertRaises(WindowsError) as ar: windows.winproxy.CreateFileA("NONEXISTFILE.FILE") class NativeUtilsTestCase(unittest.TestCase): @process_64bit_only def test_strlenw64(self): strlenw64 = windows.native_exec.create_function(nativeutils.StrlenW64.get_code(), [UINT, LPCWSTR]) self.assertEqual(strlenw64("YOLO"), 4) self.assertEqual(strlenw64(""), 0) @process_64bit_only def test_strlena64(self): strlena64 = windows.native_exec.create_function(nativeutils.StrlenA64.get_code(), [UINT, LPCSTR]) self.assertEqual(strlena64("YOLO"), 4) self.assertEqual(strlena64(""), 0) @process_64bit_only def test_getprocaddr64(self): getprocaddr64 = windows.native_exec.create_function(nativeutils.GetProcAddress64.get_code(), [ULONG64, LPCWSTR, LPCSTR]) k32 = [mod for mod in windows.current_process.peb.modules if mod.name == "kernel32.dll"][0] exports = [(x,y) for x,y in k32.pe.exports.items() if isinstance(x, basestring)] for name, addr in exports: name = name.encode() compute_addr = getprocaddr64("KERNEL32.DLL", name) # Put name in test to know which function caused the assert fails self.assertEqual((name, hex(addr)), (name, hex(compute_addr))) self.assertEqual(getprocaddr64("YOLO.DLL", "whatever"), 0xfffffffffffffffe) self.assertEqual(getprocaddr64("KERNEL32.DLL", "YOLOAPI"), 0xffffffffffffffff) @process_32bit_only def test_strlenw32(self): strlenw32 = windows.native_exec.create_function(nativeutils.StrlenW32.get_code(), [UINT, LPCWSTR]) self.assertEqual(strlenw32("YOLO"), 4) self.assertEqual(strlenw32(""), 0) @process_32bit_only def test_strlena32(self): strlena32 = windows.native_exec.create_function(nativeutils.StrlenA32.get_code(), [UINT, LPCSTR]) self.assertEqual(strlena32("YOLO"), 4) self.assertEqual(strlena32(""), 0) @process_32bit_only def test_getprocaddr32(self): getprocaddr32 = windows.native_exec.create_function(nativeutils.GetProcAddress32.get_code(), [UINT, LPCWSTR, LPCSTR]) k32 = [mod for mod in windows.current_process.peb.modules if mod.name == "kernel32.dll"][0] exports = [(x,y) for x,y in k32.pe.exports.items() if isinstance(x, basestring)] for name, addr in exports: name = name.encode() compute_addr = getprocaddr32("KERNEL32.DLL", name) # Put name in test to know which function caused the assert fails self.assertEqual((name, hex(addr)), (name, hex(compute_addr))) self.assertEqual(getprocaddr32("YOLO.DLL", "whatever"), 0xfffffffe) self.assertEqual(getprocaddr32("KERNEL32.DLL", "YOLOAPI"), 0xffffffff) class DebuggerTestCase(unittest.TestCase): def debuggable_calc_32(self): return windows.utils.create_process(r"C:\python27\python.exe", dwCreationFlags=DEBUG_PROCESS | CREATE_NEW_CONSOLE, show_windows=True) def test_init_breakpoint_callback(self): TEST_CASE = self class MyDbg(windows.debug.Debugger): def on_exception(self, exception): TEST_CASE.assertEqual(exception.ExceptionRecord.ExceptionCode, EXCEPTION_BREAKPOINT) self.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) d = MyDbg(calc, already_debuggable=True) d.loop() def test_simple_standard_breakpoint(self): TEST_CASE = self class TSTBP(windows.debug.Breakpoint): def trigger(self, dbg, exc): TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid) TEST_CASE.assertEqual(dbg.current_process.read_memory(self.addr, 1), "\xcc") TEST_CASE.assertEqual(dbg.current_thread.context.pc - 1, self.addr) d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) if windows.current_process.bitness == 32: LdrLoadDll32 = windows.current_process.peb.modules[1].pe.exports["LdrLoadDll"] else: calcref = pop_calc_32() LdrLoadDll32 = calcref.peb.modules[1].pe.exports["LdrLoadDll"] calcref.exit() d = windows.debug.Debugger(calc, already_debuggable=True) d.add_bp(TSTBP(LdrLoadDll32)) d.loop() def test_standard_breakpoint_multiple_threads(self): TEST_CASE = self data = [0] class TSTBP(windows.debug.Breakpoint): def trigger(self, dbg, exc): TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid) TEST_CASE.assertEqual(dbg.current_process.read_memory(self.addr, 1), "\xcc") TEST_CASE.assertEqual(dbg.current_thread.context.pc - 1, self.addr) data[0] += 1 d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) if windows.current_process.bitness == 32: LdrLoadDll32 = windows.current_process.peb.modules[1].pe.exports["LdrLoadDll"] else: calcref = pop_calc_32() LdrLoadDll32 = calcref.peb.modules[1].pe.exports["LdrLoadDll"] calcref.exit() d = windows.debug.Debugger(calc, already_debuggable=True) calc.execute("\xc3") calc.execute("\xc3") calc.execute("\xc3") d.add_bp(TSTBP(LdrLoadDll32)) d.loop() def test_simple_hwx_breakpoint(self): TEST_CASE = self class TSTBP(windows.debug.HXBreakpoint): def trigger(self, dbg, exc): TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid) TEST_CASE.assertEqual(dbg.current_thread.context.pc, self.addr) TEST_CASE.assertNotEqual(dbg.current_thread.context.Dr7, 0) d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) if windows.current_process.bitness == 32: LdrLoadDll32 = windows.current_process.peb.modules[1].pe.exports["LdrLoadDll"] else: calcref = pop_calc_32() LdrLoadDll32 = calcref.peb.modules[1].pe.exports["LdrLoadDll"] calcref.exit() d = windows.debug.Debugger(calc, already_debuggable=True) d.add_bp(TSTBP(LdrLoadDll32)) d.loop() def test_multiple_hwx_breakpoint(self): TEST_CASE = self data = [0] class TSTBP(windows.debug.HXBreakpoint): def __init__(self, addr, expec_before): self.addr = addr self.expec_before = expec_before def trigger(self, dbg, exc): TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid) TEST_CASE.assertEqual(dbg.current_thread.context.pc, self.addr) TEST_CASE.assertNotEqual(dbg.current_thread.context.Dr7, 0) TEST_CASE.assertEqual(data[0], self.expec_before) TEST_CASE.assertNotEqual(dbg.current_process.read_memory(self.addr, 1), "\xcc") data[0] += 1 if data[0] == 4: d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) d = windows.debug.Debugger(calc, already_debuggable=True) addr = calc.virtual_alloc(0x1000) calc.write_memory(addr, "\x90" * 8) d.add_bp(TSTBP(addr, 0)) d.add_bp(TSTBP(addr + 1, 1)) d.add_bp(TSTBP(addr + 2, 2)) d.add_bp(TSTBP(addr + 3, 3)) calc.create_thread(addr, 0) d.loop() # Used to verif we actually called the Breakpoints TEST_CASE.assertEqual(data[0], 4) def test_four_hwx_breakpoint_fail(self): TEST_CASE = self data = [0] class TSTBP(windows.debug.HXBreakpoint): def __init__(self, addr, expec_before): self.addr = addr self.expec_before = expec_before def trigger(self, dbg, exc): raise NotImplementedError("Should fail before") calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) d = windows.debug.Debugger(calc, already_debuggable=True) addr = calc.virtual_alloc(0x1000) calc.write_memory(addr, "\x90" * 8 + "\xc3") d.add_bp(TSTBP(addr, 0)) d.add_bp(TSTBP(addr + 1, 1)) d.add_bp(TSTBP(addr + 2, 2)) d.add_bp(TSTBP(addr + 3, 3)) d.add_bp(TSTBP(addr + 4, 4)) calc.create_thread(addr, 0) with self.assertRaises(ValueError) as e: d.loop() self.assertIn("DRx", e.exception.message) # Used to verif we actually NOT called the Breakpoints TEST_CASE.assertEqual(data[0], 0) def test_hwx_breakpoint_are_on_all_thread(self): TEST_CASE = self data = [0] class MyDbg(windows.debug.Debugger): def on_create_thread(self, exception): # Check that later created thread have their HWX breakpoint :) TEST_CASE.assertNotEqual(self.current_thread.context.Dr7, 0) class TSTBP(windows.debug.HXBreakpoint): def __init__(self, addr, expec_before): self.addr = addr self.expec_before = expec_before def trigger(self, dbg, exc): TEST_CASE.assertNotEqual(len(dbg.current_process.threads), 1) #for t in dbg.current_process.threads: # TEST_CASE.assertNotEqual(t.context.Dr7, 0) if data[0] == 0: #First time we got it ! create new thread data[0] = 1 calc.create_thread(addr, 0) else: d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) d = MyDbg(calc, already_debuggable=True) addr = calc.virtual_alloc(0x1000) calc.write_memory(addr, "\x90" * 2 + "\xc3") d.add_bp(TSTBP(addr, 0)) calc.create_thread(addr, 0) d.loop() # Used to verif we actually called the Breakpoints TEST_CASE.assertEqual(data[0], 1) def test_simple_breakpoint_name_addr(self): TEST_CASE = self data = [0] class TSTBP(windows.debug.Breakpoint): def trigger(self, dbg, exc): addr = exc.ExceptionRecord.ExceptionAddress TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid) TEST_CASE.assertEqual(dbg.current_process.read_memory(addr, 1), "\xcc") TEST_CASE.assertEqual(dbg.current_thread.context.pc - 1, addr) data[0] += 1 d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) d = windows.debug.Debugger(calc, already_debuggable=True) d.add_bp(TSTBP("ntdll.dll!LdrLoadDll")) d.loop() TEST_CASE.assertEqual(data[0], 1) def test_simple_hardware_breakpoint_name_addr(self): TEST_CASE = self data = [0] class TSTBP(windows.debug.HXBreakpoint): def trigger(self, dbg, exc): addr = exc.ExceptionRecord.ExceptionAddress TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid) TEST_CASE.assertEqual(dbg.current_thread.context.pc, dbg._resolve(self.addr, dbg.current_process)) TEST_CASE.assertNotEqual(dbg.current_thread.context.Dr7, 0) TEST_CASE.assertNotEqual(dbg.current_process.read_memory(addr, 1), "\xcc") data[0] += 1 d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) d = windows.debug.Debugger(calc, already_debuggable=True) d.add_bp(TSTBP("ntdll.dll!LdrLoadDll")) d.loop() TEST_CASE.assertEqual(data[0], 1) def perform_manual_getproc_loadlib_32_yolo(self, target, dll_name): dll = "KERNEL32.DLL\x00".encode("utf-16-le") api = "LoadLibraryA\x00" dll_to_load = dll_name + "\x00" RemoteManualLoadLibray = x86.MultipleInstr() code = RemoteManualLoadLibray code += x86.Mov("ECX", x86.mem("[ESP + 4]")) code += x86.Push(x86.mem("[ECX + 4]")) code += x86.Push(x86.mem("[ECX]")) code += x86.Call(":FUNC_GETPROCADDRESS32") code += x86.Push(x86.mem("[ECX + 8]")) code += x86.Call("EAX") # LoadLibrary code += x86.Pop("ECX") code += x86.Pop("ECX") code += x86.Ret() RemoteManualLoadLibray += GetProcAddress32 addr = target.virtual_alloc(0x1000) addr2 = addr + len(dll) addr3 = addr2 + len(api) addr4 = addr3 + len(dll_to_load) target.write_memory(addr, dll) target.write_memory(addr2, api) target.write_memory(addr3, dll_to_load) target.write_qword(addr4, addr) target.write_qword(addr4 + 4, addr2) target.write_qword(addr4 + 0x8, addr3) t = target.execute(RemoteManualLoadLibray.get_code(), addr4) return t def test_hardware_breakpoint_name_addr(self): TEST_CASE = self data = [0] class TSTBP(windows.debug.HXBreakpoint): def trigger(self, dbg, exc): addr = exc.ExceptionRecord.ExceptionAddress TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid) TEST_CASE.assertEqual(dbg.current_thread.context.pc, dbg._resolve(self.addr, dbg.current_process)) TEST_CASE.assertNotEqual(dbg.current_thread.context.Dr7, 0) TEST_CASE.assertNotEqual(dbg.current_process.read_memory(addr, 1), "\xcc") data[0] += 1 if data[0] == 1: # Perform a loaddll in a new thread :) # See if it's trigger a bp t = TEST_CASE.perform_manual_getproc_loadlib_32_yolo(dbg.current_process, "wintrust.dll") self.new_thread = t if hasattr(self, "new_thread") and dbg.current_thread.tid == self.new_thread.tid: for t in dbg.current_process.threads: TEST_CASE.assertNotEqual(t.context.Dr7, 0) d.current_process.exit() calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS) d = windows.debug.Debugger(calc, already_debuggable=True) d.add_bp(TSTBP("ntdll.dll!LdrLoadDll")) # Code that will load wintrust ! d.loop() #TEST_CASE.assertEqual(data[0], 1) if __name__ == '__main__': alltests = unittest.TestSuite() alltests.addTest(unittest.makeSuite(SystemTestCase)) alltests.addTest(unittest.makeSuite(WindowsTestCase)) alltests.addTest(unittest.makeSuite(WindowsAPITestCase)) alltests.addTest(unittest.makeSuite(DebuggerTestCase)) alltests.addTest(unittest.makeSuite(NativeUtilsTestCase)) alltests.debug() tester = unittest.TextTestRunner(verbosity=2) tester.run(alltests)