Miasm は、無料のオープンソース (GPLv2) リバース エンジニアリング フレームワークです。 Miasm はバイナリ プログラムを解析/変更/生成することを目的としています。以下は機能の完全なリストではありません:
その他の例やデモについては、公式ブログを参照してください。
Miasm x86 アーキテクチャをインポートします。
>>> from miasm.arch.x86.arch import mn_x86
>>> from miasm.core.locationdb import LocationDB
位置データベースを取得します。
>>> loc_db = LocationDB()
ラインを組み立てます:
>>> l = mn_x86.fromstring( ' XOR ECX, ECX ' , loc_db, 32 )
>>> print (l)
XOR ECX, ECX
>>> mn_x86.asm(l)
['1xc9', '3xc9', 'g1xc9', 'g3xc9']
オペランドを変更します。
>>> l.args[ 0 ] = mn_x86.regs. EAX
>>> print (l)
XOR EAX, ECX
>>> a = mn_x86.asm(l)
>>> print (a)
['1xc8', '3xc1', 'g1xc8', 'g3xc1']
結果を逆アセンブルします。
>>> print (mn_x86.dis(a[ 0 ], 32 ))
XOR EAX, ECX
Machine
抽象化の使用:
>>> from miasm.analysis.machine import Machine
>>> mn = Machine( ' x86_32 ' ).mn
>>> print (mn.dis( ' x33x30 ' , 32 ))
XOR ESI, DWORD PTR [EAX]
MIPS の場合:
>>> mn = Machine( ' mips32b ' ).mn
>>> print (mn.dis( b ' x97xa3x00 ' , " b " ))
LHU V1, 0x20(SP)
命令を作成します。
>>> machine = Machine( ' arml ' )
>>> instr = machine.mn.dis( ' x00 x88xe0 ' , ' l ' )
>>> print (instr)
ADD R2, R8, R0
中間表現オブジェクトを作成します。
>>> lifter = machine.lifter_model_call(loc_db)
空の ircfg を作成します。
>>> ircfg = lifter.new_ircfg()
命令をプールに追加します。
>>> lifter.add_instr_to_ircfg(instr, ircfg)
現在のプールを出力します:
>>> for lbl, irblock in ircfg.blocks.items():
... print (irblock)
loc_0:
R2 = R8 + R0
IRDst = loc_4
たとえば副作用を取得するなど、IR を操作します。
>>> for lbl, irblock in ircfg.blocks.items():
... for assignblk in irblock:
... rw = assignblk.get_rw()
... for dst, reads in rw.items():
... print ( ' read: ' , [ str (x) for x in reads])
... print ( ' written: ' , dst)
... print ()
...
read: ['R8', 'R0']
written: R2
read: []
written: IRDst
Miasm IR の詳細については、対応する Jupyter Notebook を参照してください。
シェルコードを与える:
00000000 8d4904 lea ecx, [ecx+0x4]
00000003 8d5b01 lea ebx, [ebx+0x1]
00000006 80f901 cmp cl, 0x1
00000009 7405 jz 0x10
0000000b 8d5bff lea ebx, [ebx-1]
0000000e eb03 jmp 0x13
00000010 8d5b01 lea ebx, [ebx+0x1]
00000013 89d8 mov eax, ebx
00000015 c3 ret
>>> s = b ' x8d I x04x8d [ x01x80xf9x01 t x05x8d [ xffxebx03x8d [ x01x89xd8xc3 '
Container
抽象化を利用してシェルコードをインポートします。
>>> from miasm.analysis.binary import Container
>>> c = Container.from_string(s, loc_db)
>>> c
アドレス0
のシェルコードを逆アセンブルします。
>>> from miasm.analysis.machine import Machine
>>> machine = Machine( ' x86_32 ' )
>>> mdis = machine.dis_engine(c.bin_stream, loc_db = loc_db)
>>> asmcfg = mdis.dis_multiblock( 0 )
>>> for block in asmcfg.blocks:
... print (block)
...
loc_0
LEA ECX, DWORD PTR [ECX + 0x4]
LEA EBX, DWORD PTR [EBX + 0x1]
CMP CL, 0x1
JZ loc_10
-> c_next:loc_b c_to:loc_10
loc_10
LEA EBX, DWORD PTR [EBX + 0x1]
-> c_next:loc_13
loc_b
LEA EBX, DWORD PTR [EBX + 0xFFFFFFFF]
JMP loc_13
-> c_to:loc_13
loc_13
MOV EAX, EBX
RET
スタックを使用して JIT エンジンを初期化します。
>>> jitter = machine.jitter(loc_db, jit_type = ' python ' )
>>> jitter.init_stack()
シェルコードを任意のメモリ場所に追加します。
>>> run_addr = 0x 40000000
>>> from miasm.jitter.csts import PAGE_READ , PAGE_WRITE
>>> jitter.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE , s)
シェルコードの戻りをキャッチするセンチネルを作成します。
def code_sentinelle ( jitter ):
jitter . running = False
jitter . pc = 0
return True
> >> jitter . add_breakpoint ( 0x1337beef , code_sentinelle )
> >> jitter . push_uint32_t ( 0x1337beef )
アクティブなログ:
>>> jitter.set_trace_log()
任意のアドレスで実行します。
>>> jitter.init_run(run_addr)
>>> jitter.continue_run()
RAX 0000000000000000 RBX 0000000000000000 RCX 0000000000000000 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000123FFF8 RBP 0000000000000000
zf 0000000000000000 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 0000000040000000
40000000 LEA ECX, DWORD PTR [ECX+0x4]
RAX 0000000000000000 RBX 0000000000000000 RCX 0000000000000004 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000123FFF8 RBP 0000000000000000
zf 0000000000000000 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
....
4000000e JMP loc_0000000040000013:0x40000013
RAX 0000000000000000 RBX 0000000000000000 RCX 0000000000000004 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000123FFF8 RBP 0000000000000000
zf 0000000000000000 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 0000000040000013
40000013 MOV EAX, EBX
RAX 0000000000000000 RBX 0000000000000000 RCX 0000000000000004 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000123FFF8 RBP 0000000000000000
zf 0000000000000000 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 0000000040000013
40000015 RET
>>>
ジッターとの相互作用:
>>> jitter.vm
ad 1230000 size 10000 RW_ hpad 0x2854b40
ad 40000000 size 16 RW_ hpad 0x25e0ed0
>>> hex (jitter.cpu. EAX )
'0x0L'
>>> jitter.cpu. ESI = 12
IR プールの初期化:
>>> lifter = machine.lifter_model_call(loc_db)
>>> ircfg = lifter.new_ircfg_from_asmcfg(asmcfg)
デフォルトのシンボリック値を使用してエンジンを初期化します。
>>> from miasm.ir.symbexec import SymbolicExecutionEngine
>>> sb = SymbolicExecutionEngine(lifter)
実行の開始:
>>> symbolic_pc = sb.run_at(ircfg, 0 )
>>> print (symbolic_pc)
((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
ステップログも同様です(変更のみが表示されます)。
>>> sb = SymbolicExecutionEngine(lifter, machine.mn.regs.regs_init)
>>> symbolic_pc = sb.run_at(ircfg, 0 , step = True )
Instr LEA ECX, DWORD PTR [ECX + 0x4]
Assignblk:
ECX = ECX + 0x4
________________________________________________________________________________
ECX = ECX + 0x4
________________________________________________________________________________
Instr LEA EBX, DWORD PTR [EBX + 0x1]
Assignblk:
EBX = EBX + 0x1
________________________________________________________________________________
EBX = EBX + 0x1
ECX = ECX + 0x4
________________________________________________________________________________
Instr CMP CL, 0x1
Assignblk:
zf = (ECX[0:8] + -0x1)?(0x0,0x1)
nf = (ECX[0:8] + -0x1)[7:8]
pf = parity((ECX[0:8] + -0x1) & 0xFF)
of = ((ECX[0:8] ^ (ECX[0:8] + -0x1)) & (ECX[0:8] ^ 0x1))[7:8]
cf = (((ECX[0:8] ^ 0x1) ^ (ECX[0:8] + -0x1)) ^ ((ECX[0:8] ^ (ECX[0:8] + -0x1)) & (ECX[0:8] ^ 0x1)))[7:8]
af = ((ECX[0:8] ^ 0x1) ^ (ECX[0:8] + -0x1))[4:5]
________________________________________________________________________________
af = (((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[4:5]
pf = parity((ECX + 0x4)[0:8] + 0xFF)
zf = ((ECX + 0x4)[0:8] + 0xFF)?(0x0,0x1)
ECX = ECX + 0x4
of = ((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1))[7:8]
nf = ((ECX + 0x4)[0:8] + 0xFF)[7:8]
cf = (((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1)) ^ ((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[7:8]
EBX = EBX + 0x1
________________________________________________________________________________
Instr JZ loc_key_1
Assignblk:
IRDst = zf?(loc_key_1,loc_key_2)
EIP = zf?(loc_key_1,loc_key_2)
________________________________________________________________________________
af = (((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[4:5]
EIP = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
pf = parity((ECX + 0x4)[0:8] + 0xFF)
IRDst = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
zf = ((ECX + 0x4)[0:8] + 0xFF)?(0x0,0x1)
ECX = ECX + 0x4
of = ((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1))[7:8]
nf = ((ECX + 0x4)[0:8] + 0xFF)[7:8]
cf = (((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1)) ^ ((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[7:8]
EBX = EBX + 0x1
________________________________________________________________________________
>>>
具体的な ECX を使用して実行を再試行します。ここで、シンボリック/コンコリック実行はシェルコードの最後に到達します。
>>> from miasm.expression.expression import ExprInt
>>> sb.symbols[machine.mn.regs. ECX ] = ExprInt( - 3 , 32 )
>>> symbolic_pc = sb.run_at(ircfg, 0 , step = True )
Instr LEA ECX, DWORD PTR [ECX + 0x4]
Assignblk:
ECX = ECX + 0x4
________________________________________________________________________________
af = (((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[4:5]
EIP = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
pf = parity((ECX + 0x4)[0:8] + 0xFF)
IRDst = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
zf = ((ECX + 0x4)[0:8] + 0xFF)?(0x0,0x1)
ECX = 0x1
of = ((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1))[7:8]
nf = ((ECX + 0x4)[0:8] + 0xFF)[7:8]
cf = (((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1)) ^ ((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[7:8]
EBX = EBX + 0x1
________________________________________________________________________________
Instr LEA EBX, DWORD PTR [EBX + 0x1]
Assignblk:
EBX = EBX + 0x1
________________________________________________________________________________
af = (((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[4:5]
EIP = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
pf = parity((ECX + 0x4)[0:8] + 0xFF)
IRDst = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
zf = ((ECX + 0x4)[0:8] + 0xFF)?(0x0,0x1)
ECX = 0x1
of = ((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1))[7:8]
nf = ((ECX + 0x4)[0:8] + 0xFF)[7:8]
cf = (((((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8]) & ((ECX + 0x4)[0:8] ^ 0x1)) ^ ((ECX + 0x4)[0:8] + 0xFF) ^ (ECX + 0x4)[0:8] ^ 0x1)[7:8]
EBX = EBX + 0x2
________________________________________________________________________________
Instr CMP CL, 0x1
Assignblk:
zf = (ECX[0:8] + -0x1)?(0x0,0x1)
nf = (ECX[0:8] + -0x1)[7:8]
pf = parity((ECX[0:8] + -0x1) & 0xFF)
of = ((ECX[0:8] ^ (ECX[0:8] + -0x1)) & (ECX[0:8] ^ 0x1))[7:8]
cf = (((ECX[0:8] ^ 0x1) ^ (ECX[0:8] + -0x1)) ^ ((ECX[0:8] ^ (ECX[0:8] + -0x1)) & (ECX[0:8] ^ 0x1)))[7:8]
af = ((ECX[0:8] ^ 0x1) ^ (ECX[0:8] + -0x1))[4:5]
________________________________________________________________________________
af = 0x0
EIP = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
pf = 0x1
IRDst = ((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)
zf = 0x1
ECX = 0x1
of = 0x0
nf = 0x0
cf = 0x0
EBX = EBX + 0x2
________________________________________________________________________________
Instr JZ loc_key_1
Assignblk:
IRDst = zf?(loc_key_1,loc_key_2)
EIP = zf?(loc_key_1,loc_key_2)
________________________________________________________________________________
af = 0x0
EIP = 0x10
pf = 0x1
IRDst = 0x10
zf = 0x1
ECX = 0x1
of = 0x0
nf = 0x0
cf = 0x0
EBX = EBX + 0x2
________________________________________________________________________________
Instr LEA EBX, DWORD PTR [EBX + 0x1]
Assignblk:
EBX = EBX + 0x1
________________________________________________________________________________
af = 0x0
EIP = 0x10
pf = 0x1
IRDst = 0x10
zf = 0x1
ECX = 0x1
of = 0x0
nf = 0x0
cf = 0x0
EBX = EBX + 0x3
________________________________________________________________________________
Instr LEA EBX, DWORD PTR [EBX + 0x1]
Assignblk:
IRDst = loc_key_3
________________________________________________________________________________
af = 0x0
EIP = 0x10
pf = 0x1
IRDst = 0x13
zf = 0x1
ECX = 0x1
of = 0x0
nf = 0x0
cf = 0x0
EBX = EBX + 0x3
________________________________________________________________________________
Instr MOV EAX, EBX
Assignblk:
EAX = EBX
________________________________________________________________________________
af = 0x0
EIP = 0x10
pf = 0x1
IRDst = 0x13
zf = 0x1
ECX = 0x1
of = 0x0
nf = 0x0
cf = 0x0
EBX = EBX + 0x3
EAX = EBX + 0x3
________________________________________________________________________________
Instr RET
Assignblk:
IRDst = @32[ESP[0:32]]
ESP = {ESP[0:32] + 0x4 0 32}
EIP = @32[ESP[0:32]]
________________________________________________________________________________
af = 0x0
EIP = @32[ESP]
pf = 0x1
IRDst = @32[ESP]
zf = 0x1
ECX = 0x1
of = 0x0
nf = 0x0
cf = 0x0
EBX = EBX + 0x3
ESP = ESP + 0x4
EAX = EBX + 0x3
________________________________________________________________________________
>>>
Miasm には、独自の逆アセンブラ、中間言語、および命令セマンティクスが組み込まれています。 Python で書かれています。
コードをエミュレートするには、LLVM、GCC、Clang、または Python を使用して中間表現を JIT します。シェルコードとバイナリのすべてまたは一部をエミュレートできます。 Python コールバックを実行すると、ライブラリ関数の効果をエミュレートするなど、実行と対話することができます。
一部のドキュメント リソースは doc フォルダーで入手できます。
自動生成されたドキュメントが利用可能です。
ミアズムは以下を使用します。
コード JIT を有効にするには、次のモジュールのいずれかが必須です。
「オプション」Miasm は以下も使用できます。
ジッターを使用するには、GCC または LLVM を推奨します
pip install llvmlite
または llvmlite からインストール$ cd miasm_directory
$ python setup.py build
$ sudo python setup.py install
いずれかのジッター モジュールのコンパイル中に問題が発生した場合、Miasm はエラーをスキップし、対応するモジュールを無効にします (コンパイル出力を参照)。
Miasm の IDA プラグインのほとんどは、Miasm 機能のサブセットを使用します。これらを機能させる簡単な方法は、以下を追加することです。
pyparsing.py
をC:...IDApython
にコピーするか、 pip install pyparsing
miasm/miasm
ディレクトリをC:...IDApython
に追加JITter 関連を除くすべての機能が利用可能になります。より完全なインストールについては、上の段落を参照してください。
Miasm には一連の回帰テストが付属しています。すべてを実行するには:
cd miasm_directory/test
# Run tests using our own test runner
python test_all.py
# Run tests using standard frameworks (slower, require 'parameterized')
python -m unittest test_all.py # sequential, requires 'unittest'
python -m pytest test_all.py # sequential, requires 'pytest'
python -m pytest -n auto test_all.py # parallel, requires 'pytest' and 'pytest-xdist'
いくつかのオプションを指定できます。
-m
-c
-t long
(長いテストを除く)