6

I'm currently working on a tool to automate several actions which relate to unpacking software. I would like to use the run trace of Ollydbg (1.10 preferred since it has many antidebug/usage/etc plugins). However, I do not seem to know any library which offers parsing Ollydbg run trace.

Does anyone know of any library which can do that or any project which has already done it?

  • 1
    The run trace log file is a simple text file with fixed-width (or tab-delimited, based on options) fields. Why do you need a special library to parse that? – Jason Geffner Jul 4 '13 at 22:57
  • @JasonGeffner: on the contrary why reinvent the wheel when someone could have done it already? :) +1 – 0xC0000022L Jul 5 '13 at 0:51
  • 1
    @0xC0000022L: My point was that nobody has created a library for parsing an OllyDbg Run Trace string because parsing that string is already trivial. Why create a library when you can already parse the string with a single line of code? – Jason Geffner Jul 5 '13 at 14:05
  • @JasonGeffner Totally agree +1 – PSS Jul 6 '13 at 3:06
  • @JasonGeffner: even simple formats can be intricate to parse so the question isn't at all unwarranted. Reuse is usually encouraged everywhere, so discourage it here selectively? – 0xC0000022L Jul 10 '13 at 0:51
3

I have found that parsing the run trace is not as trivial as one would wish (and as I assumed too, like the people who commented your question). There are a few reasons for this:

  1. Fields are separated by a variable number of spaces. If one of the fields is too long, a single semicolon is used as a separator instead. However a variable number of spaces is not guaranteed to be a field separator.

  2. One of the first fields is the address of the executed instruction. Instead of a hex address, this can also be a (possibly demangled C++) symbol. The lines can include beasts like

    main  std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >::~basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >;push 0;0018EB38=0;ESP=0018EB38
    

    Of course, demangled names can occur in the assembler instruction too as well, not only in the address field. Also, I believe that ABCDEF0 would be both a valid hex address and a valid symbol name, and they cannot be told apart since the trace only reports either the demangled name or the hex address.

  3. When the data pointed to as indicated in the comments field of the trace contains ASCII or unicode data according to OllyDbg's heuristics, the contained string is displayed. At least newlines inside the strings are not escaped, so you have to deal with split lines.

  4. Relevant at least if you would like to extract a call trace: It is not in general trivial do determine without referring to surrounding instructions whether a call was traced into (the normal case) or traced over (in case of Windows DLL calls). You can use heuristics like whether the "call instruction" is shown to modify other registers beyond ESP. By tracking ESP, it should be possible to determine this.

  5. The precise format of the dump trace apparently depends heavily on the options, including things like whether the assembly mnemonic is separated from the operands by spaces or a tab, and whether the assembly displayed is all caps or in lower case.

Everything above pertains to OllyDbg 2.01; I suspect there are bound to be differences between different versions (and I for one would not mind if the format was made more parseable in future versions).

Having said all that, I have written some (Haskell) code to parse the output that works for me right now with my particular options and the particular application dumped. Here's a PERL-compatible regular expression (won't work as is in a POSIX regex context) I use to match lines:

^main  ([0-9A-F]{8}|(?:unsigned |operator |vbase destructor|[^ ;]| >)+)(?: +|;)((?:[^=; ]|operator.{0,2}=| (?! ))+)(?:(?: +|;)([^ ]+=.*))?$

The 1st capturing group is the address/symbolic name, the 2nd group is the assembly instruction, and the 3rd group is the "comment" portion of the line containing memory contents and register changes.

I think I will proceed to make my Haskell program into a filter which parses run traces and outputs them in a more readily machine-parseable format (maybe CSV or something); I can share the code if someone is interested. (Sorry about using Haskell; I just need performance that scripted languages don't give. The size of my dump is 2 gigabytes, and my Haskell parser consumes it at roughly 50 Mb/s.)

2

ollydbg runtrace has a profiling option inbuilt it can profile the runtrace either module wise or globally

go to run trace window (...)icon right click and select profile module or global profile

a simple messagebox.exe (iczelions tutorial 2) will execute 1087946 instructions from system breakpoint to original entry point skipping string commands repmovsb ... movsd in xpsp3

Run trace, selected line
 Back=1087946. 
 Thread=Main
 Module=ntdll
 Address=7C90120F
 Command=RETN
 Modified registers=ESP=0013FB24

and call _LdrSnapThunk about 1000 times

Profile of whole memory, item 30
 Count=1012.
 Address=7C917BF1 LdrpSnapThunk
 First command=MOV     EDI, EDI

will call zwCreateFile 4 times

Profile of whole memory, item 1046
 Count=4.
 Address=7C90D0AE ZwCreateFile
 First command=MOV     EAX, 25

from this global profile you can hop back to disassembly window or run trace window mark this position in run trace window and jump to next marked position

the details of 4 ZwCreateFile from global profile to runtrace window correlated below

Run trace, selected line
 Back=978309. <-------------------
 Thread=Main
 Module=ntdll
 Address=7C90D0AE ZwCreateFile
 Command=MOV     EAX, 25
 Modified registers=EAX=00000025

Run trace, selected line
 Back=975485. <----------------------
 Thread=Main
 Module=ntdll
 Address=7C90D0AE ZwCreateFile
 Command=MOV     EAX, 25
 Modified registers=EAX=00000025


Run trace, selected line
 Back=956331. <-----------------------
 Thread=Main
 Module=ntdll
 Address=7C90D0AE ZwCreateFile
 Command=MOV     EAX, 25
 Modified registers=EAX=00000025


Run trace, selected line
 Back=874497. <----------------------
 Thread=Main
 Module=ntdll
 Address=7C90D0AE ZwCreateFile
 Command=MOV     EAX, 25
 Modified registers=EAX=00000025

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.