自学CE,自己做CT表!(二)

来源:互联网 发布:二维旋转矩阵公式 编辑:程序博客网 时间:2024/04/29 02:02
 
友情提醒:如果你完全不懂汇编,估计看了这些会很不明白,建议你先去补充一些必要的汇编知识,这个教程是写给那些有一定的汇编基础的人看的,看不懂的话自己去看汇编教程,我不想再浪费我的时间来说一些别人早已经写得非常清楚详细的汇编基础。

我们这次要来对前面的代码注入做两个方面的改进:
一,利用代码注入来锁定数值。
二,让CHANGE VALUE按钮和CHANGE POINTER按钮两个都同时把数值的新地址写到我们的指定位置。

前面已经说过的一些做法我就不再重复了,我现在只重点解释一些新的内容。

一,利用代码注入来锁定数值:
今天我们的做法仍然和前一次一样,只不过在0045FF10这里我们多加了几行代码,所以其实重点就是在这新加上的几行代码上,要加上的代码如下,为了后面的叙述方便,我给这几行新加上的代码加上编号:

0045FF10 - 89 05 40 ff 45 00 mov [0045ff40], eax
0045ff16 - 89 10        mov [eax], edx
0045ff18 - 8b 45 fc        mov eax, [ebp-04]
----------------------------------------------------
0045ff1b - 50       push eax        (1)
0045ff1c - 8b 05 40 ff 45 00 mov eax, [0045ff40] (2)
0045ff22 - c7 00 88 13 00 00 mov [eax], 00001388 (3)
0045ff28 - 58       pop eax       (4)
----------------------------------------------------
0045ff29 - e9 a6 61 ff ff jmp 004560d4

其实除了新增加的四行代码,其他的四行和原来完全一样。就是转到这里来之后,我们先把地址放到我们指定的位置,然后恢复原始位置上被破坏的两行代码,接 着,在跳回去之前,我们又加了些代码,其实就是要往那个保存数值的地址上写入我们指定的值(1388是十六进制数,就是十进制的5000),(3)这一行 就是做这件事的,那么为什么还要(1),(2)和(4)呢?

这就涉及了汇编的规则了,我们要往一个地址写入数值,先要把这个地址放到寄存器,然后才能写入数值,这是汇编的规定。(其实我的汇编水平也不高,为什么会 有这样要求等等,自己看教程。顺便说一下,我写的这些代码和我说的这些,也不一定是最正规的甚至不一定是正确的,一切以汇编教程和书本上的为准)。因此, 才需要(2)这一步先把我们已经保存在0045FF40上的这个数值的地址先调入到EAX寄存器中。

那么,又为什么还要用到(1)和(4)这两行呢?因为我们在(2)和(3)的时候借用了EAX这个寄存器,由于这个寄存器原来里面有数值(天知道原来的数 值是多少,还有原来的数值对程序来说有多重要!),所以我们要先把数值保留起来,然后我们开始使用EAX寄存器,使用完了之后,我们再把原来的数值放回到 EAX,这样才不会破坏程序的正常运行,有借有还,再借不难嘛,嘿嘿。PUSH和POP这两个指令就是用来保存和恢复寄存器的数值的,PUSH的作用是把 指定寄存器的值压到堆栈中,而POP则相反,是从堆栈中把数值恢复到指定的寄存器。有关PUSH和POP的用法请自行参看相关汇编教程。

所以,这一次我们这么修改,就是由原始位置(004560CF)处跳到我们的代码(0045FF10)处执行,先把放有数值地址的寄存器放到我们指定的位 置上,然后恢复被我们破坏的两条指令,再然后(1)保存EAX的值,再(2)用EAX来调入我们保存的数值地址,然后我们(3)往数值地址写入我们指定的 数字,然后(4)恢复EAX的值,最后是跳回原处执行后续的指令。

经过我们这么修改之后,现在按CHANGE VALUE按钮之后,除了0045FF40这里会保存数值的地址之外,TUT上的数字还会被我们改成5000,其实也就是数值被我们锁定在5000了。

上面只是用这个例子来说明代码注入实际上能做到的比我们想象的要多,只要你有足够的汇编水平,并且有一块足够大的内存空间给你放你的代码,事实上代码注入 几乎可以做任何你想象得到的事。比如说大家熟悉的珊瑚虫版的QQ,在早期的版本其实就是用代码注入的方法直接把查IP的代码注入到QQ主程序里面的,想不 到吧?

其实我都说了,上面这个只是扩展我们上次实例教程中所注入的代码的功能的一个例子,要锁定数值,可以做得更简单些,如果你看得懂汇编代码,知道哪一句是做什么的,就很容易用更简单的方法来锁定数值,其实在004560CF这一句:
004560CF mov [eax], edx
EDX里面就是你按CHANGE VALUE按钮之后产生的新数值,这一句就是把新数值放到数值的地址里。那么如果把这一句修改成mov [eax], 00001388,而不是把EDX放进去,这样不就行了?不过因为这个新代码比原来的代码长,直接在原始位置上修改会破坏后面的指令,所以不能直接在原始 位置上修改,要在跳转到0045FF10之后再那里修改。如果是原来的指令比我们要修改的指令长,那么还可以直接在原始位置修改,连代码注入都不用!

