Since OllyDbg plug-ins are compiled into DLLs, creating or modifying a plug-in tends to be an involved process. Therefore, when extending functionality, we employ ImmDbg, which employs Python scripts and has an easy-to-use API.
ImmDbg’s Python API includes many utilities and functions. For example, you can integrate your scripts into the debugger as native code in order to create custom tables, graphs, and interfaces of all sorts. Popular reasons to write scripts for malware analysis include anti-debugger patching, inline function hooking, and function parameter logging—many of which can be found on the Internet.
The most common type of Python script written for ImmDbg is known as a
PyCommand. This is a Python script located in the
PyCommands directory in the install location of ImmDbg. After you write a
script, you must copy it to this directory to be able to run it. These Python commands can be
executed from the command bar with a preceding !
. For a list of
available PyCommands, enter !list
at the command line.
PyCommands have the following structure:
A number of import statements can be used to import Python modules (as in any Python script).
The functionality of ImmDbg itself is accessed through the immlib
or immutils
module.
A main
function reads the command-line arguments (passed in
as a Python list).
Code implements the actions of the PyCommand.
A return
contains a string. Once the script finishes
execution, the main debugger status bar will be updated with this string.
The code in Example 9-3 shows a simple script implemented as a PyCommand. This script can be used to prevent malware from deleting a file from the system.
Example 9-3. PyCommand script to neuter DeleteFile
import immlib def Patch_DeleteFileA(imm): ❷ delfileAddress = imm.getAddress("kernel32.DeleteFileA") if (delfileAddress <= 0): imm.log("No DeleteFile to patch") return imm.log("Patching DeleteFileA") patch = imm.assemble("XOR EAX, EAX Ret 4") ❸ imm.writeMemory(delfileAddress, patch) def main(args): ❶ imm = immlib.Debugger() Patch_DeleteFileA(imm) return "DeleteFileA is patched..."
Malware often calls DeleteFile
to remove files from
the system before you can copy them to another location. If you run this script via !
scriptname
, it
will patch the DeleteFileA
function, rendering it useless. The
main
method defined at ❶ calls Patch_DeleteFileA
. This is a function we have
defined at ❷ that returns the address of DeleteFileA
by calling the ImmDbg API function getAddress
. Once we have that location, we can overwrite the function with our own code.
In this case, we overwrite it with the patch code at ❸.
This code sets EAX to 0 and returns from the DeleteFileA
call.
This patch will cause DeleteFile
to always fail, thus preventing
the malware from being able to remove files from the system.
For additional information about writing Python scripts, use the Python command scripts that ImmDbg has built for reference. For further in-depth commentary on writing Python scripts for ImmDbg, see Gray Hat Python by Justin Seitz (No Starch Press, 2009).