scrap-is-not-scrap/sins/run.py

119 lines
3.4 KiB
Python
Executable File

#! /usr/bin/env python3
from argparse import ArgumentParser
from datetime import datetime
from multiprocessing import Process, Queue
from pathlib import Path
from queue import Empty
from sqlalchemy import exists, desc
from tempfile import TemporaryDirectory
import logging
from .mutation import generation, mutate, seed_shell, growth
from .orm import db_config, ScrapNode
def sins():
now = '{0:%Y%m%dT%H%M%S}'.format(datetime.utcnow())
parser = ArgumentParser(
description='position independent code (PIC) mutation experiment.')
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
log_format = logging.Formatter('%(message)s')
if args.verbose:
log_level = logging.DEBUG
log_format = logging.Formatter(
'%(levelname)s %(filename)s:%(lineno)d\n%(message)s\n')
logger = logging.getLogger('sins')
logger.setLevel(log_level)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(log_level)
stream_handler.setFormatter(log_format)
logger.addHandler(stream_handler)
if args.output:
log_path = f'{args.output}/sins-{now}.log'
file_handler = logging.FileHandler(log_path)
file_handler.setLevel(log_level)
file_handler.setFormatter(log_format)
logger.addHandler(file_handler)
logger.info(now)
if args.output:
db_path = Path(f'{args.output}/sins.sqlite')
else:
temp_dir = TemporaryDirectory()
db_path = Path(f'{temp_dir.name}/sins.sqlite')
session = db_config(db_path)
logger.info(f'db_path: {db_path}')
recent = session.query(ScrapNode).order_by(desc('ctime')).first()
if args.seed:
seed_path = Path(args.seed)
with seed_path.open('rb') as seed_file:
seed_data = seed_file.read()
seed = ScrapNode(child=seed_data)
exists = session.query(ScrapNode).filter(
ScrapNode.checksum == seed.checksum)
if exists:
seed = exists[0]
else:
session.add(seed)
session.commit()
logger.debug(f'args.seed:\n{seed}')
elif recent:
seed = recent
logger.debug(f'recent:\n{seed}')
else:
seed = ScrapNode(child=seed_shell)
session.add(seed)
session.commit()
logger.debug(f'seed_shell:\n{seed}')
parent = seed
queue = Queue()
while True:
lineage = 0
while lineage < args.lineage:
scrap = mutate(parent.image)
logger.debug(f'lineage: {lineage}')
result = None
proc = Process(target=generation, args=(queue, scrap))
proc.start()
try:
result = queue.get(timeout=1)
except Empty:
lineage += 1
continue
if not result:
lineage += 1
continue
scrap = growth(shellcode=scrap, length=result)
parent = ScrapNode(child=scrap, parent_id=parent.id)
session.add(parent)
session.commit()
logger.info(f'scrap:\n{parent}')
lineage = 0