¿Qué es Miasm?ÍndiceEjemplos básicos¿Cómo funciona?DocumentaciónObtención de MiasmPruebasYa usan Miasm - KolMitE

¿Qué es Miasm?ÍndiceEjemplos básicos¿Cómo funciona?DocumentaciónObtención de MiasmPruebasYa usan Miasm

¿Qué es Miasm?ÍndiceEjemplos básicos¿Cómo funciona?DocumentaciónObtención de MiasmPruebasYa usan Miasm

noviembre 9, 2022 Software en General 0

Estado de construcción
Estado de construcción
Pruebas de miasma
Código Clima
Únase al chat en https://gitter.im/cea-sec/miasm

¿Qué es el miasma?

Miasm es un marco de ingeniería inversa gratuito y de código abierto (GPLv2). Miasm tiene como objetivo analizar/modificar/generar programas binarios. Aquí hay una lista no exhaustiva de características:

  • Apertura / modificación / generación de PE / ELF 32 / 64 LE / BE
  • Montaje / Desmontaje X86 / ARM / MIPS / SH4 / MSP430
  • Representación de la semántica ensambladora utilizando un lenguaje intermedio
  • Emulando usando JIT (análisis de código dinámico, desempaquetado, …)
  • Simplificación de expresiones para la desofuscación automática

Consulte el blog oficial para obtener más ejemplos y demostraciones.

Tabla de contenido

  • ¿Qué es el miasma?
  • Ejemplos básicos
    • Montaje / Desmontaje
    • representación intermedia
    • Emulación
    • ejecución simbólica
  • ¿Como funciona?
  • Documentación
  • Obtención de miasma
    • Requisitos de Software
    • Configuración
    • Windows y AIF
  • Pruebas
  • Ya usan Miasm
  • Varios

Ejemplos básicos

Montaje / Desmontaje

Importar arquitectura Miasm x86:

>>> from miasm.arch.x86.arch import mn_x86
>>> from miasm.core.locationdb import LocationDB

Obtener una base de datos de ubicación:

>>> loc_db = LocationDB()

Montar una línea:

>>> l = mn_x86.fromstring('XOR ECX, ECX', loc_db, 32)
>>> print(l)
XOR        ECX, ECX
>>> mn_x86.asm(l)
['1xc9', '3xc9', 'g1xc9', 'g3xc9']

Modificar un operando:

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

Desmontar el resultado:

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

Usando Machine abstracción:

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

Para MIPS:

>>> mn = Machine('mips32b').mn
>>> print(mn.dis(b'x97xa3x00 ', "b"))
LHU        V1, 0x20(SP)

representación intermedia

Crear una instrucción:

>>> machine = Machine('arml')
>>> instr = machine.mn.dis('x00 x88xe0', 'l')
>>> print(instr)
ADD        R2, R8, R0

Cree un objeto de representación intermedia:

>>> lifter = machine.lifter_model_call(loc_db)

Crea un ircfg vacío:

>>> ircfg = lifter.new_ircfg()

Añadir instrucción a la piscina:

>>> lifter.add_instr_to_ircfg(instr, ircfg)

Imprimir grupo actual:

>>> for lbl, irblock in ircfg.blocks.items():
...     print(irblock)
loc_0:
R2 = R8 + R0

IRDst = loc_4

Trabajar con IR, por ejemplo, obteniendo efectos secundarios:

>>> 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

Más información sobre Miasm IR se encuentra en el Jupyter Notebook correspondiente.

Emulación

Dando un shellcode:

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'x8dyox04x8d[x01x80xf9x01tx05x8d[xffxebx03x8d[x01x89xd8xc3'

Import the shellcode thanks to the Container abstraction:

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

Disassembling the shellcode at address 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

Inicializando el motor JIT con una pila:

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

Agregue el shellcode en una ubicación de memoria arbitraria:

>>> run_addr = 0x40000000
>>> from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
>>> jitter.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, s)

Cree un centinela para capturar el retorno del código shell:

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

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

Registros activos:

>>> jitter.set_trace_log()

Ejecutar en una dirección arbitraria:

>>> 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
>>>

Interactuando con el jitter:

>>> 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

ejecución simbólica

Inicializando el grupo IR:

>>> lifter = machine.lifter_model_call(loc_db)
>>> ircfg = lifter.new_ircfg_from_asmcfg(asmcfg)

Inicializando el motor con valores simbólicos predeterminados:

>>> from miasm.ir.symbexec import SymbolicExecutionEngine
>>> sb = SymbolicExecutionEngine(lifter)

