A lesser-known feature of the Windows memory manager is that it can maintain write watches on allocations for debugging and profiling purposes. Passing the
MEM_WRITE_WATCH flag to VirtualAlloc “causes the system to track pages that are written to in the allocated region”. The GetWriteWatch and ResetWriteWatch APIs can be used to manage the watch counter. This can be (ab)used to catch out debuggers and hooks that modify memory outside the expected pattern.
There are four primary ways to exploit this feature.
The first is a simple buffer manipulation check. Allocate a buffer with write watching enabled, write to it once, get the write count, and see if it’s greater than 1.
The second is an API buffer manipulation check. Allocate a buffer with write watching enabled, pass it as a parameter to an API that expects a buffer, but pass invalid values to other parameters. If an API hook doesn’t check parameters properly, or manipulates parameters, it may write to the buffer. Check the number of writes to the buffer after the call, and if it’s nonzero then there’s a hook in place. Any API will do as long as it writes to some memory. A particularly good trick is to use an API where there’s some kind of count value passed as a reference – in the real API the value will likely not be set, thus producing no memory writes, but in a hook there’s a bigger likelihood that they’ll set some placeholder value regardless.
Third, we can use the buffer to store the result of some check we care about, e.g. IsDebuggerPresent. If the write count is one and the value in the buffer is
FALSE then we can assume that there’s no debugger attached and nobody tampered with the result of the call (or skipped the call).
Finally, we can allocate some memory with RWX protection and write watching enabled, copy some anti-debug check there, call ResetWriteWatch to ensure the write counter is zeroed, execute our payload, then check the write count.
Obviously in all cases these checks themselves can be skipped over, but it’s not a well known trick and may be missed by novice reverse engineers.
I’ve contributed these tricks to al-khaser, a tool for testing VMs, debuggers, sandboxes, AV, etc. against many malware-like defences.