- UID
- 26814
注册时间2007-2-2
阅读权限20
最后登录1970-1-1
以武会友
TA的每日心情 | 开心 2020-11-19 11:04 |
---|
签到天数: 1 天 [LV.1]初来乍到
|
别怕,我可不是来真的找茬的。
一个关于“精装友情通讯录算法分析”版权的帖子,因我来这里看个究竟。其中特别注意了关于绿化大部分,甚感兴趣。但感觉大部分人在绿化时没有仔细分析软件汇编代码运行时前后各变量(包括寄存器)状态,以至于在做绿化工作时采用的方法不大合理。典型状况是:
1、添加区段,在新区段中添加新的代码。此方法虽说改动的代码并不很大,但也不是容易控制的事。
1、添加区段,引入新的API函数,实现读取软件运行目录。同样,也不是很多人能做的事。
其实,上述的方法均无必要,只要仔细分析代码的运行情况,完全可以在对应代码处直接修改。
这里所说的代码基于2005B11.20。
其一,重启验证时,其读取系统目录的代码为:- 005317AE 68 80000000 PUSH 80
- 005317B3 68 C8B25300 PUSH jzyq.0053B2C8
- 005317B8 E8 8B5BEDFF CALL <JMP.&kernel32.GetSystemDirectoryA>
复制代码 其内存地址0053B2C8就是存放返回的系统目录的。当我们运行到005317B8时,查看一下这里,你就会发现,那里已经为你做了初始化(清空)。此时,要留意运行005317B8这一命令前后各寄存器的状态,用以确定是否需要在修改代码后构造寄存器的值。如果某个寄存器的值发生改变,但后面并不是用它,则可不予理会。我们这里就是这种情况。
因此,这三行代码对我们来说完全可以不要只需要在内存0053B2C8处填充当前目录标识符即可。具体实现如下:- 005317AE MOV DWORD PTR DS:[35B2C8],5C2E
- 005317B8 NOP
- 005317B9 NOP
- 005317BA NOP
- 005317BB NOP
- 005317BC NOP
复制代码 很显然,不需要在其他位置添加代码来填充数据,我们这里还多余5个字节呢。
请注意,我这里填充的数据是DWORD的,而非WORD的,是为了保证末尾存在字符串结束符(学C的人应该知道啥意思)。
还请注意,一些字符串数据还存在长度标识,大约在字符串前面的4个字节处,如有必要,也得填上。
这种方法就是充分地利用软件的现有空间,只有在实在没法时,才去增加区段什么的。大多数情况下可在代码的最尾部处找到合适的空余地方来制作补丁的。
其二,及时验证时,其读取系统目录的代码为:- 00515285 |. 68 80000000 PUSH 80 ; /BufSize = 80 (128.)
- 0051528A |. 8D85 7BFFFFFF LEA EAX,DWORD PTR SS:[EBP-85] ; |
- 00515290 50 PUSH EAX
- 00515291 E8 B220EFFF CALL <JMP.&kernel32.GetSystemDirectoryA>
复制代码 虽说代码基本相同,但此时返回的系统目录并不是存放于内存,而是存放于堆栈。我们知道堆栈是动态申请的,故而在填充数据时不能采用直接地址法,需要采用寄存器间址。其余所需要注意的事项如前。具体代码如下:- 00515285 8D85 7BFFFFFF LEA EAX,DWORD PTR SS:[EBP-85]
- 0051528B C700 2E5C0000 MOV DWORD PTR DS:[EAX],5C2E
- 00515291 90 NOP
- 00515292 90 NOP
- 00515293 90 NOP
- 00515294 90 NOP
- 00515295 90 NOP
复制代码 可以看出,经过两次修改,共空余出10个字节的位置。不需要在其他位置来编写补丁了吧?
我所说的是,在对软件进行修改时,要注意分析构成模式,尤其是运行前后的数据关系,然后才确定补丁方案。尽量少做改动,以减少出错的机会。当然,前提是你对汇编要有较为客观的理解。
是为找茬(找茬结束)/:12 |
评分
-
查看全部评分
|