Lanzamiento de la ejecución:

>>> symbolic_pc = sb.run_at(ircfg, 0)
>>> print(symbolic_pc)
((ECX + 0x4)[0:8] + 0xFF)?(0xB,0x10)

Lo mismo, con registros de pasos (solo se muestran los cambios):

>>> 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
________________________________________________________________________________
>>>

Vuelva a intentar la ejecución con un ECX concreto. Aquí, la ejecución simbólica/concólica llega al final del shellcode:

>>> 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
________________________________________________________________________________
>>>

¿Como funciona?

Miasm incorpora su propio desensamblador, lenguaje intermedio y semántica de instrucción. Está escrito en Python.

Para emular código, utiliza LLVM, GCC, Clang o Python para JIT la representación intermedia. Puede emular shellcodes y todo o parte de binarios. Las devoluciones de llamada de Python se pueden ejecutar para interactuar con la ejecución, por ejemplo, para emular efectos de funciones de biblioteca.

Documentación

QUE HACER

Una documentación generada automáticamente está disponible:

  • doxígeno
  • pdoc

Obtención de miasma

  • Clona el repositorio: Miasm en GitHub
  • Obtenga una de las imágenes de Docker en Docker Hub

Requisitos de Software

El miasma usa:

  • python-pyparsing
  • python-dev
  • opcionalmente python-pycparser (versión >= 2.17)

Para habilitar el código JIT, uno de los siguientes módulos es obligatorio:

  • CCG
  • Sonido metálico
  • LLVM con Numba llvmlite, ver más abajo

‘opcional’ Miasm también puede usar:

  • Z3, el probador de teoremas

Configuración

Para usar el jitter, se recomienda GCC o LLVM

  • GCC (cualquier versión)
  • Clang (cualquier versión)
  • LLVM
    • Debian (en pruebas/inestable): No probado
    • Debian estable/Ubuntu/Kali/lo que sea: pip install llvmlite o instalar desde llvmlite
    • Windows: No probado
  • Compile e instale Miasm:

$ cd miasm_directory
$ python setup.py build
$ sudo python setup.py install

Si algo sale mal durante la compilación de uno de los módulos de jitter, Miasm omitirá el error y deshabilitará el módulo correspondiente (ver el resultado de la compilación).

Windows y AIF

La mayoría de los complementos IDA de Miasm utilizan un subconjunto de la funcionalidad de Miasm. Una forma rápida de hacer que funcionen es agregar:

  • pyparsing.py a C:...IDApython o pip install pyparsing
  • miasm/miasm directorio a C:...IDApython

Todas las funciones excepto las relacionadas con JITter estarán disponibles. Para una instalación más completa, consulte los párrafos anteriores.

Pruebas

Miasm viene con un conjunto de pruebas de regresión. Para ejecutarlos todos:

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'

Se pueden especificar algunas opciones:

  • Roscado mono: -m
  • Instrumentación de cobertura de código: -c
  • Solo pruebas rápidas: -t long (excluye las pruebas largas)

Ya usan Miasm

Instrumentos

  • Sibyl: una herramienta de adivinación funcional
  • R2M2: usa miasm como complemento de radare2
  • CGrex: parcheador dirigido para binarios CGC
  • ethRE: herramienta de inversión para Ethereum EVM (con la arquitectura Miasm2 correspondiente)

Publicaciones de blog / documentos / conferencias

  • Desofuscación: recuperación de un programa protegido por OLLVM
  • Domar un binario MIPS protegido por Nanomite salvaje con ejecución simbólica: no hay tal crackme
  • Génération rapide de DGA avec Miasm: cálculo rápido de DGA (artículo en francés)
  • Habilitación de la resistencia a bloqueos del lado del cliente para superar la diversificación y la ocultación de información: detectar argumentos potenciales de llamadas no dirigidas
  • Miasm: Framework de ingeniería inversa (francés)
  • Tutorial miasm (video francés)
  • Gráficos de dependencias: estilo Petit Poucet: DepGraph (francés)

Libros

  • Ingeniería inversa práctica: X86, X64, Arm, kernel de Windows, herramientas de inversión y ofuscación: Introducción a Miasm (Capítulo 5 “Ofuscación”)
  • BlackHat Python – Apéndice: muestras del libro de seguridad de Japón

Idiomas





  • Pitón
    91,5%

  • C
    8,1%


  • Otro
    0,4%

Por favor Comparte y Síguenos:
RSS
Follow by Email
Facebook
Twitter

Deja una respuesta