33.网络游戏逆向分析与漏洞攻防-游戏网络通信数据解析-游戏登录数据包分析利用

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

如果看不懂、不知道现在做的什么,那就跟着做完看效果

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

上一个内容:32.网络数据分析原理与依据

码云地址(master 分支):https://gitee.com/dye_your_fingers/titan

码云版本号:57b7d17bb70c93cea427a82f1f3831b142164a3e

代码下载地址,在 titan 目录下,文件名为:titan-游戏登录数据包分析利用.zip

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

提取码:q9n5

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

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

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

提取码:78h8

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

31.其它消息的实现与使用优化 它的代码为基础进行修改

数据包分析的基本原理:

1.数据包的组织结构有可能是数据约定和解码约定同时存在

2.看数据包最重要的突破口就是先分析可以分析出来的东西,也就是明文的内容,比如聊天里面的聊天信息登录里面的账号密码,游戏走路的时候的坐标

3.通过反复比对同一个操作的数据包,不断改变其中的变量,确定数据内的常量与变量,比如就登录这件事,可以不断的改变账号和密码,这就可以把里面的变量确定出来,比如账号密码时间戳等,不变的比如它的数据包头一些固定的常量,这就是反复比对同一个数据包

4.尝试先分析能够识别的内容,有些时候有些内容是可以分析出来的,有些内容是分析不出来的,分析不出来的东西,就是是在卡主分析不出来就先放着,把所有的数据包都分析一遍,它们之间是极有可能是有关联的,做安全就要有一个思维,就是你面对的不是计算机,你面对的是人,那么他(t她)在设计这些东西的时候往往都会再用跟之前类似的地方。

5.数据包里的常量可以不分析,比如说这个东西它就是固定的它不变,这种不变的东西就没必要看它到底是什么,因为它反正不会变,所以就不用分析

开始分析,登录:

首先打开我们的工具与注入,tiStart.exe与DataAnly.exe,百度网盘里有,这俩东西

然后使用tiStart.exe启动游戏,然后在游戏里输入123,账号密码都输入的123,然后点登录,然后就在DataAnly.exe里收到了数据,如下图

这个登录数据包是0203什么什么

虽然有搜索功能但是不用搜索就能看到,123,如下图

但是不知道哪个是密码哪个是账号,所以接下来把账号输入成1234,密码写成123,如下图,这样就可以看出上面的是账号下面的是密码

然后比对数据包

然后就会发现其它的位置都没有变化,只有下面两个图红框里的内容有变化,所以这样就可以确定它们就是账号密码了

然后分析一下其它的数据

下图中的10是十六进制,换成十进制就是16,然后10后面的数据也正好是16,所以可以猜测这个10是长度

然后02 00 03 00可能是操作类型,这个需要登录进游戏,对比其它数据包,这里先不管

然后下图红框位置没有数据,但是前面有一个10,可以猜测它是预留的接口,比如用来存放验证码

然后01不知道什么意思

然后把账号密码输入的内容超过16看看数据包有什么变化

发现长度变成了十六进制的20

然后在给它拆分一下,至于为什么这样拆分,是感觉,数字基本是4字节,状态、类型都可以用数字,下图中的02也可以分析成02 00两字节,但是考虑到这是数据包的头部,这里就假设它是1字节

然后又由于它的数据长度可能默认是16,00 03 00 00 后面的数据直到下一个代表长度的数据,也就是这里的20,这些数据长度是16,如下图红框位置,它有16个字节,这也是把02猜测成1字节的原因

然后后面的数据,仅仅只是满足于字符串的形式,前面跟着一个数字,后面是数据,这个数字代表了后面数据的长度,字符串一般都会这样,这种形式要牢牢记住。

然后下图红框的 01 00 00 00 这个就不知道是什么了,只能把01改成00或者其它数字,给服务端发送一个数据包试一试,这种就属于可能永远不知道是什么的数据

然后到这不见得分析的数据是准确的,对于利用肯定是够了,但是完整的去看这个数据包目前来讲不见得是准确的

比如下图红框位置是不是这样的拆分,这种就确定不了,它也有可能有什么系统性的方法,这东西确定不了,确定不了就算,后面发现了在看,将来看的数据包多了就能发现了就能确定了

然后根据现在得到的信息,写出它的数据类型,可以发现少了头部的0x02,这个0x02是数据包头,数据包头不属于数据

int = 0x300;

char un[0x10]{};

int lenId;

char id[lenId];

int lenPs;

char Pass[lenPs];

int lenun;

char bun[lenun];

int un;

然后登陆进游戏多看几个数据包,删除一个角色的数据包

