Log in

View Full Version : Using drivers to patch and hook other code


dELTA
February 9th, 2003, 15:23
I've been wondering for a long time about which techniques that are used when a driver is used to patch or hook other code in the operating system. For example patching operating system modules like kernel32.dll or other third-party drivers (i.e. using in-memory patching, not modifying the actual files on disk).

Is the common technique to simply patch the memory space of the target code, e.g. the code section of kernel32.dll, or is it some more advanced things that have to be done? Are there several different techniques that are usually used for this purpose? Is it elementary to make a global patch of e.g. operating system dll:s from a driver? (With global patch I mean a patch that is seen by all other programs, contrary to the "copy-on-write"-semantic effects that can occur when doing in-memory patching of dll:s from ring3 programs)

If it is only pure patching of the target module memory that is most often used, I guess that you use a driver to do it simply because there is no way to e.g. patch the code section of kernel32.dll from a ring3 program? Or can this be done from ring3 code to, but only local to the process itself, using some virtualprotect trickery?

I have recently bought a good book about driver programming, but I am worried that it won't cover these things (at least not in an apparent manner), so I thought that I'd try to find out some rough details about the used techniques beforehand, so that I can easier spot the parts of the book that are useful for these purposes.

I have understood that several people on this board are quite handy with such driver patching acrobatics, so it would be really great if you could just throw some small pieces of info my way, just to get me started.

Any pointers to good references (e.g. essays) about this subject would be really great too.

Thanks a lot!

Kayaker
February 10th, 2003, 19:03
Hi

I can indeed imagine that your driver programming book won't discuss too much about covert memory patching system code, heh, unless it's a cool Undocumented book Your question is fairly general, but I suppose the benefit of Ring0 *IS* that you can do pretty much what you want. Driver development is actually quite fun because you do have access to all the low level system calls that the Win32 apis generally thunk down to anyway, as well as a complete programming IDE if you will.

With the VMM calls you can use string management functions, access the registry, read and write to disk, modify page permissions if necessary, hook interrupts, create system hooks, as well as modifying memory directly. I'm not sure if there are some restrictions in Win2K driver development in patching certain areas of system memory. Loading your driver from an injected dll in the target program might be sufficient to give you complete memory access.

If you're simply trying to patch the kernel or some other dll for some reason you'd probably want to look into api hooking first, which would be safer and give you more flexibility than a crude patch. But if you're after deeper system control then drivers are a good way to go.

If you're interested, there's an example program in the miniproject forum (Reversing system tools) on creating a general Hook proc in a vxd with VMMCall Hook_Device_Service, with which you can intercept pretty well any VMM service call, the example hooks VMM_Add_DDB to detect when another system driver is being loaded. There's a few ideas for you anyway.

Cheers,
Kayaker

tgodd
February 11th, 2003, 00:44
You may have problems patching memory due to paging.
These problems, however, can be overcome.

You will need to familiarize yourself with the Ix86 Paging mechanism. A good source for reference is the Intel Secrets Web Site.. I believe it is now at Dr Dobbs Journal web site.

Regards,

tgodd

dELTA
February 11th, 2003, 06:21
Thanks for the info Kayaker, I was actually hoping to get a reply from you. (and thanks for the tip tgodd too)

One very big question I have, which I'm hoping someone can shed some light upon:

How big is the difference between vxd:s and the new 2000/XP WDM? Is the same API:s used (e.g. VMM_Add_DDB), or is there a set of completely new ones? In what other areas does the main differences and similarities reside?

I have sortof decided to focus mainly on WDM driver programming to begin with, since vxd:s are something of a "dying technology", but practically all info I can find on the net about drivers is about vxd:s. Hence, I would very much like to know which areas of vxd programming that are useful for WDM programming to, and which ones that are exclusive too the old vxd:s only, so I can know which tuts and info that are "unnecessary" and which ones that are useful (yes, I know, no information is really "unnecessary", but since we are only given so much time in this life, some information must get priority, however sad this might be ).

