def get_peb_addr(self): dest = self.virtual_alloc(0x1000) if self.bitness == 32: store_peb = x86.MultipleInstr() store_peb += x86.Mov('EAX', x86.mem('fs:[0x30]')) store_peb += x86.Mov(x86.create_displacement(disp=dest), 'EAX') store_peb += x86.Ret() get_peb_code = store_peb.get_code() self.write_memory(dest, "\x00" * 4) self.write_memory(dest + 4, get_peb_code) self.create_thread(dest + 4, 0) time.sleep(0.01) peb_addr = struct.unpack("<I", self.read_memory(dest, 4))[0] return peb_addr else: store_peb = x64.MultipleInstr() store_peb += x64.Mov('RAX', x64.mem('gs:[0x60]')) store_peb += x64.Mov(x64.create_displacement(disp=dest), 'RAX') store_peb += x64.Ret() get_peb_code = store_peb.get_code() self.write_memory(dest, "\x00" * 8) self.write_memory(dest + 8, get_peb_code) self.create_thread(dest + 8, 0) time.sleep(0.01) peb_addr = struct.unpack("<Q", self.read_memory(dest, 8))[0] return peb_addr
def register_kernel_call(self): # expect in buffer: the address to call and all dword to push on the stack CCall_IOCTL = x86.MultipleInstr() CCall_IOCTL += x86.Mov('EAX', self.IO_STACK_INPUT_BUFFER_LEN) CCall_IOCTL += x86.Cmp('EAX', 0) CCall_IOCTL += x86.Jz(":FAIL") # Need at least the function to call CCall_IOCTL += x86.Mov('ECX', self.IO_STACK_INPUT_BUFFER) CCall_IOCTL += x86.Label(':PUSH_NEXT_ARG') CCall_IOCTL += x86.Cmp('EAX', 4) CCall_IOCTL += x86.Jz(":DO_CALL") CCall_IOCTL += x86.Sub('EAX', 4) INPUT_BUFFER_NEXT_ARG = x86.create_displacement(base='ECX', index='EAX') CCall_IOCTL += x86.Mov('EBX', INPUT_BUFFER_NEXT_ARG) CCall_IOCTL += x86.Push('EBX') CCall_IOCTL += x86.Jmp(':PUSH_NEXT_ARG') CCall_IOCTL += x86.Label(":DO_CALL") CCall_IOCTL += x86.Mov('EAX', x86.mem('[ECX]')) CCall_IOCTL += x86.Call('EAX') CCall_IOCTL += x86.Mov('EDX', self.IRP_OUTPUT_BUFFER) CCall_IOCTL += x86.Mov(x86.mem('[EDX]'), 'EAX') CCall_IOCTL += x86.Xor('EAX', 'EAX') CCall_IOCTL += x86.Ret() CCall_IOCTL += x86.Label(":FAIL") CCall_IOCTL += x86.Mov('EAX', 0x0C000000D) CCall_IOCTL += x86.Ret() self.upgrade_driver_add_new_ioctl_handler(DU_KCALL_IOCTL, CCall_IOCTL.get_code())
def test_execute_to_proc32(self, proc32): with proc32.allocated_memory(0x1000) as addr: shellcode = x86.MultipleInstr() shellcode += x86.Mov('EAX', 0x42424242) shellcode += x86.Mov(x86.create_displacement(disp=addr), 'EAX') shellcode += x86.Ret() proc32.execute(shellcode.get_code()) time.sleep(0.1) dword = proc32.read_dword(addr) assert dword == 0x42424242
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("<I", calc.read_memory(data, 4))[0] self.assertEqual(dword, 0x42424242)
def _upgrade_driver_inject_base_upgrade(self): kldbgdrv = self.kldbgdrv upgrade = x86.MultipleInstr() IoControlCode_on_stack = x86.create_displacement(base='EBP', disp=-0x30) IO_STACK_LOCATION_on_stack = x86.create_displacement(base='EBP', disp=-0x34) IoStatus_on_stack = x86.create_displacement(base='EBP', disp=-0x3c) IRP_on_stack = x86.create_displacement(base='EBP', disp=+0x0c) upgrade += x86.Mov('EBX', IoControlCode_on_stack) upgrade += x86.Mov('EAX', x86.create_displacement(disp=kldbgdrv + self.HANDLE_ARRAY_ADDR)) upgrade += x86.Label(":LOOP") upgrade += x86.Mov('ECX', x86.create_displacement('EAX')) upgrade += x86.Cmp('EBX', 'ECX') upgrade += x86.Jnz(':END') upgrade += x86.Mov('EAX', x86.create_displacement('EAX', disp=4)) # ESI -> IO_STACK_LOCATION # EDI -> IRP upgrade += x86.Mov('ESI', IO_STACK_LOCATION_on_stack) upgrade += x86.Mov('EDI', IRP_on_stack) upgrade += x86.Call('EAX') upgrade += x86.Mov(IoStatus_on_stack, 'EAX') upgrade += x86.JmpAt(kldbgdrv + self.normal_end) upgrade += x86.Label(":END") upgrade += x86.Cmp('ECX', 0) upgrade += x86.Jnz(':NEXT') upgrade += x86.JmpAt(kldbgdrv + self.failed_offset) upgrade += x86.Label(":NEXT") upgrade += x86.Add('EAX', 8) upgrade += x86.Jmp(':LOOP') # Write new driver code self.kdbg.write_pfv_memory(kldbgdrv + self.init_function_offset, str(upgrade.get_code())) # Write first array dest self.write_pfv_ptr(kldbgdrv + self.HANDLE_ARRAY_ADDR, kldbgdrv + self.FIRST_ARRAY_ADDR) self.write_pfv_ptr(kldbgdrv + self.FIRST_ARRAY_ADDR, 0) self.write_pfv_ptr(kldbgdrv + self.FIRST_ARRAY_ADDR + 4, 0) # Jump hijack jump_init_function = x86.Jmp(self.init_function_offset - (self.hijack_offset)) self.kdbg.write_pfv_memory(kldbgdrv + self.hijack_offset, str(jump_init_function.get_code())) self.is_upgraded = True self.ioctl_array = kldbgdrv + self.FIRST_ARRAY_ADDR self.ioctl_array_ptr = kldbgdrv + self.HANDLE_ARRAY_ADDR self.next_code_addr = kldbgdrv + self.init_function_offset + len(upgrade.get_code())