Skip to content

Commit 10a6434

Browse files
committed
add 32 bit support to create_capture_hook
1 parent 49db87d commit 10a6434

File tree

1 file changed

+55
-38
lines changed

1 file changed

+55
-38
lines changed

memobj/hook.py

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -405,24 +405,69 @@ class RegisterCaptureSettings:
405405
offset: int = 0
406406

407407

408-
# TODO: remove the offset stuff from register capture, it's useless
409408
# NOTE: this registertype is kinda mid, we may need to provide our own
410409
def create_capture_hook(
411410
pattern: regex.Pattern | bytes,
412411
module: str,
412+
bitness: Literal[32] | Literal[64],
413413
*,
414-
register_captures: list[RegisterCaptureSettings]
414+
register_captures: list[RegisterCaptureSettings],
415415
) -> type[JmpHook]:
416416
"""Create a capture hook class
417417
418418
Args:
419419
pattern (regex.Pattern | bytes): Pattern to hook at
420420
module (str): Module to search in
421+
bitness (int): What bitness of hook to create
421422
register_captures (list[RegisterCaptureSettings]): Registers to capture
422423
423424
Returns:
424425
type[JmpHook]: The created capture hook
425426
"""
427+
428+
if bitness == 64:
429+
return _create_capture_hook_64bit(pattern, module, register_captures)
430+
else:
431+
return _create_capture_hook_32bit(pattern, module, register_captures)
432+
433+
434+
def _create_capture_hook_32bit(pattern: regex.Pattern | bytes, module: str, register_captures: list[RegisterCaptureSettings]):
435+
class CaptureHook(JmpHook):
436+
PATTERN = pattern
437+
MODULE = module
438+
439+
def get_code(self) -> list[Instruction]:
440+
instructions: list[Instruction] = []
441+
442+
for register_setting in register_captures:
443+
name = get_register_name(register_setting.register)
444+
capture = self.allocate_variable(f"{name}_capture", 4)
445+
446+
if register_setting.derefference is True:
447+
instructions += [
448+
# push <reg>
449+
Instruction.create_reg(Code.PUSH_R32, register_setting.register),
450+
# mov <reg>,[<reg>+<offset>]
451+
Instruction.create_reg_mem(Code.MOV_R32_RM32, register_setting.register, MemoryOperand(register_setting.register, displ=register_setting.offset, displ_size=4)),
452+
# mov [<capture_addr>],<reg>
453+
Instruction.create_mem_reg(Code.MOV_RM32_R32, MemoryOperand(displ=capture.address, displ_size=4), register_setting.register),
454+
# pop <reg>
455+
Instruction.create_reg(Code.POP_R32, register_setting.register),
456+
]
457+
458+
459+
else:
460+
# mov rax,<reg>
461+
instructions.append(
462+
Instruction.create_mem_reg(Code.MOV_RM32_R32, MemoryOperand(displ=capture.address, displ_size=4), register_setting.register)
463+
)
464+
465+
return instructions
466+
467+
return CaptureHook
468+
469+
470+
def _create_capture_hook_64bit(pattern: regex.Pattern | bytes, module: str, register_captures: list[RegisterCaptureSettings]):
426471
for register_setting in register_captures:
427472
if register_setting.register == Register.RAX:
428473
rax_register = register_setting
@@ -443,30 +488,15 @@ def get_code(self) -> list[Instruction]:
443488
# we need to get rax first since it's used to mov the rest
444489
if rax_register is not None:
445490
rax_capture = self.allocate_variable("RAX_capture", 8)
446-
if rax_register.derefference is True and rax_register.offset == 0:
447-
# mov rax,[rax]
491+
if rax_register.derefference is True:
492+
# mov rax,[rax+<offset>]
448493
instructions.append(
449494
Instruction.create_reg_mem(
450495
Code.MOV_R64_RM64,
451496
Register.RAX,
452-
MemoryOperand(Register.RAX, displ_size=8)
497+
MemoryOperand(Register.RAX, displ=rax_register.offset, displ_size=8)
453498
)
454499
)
455-
elif rax_register.derefference is False:
456-
# mov rax,rax
457-
instructions.append(Instruction.create_mem_reg(
458-
Code.MOV_MOFFS64_RAX,
459-
MemoryOperand(displ=rax_capture.address, displ_size=8),
460-
Register.RAX,
461-
))
462-
else:
463-
# mov rax,[rax+<offset>]
464-
instructions.append(
465-
Instruction.create_reg_mem(
466-
Code.MOV_R64_RM64,
467-
Register.RAX,
468-
MemoryOperand(Register.RAX, displ=rax_register.offset, displ_size=8),
469-
))
470500

471501
# mov [<addr>],rax
472502
instructions.append(Instruction.create_mem_reg(
@@ -479,17 +509,18 @@ def get_code(self) -> list[Instruction]:
479509
name = get_register_name(register_setting.register)
480510
capture = self.allocate_variable(f"{name}_capture", 8)
481511

482-
if register_setting.derefference is True and register_setting.offset == 0:
483-
# mov rax,[<reg>]
512+
if register_setting.derefference is True:
513+
# NOTE: this doesn't work for RSP
514+
# mov rax,[<reg>+<offset>]
484515
instructions.append(
485516
Instruction.create_reg_mem(
486517
Code.MOV_R64_RM64,
487518
Register.RAX,
488-
MemoryOperand(register_setting.register, displ_size=8)
519+
MemoryOperand(register_setting.register, displ=register_setting.offset, displ_size=8)
489520
)
490521
)
491522

492-
elif register_setting.derefference is False:
523+
else:
493524
# mov rax,<reg>
494525
instructions.append(
495526
Instruction.create_reg_reg(
@@ -498,21 +529,7 @@ def get_code(self) -> list[Instruction]:
498529
register_setting.register,
499530
)
500531
)
501-
else:
502-
offset = register_setting.offset
503532

504-
# TODO: make sure to account for 32 bit here if support is added
505-
if register_setting.register == Register.RSP:
506-
offset += 8 # push rax before moves
507-
508-
# mov rax,[<reg>+<offset>]
509-
instructions.append(
510-
Instruction.create_reg_mem(
511-
Code.MOV_R64_RM64,
512-
Register.RAX,
513-
MemoryOperand(base=register_setting.register, displ=offset, displ_size=8),
514-
)
515-
)
516533

517534
instructions.append(
518535
Instruction.create_mem_reg(

0 commit comments

Comments
 (0)