You must understand the PE file structure and basic windowsAPI. The following program replaces the MessageBoxA function in user32.dll with its own MyMessageBox, which is a redirection function.
[Cpp]
// NormalProject. cpp: Defines the entry point for the application.
//
# Include "stdafx. h"
# Include <windows. h>
# Include "NormalProject. h"
# Include "KPEFile. h"
Int WINAPI MyMessageA (HWND hWnd, LPCSTR pText, LPCSTR pCaption,
UINT uType );
Int APIENTRY _ tWinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
Int nCmdShow)
{
KPEFile pe (hInstance );
Pe. SetImportAddress ("user32.dll", "MessageBoxA ",
(FARPROC) MyMessageA );
MessageBoxA (NULL, "Test", "SetImportAddress", MB_ OK );
}
Int WINAPI MyMessageA (HWND hWnd, LPCSTR pText, LPCSTR pCaption,
UINT uType)
{
WCHAR wText [MAX_PATH];
WCHAR wCaption [MAX_PATH];
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, pText,-1, wText, MAX_PATH );
Wcscat (wText, L "-intercepted ");
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, pCaption,-1, wCaption, MAX_PATH );
Wcscat (wCaption, L "-intercepted ");
Return MessageBoxW (hWnd, wText, wCaption, uType );
}
Next is KPEFile. h.
[Cpp] view plaincopy
# Pragma once
Class KPEFile
{
Const char * m_pModule;
PIMAGE_DOS_HEADER m_pDOSHeader;
PIMAGE_NT_HEADERS m_pNTHeader;
Public:
KPEFile (HMODULE hModule );
~ KPEFile (void );
Const char * RVA2Ptr (unsigned rva)
{
If (m_pModule! = NULL) & rva)
{
Return m_pModule + rva;
}
Else
{
Return NULL;
}
}
Const void * GetDirectory (int id );
PIMAGE_IMPORT_DESCRIPTOR GetImportDescriptor (LPCSTR pDllName );
Const unsigned * GetFunctionPtr (PIMAGE_IMPORT_DESCRIPTOR pImport,
LPCSTR pProcName );
FARPROC SetImportAddress (maid, maid );
};
And implementation code:
[Cpp]
# Include "StdAfx. h"
# Include "KPEFile. h"
KPEFile: KPEFile (HMODULE hModule)
{
M_pModule = (const char *) hModule;
If (IsBadReadPtr (m_pModule, sizeof (IMAGE_DOS_HEADER )))
{
M_pDOSHeader = NULL;
M_pNTHeader = NULL;
}
Else
{
M_pDOSHeader = (PIMAGE_DOS_HEADER) m_pModule;
If (IsBadReadPtr (RVA2Ptr (m_pDOSHeader-> e_lfanew), sizeof (IMAGE_NT_HEADERS )))
{
M_pNTHeader = NULL;
}
Else
{
M_pNTHeader = (PIMAGE_NT_HEADERS) RVA2Ptr (m_pDOSHeader-> e_lfanew );
}
}
}
KPEFile ::~ KPEFile (void)
{
}
Const void * KPEFile: GetDirectory (int id)
{
Return RVA2Ptr (m_pNTHeader-> OptionalHeader. DataDirectory [id]. VirtualAddress );
}
PIMAGE_IMPORT_DESCRIPTOR KPEFile: GetImportDescriptor (LPCSTR pDllName)
{
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR) GetDirectory (IMAGE_DIRECTORY_ENTRY_IMPORT );
If (pImport = NULL)
{
Return NULL;
}
While (pImport-> FirstThunk)
{
If (stricmp (pDllName, RVA2Ptr (pImport-> Name) = 0)
{
Return pImport;
}
PImport ++;
}
Return NULL;
}
Const unsigned * KPEFile: GetFunctionPtr (PIMAGE_IMPORT_DESCRIPTOR pImport, LPCSTR pProcName)
{
PIMAGE_THUNK_DATA pThunk;
PThunk = (PIMAGE_THUNK_DATA) RVA2Ptr (pImport-> OriginalFirstThunk );
For (int I = 0; pThunk-> u1.Function; I ++)
{
Bool match;
If (pThunk-> u1.Ordinal & 0x80000000)
{
Match = (pThunk-> u1.Ordinal & 0 xFFFF) = (DWORD) pProcName );
}
Else
{
Match = stricmp (pProcName, RVA2Ptr (unsigned) pThunk-> u1.AddressOfData) + 2) = 0;
}
If (match)
{
Return (unsigned *) RVA2Ptr (pImport-> FirstThunk) + I;
}
PThunk ++;
}
Return NULL;
}
FARPROC KPEFile: SetImportAddress (maid, maid, FARPROC pNewProc)
{
PIMAGE_IMPORT_DESCRIPTOR pImport = GetImportDescriptor (pDllName );
If (pImport)
{
Const unsigned * pfn = GetFunctionPtr (pImport, pProcName );
If (IsBadReadPtr (pfn, sizeof (DWORD )))
{
Return NULL;
}
FARPROC oldproc = (FARPROC) * pfn;
DWORD dwWritten;
WriteProcessMemory (GetCurrentProcess (), (void *) pfn,
& PNewProc, sizeof (DWORD), & dwWritten); // change the address pointed to by the symbol to achieve the hook purpose.
Return oldproc;
}
Else
{
Return NULL;
}
}
Author: eagleatustb