مقدمة عن IDAPython


لا توجد مقالات كثيرة حول العمل مع IDAPython باللغة الروسية (وفي Habr على وجه الخصوص) ، سنحاول سد هذه الفجوة.


لمن. بالنسبة لأولئك الذين يعرفون بالفعل كيفية العمل في IDA Pro ، لكنهم لم يكتبوا نصوصًا برمجية في IDAPython. إذا كان لديك بالفعل خبرة في كتابة البرامج النصية لـ IDAPython ، فمن غير المحتمل أن تجد أي شيء جديد هنا.


ما لن يكون هنا. لن نعلم برمجة Python والعمل الأساسي في IDA Pro.


0x00.


, IDAPython — - Python, IDA . IDAPython "" IDC ( - IDA Pro).


, IDAPython , API . IDAPython python IDA ( C:\Program Files\IDA 7.0\python).


IDA Pro 7.0. IDAPython IDA "" ( ). IDA 7.4 Python 2.7 64-bit.



7- IDAPython API, 7.4 API. idc_bc695.py , - . 2017 API, .


0x01.


IDAPython — , , , .


:


  • ,
  • /,
  • / ( , ),
  • - /,
  • .

, — .



IDAPython :


  • ea — Effective Address — IDA, ;
  • here() , Disassembly-. — long;
  • idc, . , ;
  • "" ELF.


IDAPython :


  • IDA;
  • File — Script file (Alt + F7);
  • File — Script command (Shift + F2);
  • IDA Pro -S.

.


IDA CLI


IDA. , , Python.



Python CLI


IDA CLI


  • Python.
  • (, , ) , .
  • Tab.
  • .
  • help dir Python .
  • Output window (Alt + 0).


Segments idautils , IDA. Output window IDA CLI:


Python>import idautils
Python>help(idautils.Segments)
Help on function Segments in module idautils:
Segments()
Get list of segments (sections) in the binary image
@return: List of segment start addresses.
Python>for ea in idautils.Segments():
Python> print("%08x %s" % (ea, idc.get_segm_name(ea)))
Python>
08000000 .isr_vector
080000c0 .text
08006f9c .rodata
08007a14 .init_array
08007a18 .fini_array
20000000 .data
200001f8 .bss
200006c8 ._user_heap_stack
200017f8 abs

Script File


File — Script file (Alt + F7) .


(Hex / Char / Decimal). op_, :


  • op_bin(ea, n) — ;
  • op_dec(ea, n) — ;
  • op_oct(ea, n) — ;
  • op_hex(ea, n) — hex-;
  • op_chr(ea, n) — ;
  • op_seg(ea, n) — ;
  • op_stkvar(ea, n) — ;
  • op_stroff(ea, n) — ;
  • op_enum(ea, n) — ENUM-;
  • op_plain_offset(ea, n, base) — .

:


  • ea — , ;
  • n — ( ); mov eax, 0x10:
    • eax — 0- ;
    • 0x10 — 1- ;
  • base — offset- () .

IDA 7.0 Python 2.7, ( ).
:


# coding: utf-8
""" 
File: transforms.py
   
"""

START = 0x08000038
END = 0x08000084

def make_offsets32(start_ea, end_ea):
    """     """
    for ea in xrange(start_ea, end_ea, 4):
        idc.op_plain_offset(ea, 0, 0)

def make_dwords(start_ea, end_ea):
    """   32-   hex-"""
    for ea in xrange(start_ea, end_ea, 4):
        idc.op_hex(ea, 0)

if __name__ == '__main__':
    make_dwords(START, END)

Python, IDA. make_dwords START END. , , IDA CLI.


IDA Recent scripts ( View — Recent scripts Alt + F9):



: IDAPython-, , IDA, Python 2 , IDA .


Script Command


File — Script command (Shift + F2) IDA. , , . , .


. Run.



IDA c -S


IDA Pro, , . ( F1) Command line switches.


, :


> "C:\Program Files\IDA 7.0\ida.exe" -A -Sscript_name.py rhino.idb


  • -A ,
  • -S script_name.py IDB-.

/


:


  • print Output window (Alt + 0);
  • Output window Disassembly- , IDA. Output window , Disassembly-.

Python>here()
134239060         # 1.    
Python>hex(here())
0x8005354L        # 2.    
Python>"%08x" % here()
08005354          # 3.   
Python>get_name(here())
aErrorWrongHead   # 4.   

  • input/raw_input ;
  • ask_- ida_kernwin idaapi.



IDAPython , "" IDA Pro. IDA 7- .


IDAPython- ( — " ").


IDAPyHelper


, , . IDAPython IDAPyHelper, .



IDAPython Cheatsheet


IDAPython . — .



0x02.


.


. , , (Xrefs X), .



, , . IDAPython.


memcpy. , 11 memcpy.



:


  • - memcpy;
  • memcpy ;
  • ;
  • .

:


  • idautils.CodeRefsTo(func_ea, flow) — , - . flow ( 0/1) , . flow = 0;
  • idc.prev_head(ea) — , ;
  • idc.get_operand_value(ea, n) — n- . , . ARM :
    • R0 — 0;
    • R1 — 1;
    • R2 — 2 ;
  • idc.get_operand_type(ea, n) — n- . :
    • o_void = 0 — (, NOP);
    • o_reg = 1 — ;
    • o_mem = 2 — ;
    • o_phrase = 3[Base Reg + Index Reg],
    • o_displ = 4[Base Reg + Index Reg + Displacement];
    • o_imm = 5 — -;
    • o_far = 6 — FAR-;
    • o_near = 7 — NEAR-;
    • ;
  • idc.print_operand(ea, n) — ;
  • idc.set_cmt(ea, comment, repeat) — (. ).


