I would like to comment, that since this version of the protection you created, copies the index of ZwQueryInformationProcess to the SSDT directly from the ntdll.dll file itself, and does not rely on hard coded values, then this is a great improvement over vmprotect's own version which can be easily fooled by changing the windows OS build number to an unsupported random number.. I guess that randomly locating the newly created syscall function in a none fixed memory area is implemented to prevent static patching. Great work.

Share this post

Link to post

mrexodia 1,445

mrexodia
1,445

Very insightful, thanks a lot! I created issues on ScyllaHide and TitanHide and fixed the implementations of NtQuerySystemInformation and NtQueryInformationProcess, but I don't really know how to handle this for NtQueryObject... Should I just read the size from ReturnLength before overwriting the other buffers and then restore it afterwards or should I do something else? The research kernel has pretty weird handling for invalid ReturnLength addresses so I'm not entirely sure. How did you handle this in your driver?

//
// To get to this point we must have had an object and the
// information class is not defined, so we should dereference the
// object and return to our user the bad status
//

ObDereferenceObject( Object );

return( STATUS_INVALID_INFO_CLASS );
}

//
// Now if the caller asked for a return length we'll set it from
// our local copy
//

try {

if (ARGUMENT_PRESENT( ReturnLength ) ) {

*ReturnLength = TempReturnLength;
}

} except( EXCEPTION_EXECUTE_HANDLER ) {

//
// Fall through, since we cannot undo what we have done.
//
}

ObQueryTypeInfo actually writes to TempReturnLength before doing anything else, but TempReturnLength is a KM-only variable until it is copied back to the caller at the end, so the final order of writes to user mode is the same.

Share this post

Link to post

0

Xjun 115

Xjun
115

Very insightful, thanks a lot! I created issues on ScyllaHide and TitanHide and fixed the implementations of NtQuerySystemInformation and NtQueryInformationProcess, but I don't really know how to handle this for NtQueryObject... Should I just read the size from ReturnLength before overwriting the other buffers and then restore it afterwards or should I do something else? The research kernel has pretty weird handling for invalid ReturnLength addresses so I'm not entirely sure. How did you handle this in your driver?

Also, is this actually used in VMProtect or is this your POC?

This is what I learned from VMP!

In my humble opinion .When you call the original function, you should first save the returnLenght and check whether it is empty. After processing ProcessDebugObjectHandle, restore the returnLenght. The rest is the same.