Hook engine. Может кому-то пригодится

Дата публикации 11 апр 2022 | Редактировалось 2 май 2022

Hook engine


Движок для перехвата функций. Подойдет как для ring3 перехватов, так и для ring0. Проблемы могут возникнуть при копировании call в тело функции, но я думаю этого не будет.
Функции аллока и освобождения памяти намеренно убраны, т.к. для разных ring свои функции аллока памяти.
Работает так: дизассемблирует начальный код функции, и копирует в буфер столько кода, чтобы заместо него поместился call. После копирования, начало функции заменяется на call <> + nop для добивки остатков. При исполнении функции, вызывается колл, который вызывает функцию обработки, а затем переходит на исполнение первоначальных команд из функции.
Не будет работать, если сразу же в начале функции есть любые джампы или коллы. В остальных случаях все ок.
Код (ASM):
  1. .686
  2. .model flat, stdcall
  3.         include windows.inc
  4. .data
  5.         my_struct        db 20h dup(4) ; Структура для одного перехвата
  6.         hook_table       dd 10h dup(3) ; Таблица с перехваченными функциями
  7.         hook_table_c     dd  0h        ;
  8. .code
  9.         _salc     equ <db 0D6h>   ;sbb al,al
  10.         NrmTabLen equ 53
  11.         _aam macro num          ;ah=al/num;al=al mod num
  12.          db 0D4h, num
  13.         endm
  14.         _aad macro num          ;al=ah*num+al;ah=0
  15.          db 0D5h, num
  16.         endm
  17.         VirXasm32 proc
  18.         ; ==========[ disassemble instruction from esi ]===========
  19.                 pushad
  20.         ; ==========[ push packed tables to stack]=========
  21.                 push    000001510h
  22.                 push    0100101FFh
  23.                 push    0FFFFFF55h
  24.                 push    0FFFFFFF8h
  25.                 push    0F8FF7FA0h
  26.                 push    00F0EC40Dh
  27.                 push    007551004h
  28.                 push    001D005FFh
  29.                 push    0550D5D55h
  30.                 push    0555F0F88h
  31.                 push    0F3F3FFFFh
  32.                 push    00A0C1154h
  33.                 mov     edx, esi        ; store esi
  34.                 mov     esi, esp        ; esi = address of unpacked tables
  35.         ; ==========[ push unpack info bits to stack]==========
  36.                 push    11001b
  37.                 push    10110000101011000000101110000000b
  38.                 push    10111111101100011111001100111110b
  39.                 push    00000000000100011110101001011000b
  40.                 mov     ebx, esp        ; ebx = address of unpack info bits
  41.                 sub     esp, 110        ; reserve stack for unpacked tables
  42.                 mov     edi, esp        ; edi = address of buffer for unpacked tables
  43.         ; ==========[ unpack tables to stack ]==========
  44.                 cld
  45.                 push    100
  46.                 pop     ecx             ; total size of unpacked tables is 100 bytes
  47.         xa_nxtIndx:                     ;*xor al,al
  48.                 bt      [ebx], ecx      ; get unpack bit to CF
  49.                 _salc                   ; if bit==0 then al=0 (salc==sbb al,al but not change flags)
  50.                 jnc     xa_is0          ; if bit!=0 then ...
  51.                 lodsb                   ; ... load byte from tables in AL ...
  52.         xa_is0: stosb                   ; ... else write zero
  53.                 loop    xa_nxtIndx      ; next byte
  54.                 mov     esi, edx        ; restore esi
  55.         ; ==========[ process fucking opcodes ]==========
  56.                 push    2
  57.                 pop     ebx             ; ebx=2 (current mode - 32 bits)
  58.                 mov     edx, ebx        ; edx=2 (current addressing mode - 32 bits)
  59.         xa_NxtByte:
  60.                 lodsb
  61.                 push    eax
  62.                 push    eax             ; double store AL
  63.                 cmp     al, 66h         ; if 66h present then ...
  64.                 cmove   ebx, ecx        ; ... ebx=ecx=0 (current mode - 16 bits) *jne n32;xor ebx,ebx;n32:
  65.                 cmp     al, 67h         ; if 67h present then ...
  66.                 cmove   edx, ecx        ; ... edx=ecx=0 (current addressing mode - 16 bits)
  67.                 cmp     al, 0EAh        ; JMP FAR
  68.                 je      xa_jmp
  69.                 cmp     al, 09Ah        ; CALL FAR
  70.                 jne     xa_nocall
  71.         xa_cll: inc     esi
  72.         xa_jmp: lea     esi, [esi+ebx+3]        ; for JMP byte imm will be later
  73.         xa_nocall:
  74.                 cmp     al, 0C8h        ; fucking ENTER i16,i8  :[
  75.                 je      xa_i16
  76.                 and     al, 0F7h        ; C2h, CAh
  77.                 cmp     al, 0C2h        ; IRET i16 RET i16  :[
  78.                 jne     xa_no16
  79.         xa_i16: inc     esi
  80.                 inc     esi             ; imm16
  81.         ; ==========[ process prefixes ]==========
  82.         xa_no16:
  83.                 and     al, 0E7h
  84.                 cmp     al, 26h         ; 26h,2Eh,36h,3Eh (ES,CS,SS,DS)
  85.                 pop     eax             ; first restore AL (don't change flags)
  86.                 je      xa_PopNxt
  87.                 cmp     al, 0F1h        ; int1
  88.                 je      xa_F1
  89.                 and     al, 0FCh
  90.                 cmp     al, 0A0h        ; mov eax,[off16/32]
  91.                 jne     xa_noMOV
  92.                 lea     esi, [esi+edx+2]
  93.         xa_noMOV:
  94.                 cmp     al, 0F0h        ; F0h-F3h (LOCK,..,REPE,REPNE)
  95.                 je      xa_PopNxt
  96.         xa_F1:  cmp     al, 64h         ; 64h,65h,66h,67h (FS,GS,Prfx66,Prfx67)
  97.         xa_PopNxt:
  98.                 pop     eax             ; second restore AL (don't change flags)
  99.                 je      xa_NxtByte
  100.         ; ==========[ prepare opcode ]==========
  101.                 mov     edi, esp        ; edi = normal table (line info bits)
  102.                 push    edx             ; store addressing mode flag
  103.                 push    eax             ; store opcode value
  104.                 cmp     al, 0Fh
  105.                 jne     xa_Nrm          ; if ext. group code then ...
  106.                 lodsb                   ; ... load byte of ext. code
  107.         xa_Nrm: pushfd                  ; store FLAGS
  108.                 _aam    10h             ;*mov ah,al;shr ah,4;and al,0Fh
  109.                 xchg    cl, ah          ; high part of ecx still is zero
  110.                 cwde                    ;*nothing
  111.                 cdq                     ;*xor edx,edx (bicoz eax>0)
  112.                 xor     ebp, ebp
  113.                 popfd                   ; restore FLAGS
  114.                 jne     xa_NrmGroup
  115.         ; ==========[ extended group ]==========
  116.         xa_ExtGroup:
  117.                 add     edi, NrmTabLen  ; edi = extended table (line info bits)
  118.                 jecxz   xa_@3
  119.         xa_@1:  bt      [edi], ebp
  120.                 jnc     xa_@2           ; is not ModR/M only line?
  121.                 inc     edx             ; yeah
  122.         xa_@2:  inc     ebp
  123.                 loop    xa_@1
  124.                 jc      xa_@3
  125.                 _salc                   ;*xor al,al
  126.                 cdq                     ;*xor edx,edx
  127.         xa_@3:  shl     edx, 1
  128.                 jmp     xa_ProcOpcode
  129.         ; ==========[ normal group ]==========
  130.         xa_NrmGroup:
  131.                 sub     cl, 4
  132.                 jns     xa_@4
  133.                 mov     cl, 0Ch         ; bicoz 0xh,1xh,2xh,3xh are equal
  134.                 and     al, 7
  135.         xa_@4:  jecxz   xa_4x
  136.         xa_@5:  adc     dl, 1           ; in first pass CF==0
  137.                 inc     ebp
  138.                 bt      [edi], ebp
  139.                 loop    xa_@5
  140.                 jc      xa_ProcOpcode
  141.         xa_4x:  shr     al, 1           ; al/2
  142.         ; ==========[ process additional fields ]==========
  143.         xa_ProcOpcode:
  144.                 xchg    cl, al
  145.                 lea     edx, [edx*8+ecx]; edx=index of opcode in table
  146.                 pop     ecx             ; restore opcode value to CL
  147.                 pop     ebp             ; restore 67h flag
  148.                 bt      [edi+2], edx    ; edi+2=mod r/m info bits
  149.                 jnc     xa_noModRM
  150.         ; ==========[ process mod r/m bytes ]===========
  151.         xa_ModRM:
  152.                 lodsb
  153.                 _aam    8               ; ah=ModRO; al=RM
  154.                 shl     ah, 4           ; CF=hi Mod; SF=lo Mod
  155.                 jnc     xa_isModRM
  156.                 js      xa_enModRM      ; Mod==11
  157.         xa_isModRM:
  158.                 pushfd                  ; store FLAGS
  159.                 test    ebp, ebp        ; prefix 67 present
  160.                 jnz     xa_addr32
  161.                 sub     al, 6           ; 16 bit addressing
  162.                 jnz     xa_noSIB        ; if RM==6(BP) then ...
  163.                 mov     al, 5           ; ... offset 16
  164.         xa_addr32:                      ; 32 bit addressing
  165.                 cmp     al, 4
  166.                 jne     xa_noSIB        ; if RM==4 then ... (note: after addr16 al<2)
  167.                 lodsb                   ; ... get SIB
  168.                 and     al, 7           ; al=BASE
  169.         xa_noSIB:
  170.                 popfd                   ; restore FLAGS
  171.                 jc      xa_iWD          ; Mod==10
  172.                 js      xa_i8           ; Mod==01
  173.                 cmp     al, 5           ; if (RM==5BASE==5) && Mod==00 then ... (32 bit)
  174.                 jne     xa_enModRM      ; if            RM==6 && Mod==00 then ... (16 bit)
  175.         xa_iWD: add     esi, ebp        ; ... offset 16/32
  176.                 inc     esi
  177.         xa_i8:  inc     esi             ; offset 8
  178.         ; ==========[ fucking TEST!!! ]==========
  179.         xa_enModRM:
  180.                 test    ah, 60h         ; if RO!=0  RO!=1 then ...
  181.                 jnz     xa_noModRM      ; ... go away
  182.                 xchg    eax, ecx        ; ... else al=cl=opcode
  183.                 cmp     al, 0F6h        ; TEST rm,i8
  184.                 je      xa_ti8
  185.                 cmp     al, 0F7h        ; TEST rm,i16/i32
  186.                 jne     xa_noModRM
  187.                 add     esi, ebx        ; imm16/imm32 (66h prefix dependence)
  188.                 inc     esi
  189.         xa_ti8: inc     esi             ; imm8
  190.         ; ==========[ process immediate values ]==========
  191.         xa_noModRM:
  192.                 shl     edx, 1          ; edx*2
  193.                 bt      [edi+2+17], edx ; edi+2+17=immediate values info bits
  194.                 jnc     xa_Exit
  195.                 inc     edx
  196.                 bt      [edi+2+17], edx
  197.                 jnc     xa_im8
  198.                 adc     esi, ebx        ; imm16/imm32, 66h prefix dependence (ebx)
  199.         xa_im8: inc     esi
  200.         ; ==========[ return result and exit ]==========
  201.         xa_Exit:
  202.                 add     esp, 110+64     ; clear stack
  203.                 sub     esi, [esp+4]    ; esi=esi-old esi
  204.                 mov     [esp+7*4], esi  ; eax=esi
  205.                 popad
  206.                 ret
  207.         VirXasm32 EndP
  208.         Hook_Jump proc
  209.                 call Hook_Parse
  210.                 add  esp, 4h
  211.                 ; inline of function
  212.                 call Hook_Parse
  213.                 db 0Bh dup (90h)
  214.         Hook_Jump EndP
  215.         Hook_Parse proc
  216.                 ret
  217.         Hook_Parse EndP
  218.         WriteHook proc Function:DWORD, HookCode:DWORD, HookCodeLen:DWORD, OldCodeBuffer:DWORD
  219.                 pushad
  220.                         mov ebx, HookCodeLen
  221.                         mov esi, Function
  222.                         loopme:
  223.                                 call VirXasm32
  224.                                 add esi, eax
  225.                                 sub ebx, eax
  226.                                 jbe found_len
  227.                         jmp loopme
  228.                         found_len:
  229.                         neg ebx
  230.                         add ebx, HookCodeLen
  231.                         ; save to old buffer
  232.                         mov edi, OldCodeBuffer
  233.                         mov esi, Function
  234.                         call Copy_It
  235.                         mov edx, Function
  236.                         sub edx, ebx
  237.                         sub edx, edi
  238.                         add edx, 1h
  239.                         mov  byte ptr [edi+ebx+00h], 0E9h
  240.                         mov dword ptr [edi+ebx+01h], edx
  241.                         ; write new code
  242.                         xchg esi, edi
  243.                         mov  esi, HookCode
  244.                         call Copy_It
  245.                         mov dword ptr [esp+1ch], ebx
  246.                 popad
  247.                 ret
  248.         WriteHook EndP
  249.         Copy_It proc
  250.                 mov ecx, ebx
  251.                 cp_loop:
  252.                         mov al, byte ptr [esi+ecx-1]
  253.                         mov byte ptr [edi+ecx-1], al
  254.                 loop cp_loop
  255.                 retn
  256.         Copy_It EndP
  257.         Hook_Install proc function:DWORD ; Public function
  258.                 ; Нужно выделить память для структуры (8h + 4h + 4h + 10h байт)
  259.                 ;  8h code
  260.                 ; 10h oldcode + jmp back
  261.                 ;  4h real address
  262.                 ;  4h size
  263.                 mov eax, offset my_struct
  264.                 .if eax == 0
  265.                         ;DbgPrnt "insufficient resources"
  266.                         jmp exit
  267.                 .endif
  268.                 ; Save in table
  269.                 mov ebx, hook_table_c
  270.                 mov dword ptr [hook_table+ebx*4], eax
  271.                 inc hook_table_c
  272.      
  273.                 ; Prepare buffer
  274.                 mov ebx, dword ptr [Hook_Jump+00h] ; code
  275.                 mov dword ptr [eax+00h], ebx       ; code
  276.                 mov ebx, dword ptr [Hook_Jump+04h] ; code
  277.                 mov dword ptr [eax+04h], ebx       ; code
  278.                 mov ebx, offset Hook_Parse         ; <call Hook_Parse>
  279.                 sub ebx, eax                       ; <call Hook_Parse>
  280.                 sub ebx, 5h                        ; <call Hook_Parse>
  281.                 mov dword ptr [eax+01h], ebx       ; <call Hook_Parse>
  282.                 mov ebx, function                  ; function ptr
  283.                 mov dword ptr [eax+18h], ebx       ; function ptr
  284.                 neg ebx                            ; prepare <call code>
  285.                 lea ecx, dword ptr [eax+ebx-05h]   ; prepare <call code>
  286.                 mov dword ptr [Hook_Jump+09h], ecx ; prepare <call code>
  287.                 push eax
  288.                 add eax, 8h                        ; old code buffer
  289.                 invoke WriteHook, function, \      ; write hook
  290.                        addr Hook_Jump + 8h, 5, eax ; write hook
  291.                 pop ebx                            ; size
  292.                 mov dword ptr [ebx+1ch], eax       ; size
  293.                 exit:
  294.                 ret
  295.         Hook_Install EndP
  296.         Hook_RemoveAll proc  ; Public function
  297.                 pushad
  298.                         mov ecx, hook_table_c
  299.                         rm_loop:
  300.                                 cmp ecx, 0
  301.                                 jle exit
  302.                                 dec ecx
  303.                                 push ecx
  304.                                         mov  eax, dword ptr [hook_table+ecx*4]
  305.                                         lea  esi, dword ptr [eax+08h]          ; old code
  306.                                         mov  edi, dword ptr [eax+18h]          ; function ptr
  307.                                         mov  ebx, dword ptr [eax+1ch]          ; size
  308.                                         call Copy_It
  309.                                         ; Тут надо освободить память из eax
  310.                                 pop  ecx
  311.                         jmp rm_loop
  312.                         exit:
  313.                         mov hook_table_c, 0
  314.                 popad
  315.                 ret
  316.         Hook_RemoveAll EndP
  317.         testcode proc              ; Перехватываемая функция
  318.                 local teste:DWORD
  319.                 mov eax, 10
  320.                 ret
  321.         testcode EndP
  322.         Testme proc
  323.                 invoke Hook_Install, addr testcode ; Устанавливаем хук
  324.                 invoke testcode                    ; Вызываем перехваченную функцию
  325.                 invoke Hook_RemoveAll              ; Снимаем все хуки
  326.                 invoke testcode                    ; Проверяем снятие хуков
  327.                 ret
  328.         Testme EndP
  329. End Testme

2 2.672
who_know777

who_know777
Member

Регистрация:
29 мар 2021
Публикаций:
2

Комментарии


      1. x0rum 8 май 2022
        Тестить я это конечно не буду, но за олдскульный вайб безусловный лайк. )
      2. Treant 26 ноя 2023
        [​IMG]