ARM (R0-R3), :


  • ;
  • , R0, R1, R2 ( memcpy 3 );
  • , hex- , .

IDA


IDA :


— , . idc.set_cmt(ea, comment, rpt) repeat = 0:



(repeatable) — , . idc.set_cmt(ea, comment, rpt) repeat = 1:



()idc.update_extra_cmt(ea, n, comment):



.



# coding: utf-8
"""
File: funcargs.py
       
"""

import idautils

MEMCPY = 0x08006B26

def get_function_arg(ea, narg):
    """  n-   """
    while True:
        ea = idc.prev_head(ea)
        if idc.get_operand_value(ea, 0) == narg:
            break
    if idc.get_operand_type(ea, 1) in (idc.o_imm, idc.o_mem):
        res = "0x%x" % idc.get_operand_value(ea, 1)
    else:
        res = idc.print_operand(ea, 1)  
    return res

def set_comment_by_args(func_ea, nargs):
    """      """
    for ea in idautils.CodeRefsTo(func_ea, flow=0):
        func_args = []
        for i in range(0, nargs):
            arg = get_function_arg(ea, i)
            func_args.append(arg)
        args = ', '.join(a for a in func_args)  
        comment = "(%s)" % args
        idc.set_cmt(ea, comment, 0)

if __name__ == '__main__':
    set_comment_by_args(MEMCPY, 3)

-:



0x03.


, get_function_arg:


def get_function_arg(ea, narg):
    """ n-   (  )"""
    while True:
        ea = idc.prev_head(ea)
        if idc.get_operand_value(ea, 0) == narg:
            break

    if idc.get_operand_type(ea, 1) in (idc.o_imm, idc.o_mem):
        res = "0x%x" % idc.get_operand_value(ea, 1)
    else:        
        res = idc.print_operand(ea, 1)  

    return res

, , . x86, . n- push :


def get_function_arg_value(ea, narg):
    """ 
     n-   (  ).
       .
    """
    i = 0
    while True:
        ea = idc.prev_head(ea)
        if idc.print_insn_mnem(ea) == "push":
            if i == narg: break
            i += 1

    res = idc.get_operand_value(ea, 0)
    return res

0x04.


– ( , , assert). . "sendMsg error %s", "recvMsg error" "freeMsg error".



, , , . , .


, , sub_8006690:



x_printf.


0x08005034 R0 "sendMsg error %s\r\n". : , 0x08005040:


Python>"%08x" % get_operand_value(here(), 1)
08005040

ARM :


  • ( – 2 );
  • 32- , , (PC).

IDA , , .


, :


  1. x_printf idautils.CodeRefsTo
  2. ( R0) idc.get_operand_value ( get_function_arg, ).
  3. idc.get_wide_dword.
  4. idc.get_strlit_contents.
  5. , .
  6. "" , idc.set_name.

:


# coding: utf-8

import idautils

PRINTF = 0x08006690

def get_function_arg(ea, narg):
    """ n-  """
    while True:
        ea = idc.prev_head(ea)
        if idc.get_operand_value(ea, 0) == narg:
            break

    if idc.get_operand_type(ea, 1) == idc.o_mem:
        res = idc.get_operand_value(ea, 1)
    else:        
        res = idc.BADADDR

    return res

def get_func_name(str_log):
    """     """
    words = str_log.split(' ')
    if len(words) > 1 and words[1].startswith("error"):
        return words[0]
    else:
        return ""

def rename_by_log_str(log_func):
    """ ,   log_func   """
    for ea in idautils.CodeRefsTo(log_func, 0):
        arg = get_function_arg(ea, 0)
        if arg == idc.BADADDR:
            continue
        str_addr = idc.get_wide_dword(arg)
        str_log = idc.get_strlit_contents(str_addr)
        func_name = get_func_name(str_log)
        if func_name:
            print("0x%08x - 0x%08x - %s" % (arg, str_addr, func_name))

if __name__ == '__main__':
    rename_by_log_str(PRINTF)

, ( – get_func_name) .


0x05.


IDA . , , , . , , , .


– .


:


  • idc.get_color(ea, what) – ;
  • idc.set_color(ea, what, color) – ;
    • RGB hex- 0xBBGGRR (--)
    • what :
      • idc.CIC_ITEM = 1 – ;
      • idc.CIC_FUNC = 2 – ;
      • idc.CIC_SEGM = 3 – .

,


for i, ea in enumerate(xrange(0x08005196, 0x080051AE, 2)):
    idc.set_color(ea, CIC_ITEM, 0x0f << (2 * i))

0x08005196 0x080051AE :



, ARM- , , :



: .


:


  1. . idautils.Segments(), .
  2. . idc.get_segm_attr(segm, attr), . SEG_CODE ( — SEGATTR_TYPE) .
  3. . idautils.Heads(start, end), (, ) start end.
  4. idc.get_full_flags(ea) is_code(flags) , ea.
  5. .

:


BLUE = 0xF2D0AF
PINK = 0xAFD0F2

def colored_code():
    """        """

    code_segmnets = filter(lambda segm: \
                          idc.get_segm_attr(segm, SEGATTR_TYPE) == SEG_CODE,\
                          idautils.Segments())

    for segm in code_segmnets:
        end = idc.get_segm_end(segm)
        for ea in idautils.Heads(segm, end):
            flags = idc.get_full_flags(ea)
            if idc.is_code(flags):
                idc.set_color(ea, CIC_ITEM, BLUE)
            else:
                idc.set_color(ea, CIC_ITEM, PINK)


, is_code(flags) , . get_full_flags(ea).


colored_code :



, IDAPython , ( idautils.Segments idautils.Heads), (idc.set_color), (idc.get_strlit_contents) (idc.get_wide_dword).




All Articles