导入表结构
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;
}