2019-02-19 03:33:56 +00:00
|
|
|
#! /usr/bin/env python3
|
|
|
|
from multiprocessing import Queue
|
|
|
|
from random import randint
|
|
|
|
import ctypes
|
|
|
|
import mmap
|
|
|
|
|
2019-02-21 00:26:47 +00:00
|
|
|
from .disassemble import disasm
|
|
|
|
|
2019-02-19 03:33:56 +00:00
|
|
|
seed_shell = b''.join([
|
|
|
|
b'\x55',
|
|
|
|
b'\x48\x89\xe5',
|
|
|
|
b'\x90' * randint(8, 64),
|
|
|
|
b'\x48\x89\x7d\xf8',
|
|
|
|
b'\x90' * randint(8, 64),
|
|
|
|
b'\x48\x8b\x45\xf8',
|
|
|
|
b'\x5d',
|
|
|
|
b'\xc3'])
|
|
|
|
|
2019-02-20 23:32:34 +00:00
|
|
|
# use template to declutter output, todo
|
|
|
|
seed_shell = b''.join([
|
|
|
|
b'\x55', # push rbp
|
|
|
|
b'\x48\x89\xe5', # mov rbp,rsp
|
|
|
|
b'\x90' * 8, # nop
|
|
|
|
b'\x48\x89\x7d\xf8', # mov QWORD [rbp-0x8],rdi
|
|
|
|
b'\x90' * 8, # nop
|
|
|
|
b'\x48\x8b\x45\xf8', # mov rax,QWORD [rbp-0x8]
|
|
|
|
b'\x5d', # pop rbp
|
|
|
|
b'\xc3']) # ret
|
|
|
|
|
2019-02-19 03:33:56 +00:00
|
|
|
|
2019-02-20 23:32:34 +00:00
|
|
|
def mutate(shellcode: bytes):
|
2019-02-19 03:33:56 +00:00
|
|
|
shellcode = bytearray(shellcode)
|
|
|
|
offset = randint(0, len(shellcode) - 1)
|
|
|
|
flip = randint(0, 255)
|
|
|
|
shellcode[offset] ^= flip
|
|
|
|
return bytes(shellcode)
|
|
|
|
|
|
|
|
|
|
|
|
def generation(queue: Queue, shellcode: bytes):
|
|
|
|
prot = mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC
|
|
|
|
flags = mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE
|
|
|
|
exec_mem = mmap.mmap(-1, len(shellcode), prot=prot, flags=flags)
|
|
|
|
|
|
|
|
exec_mem.write(shellcode)
|
|
|
|
ctypes_buffer = ctypes.c_int.from_buffer(exec_mem)
|
|
|
|
addr = ctypes.addressof(ctypes_buffer)
|
|
|
|
|
|
|
|
function = ctypes.CFUNCTYPE(ctypes.c_uint, ctypes.c_uint)(addr)
|
|
|
|
function._avoid_gc_for_mmap = exec_mem
|
|
|
|
|
|
|
|
shellcode_len = ctypes.c_uint(len(shellcode))
|
|
|
|
result = function(shellcode_len)
|
|
|
|
|
|
|
|
queue.put(result)
|
2019-02-20 23:32:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
def growth(*, shellcode: bytes, length: int) -> bytes:
|
2019-02-21 00:26:47 +00:00
|
|
|
if length <= len(shellcode):
|
|
|
|
return bytes(shellcode)
|
2019-02-20 23:32:34 +00:00
|
|
|
|
2019-02-24 06:34:26 +00:00
|
|
|
opcodes = disasm(shellcode)
|
|
|
|
|
2019-02-24 06:38:33 +00:00
|
|
|
max_op_len = 15
|
|
|
|
|
|
|
|
if len(shellcode) > len(opcodes) * max_op_len:
|
2019-02-24 06:34:26 +00:00
|
|
|
return bytes(shellcode)
|
|
|
|
|
|
|
|
for mnemonic, op_str in opcodes:
|
|
|
|
if mnemonic == 'nop':
|
|
|
|
return bytes(shellcode)
|
|
|
|
|
2019-02-21 00:26:47 +00:00
|
|
|
shellcode = bytearray(shellcode)
|
|
|
|
shellcode += b'\x90'
|
2019-02-20 23:32:34 +00:00
|
|
|
|
|
|
|
return bytes(shellcode)
|