Jump to content
Tuts 4 You

hooking NtQueryInformationProcess


snoopy

Recommended Posts

Hey guys,

Small question, I've read the anti-debug reference from Peter Ferrie which goes into detail about tons of anti-debug tricks.

Now what I am facing is the following.

I am searching for a good way to hook NtQueryInformationProcess.

Atm:

;-------------------------------------------------------

;Original instruction 6 bytes long:

;ntdll!NtQueryInformationProcess:

;774efa78 b816000000 mov eax,16h

;774efa7d 33c9 xor ecx,ecx

;-------------------------------------------------------

NtQueryInformationProcessHook:

mov eax,16h

xor ecx,ecx

pushfd

cmp B[esp+0Ch],07h ;ProcesDebugPort 0x7

jne >CheckProcesDebugFlags

mov B[esp+0Ch],00h

CheckProcesDebugFlags:

cmp B[esp+0Ch], 1Fh ;check ProcesDebugFlags

jne >CheckProcessDebugObjectHandle

mov B[esp+0Ch],00h

CheckProcessDebugObjectHandle:

cmp B[esp+0Ch], 1Eh ;check ProcessDebugObjectHandle

jne >EndOfNtQuery

mov B[esp+0Ch],00h

EndOfNtQuery:

popfd

nop

nop

Basicly what it does is wipe the the value on the stack before the actual call to NtQueryInformationProcess is done.

The problem is when I code a small program which checks the process debug port it works fine.

But I also discovered on a lot of protectors, VMProtect etc.. it doesn't work right.

Most plugins are doing it different than I am doing, but since I don't have the source codes I am trying to discover why they

are doing it different, what part of hooking NtQueryInformationProcess am I missing.

Link to comment
Peter Ferrie

there are two things wrong here. one is that you're missing the check for the process ID - that what's being queried is what's being debugged. the other is that if you arbitrarily change the class, you might have the wrong buffer size and corrupt memory.

Link to comment

Peter, thanks for your reply. What happened when arbitarily changing the class the return value is 0xc0000004 --> STATUS_INFO_LENGTH_MISMATCH.

The that's what's being queried is what's being debugged makes sense. But the buffer and size isn't.

Would this mean, you let the call go, than check the buffer for the return value and change the returned value. Because when the call is made the pointer to the buffer and size of the buffer

are initialized before the call is made.

Link to comment
Peter Ferrie

okay, so the message that you're seeing is because the buffer size is wrong for the class that you supplied.

you should allow the original call to proceed, so that intentionally invalid parameters will get the expected failure (because it's a common detection method), but if the call succeeds, then you alter the results to hide your presence.

Link to comment
waliedassar

I see that you are replacing the "ProcessInformationClass" parameter (if it is ProcessDebugPort, ProcessDebugObjectHandle, or ProcessDebugFlags) with zero (ProcessBasicInformation). The problem is that you don't modify the rest of parameters according to the new Process information class which results into an error in the return value.

If you wanna keep the same code you have to use a well-chosen neutral "ProcessInformationClass" value. Below was taken from my "HookSysCalls" OllyDbg plugin (in Wow64).

00280000 83F8 0A CMP EAX,0A

00280003 75 1E JNZ CheckNtQueryInformationProcess

00280005 837C24 0C 11 CMP DWORD PTR SS:[ESP+C],11

0028000A 75 17 JNZ CheckNtQueryInformationProcess

0028000C C74424 0C 0F0000>MOV DWORD PTR SS:[ESP+C],0F

00280014 B8 19000000 MOV EAX,19

00280019 C74424 08 FFFFFF>MOV DWORD PTR SS:[ESP+8],-1

00280021 EB 5D JMP EmulationThunk

CheckNtQueryInformationProcess:

00280023 83F8 16 CMP EAX,16

00280026 75 58 JNZ EmulationThunk

00280028 837C24 0C 07 CMP DWORD PTR SS:[ESP+C],7

0028002D 74 49 JE ProcessDebugPort

0028002F 837C24 0C 1E CMP DWORD PTR SS:[ESP+C],1E

00280034 74 09 JE ProcessDebugObjectHandle

00280036 837C24 0C 1F CMP DWORD PTR SS:[ESP+C],1F

0028003B 74 1C JE ProcessDebugFlags

0028003D EB 41 JMP EmulationThunk

ProcessDebugObjectHandle:

0028003F 50 PUSH EAX

00280040 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14]

