Skip to content

Commit d3069f5

Browse files
committed
switch to dataclass for capture hook
1 parent 65b48a2 commit d3069f5

File tree

1 file changed

+65
-26
lines changed

1 file changed

+65
-26
lines changed

memobj/hook.py

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import time
2-
from typing import TYPE_CHECKING, Callable, Any, Self
2+
from dataclasses import dataclass
3+
from typing import TYPE_CHECKING, Callable, Any, Self, Sequence
34
from logging import getLogger
45
from functools import cached_property
56

@@ -329,12 +330,52 @@ def get_code(self) -> list[Instruction]:
329330
raise NotImplementedError()
330331

331332

333+
"""
334+
123: <block>
335+
u32 entries
336+
u32 entry_size
337+
entry
338+
entry
339+
entry
340+
341+
342+
push rax
343+
push r8
344+
push r9
345+
mov rax,[rcx]
346+
mov r8, [123]
347+
mov r9, [123+4]
348+
cmp r8,<max_entry_number>
349+
jz reset
350+
mov [123+r8*r9+8],rax
351+
inc r8
352+
mov [123],r8
353+
jmp pop_off
354+
reset:
355+
mov [123],0x00000000
356+
pop_off:
357+
pop rax
358+
pop r8
359+
pop r9
360+
"""
361+
# class ListMulticapture(JmpHook):
362+
# ...
363+
364+
365+
@dataclass
366+
class RegisterCaptureSettings:
367+
register: RegisterType
368+
derefference: bool = True
369+
offset: int = 0
370+
371+
372+
# TODO: remove the offset stuff from register capture, it's useless
332373
# NOTE: this registertype is kinda mid, we may need to provide our own
333374
def create_capture_hook(
334375
pattern: regex.Pattern | bytes,
335376
module: str,
336377
*,
337-
registers: set[tuple[RegisterType, int | None]]
378+
register_captures: list[RegisterCaptureSettings]
338379
) -> type[JmpHook]:
339380
"""Create a capture hook class
340381
@@ -348,24 +389,20 @@ def create_capture_hook(
348389
Args:
349390
pattern (regex.Pattern | bytes): Pattern to hook at
350391
module (str): Module to search in
351-
registers (set[tuple[RegisterType, int | None]]): Registers to capture
392+
register_captures (list[RegisterCaptureSettings]): Registers to capture
352393
353394
Returns:
354395
type[JmpHook]: The created capture hook
355396
"""
356-
357-
rax_offset = 0
358-
359-
for register_set in registers:
360-
if register_set[0] == Register.RAX:
361-
rax_register = True
362-
rax_offset = register_set[1]
397+
for register_setting in register_captures:
398+
if register_setting.register == Register.RAX:
399+
rax_register = register_setting
363400
break
364401
else:
365-
rax_register = False
402+
rax_register = None
366403

367-
if rax_register:
368-
registers.remove((Register.RAX, rax_offset))
404+
if rax_register is not None:
405+
register_captures.remove(rax_register)
369406

370407
class CaptureHook(JmpHook):
371408
PATTERN = pattern
@@ -375,9 +412,9 @@ def get_code(self) -> list[Instruction]:
375412
instructions: list[Instruction] = [Instruction.create_reg(Code.PUSH_R64, Register.RAX)]
376413

377414
# we need to get rax first since it's used to mov the rest
378-
if rax_register:
415+
if rax_register is not None:
379416
rax_capture = self.allocate_variable("RAX_capture", 8)
380-
if rax_offset == 0:
417+
if rax_register.derefference is True and rax_register.offset == 0:
381418
# mov rax,[rax]
382419
instructions.append(
383420
Instruction.create_reg_mem(
@@ -386,7 +423,7 @@ def get_code(self) -> list[Instruction]:
386423
MemoryOperand(Register.RAX, displ_size=8)
387424
)
388425
)
389-
elif rax_offset is None:
426+
elif rax_register.derefference is False:
390427
# mov rax,rax
391428
instructions.append(Instruction.create_mem_reg(
392429
Code.MOV_MOFFS64_RAX,
@@ -399,50 +436,52 @@ def get_code(self) -> list[Instruction]:
399436
Instruction.create_reg_mem(
400437
Code.MOV_R64_RM64,
401438
Register.RAX,
402-
MemoryOperand(Register.RAX, displ=rax_offset, displ_size=8),
439+
MemoryOperand(Register.RAX, displ=rax_register.offset, displ_size=8),
403440
))
404-
441+
405442
# mov [<addr>],rax
406443
instructions.append(Instruction.create_mem_reg(
407444
Code.MOV_MOFFS64_RAX,
408445
MemoryOperand(displ=rax_capture.address, displ_size=8),
409446
Register.RAX,
410447
))
411448

412-
for register, offset in registers:
413-
name = get_register_name(register)
449+
for register_setting in register_captures:
450+
name = get_register_name(register_setting.register)
414451
capture = self.allocate_variable(f"{name}_capture", 8)
415452

416-
if offset == 0:
453+
if register_setting.derefference is True and register_setting.offset == 0:
417454
# mov rax,[<reg>]
418455
instructions.append(
419456
Instruction.create_reg_mem(
420457
Code.MOV_R64_RM64,
421458
Register.RAX,
422-
MemoryOperand(register, displ_size=8)
459+
MemoryOperand(register_setting.register, displ_size=8)
423460
)
424461
)
425462

426-
elif offset is None:
463+
elif register_setting.derefference is False:
427464
# mov rax,<reg>
428465
instructions.append(
429466
Instruction.create_reg_reg(
430467
Code.MOV_R64_RM64,
431468
Register.RAX,
432-
register,
469+
register_setting.register,
433470
)
434471
)
435472
else:
473+
offset = register_setting.offset
474+
436475
# TODO: make sure to account for 32 bit here if support is added
437-
if register == Register.RSP:
476+
if register_setting.register == Register.RSP:
438477
offset += 8 # push rax before moves
439478

440479
# mov rax,[<reg>+<offset>]
441480
instructions.append(
442481
Instruction.create_reg_mem(
443482
Code.MOV_R64_RM64,
444483
Register.RAX,
445-
MemoryOperand(base=register, displ=offset, displ_size=8),
484+
MemoryOperand(base=register_setting.register, displ=offset, displ_size=8),
446485
)
447486
)
448487

0 commit comments

Comments
 (0)