TsudaKageyu / minhook

The Minimalistic x86/x64 API Hooking Library for Windows
http://www.codeproject.com/KB/winsdk/LibMinHook.aspx
Other
4.32k stars 886 forks source link

Concerns with increasing: MAX_MEMORY_RANGE? (FindPrevFreeRegion and FindNextFreeRegion return NULL) #107

Open dmner opened 1 year ago

dmner commented 1 year ago

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

m417z commented 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.

EthanZoneCoding commented 1 year ago

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?

m417z commented 1 year ago

I would need to make some changes to the source, right?

Yes, you'll need to do mainly 2 changes:

EthanZoneCoding commented 1 year ago

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:

— 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: @.***>

EthanZoneCoding commented 1 year ago

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?

m417z commented 1 year ago

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

m417z commented 1 year ago

@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.

EthanZoneCoding commented 1 year ago

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.

CNLouisLiu commented 2 months ago

Is there a new solution to this problem?