内容参考于:易道云信息技术研究院VIP课
上一个内容:解读聊天数据包并且利用Net发送
码云地址(游戏窗口化助手 分支):https://gitee.com/dye_your_fingers/sro_-ex.git
码云版本号:cc6370dc5ca6b0176aafc6d1243b900eb6fccc69
代码下载地址,在 SRO_EX 目录下,文件名为:SRO_Ex-解读喊话道具数据包并且利用Net发送.zip
链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg
提取码:q9n5
--来自百度网盘超级会员V4的分享
HOOK引擎,文件名为:黑兔sdk.zip
链接:https://pan.baidu.com/s/1IB-Zs6hi3yU8LC2f-8hIEw
提取码:78h8
--来自百度网盘超级会员V4的分享
以 解读聊天数据包并且利用Net发送 它的代码为基础进行修改
效果图:
付费道具全体聊天,从下图中的数据包,看不出什么东西来,首先它没有背包相关的数据,也没有物品所在背包的序号
所以再使用下图红框位置的全体聊天道具来发送一个消息,然后对比这俩物品发送数据的数据包有什么不同
它的数据包结构
对比:
然后把物品换一下位置
使用物品
使用第二个位置的物品
使用第三个位置的物品
然后可以看出,第一个字节是物品在背包里的序号,序号是从D开始
然后使用药物时的数据包结构
然后把药品移动到第一个位置,再使用,这时的数据包
除了第一个字节,其余字节都没有变化,然后物品id不可能用完四个字节这么大
九千万的数字,才只有26个字节大小,很显然物品id不可能有四字节,所以数据包后面的四字节肯定有它自己的意思,所以继续使用不同的物品从而对比分析它们的数据包的变化,然后找出规律,然后猜测它们都是什么意思,然后写C++
使用其它buffer类物品
使用道具:
分析结构,下图红框位置,前三个是全体聊天的结构,第四个是使用修理锤子道具的数据包,然后修理锤子数据包第一个字节是序号,第二个字节和第三个字节表示付费道具,第四个字节和第五个字节只能认为它是物品的id,然后全体聊天的数据包,第一个是序号,第二个字节和第三个字节表示付费道具,第四个和第五个字节是物品id,第六个和第七个是发送消息的长度,后面的就是发送的数据了,然后通过对比使用物品的数据包得出以上结果,然后它的结构体就可以定下来了
CHelperUI.cpp文件的修改,新加 TalkData结构体,修改了 OnBnClickedOk函数
// CHelperUI.cpp: 实现文件
//
#include "pch.h"
#include "CHelperUI.h"
#include "afxdialogex.h"
#include "extern_all.h"
LRESULT _stdcall CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == 0) {
// 这里接收到的不只有游戏窗口的消息,还有我们的窗口消息
// 所以要排除掉我们的窗口
PCWPSTRUCT tmp = (PCWPSTRUCT)lParam;
// 判断当前触发消息的窗口句柄是不是我们的游戏窗口句柄
if (tmp->hwnd == _ui_helper->hwndGame) {
// 拦截移动窗口消息
if (tmp->message == WM_MOVE) {
// 移动我们的窗口
_ui_helper->MoveHelper();
}
if (tmp->message == WM_CLOSE) {
// 游戏窗口右上角的X关闭按钮屏蔽掉了,这里我们给它处理一下
// 让它点击之后可以隐藏游戏窗口并且显示我们的窗口
/**
_ui_helper->HideGame(); 里执行的代码如下面的两行
this->ShowWindow(TRUE);
::ShowWindow(hwndGame, GameShow = false);
*/
_ui_helper->HideGame();
}
}
}
return CallNextHookEx(_ui_helper->hookGameWnd, nCode, wParam, lParam);
}
void _stdcall TimeProcHelper(HWND, UINT, UINT_PTR, DWORD) {
if (_ui_helper)_ui_helper->ShowData();
}
//获取程序当前所在显示器的分辨率大小,可以动态的获取程序所在显示器的分辨率
SIZE GetScreenResolution(HWND hWnd) {
SIZE size{};
if (!hWnd)
return size;
//MONITOR_DEFAULTTONEAREST 返回值是最接近该点的屏幕句柄
//MONITOR_DEFAULTTOPRIMARY 返回值是主屏幕的句柄
//如果其中一个屏幕包含该点,则返回值是该屏幕的HMONITOR句柄。如果没有一个屏幕包含该点,则返回值取决于dwFlags的值
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX miex;
miex.cbSize = sizeof(miex);
if (!GetMonitorInfo(hMonitor, &miex))
return size;
DEVMODE dm;
dm.dmSize = sizeof(dm);
dm.dmDriverExtra = 0;
//ENUM_CURRENT_SETTINGS 检索显示设备的当前设置
//ENUM_REGISTRY_SETTINGS 检索当前存储在注册表中的显示设备的设置
if (!EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm))
return size;
size.cx = dm.dmPelsWidth;
size.cy = dm.dmPelsHeight;
return size;
}
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)
ON_BN_CLICKED(IDOK2, &CHelperUI::OnBnClickedOk2)
ON_WM_CLOSE()
END_MESSAGE_MAP()
// CHelperUI 消息处理程序
struct TalkData{
char un;
char slip;
short txtlenth;
};
struct ChatData {
char un; // 内存对齐
char id;// 频道
short index; // 说话内容的序号
short lenth; // 说话内容的长度
char text[0x50]; // 说话的内容
};
void CHelperUI::OnBnClickedOk()
{
char talk[]{ "欢迎来到地球!" };
char buff[0xFF]{};
int len;
//auto netdata = _pgamebase->SRO_Net->CreateNetData(0x7025, 0x0);
auto netdata = _pgamebase->SRO_Net->CreateNetData(0x704C, 0x1);
ChatData chat{};
chat.id = 0xD;
chat.index = 0x0C31;
chat.lenth = 0x0503;
TalkData* t = (TalkData*)(chat.text - 1);
t->slip = 0x0;
t->txtlenth = sizeof(talk) - 1;
/*chat.id = 1;
chat.index = 1;
chat.lenth = sizeof(talk) -1 ;*/
memcpy(chat.text + 3, talk, t->txtlenth);
len = t->txtlenth + 8;
netdata->MakeData(&chat.id, len);
_pgamebase->SRO_Net->SendData(netdata);
// CDialogEx::OnOK();
//CString tmp;
//tmp.Format(L"%d", _pgamebase->SRO_Player->MapId);
//AfxMessageBox(tmp);
//
//CString city;
//city.Format(L"%s", _pgamebase->SRO_Res->ReadTitle(tmp.GetBuffer())->wcstr());
//AfxMessageBox(city);
// _ui->UIShow();
}
void CHelperUI::Init()
{
if (hwndGame) return;
wchar_t buff[0xFF]{};
// 获取主窗口句柄
HWND _hwnd = ::GetActiveWindow();
// 获取窗口标题
::GetWindowText(_hwnd, buff, 0xFF);
CString _title = buff;
if (_title == L"SRO_CLIENT") {
hwndGame = _hwnd;
CRect rect_me;
// 获取当前窗口句柄
GetWindowRect(&rect_me);
helper_Width = rect_me.Width();
SetWindowsHook(WH_CALLWNDPROC, CallWndProc);
}
}
void CHelperUI::MoveHelper()
{
if (hwndGame) {
CRect rect;
// 获取游戏窗口(主窗口)样式
::GetWindowRect(hwndGame, &rect);
int helper_left = rect.left + rect.Width();
SIZE windowSize = GetScreenResolution(this->m_hWnd);
if ((helper_left + helper_Width) > windowSize.cx) {
helper_left -= helper_Width;
}
// 设置窗口大小
::MoveWindow(this->m_hWnd, helper_left, rect.top, helper_Width, rect.Height(), TRUE);
}
}
void CHelperUI::ShowData()
{
CString tmp;
CString city;
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);
tmp.Format(L"%d", _pgamebase->SRO_Player->MapId);
city.Format(L"%s", _pgamebase->SRO_Res->ReadTitle(tmp.GetBuffer())->wcstr());
GetDlgItem(IDC_STATIC_MAP)->SetWindowText(city);
}
}
void CHelperUI::Show()
{
MoveHelper();
this->ShowWindow(TRUE);
}
void CHelperUI::OnBnClickedOk2()
{
if (hwndGame) {
::ShowWindow(hwndGame, GameShow = !GameShow);
}
}
void CHelperUI::OnClose()
{
if (hwndGame) {
::ShowWindow(hwndGame, GameShow = true);
this->ShowWindow(FALSE);
}
}
void CHelperUI::HideGame()
{
this->ShowWindow(TRUE);
::ShowWindow(hwndGame, GameShow = false);
}