Executing Shellcode with ReadDirectoryChanges’s Hidden Callback

While digging into the ReadDirectoryChanges API, I noticed it supports an asynchronous callback via LPOVERLAPPED_COMPLETION_ROUTINE. Most people use this API to monitor file system changes, but what if we could hijack that callback to execute shellcode? This led me to develop a proof-of-concept (PoC) that turns a mundane filesystem monitoring function into a stealthy shellcode execution vector.

The API is documented as follows by Microsoft.

In this PoC, the shellcode is embedded in the executable’s .text section and passed as the lpCompletionRoutine argument to ReadDirectoryChanges. When a file system event like creating/deleting/renaming a file in a given directory completes the asynchronous I/O operation, the Windows kernel queues a user-mode Asynchronous Procedure Call (APC) to the issuing thread. Since the main thread enters an alertable state via SleepEx(100, TRUE), the kernel delivers the APC, which invokes the shellcode as the I/O completion routine. This executes the shellcode directly in the context of the program’s main thread.

https://github.com/OsandaMalith/ReadDirectoryChanges/blob/main/ReadDirectoryChanges.c

Leave a Reply