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;
}