所以,在0045ff10那里如果你改成这样:
0045ff10 - c7 00 88 13 00 00 mov [eax], 00001388
0045ff16 - 8b 45 fc        mov eax, [ebp-04]
0045ff19 - e9 b6 61 ff ff jmp 004560d4
这样就是不用做任何外挂,直接在游戏中修改成无敌了!当然,别忘了004560CF仍然要改成JMP 0045FF10。

第一行是把原来按了CHANGE VALUE按钮之后写入新产生的数值,修改成写入固定的5000(1388),第二句仍然是恢复原始位置上被破坏的这条指令,第三行就是跳回去,就这样, 简单吧?不过这个已经是超出这个教程的本意了,我们的重点是在研究代码注入,而不是在研究游戏修改,呵呵。

再说一遍,汇编教程里面能查到的内容,别再问我,自己去看,我不会再回复汇编教程里面已经说得清楚的东西。

二,让CHANGE VALUE按钮和CHANGE POINTER按钮两个都同时把数值的新地址写到我们的指定位置。

现在我们再接着前面的续一来看看我们的第二个目标。

在我们最开始的代码注入实例中,我们利用了CHANGE VALUE这个按钮的执行代码注入了我们自己的代码,不过这样做不是很完美,因为只有在数值改变时我们才能得到新地址,而在我们按了CHANGE POINTER时,真正地址有变化的时候我们却没有及时得到新的地址,所以这次我们就来完善一下,让程序在我们按了CHANGE VALUE和CHANGE POINTER两个按钮的任何一个时,都把新的地址写到我们指定的位置。

如果你看完这个实例教程的前两篇,那么我想你对代码注入的原理和具体操作应该不陌生了(如果你还没真正弄清楚,那么先把前两篇多看几遍直到弄懂为止!)。这次的做法其实在代码注入方面没什么特别的新内容,倒是在寻找指令方面要学些新的东西。

为了让大家不致混淆,我把后面说到的几个概念再明确一下:
HP:指TUT上面显示的那个数字,为了表达方便,我们就暂且称它为HP。
HP的地址:指目前存放HP的内存地址,TUT每次运行时这个地址不同,并且按了CHANGE POINTER时它也会变化。
指针:存放“HP的地址”的一个内存地址,它在固定的位置上(以TUT2.4为例,这个地址是00BD4E64)。

我们先回顾一下我们是怎样找到指针的,就是先根据HP的变化找到HP的地址,然后看哪一条指令往这个地址里面写东西(写的就是HP),从而找到那条指令, 再根据这条指令我们知道,当程序执行到这一条指令的时候,EAX里面放的就是HP的地址,于是我们用代码注入的方法把HP的地址(也就是EAX的值)放到 0045FF40这个位置。总结起来,我们是“根据写入HP地址的指令找到指针”。

而我们这次要找的东西不一样,我们先来看看CHANGE VALUE和CHANGE POINTER两个按钮实质上的不同。CHANGE VALUE这个按钮做的事情是:把HP的值,写到HP的地址。而CHANGE POINTER要做的却不一样,它做的事情是:把变化了的HP地址,写到指针这个位置。

如果你想不明白这两个按钮之间的差别,那么趁现在先弄清楚,在没完全弄清楚之前,看下去只会越看越糊涂。

那么,如果你都弄明白了,我们就接着来开始我们这次的行动吧。

首先我们根据HP的值来找到HP的地址,再根据HP的地址来找到指针,我假设你都清楚具体该怎么做。找到指针后,我们直接把指针添加到地址列表上(地址为 00BD4E64),我们需要地址列表上有这一项,另外我们还要以指针方式把指针添加到地址列表上(勾选指针方式,地址00BD4E64,偏移量0),这 一项是最后用来检验我们的劳动成果的。

接着,我们在地址列表上刚才直接添加的指针这一项点右键,仍然是Find out what is writes this address,然后我们回到TUT,点一下CHANGE POINTER,这个时候CE应该能找到一条指令,没错了就是它在改写指针。(前面按CHANGE VALUE找指针的时候找到的那一行指令是在改写HP的地址的内容----即HP的数值,这次按CHANGE POINTER的时候找到的这条指令是在改写指针的内容----即HP的地址。想清楚两者的区别)。

我们先把找到的指令记下来,然后我们在MEMORY VIEW窗口上半部点右键->GO TO ADDRESS,输入这条指令所在的位置,我这里这条指令是在004561A9。然后把这一条指令和它后面的几条指令包括指令前面的地址记下来(主要是要 看清楚一会跳回来时跳到什么位置,也就是说它的下一条指令在什么地址,在这里只要记住这条指令本身和它的下一条指令就行了)。我这里的情况如下:

004561A9 - 89 82 10 03 00 00        mov [edx+00000310], eax
004561AF - b8 e8 03 00 00        mov eax, 000003e8