删除的数据包,看着很复杂

然后用工具(DataAnly.exe)推测一下数据

可以看到下图中选择的6个字节是美美美这三个字,这三个字是刚刚的角色名,然后数据包的头部是一个6,这个6加上美美美这三个字的长度,可以猜测这个6是名字的长度,然后后面的内容暂时不知道是什么内容

为了确定这个6是长度,还是仅仅是数据包的头,接下来创建一个更长的名字,现在的名字有四个字,应该是8个字节才对

然后看出这个6并不是名字长度,它仅仅是数据包的头

现在可以确定数据包的头是一字节,删除角色操作的数据包是06

然后在看一个登陆的

然后可以发现,登陆的角色的数据包头是4,然后后面是登陆的角色名字

它这个东西自己写的很乱是不太现实的,所以它就会把第一个字节做成数据包的头,它不可能第一个消息用04当头,第个消息用06当头,这样写的代码它自己都会难受,所以正常来讲它一定是有一个固定的方法,这个东西可以分析的原理就是这个,现在的很简单,实际的肯定会遇到各种各样的问题,遇到问题之后,就要想对方是怎样解决这个问题的,当年它写代码是怎样处理这个问题的,这个数据包它乱组织一段怎么处理,这个核心问题还是跟人有关的一个事情。

然后游戏退出之后发现它还会拿发送数据包,如下图红框,这时的数据它是发送失败的,使用x96dbg在send函数里打断点是断不下来的,这就很明显说明发送失败了

然后接下来看登录的接收数据,接收的数据是03 39 C7 00 00

现在的登录状态是通行证不存在,假设03是返回的数据包头,C739是错误码,也就是51001是通行证不存在,数据包里明明是39 C7,为什么要写成C739,是因为大端序小端序的问题,随便百度大端序小端序就也可以找到答案

然后是通行证存在密码不正确,是C73A

51002是密码错误

然后写c++代码

首先创建一个类,类名是 NetClient,监视客户端每一个操作

NetClient.cpp文件的内容

#include "pch.h"
#include "NetClient.h"

void NetClient::logfailed(int code)
{
}

NetClient.h文件的内容

#pragma once
class NetClient // 监视客户端每一个操作
{
public:
	/*
		模拟登陆的方法
		Id是账号
		Pass是密码
		它要基于发送的方法实现,因为我们没有连接socket的操作
	*/
	bool login(const char* Id, const char*Pass);
public:
	// 登陆失败,参数是错误码
	void logfailed(int code);
};

GameProc.cpp文件的修改:修改了 Init函数

#include "pch.h"
#include "GameProc.h"
#include "extern_all.h"

// typedef bool(GameWinSock::* U)(char*, unsigned);


bool _OnRecv(HOOKREFS2) {
	unsigned* _esp = (unsigned*)_ESP;
	_EAX = WinSock->RecvPoint;
	WinSock->OnRecving((char*)_esp[1], _esp[2]);
	return true;
}

bool _OnConnect(HOOKREFS2) {
	/*
		根据虚函数表做HOOK的操作
		截取 ecx 获取 winsock 的值(指针)
	*/
	unsigned* vtable = (unsigned*)_EDX;
	//WinSock = (GameWinSock *)_ECX;
	/*
		联合体的特点是共用一个内存
		由于 GameWinSock::OnConnect 的 OnConnect函数是 GameWinSock类的成员函数
		直接 vtable[0x34 / 4] = (unsigned)&GameWinSock::OnConnect; 这样写语法不通过
		所以使用联合体,让语法通过
	*/
	union {
		unsigned value;
		bool(GameWinSock::* _proc)(char*, unsigned);
	} vproc;
	DWORD oldPro, backProc;
	VirtualProtect(vtable, 0x100, PAGE_EXECUTE_READWRITE, &oldPro);
	/*
		vproc._proc = &GameWinSock::OnConnect;  这一句是把我们自己写的调用connect函数的地址的出来
	*/ 
	vproc._proc = &GameWinSock::OnConnect; 
	/*
		InitClassProc函数里做的是给指针赋值的操作
		InitClassProc(&GameWinSock::_OnConnect, vtable[0x34/4]);这一句的意思是把
		GameWinSock类里的_OnConnect变量的值赋值成vtable[0x34/4],这个 vtable[0x34/4] 是虚表里的函数
		vtable[0x34/4]是游戏中调用connect函数的函数地址,经过之前的分析调用connect是先调用了虚表中的
		一个函数,然后从这个函数中调用了connect函数
	*/
	InitClassProc(&GameWinSock::_OnConnect, vtable[0x34/4]);
	vtable[0x34 / 4] = vproc.value;


	vproc._proc = &GameWinSock::OnSend;
	InitClassProc(&GameWinSock::_OnSend, vtable[0x3C / 4]);
	vtable[0x3C / 4] = vproc.value;


	VirtualProtect(vtable, 0x100, oldPro, &backProc);
	return true;
}

