0

here is the original C++ source code of the executable that I've created to do simple RE

#include <iostream>

void myFunction() {

    printf("Hello!");
}

int main()
{
    myFunction();
    return 0;
}

When I disassembled my executable in IDA, this is the first block that I see enter image description here

With the address being 0x4112c1 enter image description here

I've created a simple IDAPython script to find out what is the next address after the jump _main_0

from idautils import *
from idaapi import *
from idc import *

cursor = 0
start_addr = 0
end_addr = 0
print("----------Starting python script----------\n")
for func in Functions():
    name = get_func_name(func)
    if "_main" == name:
        start_addr = get_func_attr(func, FUNCATTR_START)
        end_addr = get_func_attr(func, FUNCATTR_END)
        print("Start: 0x%x, End: 0x%x" %(start_addr, end_addr))

cursor = start_addr
print('0x%x %s' % (cursor, generate_disasm_line(cursor, 0)))
cur_addr = next_head(cursor, end_addr)
print("Next Head: 0x%x" %cur_addr)
print("---------Exiting Python script------")

And this is the following output:

----------Starting python script----------

Start: 0x4112c1, End: 0x4112c6
0x4112c1 jmp     _main_0
Next Head: 0xffffffff
---------Exiting Python script------

I have 2 questions I would like to ask:

  1. May I ask why isn't the address of the next head 0x411930 (which is the address of _main_0, as shown in the screenshot below) ? enter image description here
  2. Is it possible to make the script go to the address of the mentioned function when it detects a jump statement? (because I thought next head will do the trick)

**Disclaimer: I'm kinda new to RE and IDAPython so do bear with me if I ask too much

0

May I ask why isn't the address of the next head 0x411930 (which is the address of _main_0, as shown in the screenshot below) ?

From IDAPython docs:

next_head(ea, maxea=4294967295)

Get next defined item (instruction or data) in the program

That will give you the next defined item after the address passed in ea no matter what instruction is at ea.

Is it possible to make the script go to the address of the mentioned function when it detects a jump statement? (because I thought next head will do the trick)

Of course it is possible. One way to do that is to call ida_xref.get_first_cref_from and extract that address from its output. Probably there are some better ways to do that, but this one should work.

1
  • Hi! Thank you so much for your suggestion! That function works for me and it's good for me (for now :) ) – wanitaqing Mar 29 at 6:37
0

This is untested, and is just a slightly expanded version of an old function GetTarget I have. It's very low-tech (simple API usage only), and (probably) will only work correctly for the x86/64 platform where all conditional jump mnemonics start with j and no mnemonic starts with j that isn't a jump of some type.

The alternative (which I also have) using NN_* code is harder to grasp for a beginner.

def GetTarget(ea):
    mnem = GetMnem(ea)
    if not mnem:
        return BADADDR
    
    opType0 = GetOpType(ea, 0)
    if mnem == "jmp" or mnem == "call" or mnem[0] == "j":
        if opType0 != o_near and opType0 != o_mem:
            print("Can't follow opType0 " + opTypeAsName(opType0))
            return BADADDR
        else:
            return GetOperandValue(ea, 0)

    if NextHead(ea) == ea + ItemSize(ea) and isFlow(GetFlags(NextHead(ea))):
        return NextHead(ea)

def opTypeAsName(n):
    for item in [x for x in dir(idc) if x.startswith('o_')]:
        if getattr(idc, item) == n: return item

Since the way I used to code is really a little embarrassing, here is the same code in correct pythonic idapython 7

def GetTarget7(ea):
    mnem = idc.print_insn_mnem(ea)
    if not mnem:
        return idc.BADADDR
    
    opType0 = idc.get_operand_type(ea, 0)
    if mnem == "jmp" or mnem == "call" or mnem[0] == "j":
        if opType0 != o_near and opType0 != o_mem:
            print("Can't follow opType0 " + opTypeAsName(opType0))
            return idc.BADADDR
        else:
            return idc.get_operand_value(ea, 0)

    if idc.next_head(ea) == ea + idc.get_item_size(ea) and \
            idc.is_flow(idc.get_full_flags(idc.next_head(ea))):
        return idc.next_head(ea)

see my github for vim ultisnips auto-expanding 6 to 7 idapython conversion, and idapython syntax file

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.