52.x86游戏实战-XXX获取房间坐标

2024-08-31 01:52

本文主要是介绍52.x86游戏实战-XXX获取房间坐标,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

本次游戏没法给

内容参考于:微尘网络安全

工具下载:

链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd=6tw3

提取码:6tw3

复制这段内容后打开百度网盘手机App,操作更方便哦

上一个内容:51.x86游戏实战-XXX返回城镇的实现

上一个内容里把返回城镇和副本内瞬移地图搞好了,接下来找一下当前角色所在副本中的哪个房间里,这样就能定位我们的位置

找位置的方式,首先打开游戏打开CE并附加到游戏,然后上上个内容里知道了副本内地图的分布方式(x、y),x和y都是从0开始,所以进入副本,使用CE搜索0,然后切换地图让它修改x或y的值,比如x变成1了,那就使用CE再搜索1,直到留下几个地址为止

下面开始实际操作

打开CE并附加游戏

然后游戏中进入副本,然后输入0点首次扫描

扫描出的结果有很多

然后在副本中移动到下一个地图,然后输入1然后点再次扫描,下图是点完再次扫描之后截的

然后再次在副本中切换地图(移动到x为2的地图),然后输入2然后点再次扫描,下图是点完再次扫描之后截的

然后再次在副本中切换地图(移动到x为3的地图),然后输入3然后点再次扫描,下图是点完再次扫描之后截的,这里剩下的就很少了

然后经过多次切换地图最终剩下三个,然后下图红框圈出来的地址,它的值变化的比较慢,所以直接把它当做是一个没用的值

然后就剩下下图红框的两个地址,这俩地址用哪个都是,可以都看看,哪个好找用哪个

然后接下来就用到硬件断点了,然后这个游戏就检测,所以先过一下检测,下图红框过检测,过检测在34.x86游戏实战-XXX过检测代码分析里写了

然后打开OD并附加到游戏,然后输入下图红框里的内容,然后按回车(Enter键)

可以看到它下一个位置也是1,在经过观察所在地图的坐标,可以猜测0x60767E00是x坐标,0x60767E04是y坐标

然后鼠标右击下一个硬件访问断点

然后断下来,ESI+0x610位置访问了x坐标

然后取消断点

然后在下图红框位置输入esi+0x610,然后按回车键,可以看到内存区没有变化,这说明esi+0x61确实是地图的x坐标

然后继续找看看esi的值哪来的,然后往上翻,看下图红框位置是最近一次赋值

然后在下图红框位置打断点,断点住之后输入绿框位置的内容并且按回车键

然后这里游戏掉线了,所以坐标的地址与之前不一样了,但是可以确认 [esi+0x8C]+0x610 是副本地图的x坐标

然后接下来继续找esi的值哪来的,往上翻(翻之前记得双击取消断点),然后看到下图红框位置是最近一次的赋值,esi的值来自于eax,然后mov esi,eax上一行是call eax调用了一个函数,eax寄存器一般用于接收函数的返回值,所以eax的值来自于call eax的返回值

然后在下图红框位置打断点

断点之后按F7,按F7之前记得双击地址取消断点进入call eax,然后发现它里面是ecx+0x14

然后断点住的过程在下图红框位置输入dd [[ecx+0x14]+0x8C]+0x610,可以看到它还是副本地图的x坐标

然后ecx的值来自于esi,esi的值来自于eax

然后eax来自于0x752980函数,然后在下图红框位置打断点,断点住之后按F7,进入0x752980函数

进来,然后一路F8看它走到了下图红框位置

然后执行了jmp直接就来到下图位置,这个函数就没法找了,所以这条路线算是找不到基址了

然后现在可以得到副本内x的坐标,然后再次下硬件访问断点,看看还有没有别的位置访问它,尝试别的位置取追

然后看还有下图红框位置访问地图的x坐标,这里也访问了y坐标,然后尝试在这里追

然后看到最终esi的值来自于eax+0x8C,然后eax的值来自于call eax

然后在下图位置打断点,看看call eax里面的逻辑

然后取消断点之后按F7,看到是ecx+0x20A050

然后在下图红框位置写dd [[ecx+0x20A050]+0x8C]+0x610看看对不对,它的值是对的,所以接下来找ecx的值

然后ecx的值来自于0x1A5FB18

然后在下图红框位置写 dd [[[0x1A5FB18]+0x20A050]+0x8C]+0x610,然后这样就得到x和y的地址了