00280044 85C0 TEST EAX,EAX

00280046 74 06 JE SHORT 0028004E

00280048 C700 00000000 MOV DWORD PTR DS:[EAX],0

0028004E C74424 18 000000>MOV DWORD PTR SS:[ESP+18],0

00280056 58 POP EAX

00280057 EB 1F JMP ProcessDebugPort

ProcessDebugFlags:

00280059 50 PUSH EAX

0028005A 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14]

0028005E 85C0 TEST EAX,EAX

00280060 74 06 JE SHORT 00280068

00280062 C700 01000000 MOV DWORD PTR DS:[EAX],1

00280068 58 POP EAX

00280069 B8 19000000 MOV EAX,19

0028006E C74424 0C 0F0000>MOV DWORD PTR SS:[ESP+C],0F

00280076 EB 08 JMP EmulationThunk

ProcessDebugPort:

00280078 C74424 0C 160000>MOV DWORD PTR SS:[ESP+C],16

EmulationThunk:

00280080 EA 1E27AD74 3300 JMP FAR 0033:74AD271E ; Far jump

You can find the plugin here.
/>http://code.google.com/p/myollyplugins/downloads/detail?name=HookSysCalls.dll

Its source code can also be found here.
/>http://code.google.com/p/myollyplugins/downloads/detail?name=HookSysCalls.rar

N.B. The ZwQueryInformationProcess/ZwSetInformationThread tricks are typically used this way.
/>http://pastebin.com/sArnNGBN
/>http://code.google.com/p/ollytlscatch/downloads/detail?name=HookMe.exe

Link to comment
Peter Ferrie

but you still fail to deal with intentionally invalid parameters:

00280048 C700 00000000 MOV DWORD PTR DS:[EAX],0

has an issue with non-writable memory.

You also lack the verification of the PID (or it's not visible in the code, anyway).

Sometimes, a debugger is present for proper reasons, and so the query should succeed without interference.

It's simply easier and safer to allow the OS to perform the original call and modify the returned information if it succeeds.

Link to comment

@ waliedassar

Short question about your plugin HookSysCalls 0.1.So could you maybe add a enable / disable menu + plugin into Olly ini info?

- Auto Patch

- Patch

Like this I mean.Auto Patch press = On for ever and another press = Off again for ever.Patch = One time session patch.Something like this you know.On this way it would patch it automaticly after loading a target in Olly without to choose it each time manually.Would be nice if you could add this little feature too maybe. :)


[Plugin HookSysCalls]
AutoPatch=0[Plugin HookSysCalls]
AutoPatch=1

Thank you

Link to comment
  • 2 weeks later...

Thanks for all the information guys. Sorry for my late reply, been out for a vacation period.

I've succesfully changed my code according to what Peter suggested. It seems to work really well and the code is rather short.

Changing the return value / values in the buffer works nicely.

The plugin I am working on is designed for WinDBG. I will release my source when I get some gui in.

There is one odd behaviour I came across when patching the BeingDebuggedFlag using: eb $peb+0x2 00.

The problem that occurs is that WinDBG after the patching has problems breaking back into the code. Sometimes it takes up to 30 seconds before

it breaks back into the process. I am on Windows 7 Proffesional 64 bit does it has anything to do with that?

Link to comment

some Windows APIs rely on the value in that location in order to recognise the debugger and then do debugger-specific things.

however, you might have a better experience with a different debugger.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...