| 多时候CALL里的一些数值,都是变化的,或者不同的电脑值也不一样,如何寻找这些值的基址呢?不同的值有不同的找法下面就列出几条常用的方法。 
 1.CE搜索
 
 这个方法在我找CALL入门篇一中就有说过而且,很多篇章中都用过这种方法,例子:模拟器 游戏找CALL练习实例ONE
 
 
 
   这里我们找的是EAX的值,EAX的值 是不同电脑他的值也是不同的。这个我在找CALL篇一中说过。
 
   
 
 
 绿色的就是基址了, 如果搜出来没有绿色如何?可以用找血基址的方法找偏移,然后跟踪出他的基址。2.代码分析
 从汇编代码中顺藤摸瓜摸出基址,这个也是比较常用的方法。例子:CALL入门篇一武易打坐
 例子:
 
 从上面我们要找EAX的值,才能得到CALL的地址,EAX是如何来的呢?这要往上寻找了首先  我们找到的是 mov eax,[ecx]   这里 把ECX里的值 赋值给EAX  那么EAX的来源就确定了,但这还不是明确的地址,我们继续往上找
 然后  到了mov ecx,[4fa818]    这里我们找到了 赋值给ECX的值  ,而且也是 明确的地址。(摸到瓜了)
 好了  EAX的值就是   [4fa818]里的值  赋值给ECX   在从[ECX]里的值赋值给EAX
 公式   [[4fa818]+0]   (读了2次基址)
 3.CALL的返回值
 如果你寻找某个寄存器的值,苦苦追了3层还追不到,那么你就要注意了,其实这个值可能就在你原来CALL的附近。
 详细的请看 CALL提升篇一:剑侠3的喊话CALL分析后部分
 4.子程序参数的跟踪
 
 这个是 入门篇三中的模拟器代码, 我们要找EBX的值从代码上可以很清楚的找到  EBX的值 是 [EBP+8] 中传入的,而EBP  确实从ESP传入,大家都知道ESP是堆栈指针的寄存器,是不断变化的,但如何取到这个值呢?
 首先,我们要明白[EBP+*]  这种偏移的含义,  其实我前面也讲到过 这个就是 参数的值
 
 这个子程序 被传入 包头 和 数据   2个参数,然后组合。代码中  [ebp+8] 其实就等于  数据  值,  而[ebp+c]就是 包头的参数值(如果是ebp-*)这种类型 就是  临时变量
 从这里我们可以看出,EBX的值 并不是系统里的,而是我们自己应该写入的参数堆栈值,固也无法跟踪了(因为这个值是需要你自己写入的)
 这里有朋友可能要问了  如果我要写这个CALL 而不写上面那一层的CALL这里改如何写呢? 其实直接赋值就可以了, 比如说  PUSH [ebx]     这里如果需要传入40这个值 那么直接  PUSH 40便可,  (我在前面几篇中强调过,CALL只要传入适当的参数,便可以调用)这里适当的参数就是这层CALL所需要的参数数据,而不是傻傻的跟上去找原值。
 这里 具体的可以看看 提升篇一   文章中后期 对寄存器值的跟踪过程
 寄存器eax值的跟踪! R)Dh;XA  FYH^axpp
 在调用约定里 所有CALL的返回值都是靠EAX返回的,如果EAX放不下就放在EDX里。如果返回的结果是文本类型的话就会返回一个指针地址。在游戏里,一般的功能CALL返回值很少有。
 1~vv<`-
 如 iO iXo6YE
 int myadd(int a, int b) :fQN_*B4@4
 { *2Q x69`
 int c=a+b; e‑ r"gPW
 return c;  29NP!W /g
 } \$ :)Ka
 Pcr;+'q
 在反汇编的表现形式大概就是 vr$z6m
 ^
 [H>/N7v19*
 push ebp                        //寄存器环境保护 ‑ 3,Bm"'b6
 mov  ebp,esp              //将堆栈指针的值传给EBP用于开辟临时变量 %Z(lTvqG
 sub esp,4                  //开辟一个临时空间 也就是我们定义的临时变量C Y 4*?QBYA
 mov [esp-4],0            //将 c 初始化 也就是C=0 尽管我们没有写不过编译器会自动完成 {>l`P{{y
 mov eax,a                //将A放入寄存器EAX里 op|x~Thf
 add eax,b              //将EAX加上B w4Ku1G#jC
 mov [esp-4],eax              // 将计算结果保存到临时变量C k)JwCt.%
 mov eax,[esp-4]    //将保存结果的变量C传递到EAX n/IDq$[1]/P   mov esp,ebp        //将堆栈指针恢复到调用CALL之前。 pop ebp              //将寄存器保存的值取出来。 9wv 7 HD|  jI807g+
 retn P 4~C0z
 这个就是一个简单加法子程序的运行过程。所以很多时候我们跟踪一下自己写的程序,看看机器是如何运行你的代码的,这个是一件很有趣的事情,也会增加你对编程和汇编的了解。这里的反汇编代码是我手动写的可能和真正的有误差,但大概的过程是应该没有错的。 7 *HBb-
 所以很多人在跟踪寄存器EAX的时候往往会放过挨着的CALL指令,直接找上面的汇编代码。要看看EAX是否是一个CALL的返回值其实很简单,看看运行CALL指令后EAX的值是否有变化就可以了。
 寄存器esp,ebp值的跟踪! i‑'$V'x'k  上面说到 堆栈参数的传递,当参数压入到堆栈CALL的内部是如何读取的呢? o-))R| ~z
 很多朋友都看见过这样的寻址指令 mov ebx,[esp+1c]  这个时候很多朋友都去寻找赋值 ESP 相关的指令去了,但找了半天都没找到.其实这里直接指向了堆栈. ESP是一个特殊的寄存器,他永远指向了堆栈顶部.  I‑wfJDJJ
 所以一般轻易不会去变动这个值.  当 CPU 执行 PUSH指令时 ,ESP就会-4 然后把数据存放到当前ESP的地址里.这个时候如果读取刚刚压入的参数 就是 mov ,eax,[esp]  这样堆栈顶部的数据就会被读取. %q~YJ*\  但是这个时候又压入一个数据呢?  压入的时候ESP会-4  那么 指向刚刚那个参数就是 mov ebx,[esp+4] ,co~@a@9
 如果压入了5个 要指向第一个参数 就是 [esp+10]  没错就是10  一个堆栈是4字节 4个就是16字节 16在16进制里就是10 Rd?8LLz[1]
 这里要说明的一下是 CALL指令也会压入一个数值.所以
 PUSH EAX 3tO= [1]  CALL ******** =N62 ){{
 在CALL内部指向 EAX 就是 [ESP+4]  这里其实压入了2个堆栈 ,一个是PUSH EAX  还有一个是CALL. r%c[1]raf   临时参数的表达方式是 [ebp-*]  一般是在CALL头部把ESP的数值赋值到EBP  那么 EBP永远指向CALL头部时的堆栈指针,对于下面新增的堆栈就是 以减法表示 因为 压入一个堆栈ESP就会-4  .故[EBP-*]在反汇编里代表临时变量. sew0n`d1  
 
 
 
 
 
 
 |