GameProc::GameProc()
{
	hooker = new htd::hook::htdHook2();
	Init();
	InitInterface();
}

void GameProc::LoadBase()
{
	LoadLibraryA("fxnet2.dll");
}

void GameProc::Init()
{
#ifdef  anly
	anly = new CAnly();
#endif
	/*
		这里的 WinSock 是0没有创建对象,但是还是能调用Init函数
		这是因为Init函数里面没有用到this,没用到就不会报错
	*/
	WinSock->Init(); 

}



void GameProc::InitInterface()
{
	LoadBase();
	// MessageBoxA(0, "1", "1", MB_OK);
	// 只会HOOK一次,一次性的HOOK
	hooker->SetHook((LPVOID)0x10617046, 0x1, _OnConnect, 0, true);
	/*
		第一个参数是HOOK的位置
		第二个参数是HOOK的位置的汇编代码的长度(用于保证执行的汇编代码完整)
		第三个参数是HOOK之后当游戏执行到第一个参数的位置的时候跳转的位置
	*/
	hooker->SetHook((LPVOID)0x10618480, 0x1, _OnRecv);
	/*
		在这里绑定游戏处理数据包函数(0x10618480函数)
		然后0x10618480函数在上面一行代码已经进行了HOOK
		所以在调用_OnRecv函数指针时,它就会进入我们HOOK
	*/
	InitClassProc(&GameWinSock::_OnRecv, 0x10618480);
}

GameWinSock.cpp文件的修改:修改了 OnSend函数、OnRecving函数,新加 DealProc函数指针、SendDealProc函数指针变量、RecvDealProc函数指针变量、Init函数

#include "pch.h"
#include "GameWinSock.h"
#include "extern_all.h"

typedef bool(* DealProc)(char*, unsigned);

DealProc SendDealProc[0x100];
DealProc RecvDealProc[0x100];


GameWinSock::PROC GameWinSock::_OnConnect{};
GameWinSock::PROC GameWinSock::_OnSend{};
GameWinSock::PROC GameWinSock::_OnRecv{};

bool DeafaultDeal(char*, unsigned) { return true; }

// 这个函数拦截了游戏的连接
bool GameWinSock::OnConnect(char* ip, unsigned port)
{
#ifdef  Anly
	anly->SendData(TTYPE::I_DIS, 0, ip, 16);
	// 长度24的原因,它是宽字节要,一个文字要2个字节,一共是10个文字加上结尾的0是11个
	// 所以 11 乘以2,然后再加2 
	anly->SendData(TTYPE::I_LOG, 0, L"服务器正在连接。。。", 24);
#endif
    // this是ecx,HOOK的点已经有ecx了
    WinSock = this;
	bool b = (this->*_OnConnect)(ip, port);
	// 下方注释的代码时为了防止多次注入,导致虚函数地址不恢复问题导致死循环,通过一次性HOOK也能解决
	/*unsigned* vtable = (unsigned*)this;
	vtable = (unsigned*)vtable[0];
	union {
		unsigned value;
		bool(GameWinSock::* _proc)(char*, unsigned);
	} vproc;

	vproc._proc = _OnConnect;

	DWORD oldPro, backProc;
	VirtualProtect(vtable, 0x10x00, PAGE_EXECUTE_READWRITE, &oldPro);
	vtable[0x34 / 4] = vproc.value;
	VirtualProtect(vtable, 0x10x00, oldPro, &backProc);*/

    return b;
}

bool GameWinSock::OnSend(char* buff, unsigned len)
{
	
	/*
		这里就可以监控游戏发送的数据了
	*/

#ifdef  Anly
	anly->SendData(TTYPE::I_SEND, buff[0], buff, len);
#endif
	/*
		数据包的头只有一字节所以它的取值范围就是0x0-0xFF
	*/
	if (SendDealProc[buff[0]]((buff + 1), len - 1)) {// 执行失败不让游戏发送数据包
		return (this->*_OnSend)(buff, len);
	}
	else {// 发送失败屏蔽消息
		return true;// 屏蔽消息
	}

}

