Open dmner opened 1 year ago
Hi,
I encountered this problem before, see https://github.com/TsudaKageyu/minhook/issues/10. Back then, MAX_MEMORY_RANGE
was much smaller and the error was much more likely. I increased the range to 0x40000000
, assuming that it will be good enough for all practical usages. Looks like sometimes, even that's not enough.
You can increase the value, but increasing it by a factor of 2 (i.e. to 0x80000000
) can be dangerous since the distance between the target function and the relay function must be less than 0x7FFFFFFF
/0x80000000
:
; x64 mode (assumed that the target function is at 0x140000000)
; 32bit relative JMPs of 5 bytes cover about -2GB ~ +2GB
0x140000000: E9 00000080 JMP 0xC0000005 (RIP-0x80000000)
0x140000000: E9 FFFFFF7F JMP 0x1C0000004 (RIP+0x7FFFFFFF)
; Target function (Jump to the Relay Function)
0x140000000: E9 FBFF0700 JMP 0x140080000 (RIP+0x7FFFB)
; Relay function (Jump to the Detour Function)
0x140080000: FF25 FAFF0000 JMP [0x140090000 (RIP+0xFFFA)]
0x140090000: xxxxxxxxxxxxxxxx ; 64bit address of the Detour Function
(from https://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra)
With the 0x80000000
constant, there's a rare possibility to get a larger distance. Also, if 0x40000000
is sometimes not enough, can you be sure that 0x80000000
will be enough in all cases? Perhaps in your case it's better to patch the target function itself with an absolute jump, if there's enough space for it.
I have this same issue sometimes, and even increasing the MAX_MEMORY_RANGE to 0x70000000 still won't work sometimes. You mentioned using an absolute jump, I would need to make some changes to the source, right? I'm not afraid of making changes but assembly is really difficult for me. Do you have any ideas?
I would need to make some changes to the source, right?
Yes, you'll need to do mainly 2 changes:
#if defined(_M_X64) || defined(__x86_64__)
blocks).Awesome, thank you so much.
On Sat, Feb 11, 2023, 1:30 PM Michael Maltsev @.***> wrote:
I would need to make some changes to the source, right?
Yes, you'll need to do mainly 2 changes:
- Get rid of the relay function. Luckily, 32-bit already works that way, so you can just remove the code that's defined for 64-bit (some of the #if defined(_M_X64) || defined(__x86_64__) blocks).
- Change the code that patches the jump at the beginning of the function. You're less lucky here as here it's the other way around, both 32-bit and 64-bit share an implementation, and you'll need to change it for 64-bit. Here's where the jump is patched https://github.com/TsudaKageyu/minhook/blob/49d03ad118cf7f6768c79a8f187e14b8f2a07f94/src/hook.c#L395-L397. You'll need to patch an absolute jump https://github.com/TsudaKageyu/minhook/blob/49d03ad118cf7f6768c79a8f187e14b8f2a07f94/src/trampoline.c#L84 instead, which is 14 bytes in size instead of 5.
— Reply to this email directly, view it on GitHub https://github.com/TsudaKageyu/minhook/issues/107#issuecomment-1426870660, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKHIPCDYYPXEMDV4D4GS3M3WW7ZH3ANCNFSM6AAAAAATSBO74M . You are receiving this because you commented.Message ID: @.***>
I've been working on the changes. I tested them and they seem to work. One question, with the absolute jump, that would mean MAX_MEMORY_RANGE
is no longer a constraint, because an absolute jump is absolute? So I can set it to something ridiculously high as long as it is less than the maximum value of an unsigned 64 bit integer?
Not only that, you no longer need the FindPrevFreeRegion
/FindNextFreeRegion
functions and the relevant logic. This comment now applies to your 64-bit implementation as well and the same simple VirtualAlloc
call can be used:
https://github.com/TsudaKageyu/minhook/blob/49d03ad118cf7f6768c79a8f187e14b8f2a07f94/src/buffer.c#L221
@EthanZoneCoding, @g0dzcsgo what is the target program/environment that you're having this problem in? @dmner mentioned Mono, I'm wondering what other targets have this problem and what do they have in common (JITted code?). If this problem is common, perhaps it's a good idea to implement a fallback as discussed here into MinHook. I don't like it that much, since that means that these cases will only support functions which are at least 14 bytes long, but that's better than the current state of just failing.
I've been adding VR support to a game via hooking things like DirectX and internal game functions. DirectX is fine, but the internal function is hit or miss when the levels are loaded (it's a large game). That is why I thought the problem could be not finding a place to put in within the range.
Is there a new solution to this problem?
Hi,
I'm attempting to hook a function in mono (which I suspect is part of why this is hit or miss). Randomly I'll get MH_ERROR_MEMORY_ALLOC errors while trying to hook the function. I suspect this is because it depends entirely on where the function got JITted to. stdlib functions seem to have the best results, but that is likely just because they get JITted first. I locally increased the MAX_MEMORY_RANGE constant by a factor of 2 to see if that would improve things and it did. Are there any concerns with increasing this value, will it cause unintended consequences?
Thanks