REBlog
October 19th, 2007, 20:27
I do most of my malware analysis statically, which is to say that I typically analyze malware by looking at a static disassembly of it as opposed to stepping through it in a debugger. However, sometimes I come across complicated or confusing code that would be easier to understand by walking through it in a debugger.
I came across such an example the other day. An important branch decision was being made based on the result of a function that used a stack variable that IDA Pro couldn't represent in a simple way. Here's a snippet from the function:
There was a problem, though. This malware launced other instances of itself, and setting a breakpoint on the code above in a debugger didn't work since the parent process never executed that code, only the child instances did. I could have set a breakpoint on CreateProcessA(...), forced it to load the child processes in a suspended state, attached a debugger to the children, then resumed them, but this was more trouble than it was worth. Instead, I opted for another method of attack.
I configured my debugger for Just-In-Time (JIT) debugging (see http://support.microsoft.com/default.aspx?scid=kb;en-us;103861) so that I could attach to a crashed process via the Microsoft Application Error Reporting dialog box (also known as "Dr. Watson" -- see http://blogs.msdn.com/oldnewthing/archive/2005/08/10/449866.aspx). I then overwrote the code above with an int 3 and patched the file, with the expectation that after running the parent program that this would crash the child process, cause the Microsoft Application Error Reporting dialog box to pop up, and allow me to attach to the crashed child process. (It should be noted that this was done on an isolated network in a very controlled environment, and with all of our safeguards in place it was practically impossible for the modified malware to get out of our secure lab.)
I saved the patched file and ran it, waiting eagerly for the Microsoft Application Error Reporting dialog box to appear. To my surprise, nothing happened. As it turned out, the program was using custom Structured Exception Handling (SEH) routines and because of this the int 3 exception was never passed to the operating system so the Microsoft Application Error Reporting dialog box never popped up. To remediate this, I changed my int 3 patch to the following:
With this patch in place, the Microsoft Application Error Reporting dialog box popped up for the child process and I was able to attach my debugger and determine the value of arg_0 + 108h from the original code above.
http://malwareanalysis.com/CommunityServer/blogs/geffner/archive/2006/05/07/12.aspx
I came across such an example the other day. An important branch decision was being made based on the result of a function that used a stack variable that IDA Pro couldn't represent in a simple way. Here's a snippet from the function:
mov edx, [ebp+arg_0]I could have traced back in the disassembly to figure out what arg_0 + 108h was really pointing to (it turned out to be a global variable and arg_0 was set by the caller of the caller of this function), but I thought that I could save time by loading the target into a debugger and setting a breakpoint on the code above in order to determine what was actually being pushed.
add edx, 108h
push edx
There was a problem, though. This malware launced other instances of itself, and setting a breakpoint on the code above in a debugger didn't work since the parent process never executed that code, only the child instances did. I could have set a breakpoint on CreateProcessA(...), forced it to load the child processes in a suspended state, attached a debugger to the children, then resumed them, but this was more trouble than it was worth. Instead, I opted for another method of attack.
I configured my debugger for Just-In-Time (JIT) debugging (see http://support.microsoft.com/default.aspx?scid=kb;en-us;103861) so that I could attach to a crashed process via the Microsoft Application Error Reporting dialog box (also known as "Dr. Watson" -- see http://blogs.msdn.com/oldnewthing/archive/2005/08/10/449866.aspx). I then overwrote the code above with an int 3 and patched the file, with the expectation that after running the parent program that this would crash the child process, cause the Microsoft Application Error Reporting dialog box to pop up, and allow me to attach to the crashed child process. (It should be noted that this was done on an isolated network in a very controlled environment, and with all of our safeguards in place it was practically impossible for the modified malware to get out of our secure lab.)
I saved the patched file and ran it, waiting eagerly for the Microsoft Application Error Reporting dialog box to appear. To my surprise, nothing happened. As it turned out, the program was using custom Structured Exception Handling (SEH) routines and because of this the int 3 exception was never passed to the operating system so the Microsoft Application Error Reporting dialog box never popped up. To remediate this, I changed my int 3 patch to the following:
mov eax, fs:[0]This effectively overwrote the first exception handler in the SEH chain (see http://www.microsoft.com/msj/0197/exception/exception.aspx) with the default exception handler from kernel32.dll. The address of this handler is of course version-specific; in my case kernel32.dll was US English version 5.1.2600.2180.
mov [eax+4], 7c8399f3h
int 3
With this patch in place, the Microsoft Application Error Reporting dialog box popped up for the child process and I was able to attach my debugger and determine the value of arg_0 + 108h from the original code above.
http://malwareanalysis.com/CommunityServer/blogs/geffner/archive/2006/05/07/12.aspx