NtQueryObject is another example of a known and underestimated anti-debug measurement. Most anti-debug articles describe (here or here) that we must call NtQueryObject with the class ObjectAllTypesInformation (Index number 3, but the correct name is ObjectTypesInformation). This class will return a list with all existing object types. But it is much better to call this function with class index number 2 ObjectTypeInformation. ObjectTypeInformation will only return the type information of the supplied handle. So how to get a debug handle? We simply create our own debug handle. This technique is very powerful to detect any debugger and no anti-anti-debug tool/plugin is currently able to defeat this.
We simply create the debug handle with the NtCreateDebugObject API:
NTSYSCALLAPI NTSTATUS NTAPI NtCreateDebugObject ( OUT PHANDLE DebugObjectHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG Flags );
The call is very simple and it could look like this:
HANDLE debugObject; OBJECT_ATTRIBUTES oa; InitializeObjectAttributes(&oa,0,0,0,0); if (NtCreateDebugObject(&debugObject, DEBUG_ALL_ACCESS, &oa, 0) >= 0)
Now we have our own debug handle + object. Let’s query this handle with NtQueryObject:
POBJECT_TYPE_INFORMATION objectType = (POBJECT_TYPE_INFORMATION)memory; if (NtQueryObject(debugObject, ObjectTypeInformation, objectType, sizeof(memory), 0) >= 0) { if (objectType->TotalNumberOfObjects == 1) //there must be 1 object... { ShowMessageBox("Everything is ok!"); } else if (objectType->TotalNumberOfObjects == 0) //bad { ShowMessageBox("Anti-Anti-Debug Tool detected!"); } else { ShowMessageBox("Debugger detected!\r\n\r\nTotalNumberOfHandles %d\r\nTotalNumberOfObjects %d\r\n", objectType->TotalNumberOfHandles, objectType->TotalNumberOfObjects); } }
If successful there are three possibilities. We know exactly that there must be 1 handle/object. If there are more objects, a debugger is present. It is also possible to detect anti-anti-debug tools because they probably return zero, but we know that this cannot be true!
Source code and x86/x64 binaries here:
https://bitbucket.org/NtQuery/teststuff/downloads/NtQueryObject.rar
https://bitbucket.org/NtQuery/teststuff/src/eb4adfbe5ccedd3e938b38434ae99ee42992994d/NtQueryObject.cpp?at=master
Here the source code: http://pastebin.com/q0TtF8Pf
It made it easier for me to run 😉
Thx for your example! 😀
oeps,… i posted the comment on the wrong site XD epic fail :$
What stops the debugger from making sure the call always returns a count of 1?