printf打印byte_打印远程进程的INT表(IAT HOOK技术)

本文介绍了如何获取远程进程的INT表,通过EnumProcessModulesEx枚举远程进程模块,使用ReadProcessMemory读取必要的PE结构。文中指出,原始代码中ImageDirectoryEntryToData函数应用于本地进程而非远程进程,并提供了获取远程进程INT表的步骤和思路。
摘要由CSDN通过智能技术生成

      最近看到一篇文章介绍IAT HOOK实现,用ImageDirectoryEntryToData函数直接获取IID表,然后一顿操作。我当时对下面这个函数比较困惑。

pImportDescript = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hModuleToRead, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);

函数原型:

PVOID WINAPI ImageDirectoryEntryToData(_In_ PVOID Base,_In_ BOOLEAN MappedAsImage,_In_ USHORT DirectoryEntry,_Out_ PULONG Size);

hModuleToRead是要HOOK模块的基址,但是文章里并没有讲如何获取基址。大概有以下几种办法获取到模块基址:

1.hModuleToRead

2.定位远程进程的PEB

DWORD FindRemotePEB(HANDLE hProcess){      HMODULE hNTDLL = LoadLibraryA("ntdll");      if (!hNTDLL)            return 0;      FARPROC fpNtQueryInformationProcess = GetProcAddress      (            hNTDLL,            "NtQueryInformationProcess"      );      if (!fpNtQueryInformationProcess)            return 0;      NtQueryInformationProcess ntQueryInformationProcess =            (NtQueryInformationProcess)fpNtQueryInformationProcess;      PROCESS_BASIC_INFORMATION* pBasicInfo =            new PROCESS_BASIC_INFORMATION();      DWORD dwReturnLength = 0;      ntQueryInformationProcess      (            hProcess,            0,            pBasicInfo,            sizeof(PROCESS_BASIC_INFORMATION),            &dwReturnLength      );      return pBasicInfo->PebBaseAddress;}

3.EnumProcessModulesEx可以枚举出远程进程所有的模块信息。我下面用的就是这个方法。

       为了搞清楚我打算写个程序打印出远程进程的INT表,就不HOOK了。代码如下:

DWORD dwPID = 0;    HWND hd = ::FindWindow(NULL, L"Zenmap");    printf("正在打开窗口句柄\n");    ::GetWindowThreadProcessId(hd,&dwPID);    HANDLE hPID = ::OpenProcess(PROCESS_ALL_ACCESS, false, dwPID);    printf("dwPID=%d,hPID=%d\n", dwPID, hPID);    //开始打印所有模块基址    DWORD pro_base = NULL;    HMODULE hModule[100] = { 0 };    DWORD dwRet = 0;    int num = 0;    int bRet = EnumProcessModulesEx(hPID, (HMODULE *)(hModule), sizeof(hModule), &dwRet, NULL);    if (bRet == 0) {        printf("EnumProcessModules");}    // 总模块个数    num = dwRet / sizeof(HMODULE);    //printf("总模块个数: %d\n", num);     打印每一个模块加载基址    //char lpBaseName[100];    //for (int i = 0; i < num; i++) {    //GetModuleBaseNameA(hPID, hModule[i], lpBaseName, sizeof(lpBaseName));    //printf("%-2d %-25s基址: 0x%p\n", i, lpBaseName, hModule[i]);    //}    pro_base = (DWORD)hModule[0];//Zenmap.exe的基址    ULONG ulSize;    PIMAGE_IMPORT_DESCRIPTOR pImportDescript;    PIMAGE_THUNK_DATA pThunkData;    PIMAGE_IMPORT_BY_NAME pImportByName;    char *sMoldeName;    pImportDescript = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hModuleToRead, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);    while (pImportDescript->OriginalFirstThunk){        sMoldeName = (char *)((PBYTE)hModuleToRead + pImportDescript->Name);        printf("模块名为:%s\n", sMoldeName);        pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hModuleToRead + pImportDescript->OriginalFirstThunk);        while (pThunkData->u1.AddressOfData)        {            pImportByName = (PIMAGE_IMPORT_BY_NAME)((BYTE *)hModuleToRead + pThunkData->u1.AddressOfData);            printf("导入函数,HIT:%d,NAME:%s\n", pImportByName->Hint, pImportByName->Name);            pThunkData++;        }        pImportDescript++;}

大家可能一眼就看出问题来了,Zenmap.exe是远程进程,而ImageDirectoryEntryToData读取的是本地进程的IID。要如何拿到远程进程的INT(IAT)表信息呢,我没有找到现成的函数,只能用ReadProcessMemory一点点地把IID找出来。思路如下:

1.通过进程名找到窗口句柄

HWND hd = ::FindWindow(NULL, L"Zenmap");

2.通过窗口句柄找到进程id

::GetWindowThreadProcessId(hd,&dwPID);

3.通过进程id获得进程句柄

HANDLE hPID = ::OpenProcess(PROCESS_ALL_ACCESS, false, dwPID);

4.拿到各模块基址:

int bRet = EnumProcessModulesEx(hPID, (HMODULE *)(hModule), sizeof(hModule), &dwRet, NULL);

5.读取ImageDosHeader

::ReadProcessMemory(hPID,hModule[0],&ImageDosHeader,sizeof(IMAGE_DOS_HEADER),&dwRead);

6.读取ImageOptionalHeader