然后写到C++代码里

首先添加两个变量,如下图红框

然后写下图的内容

然后重新编译

重新编译完使用wctool.exe注入,然后使用Dbgview.exe观察,正常显示,人物在下图红框位置坐标正好是x的值是1,y的值是0

MyStrust.cpp文件的内容:修改InitMy函数

#include "pch.h"
#include "MyStrust.h"void MyStrust::InitMy()
{//  [[0x1AB7CDC]+0x258] 名字/**这个符号表示地址,在c++中被称为指针或指针类型int表示4字节数字int*就表示指针类型的int(int*)0x1AB7CDC;这样表示0x1AB7CDC地址里的内容是4字节的数字*/int* address = (int*)0x1AB7CDC;/*取出地址中的值,也就是取出0x1AB7CDC里的内容*address这样在左边只写一个*表示取内存地址里的值也就是取address它的值,address是0x1AB7CDC,也就是取0x1AB7CDC它的值*/int addressValue = *address;/*(*(int*)addressValue)意思是把addressValue转成int*,也就是把addressValue的值当成内存地址,addressValue的值现在是[0x1AB7CDC]+0x258这个现在这个地址里面的值是名字的地址,所以在左边加了一个*让把名字的地址去除了出来取出来之后就得到了名字,名字是UNICODE类型,UNICODE又被称为宽字节,宽字节的数据是用两个字节描述一个文字或字母在c++里wchar_t类型就是UNICODE然后在c++中名字这种数据被称为字符串,如果要用字符串必须用指针类型也就是wchar_t*右边加上*让wchar_t变成指针类型的wchar_t,才能在c++中使用字符串*/this->My.Name = (wchar_t*)(*(int*)(addressValue+0x258));// 一般函数名后面是W就表示有UNICODE,也就是要用宽字节// OutputDebugStringW(this->My.Name);// L""这两个"之间表示字符串,L""表示这个字符串是宽字节(使用Unicode编码)call_logW(L"wetool:人物姓名=%ws,测试=%ws", this->My.Name,L" 52am");//  [[0x1AB7CDC]+0x18C]x坐标//  [[0x1AB7CDC]+0x190]y坐标/*取出地址中的值,也就是取出0x1AB7CDC里的内容*address这样在左边只写一个*表示取内存地址里的值也就是取address它的值,address是0x1AB7CDC,也就是取0x1AB7CDC它的值*/this->My.X= *(float*)(addressValue + 0x18C);this->My.Y = *(float*)(addressValue + 0x190);char buf[256] = { 0 };// 拼接文字,%f表示拼接一个小数(单浮点数)sprintf(buf, "wetool:x=%f;y=%f", this->My.X, this->My.Y);OutputDebugStringA(buf);// [[0x1AB7CDC]+0x36A0]血量this->My.Blood = *(int*)(addressValue + 0x36A0);// 拼接文字,%d表示拼接一个整数(32位的整数)sprintf(buf, "wetool:血量 = %d", this->My.Blood);OutputDebugStringA(buf);My.RoomX = ReadDword(ReadDword(ReadDword(ReadDword(0x1A5FB18) + 0x20A050) + 0x8C) + 0x610);My.RoomY = ReadDword(ReadDword(ReadDword(ReadDword(0x1A5FB18) + 0x20A050) + 0x8C) + 0x614);call_logA("wetool:副本内x坐标:%d,副本内y坐标:%d", My.RoomX, My.RoomY);
}void MyStrust::UseObject(DWORD object)
{object += 3; // 背包物品序号/*try的作用如果__asm {pushadpush objectmov ecx, 0x1A5FB24 // 背包基址mov ecx, [ecx]mov eax, 0x7B9130 // 使用物品的函数地址call eaxpopad}这个代码运行过程中出现错误了,我不会让游戏崩溃,出现错误之后会执行catch (...) {OutputDebugStringA("MyStrust::UseObject error");}这个catch里面的代码,现在也就是执行OutputDebugStringA("MyStrust::UseObject error");这一行*/try { __asm {pushadpush objectmov ecx, 0x1A5FB24 // 背包基址mov ecx, [ecx]mov eax, 0x7B9130 // 使用物品的函数地址call eax popad}}catch (...) {OutputDebugStringA("MyStrust::UseObject error");}
}void MyStrust::ChangeBlooad(int v)
{try {__asm {pushadpush 0push 0push 0push vmov ecx, 0x1AB7CDC // 里面有我们玩家角色数据的基址mov ecx, [ecx]mov eax, 0x8174E0 // 修改血量的函数地址call eaxpopad}}catch (...) {OutputDebugStringA("MyStrust::ChangeBlooad error");}
}void MyStrust::NewChangeBlooad(DWORD nEcx)
{try {__asm {pushadpush 0push 0push 0push 0mov ecx, nEcxmov eax, 0x8174E0 // 修改血量的函数地址call eaxpopad}}catch (...) {OutputDebugStringA("MyStrust::NewChangeBlooad error");}
}// 遍历怪物列表函数,加吸怪
void MyStrust::FindMaster()
{wchar_t* Tmp1;/* [[[[[0x1A5E258]+3*4+0xA8]+0x14]+0x88]+0x10]下方 ReadDword 函数通过 [[[[[0x1A5E258]+3*4+0xA8]+0x14]+0x88]+0x10] 这个取值算法得到附近列表(怪物列表)*/DWORD Tmp = ReadDword(ReadDword(ReadDword(ReadDword(ReadDword(0x1A5E258) + 0x3 * 4 + 0xA8) + 0x14) + 0x88) + 0x10);if (Tmp != 0) {// 如果是0说明没有找到怪物列表for (size_t i = 0; i < 100; i++)// 这里的100是随便写的{if (ReadDword(Tmp + i * 4)>0 && (ReadDword(ReadDword(Tmp + i * 4) + 0x90) == 0x211)) {//if (ReadDword(Tmp + i * 4)>0) {Tmp1 = (wchar_t*)ReadDword(ReadDword(Tmp + i * 4) + 0x258); // 0x258位置是名字if (Tmp1 == 0) {// 如果是0说明没有名字//call_logW(L"wetool:NULL\n");this->masterNum.Name[i] = L"";}else {/*打印名字到 Dbgview.exe,其中 wetool这个是为了过滤 Dbgview.exe打印的一些跟我们不相关的日志*///call_logW(L"wetool:%ws\n", Tmp1);this->masterNum.Name[i] = Tmp1;}// 血量与玩家角色不是一个位置,可以在修改血量的位置追,这个不重要,后面有机会再找//masterNum.Blood[i] = ReadDword(ReadDword(Tmp + i * 4) + 0x90); this->masterNum.type[i] = ReadDword(ReadDword(Tmp + i * 4) + 0x90);this->masterNum.x[i] = ReadFloat(ReadDword(Tmp + i * 4) + 0x18C);this->masterNum.y[i] = ReadFloat(ReadDword(Tmp + i * 4) + 0x190);this->masterNum.x[i] = this->My.X;this->masterNum.y[i] = this->My.Y;this->masterNum.Object[i] = ReadDword(Tmp + i * 4);*(FLOAT*)(ReadDword(ReadDword(Tmp + i * 4) + 0xA8) + 0xC) = this->My.X; // 修改之后会瞬移的坐标,把它的值赋值成我们玩家的坐标*(FLOAT*)(ReadDword(ReadDword(Tmp + i * 4) + 0xA8) + 0x10) = this->My.Y; // 修改之后会瞬移的坐标,把它的值赋值成我们玩家的坐标call_logW(L"wetool:第%d个对象:%x 怪物名字:%ls type:0x%x x:%f y:%f", i, this->masterNum.Object[i], this->masterNum.Name[i], this->masterNum.type[i], this->masterNum.x[i], this->masterNum.y[i]);}}}else {call_logA("wetool:Tmp error");}
}// 吸怪加秒杀
void MyStrust::AllKill()
{try {this->InitMy();this->FindMaster();for (size_t i = 0; i < 100; i++){if (this->masterNum.Object[i] > 0 && (this->masterNum.type[i] == 0x211)) {call_logW(L"wetool:AllKill-第%d个对象:%x 怪物名字:%ls type:0x%x x:%f y:%f", i, this->masterNum.Object[i], this->masterNum.Name[i], this->masterNum.type[i], this->masterNum.x[i], this->masterNum.y[i]);this->NewChangeBlooad(this->masterNum.Object[i]);// 调用修改血量的函数}}}catch (...) {OutputDebugStringA("MyStrust::AllKill error");}
}void MyStrust::StartIn()
{try {__asm{pushad// 切换地图push 0x26mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1127D60call eaxpush 0xEmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128550call eaxpush 0x2mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128550call eaxpush 0x1Emov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128580call eaxpush 0x10Fmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128580call eaxpush 0x5mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128550call eaxpush 0xEmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128580call eaxpush 0x1mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128580call eaxmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1127EC0call eax// 进入副本选择界面push 0xFmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1127D60call eaxmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1127EC0call eax// 进入副本push 0x10mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1127D60call eaxpush 0x68mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128580call eaxpush 0mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128550call eaxpush 0mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128550call eaxpush 0mov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1128550call eaxmov eax, 0x1127EC0call eaxpopad// 进入副本选择界面pushadpush 0xFmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1127D60call eaxmov ecx, 0x1AEB6E4mov ecx, [ecx]mov eax, 0x1127EC0call eaxpopad}}catch (...){OutputDebugStringA(" MyStrust::StartIn error");}}void MyStrust::MoveInMap(DWORD x, DWORD y)
{try {DWORD nEcx = *(DWORD*)0x1AEB6E4;__asm {pushadpush 0x30mov ecx, nEcxmov eax, 0x1127D60call eax// 这里的0x2它是地图x的数据push xmov ecx, nEcxmov eax, 0x1128550call eax// 这里的0x1它是地图y的数据push ymov ecx, nEcxmov eax, 0x1128550call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x11285B0call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x11285B0call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x1128550call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x1128580call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x1128580call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x1128580call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x1128580call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x1128580call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x11285B0call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x11285B0call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x11285B0call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x11285B0call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x1128580call eax// 入参没用push 0x0mov ecx, nEcxmov eax, 0x11285B0call eaxmov ecx, nEcxmov eax, 0x1127EC0call eaxpopad}}catch (...) {OutputDebugStringA(" MyStrust::StartIn error");}}void MyStrust::ComeBackTwon()
{try {DWORD nEcx = *(DWORD*)0x1AEB6E4;__asm {pushadmov ecx, 0x1A3CBF4mov ecx, [ecx]push 0x138Dmov eax, 0x4E9740call eaxpopad}}catch (...) {OutputDebugStringA(" MyStrust::ComeBackTwon error");}
}

MyStrust.h文件的内容:修改 Myself结构体

#pragma once
struct Myself {DWORD Blood;// 血量FLOAT X; // x坐标FLOAT Y; // y坐标wchar_t* Name; // 名字DWORD RoomX; // 副本内的x坐标DWORD RoomY; // 副本内的y坐标
};struct Master {DWORD Object[100];DWORD Blood[100];FLOAT x[100];FLOAT y[100];wchar_t* Name[100];DWORD type[100];
};class MyStrust
{
public:Myself My;Master masterNum;void InitMy();// 玩家角色基本信息(血量、名字、坐标)void UseObject(DWORD object); // 修改血量void ChangeBlooad(int v); // 使用物品void NewChangeBlooad(DWORD nEcx);void FindMaster();// 遍历怪物void AllKill(); // 吸怪加秒杀void StartIn();// 秒进副本void MoveInMap(DWORD x, DWORD y); // 副本内瞬移void ComeBackTwon(); // 返回城镇
};

上方的代码不全,只有手写的代码

完整代码:以 51.x86游戏实战-XXX返回城镇的实现 它的代码为基础进行修改

链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg?pwd=q9n5

提取码:q9n5

复制这段内容后打开百度网盘手机App,操作更方便哦


img

这篇关于52.x86游戏实战-XXX获取房间坐标的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1122553

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

认知杂谈52

今天分享 有人说的一段争议性的话 I I 1拓展人脉很重要** 咱们活在这世上啊,得明白一件事儿,知识、逻辑能力和实战经验虽然重要,但确实都不是最关键的。真正关键的是要懂得怎么和那些手里有资源的人打交道。人脉那可真是一笔无形的大财富呢。你想想看,有时候一个有影响力的人帮你一把,那效果可比你累死累活干一年都强得多。 I I 就比如说,你要是认识个行业里的大牛,他可能给你介绍个特别好的工

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 (3)前端 二、开发模式 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 Validation:做参数校验Mybatis:做数据库的操作Redis:做缓存Junit:单元测试项目部署:springboot项目部署相关的知识 (3)前端 Vite:Vue项目的脚手架Router:路由Pina:状态管理Eleme