Any tips, anyone?

Kayaker
February 11th, 2003, 12:49
I know what you mean, that feeling of working with a dying technology isn't very satisfying, lol. But since WDM drivers are supposed to have cross platform compatibility and run on Win98/Me as well as Win2000 and later, I would think that little of the earlier vxd documentation is completely 'useless'.

Unfortunately none of the DDK's are available for download anymore it seems, but it's probably worth the shipping costs to get the CD from Microsnort. The only place I've seen the complete latest version of the DDK is online at

http://www.osr.com/

Actually I was just reading it and there are a couple of interesting things not in the Win98DDK that maybe allude to what Tgodd mentioned.

--------------
Accessing Read-Only System Memory

The Microsoft Windows Memory Manager enforces read-only access of pages that are not marked as writable.

Read-only memory has always been protected in user mode. However, in Windows NT 4.0 and earlier versions, read-only memory was not protected in kernel mode.

If a Windows kernel-mode driver or application attempts to write to a read-only memory segment, the system issues a bug check. See Bug Check 0xBE (ATTEMPTED_WRITE_TO_READONLY_MEMORY) for full details.

Intercepting System Calls
Some drivers intercept system calls by overwriting the driver's own code and inserting jump instructions or other changes. Since the driver's own code is read-only, this technique will cause a bug check to be issued.
-------------

My question is, would a VMMCall _PageModifyPermissions be enough to avoid the dreaded 0xBE Bug Check in these cases?


There's also this, which I guess there's probably a workaround using some of the thread or context related services:

------------
Accessing User-Space Memory

Drivers cannot allocate user-space virtual memory because they run in kernel mode. In addition, a driver cannot access memory through user-mode virtual addresses unless it is running in the context of the user-mode thread that caused the driver's current I/O operation and it is using that thread's virtual addresses.
-------------

Kayaker

tgodd
February 11th, 2003, 15:00
The PageTable locations are hard coded into the OS.
Access the pagetable directly and manipulate the pages so that you may patch the contents, however, DO remember to set the page flags back to the way you found them to start with.

Regards,
tgodd

dELTA
February 11th, 2003, 15:57
Very interesting info, thanks guys!

One question though:
In my infinite ignorance, I do not know what a "bug check" is. Could anyone give a short explanation? Does it mean that it should be completely impossible for any driver (or other software) to patch the kernel, or is there any way past such a "bug check"?

Or does it mean that the only way to patch any part of the kernel would be to modify the physical files on disk (from non-Windows mode, to get by the file locks)? I'm almost certain I have read about drivers that runtime-patch kernel code (or other parts of the kernel) but this should hence only be possible in Windows NT 4 then (except for using the "undocumented" method that tgodd is talking about)?

I would too, just like Kayaker, very much like to know if these kernel pages are given special treatment with the VMMCall_PageModifyPermissions function? Does anyone know anything about this?

Kayaker
February 12th, 2003, 00:49
You could probably use either method, the Read/Write bit of the Page Table is usually changed directly because it's sneakier. But if you pass the flag PC_WRITEABLE (00020000h) to a call to _PageModifyPermissions you should also be able to write to any address in the page. Check out Elicz's Apithunk code for an example, the call emulates VirtualProtect with the PAGE_READWRITE flag.

If you can't thunk down from Ring3 to kernel code to make the vxd call (a la Peitrek Undocumented) in Win2K, then if you're doing this in a driver anyway you just call _PageModifyPermissions directly. You can set a breakpoint on _PageModifyPermissions in Softice (type VCALL _PageMod* in SI for the address) if you want to check it out, you can trace it any time there's a task switch on your system, such as opening a window or right clicking on your desktop (a task switch reloads the CR3 register among other things).

Start with the driver development first, worry about what you want to do with it later

Cheers,
Kayaker

dELTA
February 12th, 2003, 06:52
Thanks for the info again Kayaker!

