77范文网 - 专业文章范例文档资料分享平台

郁金香VC++初级和中级篇, 最全的手记及琢字翻译(6)

来源:网络收集 时间:2019-04-01 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:或QQ: 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

前面课程当中第一个PUSH说的是药品ID,其实应该是背包数组下标. 2.4.1、找怪物列表基址 a、选定怪ID b、怪物数组基址 c、怪物数组大小 mov edx,43333

mov [95e800+eax*4],??? //GameBase[eax] mov eax,43333 mov [eax],???

add eax,4 // DWORD long for (i=1;i<200;i++) //选中怪对象

选中怪时 肯定存在一个值怪对象基址 怪对象ID号 换怪时 怪对象怪对象ID号 1、未知初始化数值 2、更改的数值 3、未更改的数值

44b9f6:mov eax,[ebx+1530]//怪ID号的偏移 44bA03: mov ecx,[eax*4+0599a110]

dd [i*4+0599a110] //0599a110对象数组基址 +C: 数组下标

[5993E80]+1530 //当前选中怪ID//对象数组下标

今天要找的是怪物列表,数组的汇编代码很常见的一种就是 edx+eax*4 等等,一般我们找怪物数组是先从当前选中怪入手,因为当前选中怪后其值一定会在内存的地址中,当再换一个怪后其值会变,如果没有选中怪则为空.有的时候找到的是怪对象,有的时候是怪物ID.

先用CE查找一下当前的选中怪(未知数值),然后换另一个怪,再查找改变的数值,这样查找多次之后找出了几个地址很像,然后在CE里下内在访问,记一下访问地址44b9f6,在CE里显示一下反汇编 mov eax,[ebx+00001530] ,那么在这一句的下面 mov ecx,[eax*4+0599a110]这就是数组访问方式了,我们在OD里附加游戏,来到这个地址看一下,发现这里像是一群怪物的对象 [attachment=563]

我们随便找一个地址看一下,发现了许多怪物相关的信息,所以看起来我们找到的这群怪物对象确实像遍历当前怪物的数组.那么从上往下查找怪物对象里面的信息,通过分析发现+C这里就是数组的下标,那么我们再来找一下基址,也就是mov eax,[ebx+00001530]这句中EBX的来源,我们向上找一直到函数头部,再返回到上一层,发现EDX是[ECX]的来源,再继续向上找ECX,再继续向上找不太好找,所以我们用CE来查找.

先看一下当前EBX里的值,放到CE里搜索16进制数值,竟然发现了很多绿色的基址,但是不知道哪一个是正确的.我们来换一个怪物,看其值会不会变化,没有变化,那么我们再退出游戏重新进一次,看这些值是否会变化.发现这些地址都很像,因为前面数组是0599****开头的,所以我们就选这个05993E80比较接近, 2.4.2、分析怪对象属性 a、怪对象ID b、怪与玩家距离 c、怪物死亡状态 d、怪物分类编号 参考2.4.1

[5993E80]+1530 //当前选中怪ID//对象数组下标 //写入怪下标 =0000FFFF 时未选中怪 =对象数组下标

[i*4+0599a110] //0599a110对象数组基址 +C: 在对象数组中下标值

[i*4+0599a110]怪物对象属性:

+8 :有可能是对象分类 怪是2E //,31,18,20,22 +C :数组下标

+31C:到当前玩家距离 +320:怪物名字 +378:怪死亡 <>0 +37C:怪死亡 <>0 +380:怪死亡 <>0 CE锁定选中怪ID

找到上节课的地址+偏移[5993E80]+1530,发现其值为0000FFFF时是未选中怪,当我们选中一个怪后就变成了00000D59,发现这个值是对象数组的下标,我们在OD里下 dd [0d59*4+0599a110],找到这个对象之后,又继续找出了相应的偏移值,各类值地址已经在教案中例出了.找怪物与人物的坐标地址,用浮点数查看,来到+31C这里,发现比较像.下面继续查找怪物的死亡状态,猜测是一个比较小的值,因为杀了怪之后就不方便分析,所以我们用CE来锁定当前选中的怪,一点一点的向下查找,发现了378/37C/380的偏移地址会随着怪物的死亡而发生改变.还是要继续分析怪物的名字,还是在这个地址下dc [0d59*4+0599a110],向下找发现+320的地址就是怪物的名字. 看老师讲的比较轻松,如果真让自己找的话,就不容易了. 2.4.3、遍历怪物列表 a、选怪关键代码 b、定位一个怪对象 c、选怪功能实现 /遍历 [i*4+0599a110] 数组

