| IAT表和导入表之间的关联 |
| 责任编辑:水土不服 更新日期:2007-10-28 |
|
|
|
虽然,我们可以看到OriginalFirstThunk和FirstThunk的RVA值是不一样的但是它们指向的内容是一致的。怎么说呢!我们姑且不管转换问题只表关系,类似C的方式如下: /------------------------------------------ Name->模块名 OriginalFirstThunk->函数名地址->函数名 /-------------------------------------------
我们可以把OriginalFirstThunk和FirstThunk当作是函数名和信息地址列表这样更准确点,不过,微软给我们一个很好的结构IMAGE_THUNK_DATA来让我们更直观方便的理解上面的内容,他没有直接声明而是见解而来,从中我看到了64位的结构,而这个时候的微软应该早就对64位做了准备了,我想在2000年以前微软就在为64位做准备吗?我是从文件来看的:
//-------------------------------------------------------------------------------------------
winnt.h里同样有: typedef IMAGE_THUNK_DATA32 IMAGE_THUNK_DATA; //这里声明了IMAGE_THUNK_DATA=IMAGE_THUNK_DATA32 typedef PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA; //PIMAGE_THUNK_DATA32=PIMAGE_THUNK_DATA
而IMAGE_THUNK_DATA32 被声明为如下格式, typedef struct _IMAGE_THUNK_DATA32 { union { PBYTE ForwarderString; PDWORD Function; DWORD Ordinal; PIMAGE_IMPORT_BY_NAME AddressOfData; } u1; } IMAGE_THUNK_DATA32; typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
而上面结构中的PIMAGE_IMPORT_BY_NAME被声明如下: typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; BYTE Name[1]; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; 同过上面的结构我们就可以肯定了我们的分析,函数名的格式都是HINT号+函数名的。
//-----------------------------------------------------------------------------------------------
因此我们最常见的导入表获取方法或代码都类似的处理如下:
//------------------------------------------------------------------------------------------------
//获取输入表相对虚拟地址: _importDesc=(PIMAGE_IMPORT_DESCRIPTOR)_ntHeader->OptionalHeader.DataDirector[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; if(_importDesc==NULL){return NULL;}
//如果是映像处理我们需要转换成虚拟地址,如果是读文件处理我们需要转换成物理偏移地址,这里就用映像法,用的最多的嘛! _importDesc=(PIMAGE_IMPORT_DESCRIPTOR)::ImageRvaToVa(_ntHeader,m_pData,(DWORD)_importDesc,NULL); //按照分析,我想我们获得地址正好就是00028000的虚拟地址00400000+0002A000=0042A000,(这里假设基地址为00400000) //而对模块信息的处理和我们之前分析的方法也是一样的 //获得相对虚拟地址 dwThunk=_importDesc->OriginalFirstThunk; //转换为虚拟地址 _pThunk=(PIMAGE_THUNK_DATA)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)_importDesc->OriginalFirstThunk,NULL); //我想看到这里的朋友都知道了上面结构指针为0002A3A4+00400000=0042A3A4的地方,下面又是按分析的来获取函数名 char *szFun=(PSTR)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)_pThunk->u1.AddressOfData->Name, 0);
//-------------------------------------------------------------------------------------------
我想目前看到这里的朋友都知道了些不知道的东西吧!故才有类似这样的C代码来获取函数名信息,很多朋友都知道拿过来用,但是根本不知道为什么要这样做!看完这里就应该知道了,总结关系如下: 00028000:PIMAGE_IMPORT_DESCRIPTOR 0002803C:PIMAGE_THUNK_DATA 000283A4:PIMAGE_IMPORT_BY_NAME
上面三个地址的关系我已经解释了,现在总结了一下,应该对导入表更清楚了点吧!也知道,那些高人们为什么要按上面说的流程来处理导入表吧!
对于HINT的由来我这里就不说明了。
二、IAT表: IAT表英文为ImportAddressTableAddress,为什么提英文呢,确实和它还有点关系,顺着翻译为导入地址表的地址,实际确实有点这样的意思哦! 03.jpg 和前面分析导入表一样,拿工具获得IAT表地址,为了方便研究我选择了同一文件,从PNHookApi对IAT表的分析来看好象和导入表差不多,实际我想对大家说的是IAT表没那么难,除了一个一唯地址列表,什么也没有,我们找到的地址为:0002A1F0,大小为000001B4,我们从前面那个区段图可以知道,IAT表依然在.idata区段,根据大小来看,我们用00028000还是没问题的:)。有朋友就说了,PNHookApi不是告诉我们它的物理地址是:000281F0吗?就没有人想想我是怎么把它给弄出的呢~ //----------------------------------------------------------------------------------------------
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
000281F0 A4 A3 02 00 8A A8 02 00 7A A8 02 00 68 A8 02 00 ぃ..姩..z?.h?. 00028200 56 A8 02 00 44 A8 02 00 34 A8 02 00 24 A8 02 00 V?.D?.4?.$?. 00028210 0E A8 02 00 00 A8 02 00 F0 A7 02 00 E4 A7 02 00 .?..?.皈..洄.. 00028220 D8 A7 02 00 CE A7 02 00 C2 A7 02 00 B2 A7 02 00 丕..围..搂..钵.. 00028230 A2 A7 02 00 92 A7 02 00 7A A7 02 00 6A A7 02 00 ⅶ..挧..z?.j?.
一堆虚拟地址,在winnt.h对IAT表的信息只有: #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table 我想大家都知道了,前面不是说过的吗?那我就不说了,拿WINHEX找到指定的地方: //-------------------------------------------------------------------------------------------------
实际微软再没做其它了,因为除了一堆相对虚拟地址以外IAT表没别的,真的很难把它看成一个表。这里就在说点大家又不知道的吧!别看一个地址,还真有点学问!
我们可以分三类: 1、API函数结构地址:买个关子后面解释 2、直接是API函数地址 3、HINT号
在说明上面三种区别方法之前我要建议一点汉化问题LoadPE在PE编辑对话框中把SizeOfImage翻译成文件大小是不对的,它的意思应该是镜像大小或者映像大小,就是说在程序运行后占用空间的大小,不是文件的大小。区分方法如下: //获取映像大小: DWORD dwsize=GetNTHeaders()->OptionalHeader.SizeOfImage;
if(*pdata!=NULL&&*pdata<=dwsize) { //为函数内部定向地址 } if(*pdata>dwsize&&*pdata<0x80000000) { //为外调用地址,可能是API函数,或加载的模块函数 } if(*pdata>=0x80000000) { //为函数的HINT号,也就是0x80000000+HINT号 }
根据上面的区分来划分IAT表中数据的类型。需要说明的是在第一类种我们会发现,它的每个地址都指向了一个PIMAGE_IMPORT_BY_NAME结构,也就是HINT号+函数名的格式,每个地址对应一个这样的结构,准确点讲IAT表的结构可以拿 PIMAGE_IMPORT_BY_NAME代替:)或 PIMAGE_THUNK_DATA代替
三、联系
我们研究了这么长时间总要有点结论!其它的不说了,我只说关键的,程序运行后IAT表的函数地址是根据导入表中函数名称确定的,而IAT表的函数地址可以直接被设定成某个API函数的地址,也可以按8标识的HINT号,就想MFC类的DLL一样,是按HINT号加载,不是按名称加载的,说到这里大家都明白IAT中的地址就是靠导入表中的函数和标号来确定函数地址的,应该知道ImportRec为什么要获取导入表修复程序了吧! 还有就是IAT表的地址是导入表中所有导入模块中FirstThunk值最小的值。
-EasyStudy For PhantomNet上一页 [1] [2] |
|
| 上一篇文章: 加密解密:小议ring 3虚拟机调试器 |
| 下一篇文章: 破解StarForce之一:StarForce分析总览篇 |
|
|
|
|