需求:
在游戏窗口化时,能够在游戏之外弹出一个窗口,可以隐藏或者显示游戏窗口,显示游戏人物的基本状态,以及其他重要的信息
UI绘制略...
分析升级经验值:
直接搜数字
改一个 发现变了,那就是这个了。
然后看什么访问这个数据,因为肯定是用某种算法求出这个然后显示到了这个地方,就看看怎么得出这个
eax刚好是等级
call后刚好就是要的结果 。
还原:
老套路了。。
typedef struct LvData
{
int un[2];
unsigned Exp;
int un1;
}*PlvData;
typedef class Core
{
typedef PlvData(Core::* PROC_D)(unsigned);
public:
static PROC_D _GetLvMaxExp;
PlvData GetLvMaxExp(unsigned lv);
#include "Core.h"
Core::PROC_D Core::_GetLvMaxExp{};
PlvData Core::GetLvMaxExp(unsigned lv)
{
return (this->*_GetLvMaxExp)(lv);
}
SRO_Core = (PCore)0x1036590;
InitClassProc(&Core::_GetLvMaxExp, 0xA21F20);
地图数据获取的逆向分析
直接先搜字符串
发现用的是第四个数据
直接看是什么访问
x32打开直接下条件断点eax==141d5f38
走一步就断下、
栈里还能看到长安的字符串
就一直往前
到这儿就没有了
所以就是调用了这个函数,走一步断下,然后看看是从哪儿开始出现的“长安”
上面这个函数里,长安出现了
这个函数刚好是之前封装过得函数,传入的是wchar_t 的字符串
传入一个25000字符串就返回的长安
再往上看
这个函数过后 就出现了25000 这个函数来得到25000
进去看看 4 个参数 传入61A8返回的25000
改一下61A9发现是25001,多试几次,发现这个函数就是16进制转十进制,就不需要调用这个函数了
61A8是来自EBP
发现直接得出来的就是61A8
eax来自1037D3C 1037D3C是玩家指针
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实现
void CHelperUI::Show()
{
MoveHelper();
this->ShowWindow(TRUE);
}
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();
}
}
void CHelperUI::MoveHelper()
{
if (hwndGame)
{
CRect rect;
::GetWindowRect(hwndGame, &rect);
int helper_left = rect.left - helper_Width;
if (helper_left < 0)helper_left = rect.left;
::MoveWindow(this->m_hWnd, helper_left, rect.top, helper_Width, rect.Height(), TRUE);
}
}
void CHelperUI::OnBnClickedOk2()//隐藏
{
if (hwndGame)
{
::ShowWindow(hwndGame, GameShow=!GameShow);
}
}
void CHelperUI::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (hwndGame)
{
::ShowWindow(hwndGame, GameShow = true);
ShowWindow(FALSE);
}
//CDialogEx::OnClose();
}
发现这个小窗口不会随着客户端的移动而移动,在没有游戏源代码情况下,最好的方法就是设置一个钩子
实现:
hookGameWnd = SetWindowsHook(WH_CALLWNDPROC, CallWndProc);//钩子
LRESULT CALLBACK 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)
{
_ui_helper->HideGame();
}
}
}
return CallNextHookEx(_ui_helper->hookGameWnd, nCode, wParam, lParam);
}