60.网游逆向分析与插件开发-游戏增加自动化助手接口-游戏公告功能的逆向分析与测试

news2025/4/8 19:04:47

内容来源于:易道云信息技术研究院VIP课

上一个内容:文字资源读取类的C++还原-CSDN博客

码云地址(master分支):https://gitee.com/dye_your_fingers/sro_-ex.git

码云版本号:878db7708de09b448010ef54526fe615bdc4a994

代码下载地址,在 SRO_EX 目录下,文件名为:SRO_Ex-游戏公告功能的逆向分析与测试.zip

链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg

提取码:q9n5

--来自百度网盘超级会员V4的分享

HOOK引擎,文件名为:黑兔sdk.zip

链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw

提取码:78h8

--来自百度网盘超级会员V4的分享

以 文字资源读取类的C++还原-CSDN博客它的代码为基础进行修改

游戏中的公告弹框:接下来就去找它,然后封装到c++类里面

首先它弹框的时候肯定会读取字符串,所以通过 Cheat Engine 搜索 中间有障碍物 这个关键字,然后就找到了四个地址:

为了确定哪一个是,对它们的值进行修改,它显示的内容对应第四个地址

然后找出是什么访问了它

然后有这么些

然后记入详细信息

然后打开x96dbg,然后在71DE07位置下一个条件断点,如下图条件

然后回到游戏,再次触发

然后ctrl + f9  再按f8,来到上一层

然后再来到上一层

这里游戏掉线了,导致eax的值变了,下图是重新登陆之后的值 

继续来到上层,在882CB8位置打断点,研究一下

它停下来的,并且没有其它位置调用,然后下图红框位置的值改成14B2F088

然后就变成了 有障碍物。。。

游戏中也正常显示,现在这里有两种可能性,一种是eax这个函数是用来读取数据或者组装数据的,一种是显示数据

这里游戏又断开连接了,下方是从新连接之后的

把eax这个函数开头写成ret 4,看看是否还会正常显示

 它可以正常显示,但显示的内容,好像不一样

把eax改的开头恢复,就会显示通过Cheat Engine改的数据,所以eax这个函数是用来处理字符串的,所以eax函数只是显示功能中的一环

然后调用eax函数的函数很大,这时就很麻烦,然后理一下思路,首先eax函数是处理数据,然后它下面就肯定有显示 或者 管理 或其它的,正常来讲这么复杂的东西,一定会封装成一个函数,就是在游戏里要显示公告,每次都要写处理数据显示公告的代码,很显然不可能,所以它一定会封装成函数,通过给函数传参数来显示公告,

所以接下来要看eax在什么地方来的:

熟悉的代码,上一个内容里,对它进行了还原(sro_string结构体)

通过下方也可以看出是,上一个内容中还原的sro_string结构体,并且它是传递进来的

然后也就是说 882C80函数,完整了,字符串的处理与显示弹框功能,也就是上面说的那个封装

然后看一下它的上一层是怎样调用的

下图红框的返回,是ret 8,所以它有两个参数,也就是push 1,push 23,是它的参数,然后push eax是882C80函数的参数,也就是我们的sro_string结构体,98F3A0函数的返回值是一个类对象,因为调用完它紧接着是mov ecx, eax,在调用函数之前给ecx复制是thiscall,也就是调用一个类函数的写法,add ecx, 370这种操作一般是继承的操作

然后再来到它的上一层,它通过1256E3C位置得到了一个类对象,然后push eax然后调用848580函数显示弹框,

然后再把848580函数开头,改成 ret 4看看游戏中是否还会显示弹框,效果就是显示不出弹框了,所以就找到了游戏中显示弹框的函数

通过模仿调用 0x848580 函数成功显示出公告弹框,使用通过获取游戏中的sro_string结构

使用自己创建的sro_string结构

GameEx.cpp文件的修改,修改了AutoHelper函数,AutoHelper函数是用来拦截自动药水设定按钮的

#include "pch.h"
#include "GameEx.h"
#include "htdHook2.h"
#include "GameProtect.h"
#include "extern_all.h"

extern int client;
extern GameProtect* _protect;
extern unsigned _stdcall GetFunctionAddress(int index);
htd::hook::htdHook2 hooker;

#include <windows.h>
#include<stdio.h>
#include<TlHelp32.h>

/**
  声明要拦截的函数地址
*/
auto h = GetModuleHandle(NULL);
DWORD address = (DWORD)h;
DWORD addRExit = address + 0x88C77E;

size_t 被拦截修改的函数的地址 = (size_t)addRExit;

