前言:
在游戏中我们可以通过鼠标滑轮来对视距进行调整,今天就来逆向一下视距达到无限视距把。
工具:
思路:
首先我们需要猜测视距的实现思路,通常这种东西都是数值,鼠标滑轮滚动那么数值就增加或者减少。但是我们不知道他的具体数值所以需要使用CE来搜索。 数据查找:
首先使用CE附加游戏:
LOL逆向之无限视距
然后选择数值类型为浮点型,扫描类型为未知的初始值:
LOL逆向之无限视距
点击首次扫描后会有几千个值,这个我们再次选择未变动的数值,应该我们刚刚没有更改视距:
LOL逆向之无限视距
然后在游戏中把视距拉到最小,搜索减少的数值:
LOL逆向之无限视距
在把游戏中的视距拉到最大搜索增加的数值:
LOL逆向之无限视距
由此反复操作N次之后我们索引到两个值:
LOL逆向之无限视距
所以我们最大视距为2250,这两个值一个是当前视距一个是最大视距,判断代码大概是这样的:
if(当前视距==最大视距){
break;
}
所以我们想要实现无限视距的思路大概就是将最大视距改变或者将判断给过掉,这里把两个数据都拉下来:
LOL逆向之无限视距
然后右键找出是什么改写了这个值:
LOL逆向之无限视距
这里CE帮我们找到了一行汇编代码,选中这行代码后右键,在汇编程序中打开地址:
LOL逆向之无限视距
在程序中直接寻找进行比较的汇编代码,往上数9行就找到了:
LOL逆向之无限视距
把这行代码nop掉就可以实现无限视距了,但是这样不利于我们写代码,所以我们需要进行分析汇编代码来找到最大视距进行更改:
League of Legends.AK::WriteBytesMem::Count+3919CE - 0F2F C8 - comiss xmm1,xmm0
League of Legends.AK::WriteBytesMem::Count+3919D1 - 77 09 - ja "League of Legends.AK::WriteBytesMem::Count"+3919DC
League of Legends.AK::WriteBytesMem::Count+3919D3 - F3 0F10 40 24 - movss xmm0,[eax+24]
League of Legends.AK::WriteBytesMem::Count+3919D8 - F3 0F5F C1 - maxss xmm0,xmm1
League of Legends.AK::WriteBytesMem::Count+3919DC - 0F2E 86 60020000 - ucomiss xmm0,[esi+00000260]
League of Legends.AK::WriteBytesMem::Count+3919E3 - B0 01 - mov al,01
League of Legends.AK::WriteBytesMem::Count+3919E5 - 9F - lahf
League of Legends.AK::WriteBytesMem::Count+3919E6 - F6 C4 44 - test ah,44
League of Legends.AK::WriteBytesMem::Count+3919E9 - 7B 12 - jnp "League of Legends.AK::WriteBytesMem::Count"+3919FD
League of Legends.AK::WriteBytesMem::Count+3919EB - F3 0F11 86 60020000 - movss [esi+00000260],xmm0
从我们定位到的那行代码开始分析,[zxsq-anti-bbcode-esi+00000260]就是当前视距,更改的视距会放如[zxsq-anti-bbcode-esi+00000260]里面,但是[zxsq-anti-bbcode-esi+00000260]是由xmm0赋值的:
movss [zxsq-anti-bbcode-esi+00000260],xmm0
翻译C++
当前视距 = xmm0
所以我们需要去查找xmm0是从哪里来的:
LOL逆向之无限视距
在红框中任意代码位置下断点看下能不能断下:
LOL逆向之无限视距
这里已经被断下了,说明xmm0是由xmm1传过来的,但是上面有一行代码在进行比较:
League of Legends.AK::WriteBytesMem::Count+3919CE - comiss xmm1,xmm0
经过刚才的分析我们知道了xmm1是要更改的视距,所以xmm0就应该是最大视距: xmm1 = 需要更改的视距
xmm0 = 最大视距
if(xmm1 == xmm0){
exit;
}
当前视距=xmm1
这里我们需要去追xmm0是从哪里来的:
LOL逆向之无限视距
此时xmm0 = [zxsq-anti-bbcode-eax+28],我们在追eax是哪里来的:
LOL逆向之无限视距
eax = [zxsq-anti-bbcode-esi+250],当前xmm0 = [zxsq-anti-bbcode-[esi+250]+28],在寻找esi是哪里来的:
LOL逆向之无限视距
esi=[zxsq-anti-bbcode-eax+0c],此时xmm0=[zxsq-anti-bbcode-[[eax+0c]+250]+28],在寻找eax是哪里来的:
LOL逆向之无限视距
eax的地址是一个基地址,这里解释下什么是基地址,基地址可以理解为web中的绝对路径,就是不会变的,那么基地址+偏移=虚拟地址。所以最终xmm0=[zxsq-anti-bbcode-[[[02067E14]]+0c]+250]+28]。
我们在CE中加入地址看看:
LOL逆向之无限视距
这里得到的值是2250,也就是我们的最大视距,将2250更改为9999:
LOL逆向之无限视距
到这里无限视距的数据就算找到了,接下来要做的就是把无限视距写成c++代码:
代码:
首先说下需要用到以下函数:
FindWindowA() 获取窗口句柄
GetWindowThreadProcessId() 获取进程ID
OpenProcess() 打开进程
ReadProcessMemory() 读取地址值
WriteProcessMemory() 写入值
详细代码如下:
#include <Windows.h>
#include <stdio.h>
void main() {
HWND 窗口 = FindWindowA("RiotWindowClass","League of Legends (TM) Client");
DWORD 进程ID;
GetWindowThreadProcessId(窗口,&进程ID);
HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS,FALSE,进程ID);
if (进程句柄 == NULL)
{
printf("进程打开失败:%d\n",GetLastError());
return;
}
DWORD 基址 = 0x02067E14;
DWORD 基址值=0;
DWORD dwsize = 0;
if (ReadProcessMemory(进程句柄, (LPVOID)基址, &基址值, sizeof(DWORD), &dwsize) == 0) {
printf("静态地址获取失败:%d\n", GetLastError());
return;
}
DWORD 一级偏移 = 0xc;
DWORD 一级偏移值;
if (ReadProcessMemory(进程句柄, LPVOID(基址值+ 一级偏移), &一级偏移值, sizeof(DWORD), &dwsize) == 0) {
printf("一级偏移获取失败:%d\n", GetLastError());
return;
}
DWORD 二级偏移 = 0x250;
DWORD 二级偏移值;
if (ReadProcessMemory(进程句柄, LPVOID(一级偏移值 + 二级偏移), &二级偏移值, sizeof(DWORD), &dwsize) == 0) {
printf("二级偏移获取失败:%d\n", GetLastError());
return;
}
DWORD 三级偏移 = 0x28;
float 三级偏移值;
if (ReadProcessMemory(进程句柄, LPVOID(二级偏移值 + 三级偏移), &三级偏移值, sizeof(DWORD), &dwsize) == 0) {
printf("三级偏移获取失败:%d", GetLastError());
return;
}
printf("视距最大值为:%f\n",三级偏移值);
float 视距修改 = 9999.0;
if (WriteProcessMemory(进程句柄, LPVOID(二级偏移值 + 三级偏移), &视距修改, sizeof(float), &dwsize)) {
printf("修改成功..\n");
}
else {
printf("修改失败:%d\n",GetLastError());
}
CloseHandle(进程句柄);
getchar();
}
|