IDA Script: Fixing 16bit pushed data segment references

A good friend has started reversing an old 16bit Borland C++ (3.1?) program, and had lots of stack push data segment offsets that were not correctly cross referencing.

After telling him the shortcuts for manually fixing the issue (press O for the data segment, or Alt-R for any segment offset), he wrote an IDC script to do it en mass.

Thus (made up example code)

push ds;      
mov ax, 0x1234;      
push ax  

should look like:

push ds;  
mov ax, ds:dword_1234;  
push ax  

Here’s his script:

#include <idc.idc>  

static main()  
{  
  auto seg, loc;  
  auto movloc, movtarget;  
  auto xref;  
  auto dsegbase;  

  dsegbase = SegByName("dseg") * 16;  
  Message("dsegbase=%x\\n", dsegbase);  

  Message("========================================\\n");  
  seg = FirstSeg();  

  while(seg != BADADDR )  
  {  
    Message("----------------------------------------\\n");  

    loc = SegStart(seg);  

    if( Byte(loc) != 0xCD || Byte(loc+1) != 0x3F)  
    {  
      Message("Fixing indirect push [ds:xx] refs from %s\\n", SegName(seg));  

      while(loc != BADADDR && loc < SegEnd(seg))  
      {  
        if (GetMnem(loc) != "push" || GetOpnd(loc, 0) != "ds")  
        {  
          loc = NextHead(loc, BADADDR);  
          continue;  
        }  
        loc = NextHead(loc, BADADDR);  

        if (GetMnem(loc) != "mov" || GetOpType(loc, 1) != o_imm)  
        {  
          loc = NextHead(loc, BADADDR);  
          continue;  
        }  
      movloc = loc;  
      movtarget = GetOpnd(movloc, 0);  
      loc = NextHead(loc, BADADDR);  

      if (GetMnem(loc) != "push" || GetOpnd(loc, 0) != movtarget)  
      {  
        continue;  
      }  

      // At this point, we know we're pushing a [ds:x] combo.  
      //Message("%x: mov %s, %s\\n", movloc, movtarget, GetOpnd(movloc, 1));  

      // Abort if there already exists a Dxref  
      xref = Dfirst(movloc);  
      if (xref != BADADDR)  
      {  
        continue;  
      }  

      Message(" Updating %s:%04x\\n", SegName(seg), (movloc - seg) & 0xffff);  
      OpOff(movloc, 1, dsegbase);  
      }  
    }  

    seg = NextSeg(seg);  
  }  
}  
Share

Comments:

Karl 2012-03-14 02:21:21

I just ran into exactly the same problem and was well on my way to writing this very script. It saved me a lot of time. Thanks for posting it!