bool GameWinSock::OnRecving(char* buff, unsigned len)
{
	// MessageBoxA(0, "11111111111111", "0", MB_OK);
	/*
		监控游戏接收的数据包
	*/
#ifdef  Anly
	anly->SendData(TTYPE::I_RECV, 0, buff, len);
#endif
	return RecvDealProc[buff[0]](buff + 1, len - 1);
}

bool GameWinSock::OnRecv(char* buff, unsigned len)
{
//#ifdef  Anly
//	anly->SendData(1, buff, len);
//#endif
	return (this->*_OnRecv)(buff, len);
}

void GameWinSock::Init()
{
	for (int i = 0; i < 0x100; i++) {
		SendDealProc[i] = &DeafaultDeal;
		RecvDealProc[i] = &DeafaultDeal;
	}
}

GameWinSock.h文件的修改:新加 Init函数

#pragma once
class GameWinSock
{
	typedef bool(GameWinSock::* PROC)(char*, unsigned);
public:
	unsigned* vatble;// 虚函数表
	unsigned un[17];
	unsigned RecvPoint; // 游戏recv之后调用处理一个数据包函数时的eax,这里偏移是0x48
public:
	static PROC _OnConnect;
	static PROC _OnSend;
	static PROC _OnRecv;
	bool OnConnect(char* ip, unsigned port);
	bool OnSend(char* buff, unsigned len);
	bool OnRecving(char* buff, unsigned len);
	bool OnRecv(char* buff, unsigned len);

	void Init();
};


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2.6、媒体查询(mediaquery)

