|
|
|
@ -3,29 +3,56 @@ from argparse import ArgumentParser
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from random import randint
|
|
|
|
|
from multiprocessing import Process, Queue
|
|
|
|
|
from queue import Empty
|
|
|
|
|
import binascii
|
|
|
|
|
import ctypes
|
|
|
|
|
import logging
|
|
|
|
|
import subprocess
|
|
|
|
|
import mmap
|
|
|
|
|
|
|
|
|
|
whoami_shell = b"\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x10\x00\x00\x00\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x77\x68\x6f\x61\x6d\x69\x00\x56\x57\x48\x89\xe6\x0f\x05"
|
|
|
|
|
seed_shell = b'U\x90H\x89\xe5\x90H\x89}\xf8\x90H\x8bE\xf8\x90]\x90\xc3'
|
|
|
|
|
template_shell = b''.join([
|
|
|
|
|
b'\x55', # push rbp
|
|
|
|
|
b'\x48\x89\xe5', # mov rbp,rsp
|
|
|
|
|
b'\x48\x89\x7d\xf8', # mov QWORD [rbp-0x8],rdi
|
|
|
|
|
b'\x48\x8b\x45\xf8', # mov rax,QWORD [rbp-0x8]
|
|
|
|
|
b'\x5d', # pop rbp
|
|
|
|
|
b'\xc3']) # ret
|
|
|
|
|
|
|
|
|
|
def shell_func(shellcode: bytes):
|
|
|
|
|
exec_mem = mmap.mmap(
|
|
|
|
|
-1, len(shellcode),
|
|
|
|
|
prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC,
|
|
|
|
|
flags=mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE)
|
|
|
|
|
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'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def flip(shellcode: bytes):
|
|
|
|
|
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)
|
|
|
|
|
function = ctypes.CFUNCTYPE(ctypes.c_uint, ctypes.c_uint)(
|
|
|
|
|
ctypes.addressof(ctypes_buffer))
|
|
|
|
|
addr = ctypes.addressof(ctypes_buffer)
|
|
|
|
|
|
|
|
|
|
function = ctypes.CFUNCTYPE(ctypes.c_uint, ctypes.c_uint)(addr)
|
|
|
|
|
function._avoid_gc_for_mmap = exec_mem
|
|
|
|
|
|
|
|
|
|
return function
|
|
|
|
|
shellcode_len = ctypes.c_uint(len(shellcode))
|
|
|
|
|
result = function(shellcode_len)
|
|
|
|
|
|
|
|
|
|
queue.put(result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sins():
|
|
|
|
@ -35,6 +62,8 @@ def sins():
|
|
|
|
|
parser.add_argument('-v', '--verbose', action='count')
|
|
|
|
|
parser.add_argument('-s', '--seed', help='path to PIC image.')
|
|
|
|
|
parser.add_argument('-o', '--output', help='path to results directory.')
|
|
|
|
|
parser.add_argument('-l', '--lineage', default=10,
|
|
|
|
|
help='max count of unsuccessful generation.')
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
log_level = logging.INFO
|
|
|
|
@ -70,35 +99,31 @@ def sins():
|
|
|
|
|
with seed.open('rb') as seed_file:
|
|
|
|
|
seed_data = seed_file.read()
|
|
|
|
|
|
|
|
|
|
logger.info(f'seed_data\n{seed_data}')
|
|
|
|
|
logger.info(f'seed_len: {len(seed_data)}')
|
|
|
|
|
logger.info(f'seed:\n{seed_data}')
|
|
|
|
|
|
|
|
|
|
seed = shell_func(seed_shell)
|
|
|
|
|
ret_val = seed(ctypes.c_uint(len(seed_data)))
|
|
|
|
|
queue = Queue()
|
|
|
|
|
|
|
|
|
|
logger.info(f'ret_val: {ret_val}')
|
|
|
|
|
while True:
|
|
|
|
|
lineage = 0
|
|
|
|
|
seed_flipped = flip(seed_data)
|
|
|
|
|
|
|
|
|
|
def func_void(shellcode: bytes):
|
|
|
|
|
exec_mem = mmap.mmap(
|
|
|
|
|
-1, len(shellcode),
|
|
|
|
|
prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC,
|
|
|
|
|
flags=mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE)
|
|
|
|
|
while lineage < args.lineage:
|
|
|
|
|
logger.info(f'lineage: {lineage}')
|
|
|
|
|
result = None
|
|
|
|
|
|
|
|
|
|
exec_mem.write(shellcode)
|
|
|
|
|
proc = Process(target=generation, args=(queue, seed_flipped))
|
|
|
|
|
proc.start()
|
|
|
|
|
try:
|
|
|
|
|
result = queue.get(timeout=1)
|
|
|
|
|
except Empty:
|
|
|
|
|
lineage += 1
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
ctypes_buffer = ctypes.c_int.from_buffer(exec_mem)
|
|
|
|
|
function = ctypes.CFUNCTYPE(ctypes.c_int64)(
|
|
|
|
|
ctypes.addressof(ctypes_buffer))
|
|
|
|
|
function._avoid_gc_for_mmap = exec_mem
|
|
|
|
|
if not result:
|
|
|
|
|
lineage += 1
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
return function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def example():
|
|
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
|
logging.info(whoami_shell)
|
|
|
|
|
logging.info('wtfm8')
|
|
|
|
|
whoami = func_void(whoami_shell)
|
|
|
|
|
ret_val = whoami()
|
|
|
|
|
# whoami doesn't ret
|
|
|
|
|
logging.info(ret_val)
|
|
|
|
|
logger.info(f'scrap:\n{seed_flipped}')
|
|
|
|
|
logger.info(f'result: {result}')
|
|
|
|
|
lineage = 0
|
|
|
|
|
seed_flipped = flip(seed_flipped)
|
|
|
|
|