Skip to content

Commit

Permalink
Include elfesteem fork in miasm
Browse files Browse the repository at this point in the history
  • Loading branch information
p-l- authored and serpilliere committed Mar 5, 2019
1 parent 944806c commit d3a42fa
Show file tree
Hide file tree
Showing 28 changed files with 6,058 additions and 33 deletions.
1 change: 1 addition & 0 deletions .codespell_ignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ uint
mye
iff
nto
rela
13 changes: 2 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Miasm is a free and open source (GPLv2) reverse engineering framework.
Miasm aims to analyze / modify / generate binary programs. Here is
a non exhaustive list of features:

* Opening / modifying / generating PE / ELF 32 / 64 LE / BE using Elfesteem
* Opening / modifying / generating PE / ELF 32 / 64 LE / BE
* Assembling / Disassembling X86 / ARM / MIPS / SH4 / MSP430
* Representing assembly semantic using intermediate language
* Emulating using JIT (dynamic code analysis, unpacking, ...)
Expand Down Expand Up @@ -525,7 +525,6 @@ Miasm uses:

* python-pyparsing
* python-dev
* elfesteem from [Elfesteem](https://github.com/serpilliere/elfesteem.git)
* optionally python-pycparser (version >= 2.17)

To enable code JIT, one of the following module is mandatory:
Expand All @@ -539,14 +538,6 @@ To enable code JIT, one of the following module is mandatory:
Configuration
-------------

* Install elfesteem
```pycon
git clone https://github.com/serpilliere/elfesteem.git elfesteem
cd elfesteem
python setup.py build
sudo python setup.py install
```

To use the jitter, GCC or LLVM is recommended
* GCC (any version)
* Clang (any version)
Expand All @@ -570,7 +561,7 @@ Windows & IDA

Most of Miasm's IDA plugins use a subset of Miasm functionality.
A quick way to have them working is to add:
* `elfesteem` directory and `pyparsing.py` to `C:\...\IDA\python\` or `pip install pyparsing elfesteem`
* `pyparsing.py` to `C:\...\IDA\python\` or `pip install pyparsing`
* `miasm/miasm` directory to `C:\...\IDA\python\`

All features excepting JITter related ones will be available. For a more complete installation, please refer to above paragraphs.
Expand Down
4 changes: 2 additions & 2 deletions example/asm/shellcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from pdb import pm

from future.utils import viewitems
from elfesteem import pe_init
from elfesteem.strpatchwork import StrPatchwork
from miasm.elfesteem import pe_init
from miasm.elfesteem.strpatchwork import StrPatchwork

from miasm.core import parse_asm, asmblock
from miasm.analysis.machine import Machine
Expand Down
48 changes: 48 additions & 0 deletions example/elfesteem/minidump_to_pe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#! /usr/bin/env python
"""Minidump to PE example"""

import sys

from future.utils import viewvalues

from miasm.elfesteem.minidump_init import Minidump
from miasm.elfesteem.pe_init import PE

minidump = Minidump(open(sys.argv[1], 'rb').read())

pe = PE()
for i, memory in enumerate(sorted(viewvalues(minidump.memory),
key=lambda x:x.address)):
# Get section name
name = str(memory.name)
if not name:
name = "s_%02d" % i
else:
name = name.split('\\')[-1]

# Get section protection
protect = memory.pretty_protect
protect_mask = 0x20
if protect == "UNKNOWN":
protect_mask |= 0xe0000000
else:
if "EXECUTE" in protect:
protect_mask |= 1 << 29
if "READ" in protect:
protect_mask |= 1 << 30
if "WRITE" in protect:
protect_mask |= 1 << 31

# Add the section
pe.SHList.add_section(name=name, addr=memory.address, rawsize=memory.size,
data=memory.content, flags=protect_mask)

# Find entry point
try:
entry_point = minidump.threads.Threads[0].ThreadContext.Eip[0]
except AttributeError:
entry_point = minidump.threads.Threads[0].ThreadContext.Rip[0]

pe.Opthdr.AddressOfEntryPoint = entry_point

open("out_pe.bin", "wb").write(bytes(pe))
31 changes: 31 additions & 0 deletions example/elfesteem/test_pe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#! /usr/bin/env python

import miasm.elfesteem.pe as pe
from miasm.elfesteem.pe_init import PE
import rlcompleter
import readline
import pdb
import sys
from pprint import pprint as pp
readline.parse_and_bind("tab: complete")


e_ = PE()
mysh = b"\xc3"
s_text = e_.SHList.add_section(
name="text", addr=0x1000, rawsize=0x1000, data=mysh)
e_.Opthdr.AddressOfEntryPoint = s_text.addr
new_dll = [({"name": "kernel32.dll",
"firstthunk": s_text.addr + 0x100},
["CreateFileA", "SetFilePointer", "WriteFile", "CloseHandle"]
),
({"name": "USER32.dll",
"firstthunk": None},
["SetDlgItemInt", "GetMenu", "HideCaret"]
)
]
e_.DirImport.add_dlldesc(new_dll)

s_myimp = e_.SHList.add_section(name="myimp", rawsize=0x1000)
e_.DirImport.set_rva(s_myimp.addr)
open('uu.bin', 'wb').write(bytes(e_))
2 changes: 1 addition & 1 deletion example/jitter/arm_sc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from miasm.core.utils import int_to_byte
from miasm.analysis.sandbox import Sandbox_Linux_armb_str
from miasm.analysis.sandbox import Sandbox_Linux_arml_str
from elfesteem.strpatchwork import StrPatchwork
from miasm.elfesteem.strpatchwork import StrPatchwork

from pdb import pm

Expand Down
2 changes: 1 addition & 1 deletion example/jitter/run_with_linuxenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import logging
import re

from elfesteem import elf as elf_csts
from miasm.elfesteem import elf as elf_csts

from miasm.os_dep.linux import environment, syscall
from miasm.analysis.machine import Machine
Expand Down
2 changes: 1 addition & 1 deletion example/jitter/unpack_upx.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import logging
from pdb import pm
from elfesteem import pe
from miasm.elfesteem import pe
from miasm.analysis.sandbox import Sandbox_Win_x86_32

# User defined methods
Expand Down
4 changes: 2 additions & 2 deletions miasm/analysis/binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class ContainerPE(Container):

def parse(self, data, vm=None, **kwargs):
from miasm.jitter.loader.pe import vm_load_pe, guess_arch
from elfesteem import pe_init
from miasm.elfesteem import pe_init

# Parse signature
if not data.startswith(b'MZ'):
Expand Down Expand Up @@ -178,7 +178,7 @@ def parse(self, data, vm=None, addr=0, apply_reloc=False, **kwargs):
"""
from miasm.jitter.loader.elf import vm_load_elf, guess_arch, \
fill_loc_db_with_symbols
from elfesteem import elf_init
from miasm.elfesteem import elf_init

# Parse signature
if not data.startswith(b'\x7fELF'):
Expand Down
3 changes: 3 additions & 0 deletions miasm/elfesteem/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python

__all__ = ['pe_init', 'elf_init', 'strpatchwork']
154 changes: 154 additions & 0 deletions miasm/elfesteem/cstruct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#! /usr/bin/env python

from __future__ import print_function
from builtins import zip
from functools import reduce
import struct

from future.utils import PY3

type_size = {}
size2type = {}
for t in 'B', 'H', 'I', 'Q':
s = struct.calcsize(t)
type_size[t] = s * 8
size2type[s * 8] = t

type_size['u08'] = size2type[8]
type_size['u16'] = size2type[16]
type_size['u32'] = size2type[32]
type_size['u64'] = size2type[64]


def fix_size(fields, wsize):
out = []
for name, v in fields:
if v.endswith("s"):
pass
elif v == "ptr":
v = size2type[wsize]
elif not v in type_size:
raise ValueError("unknown Cstruct type", v)
else:
v = type_size[v]
out.append((name, v))
fields = out
return fields


class Cstruct_Metaclass(type):

def __new__(cls, name, bases, dct):
o = super(Cstruct_Metaclass, cls).__new__(cls, name, bases, dct)
o._packstring = o._packformat + \
"".join(x[1] for x in o._fields)
o._size = struct.calcsize(o._packstring)
return o


class CStruct(object):
#__metaclass__ = Cstruct_Metaclass
_packformat = ""
_fields = []

@classmethod
def _from_file(cls, f):
return cls(f.read(cls._size))

def __init__(self, sex, wsize, *args, **kargs):
if sex == 1:
sex = '<'
else:
sex = '>'
# packformat enforce sex
if self._packformat:
sex = ""
pstr = fix_size(self._fields, wsize)
self._packstring = sex + self._packformat + \
"".join(x[1] for x in pstr)
self._size = struct.calcsize(self._packstring)

self._names = [x[0] for x in self._fields]
if kargs:
self.__dict__.update(kargs)
else:
if args:
s = args[0]
else:
s = b""
s += b"\x00" * self._size
s = s[:self._size]
self._unpack(s)

def _unpack(self, s):
disas = struct.unpack(self._packstring, s)
for n, v in zip(self._names, disas):
setattr(self, n, v)

def _pack(self):
return struct.pack(self._packstring,
*(getattr(self, x) for x in self._names))

def _spack(self, superstruct, shift=0):
attr = []
for name in self._names:
s = getattr(self, name)
if isinstance(s, CStruct):
if s in superstruct:
s = reduce(lambda x, y: x + len(y),
superstruct[:superstruct.index(s)],
0)
s += shift
else:
raise Exception("%r is not a superstructure" % s)
attr.append(s)
return struct.pack(self._packstring, *attr)

def _copy(self):
return self.__class__(**self.__dict__)

def __len__(self):
return self._size

def __str__(self):
if PY3:
return repr(self)
return self.__bytes__()

def __bytes__(self):
return self._pack()

def __repr__(self):
return "<%s=%s>" % (self.__class__.__name__, "/".join(repr(
getattr(self, x[0])) for x in self._fields
))

def __getitem__(self, item): # to work with format strings
return getattr(self, item)

def _show(self):
print("##%s:" % self.__class__.__name__)
fmt = "%%-%is = %%r" % max(len(x[0]) for x in self._fields)
for fn, ft in self._fields:
print(fmt % (fn, getattr(self, fn)))


class CStructStruct(object):

def __init__(self, lst, shift=0):
self._lst = lst
self._shift = shift

def __getattr__(self, attr):
return getattr(self._lst, attr)

def __str__(self):
if PY3:
return repr(self)
return self.__bytes__()

def __bytes__(self):
return b"".join(
a if isinstance(a, bytes) else a._spack(self._lst, self._shift)
for a in self._lst
)
Loading

0 comments on commit d3a42fa

Please sign in to comment.