Bip
Bip 是一个旨在简化使用 python 与 IDA 交互的项目。其主要目标是方便在 IDA 的交互式控制台中使用 python 以及编写插件。更笼统地说,目标是自动化通过 python API 完成的重复性任务。Bip 的开发还旨在提供一种更加面向对象、更 "python-like" 的 API 以及一份 真正的 文档。
这段代码并不完整,仍有很多功能缺失。开发工作会优先考虑用户的需求以及开发者自身的使用需求,因此请毫不犹豫地提交 PR、Feature Request 和 Issues(包括针对文档的)。
文档以 RST 格式提供(可使用 sphinx 编译),位于 docs/ 目录中,也可 在线 <https://synacktiv.github.io/bip/build/html/index.html>_ 获取。
此安装仅在 Windows 和 Linux 上测试过:python install.py。
可以使用可选的 --dest 参数将 Bip 安装到特定文件夹:
.. code-block:: none
usage: install.py [-h] [--dest DEST]
optional arguments:
-h, --help show this help message and exit
--dest DEST Destination folder where to install Bip
此安装程序默认不会安装任何插件,仅安装 Bip 的核心。默认目标文件夹是 IDA 本地使用的文件夹(Windows 为 %APPDATA%\Hex-Rays\IDA Pro\,Linux 和 MacOSX 为 $HOME/.idapro)。
本概述旨在展示最常见的操作方式,远非完整。Bip 中的所有函数和对象都通过 docstring 记录,因此只需在 shell 中使用 help(BipClass) 和 help(obj.bipmethod) 即可获取文档。
模块 bip.base 包含与 IDA 交互的大部分 基础 功能。实际上,这主要是 IDA 的反汇编部分,包括:指令、函数、基本块、操作数、数据、交叉引用、结构、类型等的操作。
指令 / 操作数~~~~~~~~~~~~~~~~~~~~~~~
The classes bip.base.BipInstr and bip.base.BipOperand:
.. code-block:: pycon
>>> from bip.base import *
>>> i = BipInstr() # BipInstr is the base class for representing an instruction
>>> i # by default the address on the screen is taken
BipInstr: 0x1800D324B (mov rcx, r13)
>>> i2 = BipInstr(0x01800D3242) # pass the address in argument
>>> i2
BipInstr: 0x1800D3242 (mov r8d, 8)
>>> i2.next # access next instruction, previous with i2.prev
BipInstr: 0x1800D3248 (mov rdx, r14)
>>> l = [i3 for i3 in BipInstr.iter_all()] # l contains the list of all BipInstruction of the database, iter_all produces a generator object
>>> i.ea # access the address
6443315787
>>> i.mnem # mnemonic representation
mov
>>> i.ops # access to the operands
[<bip.base.operand.BipOperand object at 0x0000022B0291DA90>, <bip.base.operand.BipOperand object at 0x0000022B0291DA58>]
>>> i.ops[0].str # string representation of an operand
rcx
>>> i.bytes # bytes in the instruction
[73L, 139L, 205L]
>>> i.size # number of bytes of this instruction
3
>>> i.comment = "hello" # set a comment, rcomment for the repeatable comments
>>> i
BipInstr: 0x1800D324B (mov rcx, r13; hello)
>>> i.comment # get a comment
hello
>>> i.func # access to the function
Func: RtlQueryProcessLockInformation (0x1800D2FF0)
>>> i.block # access to basic block
BipBlock: 0x1800D3242 (from Func: RtlQueryProcessLockInformation (0x1800D2FF0))
Function / Basic block
The classes ``bip.base.BipFunction`` and ``bip.base.BipBlock``:
.. code-block:: pycon
>>> from bip.base import *
>>> f = BipFunction() # Get the function, screen address used if not provided
>>> f
Func: RtlQueryProcessLockInformation (0x1800D2FF0)
>>> f2 = BipFunction(0x0018010E975) # provide an address, not necessary the first one
>>> f2
Func: sub_18010E968 (0x18010E968)
>>> f == f2 # compare two functions
False
>>> f == BipFunction(0x001800D3021)
True
>>> hex(f.ea) # start address
0x1800d2ff0L
>>> hex(f.end) # end address
0x1800d3284L
>>> f = BipFunction.get_by_name("RtlQueryProcessLockInformation") # fetch the function from its name
>>> f.name # get and set the name
RtlQueryProcessLockInformation
>>> f.name = "test"
>>> f.name
test
>>> f.size # number of bytes in the function
660
>>> f.bytes # bytes of the function
[72L, ..., 255L]
>>> f.callees # list of functions called by this function
[<bip.base.func.BipFunction object at 0x0000022B0291DD30>, ..., <bip.base.func.BipFunction object at 0x0000022B045487F0>]
>>> f.callers # list of functions which call this function
[<bip.base.func.BipFunction object at 0x0000022B04544048>]
>>> f.instr # list of instructions in the function
[<bip.base.instr.BipInstr object at 0x0000022B0291DB00>, ..., <bip.base.instr.BipInstr object at 0x0000022B0454D080>]
>>> f.comment = "welcome to bip" # comment of the function, rcomment for repeatable ones
>>> f.comment
welcome to bip
>>> f.does_return # does this function return ?
True
>>> BipFunction.iter_all() # allows to iter on all functions defined in the database
<generator object iter_all at 0x0000022B029231F8>
>>> f.nb_blocks # number of basic blocks
33
>>> f.blocks # list of blocks
[<bip.base.block.BipBlock object at 0x0000022B04544D68>, ..., <bip.base.block.BipBlock object at 0x0000022B04552240>]
>>> f.blocks[5] # access the basic block 5, could be done with BipBlock(addr)
BipBlock: 0x1800D306E (from Func: test (0x1800D2FF0))
>>> f.blocks[5].func # link back to the function
Func: test (0x1800D2FF0)
>>> f.blocks[5].instr # list of instructions in the block
[<bip.base.instr.BipInstr object at 0x0000022B04544710>, ..., <bip.base.instr.BipInstr object at 0x0000022B0291DB00>]
>>> f.blocks[5].pred # predecessor blocks, blocks where control flow lead to this one
[<bip.base.block.BipBlock object at 0x0000022B04544D68>]
>>> f.blocks[5].succ # successor blocks
[<bip.base.block.BipBlock object at 0x0000022B04544710>, <bip.base.block.BipBlock object at 0x0000022B04544438>]
>>> f.blocks[5].is_ret # is this block containing a return
False
Data
~~~~
The class ``bip.base.BipData``:
.. code-block:: pycon
>>> from bip.base import *
>>> d = BipData(0x000180110068) # .rdata:0000000180110068 bip_ex dq offset unk_180110DE0
>>> d
BipData at 0x180110068 = 0x180110DE0 (size=8)
>>> d.name # Name of the symbol if any
bip_ex
>>> d.is_word # is it a word
False
>>> d.is_qword # is it a qword
True
>>> hex(d.value) # value at that address, this take into account the basic type (byte, word, dword, qword) defined in IDA
0x180110de0L
>>> hex(d.ea) # address
0x180110068L
>>> d.comment = "example" # comment as before
>>> d.comment
example
>>> d.value = 0xAABBCCDD # change the value
>>> hex(d.value)
0xaabbccddL
>>> d.bytes # get the bytes, as before
[221L, 204L, 187L, 170L, 0L, 0L, 0L, 0L]
>>> hex(d.original_value) # get the original value before modification
0x180110de0L
>>> d.bytes = [0x11, 0x22, 0x33, 0x44, 0, 0, 0, 0] # patch the bytes
>>> hex(d.value) # get the value
0x44332211L
>>> BipData.iter_heads() # iter on "heads" of the IDB, heads are defined data in the IDB
<generator object iter_heads at 0x0000022B02923240>
>>> hex(BipData.get_dword(0x0180110078)) # staticmethod for reading value at an address
0x60004L
>>> BipData.set_byte(0x0180110078, 0xAA) # static method for modifying a value at an address
>>> hex(BipData.get_qword(0x0180110078))
0x600aaL
Element
~~~~~~~
In Bip most basic objects inherit from the same classes: ``BipBaseElt`` which is
the most basic one, ``BipRefElt`` which includes all the objects which can have
xrefs (including structures (``BipStruct``) and structure members
(``BStructMember``), see below), ``BipElt``
which represents all elements which have an address in the IDA DataBase (idb),
including ``BipData`` and ``BipInstr`` (it is this class which
implements the properties: ``comment``, ``name``, ``bytes``, ...).
It is possible to use the functions ``GetElt`` and ``GetEltByName``
to get the right basic element from an address or a name
representing a location in the binary.
.. code-block:: pycon
~~~~~~~