IMAGE_OPTIONAL_HEADER ImageOptionalHeader = {};    IMAGE_NT_HEADERS ImageNTHeader = {};    LPCVOID ImageOptionalHeader_addr = (BYTE *)hModule[0] + ImageDosHeader.e_lfanew + sizeof(ImageNTHeader.Signature) + sizeof(ImageNTHeader.FileHeader);    ::ReadProcessMemory(hPID, ImageOptionalHeader_addr, &ImageOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dwRead);

7.读取IID,ThunkData,OriginalFirstThunk等。

效果图:

3e3ea2480ad7e864b59b017f7992a25c.png

746a92b30fe5cdba7d5c8745eac4fa56.png

794320cf2169a83cbd09c9d05c764c35.png

完整代码:

{        DWORD dwPID = 0;    HWND hd = ::FindWindow(NULL, L"Zenmap");    printf("正在打开窗口句柄\n");    ::GetWindowThreadProcessId(hd,&dwPID);    HANDLE hPID = ::OpenProcess(PROCESS_ALL_ACCESS, false, dwPID);    printf("dwPID=%d,hPID=%d\n", dwPID, hPID);    //开始打印所有模块基址    DWORD pro_base = NULL;    HMODULE hModule[100] = { 0 };    DWORD dwRet = 0;    int num = 0;    int bRet = EnumProcessModulesEx(hPID, (HMODULE *)(hModule), sizeof(hModule), &dwRet, NULL);    if (bRet == 0) {        printf("EnumProcessModules");}    // 总模块个数    num = dwRet / sizeof(HMODULE);    //printf("总模块个数: %d\n", num);     打印每一个模块加载基址    //char lpBaseName[100];    //for (int i = 0; i < num; i++) {    //GetModuleBaseNameA(hPID, hModule[i], lpBaseName, sizeof(lpBaseName));    //printf("%-2d %-25s基址: 0x%p\n", i, lpBaseName, hModule[i]);    //}    pro_base = (DWORD)hModule[0];    IMAGE_DOS_HEADER ImageDosHeader = {};    DWORD dwRead = 0;    ::ReadProcessMemory(hPID,hModule[0],&ImageDosHeader,sizeof(IMAGE_DOS_HEADER),&dwRead);    printf("MZ:%p\n",ImageDosHeader.e_magic);    printf("DOS_HEADER_OFFSET:0x%p\n", ImageDosHeader.e_lfanew);    IMAGE_OPTIONAL_HEADER ImageOptionalHeader = {};    IMAGE_NT_HEADERS ImageNTHeader = {};    LPCVOID ImageOptionalHeader_addr = (BYTE *)hModule[0] + ImageDosHeader.e_lfanew + sizeof(ImageNTHeader.Signature) + sizeof(ImageNTHeader.FileHeader);    ::ReadProcessMemory(hPID, ImageOptionalHeader_addr, &ImageOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dwRead);    printf("IID:%p\n", ImageOptionalHeader.DataDirectory[1]);    IMAGE_IMPORT_DESCRIPTOR ImageImportDirectory = {};    PIMAGE_IMPORT_DESCRIPTOR ImageImportDirectory_addr = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hModule[0] + ImageOptionalHeader.DataDirectory[1].VirtualAddress);    ::ReadProcessMemory(hPID, ImageImportDirectory_addr,&ImageImportDirectory,sizeof(IMAGE_IMPORT_DESCRIPTOR),&dwRead);    PIMAGE_IMPORT_DESCRIPTOR pImportDescript;    PIMAGE_THUNK_DATA pThunkData_addr;    IMAGE_THUNK_DATA ThunkData;    PIMAGE_IMPORT_BY_NAME pImportByName_addr;    PIMAGE_IMPORT_BY_NAME ImportByName = {};    char sMoldeName[30] = {};    int a = 1;    while (ImageImportDirectory.FirstThunk){        LPCVOID sMoldeName_addr = (BYTE *)hModule[0] + ImageImportDirectory.Name;        ::ReadProcessMemory(hPID, sMoldeName_addr, sMoldeName, 29, &dwRead);        printf("导入模块%d,名为:%s\n",a++, sMoldeName);        pThunkData_addr = (PIMAGE_THUNK_DATA)((BYTE *)hModule[0] + ImageImportDirectory.OriginalFirstThunk);        ::ReadProcessMemory(hPID, pThunkData_addr, &ThunkData, sizeof(IMAGE_THUNK_DATA), &dwRead);        int i = 1;        while (ThunkData.u1.AddressOfData)        {            pImportByName_addr = (PIMAGE_IMPORT_BY_NAME)((BYTE *)hModule[0] + ThunkData.u1.AddressOfData);            void *p = malloc(15);            ::ReadProcessMemory(hPID, pImportByName_addr, p, 15, &dwRead);            //int HIT = ((int)*p);            ImportByName = (PIMAGE_IMPORT_BY_NAME)p;            printf("导入函数%d,HIT:%d,NAME:%s\n", i++, ImportByName->Hint,ImportByName->Name);            ::ReadProcessMemory(hPID, ++pThunkData_addr, &ThunkData, sizeof(IMAGE_THUNK_DATA), &dwRead);        }        ::ReadProcessMemory(hPID, ++ImageImportDirectory_addr, &ImageImportDirectory, sizeof(IMAGE_IMPORT_DESCRIPTOR), &dwRead);}}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值