SIGSEGV safe generation with mutation control
							parent
							
								
									01d309f81f
								
							
						
					
					
						commit
						9aca501928
					
				| 
						 | 
					@ -1,16 +1,11 @@
 | 
				
			||||||
version: '3'
 | 
					version: '3'
 | 
				
			||||||
services:
 | 
					services:
 | 
				
			||||||
  sins_build:
 | 
					  sins_run:
 | 
				
			||||||
    image: sins
 | 
					    image: sins
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: .
 | 
					      context: .
 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - ${PWD}:/app
 | 
					      - ${PWD}:/app
 | 
				
			||||||
    working_dir: /app
 | 
					    working_dir: /app
 | 
				
			||||||
    command: yasm seed.asm -o seed
 | 
					 | 
				
			||||||
  sins_run:
 | 
					 | 
				
			||||||
    image: sins
 | 
					 | 
				
			||||||
    volumes:
 | 
					 | 
				
			||||||
      - ${PWD}:/app
 | 
					 | 
				
			||||||
    working_dir: /app
 | 
					 | 
				
			||||||
    command: python3 -m sins
 | 
					    command: python3 -m sins
 | 
				
			||||||
 | 
					    # command: yasm seed.asm -o seed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
#! /usr/bin/env python3
 | 
					#! /usr/bin/env python3
 | 
				
			||||||
from .run import sins, shell_func
 | 
					from .run import sins, generation
 | 
				
			||||||
# from .orm import SeedNode
 | 
					# from .orm import SeedNode
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										53
									
								
								sins/run.py
								
								
								
								
							
							
						
						
									
										53
									
								
								sins/run.py
								
								
								
								
							| 
						 | 
					@ -3,6 +3,8 @@ from argparse import ArgumentParser
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from random import randint
 | 
					from random import randint
 | 
				
			||||||
 | 
					from multiprocessing import Process, Queue
 | 
				
			||||||
 | 
					from queue import Empty
 | 
				
			||||||
import binascii
 | 
					import binascii
 | 
				
			||||||
import ctypes
 | 
					import ctypes
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
| 
						 | 
					@ -27,7 +29,15 @@ seed_shell = b''.join([
 | 
				
			||||||
    b'\xc3'])
 | 
					    b'\xc3'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def shell_func(shellcode: bytes):
 | 
					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
 | 
					    prot = mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC
 | 
				
			||||||
    flags = mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE
 | 
					    flags = mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE
 | 
				
			||||||
    exec_mem = mmap.mmap(-1, len(shellcode), prot=prot, flags=flags)
 | 
					    exec_mem = mmap.mmap(-1, len(shellcode), prot=prot, flags=flags)
 | 
				
			||||||
| 
						 | 
					@ -39,7 +49,10 @@ def shell_func(shellcode: bytes):
 | 
				
			||||||
    function = ctypes.CFUNCTYPE(ctypes.c_uint, ctypes.c_uint)(addr)
 | 
					    function = ctypes.CFUNCTYPE(ctypes.c_uint, ctypes.c_uint)(addr)
 | 
				
			||||||
    function._avoid_gc_for_mmap = exec_mem
 | 
					    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():
 | 
					def sins():
 | 
				
			||||||
| 
						 | 
					@ -49,6 +62,8 @@ def sins():
 | 
				
			||||||
    parser.add_argument('-v', '--verbose', action='count')
 | 
					    parser.add_argument('-v', '--verbose', action='count')
 | 
				
			||||||
    parser.add_argument('-s', '--seed', help='path to PIC image.')
 | 
					    parser.add_argument('-s', '--seed', help='path to PIC image.')
 | 
				
			||||||
    parser.add_argument('-o', '--output', help='path to results directory.')
 | 
					    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()
 | 
					    args = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    log_level = logging.INFO
 | 
					    log_level = logging.INFO
 | 
				
			||||||
| 
						 | 
					@ -84,17 +99,31 @@ def sins():
 | 
				
			||||||
        with seed.open('rb') as seed_file:
 | 
					        with seed.open('rb') as seed_file:
 | 
				
			||||||
            seed_data = seed_file.read()
 | 
					            seed_data = seed_file.read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    seed_data = bytearray(seed_data)
 | 
					    logger.info(f'seed:\n{seed_data}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    offset = randint(0, len(seed_data))
 | 
					    queue = Queue()
 | 
				
			||||||
    flip = randint(0, 255)
 | 
					 | 
				
			||||||
    seed_data[offset] ^= flip
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    seed_len = ctypes.c_uint(len(seed_data))
 | 
					    while True:
 | 
				
			||||||
    logger.info(f'seed_data\n{binascii.b2a_hex(seed_data)}')
 | 
					        lineage = 0
 | 
				
			||||||
    logger.info(f'seed_len: {seed_len}')
 | 
					        seed_flipped = flip(seed_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    seed = shell_func(seed_shell)
 | 
					        while lineage < args.lineage:
 | 
				
			||||||
    ret_val = seed(seed_len)
 | 
					            logger.info(f'lineage: {lineage}')
 | 
				
			||||||
 | 
					            result = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    logger.info(f'ret_val:  {ret_val}')
 | 
					            proc = Process(target=generation, args=(queue, seed_flipped))
 | 
				
			||||||
 | 
					            proc.start()
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                result = queue.get(timeout=1)
 | 
				
			||||||
 | 
					            except Empty:
 | 
				
			||||||
 | 
					                lineage += 1
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if not result:
 | 
				
			||||||
 | 
					                lineage += 1
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            logger.info(f'scrap:\n{seed_flipped}')
 | 
				
			||||||
 | 
					            logger.info(f'result: {result}')
 | 
				
			||||||
 | 
					            lineage = 0
 | 
				
			||||||
 | 
					            seed_flipped = flip(seed_flipped)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue