我又回来了,接上面的教程,前面两个代码图都是我瞎截的,当时游戏在维护,现在先补上内存段代码,
复制内容到剪贴板
代码:
114FA548 50 00 00 00 00 00 00 00 00 00 00 00 64 00 00 00 P...........d...
114FA558 64 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00 d.......P.......
114FA568 E8 03 00 00 64 00 00 00 64 00 00 00 00 00 00 00 ?..d...d.......
114FA578 01 00 00 00 02 00 00 00 02 01 00 01 00 00 00 00 ...........
114FA588 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
114FA598 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
114FA5A8 08 00 00 00 00 00 00 00 99 09 00 00 00 00 00 00 .......?......注意上表的第一行,就是标号为114FA548这行,114FA548是一个十六进制数,表示内存位置地址,在这个数之后的每两位数表示内存中的一个字节,每行16个字节,第一个50也是十六进制数,对应的十进制数是80,这就是兽人第一级的血量,在第二行还有一个50,这个50是最大血量,当前血量和最大血量的地址都有了,然后用鼠标选中114fa548这个地址开始的四个字节,下断点,下断点的方法看上面的贴子.然后回到游戏,打个怪,让血减少.这时候ollydbg就会暂停
并且出现下表
复制内容到剪贴板
代码:
00617AB0 /$ 55 PUSH EBP
00617AB1 |. 8BEC MOV EBP,ESP
00617AB3 |. 8B41 08 MOV EAX,DWORD PTR DS:[ECX+8]
00617AB6 |. 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
00617AB9 |. 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8]
00617ABC |. 890C90 MOV DWORD PTR DS:[EAX+EDX*4],ECX<----这一行会被高亮黄色标示
00617ABF |. B8 01000000 MOV EAX,1
00617AC4 |. 5D POP EBP
00617AC5 \. C2 0800 RETN 8大家注意看我标了注解的这一行,这是一条汇编命令,其功能是向eax+edx*4的这个内存地址开始的位置写入一个双字,写入的值存放在ecx内,eax,edx,ecx是寄存器,具体寄存器是什么意思,大家可以google一下,在我的教程里,你只要知道寄存器可以存放内存地址和数据就行,涉及到具体的命令时我会具体解释我们现在已经知道是这行命令更改了我们的血量,而这行命令的地址是不会变化的,因为他是指令而不是数据,是在客户端载入时分配的地址,因此是固定的,而咱们现在就看看这条指令是不是只更改血量.具体操作:用鼠标左击这一行选中,然后按F2,这个动作意思是我们在这里下断点,只要程序调用这条指令,ollydbg就会中断程序并给出中断时的各项数据,包括寄存器,内存,堆栈的值.下完断点后,我们发现哪怕不打怪,不少血的情况下也会中断,也就是说不减血的时候系统也会调用这条命令....这回完球了.不仅仅地址是动态的,连程序也是公共的,公交车----大家一起上,熟泡面=====人人可以泡.不要着急,既然有人写得出外挂,那么咱们也能写.一般来说遇到这种情况就要分析程序了,一步步的向上查,看ecx的值是从哪里来的,如果程序简单的话,也许1分钟搞定,要是复杂起来,加了一百层壳的话,那就有可能要查上一会了,这就是传说中的软件破解,而且是最低级的.在HP地址这个问题上,我们有更好的办法来解决,你多启动两次游戏或者多登录两次,多查两次不同的HP地址,会发现一个规律,不管地址怎么变,最后三位总是548,注意这依然是一个十六进制数,之所计算机用十六进制数,是用计算机的硬件有关,在电脑里,只有0和1两种状态,对应就是通路和断路两种情况,而十六进制的一个数字,正好对应四位二进制数,下面为了表达方法,十六进制数加后缀H,二进制数加后缀B,1H=0001B,AH=1010B,FH=1111B,这里只是简单介绍,因为下面将要进行二进制的运算动作,如果想详细了解,还请自己google.
现在继续刚才的命令讨论,因为这条命令是复用的,因此并不是他所生产的所有数据都是我们需要的,只有当[EAX+EDX*4]这个值的最后三位数是548时,我们才需要.为了读取最后三位数并且判断是否为548,我先要介绍两个二进制的动作命令,"与","异或",注意这"与"和"异或"与我们数学中的"加""减""乘""除"是一个概念,也是一个运算符号,具体的运算法则我这里简单介绍下,我们都知道十进制的加法法则,1+1=2,2+2=4,,而二进制中,只有0和1两个数字,所以无论是什么去运算,只可能产生三种算式:0+1,0+0,1+1,1+0,其中,0+1和1+0是相同的,而二进制的运算法则如下:
1与1=1
1与0=0
0与0=0
0与1=0,"与"运算法则简单归纳就是 有0出0,双1出1
1异或1=0
0异或0=0
1异或0=1
0异或1=1,"异或"法则的速记法是"同位出,异位出1"
这两种运算均没有进位和退位,按位运算,例:0001与1101=0001,0001异或1101=1100,分别位置对应,位置不够的话在高位补0,比如1100 0000 与 0000 1111,后面这个数其实就是1111,但是在二进制运算时,需要补0再回到我们刚才的地址讨论,我们现在手上得到的HP地址是114FA548,548H=0101 0100 1000B,注意我在二进制中间加了空格,是为了大家的观察方便,实际当中是没有空格的.我们需要把高位全部清0只剩下548这三位,并且不能倍数改变原来的数字,因为我们接下来还要进行比对,看是否为548,如果是的话记录这个地址上的数值.
我们先将这个数字装入ebp内,具体的命令是mov ebp,[eax+edx+4]
然后进行与操作,将EBP与00000FFF,具体命令是and ebp,00000FFF,这样我们就将EBP内的高位清0,只剩下原来的3位十六进制数,或者是12位b
然后再异或,将EBP异或00000548,命令:xor ebp,00000548,如果结果是0的话,那么代表这个地址正是我们所需要.如果非零,那么就不用管他了
接下来,就是要把上面这些命令插到中断的这条命令后面.
[
本帖最后由 ht37 于 2007-12-13 00:52 编辑 ]