feat: support external game launchers
This commit is contained in:
parent
7aa7047ccd
commit
9099d50ba8
@ -75,6 +75,11 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LPWSTR targetExe = malloc(MAX_PATH);
|
||||
GetModuleFileNameW(NULL, targetExe, 0);
|
||||
SetCurrentDirectoryW(targetExe);
|
||||
free(targetExe);
|
||||
|
||||
this_module = instance;
|
||||
|
||||
// Dynamically link functions from ntdll
|
||||
|
@ -6,16 +6,26 @@
|
||||
#include <utils.h>
|
||||
|
||||
void utils_map_file(const wchar_t *path, struct file_mapping *map) {
|
||||
map->file = CreateFileW(path, FILE_READ_ACCESS, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
wchar_t* final_path = malloc(MAX_PATH);
|
||||
if (wcsstr(path, L"C:\\") == NULL) {
|
||||
wchar_t* tmp = malloc(MAX_PATH);
|
||||
GetEnvironmentVariableW(L"GAME_PATH", tmp, MAX_PATH);
|
||||
swprintf(final_path, MAX_PATH, L"%ls\\%ls", tmp, path);
|
||||
free(tmp);
|
||||
} else {
|
||||
swprintf(final_path, MAX_PATH, L"%ls", path);
|
||||
}
|
||||
map->file = CreateFileW(final_path, FILE_READ_ACCESS, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (map->file == INVALID_HANDLE_VALUE) {
|
||||
msg_err_w(L"Could not open file: %ls", path);
|
||||
msg_err_w(L"Could not open file: %ls", final_path);
|
||||
}
|
||||
|
||||
map->mapping = CreateFileMappingA(map->file, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
map->data = MapViewOfFile(map->mapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if (!map->data) {
|
||||
msg_err_w(L"Could not map view of file %ls", path);
|
||||
msg_err_w(L"Could not map view of file %ls", final_path);
|
||||
}
|
||||
free(final_path);
|
||||
}
|
||||
|
||||
void utils_unmap_file(struct file_mapping *map) {
|
||||
@ -30,6 +40,10 @@ int utils_path_exists(const wchar_t *filePath) {
|
||||
|
||||
uint32_t utils_file_crc32c(const wchar_t *filePath) {
|
||||
struct file_mapping map;
|
||||
// LPWSTR cwd = malloc(MAX_PATH);
|
||||
// GetCurrentDirectoryW(MAX_PATH, cwd);
|
||||
// msg_info_w(L"File %ls %ls", filePath, cwd);
|
||||
// free(cwd);
|
||||
utils_map_file(filePath, &map);
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <inject.h>
|
||||
#include <envs.h>
|
||||
|
||||
@ -9,6 +10,75 @@ typedef char *(*wgufn_t)(wchar_t* path); // wine_get_unix_file_name
|
||||
|
||||
const wchar_t *J_MB_TITLE = L"Jadeite Launcher Payload";
|
||||
|
||||
// Copied from https://cocomelonc.github.io/pentest/2021/09/29/findmyprocess.html
|
||||
// Find process ID by process name
|
||||
DWORD find_proc_id(const char *procname) {
|
||||
|
||||
HANDLE hSnapshot;
|
||||
PROCESSENTRY32 pe;
|
||||
DWORD pid = 0;
|
||||
BOOL hResult;
|
||||
|
||||
// snapshot of all processes in the system
|
||||
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
|
||||
|
||||
// initializing size: needed for using Process32First
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
|
||||
// info about first process encountered in a system snapshot
|
||||
hResult = Process32First(hSnapshot, &pe);
|
||||
|
||||
// retrieve information about the processes
|
||||
// and exit if unsuccessful
|
||||
while (hResult) {
|
||||
// if we find the process: return process ID
|
||||
if (strcmp(procname, pe.szExeFile) == 0) {
|
||||
pid = pe.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
hResult = Process32Next(hSnapshot, &pe);
|
||||
}
|
||||
|
||||
// closes an open handle (CreateToolhelp32Snapshot)
|
||||
CloseHandle(hSnapshot);
|
||||
return pid;
|
||||
}
|
||||
|
||||
// Find thread ID by process PID
|
||||
int find_main_thread(DWORD pid) {
|
||||
|
||||
HANDLE hSnapshot;
|
||||
THREADENTRY32 pe;
|
||||
DWORD threadId = 0;
|
||||
BOOL hResult;
|
||||
|
||||
// snapshot of all processes in the system
|
||||
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
|
||||
|
||||
// initializing size: needed for using Process32First
|
||||
pe.dwSize = sizeof(THREADENTRY32);
|
||||
|
||||
// info about first process encountered in a system snapshot
|
||||
hResult = Thread32First(hSnapshot, &pe);
|
||||
|
||||
// retrieve information about the processes
|
||||
// and exit if unsuccessful
|
||||
while (hResult) {
|
||||
// if we find the process: return process ID
|
||||
if (pid == pe.th32OwnerProcessID) {
|
||||
threadId = pe.th32ThreadID;
|
||||
break;
|
||||
}
|
||||
hResult = Thread32Next(hSnapshot, &pe);
|
||||
}
|
||||
|
||||
// closes an open handle (CreateToolhelp32Snapshot)
|
||||
CloseHandle(hSnapshot);
|
||||
return threadId;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
||||
// Only listen for attach
|
||||
if (reason != DLL_PROCESS_ATTACH) {
|
||||
@ -32,6 +102,13 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
||||
wcscpy(workdir, targetExe);
|
||||
*(wcsrchr(workdir, L'\\')) = L'\0';
|
||||
|
||||
// Change the game's working directory
|
||||
LPWSTR game_path = malloc(MAX_PATH);
|
||||
GetEnvironmentVariableW(L"GAME_PATH", game_path, MAX_PATH);
|
||||
wchar_t message[64];
|
||||
wsprintfW(message, L"Game Path: %ls", game_path);
|
||||
MessageBoxW(NULL, message, J_MB_TITLE, MB_OK | MB_ICONINFORMATION);
|
||||
|
||||
// SAFETY: verify that the injector is not inside the game directory
|
||||
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
|
||||
wgufn_t wine_get_unix_file_name = (wgufn_t)GetProcAddress(kernel32, "wine_get_unix_file_name");
|
||||
@ -81,7 +158,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
CREATE_SUSPENDED,
|
||||
INHERIT_PARENT_AFFINITY,
|
||||
NULL,
|
||||
workdir,
|
||||
&si,
|
||||
@ -94,10 +171,27 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Find the game process
|
||||
wprintf(L"Waiting for game process to start...\n");
|
||||
DWORD game_pid = 0;
|
||||
while (!game_pid) {
|
||||
// wprintf(L"Looking for game process...\n");
|
||||
game_pid = find_proc_id("StarRail.exe");
|
||||
Sleep(1);
|
||||
}
|
||||
DWORD thread_id = 0;
|
||||
while (!thread_id) {
|
||||
// wprintf(L"Looking for game process...\n");
|
||||
thread_id = find_main_thread(game_pid);
|
||||
Sleep(1);
|
||||
}
|
||||
HANDLE game = OpenProcess(PROCESS_ALL_ACCESS, FALSE, game_pid);
|
||||
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
|
||||
SuspendThread(hThread);
|
||||
// Inject
|
||||
void *payloadStart = &_binary_game_p_o_p_game_p_bin_start;
|
||||
size_t payloadSize = (size_t)&_binary_game_p_o_p_game_p_bin_size;
|
||||
inject(pi.hProcess, payloadStart, payloadSize, injectDll);
|
||||
inject(game, payloadStart, payloadSize, injectDll);
|
||||
|
||||
// Remove the restart flag file
|
||||
DeleteFileW(restartFlagFile);
|
||||
@ -106,15 +200,15 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
||||
char *waitEnabled = getenv("WAIT_BEFORE_RESUME");
|
||||
if (waitEnabled && *waitEnabled) {
|
||||
wchar_t message[64];
|
||||
wsprintfW(message, L"PID: %ld. Press OK to continue", pi.dwProcessId);
|
||||
wsprintfW(message, L"PID: %ld. Thread ID: %ld. Press OK to continue", game_pid, thread_id);
|
||||
MessageBoxW(NULL, message, J_MB_TITLE, MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
// Resume the process
|
||||
ResumeThread(pi.hThread);
|
||||
ResumeThread(hThread);
|
||||
|
||||
// The launcher process should now hang untill the game terminates
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
WaitForSingleObject(game, INFINITE);
|
||||
} while (GetFileAttributesW(restartFlagFile) != INVALID_FILE_ATTRIBUTES);
|
||||
|
||||
return TRUE;
|
||||
|
Loading…
Reference in New Issue
Block a user