LONG NTAPI 异常回调(struct _EXCEPTION_POINTERS* Excep)
{
    printf("异常回调1\n");

    /**
      判断出异常的地方是否为 我们修改的地方
    */
    if ((size_t)Excep->ExceptionRecord->ExceptionAddress == 被拦截修改的函数的地址) {

        //const char* szStr = "nei Rong Bei Xiu Gai";
        //*(DWORD*)(Excep->ContextRecord->Esp + 0x8) = (DWORD)szStr;
        //szStr = "biao Ti Bei Xiu Gai";
        //*(DWORD*)(Excep->ContextRecord->Esp + 0xC) = (DWORD)szStr;

        AfxMessageBox(L"游戏退出!");
        DWORD* _esp = (DWORD*)Excep->ContextRecord->Esp;
        DWORD _val = _esp[1];

        if (_val == 0x1035D0C) {
            AfxMessageBox(L"游戏退出2!");
            auto hMuls = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, L"system_seamp");
            if (hMuls) ReleaseSemaphore(hMuls, 1, 0);
            ExitProcess(0);
        }

        Excep->ContextRecord->Eip = *(DWORD *) Excep->ContextRecord->Esp;
        Excep->ContextRecord->Esp += 8;
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    else {
        /**
          防止被其它地方修改了函数地址
        */
        Excep->ContextRecord->Dr0 = 被拦截修改的函数的地址;
        Excep->ContextRecord->Dr7 = 0x405;
        return EXCEPTION_CONTINUE_SEARCH;
    }

}

VOID 设置线程的dr寄存器(HANDLE 线程句柄) {

    printf("设置线程的dr寄存器1\n");
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_ALL;
    GetThreadContext(线程句柄, &ctx);
    ctx.Dr0 = 被拦截修改的函数的地址;
    ctx.Dr7 = 0x1;
    SetThreadContext(线程句柄, &ctx);
    printf("设置线程的dr寄存器2\n");
}

VOID 使用dr寄存器拦截修改函数() {
    printf("使用dr寄存器拦截修改函数1\n");
    HANDLE 线程快照句柄 = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId());
    if (线程快照句柄 == INVALID_HANDLE_VALUE) {
        printf("线程快照创建失败");
        return;
    }

    THREADENTRY32* 线程结构体 = new THREADENTRY32;
    线程结构体->dwSize = sizeof(THREADENTRY32);

    /**
      Thread32First获取快照中第一个线程
       返回值bool类型
    */
    // Thread32First(线程快照句柄, &线程结构体);

    HANDLE 线程句柄 = NULL;

    printf("使用dr寄存器拦截修改函数2\n");

    /**
      Thread32Next获取线程快照中下一个线程
    */
    while (Thread32Next(线程快照句柄, 线程结构体))
    {
        if (线程结构体->th32OwnerProcessID == GetCurrentProcessId()) {
            printf("使用dr寄存器拦截修改函数3\n");
            线程句柄 = OpenThread(THREAD_ALL_ACCESS, FALSE, 线程结构体->th32ThreadID);
            printf("使用dr寄存器拦截修改函数4\n");
            设置线程的dr寄存器(线程句柄);
            printf("使用dr寄存器拦截修改函数5\n");
            CloseHandle(线程句柄);
        }
    }
}

bool AutoHelper(HOOKREFS2) {
    // 使用通过获取游戏中的sro_string结构
    //auto read = _pgamebase->SRO_Res->ReadTitle((wchar_t*)0xEBC968);
    // 使用自己创建的sro_string结构
    sro_string str;
    str.Ptitle = L"您还没有开通VIP服务,只能使用普通药水辅助功能,开通VIP可以使用更高级的自动化助手功能!";
    str.lenth = 47;
    str.size = 48 * 2 + 1;
    auto read = &str;
    unsigned* _ecx = (unsigned*)0x1256E3C;
    unsigned readEcx = _ecx[0];
    unsigned _call = 0x848580;
    _asm {
        mov ecx, readEcx
        push read
        call _call
    }
    bool vip = false;
    if (vip)return false;
    else return true;
}

bool ExitGame(HOOKREFS2) {
    auto read = _pgamebase->SRO_Res->ReadTitle((wchar_t*)0xEBC968);
    CString txt;
    txt.Format(L"------ %s", read->wcstr());
    read->Ptitle = L"自动助手 [VIP] (%s)";
    // AfxMessageBox(txt);

    // if (_protect->CheckDebugByNT())AfxMessageBox(L"检测到了DEBUG程序的存在");
	// AfxMessageBox(L"游戏退出2222!");
	DWORD* _esp = (DWORD*)_ESP;
	DWORD _val = _esp[1];

	if (_val == 0x1035D0C) {
		// AfxMessageBox(L"游戏退出!");
		auto hMuls = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, L"system_seamp");
		if (hMuls) ReleaseSemaphore(hMuls, 1, 0);
        client--;
		ExitProcess(0);
	}
	return true;
}

