通行证│用户名: 密码: 验证码: 验证码,看不清楚?请点击刷新验证码 电信网通铁通移动   在线
文章搜索:
热门搜索:红客 黑鹰 红客技术 安全动画 红客培训
首页 文章 软件 动画 资源 励志 论坛 邮箱 会员 军事 科技 博客 爱心红客 最近更新 800g资源
 业内新闻 漏洞公告 病毒公告 电脑知识 网络知识 菜鸟入门 攻防教程 黑客攻防 安全编程 工具使用 综合安全 个人安全 安全相关 Q Q安全 原创精华 红客人物 站内事件
您现在的位置: 爱国者安全网 >> 文章类 >> 红客教程 >> 网络编程 >> 文章正文
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] 

  • 上一篇文章:
  • 下一篇文章:
  • 最近更新
    固顶文章 爱国者安全网2007年度优秀版主评选
    普通文章 瑞星公司01月11日发布 每日计算机病毒及木马播报
    普通文章 破解博彩神助(专注彩票) V2.8.01
    推荐文章 推荐:跨站脚本执行漏洞代码的六点思路
    普通文章 Windows系统下的远程堆栈溢出 实战篇
    普通文章 Windows系统下的远程堆栈溢出 原理篇
    普通文章 MsSQLServer是如何加密口令的
    普通文章 浅谈国内的渗透评估过程
    普通文章 Dvbbs8.1 0DAY(通杀Access和mssql版本)
    普通文章 微软:我们的代码比赛门铁克更安全
    热门文章
    普通文章REAL蛀虫利用播放器漏洞下载恶意程序
    普通文章李彦宏:中国要在互联网领域逐渐超越美国
    普通文章马云:阿里巴巴的成功是一个生态链的成功
    普通文章Ingres用户认证非授权访问漏洞
    普通文章TCPreen FD_SET()函数远程栈溢出漏洞
    普通文章Winace UUE文件解压堆溢出漏洞
    普通文章Pclxav木马猎手第一代特征码引擎源代码
    普通文章IE收藏夹管理小精灵算法分析
    普通文章Extra Drive Pro算法分析历程
    普通文章雨过天晴自我注册
    精彩专题