前言:
看了很多有关植物大战僵尸的教程,比较少看到用汇编来找基址的,大多是用"找出是什么访问了这个地址"来找的
但是这种方法存在弊端,一是可能存在多个指针,二是不一定搜的到
今天给大家带来CE反汇编硬追pvz的僵尸数组头部教程
适合学习人群:比萌新稍微强一丝丝足矣
事前准备
本人使用的工具:CE7.2汉化版(不用在意版本问题) PS:OD什么的不需要啦
本人使用的游戏:植物大战僵尸原版的汉化版(非年度版) 就是阳光基址是006A9EC0+768+5560的那个
教程内容
找到僵尸血量
首先瞄准一只普通僵尸,搜索得到它的血量
PS:普通僵尸的初始血量是270 豌豆射手的攻击是20 (模糊搜索可以找到这些数据)
所以我们先搜270
然后命中之后再搜250,过滤得到
很轻松地得到这一只僵尸的血量,先把僵尸的血量改成9999(接下来要让它被狠狠地揍,我们好断点追踪),然后右键"找出是什么改写了这个地址"
接下来点击"显示反汇编程序"即可开启我们的反汇编之旅
开始反汇编追踪之旅
反汇编窗口如上所示,贴上代码:
PlantsVsZombies.exe+131319 - 89 BD C8000000 - mov [ebp+000000C8],edi
从这句我们可以得到ebp+c8这个地址里存的值就是这只僵尸的血量
于是问题转化为ebp从何而来?
我们在这里F5下个断点 顺便给这里加上备注
然后回到游戏,等待僵尸被攻击后,断下
这里我们可以看到EBP=14EE1914 ,暂且记下
大家都知道代码是从上往下执行的,于是我们以这行代码为起点,向上查找是什么给EBP赋值的
再贴代码:
PlantsVsZombies.exe+1312D0 - 83 EC 08 - sub esp,08 { 8 }
PlantsVsZombies.exe+1312D3 - 8B 44 24 14 - mov eax,[esp+14]
PlantsVsZombies.exe+1312D7 - 53 - push ebx {这里是函数头部}
PlantsVsZombies.exe+1312D8 - 55 - push ebp
PlantsVsZombies.exe+1312D9 - 8B 6C 24 14 - mov ebp,[esp+14] {ebp在这里被赋值}
PlantsVsZombies.exe+1312DD - 56 - push esi
PlantsVsZombies.exe+1312DE - 8B F0 - mov esi,eax
PlantsVsZombies.exe+1312E0 - 83 E6 08 - and esi,08 { 8 }
PlantsVsZombies.exe+1312E3 - 57 - push edi
PlantsVsZombies.exe+1312E4 - 89 74 24 10 - mov [esp+10],esi
PlantsVsZombies.exe+1312E8 - 75 07 - jne PlantsVsZombies.exe+1312F1
PlantsVsZombies.exe+1312EA - C7 45 54 19000000 - mov [ebp+54],00000019 { 25 }
PlantsVsZombies.exe+1312F1 - A8 04 - test al,04 { 4 }
PlantsVsZombies.exe+1312F3 - 74 09 - je PlantsVsZombies.exe+1312FE
PlantsVsZombies.exe+1312F5 - 6A 00 - push 00 { 0 }
PlantsVsZombies.exe+1312F7 - 8B C5 - mov eax,ebp
PlantsVsZombies.exe+1312F9 - E8 52F6FFFF - call PlantsVsZombies.exe+130950
PlantsVsZombies.exe+1312FE - 8B BD C8000000 - mov edi,[ebp+000000C8]
PlantsVsZombies.exe+131304 - 8B C5 - mov eax,ebp
PlantsVsZombies.exe+131306 - 89 7C 24 14 - mov [esp+14],edi
PlantsVsZombies.exe+13130A - E8 01C4FFFF - call PlantsVsZombies.exe+12D710
PlantsVsZombies.exe+13130F - 2B 7C 24 20 - sub edi,[esp+20]
PlantsVsZombies.exe+131313 - 89 44 24 1C - mov [esp+1C],eax
PlantsVsZombies.exe+131317 - 8B C5 - mov eax,ebp
PlantsVsZombies.exe+131319 - 89 BD C8000000 - mov [ebp+000000C8],edi { 血量被赋值}
我们找到了mov ebp,[esp+14] 并认为ebp就是在这里被赋值的,为了验证这一点,我们在这个位置下断点,并断下
我们可以看到此时的ebp尚且为14,F8单步步过以后果然发现EBP变成了14EE1914
这时的EBP则转化为了[esp+14],这时照理来说我们应该重复之前的操作去找esp,但实则不然
因为:
(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
萌新看到这里可能一脸懵逼:这是啥子呀,这里我也不说什么堆栈平衡的话了,通俗来说,ebp和esp都是临时的指针,只有像eax、ebx、edx、esi、edi这类寄存器我们才要向上去找是什么去赋值的,而遇到这种mov ebp,[esp+14]这类的,我们要去找之前push xxx的xxx,或者在前面直接就有mov [esp+xx],xxx的
为什么呢:一个push会让esp减少4,我们会发现,这里的ebp是[esp+14]得来的,但我们又能看到上面有一个sub esp,08
也就相当于mov ebp[esp-08+14]即mov ebp[esp+c],这里主义mov []里面的值是十六进制的,14=16*1+4=20 20-8=12
不知道进制转换的直接拿计算器算即可
12=4*3 即3个push xxx,是不是感觉有点意义不明☆,暂且记下
接着向上找,发现已经到达了函数的头部,于是我们得到上一层去寻找了,如何判断到达头部? 看到 ret 还有一串int3就是了
也可以右键选择当前函数,然后找到选中的第一个,就可以得到函数的头部
回到刚才我们的那个mov [ebp+000000C8],edi,下一个断点,下完断点后回到游戏,等游戏再被断下以后,可以用shift+f8执行到返回,也可以一直手动按f8直到遇到一个ret
这里我用了后面那种方式,得到了:
此时这个pop edi上面的那个call 就是我们刚才那个函数,如果在那个call那里下断,然后F7单步步入就可以进入我们刚才的地方
然后我们在call这里做个断点,并给它一个标记call1(书签也可以设置一下,避免找不到)
此时我们发现call之前有3个push,而这里的esi正好是第三个push,而esi的值也"正好"等于之前的14EE1914
所以我们可以知道,之前的mov ebp,[esp+14],其实就是将esi的值赋给了它,这边主要是说明一下值的由来,其实大家都不难发现之前就是ESI=EBP=14EE1914了
于是我们的问题便又变成了[ebp+c8]->ebp->esi->[esi+c8]
我们接着向上找ESI是由谁给它赋值的,我们发现上面没有给esi赋值的语句,那会不会是上面的call给esi赋值的呢,有这个可能,但是我们可以在call之前设置断点,发现call之前esi就已经被赋值了,一路往上直到函数头部发现ESI的值都已经是被赋值了,得出结论是从上一层给我们ESI赋值的。
于是我们故技重施,直接在call这里下断点,然后执行到返回,得到:
贴上代码
PlantsVsZombies.exe+6E004 - 55 - push ebp
PlantsVsZombies.exe+6E005 - 56 - push esi
PlantsVsZombies.exe+6E006 - 57 - push edi
PlantsVsZombies.exe+6E007 - 8B F0 - mov esi,eax {esi是由eax赋值的}
PlantsVsZombies.exe+6E009 - 8B F9 - mov edi,ecx
PlantsVsZombies.exe+6E00B - 56 - push esi
PlantsVsZombies.exe+6E00C - 8B C7 - mov eax,edi
PlantsVsZombies.exe+6E00E - E8 1DFDFFFF - call PlantsVsZombies.exe+6DD30
PlantsVsZombies.exe+6E013 - 8B 5F 5C - mov ebx,[edi+5C]
PlantsVsZombies.exe+6E016 - 83 FB 06 - cmp ebx,06 { 6 }
PlantsVsZombies.exe+6E019 - 75 21 - jne PlantsVsZombies.exe+6E03C
PlantsVsZombies.exe+6E01B - 85 F6 - test esi,esi
PlantsVsZombies.exe+6E01D - 74 1D - je PlantsVsZombies.exe+6E03C
PlantsVsZombies.exe+6E01F - 8B 46 24 - mov eax,[esi+24]
PlantsVsZombies.exe+6E022 - 83 F8 16 - cmp eax,16 { 22 }
PlantsVsZombies.exe+6E025 - 74 3E - je PlantsVsZombies.exe+6E065
PlantsVsZombies.exe+6E027 - 83 F8 0C - cmp eax,0C { 12 }
PlantsVsZombies.exe+6E02A - 74 39 - je PlantsVsZombies.exe+6E065
PlantsVsZombies.exe+6E02C - 8B 86 D8000000 - mov eax,[esi+000000D8]
PlantsVsZombies.exe+6E032 - 83 F8 01 - cmp eax,01 { 1 }
PlantsVsZombies.exe+6E035 - 74 2E - je PlantsVsZombies.exe+6E065
PlantsVsZombies.exe+6E037 - 83 F8 03 - cmp eax,03 { 3 }
PlantsVsZombies.exe+6E03A - 74 29 - je PlantsVsZombies.exe+6E065
PlantsVsZombies.exe+6E03C - 83 FB 03 - cmp ebx,03 { 3 }
PlantsVsZombies.exe+6E03F - 74 0A - je PlantsVsZombies.exe+6E04B
PlantsVsZombies.exe+6E041 - 83 FB 05 - cmp ebx,05 { 5 }
PlantsVsZombies.exe+6E044 - 74 05 - je PlantsVsZombies.exe+6E04B
PlantsVsZombies.exe+6E046 - 83 FB 06 - cmp ebx,06 { 6 }
PlantsVsZombies.exe+6E049 - 75 1A - jne PlantsVsZombies.exe+6E065
PlantsVsZombies.exe+6E04B - 83 FB 06 - cmp ebx,06 { 6 }
PlantsVsZombies.exe+6E04E - 75 0B - jne PlantsVsZombies.exe+6E05B
PlantsVsZombies.exe+6E050 - 85 F6 - test esi,esi
PlantsVsZombies.exe+6E052 - 74 07 - je PlantsVsZombies.exe+6E05B
PlantsVsZombies.exe+6E054 - 8B C6 - mov eax,esi
PlantsVsZombies.exe+6E056 - E8 E54A0C00 - call PlantsVsZombies.exe+132B40
PlantsVsZombies.exe+6E05B - 56 - push esi
PlantsVsZombies.exe+6E05C - 8B C7 - mov eax,edi
PlantsVsZombies.exe+6E05E - E8 2DF3FFFF - call PlantsVsZombies.exe+6D390
PlantsVsZombies.exe+6E063 - EB 1B - jmp PlantsVsZombies.exe+6E080
PlantsVsZombies.exe+6E065 - 85 F6 - test esi,esi
PlantsVsZombies.exe+6E067 - 74 17 - je PlantsVsZombies.exe+6E080
PlantsVsZombies.exe+6E069 - 8B C6 - mov eax,esi
PlantsVsZombies.exe+6E06B - E8 C0F1FFFF - call PlantsVsZombies.exe+6D230
PlantsVsZombies.exe+6E070 - 8D 0C 5B - lea ecx,[ebx+ebx*2]
PlantsVsZombies.exe+6E073 - 8B 14 8D C8F16900 - mov edx,[ecx*4+PlantsVsZombies.exe+29F1C8]
PlantsVsZombies.exe+6E07A - 52 - push edx
PlantsVsZombies.exe+6E07B - E8 40370C00 - call PlantsVsZombies.exe+1317C0 { call2 }
我们向上找可以发现 mov esi,eax,说明esi是由eax得来的
问题再次转化为[ebp+c8]->ebp->esi->[esi+c8]->[eax+c8]
这时我们发现又到了函数头部,再次故技重施,下断并执行到返回,再来到上一层
贴上代码:
PlantsVsZombies.exe+6D04E - 5F - pop edi
PlantsVsZombies.exe+6D04F - 5E - pop esi
PlantsVsZombies.exe+6D050 - 5D - pop ebp
PlantsVsZombies.exe+6D051 - 5B - pop ebx
PlantsVsZombies.exe+6D052 - 83 C4 20 - add esp,20 { 32 }
PlantsVsZombies.exe+6D055 - C2 0400 - ret 0004 { 4 }
PlantsVsZombies.exe+6D058 - E8 E3FCFFFF - call PlantsVsZombies.exe+6CD40 { EAX在这里面}
PlantsVsZombies.exe+6D05D - 8B D0 - mov edx,eax {edx被eax赋值}
PlantsVsZombies.exe+6D05F - 85 D2 - test edx,edx
PlantsVsZombies.exe+6D061 - 74 EB - je PlantsVsZombies.exe+6D04E
PlantsVsZombies.exe+6D063 - 80 BA BE000000 00 - cmp byte ptr [edx+000000BE],00 { 0 }
PlantsVsZombies.exe+6D06A - 74 0B - je PlantsVsZombies.exe+6D077
PlantsVsZombies.exe+6D06C - 8B CD - mov ecx,ebp
PlantsVsZombies.exe+6D06E - E8 1D000000 - call PlantsVsZombies.exe+6D090
PlantsVsZombies.exe+6D073 - 84 C0 - test al,al
PlantsVsZombies.exe+6D075 - 75 D7 - jne PlantsVsZombies.exe+6D04E
PlantsVsZombies.exe+6D077 - 8B C2 - mov eax,edx {eax被edx赋值}
PlantsVsZombies.exe+6D079 - 8B CD - mov ecx,ebp
PlantsVsZombies.exe+6D07B - E8 800F0000 - call PlantsVsZombies.exe+6E000 { call3 }
不难发现,我们这里的eax是由edx赋值的;再向上找到mov edx,eax,edx又变成了eax所以我们还是要找eax
这里其实还遇到了一个小问题,就是在mov edx,eax 这里要下断点证明是不是eax将值赋给了edx,但是设置了断点以后,一进游戏就断下来了,并且eax的值并不是14EE1914,这个时候可能就有人觉得这里不是赋值处了,但其实这里就是赋值的地方,它是一个共用段,于是我们要通过条件断点来过滤,条件断点设置如下
通过条件断点后,果然断下了
再往上看只有一个CALL 了,要么EAX就是在CALL里被赋值的,要么就是在上一层被赋值的
怎么确认呢?我们可以在CALL 这里下个条件断点,如果是上一层赋值的,则会断下,否则不会断下
设置条件断点以后发现并没有断下,得出结论,EAX是在CALL里面被赋值的
于是我们先设置一个普通的断点,然后F7单步步入CALL中,然后找到CALL的尾部(跳出CALL之前肯定EAX已经被赋值完毕了),于是我们右键选择当前函数,然后找到被选中的最后一行,如图:
代码如下:
PlantsVsZombies.exe+6CE5F - E8 8CFAFAFF - call PlantsVsZombies.exe+1C8F0
PlantsVsZombies.exe+6CE64 - 84 C0 - test al,al
PlantsVsZombies.exe+6CE66 - 0F85 25FFFFFF - jne PlantsVsZombies.exe+6CD91
PlantsVsZombies.exe+6CE6C - 8B 44 24 18 - mov eax,[esp+18] { eax被赋值 }
PlantsVsZombies.exe+6CE70 - 5F - pop edi
PlantsVsZombies.exe+6CE71 - 5E - pop esi
PlantsVsZombies.exe+6CE72 - 5D - pop ebp
PlantsVsZombies.exe+6CE73 - 5B - pop ebx
PlantsVsZombies.exe+6CE74 - 83 C4 30 - add esp,30 { 48 }
PlantsVsZombies.exe+6CE77 - C2 0400 - ret 0004 { 4 }
从下往上找,不难找到mov eax,[esp+18] 这一句,验证一下,在这一句下方设置条件断点
断下
根据前面的经验,我们知道[esp+xxx]是之前入栈的某个地址,而这里ebx正好等于eax,所以我们就可以将问题转为找ebx
从下往上接着寻找可以找到
PlantsVsZombies.exe+6CDF9 - 8B DE - mov ebx,esi { ebx被赋值 }
于是ebx又变成了esi,接着往上找可以找到
PlantsVsZombies.exe+6CD70 - 8D 74 24 14 - lea esi,[esp+14] {这里的esp+14正好和下面赋值对应}
PlantsVsZombies.exe+6CD74 - 89 44 24 18 - mov [esp+18],eax
PlantsVsZombies.exe+6CD78 - 89 44 24 1C - mov [esp+1C],eax
PlantsVsZombies.exe+6CD7C - 89 44 24 14 - mov [esp+14],eax
PlantsVsZombies.exe+6CD80 - E8 6BFBFAFF - call PlantsVsZombies.exe+1C8F0 { call }
PlantsVsZombies.exe+6CD85 - 84 C0 - test al,al
PlantsVsZombies.exe+6CD87 - 0F84 DF000000 - je PlantsVsZombies.exe+6CE6C
PlantsVsZombies.exe+6CD8D - 8B 6C 24 30 - mov ebp,[esp+30]
PlantsVsZombies.exe+6CD91 - 8B 74 24 14 - mov esi,[esp+14] { esi被赋值 }
PlantsVsZombies.exe+6CD95 - 8B 46 1C - mov eax,[esi+1C]
PlantsVsZombies.exe+6CD98 - 2B 47 1C - sub eax,[edi+1C]
PlantsVsZombies.exe+6CD9B - BB 19000000 - mov ebx,00000019
这里我们可以找到mov esi,[esp+14],在这里的下一句下条件断点,验证是否是esi被赋值
果然断下了,但这里我们发现没有寄存器的值和ESI相同,说明寄存器在入栈之后,又被改变了
于是我们只能接着向上找push xxx,或者mov [esp+xx],xx ,这里找的是mov [esi],xx 因为上面的lea esi,[esp+14]是传址指令,相当于mov [esi],xx = mov [esp+14],xx
我们很快看到上面有个mov [esp+14],eax 在那里的下一句设置条件断点EAX==0x14EE1914,很可惜并没有断下,说明CALL里面有压入的参数,于是我们直接进入CALL中查看
直接Ctrl+G,然后输入CALL后面的地址0041C8F0 即可跳转到CALL里面进行查看
CALL里面的代码如下:
PlantsVsZombies.exe+1C8F0 - 57 - push edi
PlantsVsZombies.exe+1C8F1 - BF 0000FFFF - mov edi,FFFF0000 { -65536 }
PlantsVsZombies.exe+1C8F6 - 8B 06 - mov eax,[esi]
PlantsVsZombies.exe+1C8F8 - 85 C0 - test eax,eax
PlantsVsZombies.exe+1C8FA - 75 08 - jne PlantsVsZombies.exe+1C904
PlantsVsZombies.exe+1C8FC - 8B 82 90000000 - mov eax,[edx+00000090]
PlantsVsZombies.exe+1C902 - EB 05 - jmp PlantsVsZombies.exe+1C909
PlantsVsZombies.exe+1C904 - 05 5C010000 - add eax,0000015C { 348 }
PlantsVsZombies.exe+1C909 - 8B 8A 94000000 - mov ecx,[edx+00000094]
PlantsVsZombies.exe+1C90F - 69 C9 5C010000 - imul ecx,ecx,0000015C { 348 }
PlantsVsZombies.exe+1C915 - 03 8A 90000000 - add ecx,[edx+00000090]
PlantsVsZombies.exe+1C91B - 3B C1 - cmp eax,ecx
PlantsVsZombies.exe+1C91D - 73 12 - jae PlantsVsZombies.exe+1C931
PlantsVsZombies.exe+1C91F - 90 - nop
PlantsVsZombies.exe+1C920 - 85 B8 58010000 - test [eax+00000158],edi
PlantsVsZombies.exe+1C926 - 75 13 - jne PlantsVsZombies.exe+1C93B
PlantsVsZombies.exe+1C928 - 05 5C010000 - add eax,0000015C { 348 }
PlantsVsZombies.exe+1C92D - 3B C1 - cmp eax,ecx
PlantsVsZombies.exe+1C92F - 72 EF - jb PlantsVsZombies.exe+1C920
PlantsVsZombies.exe+1C931 - C7 06 FFFFFFFF - mov [esi],FFFFFFFF { -1 }
PlantsVsZombies.exe+1C937 - 32 C0 - xor al,al
PlantsVsZombies.exe+1C939 - 5F - pop edi
PlantsVsZombies.exe+1C93A - C3 - ret
PlantsVsZombies.exe+1C93B - 89 06 - mov [esi],eax { 赋值}
PlantsVsZombies.exe+1C93D - 80 B8 EC000000 00 - cmp byte ptr [eax+000000EC],00 { 0 }
PlantsVsZombies.exe+1C944 - 75 B0 - jne PlantsVsZombies.exe+1C8F6
PlantsVsZombies.exe+1C946 - B0 01 - mov al,01 { 1 }
PlantsVsZombies.exe+1C948 - 5F - pop edi
PlantsVsZombies.exe+1C949 - C3 - ret
这个CALL比较简短,我们直接从下面找起 ,一下就找到了mov [esi],eax 可以下个条件断点验证一下
果然断下
于是问题又变成了找eax(这个14EE1914我们转了多少手寄存器了???)
接着向上找EAX,这里EAX上方是RET,则肯定是从上方的语句跳转过来的,
不难找到跳转过来的语句:
PlantsVsZombies.exe+1C926 - 75 13 - jne PlantsVsZombies.exe+1C93B
于是从跳转过来的语句接着向上找EAX的赋值
PlantsVsZombies.exe+1C8F6 - 8B 06 - mov eax,[esi] {eax赋值为[esi]内部的值}
PlantsVsZombies.exe+1C8F8 - 85 C0 - test eax,eax {判断eax是否为0}
PlantsVsZombies.exe+1C8FA - 75 08 - jne PlantsVsZombies.exe+1C904 {为0则不跳转}
PlantsVsZombies.exe+1C8FC - 8B 82 90000000 - mov eax,[edx+00000090] {eax赋值为[edx+90]}
PlantsVsZombies.exe+1C902 - EB 05 - jmp PlantsVsZombies.exe+1C909
PlantsVsZombies.exe+1C904 - 05 5C010000 - add eax,0000015C { 348 }
PlantsVsZombies.exe+1C909 - 8B 8A 94000000 - mov ecx,[edx+00000094]
PlantsVsZombies.exe+1C90F - 69 C9 5C010000 - imul ecx,ecx,0000015C { 348 }
PlantsVsZombies.exe+1C915 - 03 8A 90000000 - add ecx,[edx+00000090]
PlantsVsZombies.exe+1C91B - 3B C1 - cmp eax,ecx
PlantsVsZombies.exe+1C91D - 73 12 - jae PlantsVsZombies.exe+1C931
PlantsVsZombies.exe+1C91F - 90 - nop
PlantsVsZombies.exe+1C920 - 85 B8 58010000 - test [eax+00000158],edi
PlantsVsZombies.exe+1C926 - 75 13 - jne PlantsVsZombies.exe+1C93B
我们通过汇编语句不难得出 EAX刚开始是由[ESI]赋值的,但刚开始为0的话则为[EDX+90]赋值,也可以从外面对CALL下断,分析EAX的赋值过程得到:头部由来是[EDX+00000090],每个僵尸的大小是15C,这里其实我们已经得到了僵尸数组的动态头部地址[EDX+90],我们接着追溯EDX,这里可以看一下动态地址的头部14EE0CD8,和我们的14EE1914相减得到C3C=3132 15C=348 3132/348=9,说明我们这个僵尸是由头部地址偏移了9个僵尸~~ 然后记录一下
接着就是找EDX,此时EDX的值为14EDB520
到这里找EDX就直接在CE里搜索了(也可以汇编里接着向上找,但一是出于篇幅问题,二是留给大家练手当作业吧)
CE里直接搜索14EDB520,也就是EDX的值,然后去掉第一个动态的地址,第二个就是了,这个大家应该都很熟练了
基址找到了,手动添加验证一下:
正确得到当前的僵尸血量~~~我们的反汇编追踪之旅算是告一段落了
作业
实践是检验真理的唯一标准。这不来两份热乎的作业温习温习?
第一份作业就是上面说的,继续通过反汇编的方式,从下往上跟踪EDX,然后找到基址
第二份作业则利用到了我们找到的这个僵尸数组头部的赋值语句,我们都知道所有僵尸的产生都会在这里的代码通过,那么能否在这块代码HOOK,让僵尸直接GO DIE呢?这种全屏秒杀才算是真正的全屏秒杀,直接从源头将你弄死~~~现在大多数的全屏秒杀都是通过在僵尸移动的那一块代码直接修改僵尸的状态来实现的,但是别忘了最后的僵尸BOSS,它貌似没有移动吧?因此僵尸王无法被秒杀,秒杀不够完美。第二份作业要求:HOOK僵尸头部的这块代码,实现可以秒杀包括僵尸BOSS在内的所有僵尸
总结(注意事项)
反汇编找基址其实就是从下往上,寻找目标寄存器的来源,最终找到目标
寄存器中比较特殊的EBP和ESP,要通过寻找之前入栈的寄存器来获得赋值来源
入栈操作不仅仅是push xxx 指令 还有 mov [esp+xxx],xxx 或者先lea xxx,[esp+xxx],再mov [xxx],xxx等等
有的时候向上追代码的时候,会遇到明明还没攻击到僵尸却引发了中断,并且此时寄存器里的内容都不对,有可能是共用代码段,需要用条件断点来进行判断
找到赋值语句以后可以在那里下个断点,看是否执行以后寄存器内容被修改,验证语句来源的正确性
有时候会遇到很多跳转,但要记住,如果我们的语句执行了,那么跳过我们语句的跳转肯定是没有跳的,不然我们怎么执行?
遇事不决的时候找不到来源的时候多下断点,看看寄存器的变化,实在找不到就去函数头部下断,然后一步步单步步过,看在哪里寄存器的值发生了改变
个人感言(无关技术,可跳过)
白嫖了网络教程资源这么多年,都没写过技术教程,这次算是我的首次技术教程吧,能力不足,水平有限,欢迎大家指出我的不当之处,也请大家多多包涵一下,希望能够一起变强。
最后碎碎念一下:这个教程肝了我一晚上,太肝了。出这个教程的初衷是看到现在的找基址教程十个有九个是PVZ(夸张),但一个汇编追基址的都没有(可能有?),于是出一期看看反响如何,之后可能会接着出汇编硬追代码的系列教程,视大家的热情程度而定吧