2014-08-25

英雄联盟无限视距实现代码

原理

游戏进程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

没有评论:

发表评论

Android Root Zap Framework

‎ 1. Warning 请遵守GPL开源协议, 请遵守法律法规, 本项目仅供学习和交流, 请勿用于非法用途! 道路千万条, 安全第一条, 行车不规范, 亲人两行泪. 2. Android Root Zap Frame...