GitHubじゃ!Pythonじゃ!

GitHubからPython関係の優良リポジトリを探したかったのじゃー、でも英語は出来ないから日本語で読むのじゃー、英語社会世知辛いのじゃー

cea-sec

miasm – Pythonでのリバースエンジニアリングフレームワーク

投稿日:

Pythonでのリバースエンジニアリングフレームワーク

Pythonでのリバースエンジニアリングフレームワーク

目次

ミアムとは何ですか?

Miasmは、フリーでオープンソースの(GPLv2)リバースエンジニアリングフレームワークです。 Miasmはバイナリプログラムの解析/修正/生成を目指しています。 ここには網羅的ではない機能のリストがあります:

  • Elfesteemを使用したPE / ELF 32/64 LE / BEのオープン/変更/生成
  • X86 / ARM / MIPS / SH4 / MSP430のアセンブル/ディスアセンブル
  • 中間言語を用いたアセンブリ意味の表現
  • JITを使用したエミュレーション(動的コード解析、アンパック、…)
  • 自動解読不能化のための式の簡素化

例とデモの詳細については、公式ブログを参照してください。

基本的な例

アセンブル/ディスアセンブル

Miasm x86アーキテクチャをインポートする:

>>> from miasm2.arch.x86.arch import mn_x86

ラインを組み立てる:

>>> l = mn_x86.fromstring('XOR ECX, ECX', 32)
>>> print l
XOR        ECX, ECX
>>> mn_x86.asm(l)
['1\xc9', '3\xc9', 'g1\xc9', 'g3\xc9']

オペランドを変更する:

>>> l.args[0] = mn_x86.regs.EAX
>>> print l
XOR        EAX, ECX
>>> a = mn_x86.asm(l)
>>> print a
['1\xc8', '3\xc1', 'g1\xc8', 'g3\xc1']

結果を逆アセンブルします。

>>> print mn_x86.dis(a[0], 32)
XOR        EAX, ECX

Machine抽象化の使用:

>>> from miasm2.analysis.machine import Machine
>>> mn = Machine('x86_32').mn
>>> print mn.dis('\x33\x30', 32)
XOR        ESI, DWORD PTR [EAX]

Mipsの場合:

>>> mn = Machine('mips32b').mn
>>> print  mn.dis('97A30020'.decode('hex'), "b")
LHU        V1, 0x20(SP)

中間表現

命令を作成する:

>>> machine = Machine('arml')
>>> l = machine.mn.dis('002088e0'.decode('hex'), 'l')
>>> print l
ADD        R2, R8, R0

中間表現(IR)オブジェクトを作成する:

>>> ira = machine.ira()

プールに命令を追加する:

>>> ira.add_instr(l)

現在のプールを印刷する:

>>> for lbl, b in ira.blocs.items():
...     print b
...
loc_0000000000000000:0x00000000

        R2 = (R8+R0)

        IRDst = loc_0000000000000004:0x00000004

例えば、副作用を起こしてIRを扱う:

>>> from miasm2.expression.expression import get_rw
>>> for lbl, b in ira.blocs.items():
...     for irs in b.irs:
...         o_r, o_w = get_rw(irs)
...         print 'read:   ', [str(x) for x in o_r]
...         print 'written:', [str(x) for x in o_w]
...         print
...
read:    ['R8', 'R0']
written: ['R2']

read:    ['loc_0000000000000004:0x00000004']
written: ['IRDst']

エミュレーション

シェルコードを与える:

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 = '\x8dI\x04\x8d[\x01\x80\xf9\x01t\x05\x8d[\xff\xeb\x03\x8d[\x01\x89\xd8\xc3'

Container抽象化によってシェルコードをインポートする:

>>> from miasm2.analysis.binary import Container
>>> c = Container.from_string(s)
>>> c
<miasm2.analysis.binary.ContainerUnknown object at 0x7f34cefe6090>

アドレス0のシェルコードを逆アセンブルする:

>>> from miasm2.analysis.machine import Machine
>>> machine = Machine('x86_32')
>>> mdis = machine.dis_engine(c.bin_stream)
>>> blocs = mdis.dis_multiblock(0)
>>> for b in blocs:
...  print b
...
loc_0000000000000000:0x00000000
LEA        ECX, DWORD PTR [ECX+0x4]
LEA        EBX, DWORD PTR [EBX+0x1]
CMP        CL, 0x1
JZ         loc_0000000000000010:0x00000010
->      c_next:loc_000000000000000B:0x0000000b  c_to:loc_0000000000000010:0x00000010
loc_0000000000000010:0x00000010
LEA        EBX, DWORD PTR [EBX+0x1]
->      c_next:loc_0000000000000013:0x00000013
loc_000000000000000B:0x0000000b
LEA        EBX, DWORD PTR [EBX+0xFFFFFFFF]
JMP        loc_0000000000000013:0x00000013
->      c_to:loc_0000000000000013:0x00000013
loc_0000000000000013:0x00000013
MOV        EAX, EBX
RET
>>>

