[Theory/Prerelease/POC] New hooking method!

Posts 1–15 of 26 · Page 1 of 2
[Theory/Prerelease/POC] New hooking method!
Hello everybody,

First: I will release this only when it's completely ready

I happily present to you: A new hooking method!!!
If the good old memory, IAT, and inline hooks(detours) won't do it for you anymore, I've got some new stuff for you to try!

I'm unsure if this has already done before, but I'm sure that it'll be the first time this is shared on this site.

What does it do?

It's very easy, I made an hook function to change all calls to a certain function in a range of addresses to your hooked function. For example if you wanted to relay all calls residing in the memory range 0x10000-x0FFFFF to your own function, it means you can!

How does it do what it does?

This is also fairly simple although it cost me an headache to write and think it all out. I think it's clearest if I show a piece of pseudo code:

Code:
/*
Where AddressToStart is the address to start looking for calls
AddMemoryAddressToStartAddress() a function to get to the destination address of the call
CompareAddresses() a function to see if the function you want to hook and the call address are the same
WriteJumpAndPatchCode() a function to write the patch to your own code, over writing the previous call to a jmp which inturn jumps to the your hook

*/
for ( in i = 0; AddressToStart[i] != 0x0E8; i++){

}
AddMemoryAddressToStartAddress(i);
CompareAddresses(AddressToCompareTo, i);
NotMatch(StartOver);
Match(WriteJumpAndPatchCode);
StartOver;
The function will look for calls inside the memory range you've given, if it finds a call it compares the destination of that call to the address you've given. If the call matches the api writes a jump/call combination to your own function wherever it is in memory. Then it continues searching

On success the return value is the amount of calls patched
On failure the return value is 0

Technicalities:

Due to a the fact that the processor has the liberty to walk the opcode scheme and calculate calls & jumps flawlessly, and I can't, the call/jump combination is always a little off (1 to 8 bytes off actually)
That's why one needs to append nops & the windows preamble (saving the stack) manually, because the real preamble is probably not going to be executed

This is hook function is only local for now, but since Call/jumps can be calculated as well intermodule calls will be added later on, hence the reason why this is a Prerelease

-SCHiM

Tell me what you guys think, is it good? Has it already been done before? Any suggestions/questions?
I don't see what this would accomplish. What would be the point of using this instead of the inline hooks you mention? If you are trying to avoid detection, the whole module is usually scanned anyway.
Quote Originally Posted by mmbob View Post
I don't see what this would accomplish. What would be the point of using this instead of the inline hooks you mention? If you are trying to avoid detection, the whole module is usually scanned anyway.
Then inline would also be detected wouldn't it? But because this is something they haven't seen before maybe it slips undetected. And this is not as much a point of avoiding detection but more of an just being an alternative.

A more easy alternative since I can easily turn this into an nice lib that you can include and call without needing to know more than how to use variables while inlinehooks are harder to do
I don't wanna be the jerk this time someone else tell him, but nice job SCHiM. It's good to see people trying to create something new rather then the same-ole, same-ole.
Quote Originally Posted by why06 View Post
I don't wanna be the jerk this time someone else tell him, but nice job SCHiM. It's good to see people trying to create something new rather then the same-ole, same-ole.
tell me what?
Quote Originally Posted by .::SCHiM::. View Post
tell me what?
Meh it's just that that's the standard way a hook is done. The function is patched with a jump to the alternate code and then that code jumps back. Perhaps your actually patching the call rather then the first bytes of the functions, in which case you should know your only patching one call to the function and not hooking the function itself. But you said hooking the function, so I assumed it was the later. If so this is the standard procedure by which all function are hooked, for SetWindowsHook() to Detours.lib.

Hmmm... rereading your function it seems like it does the former. Never mind then that is unique, cut me some slack I was tired when I saw this. You confused me when you started talking about preamble or stack frame since that would not be cut if you only patched the call, maybe just a few bytes after the call.
But one thing you should know not all calls to functions are hardcoded. you may just as easily get something like this:
Code:
call EBX
In which case the code would fail. Just something to keep in mind. Might also want to patch jmps to code as well. In any case Goodjob. Turned out I spoke to soon.