GameEx::GameEx()
{
	// AfxMessageBox(L"注册hook!");
	// auto h = GetModuleHandle(NULL);
	// DWORD address = (DWORD)h;
    // DWORD* addRExit = (DWORD*)(address + 0x88C77E);
    /**addRExit = 0;*/
	// CString txt;
    // txt.Format(L"addRExit[0]D:%d,addRExit[0]X:%X,addRExit:%X", addRExit[0], addRExit[0], addRExit);
    // AfxMessageBox(txt);

    // hooker.SetHook((LPVOID)addRExit, 3, ExitGame);
    //AddVectoredExceptionHandler(1, 异常回调);
    //设置线程的dr寄存器(GetCurrentThread());
}

void GameEx::InitInterface()
{
    unsigned addr_cps =  GetFunctionAddress(0);
    hooker.SetHook((LPVOID)(addr_cps + 0x30 - 2), 0x3, ExitGame);
    hooker.SetHook((LPVOID)(addr_cps + 0x51 - 2), 0x3, ExitGame);

    unsigned addr_autohelper = GetFunctionAddress(1);
    hooker.SetHook((LPVOID)(addr_autohelper), 0x03, AutoHelper, (LPVOID)(addr_autohelper + 0x90));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1356207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手把手教你如何使用SpringBoot3打造一个个性化的代码生成器

自定义代码生成器 代码基于SpringBoot3、Vue3、highlight实现自定义代码生成功能 SpringBoot3.x、MySQL8、MyBatisPlus3.5.x、velocity2.x、SpringSecurity6.x、Vue3、TypeScript、highlight demo所需要的依赖及其对应版本号 pom <?xml version"1.0" encoding&…

运用Jmeter进行登录测试

开始了解Jmeter,写篇关于Jmeter的博客做备忘,这里以苏宁易购网站的登录请求为例实战来说明测试计划元件,创建一个 Web 测试计划。 今天简单介绍Jemeter的入门,Jmeter 的安装这边就跳过,直接讲述如何使用JMETER,如何运用Jmeter进行测试。 a.下载jmeter软件 b.安装…

一起offsetLeft值引发的样式错乱问题

问题描述&#xff1a; 首先我们来看一下正常样式和异常样式&#xff0c;正常样式的左侧菜单会正常显示出来&#xff0c;而异常样式的左侧菜单会被覆盖&#xff1b; 正常的样式&#xff1a; 异常的样式&#xff1a; 问题探索&#xff1a; 左边的间距其实跟通过读取最外层元素…

mysql(三) 索引-普通索引、复合索引、索引规则等

上文我们学习了索引基础知识、所以我画了一个查询语句简单的执行流程、希望可以帮助大家一起学习。 目录 mysql select语句执行流程 普通索引 复合索引 创建索引&#xff08;三种&#xff09; 1、使用INDEX建表的时候创建索引 (创建表时建索引) INDEX的语法&#xff1a; …

osg-材质 (osg::Material)

1.材质类 材质类 (osg::Material)继承自osg::StateAttribute 类。osg::Material 封装了 OpenGL的 glMaterial()和glColorMaterial()指令的函数功能&#xff0c;其继承关系图如图5-27 所示。 图 5-27 osg::Material 的继承关系图 在场景中设置节点的材质属性&#xff0c;首先要…

VS2017 CMake编译Opencv

先下载opencv4.2.0源码以及opencv_contrib-4.2.0 地址链接&#xff1a;https://pan.baidu.com/s/1AgFsiH4uMqTRJftNXAqmTw?pwd3663 提取码&#xff1a;3663 先建立一个opencv_debug和opencv_release文件夹这两个都是为了后续存放编译好的debug版本和release版本opencv的&#…

APP自动化测试工具:八款推荐解析

uiautomator2 github地址&#xff1a;github.com/openatx/uia… UiAutomator 是 Google 提供的用来做安卓自动化测试的一个 Java 库&#xff0c;基于 Accessibility 服务。功能很强&#xff0c;可以对第三方 App 进行测试&#xff0c;获取屏幕上任意一个 APP 的任意一个控件属…

LeetCode---378周赛

题目列表 2980. 检查按位或是否存在尾随零 2981. 找出出现至少三次的最长特殊子字符串 I 2982. 找出出现至少三次的最长特殊子字符串 II 2983. 回文串重新排列查询 一、检查按位或是否存在尾随零 这题和位运算有关&#xff0c;不是很难&#xff0c;题目要求至少有两个数的…

基于SSM的新闻网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

基于SSM的班级事务管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

WebSocket的优点和缺点:一文详解。

WebSocket 的优缺点 WebSocket 协议是一种双向通信协议&#xff0c;它使用单个 TCP 连接实现全双工通信&#xff0c;这使它比传统的 HTTP 协议更有效率。 WebSocket 优点 双向通信&#xff1a; WebSocket 协议支持双向通信&#xff0c;使服务器和客户端之间的通信更加方便和快…

googlecode.log4jdbc慢sql日志,格式化sql

前言 无论使用原生JDBC、mybatis还是hibernate&#xff0c;使用log4j等日志框架可以看到生成的SQL&#xff0c;但是占位符和参数总是分开打印的&#xff0c;不便于分析&#xff0c;显示如下的效果: googlecode Log4jdbc 是一个开源 SQL 日志组件&#xff0c;它使用代理模式实…

图像预处理——transforms

一、transforms 运行机制 torchvision是PyTorch的一个扩展库&#xff0c;提供了许多计算机视觉相关的工具和功能。下面是关于torchvision中常用模块的介绍&#xff1a; torchvision.transforms&#xff1a;提供了一系列常用的图像预处理方法&#xff0c;用于对图像进行变换、…

【生成人工智能】Ray如何解决生成人工智能基础设施的常见生产挑战

这是我们生成人工智能博客系列的第一部分。在这篇文章中&#xff0c;我们讨论了如何使用Ray来生产常见的生成模型工作负载。即将发布的一篇博客将深入探讨Alpa等项目为什么要使用Ray来扩展大型模型。 生成的图像和语言模型有望改变企业的设计、支持、开发等方式。本博客重点关…

Spring——Spring IOC(2)

1.Spring中的工厂类 1.1 ApplicationContext ApplicationContext的实现类&#xff0c;如下图&#xff1a; ClassPathXmlApplicationContext&#xff1a;加载类路径下 Spring 的配置文件FileSystemXmlApplicationContext&#xff1a;加载本地磁盘下 Spring 的配置文件 1.2 B…

基于Segformer实现PCB缺陷检测(步骤 + 代码)

导 读 本文主要介绍基于Segformer实现PCB缺陷检测 &#xff0c;并给出步骤和代码。 背景介绍 PCB缺陷检测是电子制造的一个重要方面。利用Segformer等先进模型不仅可以提高准确性&#xff0c;还可以大大减少检测时间。传统方法涉及手动检查&#xff0c;无法扩展且容易出错…

体元法--体积计算

文章目录 环境&#xff1a;1.1 体元法介绍&#xff1a;2.1 python代码3.1 可视化 环境&#xff1a; Open3D 1.1 体元法介绍&#xff1a; 用一个个体素去占据点云&#xff0c;然后对所有体素求和 2.1 python代码 conda activete deeplabv3plus(环境名称–安装好open3D的) py…

python django 生鲜商城管理系统

python django 生鲜商城管理系统,包含用户端和管理端 功能&#xff1a; 用户端&#xff1a;商城主页展示&#xff0c;登录&#xff0c;注册&#xff0c;用户中心&#xff0c;购物车&#xff0c;我的订单&#xff0c;购物车结算 管理端&#xff1a;登录&#xff0c;商品&…

QT的坐标系统,回收机制、菜单栏,工具栏,状态栏,对话框及资源文件

QT的坐标系统&#xff0c;回收机制、菜单栏&#xff0c;工具栏&#xff0c;状态栏&#xff0c;对话框及资源文件 文章目录 QT的坐标系统&#xff0c;回收机制、菜单栏&#xff0c;工具栏&#xff0c;状态栏&#xff0c;对话框及资源文件1、QT的坐标系统&#xff1f;2、对象模型…

顶帽运算在OpenCv中的应用

项目背景 假如我们拍了一张自拍&#xff0c;想为自己的照片添加一个酷炫的火星飞舞的效果&#xff0c;素材库中正好有一张火焰的照片&#xff0c;如果想去除图中的火焰&#xff0c;只保留火星效果&#xff0c;可以使用顶帽子算法 图片中的火星部分正好属于比周围亮一些的斑块…