#!/usr/bin/env python
#---------------------------------------------------------------------
# IDAPython - Python plugin for Interactive Disassembler
#
# Original IDC.IDC:
# Copyright (c) 1990-2010 Ilfak Guilfanov
#
# Python conversion:
# Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net>
#
# All rights reserved.
#
# For detailed copyright information see the file COPYING in
# the root of the distribution archive.
#---------------------------------------------------------------------
# idc.py - IDC compatibility module
#---------------------------------------------------------------------
"""
IDC compatibility module
This file contains IDA built-in function declarations and internal bit
definitions. Each byte of the program has 32-bit flags (low 8 bits keep
the byte value). These 32 bits are used in GetFlags/SetFlags functions.
You may freely examine these bits using GetFlags() but the use of the
SetFlags() function is strongly discouraged.
This file is subject to change without any notice.
Future versions of IDA may use other definitions.
"""
try:
import idaapi
except ImportError:
print "Could not import idaapi. Running in 'pydoc mode'."
import os
import re
import struct
import time
import types
__EA64__ = idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL
WORDMASK = 0xFFFFFFFFFFFFFFFF if __EA64__ else 0xFFFFFFFF
class DeprecatedIDCError(Exception):
"""
Exception for deprecated function calls
"""
pass
def _IDC_GetAttr(obj, attrmap, attroffs):
"""
Internal function to generically get object attributes
Do not use unless you know what you are doing
"""
if attroffs in attrmap and hasattr(obj, attrmap[attroffs][1]):
return getattr(obj, attrmap[attroffs][1])
else:
errormsg = "attribute with offset %d not found, check the offset and report the problem" % attroffs
raise KeyError, errormsg
def _IDC_SetAttr(obj, attrmap, attroffs, value):
"""
Internal function to generically set object attributes
Do not use unless you know what you are doing
"""
# check for read-only atributes
if attroffs in attrmap:
if attrmap[attroffs][0]:
raise KeyError, "attribute with offset %d is read-only" % attroffs
elif hasattr(obj, attrmap[attroffs][1]):
return setattr(obj, attrmap[attroffs][1], value)
errormsg = "attribute with offset %d not found, check the offset and report the problem" % attroffs
raise KeyError, errormsg
BADADDR = idaapi.BADADDR # Not allowed address value
BADSEL = idaapi.BADSEL # Not allowed selector value/number
MAXADDR = idaapi.MAXADDR & WORDMASK
SIZE_MAX = idaapi.SIZE_MAX
#
# Flag bit definitions (for GetFlags())
#
MS_VAL = idaapi.MS_VAL # Mask for byte value
FF_IVL = idaapi.FF_IVL # Byte has value ?
# Do flags contain byte value? (i.e. has the byte a value?)
# if not, the byte is uninitialized.
def hasValue(F): return ((F & FF_IVL) != 0) # any defined value?
def byteValue(F):
"""
Get byte value from flags
Get value of byte provided that the byte is initialized.
This macro works ok only for 8-bit byte machines.
"""
return (F & MS_VAL)
def isLoaded(ea):
"""Is the byte initialized?"""
return hasValue(GetFlags(ea)) # any defined value?
MS_CLS = idaapi.MS_CLS # Mask for typing
FF_CODE = idaapi.FF_CODE # Code ?
FF_DATA = idaapi.FF_DATA # Data ?
FF_TAIL = idaapi.FF_TAIL # Tail ?
FF_UNK = idaapi.FF_UNK # Unknown ?
def isCode(F): return ((F & MS_CLS) == FF_CODE) # is code byte?
def isData(F): return ((F & MS_CLS) == FF_DATA) # is data byte?
def isTail(F): return ((F & MS_CLS) == FF_TAIL) # is tail byte?
def isUnknown(F): return ((F & MS_CLS) == FF_UNK) # is unexplored byte?
def isHead(F): return ((F & FF_DATA) != 0) # is start of code/data?
#
# Common bits
#
MS_COMM = idaapi.MS_COMM # Mask of common bits
FF_COMM = idaapi.FF_COMM # Has comment?
FF_REF = idaapi.FF_REF # has references?
FF_LINE = idaapi.FF_LINE # Has next or prev cmt lines ?
FF_NAME = idaapi.FF_NAME # Has user-defined name ?
FF_LABL = idaapi.FF_LABL # Has dummy name?
FF_FLOW = idaapi.FF_FLOW # Exec flow from prev instruction?
FF_VAR = idaapi.FF_VAR # Is byte variable ?
FF_ANYNAME = FF_LABL | FF_NAME
def isFlow(F): return ((F & FF_FLOW) != 0)
def isVar(F): return ((F & FF_VAR ) != 0)
def isExtra(F): return ((F & FF_LINE) != 0)
def isRef(F): return ((F & FF_REF) != 0)
def hasName(F): return ((F & FF_NAME) != 0)
def hasUserName(F): return ((F & FF_ANYNAME) == FF_NAME)
MS_0TYPE = idaapi.MS_0TYPE # Mask for 1st arg typing
FF_0VOID = idaapi.FF_0VOID # Void (unknown)?
FF_0NUMH = idaapi.FF_0NUMH # Hexadecimal number?
FF_0NUMD = idaapi.FF_0NUMD # Decimal number?
FF_0CHAR = idaapi.FF_0CHAR # Char ('x')?
FF_0SEG = idaapi.FF_0SEG # Segment?
FF_0OFF = idaapi.FF_0OFF # Offset?
FF_0NUMB = idaapi.FF_0NUMB # Binary number?
FF_0NUMO = idaapi.FF_0NUMO # Octal number?
FF_0ENUM = idaapi.FF_0ENUM # Enumeration?
FF_0FOP = idaapi.FF_0FOP # Forced operand?
FF_0STRO = idaapi.FF_0STRO # Struct offset?
FF_0STK = idaapi.FF_0STK # Stack variable?
MS_1TYPE = idaapi.MS_1TYPE # Mask for 2nd arg typing
FF_1VOID = idaapi.FF_1VOID # Void (unknown)?
FF_1NUMH = idaapi.FF_1NUMH # Hexadecimal number?
FF_1NUMD = idaapi.FF_1NUMD # Decimal number?
FF_1CHAR = idaapi.FF_1CHAR # Char ('x')?
FF_1SEG = idaapi.FF_1SEG # Segment?
FF_1OFF = idaapi.FF_1OFF # Offset?
FF_1NUMB = idaapi.FF_1NUMB # Binary number?
FF_1NUMO = idaapi.FF_1NUMO # Octal number?
FF_1ENUM = idaapi.FF_1ENUM # Enumeration?
FF_1FOP = idaapi.FF_1FOP # Forced operand?
FF_1STRO = idaapi.FF_1STRO # Struct offset?
FF_1STK = idaapi.FF_1STK # Stack variable?
# The following macros answer questions like
# 'is the 1st (or 2nd) operand of instruction or data of the given type'?
# Please note that data items use only the 1st operand type (is...0)
def isDefArg0(F): return ((F & MS_0TYPE) != FF_0VOID)
def isDefArg1(F): return ((F & MS_1TYPE) != FF_1VOID)
def isDec0(F): return ((F & MS_0TYPE) == FF_0NUMD)
def isDec1(F): return ((F & MS_1TYPE) == FF_1NUMD)
def isHex0(F): return ((F & MS_0TYPE) == FF_0NUMH)
def isHex1(F): return ((F & MS_1TYPE) == FF_1NUMH)
def isOct0(F): return ((F & MS_0TYPE) == FF_0NUMO)
def isOct1(F): return ((F & MS_1TYPE) == FF_1NUMO)
def isBin0(F): return ((F & MS_0TYPE) == FF_0NUMB)
def isBin1(F): return ((F & MS_1TYPE) == FF_1NUMB)
def isOff0(F): return ((F & MS_0TYPE) == FF_0OFF)
def isOff1(F): return ((F & MS_1TYPE) == FF_1OFF)
def isChar0(F): return ((F & MS_0TYPE) == FF_0CHAR)
def isChar1(F): return ((F & MS_1TYPE) == FF_1CHAR)
def isSeg0(F): return ((F & MS_0TYPE) == FF_0SEG)
def isSeg1(F): return ((F & MS_1TYPE) == FF_1SEG)
def isEnum0(F): return ((F & MS_0TYPE) == FF_0ENUM)
def isEnum1(F): return ((F & MS_1TYPE) == FF_1ENUM)
def isFop0(F): return ((F & MS_0TYPE) == FF_0FOP)
def isFop1(F): return ((F & MS_1TYPE) == FF_1FOP)
def isStroff0(F): return ((F & MS_0TYPE) == FF_0STRO)
def isStroff1(F): return ((F & MS_1TYPE) == FF_1STRO)
def isStkvar0(F): return ((F & MS_0TYPE) == FF_0STK)
def isStkvar1(F): return ((F & MS_1TYPE) == FF_1STK)
#
# Bits for DATA bytes
#
DT_TYPE = idaapi.DT_TYPE & 0xFFFFFFFF # Mask for DATA typing
FF_BYTE = idaapi.FF_BYTE & 0xFFFFFFFF # byte
FF_WORD = idaapi.FF_WORD & 0xFFFFFFFF # word
FF_DWRD = idaapi.FF_DWRD & 0xFFFFFFFF # dword
FF_QWRD = idaapi.FF_QWRD & 0xFFFFFFFF # qword
FF_TBYT = idaapi.FF_TBYT & 0xFFFFFFFF # tbyte
FF_ASCI = idaapi.FF_ASCI & 0xFFFFFFFF # ASCII ?
FF_STRU = idaapi.FF_STRU & 0xFFFFFFFF # Struct ?
FF_OWRD = idaapi.FF_OWRD & 0xFFFFFFFF # octaword (16 bytes)
FF_FLOAT = idaapi.FF_FLOAT & 0xFFFFFFFF # float
FF_DOUBLE = idaapi.FF_DOUBLE & 0xFFFFFFFF # double
FF_PACKREAL = idaapi.FF_PACKREAL & 0xFFFFFFFF # packed decimal real
FF_ALIGN = idaapi.FF_ALIGN & 0xFFFFFFFF # alignment directive
def isByte(F): return (isData(F) and (F & DT_TYPE) == FF_BYTE)
def isWord(F): return (isData(F) and (F & DT_TYPE) == FF_WORD)
def isDwrd(F): return (isData(F) and (F & DT_TYPE) == FF_DWRD)
def isQwrd(F): return (isData(F) and (F & DT_TYPE) == FF_QWRD)
def isOwrd(F): return (isData(F) and (F & DT_TYPE) == FF_OWRD)
def isTbyt(F): return (isData(F) and (F & DT_TYPE) == FF_TBYT)
def isFloat(F): return (isData(F) and (F & DT_TYPE) == FF_FLOAT)
def isDouble(F): return (isData(F) and (F & DT_TYPE) == FF_DOUBLE)
def isPackReal(F): return (isData(F) and (F & DT_TYPE) == FF_PACKREAL)
def isASCII(F): return (isData(F) and (F & DT_TYPE) == FF_ASCI)
def isStruct(F): return (isData(F) and (F & DT_TYPE) == FF_STRU)
def isAlign(F): return (isData(F) and (F & DT_TYPE) == FF_ALIGN)
#
# Bits for CODE bytes
#
MS_CODE = idaapi.MS_CODE & 0xFFFFFFFF
FF_FUNC = idaapi.FF_FUNC & 0xFFFFFFFF # function start?
FF_IMMD = idaapi.FF_IMMD & 0xFFFFFFFF # Has Immediate value ?
FF_JUMP = idaapi.FF_JUMP & 0xFFFFFFFF # Has jump table
#
# Loader flags
#
NEF_SEGS = idaapi.NEF_SEGS # Create segments
NEF_RSCS = idaapi.NEF_RSCS # Load resources
NEF_NAME = idaapi.NEF_NAME # Rename entries
NEF_MAN = idaapi.NEF_MAN # Manual load
NEF_FILL = idaapi.NEF_FILL # Fill segment gaps
NEF_IMPS = idaapi.NEF_IMPS # Create imports section
NEF_FIRST = idaapi.NEF_FIRST # This is the first file loaded
NEF_CODE = idaapi.NEF_CODE # for load_binary_file:
NEF_RELOAD = idaapi.NEF_RELOAD # reload the file at the same place:
NEF_FLAT = idaapi.NEF_FLAT # Autocreated FLAT group (PE)
# List of built-in functions
# --------------------------
#
# The following conventions are used in this list:
# 'ea' is a linear address
# 'success' is 0 if a function failed, 1 otherwise
# 'void' means that function returns no meaningful value (always 0)
#
# All function parameter conversions are made automatically.
#
# ----------------------------------------------------------------------------
# M I S C E L L A N E O U S
# ----------------------------------------------------------------------------
def IsString(var): raise NotImplementedError, "this function is not needed in Python"
def IsLong(var): raise NotImplementedError, "this function is not needed in Python"
def IsFloat(var): raise NotImplementedError, "this function is not needed in Python"
def IsFunc(var): raise NotImplementedError, "this function is not needed in Python"
def IsPvoid(var): raise NotImplementedError, "this function is not needed in Python"
def IsInt64(var): raise NotImplementedError, "this function is not needed in Python"
def MK_FP(seg, off):
"""
Return value of expression: ((seg<<4) + off)
"""
return (seg << 4) + off
def form(format, *args):
raise DeprecatedIDCError, "form() is deprecated. Use python string operations instead."
def substr(s, x1, x2):
raise DeprecatedIDCError, "substr() is deprecated. Use python string operations instead."
def strstr(s1, s2):
raise DeprecatedIDCError, "strstr() is deprecated. Use python string operations instead."
def strlen(s):
raise DeprecatedIDCError, "strlen() is deprecated. Use python string operations instead."
def xtol(s):
raise DeprecatedIDCError, "xtol() is deprecated. Use python long() instead."
def atoa(ea):
"""
Convert address value to a string
Return address in the form 'seg000:1234'
(the same as in line prefixes)
@param ea: address to format
"""
segname = SegName(ea)
if segname == "":
segname = "0"
return "%s:%X" % (segname, ea)
def ltoa(n, radix):
raise DeprecatedIDCError, "ltoa() is deprecated. Use python string operations instead."
def atol(s):
raise DeprecatedIDCError, "atol() is deprecated. Use python long() instead."
def rotate_left(value, count, nbits, offset):
"""
Rotate a value to the left (or right)
@param value: value to rotate
@param count: number of times to rotate. negative counter means
rotate to the right
@param nbits: number of bits to rotate
@param offset: offset of the first bit to rotate
@return: the value with the specified field rotated
all other bits are not modified
"""
assert offset >= 0, "offset must be >= 0"
assert nbits > 0, "nbits must be > 0"
mask = 2**(offset+nbits) - 2**offset
tmp = value & mask
if count > 0:
for x in xrange(count):
if (tmp >> (offset+nbits-1)) & 1:
tmp = (tmp << 1) | (1 << offset)
else:
tmp = (tmp << 1)
else:
for x in xrange(-count):
if (tmp >> offset) & 1:
tmp = (tmp >> 1) | (1 << (offset+nbits-1))
else:
tmp = (tmp >> 1)
value = (value-(value&mask)) | (tmp & mask)
return value
def rotate_dword(x, count): return rotate_left(x, count, 32, 0)
def rotate_word(x, count): return rotate_left(x, count, 16, 0)
def rotate_byte(x, count): return rotate_left(x, count, 8, 0)
# AddHotkey return codes
IDCHK_OK = 0 # ok
IDCHK_ARG = -1 # bad argument(s)
IDCHK_KEY = -2 # bad hotkey name
IDCHK_MAX = -3 # too many IDC hotkeys
def AddHotkey(hotkey, idcfunc):
"""
Add hotkey for IDC function
@param hotkey: hotkey name ('a', "Alt-A", etc)
@param idcfunc: IDC function name
@return: None
"""
return idaapi.add_idc_hotkey(hotkey, idcfunc)
def DelHotkey(hotkey):
"""
Delete IDC function hotkey
@param hotkey: hotkey code to delete
"""
return idaapi.del_idc_hotkey(hotkey)
def Jump(ea):
"""
Move cursor to the specifed linear address
@param ea: linear address
"""
return idaapi.jumpto(ea)
def Wait():
"""
Process all entries in the autoanalysis queue
Wait for the end of autoanalysis
@note: This function will suspend execution of the calling script
till the autoanalysis queue is empty.
"""
return idaapi.autoWait()
def CompileEx(input, isfile):
"""
Compile an IDC script
The input should not contain functions that are
currently executing - otherwise the behaviour of the replaced
functions is undefined.
@param input: if isfile != 0, then this is the name of file to compile
otherwise it holds the text to compile
@param isfile: specify if 'input' holds a filename or the expression itself
@return: 0 - ok, otherwise it returns an error message
"""
if isfile:
res = idaapi.Compile(input)
else:
res = idaapi.CompileLine(input)
if res:
return res
else:
return 0
def Eval(expr):
"""
Evaluate an IDC expression
@param expr: an expression
@return: the expression value. If there are problems, the returned value will be "IDC_FAILURE: xxx"
where xxx is the error description
@note: Python implementation evaluates IDC only, while IDC can call other registered languages
"""
rv = idaapi.idc_value_t()
err = idaapi.calc_idc_expr(BADADDR, expr, rv)
if err:
return "IDC_FAILURE: "+err
else:
if rv.vtype == '\x01': # VT_STR
return rv.str
elif rv.vtype == '\x02': # long
return rv.num
elif rv.vtype == '\x07': # VT_STR2
return rv.c_str()
else:
raise NotImplementedError, "Eval() supports only expressions returning strings or longs"
def EVAL_FAILURE(code):
"""
Check the result of Eval() for evaluation failures
@param code: result of Eval()
@return: True if there was an evaluation error
"""
return type(code) == types.StringType and code.startswith("IDC_FAILURE: ")
def SaveBase(idbname, flags=0):
"""
Save current database to the specified idb file
@param idbname: name of the idb file. if empty, the current idb
file will be used.
@param flags: combination of idaapi.DBFL_... bits or 0
"""
if len(idbname) == 0:
idbname = GetIdbPath()
saveflags = idaapi.cvar.database_flags
mask = idaapi.DBFL_KILL | idaapi.DBFL_COMP | idaapi.DBFL_BAK
idaapi.cvar.database_flags &= ~mask
idaapi.cvar.database_flags |= flags & mask
res = idaapi.save_database(idbname, 0)
idaapi.cvar.database_flags = saveflags
return res
DBFL_BAK = idaapi.DBFL_BAK # for compatiblity with older versions, eventually delete this
def ValidateNames():
"""
check consistency of IDB name records
@return: number of inconsistent name records
"""
return idaapi.validate_idb_names()
def Exit(code):
"""
Stop execution of IDC program, close the database and exit to OS
@param code: code to exit with.
@return: -
"""
idaapi.qexit(code)
def Exec(command):
"""
Execute an OS command.
@param command: command line to execute
@return: error code from OS
@note:
IDA will wait for the started program to finish.
In order to start the command in parallel, use OS methods.
For example, you may start another program in parallel using
"start" command.
"""
return os.system(command)
def Sleep(milliseconds):
"""
Sleep the specified number of milliseconds
This function suspends IDA for the specified amount of time
@param milliseconds: time to sleep
"""
time.sleep(float(milliseconds)/1000)
def RunPlugin(name, arg):
"""
Load and run a plugin
@param name: The plugin name is a short plugin name without an extension
@param arg: integer argument
@return: 0 if could not load the plugin, 1 if ok
"""
return idaapi.load_and_run_plugin(name, arg)
def ApplySig(name):
"""
Load (plan to apply) a FLIRT signature file
@param name: signature name without path and extension
@return: 0 if could not load the signature file, !=0 otherwise
"""
return idaapi.plan_to_apply_idasgn(name)
#----------------------------------------------------------------------------
# C H A N G E P R O G R A M R E P R E S E N T A T I O N
#----------------------------------------------------------------------------
def DeleteAll():
"""
Delete all segments, instructions, comments, i.e. everything
except values of bytes.
"""
ea = idaapi.cvar.inf.minEA
# Brute-force nuke all info from all the heads
while ea != BADADDR and ea <= idaapi.cvar.inf.maxEA:
idaapi.del_local_name(ea)
idaapi.del_global_name(ea)
func = idaapi.get_func(ea)
if func:
idaapi.del_func_cmt(func, False)
idaapi.del_func_cmt(func, True)
idaapi.del_func(ea)
idaapi.del_hidden_area(ea)
seg = idaapi.getseg(ea)
if seg:
idaapi.del_segment_cmt(seg, False)
idaapi.del_segment_cmt(seg, True)
idaapi.del_segm(ea, idaapi.SEGDEL_KEEP | idaapi.SEGDEL_SILENT)
ea = idaapi.next_head(ea, idaapi.cvar.inf.maxEA)
def MakeCode(ea):
"""
Create an instruction at the specified address
@param ea: linear address
@return: 0 - can not create an instruction (no such opcode, the instruction
would overlap with existing items, etc) otherwise returns length of the
instruction in bytes
"""
return idaapi.create_insn(ea)
def AnalyzeArea(sEA, eEA):
"""
Perform full analysis of the area
@param sEA: starting linear address
@param eEA: ending linear address (excluded)
@return: 1-ok, 0-Ctrl-Break was pressed.
"""
return idaapi.analyze_area(sEA, eEA)
def MakeNameEx(ea, name, flags):
"""
Rename an address
@param ea: linear address
@param name: new name of address. If name == "", then delete old name
@param flags: combination of SN_... constants
@return: 1-ok, 0-failure
"""
return idaapi.set_name(ea, name, flags)
SN_CHECK = idaapi.SN_CHECK # Fail if the name contains invalid
# characters
# If this bit is clear, all invalid chars
# (those !is_ident_char()) will be replaced
# by SubstChar (usually '_')
# List of valid characters is defined in
# ida.cfg
SN_NOCHECK = idaapi.SN_NOCHECK # Replace invalid chars with SubstChar
SN_PUBLIC = idaapi.SN_PUBLIC # if set, make name public
SN_NON_PUBLIC = idaapi.SN_NON_PUBLIC # if set, make name non-public
SN_WEAK = idaapi.SN_WEAK # if set, make name weak
SN_NON_WEAK = idaapi.SN_NON_WEAK # if set, make name non-weak
SN_AUTO = idaapi.SN_AUTO # if set, make name autogenerated
SN_NON_AUTO = idaapi.SN_NON_AUTO # if set, make name non-autogenerated
SN_NOLIST = idaapi.SN_NOLIST # if set, exclude name from the list
# if not set, then include the name into
# the list (however, if other bits are set,
# the name might be immediately excluded
# from the list)
SN_NOWARN = idaapi.SN_NOWARN # don't display a warning if failed
SN_LOCAL = idaapi.SN_LOCAL # create local name. a function should exist.
# local names can't be public or weak.
# also they are not included into the list
# of names they can't have dummy prefixes
def MakeComm(ea, comment):
"""
Set an indented regular comment of an item
@param ea: linear address
@param comment: comment string
@return: None
"""
return idaapi.set_cmt(ea, comment, 0)
def MakeRptCmt(ea, comment):
"""
Set an indented repeatable comment of an item
@param ea: linear address
@param comment: comment string
@return: None
"""
return idaapi.set_cmt(ea, comment, 1)
def MakeArray(ea, nitems):
"""
Create an array.
@param ea: linear address
@param nitems: size of array in items
@note: This function will create an array of the items with the same type as
the type of the item at 'ea'. If the byte at 'ea' is undefined, then
this function will create an array of bytes.
"""
flags = idaapi.getFlags(ea)
if idaapi.isCode(flags) or idaapi.isTail(flags) or idaapi.isAlign(flags):
return False
if idaapi.isUnknown(flags):
flags = idaapi.FF_BYTE
if idaapi.isStruct(flags):
ti = idaapi.opinfo_t()
assert idaapi.get_opinfo(ea, 0, flags, ti), "get_opinfo() failed"
itemsize = idaapi.get_data_elsize(ea, flags, ti)
tid = ti.tid
else:
itemsize = idaapi.get_item_size(ea)
tid = BADADDR
return idaapi.do_data_ex(ea, flags, itemsize*nitems, tid)
def MakeStr(ea, endea):
"""
Create a string.
This function creates a string (the string type is determined by the
value of GetLongPrm(INF_STRTYPE))
@param ea: linear address
@param endea: ending address of the string (excluded)
if endea == BADADDR, then length of string will be calculated
by the kernel
@return: 1-ok, 0-failure
@note: The type of an existing string is returned by GetStringType()
"""
return idaapi.make_ascii_string(ea, 0 if endea == BADADDR else endea - ea, GetLongPrm(INF_STRTYPE))
def MakeData(ea, flags, size, tid):
"""
Create a data item at the specified address
@param ea: linear address
@param flags: FF_BYTE..FF_PACKREAL
@param size: size of item in bytes
@param tid: for FF_STRU the structure id
@return: 1-ok, 0-failure
"""
return idaapi.do_data_ex(ea, flags, size, tid)
def MakeByte(ea):
"""
Convert the current item to a byte
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doByte(ea, 1)
def MakeWord(ea):
"""
Convert the current item to a word (2 bytes)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doWord(ea, 2)
def MakeDword(ea):
"""
Convert the current item to a double word (4 bytes)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doDwrd(ea, 4)
def MakeQword(ea):
"""
Convert the current item to a quadro word (8 bytes)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doQwrd(ea, 8)
def MakeOword(ea):
"""
Convert the current item to an octa word (16 bytes/128 bits)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doOwrd(ea, 16)
def MakeYword(ea):
"""
Convert the current item to a ymm word (32 bytes/256 bits)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doYwrd(ea, 32)
def MakeFloat(ea):
"""
Convert the current item to a floating point (4 bytes)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doFloat(ea, 4)
def MakeDouble(ea):
"""
Convert the current item to a double floating point (8 bytes)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doDouble(ea, 8)
def MakePackReal(ea):
"""
Convert the current item to a packed real (10 or 12 bytes)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doPackReal(ea, idaapi.ph_get_tbyte_size())
def MakeTbyte(ea):
"""
Convert the current item to a tbyte (10 or 12 bytes)
@param ea: linear address
@return: 1-ok, 0-failure
"""
return idaapi.doTbyt(ea, idaapi.ph_get_tbyte_size())
def MakeStructEx(ea, size, strname):
"""
Convert the current item to a structure instance
@param ea: linear address
@param size: structure size in bytes. -1 means that the size
will be calculated automatically
@param strname: name of a structure type
@return: 1-ok, 0-failure
"""
strid = idaapi.get_struc_id(strname)
if size == -1:
size = idaapi.get_struc_size(strid)
return idaapi.doStruct(ea, size, strid)
def MakeCustomDataEx(ea, size, dtid, fid):
"""
Convert the item at address to custom data.
@param ea: linear address.
@param size: custom data size in bytes.
@param dtid: data type ID.
@param fid: data format ID.
@return: 1-ok, 0-failure
"""
return idaapi.doCustomData(ea, size, dtid, fid)
def MakeAlign(ea, count, align):
"""
Convert the current item to an alignment directive
@param ea: linear address
@param count: number of bytes to convert
@param align: 0 or 1..32
if it is 0, the correct alignment will be calculated
by the kernel
@return: 1-ok, 0-failure
"""
return idaapi.doAlign(ea, count, align)
def MakeLocal(start, end, location, name):
"""
Create a local variable
@param start: start of address range for the local variable
@param end: end of address range for the local variable
@param location: the variable location in the "[bp+xx]" form where xx is
a number. The location can also be specified as a
register name.
@param name: name of the local variable
@return: 1-ok, 0-failure
@note: For the stack variables the end address is ignored.
If there is no function at 'start' then this function.
will fail.
"""
func = idaapi.get_func(start)
if not func:
return 0
# Find out if location is in the [bp+xx] form
r = re.compile("\[([a-z]+)([-+][0-9a-fx]+)", re.IGNORECASE)
m = r.match(location)
if m:
# Location in the form of [bp+xx]
register = idaapi.str2reg(m.group(1))
offset = int(m.group(2), 0)
frame = idaapi.get_frame(func)
if register == -1 or not frame:
return 0
offset += func.frsize
member = idaapi.get_member(frame, offset)
if member:
# Member already exists, rename it
if idaapi.set_member_name(frame, offset, name):
return 1
else:
return 0
else:
# No member at the offset, create a new one
if idaapi.add_struc_member(frame,
name,
offset,
idaapi.byteflag(),
None, 1) == 0:
return 1
else:
return 0
else:
# Location as simple register name
return idaapi.add_regvar(func, start, end, location, name, None)
def MakeUnkn(ea, flags):
"""
Convert the current item to an explored item
@param ea: linear address
@param flags: combination of DOUNK_* constants
@return: None
"""
return idaapi.do_unknown(ea, flags)
def MakeUnknown(ea, size, flags):
"""
Convert the current item to an explored item
@param ea: linear address
@param size: size of the range to undefine (for MakeUnknown)
@param flags: combination of DOUNK_* constants
@return: None
"""
return idaapi.do_unknown_range(ea, size, flags)
DOUNK_SIMPLE = idaapi.DOUNK_SIMPLE # simply undefine the specified item
DOUNK_EXPAND = idaapi.DOUNK_EXPAND # propogate undefined items, for example
# if removing an instruction removes all
# references to the next instruction, then
# plan to convert to unexplored the next
# instruction too.
DOUNK_DELNAMES = idaapi.DOUNK_DELNAMES # delete any names at the specified address(es)
def SetArrayFormat(ea, flags, litems, align):
"""
Set array representation format
@param ea: linear address
@param flags: combination of AP_... constants or 0
@param litems: number of items per line. 0 means auto
@param align: element alignment
- -1: do not align
- 0: automatic alignment
- other values: element width
@return: 1-ok, 0-failure
"""
return Eval("SetArrayFormat(0x%X, 0x%X, %d, %d)"%(ea, flags, litems, align))
AP_ALLOWDUPS = 0x00000001L # use 'dup' construct
AP_SIGNED = 0x00000002L # treats numbers as signed
AP_INDEX = 0x00000004L # display array element indexes as comments
AP_ARRAY = 0x00000008L # reserved (this flag is not stored in database)
AP_IDXBASEMASK = 0x000000F0L # mask for number base of the indexes
AP_IDXDEC = 0x00000000L # display indexes in decimal
AP_IDXHEX = 0x00000010L # display indexes in hex
AP_IDXOCT = 0x00000020L # display indexes in octal
AP_IDXBIN = 0x00000030L # display indexes in binary
def OpBinary(ea, n):
"""
Convert an operand of the item (instruction or data) to a binary number
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
@return: 1-ok, 0-failure
@note: the data items use only the type of the first operand
"""
return idaapi.op_bin(ea, n)
def OpOctal(ea, n):
"""
Convert an operand of the item (instruction or data) to an octal number
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.op_oct(ea, n)
def OpDecimal(ea, n):
"""
Convert an operand of the item (instruction or data) to a decimal number
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.op_dec(ea, n)
def OpHex(ea, n):
"""
Convert an operand of the item (instruction or data) to a hexadecimal number
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.op_hex(ea, n)
def OpChr(ea, n):
"""
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.op_chr(ea, n)
def OpOff(ea, n, base):
"""
Convert operand to an offset
(for the explanations of 'ea' and 'n' please see OpBinary())
Example:
========
seg000:2000 dw 1234h
and there is a segment at paragraph 0x1000 and there is a data item
within the segment at 0x1234:
seg000:1234 MyString db 'Hello, world!',0
Then you need to specify a linear address of the segment base to
create a proper offset:
OpOff(["seg000",0x2000],0,0x10000);
and you will have:
seg000:2000 dw offset MyString
Motorola 680x0 processor have a concept of "outer offsets".
If you want to create an outer offset, you need to combine number
of the operand with the following bit:
Please note that the outer offsets are meaningful only for
Motorola 680x0.
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
@param base: base of the offset as a linear address
If base == BADADDR then the current operand becomes non-offset
"""
return idaapi.set_offset(ea, n, base)
OPND_OUTER = idaapi.OPND_OUTER # outer offset base
def OpOffEx(ea, n, reftype, target, base, tdelta):
"""
Convert operand to a complex offset expression
This is a more powerful version of OpOff() function.
It allows to explicitly specify the reference type (off8,off16, etc)
and the expression target with a possible target delta.
The complex expressions are represented by IDA in the following form:
target + tdelta - base
If the target is not present, then it will be calculated using
target = operand_value - tdelta + base
The target must be present for LOW.. and HIGH.. reference types
@param ea: linear address of the instruction/data
@param n: number of operand to convert (the same as in OpOff)
@param reftype: one of REF_... constants
@param target: an explicitly specified expression target. if you don't
want to specify it, use -1. Please note that LOW... and
HIGH... reference type requre the target.
@param base: the offset base (a linear address)
@param tdelta: a displacement from the target which will be displayed
in the expression.
@return: success (boolean)
"""
return idaapi.op_offset(ea, n, reftype, target, base, tdelta)
REF_OFF8 = idaapi.REF_OFF8 # 8bit full offset
REF_OFF16 = idaapi.REF_OFF16 # 16bit full offset
REF_OFF32 = idaapi.REF_OFF32 # 32bit full offset
REF_LOW8 = idaapi.REF_LOW8 # low 8bits of 16bit offset
REF_LOW16 = idaapi.REF_LOW16 # low 16bits of 32bit offset
REF_HIGH8 = idaapi.REF_HIGH8 # high 8bits of 16bit offset
REF_HIGH16 = idaapi.REF_HIGH16 # high 16bits of 32bit offset
REF_VHIGH = idaapi.REF_VHIGH # high ph.high_fixup_bits of 32bit offset (processor dependent)
REF_VLOW = idaapi.REF_VLOW # low (32-ph.high_fixup_bits) of 32bit offset (processor dependent)
REF_OFF64 = idaapi.REF_OFF64 # 64bit full offset
REFINFO_RVA = 0x10 # based reference (rva)
REFINFO_PASTEND = 0x20 # reference past an item it may point to an nonexistitng
# do not destroy alignment dirs
REFINFO_NOBASE = 0x80 # offset base is a number
# that base have be any value
# nb: base xrefs are created only if base
# points to the middle of a segment
REFINFO_SUBTRACT = 0x0100 # the reference value is subtracted from
# the base value instead of (as usual)
# being added to it
REFINFO_SIGNEDOP = 0x0200 # the operand value is sign-extended (only
# supported for REF_OFF8/16/32/64)
def OpSeg(ea, n):
"""
Convert operand to a segment expression
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.op_seg(ea, n)
def OpNumber(ea, n):
"""
Convert operand to a number (with default number base, radix)
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.op_num(ea, n)
def OpFloat(ea, n):
"""
Convert operand to a floating-point number
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
@return: 1-ok, 0-failure
"""
return idaapi.op_flt(ea, n)
def OpAlt(ea, n, opstr):
"""
Specify operand represenation manually.
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
@param opstr: a string represenation of the operand
@note: IDA will not check the specified operand, it will simply display
it instead of the orginal representation of the operand.
"""
return idaapi.set_forced_operand(ea, n, opstr)
def OpSign(ea, n):
"""
Change sign of the operand
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.toggle_sign(ea, n)
def OpNot(ea, n):
"""
Toggle the bitwise not operator for the operand
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
idaapi.toggle_bnot(ea, n)
return True
def OpEnumEx(ea, n, enumid, serial):
"""
Convert operand to a symbolic constant
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
@param enumid: id of enumeration type
@param serial: serial number of the constant in the enumeration
The serial numbers are used if there are more than
one symbolic constant with the same value in the
enumeration. In this case the first defined constant
get the serial number 0, then second 1, etc.
There could be 256 symbolic constants with the same
value in the enumeration.
"""
return idaapi.op_enum(ea, n, enumid, serial)
def OpStroffEx(ea, n, strid, delta):
"""
Convert operand to an offset in a structure
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
@param strid: id of a structure type
@param delta: struct offset delta. usually 0. denotes the difference
between the structure base and the pointer into the structure.
"""
path = idaapi.tid_array(1)
path[0] = strid
return idaapi.op_stroff(ea, n, path.cast(), 1, delta)
def OpStkvar(ea, n):
"""
Convert operand to a stack variable
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
"""
return idaapi.op_stkvar(ea, n)
def OpHigh(ea, n, target):
"""
Convert operand to a high offset
High offset is the upper 16bits of an offset.
This type is used by TMS320C6 processors (and probably by other
RISC processors too)
@param ea: linear address
@param n: number of operand
- 0 - the first operand
- 1 - the second, third and all other operands
- -1 - all operands
@param target: the full value (all 32bits) of the offset
"""
return idaapi.op_offset(ea, n, idaapi.REF_HIGH16, target)
def MakeVar(ea):
"""
Mark the location as "variable"
@param ea: address to mark
@return: None
@note: All that IDA does is to mark the location as "variable".
Nothing else, no additional analysis is performed.
This function may disappear in the future.
"""
idaapi.doVar(ea, 1)
def ExtLinA(ea, n, line):
"""
Specify an additional line to display before the generated ones.
@param ea: linear address
@param n: number of anterior additional line (0..MAX_ITEM_LINES)
@param line: the line to display
@return: None
@note: IDA displays additional lines from number 0 up to the first unexisting
additional line. So, if you specify additional line #150 and there is no
additional line #149, your line will not be displayed. MAX_ITEM_LINES is
defined in IDA.CFG
"""
idaapi.update_extra_cmt(ea, idaapi.E_PREV + n, line)
idaapi.doExtra(ea)
def ExtLinB(ea, n, line):
"""
Specify an additional line to display after the generated ones.
@param ea: linear address
@param n: number of posterior additional line (0..MAX_ITEM_LINES)
@param line: the line to display
@return: None
@note: IDA displays additional lines from number 0 up to the first
unexisting additional line. So, if you specify additional line #150
and there is no additional line #149, your line will not be displayed.
MAX_ITEM_LINES is defined in IDA.CFG
"""
idaapi.update_extra_cmt(ea, idaapi.E_NEXT + n, line)
idaapi.doExtra(ea)
def DelExtLnA(ea, n):
"""
Delete an additional anterior line
@param ea: linear address
@param n: number of anterior additional line (0..500)
@return: None
"""
idaapi.del_extra_cmt(ea, idaapi.E_PREV + n)
def DelExtLnB(ea, n):
"""
Delete an additional posterior line
@param ea: linear address
@param n: number of posterior additional line (0..500)
@return: None
"""
idaapi.del_extra_cmt(ea, idaapi.E_NEXT + n)
def SetManualInsn(ea, insn):
"""
Specify instruction represenation manually.
@param ea: linear address
@param insn: a string represenation of the operand
@note: IDA will not check the specified instruction, it will simply
display it instead of the orginal representation.
"""
return idaapi.set_manual_insn(ea, insn)
def GetManualInsn(ea):
"""
Get manual representation of instruction
@param ea: linear address
@note: This function returns value set by SetManualInsn earlier.
"""
return idaapi.get_manual_insn(ea)
def PatchDbgByte(ea,value):
"""
Change a byte in the debugged process memory only
@param ea: address
@param value: new value of the byte
@return: 1 if successful, 0 if not
"""
return idaapi.put_dbg_byte(ea, value)
def PatchByte(ea, value):
"""
Change value of a program byte
If debugger was active then the debugged process memory will be patched too
@param ea: linear address
@param value: new value of the byte
@return: 1 if the database has been modified,
0 if either the debugger is running and the process' memory
has value 'value' at address 'ea',
or the debugger is not running, and the IDB
has value 'value' at address 'ea already.
"""
return idaapi.patch_byte(ea, value)
def PatchWord(ea, value):
"""
Change value of a program word (2 bytes)
@param ea: linear address
@param value: new value of the word
@return: 1 if the database has been modified,
0 if either the debugger is running and the process' memory
has value 'value' at address 'ea',
or the debugger is not running, and the IDB
has value 'value' at address 'ea already.
"""
return idaapi.patch_word(ea, value)
def PatchDword(ea, value):
"""
Change value of a double word
@param ea: linear address
@param value: new value of the double word
@return: 1 if the database has been modified,
0 if either the debugger is running and the process' memory
has value 'value' at address 'ea',
or the debugger is not running, and the IDB
has value 'value' at address 'ea already.
"""
return idaapi.patch_long(ea, value)
def PatchQword(ea, value):
"""
Change value of a quad word
@param ea: linear address
@param value: new value of the quad word
@return: 1 if the database has been modified,
0 if either the debugger is running and the process' memory
has value 'value' at address 'ea',
or the debugger is not running, and the IDB
has value 'value' at address 'ea already.
"""
return idaapi.patch_qword(ea, value)
def SetFlags(ea, flags):
"""
Set new value of flags
This function should not used be used directly if possible.
It changes properties of a program byte and if misused, may lead to
very-very strange results.
@param ea: adress
@param flags: new flags value
"""
return idaapi.setFlags(ea, flags)
def SetRegEx(ea, reg, value, tag):
"""
Set value of a segment register.
@param ea: linear address
@param reg: name of a register, like "cs", "ds", "es", etc.
@param value: new value of the segment register.
@param tag: of SR_... constants
@note: IDA keeps tracks of all the points where segment register change their
values. This function allows you to specify the correct value of a segment
register if IDA is not able to find the corrent value.
See also SetReg() compatibility macro.
"""
reg = idaapi.str2reg(reg);
if reg >= 0:
return idaapi.splitSRarea1(ea, reg, value, tag)
else:
return False
SR_inherit = 1 # value is inherited from the previous area
SR_user = 2 # value is specified by the user
SR_auto = 3 # value is determined by IDA
SR_autostart = 4 # as SR_auto for segment starting address
def AutoMark2(start, end, queuetype):
"""
Plan to perform an action in the future.
This function will put your request to a special autoanalysis queue.
Later IDA will retrieve the request from the queue and process
it. There are several autoanalysis queue types. IDA will process all
queries from the first queue and then switch to the second queue, etc.
"""
return idaapi.auto_mark_range(start, end, queuetype)
def AutoUnmark(start, end, queuetype):
"""
Remove range of addresses from a queue.
"""
return idaapi.autoUnmark(start, end, queuetype)
def AutoMark(ea,qtype):
"""
Plan to analyze an address
"""
return AutoMark2(ea,ea+1,qtype)
AU_UNK = idaapi.AU_UNK # make unknown
AU_CODE = idaapi.AU_CODE # convert to instruction
AU_PROC = idaapi.AU_PROC # make function
AU_USED = idaapi.AU_USED # reanalyze
AU_LIBF = idaapi.AU_LIBF # apply a flirt signature (the current signature!)
AU_FINAL = idaapi.AU_FINAL # coagulate unexplored items
#----------------------------------------------------------------------------
# P R O D U C E O U T P U T F I L E S
#----------------------------------------------------------------------------
def GenerateFile(filetype, path, ea1, ea2, flags):
"""
Generate an output file
@param filetype: type of output file. One of OFILE_... symbols. See below.
@param path: the output file path (will be overwritten!)
@param ea1: start address. For some file types this argument is ignored
@param ea2: end address. For some file types this argument is ignored
@param flags: bit combination of GENFLG_...
@returns: number of the generated lines.
-1 if an error occured
OFILE_EXE: 0-can't generate exe file, 1-ok
"""
f = idaapi.fopenWT(path)
if f:
retval = idaapi.gen_file(filetype, f, ea1, ea2, flags)
idaapi.eclose(f)
return retval
else:
return -1
# output file types:
OFILE_MAP = idaapi.OFILE_MAP
OFILE_EXE = idaapi.OFILE_EXE
OFILE_IDC = idaapi.OFILE_IDC
OFILE_LST = idaapi.OFILE_LST
OFILE_ASM = idaapi.OFILE_ASM
OFILE_DIF = idaapi.OFILE_DIF
# output control flags:
GENFLG_MAPSEG = idaapi.GENFLG_MAPSEG # map: generate map of segments
GENFLG_MAPNAME = idaapi.GENFLG_MAPNAME # map: include dummy names
GENFLG_MAPDMNG = idaapi.GENFLG_MAPDMNG # map: demangle names
GENFLG_MAPLOC = idaapi.GENFLG_MAPLOC # map: include local names
GENFLG_IDCTYPE = idaapi.GENFLG_IDCTYPE # idc: gen only information about types
GENFLG_ASMTYPE = idaapi.GENFLG_ASMTYPE # asm&lst: gen information about types too
GENFLG_GENHTML = idaapi.GENFLG_GENHTML # asm&lst: generate html (gui version only)
GENFLG_ASMINC = idaapi.GENFLG_ASMINC # asm&lst: gen information only about types
def GenFuncGdl(outfile, title, ea1, ea2, flags):
"""
Generate a flow chart GDL file
@param outfile: output file name. GDL extension will be used
@param title: graph title
@param ea1: beginning of the area to flow chart
@param ea2: end of the area to flow chart.
@param flags: combination of CHART_... constants
@note: If ea2 == BADADDR then ea1 is treated as an address within a function.
That function will be flow charted.
"""
return idaapi.gen_flow_graph(outfile, title, None, ea1, ea2, flags)
CHART_PRINT_NAMES = 0x1000 # print labels for each block?
CHART_GEN_GDL = 0x4000 # generate .gdl file (file extension is forced to .gdl)
CHART_WINGRAPH = 0x8000 # call wingraph32 to display the graph
CHART_NOLIBFUNCS = 0x0400 # don't include library functions in the graph
def
IDA 6.8 python / idc.py
最新推荐文章于 2022-10-23 17:42:41 发布