Also I don't get why your jmps would be 1 to 8 bytes off of the actual call, they should be exact. If not I would like to see how your calculating this.
Quote Originally Posted by why06 View Post


Meh it's just that that's the standard way a hook is done. The function is patched with a jump to the alternate code and then that code jumps back. Perhaps your actually patching the call rather then the first bytes of the functions, in which case you should know your only patching one call to the function and not hooking the function itself. But you said hooking the function, so I assumed it was the later. If so this is the standard procedure by which all function are hooked, for SetWindowsHook() to Detours.lib.

Hmmm... rereading your function it seems like it does the former. Never mind then that is unique, cut me some slack I was tired when I saw this. You confused me when you started talking about preamble or stack frame since that would not be cut if you only patched the call, maybe just a few bytes after the call.
But one thing you should know not all calls to functions are hardcoded. you may just as easily get something like this:
Code:
call EBX
In which case the code would fail. Just something to keep in mind. Might also want to patch jmps to code as well. In any case Goodjob. Turned out I spoke to soon.

Also I don't get why your jmps would be 1 to 8 bytes off of the actual call, they should be exact. If not I would like to see how your calculating this.
Ok good,

For other's information: I really patch the calls, not the function itself, so if you have a call:

Code:
E8 01000000
I really change the number of instructions to move

Code:
E8 10000000
Perhaps your actually patching the call rather then the first bytes of the functions, in which case you should know your only patching one call to the function and not hooking the function itself
But patching all calls in the image would hook the function right?

You confused me when you started talking about preamble or stack frame since that would not be cut if you only patched the call, maybe just a few bytes after the call.
I don't know why it's off, I assume it is because the processor & call operations in general only change the EIP. And while the processor can check how long the last instruction was I cannot, so that's why the call/jump can be a little off

I would like to test it on D3D sometimes, but I don't know enough about it's functions and workings to make a reliable test, care to help?

-SCHiM
Quote Originally Posted by .::SCHiM::. View Post
I don't know why it's off, I assume it is because the processor & call operations in general only change the EIP. And while the processor can check how long the last instruction was I cannot, so that's why the call/jump can be a little off
when you call a function the return address is set in the stack to be the next instruction. They reasons your describing aren't making since. Can I see just specifically the code you used to write over the call, because I think that's where the problem lies.

EDIT:
Here's an example of a call. (Taken from Olly)
Code:
00433222   |.  E8 28010000              CALL dumpRedi.0043334F
As you can see at address 0x00433222 the program calls the function at address 0043334F. A call is essentially a jmp where the return address, which is the location of the next opcode is pushed on the stack.

Here I stepped into the call and you can see the address pushed
Code:
0012FF00     00433227  RETURN to dumpRedi.<ModuleEntryPoint>+6F from dumpRedi.0043334F
The call took up 5 bytes so notice that the return address is 0x00433222 + 5.


Also noticed the opcodes that the call consists of (I bolded them)
Code:
 E8 28010000
The call is a long jump which mean it jumps a certain distance. The distance is the last DWORD, which is written in reverse byte order or (little Endian)converted to the normal way we represent numbers (big-Endian), biggest number first we get.... 0x00000128 or 128 bytes. So I did the math with a hex calculator and found that the calling address 0x00433222 + 0x128 = 0x0043334A NOT 0x0043334F (our destination)!

What this means is the instruction CALL automatically adds 5 bytes to the distance to jump. This could be so that call does not land within itself, but whatever the reason you should make sure you add the distance (0x128 in this case) + 5 (bytes) whenever you calculate function locations using CALL!



Quote Originally Posted by why06 View Post


when you call a function the return address is set in the stack to be the next instruction. They reasons your describing aren't making since. Can I see just specifically the code you used to write over the call, because I think that's where the problem lies.

EDIT:
Here's an example of a call. (Taken from Olly)
Code:
00433222   |.  E8 28010000              CALL dumpRedi.0043334F
As you can see at address 0x00433222 the program calls the function at address 0043334F. A call is essentially a jmp where the return address, which is the location of the next opcode is pushed on the stack.

