C++ 如何在结构中读取联合变量的ProcessMemory
基本上,我试图从一个正在运行的进程中迭代函数地址,这是我创建的一个虚拟程序,所以我要做的就是C++ 如何在结构中读取联合变量的ProcessMemory,c++,winapi,portable-executable,C++,Winapi,Portable Executable,基本上,我试图从一个正在运行的进程中迭代函数地址,这是我创建的一个虚拟程序,所以我要做的就是 IMAGE_THUNK_DATA first_thunk = { 0 }; if(!ReadProcessMemory(handle,process_base_address + import_desc.FirstThunk,&first_thunk,sizeof(first_thunk),0)) return false; std::cout << "Func
IMAGE_THUNK_DATA first_thunk = { 0 };
if(!ReadProcessMemory(handle,process_base_address + import_desc.FirstThunk,&first_thunk,sizeof(first_thunk),0))
return false;
std::cout << "Function address :" << std::hex << "0x" << first_thunk.u1.Function << '\n';
IMAGE\u THUNK\u DATA first\u THUNK={0};
if(!ReadProcessMemory(句柄、进程基地址+导入说明FirstThunk和first thunk、sizeof(first thunk)、0))
返回false;
std::cout你的意思是ReadProcessMemory
带有auto address=process\u base\u address+import\u desc。FirstThunk
适合你,但不适用于process\u base\u address+import\u desc。FirstThunk
直接使用(PBYTE)
转换
根据您的描述sizeof(IMAGE_THUNK_DATA)=8,我假设您使用的是x64版本
typedef struct _IMAGE_THUNK_DATA64 {
union {
ULONGLONG ForwarderString; // PBYTE
ULONGLONG Function; // PDWORD
ULONGLONG Ordinal;
ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA64;
typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64;
当IMAGE\u THUNK\u DATA
的最大值为1时,表示函数以序列号的形式导入,否则,函数以函数名的形式导入,它是一个RVA,指向IMAGE\u IMPORT\u BY\u name
结构。我们可以使用常量IMAGE_ORDINAL_FLAG
来测试最高位是否为1
以下是我的样本工作:
#include <Windows.h>
#include <iostream>
#include <psapi.h>
#pragma warning(disable : 4996)
using namespace std;
void main()
{
int i;
HMODULE hModule;
DWORD dwOffset, cbneeded;
SIZE_T dwRet;
DWORD dwPid = 8752; // PID of process to be hooked
TCHAR szModName[MAX_PATH];
TCHAR szHookModName[MAX_PATH] = { "user32.dll" };
TCHAR szFuncName[MAX_PATH] = { "MessageBoxA" };
IMAGE_DOS_HEADER DOSHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
IMAGE_DATA_DIRECTORY DataDirectory;
IMAGE_IMPORT_DESCRIPTOR ImportDesc;
IMAGE_THUNK_DATA OrigThunkData;
IMAGE_THUNK_DATA RealThunkData;
PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)malloc(255); //function name length;
MEMORY_BASIC_INFORMATION mbi;
LPVOID lpBaseAddress;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPid);
if (hProcess == NULL)
{
printf("Fail to open process!\n");
return;
}
if (!EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbneeded))
{
printf("Fail to enum process modules!\n");
return;
}
if (!ReadProcessMemory(hProcess, hModule, (void*)&DOSHeader, sizeof(IMAGE_DOS_HEADER), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
dwOffset = DOSHeader.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + dwOffset, (void*)&OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
DataDirectory = OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
i = 0;
do
{
dwOffset = DataDirectory.VirtualAddress + sizeof(IMAGE_IMPORT_DESCRIPTOR) * i;
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + dwOffset, (void*)&ImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + ImportDesc.Name, (void*)szModName, MAX_PATH, &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (stricmp(szModName, szHookModName) == 0)
break;
i++;
} while (ImportDesc.Name);
i = 0;
do
{
lpBaseAddress = (PBYTE)hModule + ImportDesc.OriginalFirstThunk + sizeof(IMAGE_THUNK_DATA) * i;
if (!ReadProcessMemory(hProcess, lpBaseAddress, (void*)&OrigThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + ImportDesc.FirstThunk + sizeof(IMAGE_THUNK_DATA) * i, (void*)&RealThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
std::cout << "Function address :" << std::hex << "0x" << RealThunkData.u1.Function << '\n';
lpBaseAddress = (PBYTE)hModule + ImportDesc.FirstThunk + sizeof(IMAGE_THUNK_DATA) * i;
if (!ReadProcessMemory(hProcess, lpBaseAddress, (void*)&RealThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
std::cout << "Function address :" << std::hex << "0x" << RealThunkData.u1.Function << '\n';
if ((OrigThunkData.u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + OrigThunkData.u1.AddressOfData, (void*)pImportByName, sizeof(WORD) + strlen(szFuncName) + 1, &dwRet))
{
if (GetLastError() == ERROR_PARTIAL_COPY)
{
i++;
continue;
}
else
{
printf("Fail to read memory in remote process!\n");
return;
}
}
if (pImportByName->Name[0] == '\0')
{
printf("Function not located!\n");
break;
}
if (strcmpi((char*)pImportByName->Name, szFuncName) == 0)
{
printf("Function: %s \n ", pImportByName->Name);
break;
}
}
i++;
} while (OrigThunkData.u1.Function);
free(pImportByName);
}
结果:
你为什么讨厌格式化?@MikeCAT我不知道,这让我很困惑,我正在试图解决它,因为我们说“现在你看到的一切都是正确的”-如果这是真的,你不会在这里问,是吗?我不确定我是否理解你,在ReadProcessMemory
中使用auto address
和process\u base\u address+import\u desc.FirstThunk
会得到不同的结果,对吗?你试过了吗:(PBYTE)处理基地址+导入描述FirstThunk
?@DrakeWu MSFT我想你误解了我是怎么做的处理基地址+导入描述FirstThunk
(无需从内存中读取此行)可以获取MessageBoxA
的地址,类型为IMAGE\u THUNK\u DATA
的结构不应该位于IMAGE\u IMPORT\u DESCRIPTOR
struct之后吗?
#include <windows.h>
#include <iostream>
int main()
{
printf("child\n");
VOID *p = (VOID*)MessageBoxA;
MessageBoxA(NULL,"TEST","TEST",0);
getchar();
return 0;
}