The last described method does not work if the application uses an “unsupported” antidebugging trick. For example, if the application directly checks the PEB field instead of calling the IsDebuggerPresent function, the method will fail. Or the application could use something else, something from the future…
I will show you the “ultimate stealth method” which will work against the future antidebugging tricks too. We will unpack an application and create a database with clean unpacked code. This time we will use as a sample packer, say, telock but the packer does not really matter. Here is our original sample file and here is the packed file.
The application tries to detect the debugger and the debugger tries to hide itself. Now we will play the game differently: instead of hiding the debugger, we will completely remove it! The application refuses to run with debugger? Fine, let it run without! After all, we are interested in the unpacked code, not the in unpacker code.
Se we need to suspend the application when it unpacks itself. If we let the application run without any modifications, it will not suspend. We will modify it to suspend itself.
The idea: we will patch a Windows API function to suspend our application. As soon as the unpacked code calls it, the application will be suspended. For our sample program we know that the CreateWindowExA function is called. It looks like this:
We patch it to call the SuspendThread function instead of creating a window:
The next step is to let the application run without the debugger. We use the Debugger, Detach from process. The unpacker will do its job and the application will suspend itself before creating any windows, so nothing will happen on the screen. But if we check the task list, we will see our application (Debugger, Attach to process):
The application has been unpacked and is ready to be analyzed! Open the program segmentation, find the application name (sample_telocked.exe in our case) and you will see clean code.
In short, the ultimate stealth method consists of the following sequence:
Patch system dlls – Detach – Attach
What to do if we do not know what Window API functions are used by the application? We could try to patch as many functions as we want. We should not patch functions used by the unpacker since it will prevent the unpacker from doing its job. If we are really out of ideas, even ExitProcess or similar function can be patched. The application will be suspended at the exit time but we will have an opportunity to see the original import table which will give us the list of API functions to consider.
We could also patch API functions in other ways. Instead of calling SuspendThread we could write 0xCC, or invalid opcodes, or even zeroes. The application would crash and we could attach to it with IDA (turn on Debugger, Debugger options, Set as just-in-time debugger before using this method).