事实上,上面第一行中EAX就是TUT生成的新的HP地址,这一行就是把这个新生成的HP地址放到指针里面去。刚才在CE找到这条指令的时候,如果你有去 看EXTRA INFO的话,你会看到EDX=00BD4B54,如果你用WINDOWS的计算器以十六进制算一下BD4B54+310,你就不难发现结果就是 BD4E64,就是我上面说的指针的地址00BD4E64。从这里也可以很清楚地看到,以前大家一直不明白的方括号里面的算式的问题。

那么,我们现在找到了改写指针的这条指令,并且我们知道在这条指令执行的时候,EAX里面就是新的HP地址。那么我们要做的就是在这里也做一次代码注入, 当然了这次不是跳到0045FF10那里,因为那里已经放了CHANGE VALUE这个按钮的注入代码了(我假设你已经先按第一篇的做法先做好了CHANGE VALUE的代码注入了),所以我们要跟在它后面,刚巧前面注入的代码是到0045FF1F,所以我们的这次新的代码就从0045FF20开始。下面就是 0045FF10这里,两个按钮的两次代码注入之后的情况:

0045ff10 - 89 05 40 ff 45 00    - mov [0045ff40],eax
0045ff16 - 89 10              - mov [eax],edx
0045ff18 - 8b 45 fc              - mov eax,[ebp-04]
0045ff1b - e9 b4 61 ff ff    - jmp 004560d4
---------------------------------------------------------------
0045ff20 - 89 05 40 ff 45 00    - mov [0045ff40],eax
0045ff26 - 89 82 10 03 00 00        - mov [edx+00000310],eax
0045ff2c - e9 7e 62 ff ff    - jmp 004561af

上面四行和本教程第一篇完全一样,我就不再重复了,而下面三行就是我们为CHANGE POINTER按钮所做的代码注入,其实更简单,因为我们知道在004561A9这个地方,EAX里面放的就是新的HP地址,所以跳0045FF20的之 后,我们把EAX直接放到0045FF40,接着仍然是恢复被JMP破坏的指令,跟着就是跳回原始位置后面的一条指令继续执行就行了。


接着
至于原始位置,也就是004561A9那里,修改之后的情况是这样的:
004561A9 - e9 72 9d 00 00        - jmp 0045ff20
004561AE - 90          - nop
004561AF - b8 e8 03 00 00        - mov eax, 000003e8

这次有两点不同:
一,因为被我们破坏的指令这次是六字节,而我们的JMP是五字节,所以这次只破坏了一条指令,所以恢复时也只是恢复一条指令。
二,也因为这次被破坏的指令是六字节,而JMP是五字节,所以这次CE问你指令长度不一致,是否要补NOP的时候,记得一定要选YES,让CE帮你补上NOP。

现在,0045FF10这里两个注入的代码改好了,004560CF和004561A9这两处的JMP也改好了,我们的工作也完成了,当然最后别忘了检验 一下是否正确。如果你前面没有把指针以指针方式添加在地址列表里,那么现在把指针以指针方式添加到地址列表上,另外MEMORY VIEW窗口下半部也用右键->GO TO ADDRESS并输入0045FF40让它显示我们保存HP地址的指针位置,然后调整CE主窗口,MEMORY VIEW和TUT的位置,让CE主窗口的地址列表,MEMORY VIEW的下半部0045FF40和TUT的窗口都能看得到,分别点击CHANGE VALUE和CHANGE POINTER,你可以在这三个位置看到,地址列表中以指针方式添加的那一项,最后面的VALUE那一栏显示的就是HP的数值,而P->后面显示的 地址和0045FF40显示的一样,当点击CHANGE POINTER之后,0045FF40和地址列表上P->后面的地址同时变化,并且内容完全一致,这样我们的工作就算是圆满完成了。

还有,我这里是用CE4.4带的TUT2.4做的,CE5.2带的TUT是2.5,有可能一些地址例如指针等,会稍有不同,如果你是用TUT2.5,请根 据具体情况调整一下具体的地址。另外CE5.2的EXTRA INFO显示寄存器的情况和CE4.4有点不同,也请大家注意。

希望这三篇教程一方面能让大家理解代码注入的过程和原理,以及简单的应用,同时也可以让大家对DMA有个认识,看看上面关于两个按钮之间的不同,多少应该对理解DMA有一定的帮助。

怎么样?大家都看懂了吗?

看不懂?基础不好不是你的错,不去打好基础就是你的错了,呵呵。再说一遍,去看汇编教程。这个实例教程如果有些地方我说得不清楚甚至是说错了的,欢迎讨论,但如果是你基础没打好看不懂的,那还是请你自己解决吧:)

(完)

PS:这次的教程仍然是没有任何图片。电影虽然很精彩,但你仍然得学会看没有插图的小说。告诉你们,我的知识绝大多数是看那些没有图片的文字学来的,呵 呵。所以我也因此对文字比较有感情,并且学会了用文字来表达思想和传递知识。如果你一定要图片才能看得懂,那恕我直言,你得多培养一下文字理解能力和想象 力了。