Here I stepped into the call and you can see the address pushed
Code:
0012FF00     00433227  RETURN to dumpRedi.<ModuleEntryPoint>+6F from dumpRedi.0043334F
The call took up 5 bytes so notice that the return address is 0x00433222 + 5.


Also noticed the opcodes that the call consists of (I bolded them)
Code:
 E8 28010000
The call is a long jump which mean it jumps a certain distance. The distance is the last DWORD, which is written in reverse byte order or (little Endian)converted to the normal way we represent numbers (big-Endian), biggest number first we get.... 0x00000128 or 128 bytes. So I did the math with a hex calculator and found that the calling address 0x00433222 + 0x128 = 0x0043334A NOT 0x0043334F (our destination)!

What this means is the instruction CALL automatically adds 5 bytes to the distance to jump. This could be so that call does not land within itself, but whatever the reason you should make sure you add the distance (0x128 in this case) + 5 (bytes) whenever you calculate function locations using CALL!



Thanks why06!
I thought calls would only changed the EIP, it seems I was wrong. Btw the call calculation & call verification:

Code:
push eax

mov al, byte ptr[ebx+esi]

inc esi

    cmp al, 0E8h
        je @1

xor eax, eax        

add eax, ebx
add eax, esi

    cmp eax, edx
        jne BeforeEaxReturn
        
    pop eax
    ret

@1:                 ;address receive routine

mov eax, dword ptr[ebx+esi]

push eax
push esi

add esi, ebx
add esi, eax
mov eax, esi
add eax, 5d
pop esi
push ecx

@2:
sub ecx, eax
cmp ecx, 9
    ja BeforeSecondEaxReturn    ; it's not the correct function that we want to patch

So I must add 5 to the address to call to...
(did I mention it's written in assembler?)

mov ebx,address
call ebx
Did you know that when you call a function like that, the opcode changes?
I can easily find out if the call made will use a register or an imminent operand as a value. In case of the register, I could trace back mov/add/sub instructions with that particular register (second operand denotes what register to check for) and patch the function. It's possible, I just haven't done it yet
so instead of detouring with the jmp instruction youre detouring with the call instruction?
Quote Originally Posted by Astral Witch View Post
so instead of detouring with the jmp instruction youre detouring with the call instruction?
Not detouring, the original function isn't being called anymore, while detours patch the first few bytes of a function and point it to their own
Quote Originally Posted by .::SCHiM::. View Post
Not detouring, the original function isn't being called anymore, while detours patch the first few bytes of a function and point it to their own
when i said detour i meant the literal meaning, you're changing the call instruction to call your own function instead of the original. in your function you're probably going to call the original function so that you can return without crashing.

so lets see.

original: call -> original -> return

your modified version: call -> your function -> original -> return
So you want to look for every call to a certain function and patch the call so that it goes to your own function?

I can tell why this won't work at all. If you come across a call where it's operand is a register, the only way of finding out which address it's calling to is by breaking at that call and checking the contents of the register.

So everytime you see this:
Code:
mov ebx,address
call ebx
You're going to have to break, check what ebx is, decide whether or not you want to patch, and move on.

Disregarding everything I've just said, you can always manually find the address of the call you need to hook and use MS detours to detour that single instruction to your own function ( this is how most CA hacks were undetected for a while ).

So yeah, good luck with all that.

P.S: This is not new.
I don't think that's right, but it's hard for me to tell since you let the beginning out. Can you label the important mov and compare instructions and let me know what ebx starts off as?
Quote Originally Posted by why06 View Post
I don't think that's right, but it's hard for me to tell since you let the beginning out. Can you label the important mov and compare instructions and let me know what ebx starts off as?
It works, tested it myself, the jump is now flawles, thank you
I'm soon going to release it I think, both the source and a library to use it with.
Posts 1–15 of 26 · Page 1 of 2

Post a Reply

Tags for this Thread

None

Talk with us