星痕共鸣数据分析2

今天实验内容是攻击力部分

1.思路

由于昨天数据分析出了一个函数

这个函数可以把奇怪的字节变成正常的数字

cpp 复制代码
int parse_varint(unsigned const char* data, int count)
{
	int value = 0;
	int shift = 0;
	for (int i = 0; i < count; i++) {
		unsigned char byte = data[i];
		value |= ((byte & 0x7F) << shift);
		shift += 7;
	}
	return value;
}

然后,我们把函数逆推,得到下面的函数

这个函数可以把正常的数字变成奇怪的字符

cpp 复制代码
void encode_varint(unsigned char* output, int* count, int value)
{
	*count = 0;
	do {
		unsigned char byte = value & 0x7F;
		value >>= 7;
		if (value != 0) {
			byte |= 0x80;  // 设置最高位表示还有后续字节
		}
		output[(*count)++] = byte;
	} while (value != 0);
}

然后我们攻击一下场景内的怪物,造成伤害346,然后抓包

将346代入上面的函数,得到0xda, 0x02

结合抓包信息

我们可以看到伤害0xda, 0x02已经在包里面出现了(这个包的数据量比较多)

为了确保正确性,可以多次抓包验证

然后,分析字节数据发现大多数数据都是0x12+长度

可以用这个分析结构

cpp 复制代码
#include <iostream>
#include <vector>
#include <iomanip>
#include <memory>
#include"XHGM.h"
// 定义段节点结构
struct Segment {
	int length;  // 数据段长度(不包括起始的0x12和长度字节)
	std::vector<unsigned char> data;  // 段数据(可能包含子段)
	std::vector<std::unique_ptr<Segment>> children;  // 子段列表
};

// 递归解析数据为树形结构
std::unique_ptr<Segment> parseSegment(const unsigned char* data, int data_size, int& index, int depth = 0) {
	if (index >= data_size) return nullptr;

	// 创建新节点
	auto node = std::make_unique<Segment>();

	// 验证起始字节
	if (data[index] != 0x12) {
		std::cerr << "Error: Expected 0x12 at index " << index << ", found 0x"
			<< std::hex << std::setw(2) << std::setfill('0')
			<< static_cast<int>(data[index]) << std::endl;
		index++;  // 跳过无效字节
		return nullptr;
	}
	index++;  // 跳过0x12

			  // 获取段长度
	if (index >= data_size) {
		std::cerr << "Error: Missing length byte at index " << index << std::endl;
		return nullptr;
	}
	node->length = static_cast<int>(data[index]);
	index++;  // 跳过长度字节

			  // 提取段数据
	int end_index = index + node->length;
	if (end_index > data_size) {
		std::cerr << "Error: Incomplete segment at index " << index
			<< ", declared length: " << node->length << std::endl;
		return nullptr;
	}

	// 递归解析嵌套的子段
	while (index < end_index) {
		if (data[index] == 0x12) {
			// 递归解析子段
			auto child = parseSegment(data, data_size, index, depth + 1);
			if (child) {
				node->children.push_back(std::move(child));
			}
		}
		else {
			// 添加普通数据字节
			node->data.push_back(data[index]);
			index++;
		}
	}

	return node;
}

// 打印树形结构
void printSegmentTree(const Segment* node, int depth = 0) {
	if (!node) return;

	// 缩进表示层级
	std::string indent(depth * 2, ' ');

	// 打印当前节点信息
	std::cout << indent.c_str() << "Segment (Length=" << node->length << "): ";

	// 打印原始数据
	if (!node->data.empty()) {
		std::cout << "Data: ";
		for (auto byte : node->data) {
			std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0')
				<< static_cast<int>(byte) << " ";
		}
		/*int lens = node->data.size();
		char *t = new char[lens];
		int t1 = 0;
		for (auto byte : node->data) {
			t[t1++] = byte;
		}
		int tt = parse_varint(t, lens);
		std::cout << tt;
		delete[] t;*/
	}
	std::cout << std::endl;

	// 递归打印子节点
	for (const auto& child : node->children) {
		printSegmentTree(child.get(), depth + 1);
	}
}

