
역공학을 위해 IDA와의 상호작용을 단순화하는 객체 지향 Python API로, 플러그인 개발과 디스어셈블리 분석 자동화를 가능하게 합니다.
Bip
Bip은 IDA와 상호작용하기 위해 Python 사용을 단순화하는 것을 목표로 하는 프로젝트입니다. 주요 목표는 IDA의 대화형 콘솔에서 Python 사용을 용이하게 하고 플러그인 작성을 돕는 것입니다. 더 일반적으로는 Python API를 통해 수행되는 반복적인 작업을 자동화하는 것이 목표입니다. Bip은 또한 더 객체 지향적이고 "python-like"한 API와 실제 문서를 제공하기 위해 개발되었습니다.
이 코드는 완전하지 않으며, 많은 기능이 아직 누락되어 있습니다. 개발은 사람들이 요청하는 것과 개발자들이 사용하는 것에 우선순위를 두므로, PR, Feature Request 및 Issues(문서 관련 포함)를 주저하지 말고 만들어 주세요.
문서는 RST 형식으로 제공되며(docs/ 디렉토리에서 sphinx를 사용하여 컴파일할 수 있습니다), 온라인 <https://synacktiv.github.io/bip/build/html/index.html>_으로도 제공됩니다.
이 설치는 Windows와 Linux에서만 테스트되었습니다: python install.py.
특정 폴더에 설치하려면 선택적 --dest 인수를 사용할 수 있습니다:
.. 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의 모든 함수와 객체는 doc string을 사용하여 문서화되므로 셸에서 도움말을 얻으려면 help(BipClass) 및 help(obj.bipmethod)를 사용하세요.
bip.base 모듈은 IDA와 인터페이스하기 위한 기본 기능의 대부분을 포함합니다. 실제로 이것은 주로 IDA의 디스어셈블러 부분으로, 다음을 포함합니다: 명령어, 함수, 기본 블록, 피연산자, 데이터, xrefs, 구조체, 타입 조작, ...
명령어 / 피연산자~~~~~~~~~~~~~~~~~~~~~~~
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
~~~~~~~