原理
游戏进程League of Legends.exe
中某个偏移记录着视距值,游戏根据这个数值设置你的当前游戏的屏幕分辨率,最大只能达到屏幕的极限分辨率那么大,所以一旦调的太大了外面只能看到黑色一片。
实现方法
修改的方法也分两种,一种是将进程文件League of Legends.exe
打开直接搜索其中默认的Float类型视距值2250,将其改为最大值4450,最大值其实没有上限,不过改的再大也是4450的效果。这种方法有个缺点,就是游戏一旦更新,这个进程文件改变,相应的偏移位置也会发生变化,所以还要重新去修改,比较麻烦。
这里说第二种方法,游戏运行起来后,动态从内存中搜索到视距值的位置,直接通过注入的方式,将视距值动态写进去,为减少对游戏的影响,只在进入游戏界面的时候进行修改操作,游戏结束后将原始视距值复原。并且为了兼容以后视距原始值以及修改最大值的变更,将这些参数全写入配置文件,想更改只需要修改配置文件里相应的值即可。
实现代码
主流程逻辑
#include "stdafx.h"
#include "SightFunc.h"
extern "C" WINBASEAPI HWND WINAPI GetConsoleWindow ();
/*
#define oldSightValue 0x450CA000 //2250
#define newSightValue 0x457A0000 //4000
#define newSightValue 0x453B8000 //3000
#define newSightValue 0x458B1000 //4450
*/
int _tmain(int argc, _TCHAR* argv[])
{
WinInit();
int flag = 0;
BOOL isNewSight = FALSE;
DWORD dwProcId = 0;
HANDLE hProcess = NULL;
BYTE *pTagModBaseAddr = NULL;
// 如果已有互斥量存在则释放句柄并复位互斥量
HANDLE m_hMutex = CreateMutexW(NULL, FALSE, L"idhyt");
if (ERROR_ALREADY_EXISTS == GetLastError())
{
wprintf(L"The Program has been running! ErrorCode: %d\n", GetLastError());
goto gleave;
}
//L"SeDebugPrivilege"
EnablePrivilege(SE_DEBUG_NAME, TRUE);
dwProcId = GetProcessIdByName(L"League of Legends.exe");
if (0 == dwProcId)
{
wprintf(L"Get ProcessID error! ErrorCode: %d\n", GetLastError());
printf("选择完英雄,进入读条状态时再启用!\n\n");
goto gleave;
}
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcId);
if (NULL == hProcess)
{
wprintf(L"Get ProcessHandle error! ErrorCode: %d\n", GetLastError());
goto gleave;
}
pTagModBaseAddr = GetProcessModBaseAddr(L"League of Legends.exe", dwProcId);
if (NULL == pTagModBaseAddr)
{
wprintf(L"Get pTagModBaseAddr error! ErrorCode: %d\n", GetLastError());
goto gleave;
}
PINI_ProfileInfor pIniProfileInfor = GetPrivateProfileInfor();
if (pIniProfileInfor->bRet == TRUE)
{
while (true)
{
Sleep(1000);
dwProcId = 0;
hProcess = NULL;
pTagModBaseAddr = NULL;
isNewSight = FALSE;
dwProcId = GetProcessIdByName(L"League of Legends.exe");
if (0 == dwProcId)
{
if (flag == 0)
{
printf("等待进入游戏... ErrorCode: %d\n", GetLastError());
}
flag ++ ;
continue;
}
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcId);
if (NULL == hProcess)
{
wprintf(L"Get ProcessHandle error! ErrorCode: %d\n", GetLastError());
continue;
}
pTagModBaseAddr = GetProcessModBaseAddr(L"League of Legends.exe", dwProcId);
if (NULL == pTagModBaseAddr)
{
wprintf(L"Get pTagModBaseAddr error! ErrorCode: %d\n", GetLastError());
continue;
}
isNewSight = SetNewSight(hProcess, pTagModBaseAddr, pIniProfileInfor->newSight, pIniProfileInfor->oldSight, pIniProfileInfor->dwRVA);
if (isNewSight == TRUE)
{
wprintf(L"Chage Sight Success!\n");
Sleep(3000);
ShowWindow(GetConsoleWindow(), SW_HIDE);
}
else
{
wprintf(L"Chage Sight False!\n");
continue;
}
while (GetProcessIdByName(L"League of Legends.exe"))
{
Sleep(5000);
}
Sleep(3000);
ShowWindow(GetConsoleWindow(), SW_SHOW);
flag = 0;
system("cls");
printf("若继续使用无限视距功能,请勿关闭该窗口!\n");
}
}
gleave:
if (hProcess)
CloseHandle(hProcess);
if (m_hMutex)
CloseHandle(m_hMutex);
EnablePrivilege(SE_DEBUG_NAME, FALSE);
system("pause");
return 0;
}
用到的功能函数
// SightFunc.cpp
#include "stdafx.h"
#include "SightFunc.h"
DWORD WINAPI GetProcessIdByName(LPCTSTR lpFilename)
{
HANDLE hProcessSnap = NULL;
DWORD dwProcessId = 0;
PROCESSENTRY32 pe32 = {0};
pe32.dwSize = sizeof(PROCESSENTRY32);
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
return 0;
if(!Process32First(hProcessSnap,&pe32))
{
int i = GetLastError();
CloseHandle(hProcessSnap);
return 0;
}
do
{
if(0 == _wcsicmp(pe32.szExeFile,lpFilename))
{
dwProcessId = pe32.th32ProcessID;
break;
}
}
while(Process32Next(hProcessSnap,&pe32));
CloseHandle(hProcessSnap);
return dwProcessId;
}
//返回进程指定模块基址
BYTE *GetProcessModBaseAddr(LPCTSTR lpFilename, DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32 = {0};
me32.dwSize = sizeof( MODULEENTRY32 );
BYTE *pModBaseAddr = NULL;
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if(INVALID_HANDLE_VALUE == hModuleSnap)
{
wprintf(L"CreateToolhelp32Snapshot (of modules %d) Error! ErrorCode: %d", dwPID, GetLastError());
goto gleave;
}
if( Module32First( hModuleSnap, &me32 ))
{
do
{
if(0 == _wcsicmp(me32.szModule,lpFilename))
{
pModBaseAddr = me32.modBaseAddr;
break;
}
} while( Module32Next( hModuleSnap, &me32 ) );
}
else
{
wprintf(L"Module32First Error! ErrorCode: %d", GetLastError());
goto gleave;
}
gleave:
if (hModuleSnap)
CloseHandle( hModuleSnap );
return pModBaseAddr;
}
/*
功能: 是否开启Debug权限
参数: lpName:"SeDebugPrivilege"
fEnable:TRUE表示开启,反之禁用
返回值: TRUE/FLASE
SE_DEBUG_NAME SeDebugPrivilege
*/
BOOL EnablePrivilege(LPCTSTR lpszPrivilegeName, BOOL bEnable)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp = {0};
LUID luid = {0};
BOOL bRet = FALSE;
if(!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES |
TOKEN_QUERY | TOKEN_READ,
&hToken))
{
bRet =FALSE;
goto gleave;
}
if(LookupPrivilegeValue(NULL, lpszPrivilegeName, &luid))
{
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
if (AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,NULL))
{
bRet = TRUE;
}
}
gleave:
if (hToken)
CloseHandle(hToken);
return bRet;
}
VOID WinInit()
{
system("color 02 & title 英雄联盟无限视距修改器");
time_t timer;
time(&timer);
struct tm newtime;
localtime_s(&newtime, &timer);
//wprintf(L"***********************************\n");
wprintf(L"%d.%d.%d", newtime.tm_year+1900, newtime.tm_mon+1, newtime.tm_mday);
printf("--> 右键->管理员身份运行,请低调使用!\n");
printf("--> 默认视距4000,修改说明:Infinite Sight.ini\n");
printf("--> 选完英雄,进入游戏读条界面以后使用!\n");
printf("--> 勿传播,勿做非法用途!!! \n");
printf(" Date 2014.08.25 \n\n");
printf("--------------------------------------\n\n");
}
//获取配置文件信息
PINI_ProfileInfor GetPrivateProfileInfor()
{
DWORD bRet = 0;
PINI_ProfileInfor pIniProfileInfor = new INI_ProfileInfor;
memset(pIniProfileInfor, 0, sizeof(INI_ProfileInfor));
WCHAR strPath[MAX_PATH] = {0};
WCHAR strIniPath[MAX_PATH] = {0};
DWORD newSight = 0;
DWORD oldSight = 0;
DWORD dwRVA = 0;
bRet = GetCurrentDirectoryW(MAX_PATH,strPath);
if (bRet > MAX_PATH)
{
pIniProfileInfor->bRet = FALSE;
wprintf(L"GetCurrentDirectory Error! ErrorCode: %d\n", GetLastError());
goto gleave;
}
swprintf_s(strIniPath, MAX_PATH, L"%s%s", strPath, L"\\Infinite Sight.ini");
newSight = GetPrivateProfileInt(L"New Sight", L"newSight", 0, strIniPath);
if (2250 > newSight || 4000 < newSight)
{
pIniProfileInfor->bRet = FALSE;
wprintf(L"The newSight Value Error!\n");
goto gleave;
}
oldSight = GetPrivateProfileInt(L"Old Sight", L"oldSight", 0, strIniPath);
if (2250 != oldSight)
{
pIniProfileInfor->bRet = FALSE;
wprintf(L"The oldSight Value Error!\n");
goto gleave;
}
dwRVA = GetPrivateProfileInt(L"Error", L"Value", 0, strIniPath);
if (0 == dwRVA)
{
pIniProfileInfor->bRet = FALSE;
wprintf(L"The dwRVA Value Error!\n");
goto gleave;
}
pIniProfileInfor->newSight = float2hex(newSight);
pIniProfileInfor->oldSight = float2hex(oldSight);
pIniProfileInfor->dwRVA = dwRVA;
pIniProfileInfor->bRet = TRUE;
gleave:
return pIniProfileInfor;
}
DWORD float2hex(float f)
{
DWORD h = 0;
char *pf = (char*)&f;
if (pf)
{
h = *(DWORD *)pf;
}
return h;
}
BOOL SetNewSight(HANDLE hProcess, BYTE *pTagModBaseAddr, DWORD newSightValue, DWORD oldSightValue, DWORD dwRVA)
{
BOOL bRet = FALSE;
BOOL isNewSight = FALSE;
DWORD dwSight = 0;
DWORD dwRead = 0;
DWORD dwNewSight = 0;
DWORD dwWrite = 0;
DWORD dwOldProtect = 0;
DWORD dwInitProtect = 0;
pTagModBaseAddr = pTagModBaseAddr + dwRVA;
bRet = VirtualProtectEx(hProcess, pTagModBaseAddr, 0x4, 0x40, &dwInitProtect); //PAGE_EXECUTE_READWRITE
if (!bRet)
{
wprintf(L"Change PAGA_attribute error! ErrorCode: %d\n", GetLastError());
goto gleave;
}
bRet = ReadProcessMemory(hProcess, pTagModBaseAddr, &dwSight, 4, &dwRead);
if (!bRet)
{
wprintf(L"ReadProcessMemory error! ErrorCode: %d\n", GetLastError());
goto gleave;
}
if (oldSightValue == dwSight && 4 == dwRead)
{
dwNewSight = newSightValue;
bRet = WriteProcessMemory(hProcess, pTagModBaseAddr, &dwNewSight, 4, &dwWrite);
if (!bRet)
{
wprintf(L"WriteProcessMemory error! ErrorCode: %d\n", GetLastError());
goto gleave;
}
isNewSight = TRUE;
}
else
{
isNewSight = FALSE;
wprintf(L"The Sight Value not found!\n");
}
bRet = VirtualProtectEx(hProcess, pTagModBaseAddr, 0x4, dwInitProtect, &dwOldProtect); //0x40 PAGE_EXECUTE_READWRITE
if (!bRet)
{
wprintf(L"Resume PAGA_attribute error! ErrorCode: %d\n", GetLastError());
}
gleave:
return isNewSight;
}
配置文件模版
[说明]
文件名为:Infinite Sight.ini
默认视距为最大值4000,如需修改视距,改变new Sight值即可,如3000视距改为new Sight = 3000,修改值必须在2250-4000之间!
请勿移动本配置文件,需和Infinite Sight.exe在同目录下。
此插件为个人使用,请勿非法传播 :)
[New Sight]
newSight = 4000
[Old Sight]
oldSight = 2250
没有评论:
发表评论