概述 媒体查询作为响应式设计的核心,在移动设备上应用十分广泛。媒体查询可根据不同设备类型或同设备不同状态修改应用的样式。媒体查询常用于下面两种场景: 针对设备和应用的属性信息(比如显示区域、深浅色、分辨率),设计出相匹配的布局。当屏幕发生动态改变时(比如分屏…

高项-案例分析练习(范围管理)

案例一 公司在2014年初承接了一个医疗信息系统项目&#xff0c;要求2014年底完成该项目研发任务并进行试运行&#xff0c;2015年负责项目全年的运行维护&#xff0c;运行稳定后甲方验收合格项目才能结束。由于张工具有多年的医疗系统开发管理经验&#xff0c;公司领导任命他为项…

SQLiteC/C++接口详细介绍sqlite3_stmt类(十二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;十一&#xff09; 下一篇&#xff1a; SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;十三&#xff09; 48、sqlite3_stmt_isexplain sqlite3_stmt_is…

WPF 立体Border

WPF 立体Border &#xff0c;用来划分各个功能区块 在资源文件中&#xff0c;添加如下样式代码&#xff1a; <Style x:Key"BaseBorder" TargetType"Border"><Setter Property"Background" Value"White" /><Setter Prop…

深度学习Top10算法之深度神经网络DNN

深度神经网络&#xff08;Deep Neural Networks&#xff0c;DNN&#xff09;是人工神经网络&#xff08;Artificial Neural Networks&#xff0c;ANN&#xff09;的一种扩展。它们通过模仿人脑的工作原理来处理数据和创建模式&#xff0c;广泛应用于图像识别、语音识别、自然语…

从JDK动态代理一步步推导到MyBatis Plugin插件实现原理

一、前言 最近项目上&#xff0c;要做一个日志审计的功能&#xff08;通用SDK&#xff0c;期望可以在任何项目中使用&#xff09;&#xff0c;需要对Mybatis层所有的DDL操作做拦截&#xff0c;以将微服务的链路ID、执行人、Controller门面方法全部持久化到业务库。借此机会深入…

JavaScript 权威指南第七版(GPT 重译)(二)

第四章&#xff1a;表达式和运算符 本章记录了 JavaScript 表达式以及构建许多这些表达式的运算符。表达式 是 JavaScript 的短语&#xff0c;可以 评估 以产生一个值。在程序中直接嵌入的常量是一种非常简单的表达式。变量名也是一个简单表达式&#xff0c;它评估为分配给该变…

Linux安装harbor(Docker方式)

Linux安装harbor&#xff08;Docker方式&#xff09; 前置条件&#xff1a;安装docker和docker-compose先下载安装包&#xff1a;https://github.com/goharbor/harbor/releases解压到指定目录 sudo tar -zxf harbor-offline-installer-v2.1.0.tgz -C /opt/安装 cd /opt/harb…

【Canvas与艺术】简约式胡萝卜配色汽车速度表

【效果图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>胡萝卜色汽车速度仪表盘简化版</title><style type"…

AI助力生产制造质检,基于轻量级YOLOv8n模型开发构建工业生产制造场景下的瓷砖瑕疵检测识别分析系统

瓷砖生产环节一般经过原材料混合研磨、脱水、压胚、喷墨印花、淋釉、烧制、抛光&#xff0c;最后进行质量检测和包装。得益于产业自动化的发展&#xff0c;目前生产环节已基本实现无人化。而质量检测环节仍大量依赖人工完成。一般来说&#xff0c;一条产线需要配数名质检工&…

此站点正在尝试打开 ,chrome/edge 允许http网站打开url schema

正常https链接会有首次允许选项 但http没有&#xff0c;每次都会弹出&#xff0c;非常烦人。 Chrome / Edge 配置 地址栏输入 chrome://flags/搜索Insecure origins treated as secure, 配置允许网站&#xff0c;需要协议和端口再次跳转会显示始终允许选项

Sphinx + Readthedocs 避坑速通指南

博主在学习使用 Sphinx 和 Read the docs 的过程中&#xff0c; 碰到了许多奇葩的 bug, 使得很简单的任务花费了很长的时间才解决&#xff0c;现在在这里做一个分享&#xff0c;帮助大家用更少的时间高效上线文档的内容。 总的来说&#xff0c; 任务分为两个部分&#xff1a; …

Jetson AGX ORIN 初始化配置Anaconda带CUDA的OpenCV

Jetson AGX ORIN 初始化&配置CUDA&Anaconda&带CUDA的OpenCV 文章目录 Jetson AGX ORIN 初始化&配置CUDA&Anaconda&带CUDA的OpenCV1. Jetson AGX ORIN 初始化2. Jetson AGX ORIN 配置 Anaconda3. 安装带CUDA的OpenCV 1. Jetson AGX ORIN 初始化 可以参…

[音视频学习笔记]七、自制音视频播放器Part2 - VS + Qt +FFmpeg 写一个简单的视频播放器

前言 话不多说&#xff0c;重走霄骅登神路 前一篇文章 [音视频学习笔记]六、自制音视频播放器Part1 -新版本ffmpeg&#xff0c;Qt VS2022&#xff0c;都什么年代了还在写传统播放器&#xff1f; 本文相关代码仓库&#xff1a; MediaPlay-FFmpeg - Public 转载雷神的两个流程…

css3鼠标悬停图片特效,图片悬停效果源码

特效介绍 css3鼠标悬停图片特效,图片悬停效果源码&#xff0c;可以在网页上面作为自己的动态加载名片&#xff0c;放到侧边栏或者网站合适的位置即可 动态效果 代码下载 css3鼠标悬停图片特效,图片悬停效果源码

阿里云 EMR Serverless Spark 版免费邀测中

随着大数据应用的广泛推广&#xff0c;企业对于数据处理的需求日益增长。为了进一步优化大数据开发流程&#xff0c;减少企业的运维成本&#xff0c;并提升数据处理的灵活性和效率&#xff0c;阿里云开源大数据平台 E-MapReduce &#xff08;简称“EMR”&#xff09;正式推出 E…

数据挖掘与机器学习 1. 绪论

于高山之巅&#xff0c;方见大河奔涌&#xff1b;于群峰之上&#xff0c;便觉长风浩荡 —— 24.3.22 一、数据挖掘和机器学习的定义 1.数据挖掘的狭义定义 背景&#xff1a;大数据时代——知识贫乏 数据挖掘的狭义定义&#xff1a; 数据挖掘就是从大量的、不完全的、有噪声的、…

基于docker配置pycharm开发环境

开发过程中&#xff0c;为了做好环境隔离&#xff0c;经常会采用docker来进行开发&#xff0c;但是如何快速将docker中的环境和本地开发的IDE链接起来是一个常见问题&#xff0c;下面对其进行简单的总结&#xff1a; &#xff08;1&#xff09;前期准备 开发环境docker和工具p…

ENISA 2023年威胁态势报告:主要发现和建议

欧盟网络安全局(ENISA)最近发布了其年度2023年威胁态势报告。该报告确定了预计在未来几年塑造网络安全格局的主要威胁、主要趋势、威胁参与者和攻击技术。在本文中&#xff0c;我们将总结报告的主要发现&#xff0c;并提供可操作的建议来缓解这些威胁。 介绍 ENISA 威胁态势报告…

活动回顾 | 走进华为向深问路,交流数智办公新体验

3月20日下午&#xff0c;“企业数智办公之走进华为”交流活动在华为上海研究所成功举办。此次活动由上海恒驰信息系统有限公司主办&#xff0c;华为云计算技术有限公司和上海利唐信息科技有限公司协办&#xff0c;旨在通过对企业数字差旅和HR数智化解决方案的交流&#xff0c;探…