VMP下HOOK遇到的问题
关注了大神[@你与明日 ,ID:251657]的作品《DLL巧妙的绕过被VMP壳HOOK的ZwProtectVirtualMemory》一文,刚好在写一款从EXE导出数据的小工具,实际操作中碰到了闪退的问题,需要请大神们给予指志。PBYTE CHook::LoadFileContext(CString filename, CString apifun)
{
HANDLE hFile;
PBYTE hDllContext = NULL;
HMODULE ntdllAddr = NULL;
CString libname = filename;
UINT pos = filename.ReverseFind('\\');
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
MessageBox(0, ("CreateFileError"), ("error"), MB_OK);
return NULL;
}
if(pos != -1) {
libname = filename.Right(filename.GetLength()-pos-1);
}
ntdllAddr = LoadLibrary(libname);
PBYTE apiAddr = (PBYTE)GetProcAddress(ntdllAddr, apifun);
if (apiAddr == NULL || ntdllAddr == NULL) {
MessageBox(0, ("LoadLibrary|GetProcAddress,Error"), ("error"), MB_OK);
CloseHandle(hFile);
return NULL;
}
//把Ntdll读入进内存
DWORD dwHighSize = 0;
DWORD dwLowSize = GetFileSize(hFile, &dwHighSize);
BYTE* pBuff = new BYTE();
DWORDdwFileSize = 0;
ReadFile(hFile, pBuff, dwLowSize + dwHighSize, &dwFileSize, NULL);
//寻找所在区段
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuff;
PIMAGE_NT_HEADERS32 pNtHeader = (PIMAGE_NT_HEADERS32)(pDosHeader->e_lfanew + ((SIZE_T)pDosHeader));
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((SIZE_T)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS32));
DWORD Deviation = 0;
//ZwProtectVirtualMemory 地址 - ntdll地址 = RVA
SIZE_T Rva = (DWORD)apiAddr - (DWORD)ntdllAddr;
// 先通过RVA找到所在区段,再用RVA-当前区段RVA+当前区段文件偏移 = F0A
// 最后用F0A找到相对的opcode,复制到新内存执行再跳转
for (WORD i = 0; i < pNtHeader->FileHeader.NumberOfSections; ++i) {
// 通过RVA找到所在区段,再用RVA-当前区段RVA+文件偏移 = F0A
if (Rva >= pSectionHeader.VirtualAddress && Rva < pSectionHeader.VirtualAddress + pSectionHeader.SizeOfRawData) {
Deviation = Rva - pSectionHeader.VirtualAddress + pSectionHeader.PointerToRawData;
break;
}
}
if (Deviation == 0) {
MessageBoxA(0, "计算段内偏移错误", "error", MB_OK);
delete[] pBuff;
CloseHandle(hFile);
return NULL;
}
// 最后用段内偏移找到相对的opcode
// 申请一段堆空间执行被修改的汇编代码
hDllContext = (PBYTE)VirtualAlloc(0, 0x10, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (hDllContext == NULL) {
MessageBoxA(0, "VirtualAlloc Error", "error", MB_OK);
delete[] pBuff;
CloseHandle(hFile);
return NULL;
}
WriteLogger("%s <%s> file vs vmp Context: \n", libname, apifun);
for(int c=0; c<1; c++) {
WriteLogger("===%d===\r\nSRC:", c);
for(int i=0; i<16; i++) {
WriteLogger("%02X ", pBuff);
}
WriteLogger("\r\nVMP:");
for(int i=0; i<16; i++) {
WriteLogger("%02X ", apiAddr);
}
WriteLogger("\r\n");
}
memcpy(hDllContext, pBuff + Deviation, 5);//x32下VMP修改了前5字节,把文件内的原5字节拷贝过去
apiAddr += 5;
#if 0
hDllContext = 0x68;//push
memcpy(hDllContext + 6, &apiAddr, 4);//push的地址是ZwProtectVirtualMemory+5的地方
hDllContext = 0xc3;//使用retn过去
#else
// jmp ZwProtectVirtualMemory
hDllContext = 0xE9;
*((DWORD*)(hDllContext+6)) = (DWORD)apiAddr;
#endif
/*****************************************
0:b8 50 00 00 00 mov eax,0x50
5:e9 a5 30 52 77 jmp 0x775230af
************************************************/
delete[] pBuff;
CloseHandle(hFile);
WriteLogger("\n\n%08x, RESULT: \n", apiAddr);
for(int i=0; i<16; i++) {
WriteLogger("%02X ", hDllContext);
}
WriteLogger("\r\n\r\n");
return hDllContext;
}
SIZE_T CHook::ZwProtectVirtualMemory(
HANDLE ProcessHandle, // 进程句柄
PVOID* BaseAddress, // 地址的指针
SIZE_T* NumberOfBytesToProtect,// 修改的大小,函数调用后会改成成功修改的大小
ULONG NewAccessProtection, // 新的内存属性
PULONG OldAccessProtection) // 旧的内存属性
{
// ZwProtectVirtualMemory
/******************************************
0:b8 50 00 00 00 mov eax,0x50
5:ba 40 8a 30 4b mov edx,0x4b308a40
a:ff d2 call edx
c:c2 14 00 ret 0x14
f:90 nop
/******************************************
0:e9 6a cf b4 8c jmp 0x8cb4cf6f
5:ba 40 8a 53 77 mov edx,0x77538a40
a:ff d2 call edx
c:c2 14 00 ret 0x14
f:90 nop
************************************************/
if(hProtectVirtualMemory == NULL) {
hProtectVirtualMemory = (fZwProtectVirtualMemory)LoadFileContext("C:\\Windows\\System32\\ntdll.dll", "ZwProtectVirtualMemory");
if (hProtectVirtualMemory == NULL) {
MessageBox(0, ("LoadFileContext|ntdll.dll,Error"), ("error"), MB_OK);
return 0;
}
}
return hProtectVirtualMemory(
ProcessHandle,
BaseAddress,
NumberOfBytesToProtect,
NewAccessProtection,
OldAccessProtection
);
}BOOL CHook::ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesRead )
{
// ReadProcessMemory
/******************************************
0:8b ff mov edi,edi
2:55 push ebp
3:8b ec mov ebp,esp
5:5d pop ebp
6:ff 25 58 13 88 6b jmp DWORD PTR ds:0x6b881358
/******************************************
0:8b ff mov edi,edi
2:55 push ebp
3:8b ec mov ebp,esp
5:5d pop ebp
6:ff 25 58 13 72 75 jmp DWORD PTR ds:0x75721358
************************************************/
// if(hReadProcessMemory == NULL) {
// hReadProcessMemory = (fReadProcessMemory)LoadFileContext("C:\\Windows\\System32\\Kernel32.dll", "ReadProcessMemory");
// if (hReadProcessMemory == NULL) {
// MessageBox(0, ("LoadFileContext|Kernel32.dll,Error"), ("error"), MB_OK);
// return 0;
// }
// }
return ::ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead);
}
BOOL CHook::VMP_ReadData(DWORD address, DWORD* dwNews, UINT len)
{
BOOL ret = FALSE;
DWORD dwOldProtect = 0; //旧保护属性
// MyMessageBox();
// 去内存保护
WriteLogger("%s:%d modify memory.\n", __FUNCTION__, __LINE__);
this->ZwProtectVirtualMemory(INVALID_HANDLE_VALUE, (PVOID*)&address, (SIZE_T*)&len, PAGE_READWRITE, &dwOldProtect); //修改属性
// Hook 读指定长度的内存
WriteLogger("%s:%d ReadProcessMemory.\n", __FUNCTION__, __LINE__);
// if (ReadProcessMemory(INVALID_HANDLE_VALUE, (LPCVOID)address, dwNews, len, NULL) == 0) {
ret = this->ReadProcessMemory(INVALID_HANDLE_VALUE, (LPCVOID)address, dwNews, len, NULL);
// 写内存保护
WriteLogger("%s:%d restore memory.\n", __FUNCTION__, __LINE__);
this->ZwProtectVirtualMemory(INVALID_HANDLE_VALUE, (PVOID*)&address, (SIZE_T*)&len, dwOldProtect, &dwOldProtect);
if(ret) {
WriteLogger("VMP_ReadData Good, Result:%02X.\n", (BYTE)*dwNews);
} else {
WriteLogger("VMP_ReadData Faild, Cause:%s.\n", CTools::GetLastErrorString());
}
return ret;
}
注入VMP程序并执行后,VMP程序便闪退了。
代码执行后生成的记录为:CHook::VMP_ReadData:381 modify memory.
ntdll.dll <ZwProtectVirtualMemory> file vs vmp Context:
===0===
SRC:B8 50 00 00 00 BA 40 8A 30 4B FF D2 C2 14 00 90
VMP:E9 6A CF B6 8A BA 40 8A 53 77 FF D2 C2 14 00 90
775230a5, RESULT:
B8 50 00 00 00 E9 A5 30 52 77 00 00 00 00 00 00
B8 50 00 00 00 BA 40 8A 30 4B FF D2 C2 14 00 90
页:
[1]