I recently read "Windows graphic programming", which mentions some of the more practical file features of Windows systems. To sum up, I will post the code for reference.
For the original article, refer to P2. Here, only the code is written. The code can be directly run after my initial modification.
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.
// 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.
#pragma onceclass 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(LPCSTR pDllName, LPCSTR pProcName, FARPROC pNewProc);};
And implementation code:
# Include "stdafx. H "# include" kpefile. H "kpefile: kpefile (hmodule) {m_pmodule = (const char *) hmodule; If (isbadreadptr (m_pmodule, sizeof (image_dos_header) {m_pdosheader = NULL; m_pntheader = NULL;} else {m_pdosheader = (partition) m_pmodule; If (isbadreadptr (rva2ptr (m_pdosheader-> e_lfanew), sizeof (partition) {m_pntheader = NULL ;} else {m_pntheader = (pimage_nt_headers) rva2ptr (m_pdoshe Ader-> e_lfanew) ;}} kpefile ::~ Kpefile (void) {} const void * kpefile: getdirectory (int id) {return rva2ptr (m_pntheader-> optionalheader. datadirectory [ID]. virtualaddress);} using kpefile: getimportdescriptor (lpcstr pdllname) {pimage_import_descriptor pimport = (Inline) 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-> messages); For (INT I = 0; pthunk-> u1.function; I ++) {bool match; if (pthunk-> u1.ordinal & 0x80000000) {match = (pthunk-> u1.ordinal & 0 xFFFF) = (DWORD) pprocname);} else {mat Ch = stricmp (pprocname, rva2ptr (unsigned) pthunk-> u1.addressofdata) + 2) = 0;} If (MATCH) {return (unsigned *) rva2ptr (pimport-> firstthunk) + I;} pthunk ++;} return NULL;} farproc kpefile: setimportortaddress (lpcstr pdllname, lpcstr pprocname, farproc pnewproc) {pimage_import_descriptor pimport = getimportdescriptor (pdllname); If (pimport) {const unsigned * PFN = getfunctionptr (pimport, pprocname); If (isbadreadptr (P FN, 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 ;}}
There is not much time, and there is no one-to-one comment in the code.
In some Trojan and anti-Trojan technologies, this technology should be applicable.