Implement function piling in windows: intercept API methods, and pile up api
Implementation of function piling in windows: Blocking API methods recently started to study function piling methods because of work needs. Because I didn't want to make too many changes to the project, I gave up the idea of using Google gmock. But it also plagued me for another day. After fighting, we finally achieved some gains. Let's talk less and start to see how it works.
I. Basic preparation 1.How function calls work: Use the function name (function entry address) to access the function. If we can change the memory pointed to by the function's first address and redirect it to another function for execution, then we can implement function piling. 2.Method: Write A jmp xxx assembly language to the first address of the function (where xxx is the relative address to jump ). 3. if the original function is oldFun and the new function is newFun, the relative address offset of the function jump when piling is newFun-oldFun-(the size of this instruction we set ), the length of the absolute jump command is 5. Jmp xxx consists of 6 bytes.
Function:1.VirtualQuery
WINBASEAPISIZE_TWINAPIVirtualQuery (_ in_opt LPCVOID lpAddress, // The queried memory address _ out_bcount_part (dwLength, return) PMEMORY_BASIC_INFORMATION lpBuffer, // Save the buffer _ in SIZE_T dwLength of the memory region // information length );
This function is used to query the memory information of a memory area. VirtualQueryEx can also be used. 2. VirtualProtect
WINBASEAPIBOOLWINAPIVirtualProtect( __in LPVOID lpAddress, __in SIZE_T dwSize, __in DWORD flNewProtect, __out PDWORD lpflOldProtect );
This function is used to modify the protection mode of dwSize bytes in the specified memory area.
3. VirtualProtectEx
WINBASEAPIBOOLWINAPIVirtualProtectEx (_ in HANDLE hProcess, // Process HANDLE _ in LPVOID lpAddress, // The first address of the memory to be modified _ in SIZE_T dwSize, // modify the number of bytes _ in DWORD flNewProtect, // new protection attribute _ out PDWORD lpflOldProtect // old protection attribute );
VirtualProtectEx is used to change the protection mode of the specified process memory segment. By default, the memory space of the function cannot be written, which is why the function that modifies the protection attribute is used.
4. ReadProcessMemory
WINBASEAPIBOOLWINAPIReadProcessMemory( __in HANDLE hProcess, __in LPCVOID lpBaseAddress, __out_bcount_part(nSize, *lpNumberOfBytesRead) LPVOID lpBuffer, __in SIZE_T nSize, __out_opt SIZE_T * lpNumberOfBytesRead );
Read process memory. lpProcess is the first address, while lpBuffer is used to store read data. nSize is the number of bytes to be read.
5. WriteProcessMemory
WINBASEAPIBOOLWINAPIWriteProcessMemory( __in HANDLE hProcess, __in LPVOID lpBaseAddress, __in_bcount(nSize) LPCVOID lpBuffer, __in SIZE_T nSize, __out_opt SIZE_T * lpNumberOfBytesWritten );
This function is used to write the memory space of a process. It can inject data into the process memory, such as functions.
6. GetCurrentProcess
WINBASEAPI__outHANDLEWINAPIGetCurrentProcess( VOID );
This function returns a pseudo Process Handle 0 xffffffff, which can be used by any memory that requires a process handle.
2. Piling up APIs in the database
Solution 1:
Piling:
# Define FLATJMPCODE_LENGTH 5 // In x86 flat memory mode, absolute jump instruction length # define FLATJMPCMD_LENGTH 1 // mechanical code 0xe9 length # define FLATJMPCMD 0xe9 // The jmp Instruction of the corresponding Assembly // record the content of the piling function, to restore BYTE g_apiBackup [Response + Response]; BOOL setStub (LPVOID ApiFun, LPVOID HookFun) {BOOL IsSuccess = FALSE; DWORD TempProtectVar; // temporary protection attribute variable MEMORY_BASIC_INFORMATION MemInfo; // VirtualQuery (ApiFun, & MemInfo, sizeof (MEMORY_BASIC_INFORMATION); if (VirtualProtect (MemInfo. baseAddress, MemInfo. regionSize, PAGE_READWRITE, & MemInfo. protect) // modify the page to {memcpy (void *) g_apiBackup, (const void *) ApiFun, sizeof (g_apiBackup); * (BYTE *) ApiFun = FLATJMPCMD; // intercept the API and inject jmp xxx * (DWORD *) (BYTE *) ApiFun + FLATJMPCMD_LENGTH) = (DWORD) HookFun-(DWORD) ApiFun-FLATJMPCODE_LENGTH before the function code segment; virtualProtect (MemInfo. baseAddress, MemInfo. regionSize, MemInfo. protect, & TempProtectVar); // change back to the original attribute IsSuccess = TRUE;} return IsSuccess ;}
Clearance:
BOOL clearStub (LPVOID ApiFun) {BOOL IsSuccess = FALSE; DWORD TempProtectVar; // temporary protection attribute variable MEMORY_BASIC_INFORMATION MemInfo; // VirtualQuery (ApiFun, & MemInfo, sizeof (MEMORY_BASIC_INFORMATION); if (VirtualProtect (MemInfo. baseAddress, MemInfo. regionSize, PAGE_READWRITE, & MemInfo. protect) // modify the page to {memcpy (void *) ApiFun, (const void *) g_apiBackup, sizeof (g_apiBackup); // restore the code segment VirtualProtect (MemInfo. baseAddress, MemInfo. regionSize, MemInfo. protect, & TempProtectVar); // change back to the original attribute IsSuccess = TRUE;} return IsSuccess ;}
Solution 2:
Piling:
Bool setStub (LPVOID ApiFun, LPVOID HookFun) {HANDLE file_handler = GetCurrentProcess (); // obtain the pseudo Process handle dword oldProtect, TempProtectVar; char newCode [6]; // read the original memory information of the function int SIZE = FLATJMPCODE_LENGTH + FLATJMPCMD_LENGTH; // the SIZE of the memory to be modified if (! VirtualProtectEx (file_handler, ApiFun, SIZE, PAGE_READWRITE, & oldProtect) // modify the memory to read/write {return false;} if (! ReadProcessMemory (file_handler, ApiFun, newCode, SIZE, NULL) // READ memory {return false;} memcpy (void *) g_apiBackup, (const void *) newCode, sizeof (g_apiBackup); // Save the piling function information * (BYTE *) ApiFun = FLATJMPCMD; * (DWORD *) (BYTE *) ApiFun + FLATJMPCMD_LENGTH) = (DWORD) hookFun-(DWORD) ApiFun-FLATJMPCODE_LENGTH; // post function injection VirtualProtectEx (file_handler, ApiFun, SIZE, oldProtect, & TempProtectVar); // restore protection attributes}
Clearance:
Bool clearStub (LPVOID ApiFun) {BOOL temperature = FALSE; HANDLE file_handler = GetCurrentProcess (); DWORD oldProtect, TempProtectVar; int SIZE = bytes + temperature; if (VirtualProtectEx (file_handler, ApiFun, SIZE, PAGE_READWRITE, & oldProtect) {memcpy (void *) ApiFun, (const void *) g_apiBackup, sizeof (g_apiBackup )); // restore the piling Function Memory VirtualProtectEx (file_handler, ApiFun, SIZE, oldProtect, & TempProtectVar); IsSuccess = TRUE;} return IsSuccess ;}
Solution 3:
Piling:
bool setStub(LPVOID ApiFun,LPVOID HookFun){HANDLE file_handler = GetCurrentProcess();DWORD oldProtect,TempProtectVar;char newCode[6];int SIZE = FLATJMPCODE_LENGTH+FLATJMPCMD_LENGTH;if(!ReadProcessMemory(file_handler,ApiFun,newCode,SIZE,NULL)){return false;}memcpy((void*)g_apiBackup,(const void*)newCode, sizeof(g_apiBackup));*(BYTE*)newCode = FLATJMPCMD; *(DWORD*)((BYTE*)newCode + FLATJMPCMD_LENGTH) = (DWORD)HookFun - (DWORD)ApiFun - FLATJMPCODE_LENGTH; if(!WriteProcessMemory(file_handler,ApiFun,newCode,FLATJMPCODE_LENGTH,NULL)){return false;}}
It is also strange to say that this scheme does not change the read permission, but it is OK. The write method here is implemented using WriteProcessMemory, which is the same as directly using pointers. Same as above. However, if you use a pointer to write data directly, an error occurs.
So far, we have implemented the piling of functions, but there is a small problem. If this is the case, the piling of member functions in the class functions is a little problem and pointers cannot be converted, this is because the pointer of a class member function is not only a common pointer, but also contains other information. To solve this problem, we found two methods online:
1. Class normal function Member address conversion
LPVOID GetClassFnAddress (...) {LPVOID FnAddress; _ asm {lea eax, FnAddress mov edx, [ebp + 8] // ebp + 8 is the address of the first parameter, ebp + C is the second parameter address, and so on mov [eax], edx} return FnAddress ;}
2. address conversion of the class's virtual member function
LPVOID GetClassVirtualFnAddress (LPVOID pthis, int Index) // Add 2010.8.6 {LPVOID FnAddress; // pthis is the object pointer, and the index is the offset * (int *) in the virtual function table *) & FnAddress = * (int *) pthis; // lpvtable * (int *) & FnAddress = * (int *) FnAddress + Index); return FnAddress ;}
So far, the introduction of function piling has come to an end.
3. Convert common member functions
<pre name="code" class="cpp">template<class T>void * getAddr(T f){ long addr; memcpy(&addr,&f,sizeof(T)); return (int*)addr;}
Information: (great reference value) http://www.cnblogs.com/HeroZearin/articles/2772100.html
C ++ hook api intercepts system API functions
Message-based hooks and process hooks
Which of the following functions can be used to replace the porting of API functions in windows to linux? They are mainly atomic operation functions.
Use mutex lock in linux
# Include <pthread. h>
Int pthread_mutexattr_init (pthread_mutexattr_t * attr);/* initialization function */
Int pthread_mutexattr_destroy (pthread_mutexattr_t * attr);/* initialize the function */
Int pthread_mutex_lock (pthread_mutexattr_t * attr)/* Lock */
Int pthread_mutex_unlock (pthread_mutexattr_t * attr)/* unlock */
Use these functions to replace them.
For details, you can find the mutex lock.