int main() {
	// 原始数据
	unsigned char peer0_5[] = {
		0x12, 0x0b, 0x08, 0x96, 0xa1, 0x3e, 0x10, 0xa9, 0x06, 0x18, 0xe4, 0xaf, 0x01,
0x12, 0x0a, 0x08, 0x97, 0xa1, 0x3e, 0x10, 0xe0, 0x04, 0x18, 0x98, 0x75,
0x12, 0x0a, 0x08, 0x98, 0xa1, 0x3e, 0x10, 0xc7, 0x06, 0x18, 0x98, 0x75,
0x12, 0x04, 0x08, 0xf7, 0xa1, 0x3e, 
0x12, 0x0b, 0x08, 0xf8, 0xa1, 0x3e, 0x10, 0xec, 0x03, 0x18, 0x80, 0xe1, 0x01, 
0x12, 0x04, 0x08, 0xf9, 0xa1, 0x3e, 
0x12, 0x0a, 0x08, 0xfa, 0xa1, 0x3e, 0x10, 0x01, 0x18, 0x8c, 0xf6, 0x01, 
0x12, 0x0a, 0x08, 0xfb, 0xa1, 0x3e, 0x10, 0x03, 0x18, 0xf8, 0xd2, 0x01,
0x12, 0x04, 0x08, 0xfc, 0xa1, 0x3e, 
0x12, 0x0b, 0x08, 0xfd, 0xa1, 0x3e, 0x10, 0x8e, 0x01, 0x18, 0x88, 0xef, 0x01, 
0x12, 0x0b, 0x08, 0xfe, 0xa1, 0x3e, 0x10, 0xeb, 0x04, 0x18, 0xfc, 0xd9, 0x01

	};

	int data_size = sizeof(peer0_5) / sizeof(peer0_5[0]);
	int index = 0;

	std::vector<std::unique_ptr<Segment>> rootSegments;

	// 解析所有顶级段
	while (index < data_size) {
		auto segment = parseSegment(peer0_5, data_size, index);
		if (segment) {
			rootSegments.push_back(std::move(segment));
		}
		else {
			// 跳过无效字节
			index++;
		}
	}

	// 打印解析结果
	std::cout << "Found " << rootSegments.size() << " root segments:\n";
	for (size_t i = 0; i < rootSegments.size(); ++i) {
		std::cout << "\nRoot Segment " << i + 1 << ":\n";
		printSegmentTree(rootSegments[i].get());
	}

	return 0;
}
相关推荐
roman_日积跬步-终至千里几秒前
【数据Agent论文·分析与报告评测|27】ComInsight:原子洞察正确,组合后的结论就可靠吗?
人工智能·算法·机器学习·数据分析
沫璃染墨16 分钟前
《Qt从零入门系列(十四):QThread多线程详解——从线程创建到客户端阻塞处理》
开发语言·c++·笔记·qt·ui·交互·线程
草莓熊Lotso18 分钟前
【C++ 基于微服务的即时通讯系统】Elasticsearch 从安装到 C++ 客户端二次封装全落地
linux·网络·数据库·c++·elasticsearch·微服务
CHPCWWHSU29 分钟前
FreeCAD 源码解读:从 Property 到 Command,看一套 CAD 内核的完整闭环
c++·cad
学术 学术 Fun1 小时前
科研公开数据集怎么找?从关键词到许可证与数据引用
数据分析·科研·开放数据
代钦塔拉1 小时前
【C++/Qt 进阶】设计模式系列(5):适配器模式——给“不兼容的接口“贴一层翻译膜
c++·qt·设计模式
aqiu1111111 小时前
蓝桥杯真题复盘:Fibonacci 数列与黄金分割(C++ 算法详解)
c++·算法·蓝桥杯
lojox1 小时前
C++ 手写 STL list(双向循环链表)原理剖析与实现
c++·链表·list
青少儿编程课堂1 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会C/C++考级:拓扑排序课程表排课解析
c++·python·算法·bfs·信息学竞赛
roman_日积跬步-终至千里1 小时前
【数据Agent论文·企业系统与可靠性|29】QwenPaw-Data:企业分析Agent为什么要分别管理事实、方法和执行?
人工智能·数据分析