93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析

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

上一个内容:显示游戏数据到小助手UI

码云地址(游戏窗口化助手 分支):https://gitee.com/dye_your_fingers/sro_-ex.git

码云版本号:852c339f5e4c103390b123e0eaed577c9afa4fc4

代码下载地址,在 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的分享

以 游戏窗口化助手的UI设计 它的代码为基础进行修改

然后打开 Cheat Engine 找升级经验

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析_第1张图片

然后就找到了

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析_第2张图片

然后接下来看访问,因为它一定是通过某种计算得出这个结果,然后显示出来,它得到的过程就是访问的过程,所以看访问,然后接下来就看它是指怎样把这个东西得出来的,然后又三个位置

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析_第3张图片

这三个位置的代码都差不多,所以先根据第一个分析试试,然后打开x96dbg,先记录数据,好做条件断点,0x6D7C0B

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析_第4张图片

然后可以看出这里好像只有升级经验会触发,它的返回值就是经验

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析_第5张图片

然后它的入参是等级

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析_第6张图片

然后0xA21F20函数的返回值,出了下图红框位置的数据是我们要的升级经验以外,其它都不认识

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析_第7张图片

记录关键信息,0x1036590类,0xA21F20函数

效果图:

CHelperUI.cpp文件的修改:修改了 ShowData函数

// CHelperUI.cpp: 实现文件
//

#include "pch.h"
#include "CHelperUI.h"
#include "afxdialogex.h"
#include "extern_all.h"

void _stdcall TimeProcHelper(HWND, UINT, UINT_PTR, DWORD) {
	if (_ui_helper)_ui_helper->ShowData();
}

IMPLEMENT_DYNAMIC(CHelperUI, CDialogEx)

CHelperUI::CHelperUI(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_HELPER, pParent)
{

}

CHelperUI::~CHelperUI()
{
}

BOOL CHelperUI::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	this->SetBackgroundColor(RGB(255, 255, 255));
	HPBar.SetBkColor(RGB(0 ,0, 0));
	MPBar.SetBkColor(RGB(0 ,0, 0));
	RageBar.SetBkColor(RGB(0 ,0, 0));
	ExBar.SetBkColor(RGB(0 ,0, 0));
	

	HPBar.SetBarColor(RGB(255 ,0, 0));
	MPBar.SetBarColor(RGB(0x0, 0x0, 0x99));
	RageBar.SetBarColor(RGB(0x66, 0x0, 0x66));
	ExBar.SetBarColor(RGB(0x00, 0xFF, 0xCC));

	HPBar.SetRange(0, 999);
	MPBar.SetRange(0, 1000);
	RageBar.SetRange(0, 5);
	ExBar.SetRange(0, 1000);

	//HPBar.SetPos(50);
	//MPBar.SetPos(50);
	//RageBar.SetPos(50);
	//ExBar.SetPos(50);

	::SetTimer(this->m_hWnd, 0x100002, 100, TimeProcHelper);

	return TRUE;
}

void CHelperUI::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_PRO_HP, HPBar);
	DDX_Control(pDX, IDC_PRO_MP, MPBar);
	DDX_Control(pDX, IDC_PRO_RAGE, RageBar);
	DDX_Control(pDX, IDC_PRO_RAGE2, ExBar);
}


BEGIN_MESSAGE_MAP(CHelperUI, CDialogEx)
	ON_BN_CLICKED(IDOK, &CHelperUI::OnBnClickedOk)
END_MESSAGE_MAP()


// CHelperUI 消息处理程序


void CHelperUI::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	CDialogEx::OnOK();
}

void CHelperUI::ShowData()
{
	CString tmp;
	auto _player = _pgamebase->SRO_Player;
	if (_player) {
		tmp.Format(L"%s Lv %d", _player->Name.wcstrByName(), _player->Lv);
		this->SetWindowText(tmp);
		float hpStep = _player->HP * 1000;
		hpStep = hpStep / _player->MaxHP;
		HPBar.SetPos(hpStep);

		float mpStep = _player->MP * 1000;
		mpStep = mpStep / _player->MaxMP;
		MPBar.SetPos(mpStep);
		RageBar.SetPos(_player->Rage);

		unsigned max_exp = _pgamebase->SRO_Core->GetLvMaxExp(_player->Lv)->Exp;
		float expSetp = _player->Exp * 1000;
		expSetp = expSetp / max_exp;
		ExBar.SetPos(expSetp);

		tmp.Format(L"%.1f %.1f %.1f", _player->x, _player->h, _player->y);
		GetDlgItem(IDC_STATIC_CORD)->SetWindowText(tmp);
	}
}

GameBase.h文件的修改:新加 SRO_Core变量

#pragma once
#include "Res.h"
#include "Control.h"
#include "AIM.h"
#include "ITEM.h"
#include "Core.h"

class GameBase
{
	void InitClassProc(LPVOID proc_addr, unsigned value);
public:
	void Init();
	GameBase();
	PRes SRO_Res;
	PControl SRO_Control;
	PAIM SRO_Player;
	PCore SRO_Core;
};

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

#include "pch.h"
#include "GameBase.h"

GameBase* _pgamebase;

void GameBase::Init()
{
	unsigned* addrRead = (unsigned*)0x1256E3C;

	SRO_Res = (PRes)0x1036518;
	SRO_Control = (PControl)addrRead[0];
	addrRead = (unsigned*)0x1037D3C;
	SRO_Player = (PAIM)addrRead[0];
	SRO_Core = (PCore)0x1036590;
	
	InitClassProc(&Res::_ReadTitle, 0x9A46C0);
	InitClassProc(&Res::_ReadItemTitle, 0x9A4640);
	InitClassProc(&Control::_NormalNotice, 0x848580);
	InitClassProc(&Control::_NetNotice, 0x844E40);
	InitClassProc(&Control::_ChatNotice, 0x844E80);
	InitClassProc(&Control::_GetPPack, 0x866140);
	InitClassProc(&Control::_UseItem, 0x85F640);
	InitClassProc(&Control::_MangeItem, 0x864220);
	InitClassProc(&ITEM::_GetItemRes, 0x995800);
	InitClassProc(&Pack::_GetPackPack, 0x7722C0);
	InitClassProc(&Pack::_GetEquipPack, 0x772300);
	InitClassProc(&Core::_GetLvMaxExp, 0xA21F20);

}

void GameBase::InitClassProc(LPVOID proc_addr, unsigned value)
{
	unsigned* uWrite = (unsigned*)proc_addr;
	uWrite[0] = value;
}

GameBase::GameBase()
{
	_pgamebase = this;
	// Init();// 初始化机制,完成游戏与我们dll的对接
}

新加Core.cpp文件:

#include "pch.h"
#include "Core.h"
Core::PROC_D Core::_GetLvMaxExp{};
PLvData Core::GetLvMaxExp(unsigned lv)
{
	return (PLvData)(this->*_GetLvMaxExp)(lv);
}

新加Core.h文件:

#pragma once

typedef struct LvData {
	int un0[2];
	unsigned Exp;
	int un1;
}*PLvData;

typedef class Core
{
	typedef int(Core::* PROC_D)(unsigned);
public:
	static PROC_D _GetLvMaxExp;
	PLvData GetLvMaxExp(unsigned lv);

}*PCore;

你可能感兴趣的:(游戏,网游逆向,c++)