Merge branch 'main' into new-index-but-better

This commit is contained in:
matcool 2024-06-01 18:56:22 -03:00
commit 19ab68d202
10 changed files with 88 additions and 30 deletions

View file

@ -196,10 +196,10 @@ if (WIN32)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
# target x86 on windows with clang
target_compile_options(${PROJECT_NAME} INTERFACE --target=i686-pc-windows-msvc)
target_link_options(${PROJECT_NAME} INTERFACE --target=i686-pc-windows-msvc)
add_compile_options(--target=i686-pc-windows-msvc)
add_link_options(--target=i686-pc-windows-msvc)
target_compile_options(${PROJECT_NAME} INTERFACE --target=x86_64-pc-windows-msvc)
target_link_options(${PROJECT_NAME} INTERFACE --target=x86_64-pc-windows-msvc)
add_compile_options(--target=x86_64-pc-windows-msvc)
add_link_options(--target=x86_64-pc-windows-msvc)
endif()
endif()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
loader/include/link/z.lib Normal file

Binary file not shown.

View file

@ -65,39 +65,62 @@ std::string loadGeode() {
gdTimestamp = ntHeader->FileHeader.TimeDateStamp;
#ifdef GEODE_IS_WINDOWS32
constexpr size_t trampolineSize = 12;
constexpr size_t trampolineSize = GEODE_WINDOWS64(32) GEODE_WINDOWS32(12);
mainTrampolineAddr = VirtualAlloc(
nullptr, trampolineSize,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE
);
auto entryAddr = geode::base::get() + ntHeader->OptionalHeader.AddressOfEntryPoint;
const uintptr_t entryAddr = geode::base::get() + ntHeader->OptionalHeader.AddressOfEntryPoint;
// function that calls main
auto preWinMainAddr = entryAddr + 5 + *reinterpret_cast<uintptr_t*>(entryAddr + 6) + 5;
// 32 bit:
// e8 xx xx xx xx call (security)
// e9 xx xx xx xx jmp
// 64 bit:
// 48 83 ec 28 sub rsp, 0x28
// e8 xx xx xx xx call (security)
// 48 83 c4 28 add rsp, 0x28
// e9 xx xx xx xx jmp
// 6a 00 push 0
// 68 00 00 40 00 push geode::base::get()
// e8 ... call ...
uint64_t mainSearchBytes = 0xe80000000068006a;
constexpr ptrdiff_t mainCallJmpOffset = GEODE_WINDOWS64(13) GEODE_WINDOWS32(5);
const uintptr_t mainCallJmpAddress = entryAddr + mainCallJmpOffset;
const int32_t mainCallJmpValue = *reinterpret_cast<int32_t*>(mainCallJmpAddress + 1);
const uintptr_t preWinMainAddr = mainCallJmpAddress + mainCallJmpValue + 5;
// the search bytes for the main function
// 32 bit:
// 6a 00 push 0
// 68 00 00 40 00 push geode::base::get()
// e8 ... call ...
// 64 bit:
// 44 8b cb mov r9d, ebx
// 4c 8b c0 mov r8, rax
// 33 d2 xor edx, edx
// 48 8d 0d xx xx xx xx lea rcx, [rip + ...]
// e8 ... call ...
constexpr uint64_t mainSearchBytes = GEODE_WINDOWS64(0xd233c08b4ccb8b44) GEODE_WINDOWS32(0x004000006a006800);
constexpr ptrdiff_t mainSearchCallOffset = GEODE_WINDOWS64(15) GEODE_WINDOWS32(7);
#ifdef GEODE_IS_WINDOWS32
mainSearchBytes |= static_cast<uint64_t>(geode::base::get()) << 24;
#endif
uintptr_t patchAddr = 0;
// 0x10000 should be enough of a limit here..
for (auto searchAddr = preWinMainAddr; searchAddr < preWinMainAddr + 0x10000; searchAddr++) {
// 0x1000 should be enough of a limit here..
for (auto searchAddr = preWinMainAddr; searchAddr < preWinMainAddr + 0x1000; searchAddr++) {
if (*reinterpret_cast<uint64_t*>(searchAddr) != mainSearchBytes)
continue;
// follow near call address, this is the call to main
patchAddr = searchAddr + 12 + *reinterpret_cast<ptrdiff_t*>(searchAddr + 8);
const uintptr_t callAddress = searchAddr + mainSearchCallOffset;
const int32_t callValue = *reinterpret_cast<int32_t*>(callAddress + 1);
patchAddr = callAddress + callValue + 5;
break;
}
if (patchAddr == 0)
return "Geode could not find the main function, not loading Geode.";
constexpr size_t patchSize = 6;
#define JMP_ADDR(from, to) (std::bit_cast<uintptr_t>(to) - std::bit_cast<uintptr_t>(from) - 5)
#define JMP_BYTES(from, to) \
static_cast<uint8_t>((JMP_ADDR(from, to) >> 0) & 0xFF), \
@ -105,6 +128,41 @@ std::string loadGeode() {
static_cast<uint8_t>((JMP_ADDR(from, to) >> 16) & 0xFF), \
static_cast<uint8_t>((JMP_ADDR(from, to) >> 24) & 0xFF)
#ifdef GEODE_IS_WINDOWS64
constexpr size_t patchSize = 15;
uintptr_t jumpAddr = patchAddr + patchSize;
uint8_t trampolineBytes[trampolineSize] = {
// mov [rsp + 8], rbx
0x48, 0x89, 0x5c, 0x24, 0x08,
// mov [rsp + 10], rsi
0x48, 0x89, 0x74, 0x24, 0x10,
// mov [rsp + 18], rdi
0x48, 0x89, 0x7c, 0x24, 0x18,
// jmp [rip + 0]
0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
// pointer to main + 15
static_cast<uint8_t>((jumpAddr >> 0) & 0xFF), static_cast<uint8_t>((jumpAddr >> 8) & 0xFF), static_cast<uint8_t>((jumpAddr >> 16) & 0xFF), static_cast<uint8_t>((jumpAddr >> 24) & 0xFF),
static_cast<uint8_t>((jumpAddr >> 32) & 0xFF), static_cast<uint8_t>((jumpAddr >> 40) & 0xFF), static_cast<uint8_t>((jumpAddr >> 48) & 0xFF), static_cast<uint8_t>((jumpAddr >> 56) & 0xFF),
// nop to pad it out, helps the asm to show up properly on debuggers
0x90, 0x90, 0x90
};
std::memcpy(mainTrampolineAddr, trampolineBytes, trampolineSize);
auto jmpAddr = reinterpret_cast<uintptr_t>(&gdMainHook);
uint8_t patchBytes[patchSize] = {
// jmp [rip + 0]
0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
// pointer to gdMainHook
static_cast<uint8_t>((jmpAddr >> 0) & 0xFF), static_cast<uint8_t>((jmpAddr >> 8) & 0xFF), static_cast<uint8_t>((jmpAddr >> 16) & 0xFF), static_cast<uint8_t>((jmpAddr >> 24) & 0xFF),
static_cast<uint8_t>((jmpAddr >> 32) & 0xFF), static_cast<uint8_t>((jmpAddr >> 40) & 0xFF), static_cast<uint8_t>((jmpAddr >> 48) & 0xFF), static_cast<uint8_t>((jmpAddr >> 56) & 0xFF),
// nop to pad it out, helps the asm to show up properly on debuggers
0x90
};
#else
constexpr size_t patchSize = 6;
uint8_t trampolineBytes[trampolineSize] = {
// push ebp
0x55,
@ -124,15 +182,13 @@ std::string loadGeode() {
// nop to pad it out, helps the asm to show up properly on debuggers
0x90
};
#endif
DWORD oldProtect;
if (!VirtualProtectEx(process, reinterpret_cast<void*>(patchAddr), patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
return "Geode could not hook the main function, not loading Geode.";
std::memcpy(reinterpret_cast<void*>(patchAddr), patchBytes, patchSize);
VirtualProtectEx(process, reinterpret_cast<void*>(patchAddr), patchSize, oldProtect, &oldProtect);
#else
#pragma message("64-bit entry is not implemented yet.")
#endif
return "";
}

View file

@ -159,16 +159,18 @@ intptr_t Addresser::followThunkFunction(intptr_t address) {
auto jmpOffset = *reinterpret_cast<int32_t*>(address + 7 + 1);
auto tailMergeAddr = address + 7 + jmpOffset + 5;
// this is quite a scary offset, but lets hope it works
auto leaAddr = tailMergeAddr + 51;
// make sure leaAddr is pointing to a lea rcx, [rip + ...]
if (leaAddr && checkByteSequence(leaAddr, {0x48, 0x8d, 0x0d})) {
auto offset = *reinterpret_cast<int32_t*>(leaAddr + 3);
auto did = reinterpret_cast<PCImgDelayDescr>(leaAddr + 7 + offset);
address = reinterpret_cast<intptr_t>(__delayLoadHelper2(did, reinterpret_cast<FARPROC*>(leaAddress)));
// inside of the tail merge, try to find the lea rcx, [rip + ...]
for (uintptr_t leaOffset = 10; leaOffset < 100; ++leaOffset) {
auto leaAddr = tailMergeAddr + leaOffset;
if (checkByteSequence(leaAddr, {0x48, 0x8d, 0x0d})) {
auto offset = *reinterpret_cast<int32_t*>(leaAddr + 3);
auto did = reinterpret_cast<PCImgDelayDescr>(leaAddr + 7 + offset);
address = reinterpret_cast<intptr_t>(__delayLoadHelper2(did, reinterpret_cast<FARPROC*>(leaAddress)));
if (address == -1) {
address = 0;
if (address == -1) {
address = 0;
}
break;
}
}
}