The reason being is that a mid-function detour is established at a point where either the arguments haven't yet been processed or that they have but the effect of them being process can be reversed and then re performed with altered arguments. I suppose one could programatically find a convenient place for a mid-function detour but the logic behind locating it would be a complete hell to program(I had to build instruction dependency trees with my polymorhpism engine and it was quite a bit of work on its own.)
It's possible to write a (semi-)universal mid function hook by looking at stackframes. I found that you can easily build a generic approach to midfunction hooking if only you take a few things for granted:
Code:
A static location on the stack is present and known( this can be the previous stack frame, or a static variable)
The function does not alter the variables directly ( only reads their contents )
I made a somewhat generic function to hook members of the d3d library. Having studied the library before writing the function, I knew that all (relevant) functions inside the d3d library install exception handlers. So I used a signature (mov eax, dword ptr fs:[0x4], I think) to find these functions in memory. Once I found the right instruction I replaced them with a call to a special function which walks the stack, allocates a *new* stack and copies the relevant arguments onto it.
It then calls the function you intended to be your main hook, this function can just act as if the stack hasn't been tempered with and use the arguments as it pleases. When it returns we arrive at the function that originally created the stack for the main hook. Depending on how you want to use this scheme you could use this function to copy the new stack over the old, and thus changing the arguments. I've only used it to *spy* on arguments, and not actually change them, since that would indeed require more research and/or your function would no longer be generic.
I used this to hook the DIP function once, it's speed is passable and works flawlessly on the d3d library I was using. So perhaps someone could try this too one day.
Here's the function that created the new stack for the hook function to use (a few things are left out, since it's part of a much larger project and the idea is clear for anyone who is familiar with assembly and who's read the text above)
Code:
PreparePseudoStack proc FistArgument:DWORD, PreviousPseudoStack:DWORD ; where first argument is the static variable
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
mov esi, [esp+8h]
cmp esi, 0h
jne @stillStack
invoke GlobalAlloc, GPTR, 400h
mov PseudoStack, eax
add eax, 200h ; eax = middle of pseudo stack (it can grow and shrink)
@@1:
mov SaveEbp, ebp
mov SaveEsp, esp
xor esi, esi
mov edx, [esp+4]
add esp, 4h
@2:
add esp, 4h
cmp [esp], edx
jne @2 ; if past here, esp -> first parameter
sub esp, 4h ; esp -> return address (proper)
mov StackSearch, esp
mov esp, eax
mov ebp, eax
xor ebx, ebx
mov edx, StackSearch
@1:
mov ebx, [edx+esi]
mov [esp+esi], ebx
add esi, 4h
cmp esi, 28h
jne @1
push 0
mov ebp, esp ; put everthing in place for usage (first argument always = ebp + 8 (instead of 4) because push ebp in prolog code
mov eax, SaveEsp
mov eax, [eax]
mov Jumper, eax
add SaveEsp, 0Ch ; remove call + 2 arguments
mov eax, PseudoStack ; return a pointer to the stack
mov esi, SaveEbp
mov [eax], esi
mov esi, SaveEsp
mov [eax+4h], esi ; save origional esp + ebp on the pseudo stack (for DestroyPseudoStack)
jmp Jumper
@stillStack:
mov eax, [esp+8h]
mov PseudoStack, eax
add eax, 200h
jmp @@1