写这个文章不是为了脱壳,而是为了加壳.脱壳靠工具(当然,高手都是diy),加壳就靠自己了(用工具加壳似乎没什么太多意思,毕竟是自己想搞明白).加壳基本原理在我上一篇帖子中写了很多.但具体操作真的完全是两码事.一个比较头疼的问题就是合并引入表.

因为stub有自己的引用表,原来的app也有一套.我们加壳后需要继续一定的合并,是app的引入库加入packed app中.否则这个加壳的程序是不稳定的,在某种情况下是崩溃的(当然,不考虑健壮性的不算).一般来说,就把dll的名字和第一个function的名字引入就可以了.

熟悉pe结构的人都知道iat,但光光iat是不够的.关于合并两个文件的引入表,目前世面上的两边书都有一定的介绍.飞天诚信的书写的商业目的太强,你看了就迷茫了,他上面写的使用memcpy就可以做到,我的天,如果真这么简单,我必须用obj文件加自己的编译器了.看雪老大的书没有具体的操作,但有加密iat部分,可以参考.

如果要真正合并所有的引入表,我们就要搞清楚到底怎么下手.

1. 合并的东西不是一个表,而是4个表,iat,iid,int, namestr,其中,iat和iid中间一般会有一定com信息,都是不能修改的,所以在rdata区,一共有5个部分,我们要修改4个,移动5个.

2. 所有的表都不是线形的,所以memcpy是必要的,但不是全部.

3. 我们要搞清楚每个部分的起始和大小.iat的信息是在datadic中有. iid也在datadic中有,用iid-iat就得到了com信息块的信息. int的起始位置需要用iid的大小算出来,int的大小可以认为和iat一样.那剩下的就是namestr的大小了. 呵呵,这个东西说起来容易,真到计算的时候可要小心,别搞错了.

4. 要得到原来app的iid中的信息,主要的就是dllname,和functionname.按functionname不是一个简单的str,而且一个imported_by_name结构,前面有一个word呢. 所以每增加一个dll引入,整个需要增加的尺寸是sizeof(IMAGE_THUNK_DATA)*4+strlen(strDllName)+strlen(strFunctionName)+sizeof(IMAGE_IMPORT_DESCRIPTOR)+sizeof(IMAGE_IMPORT_BY_NAME)+sizeof(BYTE)*4+sizeof(WORD) ,如果是绑定的就是sizeof(IMAGE_THUNK_DATA)*4+strlen(strDllName)+sizeof(BYTE)*2+sizeof(IMAGE_IMPORT_DESCRIPTOR).

5. 由于所有的逻辑结构都要破坏(没有很巧妙的办法,遍历iid更新会造成效率的降低和逻辑的昏乱),所以我们可以放弃所有逻辑关系,按照块区数据更新. 更新iat,先memcpy老的数据,再在最后加一个IMAGE_THUNK_DATA,指向functionname,如果是ordinal,就把原来的数据copy过来,最后补4个字节的0.对所有老的数据,都要加一个偏移,偏移的大小是sizeof(IMAGE_THUNK_DATA)*4+sizeof(IMAGE_IMPORT_DESCRIPTOR. 然后更新iat的size,否则loader就再这里找com信息了. 另外,delphi的iat数据都是0!

第二步,memcpy老的com信息过来.

第三步,memcopy老的iid,所有iid的int指针都要那个偏移,而iat不用动.name指针也要加上偏移.在最后0的iid中加上新的iid.新的iid中iat指向我们刚刚加入的iat,name指向dllname,而int指针指到int的最后.更新iid的起始位置和size

第四步,memcpy老的int过来,所有int的信息都加上偏移,最后补上一个IMAGE_THUNK_DATA指向functionname.

最后一步,memcpy老大namestr过来,再最后加上dllname,和imported_by_name指向的functionname.

6. 更新rdata section的数据.这里的数据需要对齐.

看了上面一大堆,大家都晕了吧,我刚刚开始也一样,看上去简单问题,如果都是指针操作,一会就晕了,所以我放弃了使用遍历iid的方法更新所有数据的思路,抛弃了所有逻辑上的关系,完全考对数据功能的理解更新所有的数据.由于所有的表都不是完全线形的,而我们都是要在数据间插入我们的新数据,所以没一步都要小心.最好把所有文件都map进来再操作.

不了解pe结构,是无从下手的,如果指向靠工具脱壳的人,也不需要看这个东西. 

写这个文章是希望能有更多人真正的理解,其实加壳就想给pe动手术.

////////////////////////////////////////////////////////////////////
按照看雪老大的要求,我上传一下代码,大家不要笑话我,写的很乱,对绑定的iat处理不是很仔细.

这个代码的功能就是把app的第一个dll合并到stub的表中.如果要合并所有的,遍历就是了.

相关源码下载:merge.zip