Run trace

    Run trace was first introduced in OllyDbg 1.04. This debugging technique is basically very simple. Code is executed step by step, and debugger protocols every command, together with registers and flags, in the large circular buffer. When exception occurs, one can backtrace several (or hundreds of thousands) last commands and analyse conditions that led to error.
    OllyDbg 1.06 has significantly improved the possibilities of run trace. Run trace shows modified registers and keeps important messages and operands of known functions. One can set conditions to pause run trace, profile traced code, write run trace to disk in order to overcome memory limitations or to compare two runs, debug self-modified programs, find ount when command at certain location was executed for the last time, and so on.

    Please keep in mind, however, that run trace is slow. On a 500-MHz processor, OllyDbg can trace up to 2500 (Windows 95) or 5000 (NT) commands per second. To accelerate run trace, one can mark quasi-linear pieces of code (without jumps to outside) that should be executed at once. And one more limitation: OllyDbg doesn't save the contents of accessed memory.

    To make you familiar with the run trace, let's try to debug a simple console application:

#include <stdio.h>
void f1(void) { printf("a"); };
void f2(void) { printf("b"); };
void f3(void) { printf("c"); };
void (*f[3])() = { f1,f2,f3 };
void main(void) {
  int i,j,k;
  for (i=0; i<100; i++) {
    for (j=0; j<1000000; j++) ;  // Long code
    if (k>3) continue;
    f[k]();                      // Here error (when i==99)!
    Functions f1, f2 and f3 print letters a, b and c. Main program calls each function 33 times, then prints newline and terminates... at least in theory. (You have already found the error, don't you? Well done, but here we learn how to come to the same result using run trace). Try to run rtrace.exe, and in a couple of seconds it crashes:

    Oh, no! Something is definitely wrong! As OllyDbg is your just-in-time debugger of choice, you press "Debug", but Disassembler window is empty! Address 00620061 points to nowhere, and you have not the faintest idea which command jumped to this location. Let's try from the very beginning. Press Ctrl+F2 (shortcut for Restart), then Ctrl+F11 (Trace into) and wait for a minute or two. Console is still empty. Maybe some part of the code takes too long to execute? Pause run trace by pressing F12 (Pause) or Esc. In the Executable modules, click on RTRACE and select "View run trace profile":

    A command or a sequence of commands at address 00401191 was executed more than 24000 times. Follow this line in Disassembler:

    A short 3-command cycle executes F4240 (decimal 1000000) times. At 5000 commands per second, OllyDbg will need 10 minutes to trace this cycle. Note that sequence is quasi-linear, i.e. has no jumps to outside. From the pop-up menu, choose "Run trace|Skip selection when tracing". Red line in the fourth column indicates that commands are excluded from run trace. When OllyDbg encounters excluded sequence, it sets temporary breakpoint at the command that immediately follows excluded block (in our case, 00401199) and runs it at once. Of course, any return or  jump to outside would make correct tracing impossible, so OllyDbg checks the piece of code you want to exclude and in hard cases asks you for confirmation.
    Continue run trace. The digits now appear quickly. Within 20 seconds, OllyDbg reports error:

    Confirm this error, open Run trace window (button with period '...' in the toolbar) and scroll it to the bottom:

    Now we can see that command that jumped to 00620061 was CALL EAX at 004011AF, and invalid address was calculated one command before the call. Doubleclick this line to see it in Disassembler. Registers and information are grayed to emphasize that they are not actual, but taken from the trace:

    Address constant 0040A128 points to array of 3 fixups containing addresses of functions f1, f2 and f3. When this command was executed for the last time, EAX contained index 3, outside the array's bounds. Two previous commands should perform bounds checking, but condition is invalid: jump is taken when EAX is greater than 3. Correct condition would be "greater or equal". Doubleclick invalid line and correct condition:

    After you assemble new command, line in Disassembler gets red, indicating that command is modified. Select it again and in the pop-up menu choose the powerful item "Copy to executable file". This applies your modification directly to the executable file:

    All you need is to save modified executable (under different name, of course) and check it. Now the program works correctly! It was easy, isn't it?..
    You can download this tutorial and sample program rtrace.exe here.