首页
社区
课程
招聘
[原创]让我们熟练掌握输入表,高手早已掌握
发表于: 2008-11-24 16:53 103950

[原创]让我们熟练掌握输入表,高手早已掌握

2008-11-24 16:53
103950
无论是在脱壳还是在PEDIY中,“输入表”这一概念总像阴魂一样缠绕在电脑屏幕前,令我等菜鸟彷徨叹息。遂于近日认真学习了一下PE格式,终于将此恶魔搞定。
  将实例PE.EXE载入LordPE中,依次点击“数据目录”,“输入表”旁的小点点,弹出以下窗口。我们勾选下面的"总是查看FirstThunk".

  

只见有两个dll:user32.dll和kernel32.dll以及各dll引出的诸函数.
可见每个dll有五个属性.
我们暂且只记住第一个dll的FirstThunk值如图:00002010,窗口下半部表明该值指向了名为DrawTextA的API函数.
我们用OD载入实例.下断 bpx DrawTextA ,F9运行被断下,如图:


到达程序对DrawTextA的调用处,F7跟进


双击一下,原来是直接跳转到[402010]的地方去了.
我们在数据窗口中d 402010看看402010到底是什么。

为方便查看,我们右键选择"长型","地址".



原来,402010地址里面的值是77D3C6CA那么jmp dwort ptr [402010]就是跳到77D3C6CA了.这个地址就是DrawTextA函数的入口地址。
现在我们大致知道输入表中这个First Thunk值的作用了,原来程序中对这些输入函数的调用都是jmp 402010 实现的。
为进一步理解,我们在16进制编辑器(如winhex)中查看输入表。



数据目录表第二项是 输入表的RVA:2050.将其转换成文件偏移650.该处就是输入表的开始。
蓝色部分是2个IID数组。每个数组有五个属性,对应着一个DLL。这就是lordpe中输入表五个属性的由来,可与lordpe对照:
OringinalFirstThunk TimeDateStamp  ForwarderChain  Name     FirstThunk
9C200000            00000000       00000000        CA210000 10200000
8C200000            00000000       00000000        0A220000 00200000
且看第一个IID。
他的OriginalFirstThunk 值为209C这是RVA值转化为文件偏移69C.便是图中淡黄色部分.
    FirstThunk值为2010转化为文件偏移610.便是图中深黄色部分.
明眼人已经看出来了,这两部分的数据是一模一样的。前者称为INT后者是IAT。
这部分数据也是指针,22210000 转换后是00002122再转化成文件偏移722.看772处是什么?
原来是DrawTextA这个字符串.再看2E210000转化文件偏移72e.看72e处是什么?原来是EndPaint字符串....后面再不一一看了:)------------请注意到并不是刚好指向函数的字符串前面还多了两个字节称为hint值 可为0,此处不详讨.
772,77e....是函数名的地址,这群地址组成的结构被称为IMAGE_IMPORT_BY_NAME.
为什么INT和IAT两个都指向这一结构呢?
系统在程序初始化时根据OrignalFirstThunk的值找到函数名,调用GetProcAddress函数(或类似功能的系统代码)且根据函数名取得函数的入口地址,
然后用函数入口地址取代FirstThunk指向的地址串的值IAT.

回顾本文开头时我们OD的一段跟踪,这段话便不难理解了.当我们在OD中查看00402010(RVA2010加上基址400000)时,里面已经是DrawTextA函数的入口地址。
因为系统已经用真正的函数入口地址取代IAT了。

为加强理解,我们针对以上理论做以下实验.

1.有时候程序不存在OrignalFirstThunk,我们将此程序的该值去掉以看效果.
将650处的9C20以0填充,保存文件.双击。。程序运行正常.可见,在没有OrignalFisrtThunk的情况下,系统直接以IAT中的的函数名得到函数入口地址并填充IAT。

2.OrignalFirstThunk值不变将INT以0填充以看效果.
按CTRL+Z数次恢复对文件的修改,把上图淡黄色部分用0填充,保存文件。双击.弹出程序运行错误窗口.
可见系统根据OrignalFirstThunk值只找到空的INT,程序便运行错误了.

3.依照理解IAT反正会被根据OrignalFirstThunk得到函数入口地址所取代,似乎IAT原始值没有存在的必要.
按CTRL+Z数次恢复对文件的修改.这次将610处即上图深黄色部分用0填充,保存文件.双击.弹出程序运行错误窗口.
按CTRL+Z数次恢复对文件的修改,程序又能运行了.由此可见即使OrignalFirst值正常,INT也正常,IAT的值仍然必不可少,由此可见IAT的重要性!

