mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
handle delayLoad failure in Addresser::followThunkFunction
This commit is contained in:
parent
68732ebe57
commit
cf111ca000
1 changed files with 30 additions and 6 deletions
|
@ -69,12 +69,26 @@ Addresser::MultipleInheritance* Addresser::instance() {
|
|||
#ifdef GEODE_IS_WINDOWS
|
||||
#include <delayimp.h>
|
||||
extern "C" FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd, FARPROC* ppfnIATEntry); // NOLINT(*-reserved-identifier)
|
||||
|
||||
FARPROC WINAPI delayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli) {
|
||||
switch (dliNotify) {
|
||||
case dliFailLoadLib:
|
||||
case dliFailGetProc:
|
||||
// incase the delayload helper fails at all (missing symbol, or library entirely),
|
||||
// return -1, so we can more easily handle it below
|
||||
return (FARPROC)(-1);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" const PfnDliHook __pfnDliFailureHook2 = delayLoadHook;
|
||||
#endif
|
||||
|
||||
intptr_t Addresser::followThunkFunction(intptr_t address) {
|
||||
#ifdef GEODE_IS_WINDOWS32
|
||||
// if theres a jmp at the start
|
||||
if (*reinterpret_cast<uint8_t*>(address) == 0xE9) {
|
||||
if (address && *reinterpret_cast<uint8_t*>(address) == 0xE9) {
|
||||
auto relative = *reinterpret_cast<uint32_t*>(address + 1);
|
||||
auto newAddress = address + relative + 5;
|
||||
// and if that jmp leads to a jmp dword ptr, only then follow it,
|
||||
|
@ -87,7 +101,7 @@ intptr_t Addresser::followThunkFunction(intptr_t address) {
|
|||
}
|
||||
|
||||
// check if first instruction is a jmp dword ptr [....], i.e. if the func is a thunk
|
||||
if (*reinterpret_cast<uint8_t*>(address) == 0xFF && *reinterpret_cast<uint8_t*>(address + 1) == 0x25) {
|
||||
if (address && *reinterpret_cast<uint8_t*>(address) == 0xFF && *reinterpret_cast<uint8_t*>(address + 1) == 0x25) {
|
||||
// read where the jmp reads from
|
||||
address = *reinterpret_cast<uint32_t*>(address + 2);
|
||||
// that then contains the actual address of the func
|
||||
|
@ -95,7 +109,7 @@ intptr_t Addresser::followThunkFunction(intptr_t address) {
|
|||
}
|
||||
|
||||
// if it starts with mov eax,..., it's a delay loaded func
|
||||
if (*reinterpret_cast<uint8_t*>(address) == 0xB8) {
|
||||
if (address && *reinterpret_cast<uint8_t*>(address) == 0xB8) {
|
||||
// follow the jmp to the tailMerge func and grab the ImgDelayDescr pointer from there
|
||||
// do it this way instead of grabbing it from the NT header ourselves because
|
||||
// we don't know the dll name
|
||||
|
@ -110,6 +124,11 @@ intptr_t Addresser::followThunkFunction(intptr_t address) {
|
|||
|
||||
// get the address of the function, loading the library if needed
|
||||
address = reinterpret_cast<intptr_t>(__delayLoadHelper2(idd, imp));
|
||||
|
||||
// if the helper failed, it will return -1, so we can handle it here
|
||||
if (address == -1) {
|
||||
address = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef GEODE_IS_WINDOWS64
|
||||
|
@ -124,7 +143,7 @@ intptr_t Addresser::followThunkFunction(intptr_t address) {
|
|||
|
||||
// check if first instruction is a jmp qword ptr [rip + ...], i.e. if the func is a thunk
|
||||
// FF 25 xxxxxxxx
|
||||
if (checkByteSequence(address, {0xFF, 0x25})) {
|
||||
if (address && checkByteSequence(address, {0xFF, 0x25})) {
|
||||
const auto offset = *reinterpret_cast<int32_t*>(address + 2);
|
||||
// rip is at address + 6 (size of the instruction)
|
||||
address = *reinterpret_cast<uintptr_t*>(address + 6 + offset);
|
||||
|
@ -132,7 +151,7 @@ intptr_t Addresser::followThunkFunction(intptr_t address) {
|
|||
|
||||
// if it starts with lea eax,..., it's a delay loaded func
|
||||
// 48 8D 05 xxxxxxxx
|
||||
if (checkByteSequence(address, {0x48, 0x8d, 0x05})) {
|
||||
if (address && checkByteSequence(address, {0x48, 0x8d, 0x05})) {
|
||||
// follow the jmp to the tailMerge func and grab the ImgDelayDescr pointer from there
|
||||
// do it this way instead of grabbing it from the NT header ourselves because
|
||||
// we don't know the dll name
|
||||
|
@ -140,17 +159,22 @@ 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 let's hope it works
|
||||
auto leaAddr = tailMergeAddr + 51;
|
||||
// make sure leaAddr is pointing to a lea rcx, [rip + ...]
|
||||
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 theres a jmp at the start
|
||||
if (*reinterpret_cast<uint8_t*>(address) == 0xE9) {
|
||||
if (address && *reinterpret_cast<uint8_t*>(address) == 0xE9) {
|
||||
auto relative = *reinterpret_cast<uint32_t*>(address + 1);
|
||||
auto newAddress = address + relative + 5;
|
||||
address = newAddress;
|
||||
|
|
Loading…
Reference in a new issue