about summary refs log tree commit diff stats
path: root/example/asm/shellcode.py
diff options
context:
space:
mode:
authorCamille Mougey <camille.mougey@cea.fr>2015-01-22 17:59:11 +0100
committerCamille Mougey <camille.mougey@cea.fr>2015-01-23 17:24:43 +0100
commit8b9047402913c46a545aadeea10fce1011ddd6bd (patch)
treeef3f66c76e5f46096b0d26d92e08b3fe3b856629 /example/asm/shellcode.py
parent9bec8ef1242d03a791014d71eaf896fc11def3fa (diff)
downloadfocaccia-miasm-8b9047402913c46a545aadeea10fce1011ddd6bd.tar.gz
focaccia-miasm-8b9047402913c46a545aadeea10fce1011ddd6bd.zip
Example/ASM: Avoid duplicating code by using a common script shellcode.py
Diffstat (limited to 'example/asm/shellcode.py')
-rw-r--r--example/asm/shellcode.py110
1 files changed, 110 insertions, 0 deletions
diff --git a/example/asm/shellcode.py b/example/asm/shellcode.py
new file mode 100644
index 00000000..89914b6d
--- /dev/null
+++ b/example/asm/shellcode.py
@@ -0,0 +1,110 @@
+#! /usr/bin/env python
+from argparse import ArgumentParser
+from pdb import pm
+
+from elfesteem import pe_init
+from elfesteem.strpatchwork import StrPatchwork
+
+from miasm2.core.cpu import parse_ast
+from miasm2.core import parse_asm, asmbloc
+import miasm2.expression.expression as m2_expr
+from miasm2.analysis.machine import Machine
+
+parser = ArgumentParser("Multi-arch (32 bits) assembler")
+parser.add_argument('architecture', help="architecture: " + \
+                        ",".join(Machine.available_machine()))
+parser.add_argument("source", help="Source file to assemble")
+parser.add_argument("output", help="Output file")
+parser.add_argument("--PE", help="Create a PE with a few imports",
+                    action="store_true")
+parser.add_argument("-e", "--encrypt",
+                    help="Encrypt the code between <label_start> <label_stop>",
+                    nargs=2)
+args = parser.parse_args()
+
+# Get architecture-dependent parameters
+machine = Machine(args.architecture)
+try:
+    attrib = machine.dis_engine.attrib
+    size = int(attrib)
+except AttributeError:
+    attrib = None
+    size = 32
+except ValueError:
+    size = 32
+reg_and_id = dict(machine.mn.regs.all_regs_ids_byname)
+base_expr = machine.base_expr
+
+# Output format
+if args.PE:
+    pe = pe_init.PE(wsize=size)
+    s_text = pe.SHList.add_section(name="text", addr=0x1000, rawsize=0x1000)
+    s_iat = pe.SHList.add_section(name="iat", rawsize=0x100)
+    new_dll = [({"name": "USER32.dll",
+                 "firstthunk": s_iat.addr}, ["MessageBoxA"])]
+    pe.DirImport.add_dlldesc(new_dll)
+    s_myimp = pe.SHList.add_section(name="myimp", rawsize=len(pe.DirImport))
+    pe.DirImport.set_rva(s_myimp.addr)
+    pe.Opthdr.AddressOfEntryPoint = s_text.addr
+
+    addr_main = pe.rva2virt(s_text.addr)
+    virt = pe.virt
+    output = pe
+
+else:
+    st = StrPatchwork()
+
+    addr_main = 0
+    virt = st
+    output = st
+
+# Fix the AST parser
+def my_ast_int2expr(a):
+    return m2_expr.ExprInt_fromsize(size, a)
+
+def my_ast_id2expr(t):
+    return reg_and_id.get(t, m2_expr.ExprId(t, size=size))
+
+my_var_parser = parse_ast(my_ast_id2expr, my_ast_int2expr)
+base_expr.setParseAction(my_var_parser)
+
+# Get and parse the source code
+with open(args.source) as fstream:
+    source = fstream.read()
+
+blocs, symbol_pool = parse_asm.parse_txt(machine.mn, attrib, source)
+
+# Fix shellcode addrs
+symbol_pool.set_offset(symbol_pool.getby_name("main"), addr_main)
+
+if args.PE:
+    symbol_pool.set_offset(symbol_pool.getby_name_create("MessageBoxA"),
+                           pe.DirImport.get_funcvirt('MessageBoxA'))
+
+# Print and graph firsts blocs before patching it
+for bloc in blocs[0]:
+    print bloc
+graph = asmbloc.bloc2graph(blocs[0])
+open("graph.txt", "w").write(graph)
+
+# Apply patches
+resolved_b, patches = asmbloc.asm_resolve_final(machine.mn,
+                                                blocs[0],
+                                                symbol_pool)
+if args.encrypt:
+    # Encrypt code
+    ad_start = symbol_pool.getby_name_create(args.encrypt[0]).offset
+    ad_stop = symbol_pool.getby_name_create(args.encrypt[1]).offset
+
+    new_patches = dict(patches)
+    for ad, val in patches.items():
+        if ad_start <= ad < ad_stop:
+            new_patches[ad] = "".join([chr(ord(x) ^ 0x42) for x in val])
+    patches = new_patches
+
+print patches
+for offset, raw in patches.items():
+    virt[offset] = raw
+
+# Produce output
+open(args.output, 'wb').write(str(output))