3

I have the following IDA Python script. It is intended to break on first instruction of imported function when call comes from the module of interest:

list = []

def set_cb(ea, name, ord):
    global list
    actual_ea = Dword(ea)
    AddBpt(actual_ea)
    list.append(actual_ea)
        return True

def set_breakpoints():
    global list
    del list[:]
    nimps = idaapi.get_import_module_qty()
    for i in xrange(0, nimps):
        idaapi.enum_import_names(i, set_cb)

def rem_cb(ea, name, ord):
    actual_ea = Dword(ea)
    DelBpt(actual_ea)
        return True

def rem_breakpoints():
    global list
    del list[:]
    nimps = idaapi.get_import_module_qty()
    for i in xrange(0, nimps):
        idaapi.enum_import_names(i, rem_cb)

def step_cb():
    global list
    minea = MinEA()
    maxea = MaxEA()
    while GetDebuggerEvent(WFNE_SUSP | WFNE_CONT, -1) > 0:
        r_eip = GetRegValue("EIP")
        if r_eip in list:
            r_esp = GetRegValue("ESP")
            caller = Dword(r_esp)
            if (caller >= minea) and (caller < maxea):
                break
        else:
            break

idaapi.add_hotkey("F3", set_breakpoints)
idaapi.add_hotkey("F5", rem_breakpoints)
idaapi.add_hotkey("F10", step_cb)

I debug dll and I need to break only on win api calls that are made directly from this dll, not from C runtime library. However MinEA and MaxEA functions return minimum and maximum addresses used in entire program. What I need is something like this:

ea = GetModuleByName("some.dll")
minea = ModuleStart(ea)
maxea = ModuleEnd(ea)

Do you know such api? Thanks.

1

There's no GetModuleByName in IDA, instead, using the EIP register value (which you already fetch) you could use SegStart and SegEnd.

Your code should look something like:

def step_cb():
    global list
    while GetDebuggerEvent(WFNE_SUSP | WFNE_CONT, -1) > 0:
        r_eip = GetRegValue("EIP")
        if r_eip in list:
            r_esp = GetRegValue("ESP")
            caller = Dword(r_esp)
            if (caller >= SegStart(r_eip)) and (caller < SegEnd(r_eip)):
                break
        else:
            break
| improve this answer | |
0

The final version of script in case someone else needs it. What you need to do:

1) set breakpoint and wait until debugger hits it
2) load script (file -> script file)
3) open breakpoints window (to see whether breakpoints were added)
4) press "F3", breakpoints will be added automatically (you can also add another breakpoints by hand)
5) press "F10", debugger will stop on breakpoints added by hand or on API calls that were made directly from module being examined (calls from library functions are skipped)
6) you can examine stack now and follow pushed EIP in disassembly view
7) when suspended you can delete breakpoints that were added by script (with "F5"), add them again, and so on (it is useful when you want to quickly disable breakpoints to follow usual execution flow)
8) also notice the condition in 'set_cb' callback (you can filter out some well-known functions)

list = []   #global list to hold EIP values

def set_cb(ea, name, ord):
    global list
    if (name != 'lstrcpynA') and (name != 'lstrcmpA') and (name != 'lstrcpyA') and (name != 'lstrcatA') and (name != 'lstrcmpiA') and (name != 'lstrlenA') and (name != 'wsprintfA') and (name != 'DefWindowProcA') and (name != 'PeekMessageA') and (name != 'TranslateMessage') and (name != 'DispatchMessageA') and (name != 'IsDBCSLeadByte') and (name != 'CharNextA'):
        actual_ea = Dword(ea)
        AddBpt(actual_ea)
        list.append(actual_ea)
        return True

def set_breakpoints():
    global list
    del list[:]
    nimps = idaapi.get_import_module_qty()
    for i in xrange(0, nimps):
        idaapi.enum_import_names(i, set_cb)

def rem_cb(ea, name, ord):
    actual_ea = Dword(ea)
    DelBpt(actual_ea)
        return True

def rem_breakpoints():
    global list
    del list[:]
    nimps = idaapi.get_import_module_qty()
    for i in xrange(0, nimps):
        idaapi.enum_import_names(i, rem_cb)

def step_cb():
    global list
    minea = idaapi.get_imagebase()
    maxea = minea + 0x98000     #image size retrieved by WIN API (from C++ program)
    while GetDebuggerEvent(WFNE_SUSP | WFNE_CONT, -1) > 0:
        r_eip = GetRegValue("EIP")
        if r_eip in list:
            r_esp = GetRegValue("ESP")
            caller = Dword(r_esp)
            if (caller >= minea) and (caller < maxea):
                if not(GetFunctionFlags(caller) & FUNC_LIB):
                    break
        else:
            break

idaapi.add_hotkey("F3", set_breakpoints)
idaapi.add_hotkey("F5", rem_breakpoints)
idaapi.add_hotkey("F10", step_cb)
| improve this answer | |
  • 1
    Is there any perticular reason you chose not to use the solution I suggested? – NirIzr Oct 5 '16 at 6:52

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.