mirror of
https://github.com/wangdage12/genshin-fps-unlock.git
synced 2026-02-18 02:42:13 +08:00
sync code from winTEuser support 4.8
This commit is contained in:
@@ -26,124 +26,105 @@ const std::vector<DWORD> PrioityClass = {
|
|||||||
IDLE_PRIORITY_CLASS
|
IDLE_PRIORITY_CLASS
|
||||||
};
|
};
|
||||||
//credit by winTEuser
|
//credit by winTEuser
|
||||||
BYTE _shellcode_genshin[] =
|
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, // uint32_t unlocker_Handle _shellcode_genshin[4]
|
0x00, 0x00, 0x00, 0x00, //FREE _shellcode_genshin[4]
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 unlocker_FpsValue_addr _shellcode_genshin[8]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 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, //DWORD64 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, //DWORD64 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, //DWORD64 API_Sleep _shellcode_genshin[32]
|
||||||
0x00, 0x00, 0x00, 0x00, //uint32_t Readmem_buffer _shellcode_genshin[40]
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 API_MessageBoxA _shellcode_genshin[40]
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, //int3
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //DWORD64 API_CloseHandle _shellcode_genshin[48]
|
||||||
0x48, 0x83, 0xEC, 0x38, //sub rsp,0x38 _shellcode_genshin[48] _sync_thread
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //FREE _shellcode_genshin[56]
|
||||||
0x8B, 0x05, 0xC6, 0xFF, 0xFF, 0xFF, //mov eax,dword[unlocker_pid]
|
//int3
|
||||||
0x85, 0xC0, //test eax
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
0x74, 0x5B, //je return
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
|
//int3
|
||||||
|
0x48, 0x83, 0xEC, 0x38, //sub rsp,0x38 _shellcode_genshin[80] _sync_thread
|
||||||
|
0x8B, 0x05, 0xA6, 0xFF, 0xFF, 0xFF, //mov eax,dword[unlocker_pid]
|
||||||
|
0x85, 0xC0, //test eax, eax
|
||||||
|
0x74, 0x5C, //jz return
|
||||||
0x41, 0x89, 0xC0, //mov r8d, eax
|
0x41, 0x89, 0xC0, //mov r8d, eax
|
||||||
0x33, 0xD2, //xor edx, edx
|
0x33, 0xD2, //xor edx, edx
|
||||||
0xB9, 0xFF, 0xFF, 0x1F, 0x00, //mov ecx,1FFFFF
|
0xB9, 0xFF, 0xFF, 0x1F, 0x00, //mov ecx,1FFFFF
|
||||||
0xFF, 0x15, 0xC2, 0xFF, 0xFF, 0xFF, //call [API_OpenProcess]
|
0xFF, 0x15, 0xA2, 0xFF, 0xFF, 0xFF, //call [API_OpenProcess]
|
||||||
0x85, 0xC0, //test eax
|
0x85, 0xC0, //test eax, eax
|
||||||
0x74, 0x47, //je return
|
0x74, 0x48, //jz return
|
||||||
0x89, 0x05, 0xAC, 0xFF, 0xFF, 0xFF, //mov dword[unlocker_Handle],eax
|
|
||||||
0x89, 0xC6, //mov esi, eax
|
0x89, 0xC6, //mov esi, eax
|
||||||
0x48, 0x8B, 0x3D, 0xA7, 0xFF, 0xFF, 0xFF,//mov rdi,qword[unlocker_FpsValue_addr]
|
0x48, 0x8B, 0x3D, 0x8D, 0xFF, 0xFF, 0xFF,//mov rdi,qword[unlocker_FpsValue_addr]
|
||||||
0x0F, 0x1F, 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, 0xB8, 0xFF, 0xFF, 0xFF,//lea r8,qword[Readmem_buffer]
|
0x4C, 0x8D, 0x05, 0xF8, 0x00, 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
|
||||||
0xFF, 0x15, 0x95, 0xFF, 0xFF, 0xFF, //call [API_ReadProcessmem]
|
0xFF, 0x15, 0x79, 0xFF, 0xFF, 0xFF, //call [API_ReadProcessmem]
|
||||||
0x85, 0xC0, //test eax
|
0x85, 0xC0, //test eax, eax
|
||||||
0x74, 0x12, //jz return
|
0x74, 0x12, //jz Show msg and closehandle
|
||||||
0xB9, 0xE8, 0x03, 0x00, 0x00, //mov ecx,0x3E8 (1000ms)
|
0xB9, 0xF4, 0x01, 0x00, 0x00, //mov ecx,0x1F4 (500ms)
|
||||||
0xFF, 0x15, 0x8E, 0xFF, 0xFF, 0xFF, //call [API_Sleep]
|
0xFF, 0x15, 0x72, 0xFF, 0xFF, 0xFF, //call [API_Sleep]
|
||||||
0xE8, 0x49, 0x00, 0x00, 0x00, //call Sync_Set
|
0xE8, 0x4D, 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
|
||||||
0x48, 0x83, 0xC4, 0x38, //add rsp,0x38
|
0x48, 0x83, 0xC4, 0x38, //add rsp,0x38
|
||||||
0xC3, //ret
|
0xC3, //return
|
||||||
0xCC, 0xCC, //int3
|
0xCC,
|
||||||
0x89, 0x0D, 0x22, 0x00, 0x00, 0x00, //mov [Game_Current_set], ecx //hook_fps_set _shellcode_genshin[160]
|
//int3
|
||||||
0xEB, 0x00, //nop
|
0x89, 0x0D, 0xBA, 0x00, 0x00, 0x00, //mov [Game_Current_set], ecx //hook_fps_set _shellcode_genshin[192]
|
||||||
|
0x31, 0xC0, //xor eax, eax
|
||||||
0x83, 0xF9, 0x1E, //cmp ecx, 0x1E
|
0x83, 0xF9, 0x1E, //cmp ecx, 0x1E
|
||||||
0x74, 0x0C, //je set 60
|
0x74, 0x0E, //je set 60
|
||||||
0x83, 0xF9, 0x2D, //cmp ecx, 0x2D
|
0x83, 0xF9, 0x2D, //cmp ecx, 0x2D
|
||||||
0x74, 0x12, //je return
|
0x74, 0x15, //je Sync_buffer
|
||||||
0xB9, 0xFF, 0xFF, 0xFF, 0xFF, //mov ecx,[Readmem_buffer]
|
0x90, //nop
|
||||||
0xEB, 0x05, //jmp set
|
0xB9, 0xE8, 0x03, 0x00, 0x00, //mov ecx, 0x3E8
|
||||||
|
0xEB, 0x06, //jmp set
|
||||||
|
0xCC, //int3
|
||||||
0xB9, 0x3C, 0x00, 0x00, 0x00, //mov ecx, 0x3C
|
0xB9, 0x3C, 0x00, 0x00, 0x00, //mov ecx, 0x3C
|
||||||
0x89, 0x0D, 0x0D, 0x00, 0x00, 0x00, //mov [hook_fps_get + 1],ecx
|
0x89, 0x0D, 0x0B, 0x00, 0x00, 0x00, //mov [hook_fps_get+1], ecx //set
|
||||||
0xC3, //ret
|
0xC3, //ret
|
||||||
0xCC, 0xCC, 0xCC, //int3
|
0x8B, 0x0D, 0x97, 0x00, 0x00, 0x00, //mov ecx, dword[Readmem_buffer] //Sync_buffer
|
||||||
0x00, 0x00, 0x00, 0x00, //uint32_t Game_Current_set
|
0xEB, 0xF1, //jmp set
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, //int3
|
0xCC,
|
||||||
0xB8,0x78, 0x00, 0x00, 0x00, //mov eax,0x78 //hook_fps_get _shellcode_genshin[208]
|
//int3
|
||||||
|
0xB8, 0x78, 0x00, 0x00, 0x00, //mov eax,0x78 //hook_fps_get _shellcode_genshin[240]
|
||||||
0xC3, //ret
|
0xC3, //ret
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,//int3
|
//int3
|
||||||
0x56, //push rsi //Sync_Set
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
0x57, //push rdi
|
//int3
|
||||||
0x48, 0x83, 0xEC, 0x18, //sub rsp, 0x18
|
0x8B, 0x05, 0x7A, 0x00, 0x00, 0x00, //mov eax, dword[Game_Current_set] //Sync_auto
|
||||||
0x8B, 0x05, 0xDC, 0xFF, 0xFF, 0xFF, //mov eax, dword[Game_Current_set]
|
|
||||||
0x83, 0xF8, 0x2D, //cmp eax, 0x2D
|
0x83, 0xF8, 0x2D, //cmp eax, 0x2D
|
||||||
0x75, 0x0C, //jne return
|
0x75, 0x0C, //jne return
|
||||||
0x8B, 0x05, 0x31, 0xFF, 0xFF, 0xFF, //mov eax, dword[Game_Current_set]
|
0x8B, 0x05, 0x73, 0x00, 0x00, 0x00, //mov eax, dword[Readmem_buffer]
|
||||||
0x89, 0x05, 0xD4, 0xFF, 0xFF, 0xFF, //mov dword[hook_fps_get + 1], eax
|
0x89, 0x05, 0xDA, 0xFF, 0xFF, 0xFF, //mov dword[hook_fps_get + 1], eax
|
||||||
0x48, 0x83, 0xC4, 0x18, //add rsp, 0x18
|
|
||||||
0x5F, //pop rdi
|
|
||||||
0x5E, //pop rsi
|
|
||||||
0xC3, //ret
|
0xC3, //ret
|
||||||
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC
|
//int3
|
||||||
|
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||||
|
//int3
|
||||||
|
0x48, 0x83, 0xEC, 0x28, //sub rsp, 0x28 //Show Errormsg and closehandle
|
||||||
|
0x31, 0xC9, //xor ecx, ecx
|
||||||
|
0x48, 0x8D, 0x15, 0x23, 0x00, 0x00, 0x00,//lea rdx, qword:["Sync failed!"]
|
||||||
|
0x4C, 0x8D, 0x05, 0x2C, 0x00, 0x00, 0x00,//lea r8, qword:["Error"]
|
||||||
|
0x41, 0xB9, 0x10, 0x00, 0x00, 0x00, //mov r9d, 0x10
|
||||||
|
0xFF, 0x15, 0xE8, 0xFE, 0xFF, 0xFF, //call [API_MessageBoxA]
|
||||||
|
0x89, 0xF1, //mov ecx, esi
|
||||||
|
0xFF, 0x15, 0xE8, 0xFE, 0xFF, 0xFF, //call [API_CloseHandle]
|
||||||
|
0x48, 0x83, 0xC4, 0x28, //add rsp, 0x28
|
||||||
|
0xC3, //ret
|
||||||
|
//int3
|
||||||
|
0xCC, 0xCC, 0xCC,
|
||||||
|
'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,
|
||||||
|
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 Readmem_buffer
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>
|
|
||||||
uintptr_t PatternScan(void* module, const char* signature)
|
|
||||||
{
|
|
||||||
static auto pattern_to_byte = [](const char* pattern) {
|
|
||||||
auto bytes = std::vector<int>{};
|
|
||||||
auto start = const_cast<char*>(pattern);
|
|
||||||
auto end = const_cast<char*>(pattern) + strlen(pattern);
|
|
||||||
|
|
||||||
for (auto current = start; current < end; ++current) {
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> winTEuser
|
||||||
if (*current == '?') {
|
|
||||||
++current;
|
|
||||||
if (*current == '?')
|
|
||||||
++current;
|
|
||||||
bytes.push_back(-1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bytes.push_back(strtoul(current, ¤t, 16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto dosHeader = (PIMAGE_DOS_HEADER)module;
|
|
||||||
auto ntHeaders = (PIMAGE_NT_HEADERS)((std::uint8_t*)module + dosHeader->e_lfanew);
|
|
||||||
|
|
||||||
auto sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage;
|
|
||||||
auto patternBytes = pattern_to_byte(signature);
|
|
||||||
auto scanBytes = reinterpret_cast<std::uint8_t*>(module);
|
|
||||||
|
|
||||||
auto s = patternBytes.size();
|
|
||||||
auto d = patternBytes.data();
|
|
||||||
|
|
||||||
for (auto i = 0ul; i < sizeOfImage - s; ++i) {
|
|
||||||
bool found = true;
|
|
||||||
for (auto j = 0ul; j < s; ++j) {
|
|
||||||
if (scanBytes[i + j] != d[j] && d[j] != -1) {
|
|
||||||
found = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found) {
|
|
||||||
return (uintptr_t)&scanBytes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
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)
|
||||||
@@ -227,6 +208,36 @@ bool GetModule2(HANDLE GameHandle, std::string ModuleName, PMODULEENTRY32 pEntry
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
static bool GetModule(DWORD pid, std::string ModuleName, PMODULEENTRY32 pEntry)
|
||||||
|
{
|
||||||
|
if (!pEntry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MODULEENTRY32 mod32{};
|
||||||
|
mod32.dwSize = sizeof(mod32);
|
||||||
|
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
|
||||||
|
bool temp = Module32First(snap, &mod32);
|
||||||
|
if (temp)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (mod32.th32ProcessID != pid)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mod32.szModule == ModuleName)
|
||||||
|
{
|
||||||
|
*pEntry = mod32;
|
||||||
|
CloseHandle(snap);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (Module32Next(snap, &mod32));
|
||||||
|
|
||||||
|
}
|
||||||
|
CloseHandle(snap);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
// ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID
|
// ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID
|
||||||
DWORD GetPID(std::string ProcessName)
|
DWORD GetPID(std::string ProcessName)
|
||||||
{
|
{
|
||||||
@@ -266,68 +277,30 @@ bool WriteConfig(std::string GamePath, int fps)
|
|||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
}
|
}
|
||||||
//Hotpatch
|
//Hotpatch
|
||||||
static DWORD64 inject_patch(LPVOID unity_module, DWORD64 unity_baseaddr, DWORD64 _ptr_fps, HANDLE Tar_handle)
|
static DWORD64 inject_patch(LPVOID text_buffer, DWORD text_size, DWORD64 _text_baseaddr, uint64_t _ptr_fps, HANDLE Tar_handle)
|
||||||
{
|
{
|
||||||
BYTE search_sec[] = ".text";//max 8 byte
|
if (text_buffer == 0 || text_size == 0 || _text_baseaddr == 0 || _ptr_fps == 0 || Tar_handle == 0)
|
||||||
uintptr_t WinPEfileVA = *(uintptr_t*)(&unity_module) + 0x3c; //dos_header
|
|
||||||
uintptr_t PEfptr = *(uintptr_t*)(&unity_module) + *(uint32_t*)WinPEfileVA; //get_winPE_VA
|
|
||||||
_IMAGE_NT_HEADERS64 _FilePE_Nt_header = *(_IMAGE_NT_HEADERS64*)PEfptr;
|
|
||||||
_IMAGE_SECTION_HEADER _sec_temp{};
|
|
||||||
DWORD64 Module_TarSec_RVA;
|
|
||||||
DWORD64 Module_TarSecEnd_RVA;
|
|
||||||
DWORD Module_TarSec_Size;
|
|
||||||
if (_FilePE_Nt_header.Signature == 0x00004550)
|
|
||||||
{
|
|
||||||
DWORD sec_num = _FilePE_Nt_header.FileHeader.NumberOfSections;//<2F><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>ڶβ<DAB6><CEB2><EFBFBD>
|
|
||||||
DWORD num = sec_num;
|
|
||||||
while (num)
|
|
||||||
{
|
|
||||||
_sec_temp = *(_IMAGE_SECTION_HEADER*)(PEfptr + 264 + (40 * (static_cast<unsigned long long>(sec_num) - num)));
|
|
||||||
|
|
||||||
//printf_s("sec_%d_is: %s\n", sec_num - num, _sec_temp.Name);
|
|
||||||
int i = 8;
|
|
||||||
int len = sizeof(search_sec) - 1;
|
|
||||||
int cmp = 0;
|
|
||||||
while ((i != 0) && _sec_temp.Name[8 - i] && search_sec[8 - i])
|
|
||||||
{
|
|
||||||
if (_sec_temp.Name[8 - i] == search_sec[8 - i])
|
|
||||||
{
|
|
||||||
cmp++;
|
|
||||||
}
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
if (cmp == len)
|
|
||||||
{
|
|
||||||
Module_TarSec_RVA = _sec_temp.VirtualAddress + (DWORD64)unity_module;
|
|
||||||
Module_TarSec_Size = _sec_temp.Misc.VirtualSize;
|
|
||||||
Module_TarSecEnd_RVA = Module_TarSec_RVA + Module_TarSec_Size;
|
|
||||||
goto __Get_target_sec;
|
|
||||||
}
|
|
||||||
num--;
|
|
||||||
}
|
|
||||||
printf_s("Get Target Section Fail !\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
__Get_target_sec:
|
DWORD64 Module_TarSec_RVA = (DWORD64)text_buffer;
|
||||||
|
DWORD Module_TarSec_Size = text_size;
|
||||||
|
|
||||||
DWORD64 address = 0;
|
DWORD64 address = 0;
|
||||||
{
|
|
||||||
DWORD64 Hook_addr_fpsget = 0; //in buffer
|
DWORD64 Hook_addr_fpsget = 0; //in buffer
|
||||||
DWORD64 Hook_addr_tar_fpsget = 0;
|
DWORD64 Hook_addr_tar_fpsget = 0;
|
||||||
DWORD64 Hook_addr_fpsSet = 0; //in buffer
|
DWORD64 Hook_addr_fpsSet = 0; //in buffer
|
||||||
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, Module_TarSec_Size, "CC 8B 05 ?? ?? ?? ?? C3 CC"))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷpatch<EFBFBD><EFBFBD>λ//get_fps
|
while (address = PatternScan_Region(Module_TarSec_RVA, text_size, "CC 8B 05 ?? ?? ?? ?? C3 CC"))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷhook<EFBFBD><EFBFBD>λ//get_fps
|
||||||
{
|
{
|
||||||
uintptr_t rip = address;
|
uintptr_t rip = address;
|
||||||
rip += 3;
|
rip += 3;
|
||||||
rip += *(int32_t*)(rip)+4;
|
rip += *(int32_t*)(rip)+4;
|
||||||
if ((rip - (uintptr_t)unity_module + (uintptr_t)unity_baseaddr) == _ptr_fps)
|
if ((rip - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr) == _ptr_fps)
|
||||||
{
|
{
|
||||||
Hook_addr_fpsget = address + 1;
|
Hook_addr_fpsget = address + 1;
|
||||||
Hook_addr_tar_fpsget = Hook_addr_fpsget - (uintptr_t)unity_module + (uintptr_t)unity_baseaddr;
|
Hook_addr_tar_fpsget = Hook_addr_fpsget - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr;
|
||||||
goto __Get_fpsGet_addr;
|
goto __Get_fpsGet_addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -335,19 +308,19 @@ __Get_target_sec:
|
|||||||
*(uint64_t*)(address + 1) = 0xCCCCCCCCCCCCCCCC;
|
*(uint64_t*)(address + 1) = 0xCCCCCCCCCCCCCCCC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf_s("\nPatch pattern1 outdate...\n");
|
printf_s("Get get_fps pattern Fail! \n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
__Get_fpsGet_addr:
|
__Get_fpsGet_addr:
|
||||||
while (address = PatternScan_Region(Module_TarSec_RVA, Module_TarSec_Size, "CC 89 0D ?? ?? ?? ?? C3 CC"))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷpatch<EFBFBD><EFBFBD>λ//set_fps
|
while (address = PatternScan_Region(Module_TarSec_RVA, text_size, "CC 89 0D ?? ?? ?? ?? C3 CC"))//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷhook<EFBFBD><EFBFBD>λ//set_fps
|
||||||
{
|
{
|
||||||
uintptr_t rip = address;
|
uintptr_t rip = address;
|
||||||
rip += 3;
|
rip += 3;
|
||||||
rip += *(int32_t*)(rip)+4;
|
rip += *(int32_t*)(rip)+4;
|
||||||
if ((rip - (uintptr_t)unity_module + (uintptr_t)unity_baseaddr) == _ptr_fps)
|
if ((rip - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr) == _ptr_fps)
|
||||||
{
|
{
|
||||||
Hook_addr_fpsSet = address + 1;
|
Hook_addr_fpsSet = address + 1;
|
||||||
Hook_addr_tar_fpsSet = Hook_addr_fpsSet - (uintptr_t)unity_module + (uintptr_t)unity_baseaddr;
|
Hook_addr_tar_fpsSet = Hook_addr_fpsSet - (uintptr_t)Module_TarSec_RVA + (uintptr_t)_text_baseaddr;
|
||||||
goto __Get_fpsSet_addr;
|
goto __Get_fpsSet_addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -355,119 +328,79 @@ __Get_target_sec:
|
|||||||
*(uint64_t*)(address + 1) = 0xCCCCCCCCCCCCCCCC;
|
*(uint64_t*)(address + 1) = 0xCCCCCCCCCCCCCCCC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf_s("\nPatch pattern2 outdate...\n");
|
printf_s("Get set_fps pattern Fail! \n");
|
||||||
return 0;
|
|
||||||
|
|
||||||
__Get_fpsSet_addr:
|
__Get_fpsSet_addr:
|
||||||
uint64_t _Addr_OpenProcess = 0;
|
uint64_t _shellcode_buffer = (uint64_t)VirtualAlloc(0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
uint64_t _Addr_ReadProcessmem = 0;
|
if (_shellcode_buffer == 0)
|
||||||
uint64_t _Addr_Sleep = 0;
|
|
||||||
if (address = PatternScan_Region(Module_TarSec_RVA, Module_TarSec_Size, "33 D2 B9 00 04 00 00 FF 15 ?? ?? ?? ??"))//get API OpenProcess
|
|
||||||
{
|
{
|
||||||
uintptr_t rip = address;
|
printf_s("Buffer Alloc Fail! \n");
|
||||||
rip += 9;
|
|
||||||
rip += *(int32_t*)(rip)+4;
|
|
||||||
if (*(uint64_t*)(rip) == 0)
|
|
||||||
{
|
|
||||||
rip = rip - (uintptr_t)unity_module + (uintptr_t)unity_baseaddr;
|
|
||||||
while (_Addr_OpenProcess == 0)
|
|
||||||
{
|
|
||||||
if (ReadProcessMemory(Tar_handle, (LPCVOID)rip, &_Addr_OpenProcess, 8, 0) == 0)
|
|
||||||
{
|
|
||||||
DWORD ERR_code = GetLastError();
|
|
||||||
printf_s("\nGet Target Openprocess API Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
memcpy((void*)_shellcode_buffer, &_shellcode_genshin_Const, sizeof(_shellcode_genshin_Const));
|
||||||
}
|
|
||||||
else { _Addr_OpenProcess = *(uint64_t*)rip; }
|
uint64_t _Addr_OpenProcess = (uint64_t)(&OpenProcess);
|
||||||
}
|
uint64_t _Addr_ReadProcessmem = (uint64_t)(&ReadProcessMemory);
|
||||||
if (address = PatternScan_Region(Module_TarSec_RVA, Module_TarSec_Size, "48 89 44 24 20 FF 15 ?? ?? ?? ?? 48 8B 54 24 70"))//get API ReadProcmem
|
uint64_t _Addr_Sleep = (uint64_t)(&Sleep);
|
||||||
{
|
uint64_t _Addr_MessageBoxA = (uint64_t)(&MessageBoxA);
|
||||||
uintptr_t rip = address;
|
uint64_t _Addr_CloseHandle = (uint64_t)(&CloseHandle);
|
||||||
rip += 7;
|
*(uint32_t*)_shellcode_buffer = GetCurrentProcessId(); //unlocker PID
|
||||||
rip += *(int32_t*)(rip)+4;
|
*(uint64_t*)(_shellcode_buffer + 8) = (uint64_t)(&FpsValue); //unlocker fps ptr
|
||||||
if (*(uint64_t*)(rip) == 0)
|
*(uint64_t*)(_shellcode_buffer + 16) = _Addr_OpenProcess;
|
||||||
{
|
*(uint64_t*)(_shellcode_buffer + 24) = _Addr_ReadProcessmem;
|
||||||
rip = rip - (uintptr_t)unity_module + (uintptr_t)unity_baseaddr;
|
*(uint64_t*)(_shellcode_buffer + 32) = _Addr_Sleep;
|
||||||
while (_Addr_ReadProcessmem == 0)
|
*(uint64_t*)(_shellcode_buffer + 40) = _Addr_MessageBoxA;
|
||||||
{
|
*(uint64_t*)(_shellcode_buffer + 48) = _Addr_CloseHandle;
|
||||||
if (ReadProcessMemory(Tar_handle, (LPCVOID)rip, &_Addr_ReadProcessmem, 8, 0) == 0)
|
*(uint32_t*)(_shellcode_buffer + 0xD4) = 1000;
|
||||||
{
|
*(uint32_t*)(_shellcode_buffer + 0xDC) = 60;
|
||||||
DWORD ERR_code = GetLastError();
|
|
||||||
printf_s("\nGet Target Readprocmem API Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { _Addr_ReadProcessmem = *(uint64_t*)rip; }
|
|
||||||
}
|
|
||||||
if (address = PatternScan_Region(Module_TarSec_RVA, Module_TarSec_Size, "41 8B C8 FF 15 ?? ?? ?? ?? 8B C7"))//get API Sleep
|
|
||||||
{
|
|
||||||
uintptr_t rip = address;
|
|
||||||
rip += 5;
|
|
||||||
rip += *(int32_t*)(rip)+4;
|
|
||||||
if (*(uint64_t*)(rip) == 0)
|
|
||||||
{
|
|
||||||
rip = rip - (uintptr_t)unity_module + (uintptr_t)unity_baseaddr;
|
|
||||||
while (_Addr_Sleep == 0)
|
|
||||||
{
|
|
||||||
if (ReadProcessMemory(Tar_handle, (LPCVOID)rip, &_Addr_Sleep, 8, 0) == 0)
|
|
||||||
{
|
|
||||||
DWORD ERR_code = GetLastError();
|
|
||||||
printf_s("\nGet Target Sleep API Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { _Addr_Sleep = *(uint64_t*)rip; }
|
|
||||||
}
|
|
||||||
*(uint32_t*)(&_shellcode_genshin) = GetCurrentProcessId(); //unlocker PID
|
|
||||||
*(uint64_t*)(&_shellcode_genshin[8]) = (uint64_t)(&FpsValue); //unlocker fps set
|
|
||||||
*(uint64_t*)(&_shellcode_genshin[16]) = _Addr_OpenProcess;
|
|
||||||
*(uint64_t*)(&_shellcode_genshin[24]) = _Addr_ReadProcessmem;
|
|
||||||
*(uint64_t*)(&_shellcode_genshin[32]) = _Addr_Sleep;
|
|
||||||
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, &_shellcode_genshin, sizeof(_shellcode_genshin), 0));
|
if (WriteProcessMemory(Tar_handle, __Tar_proc_buffer, (void*)_shellcode_buffer, sizeof(_shellcode_genshin_Const), 0))
|
||||||
{
|
{
|
||||||
_addr_tar_fpsSet_TarFun = (uint64_t)__Tar_proc_buffer + 160;
|
VirtualFree((void*)_shellcode_buffer, 0, MEM_RELEASE);
|
||||||
_addr_tar_fpsget_TarFun = (uint64_t)__Tar_proc_buffer + 208;
|
_addr_tar_fpsSet_TarFun = (uint64_t)__Tar_proc_buffer + 0xC0;
|
||||||
*(uint64_t*)Hook_addr_fpsget = 0xCCCCCCCCCCCCCCCC;
|
_addr_tar_fpsget_TarFun = (uint64_t)__Tar_proc_buffer + 0xF0;
|
||||||
*(uint64_t*)Hook_addr_fpsSet = 0xCCCCCCCCCCCCCCCC;
|
*(uint64_t*)Hook_addr_fpsget = 0xB848; //hook mov rax,[jmp addr]
|
||||||
*(uint64_t*)Hook_addr_fpsget = 0x25FF;
|
*(uint64_t*)(Hook_addr_fpsget + 2) = _addr_tar_fpsget_TarFun;
|
||||||
*(uint64_t*)(Hook_addr_fpsget + 6) = _addr_tar_fpsget_TarFun;
|
*(uint16_t*)(Hook_addr_fpsget + 10) = 0xE0FF; // jmp rax
|
||||||
*(uint64_t*)Hook_addr_fpsSet = 0x25FF;
|
*(uint64_t*)Hook_addr_fpsSet = 0xB848;
|
||||||
*(uint64_t*)(Hook_addr_fpsSet + 6) = _addr_tar_fpsSet_TarFun;
|
*(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)
|
if (WriteProcessMemory(Tar_handle, (LPVOID)Hook_addr_tar_fpsget, (LPVOID)Hook_addr_fpsget, 0x10, 0) == 0)
|
||||||
{
|
{
|
||||||
DWORD ERR_code = GetLastError();
|
DWORD ERR_code = GetLastError();
|
||||||
printf_s("\nHook get_fps Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
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)
|
if (WriteProcessMemory(Tar_handle, (LPVOID)Hook_addr_tar_fpsSet, (LPVOID)Hook_addr_fpsSet, 0x10, 0) == 0)
|
||||||
{
|
{
|
||||||
DWORD ERR_code = GetLastError();
|
DWORD ERR_code = GetLastError();
|
||||||
printf_s("\nHook get_fps Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
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 + 0x30), 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)
|
||||||
{
|
{
|
||||||
CloseHandle(temp);
|
CloseHandle(temp);
|
||||||
}
|
}
|
||||||
return ((uint64_t)__Tar_proc_buffer + 0xD1);
|
else
|
||||||
|
{
|
||||||
|
printf_s("Create InGame SyncThread Fail! ");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
DWORD ERR_code = GetLastError();
|
return ((uint64_t)__Tar_proc_buffer + 0xF1);
|
||||||
printf_s("\nWrite Patch Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
}
|
||||||
|
printf_s("Inject shellcode Fail! ");
|
||||||
|
VirtualFree((void*)_shellcode_buffer, 0, MEM_RELEASE);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DWORD ERR_code = GetLastError();
|
printf_s("Alloc shellcode space Fail! ");
|
||||||
printf_s("\nVirtual Alloc Fail! ( 0x%X ) - %s\n", ERR_code, GetLastErrorAsString(ERR_code).c_str());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void LoadConfig()
|
void LoadConfig()
|
||||||
{
|
{
|
||||||
@@ -485,8 +418,6 @@ void LoadConfig()
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
|
||||||
// <20><>ȡ<EFBFBD><C8A1><EFBFBD>̾<EFBFBD><CCBE><EFBFBD> - <20><>Ȩ<EFBFBD>ܵ͵<DCB5><CDB5><EFBFBD> - <20><>Ӧ<EFBFBD>û<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
// <20><>ȡ<EFBFBD><C8A1><EFBFBD>̾<EFBFBD><CCBE><EFBFBD> - <20><>Ȩ<EFBFBD>ܵ͵<DCB5><CDB5><EFBFBD> - <20><>Ӧ<EFBFBD>û<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
|
||||||
// PROCESS_QUERY_LIMITED_INFORMATION - <20><><EFBFBD>ڲ<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD>·<EFBFBD><C2B7> (K32GetModuleFileNameExA)
|
|
||||||
// SYNCHRONIZE - <20><><EFBFBD>ڵȴ<DAB5><C8B4><EFBFBD><EFBFBD>̽<EFBFBD><CCBD><EFBFBD> (WaitForSingleObject)
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -595,8 +526,9 @@ int main(int argc, char** argv)
|
|||||||
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 \n4.7<EFBFBD>汾<EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD>лwinTEuser<EFBFBD>ϸ<EFBFBD>֧<EFBFBD><EFBFBD> \n");
|
||||||
printf("<EFBFBD><EFBFBD>Ϸ·<EFBFBD><EFBFBD>: %s\n\n", ProcessPath.c_str());
|
printf("<EFBFBD><EFBFBD>Ϸ·<EFBFBD><EFBFBD>: %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);
|
||||||
|
|
||||||
DWORD pid = GetPID(ProcessPath.substr(ProcessPath.find_last_of("\\") + 1));
|
DWORD pid = GetPID(procname);
|
||||||
if (pid)
|
if (pid)
|
||||||
{
|
{
|
||||||
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>\n");
|
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>\n");
|
||||||
@@ -616,40 +548,120 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
printf("PID: %d\n", pi.dwProcessId);
|
printf("PID: %d\n", pi.dwProcessId);
|
||||||
|
Sleep(200);
|
||||||
StartPriority = PrioityClass[1];
|
StartPriority = PrioityClass[1];
|
||||||
SetPriorityClass(pi.hProcess, StartPriority);
|
SetPriorityClass(pi.hProcess, StartPriority);
|
||||||
|
|
||||||
// <20>ȴ<EFBFBD>UnityPlayer.dll<6C><6C><EFBFBD>غͻ<D8BA>ȡDLL<4C><4C>Ϣ
|
// <20>ȴ<EFBFBD>UnityPlayer.dll<6C><6C><EFBFBD>غͻ<D8BA>ȡDLL<4C><4C>Ϣ
|
||||||
MODULEENTRY32 hUnityPlayer{};
|
MODULEENTRY32 hUnityPlayer{};
|
||||||
|
{
|
||||||
|
DWORD times = 1000;
|
||||||
|
while (times != 0)
|
||||||
|
{
|
||||||
|
if (GetModule2(pi.hProcess, procname, &hUnityPlayer))
|
||||||
|
{
|
||||||
|
goto __get_procbase_ok;
|
||||||
|
}
|
||||||
|
Sleep(50);
|
||||||
|
times -= 5;
|
||||||
|
}
|
||||||
|
printf("Get BaseModule time out! \n");
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
return (int)-1;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
DWORD times = 1000;
|
||||||
while (!GetModule2(pi.hProcess, "UnityPlayer.dll", &hUnityPlayer))
|
while (!GetModule2(pi.hProcess, "UnityPlayer.dll", &hUnityPlayer))
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
{
|
||||||
|
Sleep(50);
|
||||||
|
times -= 5;
|
||||||
|
if (GetModule2(pi.hProcess, "unityplayer.dll", &hUnityPlayer))
|
||||||
|
{
|
||||||
|
goto __get_procbase_ok;
|
||||||
|
}
|
||||||
|
if (times == 0)
|
||||||
|
{
|
||||||
|
printf("Get Unitymodule time out! \n");
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
return (int)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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:
|
||||||
|
LPVOID _mbase_PE_buffer = VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
// <20>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UnityPlayer.dll<6C><6C>С<EFBFBD><D0A1><EFBFBD>ڴ<EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
if (_mbase_PE_buffer == 0)
|
||||||
LPVOID up = VirtualAlloc(nullptr, hUnityPlayer.modBaseSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
|
||||||
if (!up)
|
|
||||||
{
|
{
|
||||||
DWORD code = GetLastError();
|
printf_s("VirtualAlloc Failed! (PE_buffer)");
|
||||||
printf("VirtualAlloc UP failed (%d): %s", code, GetLastErrorAsString(code).c_str());
|
CloseHandle(pi.hProcess);
|
||||||
return 0;
|
return (int)-1;
|
||||||
}
|
}
|
||||||
|
if (hUnityPlayer.modBaseAddr == 0)
|
||||||
|
return (int)-1;
|
||||||
|
if (ReadProcessMemory(pi.hProcess, hUnityPlayer.modBaseAddr, _mbase_PE_buffer, 0x1000, 0) == 0)
|
||||||
|
{
|
||||||
|
printf_s("Readmem Failed! (PE_buffer)");
|
||||||
|
VirtualFree(_mbase_PE_buffer, 0, MEM_RELEASE);
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
return (int)-1;
|
||||||
|
}
|
||||||
|
BYTE search_sec[8] = ".text";//max 8 byte
|
||||||
|
uint64_t tar_sec = *(uint64_t*)&search_sec;
|
||||||
|
uintptr_t WinPEfileVA = *(uintptr_t*)(&_mbase_PE_buffer) + 0x3c; //dos_header
|
||||||
|
uintptr_t PEfptr = *(uintptr_t*)(&_mbase_PE_buffer) + *(uint32_t*)WinPEfileVA; //get_winPE_VA
|
||||||
|
_IMAGE_NT_HEADERS64 _FilePE_Nt_header = *(_IMAGE_NT_HEADERS64*)PEfptr;
|
||||||
|
_IMAGE_SECTION_HEADER _sec_temp{};
|
||||||
|
uintptr_t Text_Remote_RVA;
|
||||||
|
uint32_t Text_Vsize;
|
||||||
|
if (_FilePE_Nt_header.Signature == 0x00004550)
|
||||||
|
{
|
||||||
|
DWORD sec_num = _FilePE_Nt_header.FileHeader.NumberOfSections;//<2F><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>ڶβ<DAB6><CEB2><EFBFBD>
|
||||||
|
DWORD num = sec_num;
|
||||||
|
DWORD target_sec_VA_start = 0;
|
||||||
|
while (num)
|
||||||
|
{
|
||||||
|
_sec_temp = *(_IMAGE_SECTION_HEADER*)(PEfptr + 264 + (40 * (static_cast<unsigned long long>(sec_num) - num)));
|
||||||
|
|
||||||
|
//printf_s("sec_%d_is: %s\n", sec_num - num, _sec_temp.Name);
|
||||||
|
|
||||||
|
if (*(uint64_t*)(_sec_temp.Name) == tar_sec)
|
||||||
|
{
|
||||||
|
target_sec_VA_start = _sec_temp.VirtualAddress;
|
||||||
|
Text_Vsize = _sec_temp.Misc.VirtualSize;
|
||||||
|
Text_Remote_RVA = (uintptr_t)hUnityPlayer.modBaseAddr + target_sec_VA_start;
|
||||||
|
goto __Get_target_sec;
|
||||||
|
}
|
||||||
|
num--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf_s("Invalid PE header!");
|
||||||
|
VirtualFree(_mbase_PE_buffer, 0, MEM_RELEASE);
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
return (int)-1;
|
||||||
|
}
|
||||||
|
__Get_target_sec:
|
||||||
|
// <20>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>С<EFBFBD><D0A1><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);
|
||||||
|
if (Copy_Text_VA == NULL)
|
||||||
|
{
|
||||||
|
printf("VirtualAlloc Failed! (Text)");
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
return (int)-1;
|
||||||
|
}
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
if (!ReadProcessMemory(pi.hProcess, hUnityPlayer.modBaseAddr, up, hUnityPlayer.modBaseSize, nullptr))
|
if (ReadProcessMemory(pi.hProcess, (void*)Text_Remote_RVA, Copy_Text_VA, Text_Vsize, 0) == 0)
|
||||||
{
|
{
|
||||||
DWORD code = GetLastError();
|
printf("Readmem Fail ! (text)");
|
||||||
printf("ReadProcessMemory unity failed (%d): %s", code, GetLastErrorAsString(code).c_str());
|
VirtualFree(Copy_Text_VA, 0, MEM_RELEASE);
|
||||||
return 0;
|
CloseHandle(pi.hProcess);
|
||||||
|
return (int)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
printf("Searching for pattern...\n");
|
printf("Searching for pattern...\n");
|
||||||
|
|
||||||
//credit by winTEuser
|
//credit by winTEuser
|
||||||
|
uintptr_t address = PatternScan_Region((uintptr_t)Copy_Text_VA, Text_Vsize, "7F 0E E8 ?? ?? ?? ?? 66 0F 6E C8"); // ver 3.7 - last
|
||||||
uintptr_t address = PatternScan(up, "7F 0E E8 ?? ?? ?? ?? 66 0F 6E C8"); // ver 3.7 - last
|
|
||||||
if (!address)
|
if (!address)
|
||||||
{
|
{
|
||||||
printf("outdated pattern\n");
|
printf("outdated pattern\n");
|
||||||
@@ -663,19 +675,20 @@ int main(int argc, char** argv)
|
|||||||
rip += 3;
|
rip += 3;
|
||||||
rip += *(int32_t*)(rip)+6;
|
rip += *(int32_t*)(rip)+6;
|
||||||
rip += *(int32_t*)(rip)+4;
|
rip += *(int32_t*)(rip)+4;
|
||||||
pfps = rip - (uintptr_t)up + (uintptr_t)hUnityPlayer.modBaseAddr;
|
pfps = rip - (uintptr_t)Copy_Text_VA + Text_Remote_RVA;
|
||||||
printf("FPS Offset: %X\n", pfps);
|
printf("FPS Offset: %X\n", pfps);
|
||||||
}
|
}
|
||||||
uintptr_t Patch_ptr = 0;
|
uintptr_t Patch_ptr = 0;
|
||||||
{
|
{
|
||||||
Patch_ptr = inject_patch(up, (DWORD64)hUnityPlayer.modBaseAddr, pfps, pi.hProcess);//45 patch config
|
Patch_ptr = inject_patch(Copy_Text_VA, Text_Vsize, Text_Remote_RVA, pfps, pi.hProcess);//patch inject
|
||||||
if (Patch_ptr == NULL)
|
if (Patch_ptr == NULL)
|
||||||
{
|
{
|
||||||
printf_s("Inject Patch Fail!\n\n");
|
printf_s("Inject Patch Fail!\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFree(up, 0, MEM_RELEASE);
|
VirtualFree(_mbase_PE_buffer, 0, MEM_RELEASE);
|
||||||
|
VirtualFree(Copy_Text_VA, 0, MEM_RELEASE);
|
||||||
printf("Done\n\n");
|
printf("Done\n\n");
|
||||||
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ctrl + <20><>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:\n");
|
printf("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ctrl + <20><>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:\n");
|
||||||
printf(" <20><>ctrl + <20><>: +20\n");
|
printf(" <20><>ctrl + <20><>: +20\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user