Inline Hook of ring3 simple C++ implementation method

  • 2020-04-02 02:33:39
  • OfStack

C++ Inline Hook code, using the method of backup DLL, so in the custom function can be directly called in memory backup DLL code, without changing the function header to change. Using the SetWindowsHookEx program should increase the stability a lot.

It's important to note that we didn't change the head of the function back a few bytes in the example because the program is so simple that you can exit after just testing the effect and nothing else. In practice, you also need to change the first few bytes of the original function back when the DLL module you injected is unloaded, so as not to affect the stability of the program. Since the injected program is not its own, it is impossible to know exactly when and how many function calls we Hook.

The specific implementation code is as follows:


#include <ntifs.h>
#include <windef.h> 
#include <stdio.h>
#pragma comment(lib, "psapi.lib")
//BYTE Org_Code[7];//Back up the DLL method, so you don't need it
BYTE New_Code[7];
HMODULE hDllHandle = NULL; //DLL handle that is hooked
HANDLE hProcess = NULL; //Process to handle
LPVOID _MessageBoxA = NULL; //MessageBoxA () the original address
DWORD _ShowMessage = NULL; //Custom function address
void InlineHook();
//void UnInlineHook(); //Back up the DLL method, so you don't need it
void BackupDll();
//Custom function
int WINAPI ShowMessage(HWND, LPTSTR, LPTSTR, UINT);
void main()
{
  hProcess = ::GetCurrentProcess();
  hDllHandle = ::LoadLibrary("user32.dll");
  if (hDllHandle == NULL)
    return;
  _MessageBoxA = (LPVOID)::GetProcAddress(hDllHandle, "MessageBoxA");
  if (_MessageBoxA == NULL)
    return;
  BackupDll();
  InlineHook();
  char szText[256];
  char szTitle[256];
  memset(szText, 0x0, sizeof(szText));
  memset(szTitle, 0x0, sizeof(szTitle));
  //The following loop receives characters from user input and USES MessageBoxA()
  //Try it out and see what happens. :)
  while (TRUE)
  {
    printf("Message Text: ");
    scanf("%s", szText);
    printf("Message Title: ");
    scanf("%s", szTitle);
    MessageBoxA(NULL, szText, szTitle, 0);
    printf("n");
  }
  return;
}
void InlineHook()
{
  DWORD _JmpAddr = (DWORD)ShowMessage;
  //Construct the new header code
  New_Code[0] = 0xB8;            //
  memcpy(&New_Code[1], &_JmpAddr, 4);    // mov eax, _JmpAddr
  New_Code[5] = 0xFF;            //
  New_Code[6] = 0xE0;            // jmp eax
  DWORD dwOldProtect = 0;
  //De-memory protection
  ::VirtualProtect(_MessageBoxA, 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  //Write the new code to the header of MessageBoxA(), which is also Inline Hook
  //The heart of it.
  ::WriteProcessMemory(
    hProcess,
    _MessageBoxA,
    New_Code,
    sizeof(New_Code),
    NULL
  );
  //Write memory protection
  ::VirtualProtect(_MessageBoxA, 7, dwOldProtect, &dwOldProtect);
  return;
}
/*
void UnInlineHook() //Back up the DLL method, so you don't need it
{
  return;
}
*/
int WINAPI ShowMessage(HWND hWnd, LPTSTR lpText, LPTSTR lpTitle, UINT uType)
{
  typedef int WINAPI SHOWMSG(HWND hWnd, LPTSTR lpText, LPTSTR lpTitle, UINT uType);
  SHOWMSG *pShowMsg = (SHOWMSG*)_ShowMessage;
  //Discard the parameters passed in and define the dialog text
  char buf[1024];
  ::wsprintf(buf, "The Text:"%s" was hacked by miku_fl", lpText);
  return pShowMsg(hWnd, buf, lpTitle, MB_ICONINFORMATION | MB_TOPMOST);
}
void BackupDll()
{
  MODULEINFO  Mdl_Info;
  LPVOID    lpNewDLL  =  NULL;
  //Get module information
  ::GetModuleInformation(hProcess, hDllHandle, &Mdl_Info, sizeof(Mdl_Info));
  //Allocate memory space for backing up DLLS (so there is no need to restore the original header code, called
  //Rewrite your custom header after you're done).
  lpNewDLL = ::VirtualAllocEx(
    hProcess,
    NULL,
    Mdl_Info.SizeOfImage,
    MEM_COMMIT,
    PAGE_EXECUTE_READWRITE
  );
  if (lpNewDLL == NULL)
    return;
  //Writes the contents of DLL files in allocated memory
  ::WriteProcessMemory(hProcess, lpNewDLL, Mdl_Info.lpBaseOfDll, Mdl_Info.SizeOfImage, NULL);
  //Calculates the address of the custom function.
  //Formula: custom address = original API function address - module base address + allocated memory base address
  _ShowMessage = (DWORD)_MessageBoxA - (DWORD)Mdl_Info.lpBaseOfDll + (DWORD)lpNewDLL;
  return;
}

Hopefully, the program examples described in this article will be helpful.


Related articles: