mirror of
https://github.com/wangdage12/genshin-fps-unlock.git
synced 2026-02-18 02:42:13 +08:00
fix 31-4302
This commit is contained in:
@@ -28,20 +28,20 @@ const std::vector<DWORD> PrioityClass = {
|
|||||||
//credit by winTEuser
|
//credit by winTEuser
|
||||||
const BYTE _shellcode_genshin_Const[] =
|
const BYTE _shellcode_genshin_Const[] =
|
||||||
{
|
{
|
||||||
0x00, 0x00, 0x00, 0x00, //uint32_t unlocker_pid _shellcode_genshin[0]
|
0x00, 0x00, 0x00, 0x00, //uint32_t unlocker_pid _shellcode_genshin[0]
|
||||||
0x00, 0x00, 0x00, 0x00, //FREE _shellcode_genshin[4]
|
0x00, 0xC0, 0x9C, 0x66, //uint32_t shellcode_timestamp _shellcode_genshin[4] //2024-07-21 16:00:00
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 unlocker_FpsValue_addr _shellcode_genshin[8]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //uint64_t unlocker_FpsValue_addr _shellcode_genshin[8]
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 API_OpenProcess _shellcode_genshin[16]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //uint64_t API_OpenProcess _shellcode_genshin[16]
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 API_ReadProcessmem _shellcode_genshin[24]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //uint64_t API_ReadProcessmem _shellcode_genshin[24]
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 API_Sleep _shellcode_genshin[32]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //uint64_t API_Sleep _shellcode_genshin[32]
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 API_MessageBoxA _shellcode_genshin[40]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //uint64_t API_MessageBoxA _shellcode_genshin[40]
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 API_CloseHandle _shellcode_genshin[48]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //uint64_t API_CloseHandle _shellcode_genshin[48]
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //FREE _shellcode_genshin[56]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //FREE _shellcode_genshin[56]
|
||||||
//int3
|
//int3
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
//int3
|
//int3
|
||||||
0x48, 0x83, 0xEC, 0x38, //sub rsp,0x38 _shellcode_genshin[80] _sync_thread
|
0x48, 0x83, 0xEC, 0x38, //sub rsp,0x38 _shellcode_genshin[80] _sync_thread
|
||||||
0x8B, 0x05, 0xA6, 0xFF, 0xFF, 0xFF, //mov eax,dword[unlocker_pid]
|
0x8B, 0x05, 0xA6, 0xFF, 0xFF, 0xFF, //mov eax,dword[unlocker_pid]
|
||||||
0x85, 0xC0, //test eax, eax
|
0x85, 0xC0, //test eax, eax
|
||||||
0x74, 0x5C, //jz return
|
0x74, 0x5C, //jz return
|
||||||
@@ -56,7 +56,7 @@ const BYTE _shellcode_genshin_Const[] =
|
|||||||
0x0F, 0x1F, 0x44, 0x00, 0x00, //nop
|
0x0F, 0x1F, 0x44, 0x00, 0x00, //nop
|
||||||
0x89, 0xF1, //mov ecx, esi //Read_tar_fps
|
0x89, 0xF1, //mov ecx, esi //Read_tar_fps
|
||||||
0x48, 0x89, 0xFA, //mov rdx, rdi
|
0x48, 0x89, 0xFA, //mov rdx, rdi
|
||||||
0x4C, 0x8D, 0x05, 0xF8, 0x00, 0x00, 0x00,//lea r8, qword:[Readmem_buffer]
|
0x4C, 0x8D, 0x05, 0x08, 0x01, 0x00, 0x00,//lea r8, qword:[Readmem_buffer]
|
||||||
0x41, 0xB9, 0x04, 0x00, 0x00, 0x00, //mov r9d, 4
|
0x41, 0xB9, 0x04, 0x00, 0x00, 0x00, //mov r9d, 4
|
||||||
0x31, 0xC0, //xor eax, eax
|
0x31, 0xC0, //xor eax, eax
|
||||||
0x48, 0x89, 0x44, 0x24, 0x20, //mov qword ptr ss:[rsp+20],rax
|
0x48, 0x89, 0x44, 0x24, 0x20, //mov qword ptr ss:[rsp+20],rax
|
||||||
@@ -65,21 +65,23 @@ const BYTE _shellcode_genshin_Const[] =
|
|||||||
0x74, 0x12, //jz Show msg and closehandle
|
0x74, 0x12, //jz Show msg and closehandle
|
||||||
0xB9, 0xF4, 0x01, 0x00, 0x00, //mov ecx,0x1F4 (500ms)
|
0xB9, 0xF4, 0x01, 0x00, 0x00, //mov ecx,0x1F4 (500ms)
|
||||||
0xFF, 0x15, 0x72, 0xFF, 0xFF, 0xFF, //call [API_Sleep]
|
0xFF, 0x15, 0x72, 0xFF, 0xFF, 0xFF, //call [API_Sleep]
|
||||||
0xE8, 0x4D, 0x00, 0x00, 0x00, //call Sync_auto
|
0xE8, 0x5D, 0x00, 0x00, 0x00, //call Sync_auto
|
||||||
0xEB, 0xCB, //jmp Read_tar_fps
|
0xEB, 0xCB, //jmp Read_tar_fps
|
||||||
0xE8, 0x66, 0x00, 0x00, 0x00, //call Show Errormsg and CloseHandle
|
0xE8, 0x76, 0x00, 0x00, 0x00, //call Show Errormsg and CloseHandle
|
||||||
0x48, 0x83, 0xC4, 0x38, //add rsp,0x38
|
0x48, 0x83, 0xC4, 0x38, //add rsp,0x38
|
||||||
0xC3, //return
|
0xC3, //return
|
||||||
0xCC,
|
|
||||||
//int3
|
//int3
|
||||||
0x89, 0x0D, 0xBA, 0x00, 0x00, 0x00, //mov [Game_Current_set], ecx //hook_fps_set _shellcode_genshin[192]
|
0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
|
//int3
|
||||||
|
0x89, 0x0D, 0xBA, 0x00, 0x00, 0x00, //mov [Game_Current_set], ecx //hook_fps_set _shellcode_genshin[0xD0]
|
||||||
0x31, 0xC0, //xor eax, eax
|
0x31, 0xC0, //xor eax, eax
|
||||||
0x83, 0xF9, 0x1E, //cmp ecx, 0x1E
|
0x83, 0xF9, 0x1E, //cmp ecx, 0x1E
|
||||||
0x74, 0x0E, //je set 60
|
0x74, 0x0E, //je set 60
|
||||||
0x83, 0xF9, 0x2D, //cmp ecx, 0x2D
|
0x83, 0xF9, 0x2D, //cmp ecx, 0x2D
|
||||||
0x74, 0x15, //je Sync_buffer
|
0x74, 0x15, //je Sync_buffer
|
||||||
0x90, //nop
|
0x2E, 0xB9, 0xE8, 0x03, 0x00, 0x00, //mov ecx, 0x3E8
|
||||||
0xB9, 0xE8, 0x03, 0x00, 0x00, //mov ecx, 0x3E8
|
|
||||||
0xEB, 0x06, //jmp set
|
0xEB, 0x06, //jmp set
|
||||||
0xCC, //int3
|
0xCC, //int3
|
||||||
0xB9, 0x3C, 0x00, 0x00, 0x00, //mov ecx, 0x3C
|
0xB9, 0x3C, 0x00, 0x00, 0x00, //mov ecx, 0x3C
|
||||||
@@ -89,10 +91,11 @@ const BYTE _shellcode_genshin_Const[] =
|
|||||||
0xEB, 0xF1, //jmp set
|
0xEB, 0xF1, //jmp set
|
||||||
0xCC,
|
0xCC,
|
||||||
//int3
|
//int3
|
||||||
0xB8, 0x78, 0x00, 0x00, 0x00, //mov eax,0x78 //hook_fps_get _shellcode_genshin[240]
|
0xB8, 0x78, 0x00, 0x00, 0x00, //mov eax,0x78 //hook_fps_get _shellcode_genshin[0xF0]
|
||||||
0xC3, //ret
|
0xC3, //ret
|
||||||
//int3
|
//int3
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
//int3
|
//int3
|
||||||
0x8B, 0x05, 0x7A, 0x00, 0x00, 0x00, //mov eax, dword[Game_Current_set] //Sync_auto
|
0x8B, 0x05, 0x7A, 0x00, 0x00, 0x00, //mov eax, dword[Game_Current_set] //Sync_auto
|
||||||
0x83, 0xF8, 0x2D, //cmp eax, 0x2D
|
0x83, 0xF8, 0x2D, //cmp eax, 0x2D
|
||||||
@@ -105,26 +108,27 @@ const BYTE _shellcode_genshin_Const[] =
|
|||||||
//int3
|
//int3
|
||||||
0x48, 0x83, 0xEC, 0x28, //sub rsp, 0x28 //Show Errormsg and closehandle
|
0x48, 0x83, 0xEC, 0x28, //sub rsp, 0x28 //Show Errormsg and closehandle
|
||||||
0x31, 0xC9, //xor ecx, ecx
|
0x31, 0xC9, //xor ecx, ecx
|
||||||
0x48, 0x8D, 0x15, 0x23, 0x00, 0x00, 0x00,//lea rdx, qword:["Sync failed!"]
|
0x48, 0x8D, 0x15, 0x33, 0x00, 0x00, 0x00,//lea rdx, qword:["Sync failed!"]
|
||||||
0x4C, 0x8D, 0x05, 0x2C, 0x00, 0x00, 0x00,//lea r8, qword:["Error"]
|
0x4C, 0x8D, 0x05, 0x3C, 0x00, 0x00, 0x00,//lea r8, qword:["Error"]
|
||||||
0x41, 0xB9, 0x10, 0x00, 0x00, 0x00, //mov r9d, 0x10
|
0x41, 0xB9, 0x10, 0x00, 0x00, 0x00, //mov r9d, 0x10
|
||||||
0xFF, 0x15, 0xE8, 0xFE, 0xFF, 0xFF, //call [API_MessageBoxA]
|
0xFF, 0x15, 0xD8, 0xFE, 0xFF, 0xFF, //call [API_MessageBoxA]
|
||||||
0x89, 0xF1, //mov ecx, esi
|
0x89, 0xF1, //mov ecx, esi
|
||||||
0xFF, 0x15, 0xE8, 0xFE, 0xFF, 0xFF, //call [API_CloseHandle]
|
0xFF, 0x15, 0xD8, 0xFE, 0xFF, 0xFF, //call [API_CloseHandle]
|
||||||
0x48, 0x83, 0xC4, 0x28, //add rsp, 0x28
|
0x48, 0x83, 0xC4, 0x28, //add rsp, 0x28
|
||||||
0xC3, //ret
|
0xC3, //ret
|
||||||
//int3
|
//int3
|
||||||
0xCC, 0xCC, 0xCC,
|
0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
'S','y','n','c',' ','f','a','i','l','e','d','!', 0x00, 0x00, 0x00, 0x00,
|
'S','y','n','c',' ','f','a','i','l','e','d','!', 0x00, 0x00, 0x00, 0x00,
|
||||||
'E','r','r','o','r', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
'E','r','r','o','r', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
|
||||||
0x00, 0x00, 0x00, 0x00, //uint32_t Game_Current_set
|
0x00, 0x00, 0x00, 0x00, //uint32_t Game_Current_set
|
||||||
0x00, 0x00, 0x00, 0x00, //uint32_t Readmem_buffer
|
0x00, 0x00, 0x00, 0x00, //uint32_t Readmem_buffer
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> winTEuser
|
// 特征搜索 winTEuser
|
||||||
static uintptr_t PatternScan_Region(uintptr_t startAddress, size_t regionSize, const char* signature)
|
static uintptr_t PatternScan_Region(uintptr_t startAddress, size_t regionSize, const char* signature)
|
||||||
{
|
{
|
||||||
auto pattern_to_byte = [](const char* pattern)
|
auto pattern_to_byte = [](const char* pattern)
|
||||||
@@ -176,38 +180,6 @@ std::string GetLastErrorAsString(DWORD code)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetModule2(HANDLE GameHandle, std::string ModuleName, PMODULEENTRY32 pEntry)
|
|
||||||
{
|
|
||||||
if (!pEntry)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::vector<HMODULE> modules(1024);
|
|
||||||
ZeroMemory(modules.data(), modules.size() * sizeof(HMODULE));
|
|
||||||
DWORD cbNeeded = 0;
|
|
||||||
|
|
||||||
if (!EnumProcessModules(GameHandle, modules.data(), modules.size() * sizeof(HMODULE), &cbNeeded))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
modules.resize(cbNeeded / sizeof(HMODULE));
|
|
||||||
for (auto& it : modules)
|
|
||||||
{
|
|
||||||
char szModuleName[MAX_PATH]{};
|
|
||||||
if (!GetModuleBaseNameA(GameHandle, it, szModuleName, MAX_PATH))
|
|
||||||
continue;
|
|
||||||
if (ModuleName != szModuleName)
|
|
||||||
continue;
|
|
||||||
MODULEINFO modInfo{};
|
|
||||||
if (!GetModuleInformation(GameHandle, it, &modInfo, sizeof(MODULEINFO)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pEntry->modBaseAddr = (BYTE*)modInfo.lpBaseOfDll;
|
|
||||||
pEntry->modBaseSize = modInfo.SizeOfImage;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
static bool GetModule(DWORD pid, std::string ModuleName, PMODULEENTRY32 pEntry)
|
static bool GetModule(DWORD pid, std::string ModuleName, PMODULEENTRY32 pEntry)
|
||||||
{
|
{
|
||||||
if (!pEntry)
|
if (!pEntry)
|
||||||
@@ -238,7 +210,7 @@ static bool GetModule(DWORD pid, std::string ModuleName, PMODULEENTRY32 pEntry)
|
|||||||
CloseHandle(snap);
|
CloseHandle(snap);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID
|
// 通过进程名搜索进程ID
|
||||||
DWORD GetPID(std::string ProcessName)
|
DWORD GetPID(std::string ProcessName)
|
||||||
{
|
{
|
||||||
DWORD pid = 0;
|
DWORD pid = 0;
|
||||||
@@ -292,43 +264,6 @@ static DWORD64 inject_patch(LPVOID text_buffer, DWORD text_size, DWORD64 _text_b
|
|||||||
DWORD64 Hook_addr_tar_fpsSet = 0;
|
DWORD64 Hook_addr_tar_fpsSet = 0;
|
||||||
DWORD64 _addr_tar_fpsget_TarFun = 0;
|
DWORD64 _addr_tar_fpsget_TarFun = 0;
|
||||||
DWORD64 _addr_tar_fpsSet_TarFun = 0;
|
DWORD64 _addr_tar_fpsSet_TarFun = 0;
|
||||||
while (address = PatternScan_Region(Module_TarSec_RVA, text_size, "CC 8B 05 ?? ?? ?? ?? C3 CC"))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷhook<6F><6B>λ//get_fps
|
|
||||||
{
|
|
||||||
uintptr_t rip = address;
|
|
||||||
rip += 3;
|
|
||||||
rip += *(int32_t*)(rip)+4;
|
|
||||||
if ((rip - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr) == _ptr_fps)
|
|
||||||
{
|
|
||||||
Hook_addr_fpsget = address + 1;
|
|
||||||
Hook_addr_tar_fpsget = Hook_addr_fpsget - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr;
|
|
||||||
goto __Get_fpsGet_addr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(uint64_t*)(address + 1) = 0xCCCCCCCCCCCCCCCC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf_s("Get get_fps pattern Fail! \n");
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
__Get_fpsGet_addr:
|
|
||||||
while (address = PatternScan_Region(Module_TarSec_RVA, text_size, "CC 89 0D ?? ?? ?? ?? C3 CC"))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷhook<6F><6B>λ//set_fps
|
|
||||||
{
|
|
||||||
uintptr_t rip = address;
|
|
||||||
rip += 3;
|
|
||||||
rip += *(int32_t*)(rip)+4;
|
|
||||||
if ((rip - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr) == _ptr_fps)
|
|
||||||
{
|
|
||||||
Hook_addr_fpsSet = address + 1;
|
|
||||||
Hook_addr_tar_fpsSet = Hook_addr_fpsSet - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr;
|
|
||||||
goto __Get_fpsSet_addr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(uint64_t*)(address + 1) = 0xCCCCCCCCCCCCCCCC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf_s("Get set_fps pattern Fail! \n");
|
|
||||||
|
|
||||||
__Get_fpsSet_addr:
|
__Get_fpsSet_addr:
|
||||||
uint64_t _shellcode_buffer = (uint64_t)VirtualAlloc(0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
uint64_t _shellcode_buffer = (uint64_t)VirtualAlloc(0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
@@ -351,34 +286,22 @@ __Get_fpsSet_addr:
|
|||||||
*(uint64_t*)(_shellcode_buffer + 32) = _Addr_Sleep;
|
*(uint64_t*)(_shellcode_buffer + 32) = _Addr_Sleep;
|
||||||
*(uint64_t*)(_shellcode_buffer + 40) = _Addr_MessageBoxA;
|
*(uint64_t*)(_shellcode_buffer + 40) = _Addr_MessageBoxA;
|
||||||
*(uint64_t*)(_shellcode_buffer + 48) = _Addr_CloseHandle;
|
*(uint64_t*)(_shellcode_buffer + 48) = _Addr_CloseHandle;
|
||||||
*(uint32_t*)(_shellcode_buffer + 0xD4) = 1000;
|
*(uint32_t*)(_shellcode_buffer + 0xE4) = 1000;
|
||||||
*(uint32_t*)(_shellcode_buffer + 0xDC) = 60;
|
*(uint32_t*)(_shellcode_buffer + 0xEC) = 60;
|
||||||
|
|
||||||
|
*(uint64_t*)(_shellcode_buffer + 0x110) = 0xB848; //mov rax, game_pfps
|
||||||
|
*(uint64_t*)(_shellcode_buffer + 0x118) = 0x741D8B0000; //mov ebx, dword[Readmem_buffer]
|
||||||
|
*(uint64_t*)(_shellcode_buffer + 0x120) = 0xCCCCCCCCCCC31889; //mov [rax], ebx
|
||||||
|
*(uint64_t*)(_shellcode_buffer + 0x112) = _ptr_fps; //ret
|
||||||
|
*(uint64_t*)(_shellcode_buffer + 0x15C) = 0x5C76617E8834858; //keep thread
|
||||||
|
*(uint64_t*)(_shellcode_buffer + 0x164) = 0xE0FF21EBFFFFFF16;
|
||||||
|
|
||||||
LPVOID __Tar_proc_buffer = VirtualAllocEx(Tar_handle, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
LPVOID __Tar_proc_buffer = VirtualAllocEx(Tar_handle, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
if (__Tar_proc_buffer)
|
if (__Tar_proc_buffer)
|
||||||
{
|
{
|
||||||
if (WriteProcessMemory(Tar_handle, __Tar_proc_buffer, (void*)_shellcode_buffer, sizeof(_shellcode_genshin_Const), 0))
|
if (WriteProcessMemory(Tar_handle, __Tar_proc_buffer, (void*)_shellcode_buffer, sizeof(_shellcode_genshin_Const), 0))
|
||||||
{
|
{
|
||||||
VirtualFree((void*)_shellcode_buffer, 0, MEM_RELEASE);
|
VirtualFree((void*)_shellcode_buffer, 0, MEM_RELEASE);
|
||||||
_addr_tar_fpsSet_TarFun = (uint64_t)__Tar_proc_buffer + 0xC0;
|
|
||||||
_addr_tar_fpsget_TarFun = (uint64_t)__Tar_proc_buffer + 0xF0;
|
|
||||||
*(uint64_t*)Hook_addr_fpsget = 0xB848; //hook mov rax,[jmp addr]
|
|
||||||
*(uint64_t*)(Hook_addr_fpsget + 2) = _addr_tar_fpsget_TarFun;
|
|
||||||
*(uint16_t*)(Hook_addr_fpsget + 10) = 0xE0FF; // jmp rax
|
|
||||||
*(uint64_t*)Hook_addr_fpsSet = 0xB848;
|
|
||||||
*(uint64_t*)(Hook_addr_fpsSet + 2) = _addr_tar_fpsSet_TarFun;
|
|
||||||
*(uint16_t*)(Hook_addr_fpsSet + 10) = 0xE0FF;
|
|
||||||
if (WriteProcessMemory(Tar_handle, (LPVOID)Hook_addr_tar_fpsget, (LPVOID)Hook_addr_fpsget, 0x10, 0) == 0)
|
|
||||||
{
|
|
||||||
DWORD ERR_code = GetLastError();
|
|
||||||
printf_s("\nHook Get_fps Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (WriteProcessMemory(Tar_handle, (LPVOID)Hook_addr_tar_fpsSet, (LPVOID)Hook_addr_fpsSet, 0x10, 0) == 0)
|
|
||||||
{
|
|
||||||
DWORD ERR_code = GetLastError();
|
|
||||||
printf_s("\nHook Set_fps Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
HANDLE temp = CreateRemoteThread(Tar_handle, 0, 0, (LPTHREAD_START_ROUTINE)((uint64_t)__Tar_proc_buffer + 0x50), 0, 0, 0);
|
HANDLE temp = CreateRemoteThread(Tar_handle, 0, 0, (LPTHREAD_START_ROUTINE)((uint64_t)__Tar_proc_buffer + 0x50), 0, 0, 0);
|
||||||
if (temp)
|
if (temp)
|
||||||
{
|
{
|
||||||
@@ -389,7 +312,7 @@ __Get_fpsSet_addr:
|
|||||||
printf_s("Create InGame SyncThread Fail! ");
|
printf_s("Create InGame SyncThread Fail! ");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return ((uint64_t)__Tar_proc_buffer + 0xF1);
|
return ((uint64_t)__Tar_proc_buffer + 0x194);
|
||||||
}
|
}
|
||||||
printf_s("Inject shellcode Fail! ");
|
printf_s("Inject shellcode Fail! ");
|
||||||
VirtualFree((void*)_shellcode_buffer, 0, MEM_RELEASE);
|
VirtualFree((void*)_shellcode_buffer, 0, MEM_RELEASE);
|
||||||
@@ -410,14 +333,14 @@ void LoadConfig()
|
|||||||
INIReader reader("fps_config.ini");
|
INIReader reader("fps_config.ini");
|
||||||
if (reader.ParseError() != 0)
|
if (reader.ParseError() != 0)
|
||||||
{
|
{
|
||||||
printf("<EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n<EFBFBD>벻Ҫ<EFBFBD>رմ˽<EFBFBD><EFBFBD><EFBFBD> - Ȼ<><C8BB><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ\n<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> - <20><><EFBFBD>ڻ<EFBFBD>ȡ<EFBFBD><C8A1>Ϸ·<CFB7><C2B7>\n");
|
printf("配置不存在\n请不要关闭此进程 - 然后手动开启游戏\n这只需要进行一次 - 用于获取游戏路经\n");
|
||||||
printf("\n<EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>...\n");
|
printf("\n等待游戏启动...\n");
|
||||||
|
|
||||||
DWORD pid = 0;
|
DWORD pid = 0;
|
||||||
while (!(pid = GetPID("YuanShen.exe")) && !(pid = GetPID("GenshinImpact.exe")))
|
while (!(pid = GetPID("YuanShen.exe")) && !(pid = GetPID("GenshinImpact.exe")))
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
|
||||||
// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD><EFBFBD><EFBFBD> - <20><>Ȩ<EFBFBD>ܵ͵<DCB5><CDB5><EFBFBD> - <20><>Ӧ<EFBFBD>û<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
// 获取进程句柄 - 这权限很低的了 - 不应该获取不了
|
||||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid);
|
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid);
|
||||||
if (!hProcess)
|
if (!hProcess)
|
||||||
{
|
{
|
||||||
@@ -458,13 +381,13 @@ void LoadConfig()
|
|||||||
|
|
||||||
if (GetFileAttributesA(GamePath.c_str()) == INVALID_FILE_ATTRIBUTES)
|
if (GetFileAttributesA(GamePath.c_str()) == INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ·<EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD> - <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
|
printf("配置里的游戏路经改变了 - 开始重新配置\n");
|
||||||
DeleteFileA("config.ini");
|
DeleteFileA("config.ini");
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// <EFBFBD>ȼ<EFBFBD><EFBFBD>߳<EFBFBD>
|
// 热键线程
|
||||||
DWORD __stdcall Thread1(LPVOID p)
|
DWORD __stdcall Thread1(LPVOID p)
|
||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
@@ -513,7 +436,7 @@ int main(int argc, char** argv)
|
|||||||
CommandLine += argv[i] + std::string(" ");
|
CommandLine += argv[i] + std::string(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
// 读取配置
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
int TargetFPS = FpsValue;
|
int TargetFPS = FpsValue;
|
||||||
std::string ProcessPath = GamePath;
|
std::string ProcessPath = GamePath;
|
||||||
@@ -522,18 +445,18 @@ int main(int argc, char** argv)
|
|||||||
if (ProcessPath.length() < 8)
|
if (ProcessPath.length() < 8)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
printf("FPS<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>õĻ<C3B5><C4BB><EFBFBD><EFBFBD><EFBFBD>star<61><72>\n");
|
printf("FPS解锁 好用的话点个star吧 4.8\n");
|
||||||
printf("https://github.com/xiaonian233/genshin-fps-unlock \n4.7<EFBFBD>汾<EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD>лwinTEuser<EFBFBD>ϸ<EFBFBD>֧<EFBFBD><EFBFBD> \n");
|
printf("https://github.com/xiaonian233/genshin-fps-unlock \n特别感谢winTEuser老哥 \n");
|
||||||
printf("<EFBFBD><EFBFBD>Ϸ·<EFBFBD><EFBFBD>: %s\n\n", ProcessPath.c_str());
|
printf("游戏路经: %s\n\n", ProcessPath.c_str());
|
||||||
ProcessDir = ProcessPath.substr(0, ProcessPath.find_last_of("\\"));
|
ProcessDir = ProcessPath.substr(0, ProcessPath.find_last_of("\\"));
|
||||||
std::string procname = ProcessPath.substr(ProcessPath.find_last_of("\\") + 1);
|
std::string procname = ProcessPath.substr(ProcessPath.find_last_of("\\") + 1);
|
||||||
|
|
||||||
DWORD pid = GetPID(procname);
|
DWORD pid = GetPID(procname);
|
||||||
if (pid)
|
if (pid)
|
||||||
{
|
{
|
||||||
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>\n");
|
printf("检测到游戏已在运行!\n");
|
||||||
printf("<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD>ᵼ<EFBFBD><EFBFBD>ʧЧ<EFBFBD><EFBFBD>\n");
|
printf("手动启动游戏会导致失效的\n");
|
||||||
printf("<EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD>Ϸ - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ\n");
|
printf("请手动关闭游戏 - 解锁器会自动启动游戏\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,13 +474,13 @@ int main(int argc, char** argv)
|
|||||||
Sleep(200);
|
Sleep(200);
|
||||||
StartPriority = PrioityClass[1];
|
StartPriority = PrioityClass[1];
|
||||||
SetPriorityClass(pi.hProcess, StartPriority);
|
SetPriorityClass(pi.hProcess, StartPriority);
|
||||||
// <EFBFBD>ȴ<EFBFBD>UnityPlayer.dll<EFBFBD><EFBFBD><EFBFBD>غͻ<EFBFBD>ȡDLL<EFBFBD><EFBFBD>Ϣ
|
// 等待UnityPlayer.dll加载和获取DLL信息
|
||||||
MODULEENTRY32 hUnityPlayer{};
|
MODULEENTRY32 hUnityPlayer{};
|
||||||
{
|
{
|
||||||
DWORD times = 1000;
|
DWORD times = 1000;
|
||||||
while (times != 0)
|
while (times != 0)
|
||||||
{
|
{
|
||||||
if (GetModule2(pi.hProcess, procname, &hUnityPlayer))
|
if (GetModule(pi.dwProcessId, procname, &hUnityPlayer))
|
||||||
{
|
{
|
||||||
goto __get_procbase_ok;
|
goto __get_procbase_ok;
|
||||||
}
|
}
|
||||||
@@ -570,11 +493,11 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
DWORD times = 1000;
|
DWORD times = 1000;
|
||||||
while (!GetModule2(pi.hProcess, "UnityPlayer.dll", &hUnityPlayer))
|
while (!GetModule(pi.dwProcessId, "UnityPlayer.dll", &hUnityPlayer))
|
||||||
{
|
{
|
||||||
Sleep(50);
|
Sleep(50);
|
||||||
times -= 5;
|
times -= 5;
|
||||||
if (GetModule2(pi.hProcess, "unityplayer.dll", &hUnityPlayer))
|
if (GetModule(pi.dwProcessId, "unityplayer.dll", &hUnityPlayer))
|
||||||
{
|
{
|
||||||
goto __get_procbase_ok;
|
goto __get_procbase_ok;
|
||||||
}
|
}
|
||||||
@@ -587,7 +510,7 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("UnityPlayer: %X%X\n", (uintptr_t)hUnityPlayer.modBaseAddr >> 32 & -1, hUnityPlayer.modBaseAddr);
|
printf("UnityPlayer: %X%X\n", (uintptr_t)hUnityPlayer.modBaseAddr >> 32 & -1, hUnityPlayer.modBaseAddr);
|
||||||
__get_procbase_ok:
|
__get_procbase_ok:
|
||||||
LPVOID _mbase_PE_buffer = VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
LPVOID _mbase_PE_buffer = VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
if (_mbase_PE_buffer == 0)
|
if (_mbase_PE_buffer == 0)
|
||||||
{
|
{
|
||||||
@@ -614,7 +537,7 @@ int main(int argc, char** argv)
|
|||||||
uint32_t Text_Vsize;
|
uint32_t Text_Vsize;
|
||||||
if (_FilePE_Nt_header.Signature == 0x00004550)
|
if (_FilePE_Nt_header.Signature == 0x00004550)
|
||||||
{
|
{
|
||||||
DWORD sec_num = _FilePE_Nt_header.FileHeader.NumberOfSections;//<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ڶβ<EFBFBD><EFBFBD><EFBFBD>
|
DWORD sec_num = _FilePE_Nt_header.FileHeader.NumberOfSections;//获得指定节段参数
|
||||||
DWORD num = sec_num;
|
DWORD num = sec_num;
|
||||||
DWORD target_sec_VA_start = 0;
|
DWORD target_sec_VA_start = 0;
|
||||||
while (num)
|
while (num)
|
||||||
@@ -641,7 +564,7 @@ int main(int argc, char** argv)
|
|||||||
return (int)-1;
|
return (int)-1;
|
||||||
}
|
}
|
||||||
__Get_target_sec:
|
__Get_target_sec:
|
||||||
// <EFBFBD>ڱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
// 在本进程内申请代码段大小的内存 - 用于特征搜索
|
||||||
LPVOID Copy_Text_VA = VirtualAlloc(0, Text_Vsize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
LPVOID Copy_Text_VA = VirtualAlloc(0, Text_Vsize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
if (Copy_Text_VA == NULL)
|
if (Copy_Text_VA == NULL)
|
||||||
{
|
{
|
||||||
@@ -649,7 +572,7 @@ __Get_target_sec:
|
|||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
return (int)-1;
|
return (int)-1;
|
||||||
}
|
}
|
||||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
// 把整个模块读出来
|
||||||
if (ReadProcessMemory(pi.hProcess, (void*)Text_Remote_RVA, Copy_Text_VA, Text_Vsize, 0) == 0)
|
if (ReadProcessMemory(pi.hProcess, (void*)Text_Remote_RVA, Copy_Text_VA, Text_Vsize, 0) == 0)
|
||||||
{
|
{
|
||||||
printf("Readmem Fail ! (text)");
|
printf("Readmem Fail ! (text)");
|
||||||
@@ -668,7 +591,7 @@ __Get_target_sec:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD>ַ (FPS)
|
// 计算相对地址 (FPS)
|
||||||
uintptr_t pfps = 0;
|
uintptr_t pfps = 0;
|
||||||
{
|
{
|
||||||
uintptr_t rip = address;
|
uintptr_t rip = address;
|
||||||
@@ -677,7 +600,9 @@ __Get_target_sec:
|
|||||||
rip += *(int32_t*)(rip)+4;
|
rip += *(int32_t*)(rip)+4;
|
||||||
pfps = rip - (uintptr_t)Copy_Text_VA + Text_Remote_RVA;
|
pfps = rip - (uintptr_t)Copy_Text_VA + Text_Remote_RVA;
|
||||||
printf("FPS Offset: %X\n", pfps);
|
printf("FPS Offset: %X\n", pfps);
|
||||||
|
goto __offset_ok;
|
||||||
}
|
}
|
||||||
|
__offset_ok:
|
||||||
uintptr_t Patch_ptr = 0;
|
uintptr_t Patch_ptr = 0;
|
||||||
{
|
{
|
||||||
Patch_ptr = inject_patch(Copy_Text_VA, Text_Vsize, Text_Remote_RVA, pfps, pi.hProcess);//patch inject
|
Patch_ptr = inject_patch(Copy_Text_VA, Text_Vsize, Text_Remote_RVA, pfps, pi.hProcess);//patch inject
|
||||||
@@ -690,30 +615,36 @@ __Get_target_sec:
|
|||||||
VirtualFree(_mbase_PE_buffer, 0, MEM_RELEASE);
|
VirtualFree(_mbase_PE_buffer, 0, MEM_RELEASE);
|
||||||
VirtualFree(Copy_Text_VA, 0, MEM_RELEASE);
|
VirtualFree(Copy_Text_VA, 0, MEM_RELEASE);
|
||||||
printf("Done\n\n");
|
printf("Done\n\n");
|
||||||
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ctrl + <EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:\n");
|
printf("用右ctrl + 箭头键更改限制:\n");
|
||||||
printf(" <EFBFBD><EFBFBD>ctrl + <EFBFBD><EFBFBD>: +20\n");
|
printf(" 右ctrl + 上: +20\n");
|
||||||
printf(" <EFBFBD><EFBFBD>ctrl + <EFBFBD><EFBFBD>: -20\n");
|
printf(" 右ctrl + 下: -20\n");
|
||||||
printf(" <EFBFBD><EFBFBD>ctrl + <EFBFBD><EFBFBD>: -2\n");
|
printf(" 右ctrl + 左: -2\n");
|
||||||
printf(" <EFBFBD><EFBFBD>ctrl + <EFBFBD><EFBFBD>: +2\n\n");
|
printf(" 右ctrl + 右: +2\n\n");
|
||||||
|
|
||||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><EFBFBD>߳<EFBFBD>
|
// 创建热键线程
|
||||||
HANDLE hThread = CreateThread(nullptr, 0, Thread1, &TargetFPS, 0, nullptr);
|
HANDLE hThread = CreateThread(nullptr, 0, Thread1, &TargetFPS, 0, nullptr);
|
||||||
if (hThread)
|
if (hThread)
|
||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
|
|
||||||
DWORD dwExitCode = STILL_ACTIVE;
|
DWORD dwExitCode = STILL_ACTIVE;
|
||||||
|
uint32_t fps = 0;
|
||||||
while (dwExitCode == STILL_ACTIVE)
|
while (dwExitCode == STILL_ACTIVE)
|
||||||
{
|
{
|
||||||
GetExitCodeProcess(pi.hProcess, &dwExitCode);
|
GetExitCodeProcess(pi.hProcess, &dwExitCode);
|
||||||
|
|
||||||
// ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>
|
// 每两秒检查一次
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
int fps = 0;
|
int fps = 0;
|
||||||
ReadProcessMemory(pi.hProcess, (LPVOID)pfps, &fps, sizeof(fps), nullptr);
|
ReadProcessMemory(pi.hProcess, (LPVOID)pfps, &fps, sizeof(fps), nullptr);
|
||||||
if (fps == -1)
|
if (fps == -1)
|
||||||
continue;
|
continue;
|
||||||
if (fps != TargetFPS)
|
if (fps != TargetFPS)
|
||||||
|
{
|
||||||
WriteProcessMemory(pi.hProcess, (LPVOID)pfps, &TargetFPS, sizeof(TargetFPS), nullptr);
|
WriteProcessMemory(pi.hProcess, (LPVOID)pfps, &TargetFPS, sizeof(TargetFPS), nullptr);
|
||||||
|
//热修补循环
|
||||||
|
WriteProcessMemory(pi.hProcess, (LPVOID)Patch_ptr, &TargetFPS, 4, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user