相信至此 读者已对输入表有了一定程度的认识,无论是ImportREC重建输入表还是手工重建输入表亦或是增加输入函数都已不再是难事.
PE.zip

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 8
支持
分享
最新回复 (139)
雪    币: 342
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
希望多发这样的帖,简单明了
2008-11-24 17:10
0
雪    币: 251
活跃值: (25)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
3
好文章,支持一下
2008-11-24 17:16
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
好文章,支持!学习了
2008-11-24 17:51
0
雪    币: 240
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
感谢大家支持,吾将继续努力!
2008-11-24 18:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好文章,支持!学习了
2008-11-24 18:49
0
雪    币: 347
活跃值: (25)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
7
很好,学习了,感谢楼主
2008-11-24 20:51
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
2008-11-25 05:52
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
//---------------------------------------------------------------------------
#include <windows.h>
#include <imagehlp.h>
#pragma argsused
//---------------------------------------------------------------------------
typedef void WINAPI (*SLEEPFUCTION)(DWORD dwMilliseconds);

SLEEPFUCTION P_Sleep;
void WINAPI MySleep(DWORD dwMilliseconds)
{
    if(dwMilliseconds<20)
        P_Sleep(1);
    else
        P_Sleep(dwMilliseconds/20);
}
//---------------------------------------------------------------------------
void WINAPI HookOneAPI(LPCTSTR ModuleName,LPCTSTR ApiName,PROC NewFuction,PROC &OldFuction)
{
    DWORD size;
    HMODULE hInstance = GetModuleHandle(NULL);
    PROC HookAPIAddr = GetProcAddress(GetModuleHandle(ModuleName),ApiName);
    OldFuction = HookAPIAddr;
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hInstance,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
    if(pImportDesc == NULL)
        return;
    for (;pImportDesc->Name;pImportDesc++)
    {
        LPSTR pszDllName = (LPSTR)((PBYTE)hInstance + pImportDesc->Name);
        if(lstrcmpiA(pszDllName,ModuleName) == 0)
            break;
    }
    if(pImportDesc->Name == NULL)
        return;
    PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hInstance + pImportDesc->FirstThunk);//IAT
    for(;pThunk->u1.Function;pThunk++)
    {
        PROC * ppfn= (PROC *)&pThunk->u1.Function;
        if (*ppfn == HookAPIAddr)
        {
            MEMORY_BASIC_INFORMATION mbi;
            ZeroMemory(&mbi, sizeof(MEMORY_BASIC_INFORMATION));
            VirtualQuery(ppfn,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
            VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect);
            *ppfn = *NewFuction;
            DWORD dwOldProtect;
            VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProtect);
            return;
        }
    }
}
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
    if(reason == DLL_PROCESS_ATTACH)
    {
        PROC SleepAddress = NULL;
        HookOneAPI("kernel32.dll","Sleep",(PROC)MySleep,(PROC)SleepAddress);
        P_Sleep = (SLEEPFUCTION)SleepAddress;
    }
    else if(reason == DLL_PROCESS_DETACH)
    {
    }
    return true;
}
2008-11-25 10:17
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
10
比较崇拜 知其然,知其所以然的大侠 。
很好......
支持.....
2008-11-25 11:18
0
雪    币: 563
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
好帖
2008-11-25 12:09
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SCH
12
说得很好。。学习了
2008-11-25 12:36
0
雪    币: 590
活跃值: (177)
能力值: ( LV9,RANK:680 )
在线值:
发帖
回帖
粉丝
13
不错,学习了
2008-11-25 13:14
0
雪    币: 894
活跃值: (4032)
能力值: ( LV5,RANK:69 )
在线值:
发帖
回帖
粉丝
14
还是看不明白     
2008-11-25 15:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
数据目录表第二项是 输入表的RVA:2050.将其转换成文件偏移650.该处就是输入表的开始。

怎么转的? 怎么转不了和你一样的/?
2008-11-25 15:39
0
雪    币: 240
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
16
哪里不明白 可以提出
2008-11-25 16:26
0
雪    币: 240
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
若用工具,可用LordPE的FLC位置计算器;
若自行计算,不妨用如下方法:
      查看区段,2000的文件偏移是600那么2050就是650了

不知道你是怎么计算的呢?
2008-11-25 16:30
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
人家叫我用OC  我郁闷``````````
2008-11-25 16:41
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
19
你这几个图太好了。

有这几个图,直观多了。我看MSDN上的technical article看了两小时,数据结构反复试验,也还是有些懵,看完楼主给的几个图,真是豁然开朗。

不错不错。谢谢了。
2008-11-25 20:42
0
雪    币: 6857
活跃值: (3353)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
在次学习输入表,这样就记主了,谢谢楼主。
2008-11-26 15:12
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
不错,浅出。
2008-11-26 19:46
0
雪    币: 201
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习了,谢谢!
2008-12-12 18:08
0
雪    币: 204
活跃值: (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
支持一下LZ的教程~~十分感谢
2008-12-12 18:59
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
很好,学习了,感谢楼主
2008-12-30 00:50
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
这个好 初学者需要的 支持哈
2008-12-30 16:41
0
游客
登录 | 注册 方可回帖
返回
//