The principle and application example of C + + realization of inline hook _c language

Source: Internet
Author: User
Tags apc

This paper introduces the principle and application of C + + to realize inline hook, and it is helpful for us to understand the principle and application of inline hook better. The specific contents are as follows:

First, Inline hook introduction:

1.INLINE Hook principle:

The Inline Hook writes a jump statement to the kernel API's memory space in a hard-coded way (usually the beginning of a byte, and generally before the first call, to prevent stack clutter), so that as soon as the API is invoked, the program jumps into our function, We need to complete 3 tasks in our own written function:

1) readjust the current stack. Program flow in just jump, the kernel API did not finish, and our function needs to be based on the results of information filtering, so we need to ensure that the kernel API can be completed after the successful return to our function, which requires the current stack to make an adjustment.

2 Execute the lost instruction. When we go to the kernel API address space such as jump instruction (jmp xxxxxxxx), it is bound to overwrite some of the original assembly instructions, so we must ensure that these covered instructions can be implemented smoothly (otherwise, your and will be BSOD, hehe, Blue screen of Death). The implementation of this part of the instruction is generally placed in our function, let our function "help" Kernel API to execute the overridden instructions, and then jump back to the kernel API after the cover of the address to continue to execute the remaining content. Jump back to the time, must be counted is to jump back to what address, is the kernel API starting address after the first few bytes.

3) Information filtering. This is needless to say, the kernel API to execute smoothly and return to our function, we naturally have to do some information filtering based on the results, this part of the hook for the API and the hook for different purposes.

2.Inline Hook Workflow:

1 Verify the version of the kernel API (signature matching).

2 Write your own function, to complete the above three tasks.

3 Get the address of its own function, overwriting the kernel API memory for jump.

In short, theprinciple of inlinehook is to modify the function so that it jumps to the place we specify.

It is common to change the function of the entrance, also have the function of the tail, function in the middle of the
For example, usually the assembly code at the beginning of a function is like this: mov edi,edi;push Esp;mov ebp,esp, and we can modify the hook here.

Second, sample code (this example is from snow-watching)

