def setUpClass(self): windows.winproxy.SetThreadAffinityMask(dwThreadAffinityMask=(1 << 0)) self.kdbg = LocalKernelDebugger() modules = windows.utils.get_kernel_modules() self.modules = modules self.ntkernelbase = modules[0].Base self.kernelpath = modules[0].ImageName[:] self.kernelpath = os.path.expandvars(self.kernelpath.replace("\SystemRoot", "%SystemRoot%")) self.kernelmod = winproxy.LoadLibraryA(self.kernelpath) pe = windows.pe_parse.PEFile(self.kernelmod) self.NtCreateFileVA = pe.exports['NtCreateFile'] - self.kernelmod + self.ntkernelbase
def setUpClass(self): windows.winproxy.SetThreadAffinityMask(dwThreadAffinityMask=(1 << 0)) self.kdbg = LocalKernelDebugger() modules = windows.utils.get_kernel_modules() self.ntkernelbase = modules[0].Base self.kernelpath = modules[0].ImageName[:] self.kernelpath = os.path.expandvars(self.kernelpath.replace("\SystemRoot", "%SystemRoot%")) self.kernelbuf = open(self.kernelpath, "rb").read() self.kernelmod = winproxy.LoadLibraryA(self.kernelpath) pe = windows.pe_parse.PEFile(self.kernelmod) self.kernel_section_data = [section for section in pe.sections if section.name == ".data"][0]
# Value from _BUS_DATA_TYPE # https://msdn.microsoft.com/en-us/library/windows/hardware/ff540700(v=vs.85).aspx PCIConfiguration = 4 # LPC device PCI configuration space bus_num = 0 device_num = 0x1F function_num = 0 # BIOS_CNTL register offset_bios_cntl = 0xDC SMM_BWP_mask = 1 << 5 # 0x20 BLE_mask = 1 << 1 # 0x2 BIOSWE_mask = 1 << 0 # 0x1 if __name__ == '__main__': kdbg = LocalKernelDebugger() # You can read data from a system bus by specifying the bus data type, bus number, # slot number, offset and size of data to read # IDebugDataSpaces::ReadBusData # https://msdn.microsoft.com/en-us/library/windows/hardware/ff553519(v=vs.85).aspx bios_cntl = ord(kdbg.read_bus_data(PCIConfiguration, bus_num, device_num + (function_num << 5), offset_bios_cntl, 1)) if bios_cntl & SMM_BWP_mask: print("[+] Speed Racer: Not Vulnerable") else: print("[-] Speed Racer: Vulnerable") if bios_cntl & BIOSWE_mask: print("[-] BIOS Rewriting: Enable") else: print("[+] BIOS Rewriting: Disable")
"""A simple demonstration of the output possibilities of the LDK""" import sys import os if os.getcwd().endswith("example"): sys.path.append(os.path.realpath("..")) else: sys.path.append(os.path.realpath(".")) from dbginterface import LocalKernelDebugger # A default LKD can be quiet or not # A quiet LKD will have no output # A noisy one will have the exact same output as windbg kdbg = LocalKernelDebugger(quiet=True) # With a quiet LKD this ligne will have no output print('Executing "lm m nt*" in quiet LKD') kdbg.execute("lm m nt*") # To change the quiet state of the LKD just set the variable 'quiet' kdbg.quiet = False print("") print('Executing "lm m nt*" in noisy LKD') kdbg.execute("lm m nt*") # If you want to parse the output of a command, kdbg.execute accept the argument 'to_string' # A command with to_string=True will have no output, even with quiet=False print("") disas = kdbg.execute("u nt!NtCreateFile", to_string=True) print('Here is the 3rd line of the command "u nt!NtCreateFile"') print(disas.split("\n")[2])
class IDebugSymbolsTestCase(unittest.TestCase): def setUp(self): pass @classmethod def setUpClass(self): windows.winproxy.SetThreadAffinityMask(dwThreadAffinityMask=(1 << 0)) self.kdbg = LocalKernelDebugger() modules = windows.utils.get_kernel_modules() self.modules = modules self.ntkernelbase = modules[0].Base self.kernelpath = modules[0].ImageName[:] self.kernelpath = os.path.expandvars(self.kernelpath.replace("\SystemRoot", "%SystemRoot%")) self.kernelmod = winproxy.LoadLibraryA(self.kernelpath) pe = windows.pe_parse.PEFile(self.kernelmod) self.NtCreateFileVA = pe.exports['NtCreateFile'] - self.kernelmod + self.ntkernelbase def tearDown(self): #self.kdbg.detach() self.kdbg = None def test_get_symbol_offset(self): # IDebugSymbols::GetOffsetByName x = self.kdbg.get_symbol_offset("nt") self.assertEqual(x, self.ntkernelbase) @RequireSymbol("ntdll!NtCreateFile") def test_get_symbol_offset_user(self): # IDebugSymbols::GetOffsetByName x = windows.utils.get_func_addr("ntdll", "NtCreateFile") y = self.kdbg.get_symbol_offset("ntdll!NtCreateFile") self.assertEqual(x, y) @RequireSymbol("nt!NtCreateFile") def test_get_symbol(self): # IDebugSymbols::GetNameByOffset x = self.kdbg.get_symbol(self.NtCreateFileVA) self.assertEqual(x[0], 'nt!NtCreateFile') self.assertEqual(x[1], 0x00) @RequireSymbol("ntdll!NtCreateFile") def test_get_symbol_user(self): # IDebugSymbols::GetNameByOffset x = windows.utils.get_func_addr("ntdll", "NtCreateFile") y = self.kdbg.get_symbol(x) self.assertIn(y[0], ["ntdll!NtCreateFile", "ntdll!ZwCreateFile"]) def test_get_number_modules(self): # IDebugSymbols::GetNumberModules loaded, unloaded = self.kdbg.get_number_modules() def test_get_module_by_index(self): # IDebugSymbols::GetModuleByIndex for i in range(self.kdbg.get_number_modules()[0]): x = self.kdbg.get_module_by_index(i) if x == self.ntkernelbase: return raise AssertionError("ntoskrnl not found") def test_get_module_name_by_index(self): # IDebugSymbols::GetModuleNames for i in range(self.kdbg.get_number_modules()[0]): x = self.kdbg.get_module_name_by_index(i) if x[1] == "nt": return raise AssertionError("ntoskrnl not found") def test_symbol_match(self): # IDebugSymbols::StartSymbolMatch | IDebugSymbols::GetNextSymbolMatch | IDebugSymbols::EndSymbolMatch x = list(self.kdbg.symbol_match("nt!NtCreateF*")) self.assertEqual(x[0][0], 'nt!NtCreateFile') self.assertEqual(x[0][1], self.NtCreateFileVA)
def setUpClass(self): self.kdbg = LocalKernelDebugger()
class DriverUpgradeTestCase(unittest.TestCase): @classmethod def setUpClass(self): self.kdbg = LocalKernelDebugger() def test_alloc_memory(self): addr = self.kdbg.alloc_memory(0x1000) self.kdbg.write_byte(addr, 0x42) self.assertEqual(self.kdbg.read_byte(addr), 0x42) self.kdbg.write_byte(addr + 0xfff, 0x42) self.assertEqual(self.kdbg.read_byte(addr + 0xfff), 0x42) def test_full_driver_upgrade(self): upgrader = self.kdbg.upgrader upgrader.registered_ioctl = [] upgrader.full_driver_upgrade() self.test_alloc_memory() def test_retrieve_driver_upgrade(self): # Get current registered IO registered_io = self.kdbg.upgrader.registered_ioctl # Verif that some IO are registered self.assertTrue(registered_io) new_upgrader = type(self.kdbg.upgrader)(self.kdbg) # Verif that new upgrader see that driver is upgraded self.assertTrue(new_upgrader.is_driver_already_upgraded()) # Verif IOCTL retrieving new_upgrader.retrieve_upgraded_info() self.assertItemsEqual(registered_io, new_upgrader.registered_ioctl) def test_map_page_to_userland(self): kpage = self.kdbg.alloc_memory(0x1000) userpage = self.kdbg.map_page_to_userland(kpage, 0x1000) self.kdbg.write_dword(kpage, 0x11223344) self.assertEqual(ctypes.c_uint.from_address(userpage).value, 0x11223344) ctypes.c_uint.from_address(userpage + 4).value = 0x12345678 self.assertEqual(self.kdbg.read_dword(kpage + 4), 0x12345678)
class IDebugDataSpacesTestCase(unittest.TestCase): def setUp(self): pass @classmethod def setUpClass(self): windows.winproxy.SetThreadAffinityMask(dwThreadAffinityMask=(1 << 0)) self.kdbg = LocalKernelDebugger() modules = windows.utils.get_kernel_modules() self.ntkernelbase = modules[0].Base self.kernelpath = modules[0].ImageName[:] self.kernelpath = os.path.expandvars(self.kernelpath.replace("\SystemRoot", "%SystemRoot%")) self.kernelbuf = open(self.kernelpath, "rb").read() self.kernelmod = winproxy.LoadLibraryA(self.kernelpath) pe = windows.pe_parse.PEFile(self.kernelmod) self.kernel_section_data = [section for section in pe.sections if section.name == ".data"][0] def tearDown(self): #self.kdbg.detach() self.kdbg = None def test_read_byte(self): # IDebugDataSpaces::ReadVirtual x = self.kdbg.read_byte(self.kdbg.get_symbol_offset("nt")) self.assertEqual(x, ord(self.kernelbuf[0])) def test_read_word(self): # IDebugDataSpaces::ReadVirtual x = self.kdbg.read_word(self.kdbg.get_symbol_offset("nt")) self.assertEqual(x, struct.unpack("<H", self.kernelbuf[:2])[0]) def test_read_dword(self): # IDebugDataSpaces::ReadVirtual x = self.kdbg.read_dword(self.kdbg.get_symbol_offset("nt")) self.assertEqual(x, struct.unpack("<I", self.kernelbuf[:4])[0]) def test_read_qword(self): # IDebugDataSpaces::ReadVirtual x = self.kdbg.read_qword(self.kdbg.get_symbol_offset("nt")) self.assertEqual(x, struct.unpack("<Q", self.kernelbuf[:8])[0]) def test_read_byte_p(self): # IDebugDataSpaces::ReadPhysical x = self.kdbg.read_byte(self.kdbg.get_symbol_offset("nt")) y = self.kdbg.read_byte_p(self.kdbg.virtual_to_physical(self.kdbg.get_symbol_offset("nt"))) self.assertEqual(x, y) def test_read_word_p(self): # IDebugDataSpaces::ReadPhysical x = self.kdbg.read_word(self.kdbg.get_symbol_offset("nt")) y = self.kdbg.read_word_p(self.kdbg.virtual_to_physical(self.kdbg.get_symbol_offset("nt"))) self.assertEqual(x, y) def test_read_dword_p(self): # IDebugDataSpaces::ReadPhysical x = self.kdbg.read_dword(self.kdbg.get_symbol_offset("nt")) y = self.kdbg.read_dword_p(self.kdbg.virtual_to_physical(self.kdbg.get_symbol_offset("nt"))) self.assertEqual(x, y) def test_read_qword_p(self): # IDebugDataSpaces::ReadPhysical x = self.kdbg.read_qword(self.kdbg.get_symbol_offset("nt")) y = self.kdbg.read_qword_p(self.kdbg.virtual_to_physical(self.kdbg.get_symbol_offset("nt"))) self.assertEqual(x, y) @test_32bit_only @RequireSymbol('nt!KiFastCallEntry') def test_read_msr32(self): # IDebugDataSpaces::ReadMsr IA32_SYSENTER_EIP = 0x176 x = self.kdbg.read_msr(IA32_SYSENTER_EIP) y = self.kdbg.get_symbol(x) self.assertEqual(y[0], 'nt!KiFastCallEntry') @test_64bit_only @RequireSymbol('nt!KiSystemCall64') def test_read_msr64(self): # IDebugDataSpaces::ReadMsr LSTAR = 0xC0000082 x = self.kdbg.read_msr(LSTAR) y = self.kdbg.get_symbol(x) self.assertEqual(y[0], 'nt!KiSystemCall64') @test_32bit_only def test_read_processor_system_data32(self): # IDebugDataSpaces::ReadProcessorSystemData DEBUG_DATA_PROCESSOR_IDENTIFICATION = 4 x = self.kdbg.read_processor_system_data(0, DEBUG_DATA_PROCESSOR_IDENTIFICATION) self.assertEqual(cpuid.get_vendor_id(), x.X86.VendorString) self.assertEqual(cpuid.get_proc_family_model(), (x.X86.Family, x.X86.Model)) @test_64bit_only def test_read_processor_system_data64(self): # IDebugDataSpaces::ReadProcessorSystemData DEBUG_DATA_PROCESSOR_IDENTIFICATION = 4 x = self.kdbg.read_processor_system_data(0, DEBUG_DATA_PROCESSOR_IDENTIFICATION) self.assertEqual(cpuid.get_vendor_id(), x.Amd64.VendorString) self.assertEqual(cpuid.get_proc_family_model(), (x.Amd64.Family, x.Amd64.Model)) def test_write_byte(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 1 self.kdbg.write_byte(addr, 0x42) x = self.kdbg.read_byte(addr) self.assertEqual(0x42, x) def test_write_byte_p(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 1 self.kdbg.write_byte_p(self.kdbg.virtual_to_physical(addr), 0x43) x = self.kdbg.read_byte(addr) self.assertEqual(0x43, x) def test_write_word(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 2 self.kdbg.write_word(addr, 0x4444) x = self.kdbg.read_word(addr) self.assertEqual(0x4444, x) def test_write_word_p(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 2 self.kdbg.write_word_p(self.kdbg.virtual_to_physical(addr), 0x4545) x = self.kdbg.read_word(addr) self.assertEqual(0x4545, x) def test_write_dword(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 4 self.kdbg.write_dword(addr, 0x46464646) x = self.kdbg.read_dword(addr) self.assertEqual(0x46464646, x) def test_write_dword_p(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 4 self.kdbg.write_dword_p(self.kdbg.virtual_to_physical(addr), 0x47474747) x = self.kdbg.read_dword(addr) self.assertEqual(0x47474747, x) def test_write_qword(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 8 self.kdbg.write_qword(addr, 0x4848484848484848) x = self.kdbg.read_qword(addr) self.assertEqual(0x4848484848484848, x) def test_write_qword_p(self): kernel_base = self.kdbg.get_symbol_offset("nt") addr = kernel_base + self.kernel_section_data.VirtualAddress + self.kernel_section_data.VirtualSize - 8 self.kdbg.write_qword_p(self.kdbg.virtual_to_physical(addr), 0x4949494949494949) x = self.kdbg.read_qword(addr) self.assertEqual(0x4949494949494949, x)
import time import ctypes import os if os.getcwd().endswith("example"): sys.path.append(os.path.realpath("..")) else: sys.path.append(os.path.realpath(".")) import windows import windows.native_exec.simple_x86 as x86 import windows.native_exec.simple_x64 as x64 from dbginterface import LocalKernelDebugger kdbg = LocalKernelDebugger() if windows.system.bitness != 32: raise ValueError("Test for kernel32 only") def hook_ntcreatefile(kdbg, ignore_jump_space_check=False): """Hook NtCreateFile, the hook write the filename to a shared memory page""" nt_create_file = kdbg.resolve_symbol("nt!NtCreateFile") if not ignore_jump_space_check: # Check that function begin with mov edi, edi for the hook short jump if kdbg.read_word(nt_create_file) != 0xff8b: # mov edi, edi print(hex(kdbg.read_word(nt_create_file))) raise ValueError( "Cannot hook fonction that doest not begin with <mov edi,edi> (/f to force if hook already in place)" )
print("Dumping {0} first entries".format(nb_pebs_entry)) pebs_entries_buffer = (self.PEBSRecord * nb_pebs_entry)() kdbg.read_virtual_memory_into(ds_content.PEBSBufferBase, pebs_entries_buffer) return pebs_entries_buffer def dump_PEBS_records(self): ds_addr, ds_content = self.get_DsManagementArea(proc_nb) print("PEBSBufferBase = {0}".format(hex(ds_content.PEBSBufferBase))) x = self.get_pebs_records(0) for pebs_record in x: print(" {0} = {1}".format("rip", hex(pebs_record.rip))) # BTS kdbg = LocalKernelDebugger() check_feature(kdbg) kdbg.reload() kdbg.set_current_processor(0) btsm = BTSManager(kdbg) btsm.setup_DsManagementArea(0) btsm.setup_BTS(0, buffer_size=0x100000) btsm.start_BTS(enable=1) import time time.sleep(1) btsm.stop_BTS() btsm.dump_bts() # # PEBS # kdbg = LocalKernelDebugger() # check_feature(kdbg)
from dbginterface import LocalKernelDebugger import windows # This demo works on 32bits kernel only because # in _KPCR fieldnames are not the same (IDT / IdtBase, ...) if windows.system.bitness != 32: raise ValueError("Test for kernel32 only") # A lot of IDebugSymbols functions need a type identifier (TypeId) to # perform operation on said type # We tried our best to also accept the type name in this case and get # the type id automatically # (like the functions that take an address also accept a symbol) kdbg = LocalKernelDebugger() type_id = kdbg.get_type_id("nt", "_KPCR") print('type_id for "nt!_KPCR" is {0}'.format(hex(type_id))) name = kdbg.get_type_name("nt", type_id) print("The type name is {0}".format(name)) # proof that you can either use the type_id or the type name in our API size = kdbg.get_type_size("nt", type_id) print("The size retrieved using type_id is {0}".format(hex(size))) size = kdbg.get_type_size("nt", "_KPCR") print('The size retrieved using "_KPCR" is {0}'.format(hex(size))) offset = kdbg.get_field_offset("nt", "_KPCR", "IDT") print('Field "IDT" is at offset {0} in "nt!_KPCR"'.format(hex(offset)))
nb_pebs_entry = min(nb_pebs_entry, max_dump) print("Dumping {0} first entries".format(nb_pebs_entry)) pebs_entries_buffer = (self.PEBSRecord * nb_pebs_entry)() kdbg.read_virtual_memory_into(ds_content.PEBSBufferBase, pebs_entries_buffer) return pebs_entries_buffer def dump_PEBS_records(self): ds_addr, ds_content = self.get_DsManagementArea(proc_nb) print("PEBSBufferBase = {0}".format(hex(ds_content.PEBSBufferBase))) x = self.get_pebs_records(0) for pebs_record in x: print(" {0} = {1}".format("rip", hex(pebs_record.rip))) # BTS kdbg = LocalKernelDebugger() check_feature(kdbg) kdbg.reload() kdbg.set_current_processor(0) btsm = BTSManager(kdbg) btsm.setup_DsManagementArea(0) btsm.setup_BTS(0, buffer_size=0x100000) btsm.start_BTS(enable=1) import time time.sleep(1) btsm.stop_BTS() btsm.dump_bts() # # PEBS
l_idt.append((None, None)) continue addr = (idt32.ExtendedOffset << 16) | idt32.Offset if (addr < addr_nt_KiStartUnexpectedRange or addr > addr_nt_KiEndUnexpectedRange): l_idt.append((addr, get_kinterrupt(kdbg, addr, kpcr_addr, i))) else: addr_kinterrupt = get_kinterrupt(kdbg, addr, kpcr_addr, i) if addr_kinterrupt is None: addr = None l_idt.append((addr, addr_kinterrupt)) return l_idt if __name__ == '__main__': kdbg = LocalKernelDebugger() if windows.current_process.bitness == 32: l_idt = get_idt_32(kdbg) else: l_idt = get_idt_64(kdbg) for i in range(len(l_idt)): if l_idt[i][0] is not None: if l_idt[i][1] is not None: print("0x{0:02X} {1} {2} (KINTERRUPT {3})".format( i, hex(l_idt[i][0]), kdbg.get_symbol(l_idt[i][0])[0], hex(l_idt[i][1]))) else: print("0x{0:02X} {1} {2}".format( i, hex(l_idt[i][0]), kdbg.get_symbol(l_idt[i][0])[0]))
idt_base = kdbg.read_ptr(kpcr_addr + idt_base_offset) for i in xrange(0, 0xFF): idt32 = IDT32() kdbg.read_virtual_memory_into(idt_base + i * sizeof(IDT32), idt32) if (idt32.ExtendedOffset == 0 or idt32.Offset == 0): l_idt.append((None, None)) continue addr = (idt32.ExtendedOffset << 16) | idt32.Offset if (addr < addr_nt_KiStartUnexpectedRange or addr > addr_nt_KiEndUnexpectedRange): l_idt.append((addr, get_kinterrupt(kdbg, addr, kpcr_addr, i))) else: addr_kinterrupt = get_kinterrupt(kdbg, addr, kpcr_addr, i) if addr_kinterrupt is None: addr = None l_idt.append((addr, addr_kinterrupt)) return l_idt if __name__ == '__main__': kdbg = LocalKernelDebugger() if windows.current_process.bitness == 32: l_idt = get_idt_32(kdbg) else: l_idt = get_idt_64(kdbg) for i in range(len(l_idt)): if l_idt[i][0] is not None: if l_idt[i][1] is not None: print("0x{0:02X} {1} {2} (KINTERRUPT {3})".format(i, hex(l_idt[i][0]), kdbg.get_symbol(l_idt[i][0])[0], hex(l_idt[i][1]))) else: print("0x{0:02X} {1} {2}".format(i, hex(l_idt[i][0]), kdbg.get_symbol(l_idt[i][0])[0]))