怎样为程序打补丁(二)―――提高篇

2008-04-09 04:07:00来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

不知道各位把“基础篇”中的内容搞懂没有,我现在要带领大家提高啦,请各位用心听讲!

这次要教大家的是如何为程序添加功能。大家都知道,在可执行文件当中只有少量的空间和位置可以放置我们的补丁程序,这就注定了要实现比较复杂的功能是非常有局限的。想象一下,如果在人家程序中添加大量的汇编代码,且只能是汇编代码(不要问我为什么),并且调试运行。因为是在人家的运行环境中运行,必须维护大量的寄存器,地址空间,堆栈等等,那将是何其困难和痛苦的一件事情。汇编能作很多事情,但是也不是万能,要用汇编实现很多复杂的功能简直就是变态的行为。我为大家制作的FolkQQ补丁程序,其实汇编代码也就几十行,功能也很简单,就几十个字节。但这已经使我够痛苦的了,如果再多些,常人是吃不消的(调试运行这些代码很费力,如果一个地方错了至少得重敲,而且死机重起是常事)。

看到这里,可能有同学会问,像你的SE补丁系列,实现了IP地址到具体物理地址的转换,难道也是你用汇编写的吗(用汇编写这个会死人的)?当然不是,大家注意到有个IPsearcher.dll,这是一个动态链接库,看名字就知道这是关于IP地址转换成实际地址功能的东东。对,所有的转换工作就是在其中完成。他是我用VC写的,程序很简单,但是如果用汇编写那就复杂了。我想我自己都没有毅力把它用汇编写完,然后一个一个字节一个一个指令的敲到人家的程序中去。

呵呵,今天要教大家的就是如何在补丁程序中实现复杂的功能,具体问题在上面已经描述了,方法就是为程序附带一个动态链接库,把所有复杂的功能都留在DLL里面,让高级语言去作低级语言难于实现的功能,留出接口,供被打补丁的使用即可。

关于什么是DLL,我想不用我再多说了。简单的理解就是一个函数库,别人调用它,它具体完成,就这么简单。大家可以用软件看看我写的那个IPsearcher.dll(用tdump,或者VC中的工具depends.exe),可以看到其中只有一个函数接口,叫“_GetAddress”。给它一个IP地址的作为参数,它就能返回那个IP地址的实际地址。具体它的实现不在我们今天的讨论范围当中。

问题的关键就是如何在要被打补丁的程序中调用到这个动态链接库,让它为我们添加的补丁程序服务。

再往下看,就需要各位同学具备一定的Win32 PE格式的可执行文件的基础了(可以参考我以前写的“关于Win95下的可执行文件的加密研究”和“基础篇”)。在PE文件中,指定了该程序要使用到的所有动态链接库,还有要调用的哪个函数接口。这些信息都写在一个叫Import Table的数据结构当中。它描述了某个动态链接库的某个函数接口的调用地址,这个是为了使系统能够为该程序装入动态链接库并且重定位接口地址信息的。

可能大家有点晕菜了,没关系。让我用一个实例来解释一下Import Table。我们用tdump 打开一个PE格式的可执行文件:

C:\>tdump example.exe |more
Turbo Dump Version 5.0.16.12 Copyright (c) 1988, 2000 Inprise Corporation

........

Name RVA Size
------------------ -------- --------
Exports 00000000 00000000
Imports 0019CFA0 0000017C
Resources 00287000 00077F18

........

# Name VirtSize RVA PhysSize Phys off Flags
-- -------- -------- -------- -------- -------- --------
01 .text 00157744 00001000 00158000 00001000 60000020 [CER]
02 .rdata 0004723A 00159000 00048000 00159000 40000040 [IR]
03 .data 000E5C28 001A1000 0002A000 001A1000 C0000040 [IRW]

.......

Section: Import
ImportLookUpTblRVA:0019D938
Time Stamp: 00000000
Forwarder Chain: 00000000 (index of first forwarder reference)

Imports from WINMM.dll
(hint = 0071) mixerOpen
(hint = 0065) mixerClose
(hint = 006B) mixerGetLineControlsA

先说说第一个出现红字的地方,这是这个程序的Import Table的RVA地址(什么是RVA自己查)和长度;第二个红字是1A1000,它大于19CFA0,说明什么呢,Import Table的地址在.rdata段当中(好像知道了也没什么用,呵呵,写都写了,也不管这么多了);第三个红字的地方就是tdump解析出的Import Table具体的内容,比如有个叫WINMM.DLL的动态链接库,需要调用它的序列号是0ach的waveOutClose 函数。诸如此类的后面还有很多很多,通常一个程序需要调用至少是几个的动态链接库(kernel32.dll,user32.dll等等)。

那Import Table在文件中具体的样子是什么呢,同学们可以用UltraEdit打开偏移为19CFA0的地方看看。然后结合我给出的数据结构和tdump解析出的结果,具体分析和理解一下。

以下摘抄于“关于Win95下的可执行文件的加密研究”

.idata块以一个IMAGE_IMPORT_DESCRIPTOR数组开始。每一个被PE文件隐式连结进来的DLL都有一个IMAGE_IMPORT_DESCRIPTOR。在这个数组中,没有字段指出该结构数组的项数,但它的最后一个单元是NULL,可以由此计数算出该数组的项数。IMAGE_IMPORT_DESCRIPTOR的格式如下:
Dword Characteristics
该字段是一个指针数组的RVA偏移。其中每一个指针都指向一个IMAGE_IMPORT_BY_NAME结构
Dword TimeDateStamp
时间及日期标志,可以忽略。
Dword ForwarderChain
正向链结索引。我们的资料中没有函数正向链结的格式,也没有这一样的例子。
Dword Name
以NULL结尾的ASCII字符的RVA地址,该字符串包含输入的DLL名,比如“Kernel32.dll”或“USER32.DLL”。
PIMAGE_THUNK_DATA FirstThunk
该字段是在Image_thunk_data联合结构中的RVA偏移。大多数情况下,Image_thunk_data是指IMAGE_IMPORT_BY_NAME结构的指针。如果不是一个指针的话,那它就是该功能在DLL中的序号。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:编程应该考虑的程序界面和易用性的问题

下一篇:程序设计规范(转载)