#include <ntifs.h> #include <windef.h> ULONG G_KIINSERTQUEUEAPC;
ULONG g_ucr0; BYTE G_hookcode[5] = {0xe9, 0, 0, 0, 0}; JMP NEAR BYTE G_origcode[5] = {0}; The former byte content of the original function byte jmp_orig_code[7] = {0xEA, 0, 0, 0, 0, 0x08, 0x00};
JMP FAR BOOL g_bhooked = FALSE;
VOID FAKE_KIINSERTQUEUEAPC (Pkapc Apc, kpriority Increment);
VOID PROXY_KIINSERTQUEUEAPC (Pkapc Apc, kpriority Increment);
  void Wpoff () {ULONG uattr;
    _asm {push eax;
    mov eax, CR0;
    mov uattr, eax; and eax, 0FFFEFFFFh;
    CR0 BIT = 0 mov cr0, eax;
    Pop eax;
  CLI}; G_UCR0 = uattr;
    Preserve the original CRO} VOID Wpon () {_asm {STI push eax; mov eax, g_ucr0;
    Restore the original CR0 of CR0, eax;
  Pop eax;
};
  ///stop inline hook//VOID UNHOOKKIINSERTQUEUEAPC () {KIRQL oldirql;
  Wpoff ();
  OLDIRQL = Keraiseirqltodpclevel ();
  Rtlcopymemory ((byte*) G_KIINSERTQUEUEAPC, G_origcode, 5);KELOWERIRQL (OLDIRQL);
  Wpon ();
g_bhooked = FALSE;
  ////start inline hook--KIINSERTQUEUEAPC//VOID HOOKKIINSERTQUEUEAPC () {KIRQL oldirql;
    if (G_KIINSERTQUEUEAPC = = 0) {dbgprint ("KIINSERTQUEUEAPC = = null\n");
  Return
  //dbgprint ("Start inline hook--kiinsertqueueapc\n");
  Dbgprint ("KIINSERTQUEUEAPC's Address t0x%08x\n", (ULONG) G_KIINSERTQUEUEAPC);
  
  Dbgprint ("FAKE_KIINSERTQUEUEAPC's Address t0x%08x\n", (ULONG) FAKE_KIINSERTQUEUEAPC);
  Saves the first byte content of the original function rtlcopymemory (G_origcode, (byte*) G_KIINSERTQUEUEAPC, 5); JMP instruction, which is a short hop, calculates the relative offset, and jmp xxxxxx This instruction takes up 5 bytes * ((ulong*) (G_hookcode + 1)) = (ULONG) FAKE_KIINSERTQUEUEAPC-(ULONG) g_kii
  nsertQueueApc-5;
  Prohibit system write protection, elevate IRQL to DPC Wpoff ();
  OLDIRQL = Keraiseirqltodpclevel ();
  Rtlcopymemory ((byte*) G_KIINSERTQUEUEAPC, G_hookcode, 5);
  * ((ulong*) (Jmp_orig_code + 1)) = (ULONG) ((byte*) G_KIINSERTQUEUEAPC + 5);
  Rtlcopymemory ((byte*) PROXY_KIINSERTQUEUEAPC, G_origcode, 5); Rtlcopymemory ((byte*) PROXY_KIINSERTQUEUEAPC + 5, Jmp_orig_code, 7);
  Restore write protection, reduce IRQL KELOWERIRQL (OLDIRQL);
  Wpon ();
g_bhooked = TRUE;
            ////jump to our function to preprocess, bare function, have the caller stack balance//__declspec (naked) VOID FAKE_KIINSERTQUEUEAPC (PKAPC Apc, Kpriority Increment) {//Remove dbgprint, or this hook will generate recursion//dbgprint ("inline hook--KIINSERTQUEUEAPC successful \ \")
  ; __asm {jmp PROXY_KIINSERTQUEUEAPC}}///proxy function, responsible for jumping to the original function//__declspec (naked) VOID PROXY_KIINSERTQUEUEAPC
(Pkapc Apc, kpriority Increment)
      {__asm {//Total bytes _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90 _emit 0x90//Pre bytes implement header byte function of original function _emit 0x90//This fill jmp _emit 0x90 _emit 0x90 _emit 0x90 the _emit 0x90//This byte saves the original function + 5 address _emi T 0x90 _emit 0x90//Because it is a long transfer, it must be 0x0080} ULONG getfunctionaddr (in pcwstr functionname) {unicode_string Uni
  Codefunctionname;
  Rtlinitunicodestring (&unicodefunctionname, functionname); Return (ULONG) MMgetsystemroutineaddress (&unicodefunctionname); KEINSERTQUEUEAPC Search KIINSERTQUEUEAPC ULONG findkiinsertqueueapcaddress () {char * ADDR_KEINSERTQUEUEAPC = 0 based on eigenvalues)
  ;
  int i = 0;
  Char findcode[] = {0xe8, 0xcc, 0x29, 0x00, 0x00};
  ULONG ADDR_KIINSERTQUEUEAPC = 0;
  ADDR_KEINSERTQUEUEAPC = (char *) getfunctionaddr (L "KEINSERTQUEUEAPC"); for (i = 0; i < i + +) {if (addr_keinsertqueueapc[i] = = Findcode[0] && addr_keinsertqueueapc[i + 1] = = Findcode[1] && addr_keinsertqueueapc[i + 2] = = Findcode[2] && addr_keinsertqueueapc[i  + 3] = = Findcode[3] && addr_keinsertqueueapc[i + 4] = = Findcode[4] {ADDR_KIINSERTQUEUEAPC =
      (ULONG) &addr_keinsertqueueapc[i] + 0x29cc + 5;
    Break
} return ADDR_KIINSERTQUEUEAPC;
  } VOID OnUnload (in Pdriver_object driverobject) {dbgprint (' my Driver unloaded! ');
UNHOOKKIINSERTQUEUEAPC (); } NTSTATUS DriverEntry (in Pdriver_object thedriverobject, in Punicode_string Theregistrypath) {dbgprint ("my Driver loaded!");
  Thedriverobject->driverunload = OnUnload;
  G_KIINSERTQUEUEAPC = Findkiinsertqueueapcaddress ();
  HOOKKIINSERTQUEUEAPC ();
return status_success;
 }
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.