09授人以鱼不如授之以渔●CALL入门篇一:CALL的本质
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
09授人以鱼不如授之以渔●CALL入门篇一:CALL的本质
*所谓的call,其实本质上来说就是一条汇编指令.
*只要找到了关键代码的地址,传入适当参数,就可以借用游戏中已有功能来完成内挂的功能。
当程序被编译以后,便不会存在任何函数,存在的只是0和1.所以我们调用也只是这段机器码而已.
网上找CALL的教程很多,但是却是从一个游戏的某一个功能入手,比如说完美的打坐,剑侠3的技能CALL,等等,那是因为每个游戏的数据结构都是不同的.一个游戏的怪物数组可以用数组结构也可以用树可以用链表,所以说bp send 在返回, 并不是万能的.
P:当我们上手一款游戏,我们一开始如何分析,从哪里开始?
每个人都有不同的想法,而且水平不同,开始寻找的侧重点也不同,寻找多了之后你自然而然的会明白自己该从何入手,而且能确认哪个是真正要找的数据,这个就是经验了.
目标:武易的打坐CALL
目的:以打坐为例子讲解各层CALL的含义
好了,今天就拿武易这个游戏做例子,这个游戏的非常简单,有些类似于传奇.
首先分析下,能不能用OD加载,或者看看有没有启动什么保护之类的.
加载好以后,我们来试试游戏的一些功能(有些朋友一上手就去分析数据了) , 知彼知己,方能做出好的功能的辅助,一个做的好的辅助,他的游戏经验也一定很好,只有玩这个游戏精通的人才能做出最适合的辅助来.
color=Black]玩了一段时间,我们发现,一开始,是需要领取武器和衣服,要不然你会死的很惨.... 好了,玩了下发现游戏按D 是打坐, TAB 是选怪,右键是跑,在地图上面点击能自动寻路,任务里面能点击怪物自动寻路. 好了简单的游戏功能都已经出来了,我们下面从最简单的功能开始,就先寻找打坐的CALL吧
我们下来下bp send 命令, 然后返回游戏按D 这个时候OD就断下来了,(如果不断试试WSASend或其他发包函数)
既然断下来了,我们就能确认他是用send 发包
好了我们又来到了老地方了,这里是send 函数的头部,前面我们讲过只要CALL这个地方并且传入4个值就能正确调用这个函数了.
好了,返回一层我们到了这里,这里是游戏调用send 函数发包的地方.
这里是我们加密包后的CALL. 为什么呢?
好了,我们在断一次看看封包地址内容是什么, 是不是和上面的差不多?
当然这个游戏比较简单, 所以很多东西都比较直观.
我们继续返回
这里有一层CALL,比较像打坐的.我们来看看堆栈地址,发现压入的堆栈是加密后的数据,但是少了一些内容
看来这里还不是打坐CALL的地址,要不然不会压入封包加密后的数据.
又返回一层到了这里,这里我们发现压入了好多东西,我们看看那个EAX有啥数据,看堆栈...
这里压入的顺序和代码压入堆栈的顺序是一样的. 这里我们可以看到EAX=
有经验的人就能看出这里是封包构造的那一层, 3AAC 是封包内容中打坐的标志.~
当然了以我们目前得到的数据来说的话这一切只是猜的,而且这层里面包含2个CALL
在这里如果如我们猜想的正确的话那么就是明文封包的打坐CALL的封包结构了,而这一层就是所有构造封包的CALL.
我们先来分析下他的数据...
==============================CALL的分析========================
在第一行push ebx下断. 压入了20 这个值
第二行004931C1 8A5C24 08 mov bl, byte ptr [esp+8]
*这里[esp+8] 是指上一层CALL所压入的参数.([esp-8] 表示局部变量详情请看反汇编原理篇一),不信的话还可以去上一层看看压入的参数是否一样
[esp+8] 指针的内容是01 bl = 01
第三行004931C5 66:0FB6C3 movzx ax, bl
我们先来看下movzx 指令的含义
movzx:
带0扩展传送指令(注意是通用数据传送指令,所以符合mov一般寻址方式)
格式:movzx DST,SRC
执行操作:(DST)<-0扩展(SRC)
两种格式
movzx reg1,reg2
movzx reg,mem
该指令不影响标志位
源操作数任意寄存器或内存寻址而目的操作数必须寄存器寻址,且长度一定大于源操作数,将源操作数带0扩展传送
例如:
movzx dx,al
al=8ah,10001010,扩展后dx 00000000 10001010 008a
是不是看的很迷茫?没事只要我们多实战几次自然就会懂的.
我们先来看看执行这条指令后的结果.
004de150 变成了004d0001 呵呵现在应该有点明白上面指令解说里的意思了吧.
第四行004931C9 56 push esi ESI= 7C80934A不知道会不会变
004931CA 6A 00 push 0这一行不解释了压入了一个0
004931CC 8BF1 mov esi, ecx将ECX的值压入到ESI, ECX的值从哪来?
004931CE 50 push eax这里就是把前面得到的
4d0001 压入堆栈也就是说封包内容(别问我咋知道的我是猜的) 004931CF 6A 00 push 0
004931D1 6A 00 push 0
004931D3 68 AC3A0000 push 3AAC
压入2个0 然后压入3AAC (可能是封包标志)
好啦接下来是CALL call 004200B0
现在差一个ECX ,我们多断几次看看他的值会不会变当然还有ESI的值.
我们断了几次发现ECX的值暂时不会变化(重新打开游戏可能会变化) 这里顺便提一下如何寻找ECX 和ESI 的值的基址.
方法一用CE查找.
我在找基址一中就说过在CE中绿色的就是基址了
以后读取这个地址就可以取到ECX的值了
用同样的方法就能取到ESI的值这里我们发现有好几个绿色的值我们随便取一个就可以了
==============================CALL分析结束
===================
既然CALL已经分析完了,那么我们用代码注入器来写CALL
push 20
mov esi,[600F1FC]
push esi
push 0
mov ecx,[4FA818]
mov esi,ecx
push 4d0001 '这里我们直接压入获得的EAX值push 0
push 0
push 3aac
call 4200b0
add esp,1c '堆栈平衡压入了7个堆栈7*4=28 =1C 10进制的28=16进制的1C
好了, 注入远程代码, 发现游戏人物并未执行打坐动作,但是游戏没有出错,我们的CALL是写正确了.
但可能不是封包结构的CALL,估计我们猜错了
很多时候,我们都在作无用功,但是成功可能在离你不远的地方,就要看你能不能坚持下去了.
我们这时候发现下面还有一一个CALL ,如果继续写的话还不如直接调用上一层CALL呢。
好了继续返回, 这里有个CALL [EAX+84] 这个是间接地址,我们先断下来看看.
=============================CALL 分析======================
首先我们看下CALL的值
call [eax+84]=[004DE1D4]=004931C0
然后我们来找下edx 的值 .....我们多断几次发现EDX的值每次都是变化的.
好了我们进去看看到底哪个语句调用了这个参数.
进入了[EAX+84] 的内部也就是刚刚我们分析的那一层.
我们来找下
004931C1 8A5C24 08 mov bl, byte ptr [esp+8] ; 01
这句话就是使用了刚刚PUSH 进来的值. 为啥是这个呢,我们在上面说过[堆栈+*] 这种都是参数.
也就是在易语言里子程序被传入的参数.
BL 是EBX EX BX EX=EH EL BX=BH BL
所以这里不管[ESP+8] 有多少数字只会传入8个字节也就是说16进制的2位那么这里除了个位数和十位数有用其他位数的不都没用了么?
回答正确.~
我们多断几次发现他不管怎么变化后面2位都是01
也就是说传入EBX的值就是=1
我们PUSH 1 试试
参数解决了,那么我们来解决寄存器问题首先进入到CALL内部来看看CALL需要哪些寄存器
004931C0 53 push ebx ''这里调用了EBX
004931C1 8A5C24 08 mov bl, byte ptr [esp+8] ; 01
004931C5 66:0FB6C3 movzx ax, bl ''这里的BL 上面已经赋值了所以不需要我们写了
004931C9 56 push esi ''调用了ESI
004931CA 6A 00 push 0
004931CC 8BF1 mov esi, ecx ECX未被赋值所以CALL调用了ECX
004931CE 50 push eax ; 004D0001 ''EAX上面已经赋值了
004931CF 6A 00 push 0
004931D1 6A 00 push 0
004931D3 68 AC3A0000 push 3AAC
004931D8 E8 D3CEF8FF call 004200B0
004931DD 8B8E 98040000 mov ecx, dword ptr [esi+498] ; 4
004931E3 8B96 84040000 mov edx, dword ptr [esi+484] ; 9a
004931E9 8B86 80040000 mov eax, dword ptr [esi+480] ; 67
004931EF 83C4 14 add esp, 14
其他都没了~ 我们来整理下一共调用了3个寄存器一个是EBX ESI ECX
我们来看看3个值到底多少
这里我们断在CALL的时候寄存器的值EBX=20 ESI =7C80934A ECX=0DDC01D8
我们在上面分析过了EBX 和ESI的值都是不会变化的,而ECX的值重新开游戏就会有变化
我们上面用了CE找基址这次我们来用另外一个方法
00471B7E 8B0D 18A84F00 mov ecx, dword ptr [4FA818]
这里传入了ECX的值是不是跟我们上面找的一样?
00471B8E 8A91 0E050000 mov dl, byte ptr [ecx+50E] ; 打坐状态
这里有个ECX的偏移多次打坐站起来后我发现打坐的话就是1 不打坐就是0
这里就是打坐的状态, 大家可能会发现修改这里的内存值会直接打坐,其实这只是本地的效果,在服务器并没有打坐,也不会有恢复血量的变化,所以你还是老老实实的调用CALL吧
================================分析结束==============
好了分析结束了我们开始调用CALL
好了调用成功了.
这里,我们来找找mov esi,7c80934a 中7c80934a 的基址
随便挑一个,写成汇编代码就是mov esi,[600F1FC]
这里我们把CALL换一种写法我们来写一下CALL 的基址
mov ecx,[4fa818]
mov eax,[ecx]
call [eax+84]
这里我用红色的框标出来了,这里可以直接找到基址(注:这里基址你们的基址可能跟我的不同,我最后会讲这个原因)
好了整合下测试成功~(这里因为间接地址的原因(如[EBX+84] ),可能基址会不同.)
mov esi,[600F1FC]
mov ebx,20
mov ecx,[4fa818]
mov eax,[ecx]
mov eax,[eax+84]
push 1
call eax
不过这样写还是太麻烦了,所以我们再去上一层看看这里便是上一层的代码了.我们来分析下
====================CALL分析=========================
首先来看看堆栈的数值PUSH ESI esi=09ECA1A8 重开游戏发现这个值变化了.我们来找找这个值从哪来的,打开CE 搜ESI的值,找到一个绿色的地址, 这个就是ESI的基址
好了接下来我们看看CALL内部调用什么寄存器.
=======================================分析结束================
好了我们写一下CALL
===============================最后分析========================
我们在讲解第二个CALL的时候,你可能会发现你的基址跟我的可能有些不一样.
下面那张图是不同电脑的CALL 原型.
后来我发现很多动作都调用了这个CALL, 比如说打开地图啊修理啊, 关闭背包等等.
这里可能是调用了外部模块的原因 .这里我无法肯定,因为我也没有具体的去研究过.或者是游戏版本的不同
如果有朋友知道请回帖说下,不甚感激.
从上面那张图可以敲出除非用特征码来寻找基址,估计没有其他办法来确定固定的值了,或者说我不知道.如果用特征码的话那么就太麻烦了.
如果调用这层CALL来做挂的话,我估计也只能你自己用了.~~~~.
好了,花费那么多时间来研究一个自能自己用的CALL 到底值不值呢?这个只有你自己最清楚了.。