比如打怪功能.,点击怪物之后触发的功能调用可能如下
鼠标点击CALL { ..判断点的什么东西call { ....选中怪物call { ......走路call { ..........攻击call { 技能CALL { ... ... } } } } } }
struct 技能对象 { 技能ID 当前是否可用 攻击距离 消耗MP 伤害值 恢复值 技能类型 冷却 学习等级 }
我作为一个新手,目前能想到的起手方法就两种,
第一种就是利用发包CALL追功能.因为每个功能都会发包,只要从发包call往回走就能找到功能,但是线程发包除外,线程发包的话需要先追到线程外的数据来源,然后再往回追才是功能CALL
第二种是找突破口(简单说法),比如,我想找某个动作的调用call,可以先找到动作列表,然后得知某个动作的对象地址,然后给他下访问断点,使用动作时就会断下,然后可以追到动作. 再比如想追走路call,那么可以从人物的状态下手.静止不动可能状态为0,走路起来,状态改变,(一般改为1,也可能23456),最后搜索到人物状态的地址.那么给这个地址下写入断点,进行人物移动就会断下,就能找到功能call
首先第一件事我们要确定参数的个数,方法:
第一步,简单的一种方法就是进入这个call的内部,看他的ret数值.一个参数占4字节,这个ret4,那么就是一个参数..
第二部,检查有没有寄存器传参
正在上传…重新上传取消
比如这幅图,这是在功能call的内部,ecx没有任何来源,就直接赋值给了其他地方进行使用,说明ecx来自外部,是个寄存器参数.这样的情况需要在call调用之前追到ecx的来源.(基址+偏移)
第三步,如果你认为这个call有参数,但是内部ret 没有参数,如果他有参数,但是内部没有ret,他可能是个外平栈.,那么你需要看看功能call的下一行有没有pop或者add esp的指令(进行堆栈平衡,call之前esp在哪,调用完之后esp的位置也要恢复)
正在上传…重新上传取消
比如如上图这个call,第一个参数是0,第二个参数是1每次调用都不变,那么不需要管.我再说第三个第四个参数可能和我一样刚开始的新手会不理解,明明只有两个push哪来的第三四个参数. 第三四个参数来自 sub esp,8 这行指令. 思考一下,push 0他的过程就是esp开一个四字节空间,吧0放进去. 那subesp,8同理,就是开辟两个四字节空间.然后下面的 movss给这两个空间赋值. 所以他有四个参数. 第三个,目的地Y坐标,第四个参数:目的地X坐标. (这两个参数需要在编程过程中自己设置) 然后就是寄存器参数,确认ecx是个寄存器参数.然后向上走追他的来源.mov ecx,esi,//ecx来自esi,然后追esi来自什么.如果到了头部,就返回到上一层call继续追,直到追到基址.最后就可以调用了.
比如:
1.eax处追错了,那么你可能忽略了一个知识点, 所有call的返回值都存储到eax,如果eax往上追的过程中遇到了call,就需要进入call的内部追eax
转存失败重新上传取消
就比如上图,想知道test eax 中eax的值就需要进入call 005aa720去追
2.往上追遇到了一些乱七八糟的代码,代码也不齐全,偏移也巨大.那么可能是追到了VM区域,这一块代码被抹掉不让你看了.那么该怎么绕过这一段代码继续追呢.????假如你此刻正在追的是edi吧.那你就把edi里面的值记录下来,打开ce,搜索这个值,找到记录他的地方A,然后在dd A ,
给dd的地址下断点然后让他断下后追就可以了,从而绕过VM
3.ebp和esp不同其他寄存器.这一块需要学习堆栈知识,了解堆栈结构.如果想速成,我也只能说几个注意点
(1)ebp-xx是这整个call体内的局部变量.(就是进入某个call之后创建的变量,). ebp+是保存下来的数据,如果遇到了,ebp +或者- xxx 不要单独追ebp,要追[eb+-XXX]这个整体.
(2)[ebp+8]是上层的第一个参数(离call最近的是第一个),[ebp+C]是第二个 [ebp+10]是第三个
.....四字节累加,区分好16进制和10进制,
(3)在追esp+-XXX的过程中也要整体代入,但是往上走的过程中他和ebp不同,esp会变化.ebp不会变.
为什么esp变化.???因为push 和pop引起.遇到引起esp变化的代码就修改一下esp+-的偏移然后继续追
(4)追到头部之后,[esp+4]是外层第一个参数 [esp+8]第二个............