How to patch a Windows API in x64dbg

How to patch a Windows API in x64dbg

Some months ago, I analyzed a banking Trojan that employed a chain of injections. First, it hollowed an instance of svchost.exe. From there, it injected its code into several processes (especially browsers). My goal was to analyze the network protocol. Unfortunately, all processes could communicate with the CC and there was a mutual exclusion scheme that ensured only one network communicator at a time. This resulted in my process never contacting the CC and in me not seeing the network protocol.

My quick hack was to prevent others instances to communicate via the network by preventing further code injections. The malware at hand utilized ZwOpenProcess during its code injections. The solution: patch a Windows API in x64dbg to always return zero yielded no more injections. And finally, I was able to tamper with the network protocol.

Most of the time I utilize x64dbg, an open source debugger. Since a couple of months python bindings exist. They work fine, though there is no documentation. The following gist does the trick: patching ZwOpenProcess to always return zero. This should yield no more code injections in many malware families. Furthmore, you can use it as a blue print for patching other APIs in x64dbg.

from x64dbgpy.pluginsdk import *       
                         
def patchZwOpenProcess():       
    # This function patches the function ZwOpenProcess in such way that the XXX fails to open and infect more processes       
    # The good thing about that is that there won't be any concurrency issues and you can be sure that the networking       
    # will be done in the current process.       
                
    # patches mov eax, 0; jmp TO_RETURN (should be +3)       
    PATCH = "\xB8" + "\x00" * 4 + "\xEB\x03" + "\x90" * 3       
    addrZwOpenProcess = RemoteGetProcAddress('ntdll', 'ZwOpenProcess')       
    memory.Write(addrZwOpenProcess, PATCH)       
                
def main():       
    patchZwOpenProcess()       
                
main()

The gist just assembles some shellcode (mov eax, 0; jmp TO_RETURN) to force the API to return zero, resolves the target API with RemoteGetProcAddress and overwrites the original code of the api with memory.Write. As I said, there is no documentation of x64dbgpy. You can refer to this folder of x64dbgpy’s repo.

Share: Twitter Facebook
Thomas Barabosch's Picture

About Thomas Barabosch

Thomas holds a PhD in computer science. He is passionately engaged in malware analysis, threat actor tracking, and bug hunting. Throughout the last years he has found numerous vulnerabilities in low-level software and participated in several botnet take-downs. In his blogs he tells techies and non-techies stories about his adventures in binary code wonderland.

Germany https://0xc0decafe.com/