Jitエンジンをスタックで初期化する:

>>> jitter = machine.jitter(jit_type='python')
>>> jitter.init_stack()

任意のメモリ位置にシェルコードを追加する:

>>> run_addr = 0x40000000
>>> myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, s)

シェルコードの戻り値をキャッチするためにセンチネルを作成する:

def code_sentinelle(jitter):
    jitter.run = False
    jitter.pc = 0
    return True

>>> jitter.add_breakpoint(0x1337beef, code_sentinelle)
>>> jitter.push_uint32_t(0x1337beef)

アクティブなログ:

>>> jitter.jit.log_regs = True
>>> jitter.jit.log_mn = True

任意のアドレスで実行:

>>> 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プールの初期化:

>>> ira = machine.ira()
>>> for b in blocs:
...    ira.add_bloc(b)
...

デフォルトの記号値でエンジンを初期化する:

>>> from miasm2.ir.symbexec import symbexec
>>> sb = symbexec(ira, machine.mn.regs.regs_init)

実行を開始する:

>>> symbolic_pc = sb.emul_ir_blocs(ira, 0)
>>> print symbolic_pc
((ECX_init+0x4)[0:8]+0xFF)?(0xB,0x10)

ステップ・ログと同じです(変更のみが表示されます)。

>>> sb = symbexec(ira, machine.mn.regs.regs_init)
>>> symbolic_pc = sb.emul_ir_blocs(ira, 0, step=True)
________________________________________________________________________________
ECX (ECX_init+0x4)
________________________________________________________________________________
ECX (ECX_init+0x4)
EBX (EBX_init+0x1)
________________________________________________________________________________
zf ((ECX_init+0x4)[0:8]+0xFF)?(0x0,0x1)
nf ((ECX_init+0x4)[0:8]+0xFF)[7:8]
pf (parity ((ECX_init+0x4)[0:8]+0xFF))
of ((((ECX_init+0x4)[0:8]+0xFF)^(ECX_init+0x4)[0:8])&((ECX_init+0x4)[0:8]^0x1))[7:8]
cf (((((ECX_init+0x4)[0:8]+0xFF)^(ECX_init+0x4)[0:8])&((ECX_init+0x4)[0:8]^0x1))^((ECX_init+0x4)[0:8]+0xFF)^(ECX_init+0x4)[0:8]^0x1)[7:8]
af (((ECX_init+0x4)[0:8]+0xFF)&0x10)?(0x1,0x0)
ECX (ECX_init+0x4)
EBX (EBX_init+0x1)
________________________________________________________________________________
IRDst ((ECX_init+0x4)[0:8]+0xFF)?(0xB,0x10)
zf ((ECX_init+0x4)[0:8]+0xFF)?(0x0,0x1)
nf ((ECX_init+0x4)[0:8]+0xFF)[7:8]
pf (parity ((ECX_init+0x4)[0:8]+0xFF))
of ((((ECX_init+0x4)[0:8]+0xFF)^(ECX_init+0x4)[0:8])&((ECX_init+0x4)[0:8]^0x1))[7:8]
cf (((((ECX_init+0x4)[0:8]+0xFF)^(ECX_init+0x4)[0:8])&((ECX_init+0x4)[0:8]^0x1))^((ECX_init+0x4)[0:8]+0xFF)^(ECX_init+0x4)[0:8]^0x1)[7:8]
af (((ECX_init+0x4)[0:8]+0xFF)&0x10)?(0x1,0x0)
EIP ((ECX_init+0x4)[0:8]+0xFF)?(0xB,0x10)
ECX (ECX_init+0x4)
EBX (EBX_init+0x1)

具体的なECXで実行を再試行してください。 ここで、シンボリック/コンコードの実行はシェルコードの終わりに達します:

