Miasm은 무료 오픈 소스(GPLv2) 리버스 엔지니어링 프레임워크입니다. Miasm은 바이너리 프로그램을 분석/수정/생성하는 것을 목표로 합니다. 다음은 전체 기능 목록입니다.
더 많은 예제와 데모를 보려면 공식 블로그를 참조하세요.
Miasm x86 아키텍처 가져오기:
>>> from miasm.arch.x86.arch import mn_x86
>>> from miasm.core.locationdb import LocationDB
위치 DB를 얻으세요:
>>> 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에는 자체 디스어셈블러, 중간 언어 및 명령 의미 체계가 포함되어 있습니다. 파이썬으로 작성되었습니다.
코드를 에뮬레이트하기 위해 LLVM, GCC, Clang 또는 Python을 사용하여 중간 표현을 JIT합니다. 쉘코드와 바이너리 전체 또는 일부를 에뮬레이션할 수 있습니다. 예를 들어 라이브러리 함수 효과를 에뮬레이션하기 위해 Python 콜백을 실행하여 실행과 상호 작용할 수 있습니다.
일부 문서 리소스는 doc 폴더에서 사용할 수 있습니다.
자동 생성된 문서를 사용할 수 있습니다:
Miasm은 다음을 사용합니다.
코드 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
(긴 테스트 제외)