void CWGForm::OnChkAutobeatmon() {
UpdateData(true); if (m_bautobeatmon) {
SetTimer(TimerBeat_ID,1500,&AutoBeat);//每1.5秒执行一次 } else
{KillTimer(TimerBeat_ID);} }
这样就形成了一个完整的选怪打怪命令.
随笔:现在的小挂已经具有最初级的功能,可以让人物自动打怪,记的以前有的一些免费挂就这样一个功能,就会受到很多网友的欢迎了,毕竟每个怪都用鼠标或键盘来打的话实在是太累人了. 2.5.3、物品背包数组基址+偏移分析(CE+OD) a、确定突破口 b、回溯基址 c、用OD验证
d、推导出基址+偏移公式 CE查找 物品数量 222
[45B3AAC]=[059E7024]=0d80F548 物品背包数组(基址0d80F548)(0): +4 物品对象(1)
+8 物品对象(2)+0*4+3d8(相对基址271e1750): +??
+4a0 物品数量:int偏移271E1BF0 +?? 物品名称:char * +?? 功能说明:char *
006799E1:mov ecx,[edx+eax*4] 00576E15:mov eax,[edi+esi*4+3d8] 00577121:mov ecx,[edi+esi*4+3d8]
一级基址:[45B3AAC]=[059E7024]=0d80f548 +i*4+3d8 +4a0
dd [[059E7024]+i*4+3d8] //数组 dc [[45B3AAC]+6*4+3d8]+58 +58 //物品名字 char * +4a0 //物品数量
找背包,一般是从物品数量为突破口,因为数量为一个很精确的值,这样找起来很方便,找到数量后也可以顺着找出物品的其它属性.用CE找金创药数量,吃下再找就出来了.下内存访问查找基址,发现上级偏移是271E2F18,在CE里搜索这个16进制数,发现了一个绿色基址,但感觉不对,我们找另外的两个地址,用CE查找访问,需要找的是带有数组的汇编代码:006799e1 mov ecx,[edx+eax*4].一不小心游戏出错了,用CE再来查找一次. [attachment=567] 再向上就找到了基址 [attachment=568]
一级基址:[45B3AAC]=[059E7024]=0d80f548 这个公式就是dd [[059E7024]+i*4+3d8]
打开OD来到这个地址处,找到了其它的偏移信息 +58 //物品名字 +4a0 //物品数量
最后将特征码复制出来以方便下次查找 背包数组 esi为下标
LEA EAX,DWORD PTR DS:[ESI+ESI*8] LEA EDX,DWORD PTR DS:[EBX+ESI*4+3D8] PUSH EDI
MOV DWORD PTR SS:[EBP+8],EDX
LEA ECX,DWORD PTR DS:[EBX+EAX*4+5B4] MOV DWORD PTR SS:[EBP-14],ECX MOV EDX,DWORD PTR SS:[EBP+8] MOV ESI,DWORD PTR DS:[EDX] TEST ESI,ESI
2.5.4 、使用指定物品 UseGoods(int index=0); a、算法原理
b、返回物品在背包中的下标 int GetGoodsIndex(char* name); c、useGoods(GetGoodsIndex(\金创药(小)\参考 2.2.2 来更新 物品使用CALL 005e47a4:
MOV EDX,DWORD PTR DS:[EAX+208] PUSH EDX //物品背包下标 PUSH 1 PUSH 0
31
CALL 0057FF10
参考 2.5.3 来更新 背包数组基址 dd [45BA62C]+0*4+3d8 +58 //物品名字 char * +4a0 //物品数量
8. int memcmp(c*****t void *s1, c*****t void *s2, size_t n) 功能 : 对内存中两个字符串进行大小写敏感的比较; 返回值 : s1 == s2 return 0 s1 > s2 return 1 s1 < s2 return -1 原理
///////////函数实现部分
c*****t int GoodsBase=0x45BA62C;
int GetGoodsIndex(c*****t char* name)//获取物品下标 {
char * CurGoodName; int iaddr;
for (int i=0;i<35;i++) // 0..34 {
iaddr=i*4; _asm {
mov ecx,GoodsBase;
mov ecx,[ecx] //mov ecx,[0x45BA62C] add ecx,iaddr // ecx,[0x45BA62C]+i*4
add ecx,0x3d8 // ecx,[0x45BA62C]+i*4+3d8 mov ecx,[ecx] // ecx,[[0x45BA62C]+i*4+3d8]
mov iaddr,ecx //物品对象iaddr=[[0x45BA62C]+i*4+3d8] }
if (iaddr>0) _asm {
mov ecx,iaddr // ecx=[[0x45BA62C]+i*4+3d8] add ecx,0x58 // ecx =[[0x45BA62C]+i*4+3d8]+58
mov CurGoodName,ecx //CurGoodName=[[0x45BA62C]+i*4+3d8]+58 }
if (memcmp(name,CurGoodName,strlen(name))==0) return i; } //end for
return 0;//遍历背包 未找到指定物品 }//end GetGoodsIndex;
c*****t int UseGoodsCallBase=0x0057FF10 void UseGoods(c*****t int index) { _asm {
PUSH index //物品背包下标 PUSH 1 PUSH 0
mov edx,UseGoodsCallBase CALL edx// } }
先测试一下使用物品CALL,然后编写代码遍历背包通过物品名称来识别物品,先写汇编代码读出物品对象,然后再通过对象找出物品名称 int GetGoodsIndex(c*****t char* name)//获取物品下标 {
char * CurGoodName;//物品名称 int iaddr;//格子
for (int i=0;i<35;i++) // 0..34一共35个背包格子 {
iaddr=i*4;//格子向下偏移 _asm
{ //取得物品对象
mov ecx,GoodsBase;
mov ecx,[ecx] //mov ecx,[0x45BA62C] add ecx,iaddr // ecx,[0x45BA62C]+i*4
add ecx,0x3d8 // ecx,[0x45BA62C]+i*4+3d8
32
mov ecx,[ecx] // ecx,[[0x45BA62C]+i*4+3d8]
mov iaddr,ecx //物品对象iaddr=[[0x45BA62C]+i*4+3d8] }
if (iaddr>0) _asm
{ //取得物品名称
mov ecx,iaddr // ecx=[[0x45BA62C]+i*4+3d8] add ecx,0x58 // ecx =[[0x45BA62C]+i*4+3d8]+58
mov CurGoodName,ecx //CurGoodName=[[0x45BA62C]+i*4+3d8]+58 }
if (memcmp(name,CurGoodName,strlen(name))==0) return i;//如果找到物品则真 } //end for
return 0;//未找到物品则假
找到了物品之后还需要使用物品功能
c*****t int UseGoodsCallBase=0x0057FF10;//物品使用CALL 基址 void UseGoods(c*****t int index) { _asm {
PUSH index //物品背包下标 PUSH 1 PUSH 0
mov edx,UseGoodsCallBase CALL edx }
使用时是这样调用的
void CWGForm::OnBUTTONusegoods() {
UseGoods(GetGoodsIndex(\人参\}
《》2.5.5 tabCtrl关联控件变量: m_tabmain
#include \#include \
#include \CPAG_GJ page_gj;
CPAGE_SAFE page_safe;
CPAGE_TESTCALL page_testcall; m_tab.InsertItem(0,\ m_tab.InsertItem(1,\
p1.Create(IDD_PAG1,GetDlgItem(IDC_TAB1)); p2.Create(IDD_PAG2,GetDlgItem(IDC_TAB1)); switch(m_tab.GetCurSel()) {
case 0: {
p1.ShowWindow(true); p2.ShowWindow(false); break; }
case 1: {
p1.ShowWindow(false); p2.ShowWindow(true); break; } default: {
break; } }
在DELPHI中增加控件编写程序是很容易的,但是在VC中控件就少很多不太容易,所以本节就是讲了VC中控件的应用.我们新建了TabCtrl控件,并新m_maintab变量,用于设置TabCtrl控件 m_tabmain.InsertItem(1,\测试\ m_tabmain.InsertItem(2,\挂机\ m_tabmain.InsertItem(3,\保护\
33
m_tabmain.InsertItem(5,\测试5\这样设置好之后就会出现TabCtrl的选项了
这样标签已经上去了,但是里面的按钮怎么放上去呢?这时我们就要插入资源,然后选择Dialog对话框,选择一个比较大的页面(第5个),有几个标签就插入几个资源.但是这样也不能添入到各个标签中,还需要新创建一个类,创建完类之后还要定义头文件?? 这些代码我实在是搞不懂了??
这节课笔记都不太好记了,因为老师也出错了好几次? 然后又写了一个结构
switch(m_tab.GetCurSel()) ??
就这样的一个简单的功能,竟然要编写这么多代码和设置 [attachment=572]
我承认这节课我的笔记记的很不好,但是太不好记了,我已经尽力了. 2.5.6、TabCtrl控件BUG修证(VC++基础好的可跳过) a、修证乱码 b、修证对齐
c、局部美化(位置大小调整) //删掉有乱码的窗口资源 GetCurSel() ? ?
继续上节课,修改了几个显示错误的TAB控件,在代码里分别设置5个页面,在许多地方添加了许多代码之后,终于做好了这个TAB控件,目地就是每次单击Tab控件的时候,就通过GetCurSel函数来设置面板上的各个页面来显示控件.经过多次的调整最终效果如下: [attachment=573] 补充说明
http://bbs.yjxsoft.net/read.php?tid-2249.html 2.5.7、捡物功能分析实现
a、捡物功能CALL分析 b、捡物CALL参数分析
c、测试及封装到pickgoods()函数
参考2.5.1 更新普通攻击CALL 地址为:004603C0 找捡物CALL 思路:
第一种:1、先找F1-F10技能栏数组(DWORD)(4字节)
2、把捡物动作放到F10上(其它的快捷栏也可以)
3、对F10技能栏下内存访问断点(因为在按下F10技能栏时,游戏本身会去访问它,以读出相应栏究竟是放的,物品/技能/动作) 4、断下来的地址,其它之一肯定就是捡物CALL附近的地址,通过分析一般能找出捡物CALL(参考2.5.1) 第二种:通过普攻CALL来回溯分析
1、因为普攻 和捡物 属于同一类的 动作 大部分程序员会把它放在一个大的CASE里边 如:switch(动作号) //前面下断
{ case 普攻ID:{调用普攻CALL} case 捡物ID:{相应CALL功能} case 打坐ID:{相应CALL功能} case 走跑ID:{相应CALL功能} case 逃脱ID:{相应CALL功能} case 组队ID:{相应CALL功能} case 交易ID:{相应CALL功能} //......... default: }
访问 选中怪ID
打怪CALL 上级CALL //普攻
mov ecx,59F3238//当前角色基址 mov ecx,[ecx] CALL 0045ECE0 ///捡物
mov ecx,59F3238//当前角色基址 mov ecx,[ecx] CALL 0045EEE0 //打坐功能 CALL 005E37C0
捡物有两种思路,首先是通过技能拦,所以我们要查找技能拦数组,因为我们之前已经找到技能拦的调用了,所以我们找第二种方法,就是直接调用捡物功能.
因为在游戏中各种动作都是一个分支语句,那么我们就先用OD附加游戏,来到普通攻击地址004603c0(以前找到的),那么我们再来到该CALL的上级看一下,就找到了一堆CASE语句了,那么我们一下子就将这里面这几个动作都找到了,然后经过测试也证实了我们的猜想. [attachment=574]
代码分析完后,我们打开VC编写代码来调用这几个功能CALL.
34
void PickGoods()//捡物功能 {
_asm {
mov ecx,CurRoleBase //当前角色基址 mov ecx,[ecx]
mov eax,PickGoodsCall call eax } }
修改了多处错误,又发现360在干扰我们的DLL注入,最终调用成功. 2.5.8:F1-F10技能数组分析
a、F1-F10技能栏数组(基址+偏移) b、F1-F10功能调用核心代码分析 1、打开游戏
DWORD F1_F10;//10*4字节 //00FF1,00ff2,00ff3 5*4字节为0
2、移动一个物品对象(技能对象) 到F1技能栏 数值>0
3、移出物品对象。
数值=0 扫描类型(精确数值=0) 4、移动人物
走上几部 ,其它数据发生变化,但F1=0 5、再次移动物品对象至F1栏上 数值>0 扫描类型(大于) 6、扫描 未更新的数值 7、移出物品对象 扫描 精确数值0
8、查找访问该地址的代码:
0057a14c/0057a2b6/0057a500/005e271d/005e2737/0057fd44/ mov eax,[edi+esi*4+3d8] [edi+3d8+esi*4] //esi下标 //edi+3d8 数组基址 005e271d
mov ecx,[ecx+ebx*4+3d8] ecx=[45BC28C]
dd [[45BC28C]+0*4+3d8] //显示F1对象
dd [45BC28C]+0*4+3d8 //显示F1-F10对象数组 F1-F10关键 核心代码地址 005E462c/005e46b8
这节课要找的是游戏中的技能拦数组,在技能拦上如果有技能则是非0的值,没有技能应该是0, 这样在CE里搜索,如果搜索到的数值非常多,那么就在游戏里移动一下,多次之后就找到了几个地址,首先看一下第一个地址 [attachment=577]
发现还有其它地址也像,又搜索了一个 [attachment=578]
然后用OD附加游戏,在各个地址间查看,挑一下看哪个地址比较好找些.005e2717这个好. [attachment=579]
最终找到的就是这个值,详细记录都在上面教案中 dd [[45BC28C]+0*4+3d8] //显示F1对象
dd [45BC28C]+0*4+3d8 //显示F1-F10对象数组 2.5.9、F1-F10功能CALL a、找出真的功能CALL
b、F1-F10功能CALL参数分析
c、F1-F10功能CALL测试(集成功能至GameProc.h) 参考2.5.8
dd [[45BC28C]+0*4+3d8] //显示F1对象
dd [45BC28C]+0*4+3d8 //显示F1-F10对象数组 F1-F10关键 核心代码地址 005E462c/005e46b8
void F1_F10( int index=1) { index=index-1; _asm {
mov ecx,[0x144c590] push index
mov ecx,[ecx+0x23c]
mov eax,0x005e4610 //eax,ebx,edx,edi,esi
35
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库郁金香VC++初级和中级篇, 最全的手记及琢字翻译(7)在线全文阅读。
相关推荐: