library: inject plugin lib and luajit from stub

This commit is contained in:
Adam
2024-07-30 01:49:12 +01:00
parent 18902eecab
commit 3b51eddd7f
7 changed files with 279 additions and 30 deletions

View File

@@ -14,31 +14,41 @@ if (WIN32)
set(BOLT_STUB_ENTRYNAME entry)
set(BOLT_STUB_ENTRYORDINAL 1)
file(GENERATE OUTPUT stub.def CONTENT "LIBRARY STUB\nEXPORTS\n${BOLT_STUB_ENTRYNAME} @${BOLT_STUB_ENTRYORDINAL}\n")
add_library(stub SHARED dll/stub.c "${CMAKE_CURRENT_BINARY_DIR}/stub.def")
file(GENERATE OUTPUT plugin.def CONTENT "LIBRARY BOLT-PLUGIN\nEXPORTS\n${BOLT_STUB_ENTRYNAME} @${BOLT_STUB_ENTRYORDINAL}\n")
add_library(${BOLT_PLUGIN_LIB_NAME} SHARED dll/main.c plugin/plugin.c gl.c
rwlock/rwlock_win32.c ipc_win32.c plugin/plugin_win32.c ../../modules/hashmap/hashmap.c
../miniz/miniz.c ../../modules/spng/spng/spng.c "${CMAKE_CURRENT_BINARY_DIR}/plugin.def")
target_compile_definitions(${BOLT_PLUGIN_LIB_NAME} PUBLIC BOLT_STUB_ENTRYNAME=${BOLT_STUB_ENTRYNAME})
target_link_libraries(${BOLT_PLUGIN_LIB_NAME} PUBLIC "${BOLT_LUAJIT_DIR}/lua51.lib")
target_include_directories(${BOLT_PLUGIN_LIB_NAME} PUBLIC "${BOLT_LUAJIT_DIR}" "${BOLT_ZLIB_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../miniz")
add_executable(dll_inject_generator dll/dll_inject_generator.cxx)
target_compile_definitions(dll_inject_generator PUBLIC BOLT_STUB_ENTRYORDINAL=${BOLT_STUB_ENTRYORDINAL})
set_target_properties(dll_inject_generator PROPERTIES CXX_STANDARD 20 CXX_EXTENSIONS OFF)
add_custom_command(
OUTPUT dll_inject_cmake_gen.c
DEPENDS ${BOLT_PLUGIN_LIB_NAME} dll_inject_generator
COMMAND dll_inject_generator $<TARGET_FILE:${BOLT_PLUGIN_LIB_NAME}> "${BOLT_LUAJIT_DIR}/lua51.dll" "${CMAKE_CURRENT_SOURCE_DIR}/dll/dll_inject.h" ">dll_inject_cmake_gen.c"
)
add_library(stub SHARED dll/stub.c dll_inject_cmake_gen.c "${CMAKE_CURRENT_BINARY_DIR}/stub.def")
target_compile_definitions(stub PUBLIC BOLT_STUB_ENTRYNAME=${BOLT_STUB_ENTRYNAME})
add_executable(stub_inject_generator dll/stub_inject_generator.cxx)
target_compile_definitions(stub_inject_generator PUBLIC BOLT_STUB_ENTRYORDINAL=${BOLT_STUB_ENTRYORDINAL})
set_target_properties(stub_inject_generator PROPERTIES CXX_STANDARD 20 CXX_EXTENSIONS OFF)
add_custom_command(
OUTPUT stub_inject_cmake_gen.cxx
DEPENDS stub stub_inject_generator
COMMAND stub_inject_generator $<TARGET_FILE:stub> "${CMAKE_CURRENT_SOURCE_DIR}/dll/stub_inject.hxx" ">stub_inject_cmake_gen.cxx"
COMMAND stub_inject_generator $<TARGET_FILE:stub> "${CMAKE_CURRENT_SOURCE_DIR}/dll/stub_inject.h" ">stub_inject_cmake_gen.cxx"
)
add_custom_target(BOLT_STUB_INJECT_DEPENDENCY DEPENDS stub_inject_cmake_gen.cxx)
set(BOLT_STUB_INJECT_CXX "${CMAKE_CURRENT_BINARY_DIR}/stub_inject_cmake_gen.cxx" PARENT_SCOPE)
add_library(${BOLT_PLUGIN_LIB_NAME} SHARED dll/main.c plugin/plugin.c gl.c
rwlock/rwlock_win32.c ipc_win32.c plugin/plugin_win32.c ../../modules/hashmap/hashmap.c
../miniz/miniz.c ../../modules/spng/spng/spng.c)
target_link_libraries(${BOLT_PLUGIN_LIB_NAME} PUBLIC "${BOLT_LUAJIT_DIR}/lua51.lib")
target_include_directories(${BOLT_PLUGIN_LIB_NAME} PUBLIC "${BOLT_LUAJIT_DIR}" "${BOLT_ZLIB_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../miniz")
install(TARGETS ${BOLT_PLUGIN_LIB_NAME} DESTINATION "${BOLT_CEF_INSTALLDIR}/bolt-launcher")
install(FILES "${BOLT_LUAJIT_DIR}/lua51.dll" DESTINATION "${BOLT_CEF_INSTALLDIR}/bolt-launcher")
if(MSVC)
set_property(TARGET stub PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_property(TARGET stub_inject_generator PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_property(TARGET ${BOLT_PLUGIN_LIB_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_property(TARGET stub PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_property(TARGET dll_inject_generator PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_property(TARGET stub_inject_generator PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
target_compile_options(stub_inject_generator PUBLIC ${BOLT_WINDOWS_NONMSVC_OPTIONS})
target_link_options(stub_inject_generator PUBLIC ${BOLT_WINDOWS_NONMSVC_LINKOPTIONS})

View File

@@ -0,0 +1,9 @@
#include <Windows.h>
struct PluginInjectParams {
HMODULE kernel32;
HMODULE(__stdcall* pGetModuleHandleW)(LPCWSTR);
FARPROC(__stdcall* pGetProcAddress)(HMODULE, LPCSTR);
};
void InjectPluginDll(HANDLE process, HMODULE kernel32, HMODULE(__stdcall* pGetModuleHandleW)(LPCWSTR), FARPROC(__stdcall* pGetProcAddress)(HMODULE, LPCSTR));

View File

@@ -0,0 +1,224 @@
#include "stub_inject.h"
#include <algorithm>
#include <iostream>
DWORD perms_for_characteristics(DWORD characteristics) {
const bool readp = (characteristics & IMAGE_SCN_MEM_READ);
const bool writep = (characteristics & IMAGE_SCN_MEM_WRITE);
const bool execp = (characteristics & IMAGE_SCN_MEM_EXECUTE);
return
readp ?
writep ?
execp ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE
:
execp ? PAGE_EXECUTE_READ : PAGE_READONLY
:
writep ?
execp ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY
:
execp ? PAGE_EXECUTE : PAGE_NOACCESS;
}
/// This program is run by the build system on Windows. It manually maps the plugin DLL, then outputs some C code which
/// writes that DLL into a target process, invokes the payload on a remote thread, and blocks until that thread returns.
/// The function generated by this code will be called by the stub DLL during a CreateProcessW hook.
int wmain(int argc, const wchar_t **argv) {
if (argc != 4) {
std::cerr << "dll_inject_generator must be called with exactly three arguments: the absolute path to the "
"plugin dll, the absolute path to lua51.dll, and the absolute path to dll_inject.h." << std::endl;
return 1;
}
HANDLE plugin_file = CreateFileW(argv[1], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (plugin_file == INVALID_HANDLE_VALUE) {
std::cerr << "dll_inject_generator could not open the dll file: ";
std::wcerr << argv[1];
std::cerr << std::endl;
return 1;
}
DWORD plugin_file_size = GetFileSize(plugin_file, NULL);
PVOID plugin_dll = VirtualAlloc(NULL, plugin_file_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!ReadFile(plugin_file, plugin_dll, plugin_file_size, nullptr, nullptr)) {
std::cerr << "dll_inject_generator could not read the dll file: " << GetLastError() << std::endl;
return 1;
}
HANDLE luajit_file = CreateFileW(argv[2], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (luajit_file == INVALID_HANDLE_VALUE) {
std::cerr << "dll_inject_generator could not open the lua dll file: ";
std::wcerr << argv[2];
std::cerr << std::endl;
return 1;
}
DWORD luajit_file_size = GetFileSize(luajit_file, NULL);
PVOID luajit_dll = VirtualAlloc(NULL, luajit_file_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!ReadFile(luajit_file, luajit_dll, luajit_file_size, nullptr, nullptr)) {
std::cerr << "dll_inject_generator could not read the lua dll file: " << GetLastError() << std::endl;
return 1;
}
PIMAGE_DOS_HEADER plugin_dos_header = (PIMAGE_DOS_HEADER)plugin_dll;
PIMAGE_NT_HEADERS plugin_nt_headers = (PIMAGE_NT_HEADERS)((LPBYTE)plugin_dll + plugin_dos_header->e_lfanew);
PIMAGE_SECTION_HEADER plugin_section_header = (PIMAGE_SECTION_HEADER)(plugin_nt_headers + 1);
PIMAGE_DOS_HEADER luajit_dos_header = (PIMAGE_DOS_HEADER)luajit_dll;
PIMAGE_NT_HEADERS luajit_nt_headers = (PIMAGE_NT_HEADERS)((LPBYTE)luajit_dll + luajit_dos_header->e_lfanew);
PIMAGE_SECTION_HEADER luajit_section_header = (PIMAGE_SECTION_HEADER)(luajit_nt_headers + 1);
// find a function in the export table with ordinal value 1, so we can hard-code its RVA.
// this assumes the whole export table of plugin.dll is in one section.
DWORD entry_point_rva = 0;
IMAGE_DATA_DIRECTORY plugin_export_virtual_details = plugin_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
for (size_t i = 0; i < plugin_nt_headers->FileHeader.NumberOfSections; i += 1) {
if (plugin_section_header[i].VirtualAddress > plugin_export_virtual_details.VirtualAddress) continue;
if (plugin_section_header[i].VirtualAddress + plugin_section_header[i].Misc.VirtualSize <= plugin_export_virtual_details.VirtualAddress) continue;
const DWORD export_section_offset = plugin_section_header[i].PointerToRawData - plugin_section_header[i].VirtualAddress;
PIMAGE_EXPORT_DIRECTORY plugin_exports = (PIMAGE_EXPORT_DIRECTORY)((LPBYTE)plugin_dll + (plugin_export_virtual_details.VirtualAddress + export_section_offset));
PDWORD export_address_list = (PDWORD)((LPBYTE)plugin_dll + (plugin_exports->AddressOfFunctions + export_section_offset));
entry_point_rva = export_address_list[BOLT_STUB_ENTRYORDINAL - plugin_exports->Base];
break;
}
if (!entry_point_rva) {
std::cerr << "dll_inject_generator could not locate entry point" << std::endl;
return 1;
}
// output file header and #include lines
std::cout << "// This file was created programmatically by Bolt's build system. Don't change this file - change the code that generated it." << std::endl;
std::cout << "#include <Windows.h>" << std::endl << "#include <stdint.h>" << std::endl << "#include \"";
std::wcout << argv[3];
std::cout << "\"" << std::endl;
// embed dll headers
std::cout << "static const uint8_t plugin_dll_headers[] = {";
for (size_t i = 0; i < plugin_nt_headers->OptionalHeader.SizeOfHeaders; i += 1) {
if (i != 0) std::cout << ",";
std::cout << (WORD)((LPBYTE)plugin_dll)[i];
}
std::cout << "};" << std::endl;
std::cout << "static const uint8_t luajit_dll_headers[] = {";
for (size_t i = 0; i < luajit_nt_headers->OptionalHeader.SizeOfHeaders; i += 1) {
if (i != 0) std::cout << ",";
std::cout << (WORD)((LPBYTE)luajit_dll)[i];
}
std::cout << "};" << std::endl;
// embed dll sections
for (size_t i = 0; i < plugin_nt_headers->FileHeader.NumberOfSections; i += 1) {
std::cout << "static const uint8_t psect" << i << "[] = {";
LPBYTE section_start = (LPBYTE)plugin_dll + plugin_section_header[i].PointerToRawData;
for (size_t j = 0; j < plugin_section_header[i].SizeOfRawData; j += 1) {
if (j != 0) std::cout << ",";
std::cout << (WORD)section_start[j];
}
std::cout << "};" << std::endl;
}
for (size_t i = 0; i < luajit_nt_headers->FileHeader.NumberOfSections; i += 1) {
std::cout << "static const uint8_t luasect" << i << "[] = {";
LPBYTE section_start = (LPBYTE)luajit_dll + luajit_section_header[i].PointerToRawData;
for (size_t j = 0; j < luajit_section_header[i].SizeOfRawData; j += 1) {
if (j != 0) std::cout << ",";
std::cout << (WORD)section_start[j];
}
std::cout << "};" << std::endl;
}
// embed the amount of zeroes we'll need (WriteProcessMemory needs actual memory to copy from)
std::cout << "static const uint8_t zeroes["
<< max(plugin_nt_headers->OptionalHeader.SizeOfHeaders, luajit_nt_headers->OptionalHeader.SizeOfHeaders)
<< "] = {0};" << std::endl;
std::cout << "void InjectPluginDll(HANDLE process, HMODULE kernel32, HMODULE(__stdcall* pGetModuleHandleW)(LPCWSTR), FARPROC(__stdcall* pGetProcAddress)(HMODULE, LPCSTR)) {" << std::endl;
// we can't call imported functions at this point, so lookup the ones we need from kernel32
#define DEFLOOKUP(RET, FN, ARGS) #RET "(__stdcall* p" #FN ")" ARGS "=(" #RET "(__stdcall*)" ARGS ")pGetProcAddress(kernel32, \"" #FN "\");"
std::cout <<
DEFLOOKUP(LPVOID, VirtualAllocEx, "(HANDLE, LPVOID, SIZE_T, DWORD, DWORD)")
DEFLOOKUP(BOOL, VirtualFreeEx, "(HANDLE, LPVOID, SIZE_T, DWORD)")
DEFLOOKUP(BOOL, WriteProcessMemory, "(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*)")
DEFLOOKUP(BOOL, ReadProcessMemory, "(HANDLE, LPCVOID, LPVOID, SIZE_T, SIZE_T*)")
DEFLOOKUP(BOOL, VirtualProtectEx, "(HANDLE, LPVOID, SIZE_T, DWORD, PDWORD)")
DEFLOOKUP(HANDLE, CreateRemoteThread, "(HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD)")
DEFLOOKUP(DWORD, WaitForSingleObject, "(HANDLE, DWORD)")
<< std::endl;
#undef DEFLOOKUP
// allocate memory in the remote process
std::cout << "LPBYTE dll_plugin = (LPBYTE)pVirtualAllocEx(process, NULL, " << plugin_nt_headers->OptionalHeader.SizeOfImage << ", MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);" << std::endl;
std::cout << "LPBYTE dll_lua = (LPBYTE)pVirtualAllocEx(process, NULL, " << luajit_nt_headers->OptionalHeader.SizeOfImage << ", MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);" << std::endl;
// copy DLL headers to the target process
std::cout << "pWriteProcessMemory(process, dll_plugin, (PVOID)plugin_dll_headers, " << plugin_nt_headers->OptionalHeader.SizeOfHeaders << ", NULL);" << std::endl;
std::cout << "pWriteProcessMemory(process, dll_lua, (PVOID)luajit_dll_headers, " << luajit_nt_headers->OptionalHeader.SizeOfHeaders << ", NULL);" << std::endl;
// copy each section to the target process
for (size_t i = 0; i < plugin_nt_headers->FileHeader.NumberOfSections; i += 1) {
std::cout << "pWriteProcessMemory(process, (PVOID)(dll_plugin + " << plugin_section_header[i].VirtualAddress << "), (PVOID)psect" << i << ", " << plugin_section_header[i].SizeOfRawData << ", NULL);" << std::endl;
}
for (size_t i = 0; i < luajit_nt_headers->FileHeader.NumberOfSections; i += 1) {
std::cout << "pWriteProcessMemory(process, (PVOID)(dll_lua + " << luajit_section_header[i].VirtualAddress << "), (PVOID)luasect" << i << ", " << luajit_section_header[i].SizeOfRawData << ", NULL);" << std::endl;
}
// fix relocations
std::cout <<
"ptrdiff_t reloc_delta = (ptrdiff_t)(dll_plugin - " << plugin_nt_headers->OptionalHeader.ImageBase << ");"
"PIMAGE_BASE_RELOCATION remote_reloc_address = (PIMAGE_BASE_RELOCATION)(dll_plugin + " << plugin_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress << ");"
"WORD offset;"
"DWORD ptr;"
"while (1) {"
"IMAGE_BASE_RELOCATION remote_reloc;"
"pReadProcessMemory(process, (LPCVOID)remote_reloc_address, (LPVOID)&remote_reloc, sizeof(remote_reloc), NULL);"
"if (!remote_reloc.VirtualAddress) break;"
"if (remote_reloc.SizeOfBlock > sizeof(remote_reloc)) {"
"PWORD list = (PWORD)(remote_reloc_address + 1);"
"for (size_t i = 0; i < (remote_reloc.SizeOfBlock - sizeof(remote_reloc)) / sizeof(WORD); i += 1) {"
"pReadProcessMemory(process, (LPCVOID)(list + i), (LPVOID)&offset, sizeof(offset), NULL);"
"if (!offset) continue;"
"LPVOID remote_ptr_address = (LPVOID)(dll_plugin + remote_reloc.VirtualAddress + (offset & 0xFFF));"
"pReadProcessMemory(process, (LPCVOID)remote_ptr_address, (LPVOID)&ptr, sizeof(ptr), NULL);"
"ptr += reloc_delta;"
"pWriteProcessMemory(process, remote_ptr_address, (LPCVOID)&ptr, sizeof(ptr), NULL);"
"}"
"}"
"remote_reloc_address = (PIMAGE_BASE_RELOCATION)((LPBYTE)remote_reloc_address + remote_reloc.SizeOfBlock);"
"}"
"reloc_delta = (ptrdiff_t)(dll_lua - " << luajit_nt_headers->OptionalHeader.ImageBase << ");"
"remote_reloc_address = (PIMAGE_BASE_RELOCATION)(dll_lua + " << luajit_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress << ");"
"while (1) {"
"IMAGE_BASE_RELOCATION remote_reloc;"
"pReadProcessMemory(process, (LPCVOID)remote_reloc_address, (LPVOID)&remote_reloc, sizeof(remote_reloc), NULL);"
"if (!remote_reloc.VirtualAddress) break;"
"if (remote_reloc.SizeOfBlock > sizeof(remote_reloc)) {"
"PWORD list = (PWORD)(remote_reloc_address + 1);"
"for (size_t i = 0; i < (remote_reloc.SizeOfBlock - sizeof(remote_reloc)) / sizeof(WORD); i += 1) {"
"pReadProcessMemory(process, (LPCVOID)(list + i), (LPVOID)&offset, sizeof(offset), NULL);"
"if (!offset) continue;"
"LPVOID remote_ptr_address = (LPVOID)(dll_lua + remote_reloc.VirtualAddress + (offset & 0xFFF));"
"pReadProcessMemory(process, (LPCVOID)remote_ptr_address, (LPVOID)&ptr, sizeof(ptr), NULL);"
"ptr += reloc_delta;"
"pWriteProcessMemory(process, remote_ptr_address, (LPCVOID)&ptr, sizeof(ptr), NULL);"
"}"
"}"
"remote_reloc_address = (PIMAGE_BASE_RELOCATION)((LPBYTE)remote_reloc_address + remote_reloc.SizeOfBlock);"
"}" << std::endl;
// set rwx permissions for each section
std::cout << "DWORD oldp;" << std::endl;
for (size_t i = 0; i < plugin_nt_headers->FileHeader.NumberOfSections; i += 1) {
DWORD permission = perms_for_characteristics(plugin_section_header[i].Characteristics);
std::cout << "pVirtualProtectEx(process, (LPVOID)(dll_plugin + " << plugin_section_header[i].VirtualAddress << "), " << plugin_section_header[i].Misc.VirtualSize << ", " << permission << ", &oldp);" << std::endl;
}
for (size_t i = 0; i < luajit_nt_headers->FileHeader.NumberOfSections; i += 1) {
DWORD permission = perms_for_characteristics(luajit_section_header[i].Characteristics);
std::cout << "pVirtualProtectEx(process, (LPVOID)(dll_lua + " << luajit_section_header[i].VirtualAddress << "), " << luajit_section_header[i].Misc.VirtualSize << ", " << permission << ", &oldp);" << std::endl;
}
// invoke entrypoint
std::cout << "struct PluginInjectParams params = {.kernel32=kernel32, .pGetModuleHandleW=pGetModuleHandleW, .pGetProcAddress=pGetProcAddress};" << std::endl;
std::cout << "struct PluginInjectParams* remote_params = (struct PluginInjectParams*)pVirtualAllocEx(process, NULL, sizeof(params), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);" << std::endl;
std::cout << "pWriteProcessMemory(process, remote_params, &params, sizeof(params), NULL);" << std::endl;
std::cout << "HANDLE remote_thread = pCreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)(dll_plugin + " << entry_point_rva << "), remote_params, 0, NULL);" << std::endl;
std::cout << "pWaitForSingleObject(remote_thread, INFINITE);" << std::endl;
std::cout << "pVirtualFreeEx(process, remote_params, 0, MEM_RELEASE);" << std::endl;
// wipe dll headers from remote process
std::cout << "pWriteProcessMemory(process, dll_plugin, (PVOID)zeroes, " << plugin_nt_headers->OptionalHeader.SizeOfHeaders << ", NULL);" << std::endl;
std::cout << "pWriteProcessMemory(process, dll_lua, (PVOID)zeroes, " << luajit_nt_headers->OptionalHeader.SizeOfHeaders << ", NULL);" << std::endl;
std::cout << "}" << std::endl;
CloseHandle(luajit_file);
CloseHandle(plugin_file);
VirtualFree(luajit_dll, luajit_file_size, MEM_RELEASE);
VirtualFree(plugin_dll, plugin_file_size, MEM_RELEASE);
return 0;
}

View File

@@ -1,5 +1,6 @@
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
#include <Windows.h>
#include "dll_inject.h"
DWORD __stdcall BOLT_STUB_ENTRYNAME(struct PluginInjectParams* data) {
return 0;
}

View File

@@ -1,18 +1,17 @@
#include "stub_inject.hxx"
#include "stub_inject.h"
#include "dll_inject.h"
//typedef HANDLE(__stdcall* CREATEFILEW)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
//typedef FARPROC(__stdcall* CLOSEHANDLE)(HANDLE);
//typedef BOOL(__stdcall* WRITEFILE)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
typedef BOOL(__stdcall* CREATEPROCESSW)(LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
typedef BOOL(__stdcall* VIRTUALPROTECT)(LPVOID, SIZE_T, DWORD, PDWORD);
typedef DWORD(__stdcall* RESUMETHREAD)(HANDLE);
//static CREATEFILEW real_CreateFileW;
//static CLOSEHANDLE real_CloseHandle;
//static WRITEFILE real_WriteFile;
static RESUMETHREAD real_ResumeThread;
static CREATEPROCESSW real_CreateProcessW;
BOOL hook_CreateProcessW(LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
struct StubInjectParams params;
// true if match, false if not, for case-insensitive mode a2 must be all lowercase
BOOL bolt_cmp(const char* a1, const char* a2, BOOL case_sensitive) {
while (1) {
@@ -33,10 +32,9 @@ BOOL bolt_cmp(const char* a1, const char* a2, BOOL case_sensitive) {
// process passes us its function pointers for GetModuleHandleW and GetProcAddress. using those, we
// can find the game's imported modules and use them for ourselves.
DWORD __stdcall BOLT_STUB_ENTRYNAME(struct StubInjectParams* data) {
params = *data;
VIRTUALPROTECT pVirtualProtect = (VIRTUALPROTECT)data->pGetProcAddress(data->kernel32, "VirtualProtect");
//real_CreateFileW = (CREATEFILEW)data->pGetProcAddress(data->kernel32, "CreateFileW");
//real_CloseHandle = (CLOSEHANDLE)data->pGetProcAddress(data->kernel32, "CloseHandle");
//real_WriteFile = (WRITEFILE)data->pGetProcAddress(data->kernel32, "WriteFile");
real_ResumeThread = (RESUMETHREAD)data->pGetProcAddress(data->kernel32, "ResumeThread");
HMODULE main_module = data->pGetModuleHandleW(NULL);
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)main_module;
@@ -78,17 +76,24 @@ BOOL hook_CreateProcessW(
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
) {
// CreateProcessW hook, check if we're starting rs2client and if so, inject bolt-plugin.dll
return real_CreateProcessW(
// CreateProcessW hook - the game launcher downloads a new version of the game client, if any,
// then runs it using CreateProcessW. it's the only time it uses this function, so we don't need
// to check what the child process is. just inject the plugin loader into it.
const BOOL is_already_suspended = dwCreationFlags & CREATE_SUSPENDED ? TRUE : FALSE;
BOOL ret = real_CreateProcessW(
lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
dwCreationFlags | CREATE_SUSPENDED,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation
);
if (!ret) return 0;
InjectPluginDll(lpProcessInformation->hProcess, params.kernel32, params.pGetModuleHandleW, params.pGetProcAddress);
if (!is_already_suspended) real_ResumeThread(lpProcessInformation->hThread);
return ret;
}

View File

@@ -1,4 +1,4 @@
#include "stub_inject.hxx"
#include "stub_inject.h"
#include <iostream>
/// This program is run by the build system on Windows. It manually maps the stub DLL, then outputs some C++ code which