Hi,

I've spawned recent interests in hooking APIs, and i was just wondering if anybody knew/knows how to achieve API hooking via KMD? I couldn't find anything by googling, and the only stuff i found were v*ral stuff, which i won't mention here...plus, everything i tried to look for were in C++, with really vague inline ASM. So far, i've scourged up some articles and read them, and apparently there are a bunch of ways to hook API, most of them were sort-of explained, and they worked in ring3. My goal that i wish to reach is coding a professional "semi-AV" program, in which if a executable is executed, and it is labeled as "suspicious", the execution is intercepted, and the user is given the choice to allow the task to execute or not...I've looked on other examples, such as IAT patching (still sort of unclear in my mind...), but i think patching the IAT for everything deems unrealistic for me, as i would have to patch all the processes in memory? So the alternative i found was a KMD, hooking in kernel level....does anybody know/have some examples of this?

Thanks for your help! any help is greatly appreciated!


-Drocon
Posted on 2003-07-08 09:08:14 by Drocon
If you mean system servises hooking ( Nt* or Zw ) download Invisibility (masm32 source) from Iczelion's http://win32asm.cjb.net/

RegMom or FileMon ( sysinternals.com ) are very good examples. The c-sources were available till ~v4.24. May be you will be able to find it.

If you mean user mode API hooking from KM, it gives you no advantages. It's better to use well known methods.
Explore this thread. Hook question for advanced coders It contents doesn't matter but the links are useful.
Posted on 2003-07-08 11:26:32 by Four-F
Windows NT ( at least since W2K, dunno about NT4 ) uses a feature called COW ( Copy On Write ).

The system memory pages considered as shared ( shared: pages that every process can see but they all point to same real memory pages ) are read only ( yes, read only, no matter if you madify their portection flags by VirtualProtect or alike, they will still be write protected ).

Why?, Imagine you do:

...
mov eax,
mov ,MyHookFunction ( this is only to ilustrate a possible hook escenario )
...

What would happen if you would be able to write to that memory page ( if that page was really ReadWrite )? All the processes would see the change, cos being a shared page, all processes map their virtual address for this page to the same real memory page.

So this is not possible, then, what does really happen?

Imagine you """unprotect""" that memory page by VirtualProtect and then:

...
mov eax,
mov ,MyHookFunction
...

You would just hooked ExitProcess FOR YOUR PROCESS MEMORY SPACE... "How?! didn?t you say its shared memory? Then why does the change affect only my process? memory view?"

As I said, the page is write protected so when you perform a write access to the page a fage fault occurs and kernel catches the exception...

Then when it catches the exception it checks ( among other things ) if a shared memory page is being written and so if this was the case, it:

A) Allocates a page ( 4096 bytes ) of real ( physical ) memory and copies the still untouched shared memory page that the write instruction was trying to write on to this newly allocated real memory page.

B) Changes the LinearToPhysical memory correspondence info ( PAGE TABLE ENTRY in system info structs for the process... see 386 protected mode info ... ) for the process and makes it point to the newly allocated physical memory page.

C) Sets this new page as read&write by changing its PAGE TABLE ENTRY too so that further write accesses are possible as for a normal data page.

D) Continues the execution and the instruction that caused the fault no longer causes the fault, it is executed normally cos the page has now read&write access.

So, this way, your process sees the changes in its virtual memory, but as real memory page corresponding to that virtual memory page has been copied to another real memory page and ONLY THEN has been changed, other processes still see the original contents of the original real memory page.

P.S.: I have written this quite in a hurry :S // Does this all sound as martian language ?? >> http://www.cl.cam.ac.uk/~nej22/cprg/i386manual/ ( chapters 5, and 6, but everything of it in general ) a MUST for every x86 ASM programmer I think... Just to jump out of the matrix ;D
Posted on 2003-08-06 08:25:10 by sheroc
If you get ring0 ( by a WDM a KMD or a Ring0Call/IntGate trick ) in NT, then to modify a page you would:

mov eax,cr0
push eax
and eax,0FFFEFFFFh ; Disable WP ( write protection ) bit in CR0
mov cr0,eax ; so that write access violations dont occur ( everything is writable if its present )

;; This will disable CopyOnWrite temporally

then modify that kernel32.dll module pages in memory ( be careful, this might not be directly accesible from kernel mode -IT IS if you use Call/IntGate trick- ) as you want/please

then:

pop eax
mov cr0,eax ; restore the original CR0 settings and original WP state ;D

;; This will re ENABLE ( or DISABLE if it was originally disabled -some old softice versions need it disabled- ) CopyOnWrite or better to say kernel mode write protection.

P.S.: See Mark Russinovich?s article on direct Physical Memory Mapping under WinNT ( used for the NT Call/IntGate trick that might be needed to implement global system hook propperly ) in www.sysinternals.com // needless to say this will require admin privileges :P // Other authors have also written more on this, EliCZ and some others ( google for it! ).
Posted on 2003-08-06 08:39:08 by sheroc
You could use Elicz? backdoor trick too. And in XP atleast this works:

example:

void func() {
DWORD FuncAddr = (DWORD) GetProcAddress( GetModuleHandle( "ntdll" ), "NtSomeCommand" ) );
VirtualProtect....

__asm {
mov edi, FuncAddr
mov byte ptr , 90h
}
}
That does work...
Posted on 2003-08-06 14:02:50 by SFP
Well, I dont know if we are speaking about the same stuff but \Device\Physicalmemory editing to create Call/IntGate is from not EliCZ ( although he has done a variant as other have done too; originally its Mark Russinovich?s trick... )

And yes, the thing can be done several ways but easiest is to a) modify the memory page directly or b) go ring0, disable kernel write protection and modify the page and return to ring3.

But a) approach needs some serious surgery ( is not easy to manage physical addressing for virtual addresses out of 80000000h to A0000000h memory range... -maybe seek&destroy alike way?, I would use b) way- )

Bye!
Posted on 2003-08-06 14:18:20 by sheroc