>>> from miasm2.expression.expression import ExprInt32
>>> sb.symbols[machine.mn.regs.ECX] = ExprInt32(-3)
>>> symbolic_pc = sb.emul_ir_blocs(ira, 0, step=True)
________________________________________________________________________________
ECX 0x1
________________________________________________________________________________
ECX 0x1
EBX (EBX_init+0x1)
________________________________________________________________________________
zf 0x1
nf 0x0
pf 0x1
of 0x0
cf 0x0
af 0x0
ECX 0x1
EBX (EBX_init+0x1)
________________________________________________________________________________
IRDst 0x10
zf 0x1
nf 0x0
pf 0x1
of 0x0
cf 0x0
af 0x0
EIP 0x10
ECX 0x1
EBX (EBX_init+0x1)
________________________________________________________________________________
IRDst 0x10
zf 0x1
nf 0x0
pf 0x1
of 0x0
cf 0x0
af 0x0
EIP 0x10
ECX 0x1
EBX (EBX_init+0x2)
________________________________________________________________________________
IRDst 0x13
zf 0x1
nf 0x0
pf 0x1
of 0x0
cf 0x0
af 0x0
EIP 0x10
ECX 0x1
EBX (EBX_init+0x2)
________________________________________________________________________________
IRDst 0x13
zf 0x1
nf 0x0
pf 0x1
of 0x0
cf 0x0
af 0x0
EIP 0x10
EAX (EBX_init+0x2)
ECX 0x1
EBX (EBX_init+0x2)
________________________________________________________________________________
IRDst @32[ESP_init]
zf 0x1
nf 0x0
pf 0x1
of 0x0
cf 0x0
af 0x0
EIP @32[ESP_init]
EAX (EBX_init+0x2)
ECX 0x1
EBX (EBX_init+0x2)
ESP (ESP_init+0x4)
>>> print symbolic_pc
@32[ESP_init]
>>> sb.dump_id()
IRDst @32[ESP_init]
zf 0x1
nf 0x0
pf 0x1
of 0x0
cf 0x0
af 0x0
EIP @32[ESP_init]
EAX (EBX_init+0x2)
ECX 0x1
EBX (EBX_init+0x2)
ESP (ESP_init+0x4)

どのように機能するのですか?

Miasmは、独自の逆アセンブラ、中間言語、命令セマンティックを組み込みます。 これはPythonで書かれています。

コードをエミュレートするために、LibTCC、LLVM、GCC、ClangまたはPythonを使用して、中間表現をJITします。 シェルコードとバイナリの全部または一部をエミュレートできます。 実行と対話するために、例えばライブラリ関数のエフェクトをエミュレートするために、Pythonコールバックを実行することができます。

ドキュメンテーション

TODO

ここでは自動生成されたドキュメントが利用できます

重度を得る

ソフトウェア要件

Miasmは以下を使用します。

  • python-pyparsing
  • python-dev
  • エルフェシュテームからのエルフェシュテーム
  • オプションでpython-pycparser(バージョン> = 2.17)

コードJITを有効にするには、次のいずれかのモジュールが必須です。

‘optional’ Miasmは以下を使用することもできます:

構成

  • インストールelfesteem
git clone https://github.com/serpilliere/elfesteem.git elfesteem
cd elfesteem
python setup.py build
sudo python setup.py install

ジッタを使用するには、GCC、TCCまたはLLVMを推奨します

  • GCC(任意のバージョン)
  • Clang(任意のバージョン)
  • LibTCCは--disable-staticオプションで設定する必要があります
    • 競合を避けるためにlibtcc-devをシステムから削除してください
    • クローンTinyCCgit clone http://repo.or.cz/tinycc.git
    • バージョン0.9.26にブランチを設定してください: cd tinycc/git checkout release_0_9_26
    • ./configure --disable-static
    • make
    • sudo make install
    • ドキュメントの生成にエラーがある可能性があります
  • LLVM
    • Debian(テスト/不安定):テストされていません
    • Debian stable / Ubuntu / Kali / whatever: pip install llvmliteまたはllvmliteからインストールする
    • Windows:テストされていない
  • Miasmのビルドとインストール:
$ cd miasm_directory
$ python setup.py build
$ sudo python setup.py install

ジッタモジュールのコンパイル中に問題が発生すると、Miasmはエラーをスキップして対応するモジュールを無効にします(コンパイル出力を参照)。

Windows&IDA

MiasmのIDAプラグインのほとんどは、Miasmの機能性のサブセットを使用します。 それらを動作させる簡単な方法は次のものを追加することです:

  • elfesteemディレクトリとpyparsing.pyC:\...\IDA\python\またはpip install pyparsing elfesteem
  • miasm2/miasm2ディレクトリからC:\...\IDA\python\

JITter関連の機能を除くすべての機能を利用できます。 より完全なインストールについては、上記の段落を参照してください。

テスト

Miasmには一連の回帰テストが付属しています。 それらをすべて実行するには:

cd miasm_directory/test
python test_all.py

いくつかのオプションを指定することができます:

  • モノスレッド: -m
  • コードカバレッジ計測: -c
  • 高速テストのみ: -t long (長いテストを除く)

彼らはすでにMiasmを使用しています

ツール

  • シビル :機能の占いも
  • R2M2 :radias2プラグインとしてmiasm2を使用する
  • CGrex :CGCバイナリのターゲットパッチ
  • ethrie Ethereum EVMのリバースツール(対応するMiasm2アーキテクチャを使用)

ブログ投稿/論文/会議

書籍

その他

  • 男、miasmにrr0dとのリンクがありますか?
  • はい! 愚かなコードと醜いドキュメント。







-cea-sec
-, , , , , ,

執筆者: