定位IAT表

定位IAT可根据读取exe的方法分为两类:pe装载器以装载的exe文件/通过内存映射方法读取exe文件。

    1.简单方法:
    直接通过以运行的exe文件来定位IAT

      #include <stdio.h>
    #include <windows.h>

void main()    
{
    HMODULE hMod = ::GetModuleHandle(NULL); //已运行的exe文件在内存中的基地址 为一般0x400000h
                                                                              //,也就是通常所说的IMAGEBASE


    IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hMod;
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)((BYTE*)hMod + pDosHeader->e_lfanew + 24); 

    IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)
        ((BYTE*)hMod + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress/*RVA值*/);

    while(pImportDesc->FirstThunk)
    {
        char* pszDllName = (char*)((BYTE*)hMod +pImportDesc->Name/*RVA值*/);
        printf("\n模块名称:%s \n", pszDllName);
    
        
        // 一个IMAGE_THUNK_DATA就是一个双字,它指定了一个导入函数
        IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)
            ((BYTE*)hMod + pImportDesc->OriginalFirstThunk);
        int n = 0;
        while(pThunk->u1.Function)
        {
            // 取得函数名称。hint/name表前两个字节是函数的序号,后4个字节是函数名称字符串的地址
            char* pszFunName = (char*)
                ((BYTE*)hMod + (DWORD)pThunk->u1.AddressOfData + 2);
            // 取得函数地址。IAT表就是一个DWORD类型的数组,每个成员记录一个函数的地址
            PDWORD lpAddr = (DWORD*)((BYTE*)hMod + pImportDesc->FirstThunk) + n;//RVA+ImageBase

            // 打印出函数名称和地址
            printf(" 从此模块导入的函数:%-25s,", pszFunName);
            printf("函数地址:%X \n", lpAddr);
            n++; pThunk++; //指向下一个FirstThunk结构
        }
        
        pImportDesc++;//下一个导入表descriptor,也就是在本进程载入的下一个dll文件中查找
    }
}


2.通过内存映射文件读取exe文件来到处IAT

先转载一下别人提供的代码,
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>

DWORD RVAToOffset(LPVOID lpBase,DWORD VirtualAddress)
{
    IMAGE_DOS_HEADER *dosHeader;
    IMAGE_NT_HEADERS *ntHeader;
    IMAGE_SECTION_HEADER *SectionHeader;
    int NumOfSections;
    dosHeader=(IMAGE_DOS_HEADER*)lpBase;
    ntHeader=(IMAGE_NT_HEADERS*)((BYTE*)lpBase+dosHeader->e_lfanew);
    NumOfSections=ntHeader->FileHeader.NumberOfSections;
    for (int i=0;i<NumOfSections;i++)
    {
        SectionHeader=(IMAGE_SECTION_HEADER*)((BYTE*)lpBase+dosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS))+i;
        if(VirtualAddress>SectionHeader->VirtualAddress&&VirtualAddress<SectionHeader->VirtualAddress+SectionHeader->SizeOfRawData)
        {
            DWORD AposRAV=VirtualAddress-SectionHeader->VirtualAddress;
            DWORD Offset=SectionHeader->PointerToRawData+AposRAV;
            return Offset;
        }
    }
    return 0;
}

int main(int argc, char* argv[])
{
    //打开文件
    HANDLE hFile=CreateFile(argv[1],GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile==INVALID_HANDLE_VALUE)
    {
        printf("CreateFile Failed\n");
        return 0;
    }
    //创建内存映射文件的内核对象
    HANDLE hMap=CreateFileMapping(hFile,NULL,PAGE_READONLY,NULL,NULL,NULL);
    if(hMap==INVALID_HANDLE_VALUE)
    {
        printf("CreateFileMapping Failed\n");
        return 0;
    }
    //把文件映射入内存
    LPVOID lpBase=MapViewOfFile(hMap,FILE_MAP_READ,0,0,0);
    if(lpBase==NULL)
    {
        printf("MapViewOfFile Failed\n");
        return 0;    
    }
    IMAGE_DOS_HEADER *dosHeader;
    IMAGE_NT_HEADERS *ntHeader;
    IMAGE_IMPORT_BY_NAME *ImportName;
    //lpBase由MapViewOfFile函数返回
    dosHeader=(IMAGE_DOS_HEADER*)lpBase;
    //检测是否是有效的PE文件
    if (dosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
    {
        printf("This is not a windows file\n");
        return 0;
    }
    //定位到PE header
    ntHeader=(IMAGE_NT_HEADERS*)((BYTE*)lpBase+dosHeader->e_lfanew);
    if(ntHeader->Signature!=IMAGE_NT_SIGNATURE)
    {
        printf("This is not a win32 file\n");
        return 0;
    }
    //定位到导入表
    IMAGE_IMPORT_DESCRIPTOR *ImportDec=(IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)lpBase+RVAToOffset(lpBase,ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
    while(ImportDec->FirstThunk)
    {
        //得到DLL文件名
        char *pDllName=(char*)((BYTE*)lpBase+RVAToOffset(lpBase,ImportDec->Name));
        printf("\nDLL文件名:%s\n",pDllName);
        //通过OriginalFirstThunk定位到PIMAGE_THUNK_DATA结构数组
        PIMAGE_THUNK_DATA pThunk=(PIMAGE_THUNK_DATA)((BYTE*)lpBase+RVAToOffset(lpBase,ImportDec->OriginalFirstThunk));
        while(pThunk->u1.Function)
        {
            //判断函数是用函数名导入的还是序号导入的
            if(pThunk->u1.Ordinal& IMAGE_ORDINAL_FLAG32)
            {
                //输出序号
                printf("从此DLL模块导出的函数的序号:%x\n",pThunk->u1.Ordinal&0xFFFF);
            }
            else
            {
                //得到IMAGE_IMPORT_BY_NAME结构中的函数名
                ImportName=(IMAGE_IMPORT_BY_NAME*)((BYTE*)lpBase+RVAToOffset(lpBase,(DWORD)pThunk->u1.AddressOfData));
                printf("从此DLL模块导出的函数的函数名:%s\n",ImportName->Name);
            }
            pThunk++;
        }
        ImportDec++;
    }
    UnmapViewOfFile(lpBase);
    CloseHandle(hMap);
    CloseHandle(hFile);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值