And yes, I should probably try not to get too far ahead of myself, but I just can't help it, reality is too slow, and I have too little time.

nikolatesla20
February 12th, 2003, 18:01
Perhaps I am running into a page lock problem myself?

I tried to use a device driver to patch Kernel32.dll's "UnhandledExceptionFilter" on a global scale. I bug check as soon as I try it. If I could patch the "global" copy ... but I think SoftICE would just re-patch it anyway back into an INT3. I know you can patch SI to not do this anymore, but it leaves tons of ugly trace messages in your SI window, so I prefer not to do it that way. I tried to use my INT1 patch driver to also do the INT3, but alas, writing to kernel memory bug checks.

Patching the IDT table works fine however.

I'm using Win2000 with the memory protection turned off - just as a note, patching IDT works on every machine I've tried it on (Win2k/ XP) with or without system memory protection.

By the way Kayaker, bug check means BSOD.

-nt20

dELTA
February 12th, 2003, 18:18
Thanks for the info nikolatesla20,

When you say that it is possible to "patch the IDT table", is this the same thing that Kayaker refers to as "changing the Read/Write bit of the Page Table"?

Also, have you tried to use the "_PageModifyPermissions" function and it does not work with the kernel memory?

Also, exactly what is the difference between using and not using "memory protection" in Windows 2000/XP? Is all memory access checking disabled when not using this memory protection? I mean, at least in non-kernel code, so that I can e.g. write to the code section of a normal windows app in memory without changing the page permissions with VirtualProtectXXX?

And finally, I was the one who wanted to know what a bug check was, not Kayaker, I'm quite sure he already knows that. I still appreciate the info though.

Manko
February 12th, 2003, 18:27
Hi, nikolatesla20!

At the risk of sounding stupid...
What about icedump?
A while back someone discovered it left kernelspace writeenabled...
But I guess isolating the culprit in that source might be tedious...
And besides, I don't know the least bit about any of this, so for my ego's sake I shouldn't even open my mouth, as I'm probably WAAAAAAAAAAAAAAY off.

/Manko

nikolatesla20
February 12th, 2003, 19:58
By "Patching the IDT table" I mean I can directly write into the IDT table entries with abandon.

All I have to do is:

Code:

// IDT is 5 bytes.
char IDTAddress[]={0x00,0x00,0x00,0x00,0x00};

_asm{

sidt IDTAddress
mov eax, IDTAddress
add eax, 0x0D // got to INT1 entry.
mov [eax], 0x8E //Restore normal IDT vector IOPL.

}



I can write directly to it with a mov instruction. If you try this with a Kernel32 call, you will blue screen. At least I did. Every time.

Manko: About IceDUMP: I've never gotten it to work on 2K/XP, and it doesn't hide INT1.

About Write protection: As far as I know, this is mainly for kernel mode code. You still can never write to another process from Ring3 (unless you use WriteProcessMemory and VirtualProtect, etc). WriteProcessMemory actually runs in kernel mode, switches address context to the appropriate process, and mods the data.

From what I understand, you don't have to go thru any type of page table in kernel code. The processor does that for you when you try to write to an address, since paging is part of the processor. YOu only have to make sure you are in the right process context, which means the page tables are pointing to the process you want to modify. So for example, if you are in the correct context, you could write to 0x00400000 in your process and be fine. Unless of course that page is not in memory

Another thing: compared to VXD's , WDM and normal NT kernel drivers are actually "easier" (if a driver could ever be so). I just used the tools that came with D.S 2.7 (Driverworks wizard, etc) and made NT style driver.

One last thing for Kayaker:
You might already know this, but a driver is always running in context of user program when it's called with a DeviceIOControl. You can use this to your advantage. Basically, all addresses will be valid in that case. As long as you don't queue the driver message packets (IRP's), you run synchronous and will be in user program context. Of course that is obvious :P Also, you can force switch the context if you have the processID - there is a kernel mode api call that will do it..KeSwitchContext(), same call WriteProcessMemory uses.

-nt20