//+8 :有可能是对象分类 怪是2E //+C :数组下标

26

//+31C:到当前玩家距离 //+380:怪死亡 <>0

int* b8,*bc,*b380;//定义偏移变量 float *b31c;//坐标变量,浮点型 int* pb;//定义指针对象

for (int i=0x0599a110;i<(0x0599a110+0x0FFF*4);i+=4)//每次增加4字节 { pb=(int*)i;//遍历变量

b8=(int*)(*pb+0x8);//偏移8,怪物分类 bc=(int*)(*pb+0xc);//偏移0C,数组下标

b31c=(float*)(*pb+0x31c);//偏移31C,坐标距离 b380=(int*)(*pb+0x380);//偏移380,死亡标识

if ((*b8==0x2E )&&(*b31c<=100)&&(*b380==0))//查找符合条件的怪物 {

//选怪[[0x5993E80]+1530 ]=*bc;优化改进 显示怪血条 pb=(int*)0x5993E80; pb=(int*)(*pb+0x1530); *pb=*bc; return ; } // end if }//end for

//////////////////////纯汇编 选怪代码

// TODO: Add your control notification handler code here //[i*4+0599a110]怪物对象属性:

for (int i=0x0599a110;i<(0x0599a110+0x0dff*4);i+=4) { //遍历对象列表 有可能是对象分类 _asm

{ mov eax,i mov eax,[eax] mov ecx,[eax+8]

mov b8,ecx //取出+8偏移 mov ecx,[eax+0xc]

mov bc,ecx //取出+c偏移 mov ecx,[eax+0x31c]

mov b31c,ecx //取出+31c偏移 mov ecx,[eax+0x380]

mov b380,ecx //取出+380偏移 } //end asm

//+8怪是=2E //+31C<100 //+380==0 if ((b8==0x2e)&& (b31c<100)&&(b380==0)) { //[5993E80]+1530 =+C _asm

{ mov ecx,0x5993E80 mov ecx,[ecx] mov eax,bc

mov [ecx+0x1530],eax //[ecx+0x1530]=bc }//end asm // int * selmon;

//selmon=(int*)0x5993E80;

//selmon=(int*)(*selmon+0x1530); //*selmon=bc; return; } //end if } //end for

//作业:优化选怪功能 //显示出怪物血条

前面找到了遍历怪物的地址,我们要编写代码将怪物例显示出来,首先是要查找偏移地址是否为2E,然后再查找偏移31C的距离是否小于100,当然还要查找偏移380是否为0,如果非0则说明怪物已死亡.然后遍历的时候再每次下向4个字节,要不断的遍历,代码已经在上面教案中.也就是VC代码的那部分.写完代码之后加载主EXE调用一下试试.注意坐标类型为浮点数,否则会出错.虽然已经可以选怪了,但是被选中的怪并没有显示出血条,下节课再弄.至于汇编的选怪代码已经在教案中例出,课后自己学习. 2.4.4、选怪功能优化

a、OD分析选怪功能对应代码

b、写测试代码让选定怪物血条正确显示 c、集成选怪函数到SelMon() 参考 2-4-2

dd [5993E80]+1530 //写入 怪在对象列表的 数组下标 dd [0d66*4+0599a110] //对象基址

27

//显示血条,设置怪选中状态 void SelMon() //选怪功能

{ // TODO: Add your control notification handler code here //遍历 [i*4+0599a110] 数组

//+8 :有可能是对象分类 怪是2E //+C :数组下标

//+31C:到当前玩家距离 //+380:怪死亡 <>0 _asm {

mov eax,eax mov eax,eax }

int* b8,*bc,*b380,*p1530; float *b31c; int* pb,*p2;

for (int i=0x0599a110;i<(0x0599a110+0x0FFF*4);i+=4)//每次增加4字节 { pb=(int*)i;

b8=(int*)(*pb+0x8); bc=(int*)(*pb+0xc);

b31c=(float*)(*pb+0x31c);// b380=(int*)(*pb+0x380);

//if (([ecx+8]==0x2E )&&([ecx++0x31C]<=100)&&([ecx+380]==0)) p1530=(int*)0x5993E80;

p1530=(int*)(*p1530+0x1530);

if ((*b8==0x2E )&&(*b31c<=100)&&(*b380==0)) {

//选怪[[0x5993E80]+1530 ]=*bc;优化改进 显示怪血条 p2=pb;

//显示血条,设置怪选中状态 //selmonbase怪对象基址 int selmonbase=*p2; if (*p1530==0xFFFF) { _asm {

mov edi,selmonbase mov eax,[edi] push 0 push 1 push 0x44c mov ecx,edi mov eax,[eax+4] call eax }

} //end if

p1530=(int*)0x5993E80;

p1530=(int*)(*p1530+0x1530); *p1530=*bc;//写入下标 return ; //

} // end if }//end for }

继续上节课进行选怪功能的优化,先用OD附加游戏进行分析,因为在未选中怪的时候dd [5993E80]+1530标识是0000FFFF,那么我们在这里下内存写入断点,来到了选怪函数,向上找发现一个CALL比较像 [attachment=566]

然后就将上面的汇编代码照着写了出来,已贴在教案中.注意在VC++内联汇编中,如果是mov edx,[XXX] 那么程序会自动将[]去掉,变成 mov edx,xxxx 所以要这样写 mov edx,xxxx mov edx,[edx]

这样我们来选中怪后被选中的怪就会显示出血条,但是再继续选下一个怪时游戏又出错了,再改了一下代码,但是选中多次之后又出错,再继续修改了一下代码.测试好后将选怪的代码放到GameProc.h头文件里,方便以后调用.

随笔:写代码要经过多次的测试,一个小挂都是需要很长时间的各方面测试才能成熟, 2.5.1、普通攻击CALL关键代码分析 a、更新游戏选怪基址

b、分析攻击CALL关键代码

c、汇编指令与应高级语言对照翻译

28

[59Ec688]+1530 //当前选中怪ID//对象数组下标 //写入怪下标 =0000FFFF 时未选中怪 =对象数组下标

[i*4+59E6748] //0599a110对象数组基址 OK +C: 在对象数组中下标值

//打怪后访问 怪ID的 代码地址 44f625/45ed58/45edbe/ //44f625//45ed58//45edbe //打怪CALL

mov ecx,[59EC688] CALL 0045ED40

代码注入器测试代码 //先选中怪物 mov ecx, 59Ec688 mov ecx,[ecx] call 0045ED40

游戏更新了,所以再次查找基址.首先还是打开CE,因为我们知道在游戏当中如果没有选中怪则是0000FFFF,选中了会变化,所以我们就按照这样的方法搜索几次就找到了,再查找一次地址访问就找到了新的基地和地址了.

当我们按下攻击按钮的时候,发现了几个新的地址,在0044F625这里向上和下看,经过几次分析,发现了一个可能CALL, 也就是call 00460430,但是经过测试之后却不是,向上看函数的头部有许多的参数,所以又返回上一层,call 0045ED40 发现这里是对的. 随笔: 找CALL对我来说还是比较熟的,呵呵. 2.5.2、挂机打怪功能

1、更新选怪CALL地址 2、优化代码结构 3、自动选怪代码编写 4、自动打怪代码编写 5、代码测试 参考 2.5.1

[59Ec688]+1530 //当前选中怪ID//对象数组下标 //写入怪下标 =0000FFFF 时未选中怪 =对象数组下标

[i*4+59E6748] //0599a110对象数组基址 OK curRoleBase=0x59Ec688//当前角色基址 curListBase=0x59E6748//当前对象列表基址 1、更新选怪CALL地址 写入 [59Ec688]+1530

hw [59Ec688]+1530 //hw OD硬件断点 代码注入器测试代码 //先选中怪物 mov ecx, 59Ec688 mov ecx,[ecx] call 0045ED40

VOID CALLBACK TimerProc(

HWND hwnd, // handle of window for timer messages UINT uMsg, // WM_TIMER message UINT idEvent, // timer identifier DWORD dwTime // current system time );

再重新找一次地址,为了方便写代码,我们将角色基址和对象列表地址定义两个常量值, 用OD加载游戏,下硬件断点hw [59ec688]+1530,找到游戏中的地址后,打开前面的代码,将定义的常量替换原来的地址,在GameDll.cpp中具体代码如下: /********************郁金香灬老师***************** *********************QQ:150330575****************/ void SelMon(); //选怪功能 void BeatMon();//打怪功能

//#define 这样定义是直接将数值写入程序,是个命令宏,如果用int来定义可以取地址 #define CurRoleBase 0x59Ec688 //当前角色基址 #define CurListBase 0x59E6748 //当前对象列表基址 #define BeatMonCall 0x0045ED40 //普攻打怪CALL ////////////////Timer ID ////////////////

#define TimerSel_ID 116//自动打怪的时间控制定义1 #define TimerBeat_ID 118//自动打怪的时间控制定义2 void SelMon() //选怪功能

{ // TODO: Add your control notification handler code here //遍历 [i*4+CurListBase] 数组 //+8 :有可能是对象分类 怪是2E

29

//+C :数组下标

//+31C:到当前玩家距离 //+380:怪死亡 <>0

_asm//放一个特征码便于查找 {

mov eax,eax mov eax,eax }

int* b8,*bc,*b380,*p1530;//定义偏移的变量 float *b31c;//浮点坐标 int* pb,*p2; //遍历周围的怪

for (int i=CurListBase;i<(CurListBase+0x0FFF*4);i+=4)//每次增加4字节 { pb=(int*)i;

b8=(int*)(*pb+0x8); bc=(int*)(*pb+0xc);

b31c=(float*)(*pb+0x31c); b380=(int*)(*pb+0x380);

//if (([ecx+8]==0x2E )&&([ecx++0x31C]<=100)&&([ecx+380]==0)) p1530=(int*)CurRoleBase; p1530=(int*)(*p1530+0x1530);

if ((*b8==0x2E )&&(*b31c<=100)&&(*b380==0)) {

//选怪[[CurRoleBase]+1530 ]=*bc;优化改进 显示怪血条 p2=pb;

//显示血条,设置怪选中状态 //selmonbase怪对象基址 int selmonbase=*p2; if (*p1530==0xFFFF) { _asm {

mov edi,selmonbase mov eax,[edi] push 0 push 1 push 0x44c mov ecx,edi mov eax,[eax+4] call eax }

} //end if

p1530=(int*)CurRoleBase; p1530=(int*)(*p1530+0x1530); *p1530=*bc;//写入下标 return ; } // end if }//end for }

//普攻打怪,上节课找出的打怪代码 void BeatMon() {

_asm {

mov ecx,CurRoleBase mov ecx,[ecx]

mov eax,BeatMonCall call eax } }

然后还需要添加一个定时器,在WGForm.cpp中添加代码,时间函数的定义在上面 void CWGForm::OnChkAutoselmon() {

UpdateData(true); if (m_bautoselmon){

SetTimer(TimerSel_ID,2000,&AutoSel);//每2秒自动执行一次 } else {KillTimer(TimerSel_ID);} }

30

百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库郁金香VC++初级和中级篇, 最全的手记及琢字翻译(6)在线全文阅读。

郁金香VC++初级和中级篇, 最全的手记及琢字翻译(6).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.77cn.com.cn/wenku/zonghe/561020.html(转载请注明文章来源)
Copyright © 2008-2022 免费范文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ: 邮箱:tiandhx2@hotmail.com
苏ICP备16052595号-18
× 注册会员免费下载(下载后可以自由复制和排版)
注册会员下载
全站内容免费自由复制
注册会员下载
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: