11import 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
34from logging import getLogger
45from 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
333374def 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