5

Can anyone tell me how to clean up the code which contains the following blocks:

call $+5
pop reg
add reg, 08BE96h
[...]

In other words I need to change all such blocks to:

mov reg, offset

Edit # 1

List all block EA's:

ea = ScreenEA()
for funcea in Functions(SegStart(ea), SegEnd(ea)):
    E = list(FuncItems(funcea))
    for e in E:
        if idc.GetMnem(e) == "call" and idc.GetOpnd(e, 0) == "$+5" and idc.GetMnem(e + 5) == "pop":
            print "%x" % e
  • Are you asking for a full idc/idapython script? – DCoder May 22 '13 at 10:39
  • Well, if such script exists... – Ilya Matveychikov May 22 '13 at 11:05
  • It is definitely possible to patch IDA database content through IDC (PatchByte). If nobody else replies, I will try to come up with my own version later. – DCoder May 22 '13 at 13:38
9

Here's a rough implementation that scans the currently focused function for this pattern:

call $+5
pop <reg>
op <reg>, imm32

And changes it to

mov <reg>, <computed imm32>
nop
nop

Adapting it to scan different ranges and support more instructions is left as an exercise to the reader.

def simplify(tgtEA):
  ins1 = tgtEA
  if not idc.isHead(idc.GetFlags(ins1)):
    ins1 = idaapi.prev_head(ins1, limits.startEA)

  ins2 = idaapi.next_head(ins1, limits.endEA)
  if ins2 == 0xFFFFFFFF:
    return False

  ins3 = idaapi.next_head(ins2, limits.endEA)
  if ins3 == 0xFFFFFFFF:
    return False

  print "Scanning instructions at %d, %d, %d" % (ins1, ins2, ins3)

  result = ins2
  matched = False
  reg = 0

  if idc.GetMnem(ins1) == "call":
    if idc.GetOpnd(ins1, 0) == "$+5":
      if idc.GetMnem(ins2) == "pop":
        if idc.GetOpType(ins3, 0) == 1:
          reg = GetOperandValue(ins2, 0)
          if idc.GetOperandValue(ins3, 0) == reg:
            op = idc.GetMnem(ins3)
            optype = idc.GetOpType(ins3, 1)

            if op == "inc":
              matched = True
              result = result + 1
            elif op == "dec":
              matched = True
              result = result - 1
            elif op == "add":
              if optype == 5:
                # optype 5 = immediate
                matched = True
                offset = idc.GetOperandValue(ins3, 1)
                result = result + offset

  if matched:
    # patch the bytes by hand - there's no nice API to assemble("foo bar")?
    # MOV r32, imm32 = 0xB8 /rd 
    # reg is the register number acquired from IDA operand value
    # IDA uses the same register numbering as Intel
    regbyte = 0xB8 + reg;
    idaapi.patch_byte(ins1, regbyte)
    idaapi.patch_long(ins1 + 1, result)
    idaapi.patch_word(ins1 + 5, 0x9090) # NOP NOP 
    return True

  return False

# ----

curEA = ScreenEA()
tgtEA = idaapi.askaddr(curEA, "Enter target address")
#tgtEA = curEA
if tgtEA is None:
  exit

f = idaapi.get_func(tgtEA)
if not f:
  print "No function at 0x%x" % (tgtEA)
  exit

limits = idaapi.area_t()
if not idaapi.get_func_limits(f, limits):
  print "No limits in this function?!"
  exit

print "Scanning function from %x to %x" % (limits.startEA, limits.endEA)

itEA = limits.startEA
while itEA < limits.endEA:
  if simplify(itEA):
    itEA = idaapi.next_head(itEA + 7, limits.endEA)
  else:
    itEA = idaapi.next_head(itEA, limits.endEA)
| improve this answer | |
  • Thanks, but I found that your script needs to be corrected as it breaks the code in my case. I'll post the result in a few days. – Ilya Matveychikov May 23 '13 at 19:32
3

call $+5 is 5 byte (e8 00000000) pop reg is 1 byte add reg will be 3 and more bytes

if you require call $+5 to become mov reg , const

you first need to compute the return address + the value of constant

in your case the address of pop reg + 0xbe96

and then use a 5 byte mov REG, computed value

that leaves 4 + bytes which you need to nop out so that the execution path remains the same if you did not nop the bytes then the left out garbage bytes can alter the execution path

| improve this answer | |

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.