PE导入表(输入表)学习笔记

导入表结构

typedef struct _IMAGE_IMPORT_DESCRIPTOR
{
    union
    {
        DWORD   Characteristics;           
        DWORD   OriginalFirstThunk;  //指向输入名称表(简称INT)的RVA,INI是一个IMAGE_THUNK_DATA32结构     
        };
    DWORD   TimeDateStamp;   //一个32位时间标志        
    DWORD   ForwarderChain;  //第一个被转向的API索引,一般为0。              
    DWORD   Name;//指向DLL名称的RVA地址(是个以00结尾的ASCII字符的地址)
    DWORD   FirstThunk;//包含指向输入地址表(IAI)的RVA,IAI是一个IMAGE_THUNK_DATA32结构              
} IMAGE_IMPORT_DESCRIPTOR;

typedef struct _IMAGE_THUNK_DATA32
{
    union {
        PBYTE  ForwarderString;//指向一个转向者字符串的RVA
        PDWORD Function;//被输入的函数内存地址
        DWORD Ordinal;//被输入的API的序数值 
        PIMAGE_IMPORT_BY_NAME  AddressOfData;//指向IMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA32; 

typedef struct _IMAGE_IMPORT_BY_NAME
{
    WORD    Hint;//指示本函数在其所驻留DLL输出表中的序号,该域被PE装载器用来在DLL的输出表里快速查询函数
    BYTE    Name[1];//含有输入函数的函数名,函数名是一个ASCII码字符串,以NULL结尾。
} IMAGE_IMPORT_BY_NAME;

这里写图片描述

注意点:

  • 输入表是以一个IMAGE_IMPORT_DESCRIPTOR(简称LLD)数组开始,一个接一个。每个被PE文件隐式地链接进来的DLL都有一个IID。结束判断是该数组的最后一个单元为NULL。

  • 对于IMAGE_THUNK_DATA的理解不要考虑复杂,整体判断它就是一个以DWORD数组开始,一个接一个,结束判断是出现0,所以在定义时可以直接用PDWORD。个体判断分2种情况,一是DWORD的第32位为1时,表示函数是以序号方式输入,这是低31位被看作一个函数序号(跟第32位的1没关系)。当最高位为0时,表示函数以字符串类型的函数方式输入,这时DWORD是一个RVA(才会用到IMAGE_IMPORT_BY_NAME结构),指向一个IMAGE_IMPORT_BY_NAME结构。

  • IMAGE_IMPORT_BY_NAME结构注意WORD Hint开始占2个字节,打印输入函数的函数名时一定要把IMAGE_THUNK_DATA中的值转化为FOA时移动2个字节,才能正确指向输入函数的函数名的首地址。

输入表打印中的部分核心代码(API形式)

//主要是对IMAGE_IMPORT_DESCRIPTOR(简称LLD)数组中其中任意一个有输入的函数的打印
VOID Enum_IMPORT_THUNK_DATA_listView(HWND hListDescriport,HWND hListThunkData,
                                     WPARAM wParam,LPARAM lParam ,HWND hDlg)
{
    SendMessage(hListThunkData,LVM_DELETEALLITEMS ,0,0);//清除ListControl控件里面的所有条目
    DWORD dwRowId,dwOriginalFirstThunk;
    DWORD index=0;
    TCHAR szOriginalFirstThunk[0x20];
    LV_ITEM lvI;

    //初始化
    memset(&lvI,0,sizeof(LV_ITEM));
    memset(szOriginalFirstThunk,0,0x20);
    //获取选择行
    dwRowId=SendMessage(hListDescriport,LVM_GETNEXTITEM,-1,LVNI_SELECTED);
    if (dwRowId==-1)
    {
        MessageBox(NULL,TEXT("请选择DLL"),TEXT("出错了"),MB_OK);
    }

    //获取OriginalFirstThunk
    lvI.iSubItem=1;//要获取的列
    lvI.pszText=szOriginalFirstThunk;//指定存储查询结果的缓冲区
    lvI.cchTextMax=0x20;//指定缓冲区大小
    SendMessage(hListDescriport,LVM_GETITEMTEXT,dwRowId,(DWORD)&lvI);

    sscanf(szOriginalFirstThunk,"%x",&dwOriginalFirstThunk);
    PDWORD pThunkData=(PDWORD)((DWORD)lpMemory +
        RVAToFOA(lpMemory, dwOriginalFirstThunk));

    char string[32];
    char string1[32];
    ZeroMemory(string,32);
    ZeroMemory(string1,32);

    while(*pThunkData)
    {
        ZeroMemory(&lvI,sizeof(lvI));
        lvI.iItem=index;
        lvI.mask=LVIF_TEXT;

        lvI.iSubItem=0;
        ZeroMemory(string,32);
        wsprintf(string, "%08X",*pThunkData); 
        lvI.pszText=TEXT(string);
        ListView_InsertItem(hListThunkData,&lvI);

        lvI.iSubItem=2;
        ZeroMemory(string,32);
        wsprintf(string, "%08X",FOAToRVA(lpMemory,(DWORD)pThunkData-(DWORD)lpMemory)); 
        lvI.pszText=TEXT(string);
        ListView_SetItem(hListThunkData,&lvI);

        if (*pThunkData>>31!=1)
        {
            lvI.iSubItem=1;
            ZeroMemory(string,32);
            wsprintf(string, "%08X", (DWORD)((DWORD)pThunkData-(DWORD)lpMemory)); 
            lvI.pszText=TEXT(string);
            ListView_SetItem(hListThunkData,&lvI);

            lvI.iSubItem=3;
            ZeroMemory(string,32);
            wsprintf(string, "%08X",*((PWORD)((DWORD)lpMemory +RVAToFOA(lpMemory, *pThunkData)))); 
            lvI.pszText=TEXT(string);
            ListView_SetItem(hListThunkData,&lvI);

            lvI.iSubItem=4;
            ZeroMemory(string,32);
            lvI.pszText=TEXT((char*)((DWORD)lpMemory +RVAToFOA(lpMemory, *pThunkData))+2);
            ListView_SetItem(hListThunkData,&lvI);
        } 
        else
        {
            lvI.iSubItem=3; 
            lvI.pszText=TEXT("-");
            ListView_SetItem(hListThunkData,&lvI);

            lvI.iSubItem=4;
            ZeroMemory(string,32);
            ZeroMemory(string1,32);
            wsprintf(string, "%03d", *pThunkData&0X7FFFFFFF); 
            strcpy(string1,"函数序号:");
            strcat(string1, string);
            lvI.pszText=TEXT(string1);
            ListView_SetItem(hListThunkData,&lvI);
        }
        index++;
        pThunkData++;
    }
}


//对于PIMAGE_IMPORT_DESCRIPTOR结构中数据的打印
BOOL Add_list_IMPORT_View_Items(HWND hListDescriport,HWND hDlg)
{
    LVITEM lvI;
    DWORD index=0;
    char string[32];
    ZeroMemory(string,32);
    ZeroMemory(&lvI,sizeof(lvI));
    lvI.mask=LVIF_TEXT;//

    PIMAGE_IMPORT_DESCRIPTOR pIMPORTDESCRIPTOR=NULL;
    pIMPORTDESCRIPTOR=(PIMAGE_IMPORT_DESCRIPTOR)  
        ((DWORD)lpMemory + RVAToFOA(lpMemory, pOptionHeader->DataDirectory[1].VirtualAddress));  

    if(!pIMPORTDESCRIPTOR)
    {
        MessageBox(hDlg,"can't get IMPORTDESCRIPTOR ","IMPORTD",MB_OK);
        return FALSE;
    }

    while (pIMPORTDESCRIPTOR->FirstThunk)
    {
        ZeroMemory(&lvI,sizeof(lvI));
        lvI.iItem=index;
        lvI.mask=LVIF_TEXT;

        lvI.iSubItem=0;
        lvI.pszText=TEXT((char*)((DWORD)lpMemory + RVAToFOA(lpMemory,pIMPORTDESCRIPTOR->Name)) );
        ListView_InsertItem(hListDescriport,&lvI);

        lvI.iSubItem=1;
        ZeroMemory(string,32);
        wsprintf(string, "%08X", pIMPORTDESCRIPTOR->OriginalFirstThunk); 
        lvI.pszText=TEXT(string);
        ListView_SetItem(hListDescriport,&lvI);

        lvI.iSubItem=2;
        ZeroMemory(string,32);
        wsprintf(string, "%08X", pIMPORTDESCRIPTOR->TimeDateStamp); 
        lvI.pszText=TEXT(string);
        ListView_SetItem(hListDescriport,&lvI);

        lvI.iSubItem=3;
        ZeroMemory(string,32);
        wsprintf(string, "%08X", pIMPORTDESCRIPTOR->ForwarderChain); 
        lvI.pszText=TEXT(string);
        ListView_SetItem(hListDescriport,&lvI);

        lvI.iSubItem=4;
        ZeroMemory(string,32);
        wsprintf(string, "%08X", pIMPORTDESCRIPTOR->Name); 
        lvI.pszText=TEXT(string);
        ListView_SetItem(hListDescriport,&lvI);

        lvI.iSubItem=5;
        ZeroMemory(string,32);
        wsprintf(string, "%08X", pIMPORTDESCRIPTOR->FirstThunk); 
        lvI.pszText=TEXT(string);
        ListView_SetItem(hListDescriport,&lvI);

        index++;
        pIMPORTDESCRIPTOR++;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值