parser = ArgumentParser()
parser.add_argument("original")
parser.add_argument("patched")
args = parser.parse_args()

try:
    os.unlink(args.patched)
except OSError:
    pass
try:
    os.unlink(args.patched + ".bin")
except OSError:
    pass

backend = DetourBackend(args.original, variant="stm32")
patches = []

typedef = '''
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
'''
transmit_code = '''
void rx_brake_routine( unsigned char buff[], void *bumper ){
	uint16_t speed_value;  
	uint8_t brake_switch;
	speed_value  = (buff[3] << 8) + buff[2];
	brake_switch = (buff[4] & 0b00001100) >> 2;
	((unsigned char*)bumper)[13] = (brake_switch) ? 1 : 0;

	if ( ((unsigned char*)bumper)[13] ) {
Exemple #2
0
def test_0b32aa01_01():
    print "Testing test_0b32aa01_01..."
    filepath = os.path.join(bin_location, "0b32aa01_01_2")
    backend = DetourBackend(filepath)
    cfg = backend.cfg

    legitimate_functions = set([
        0x80480a0,
        0x8048230,
        0x8048400,
        0x80484f0,
        0x80485fc,
        0x8048607,
        0x8048615,
        0x8048635,
        0x80486c3,
        0x80486a9L,
        0x8048613L,
        0x8048655L,
        0x804867bL,
        0x80486deL,
        0x8048695L])

    non_syscall_functions = [v for k,v in cfg.functions.iteritems() if not v.is_syscall]
    #check startpoints, I know that sometimes they could be None, but this should not happen in CADET_00003
    function_entrypoints = set([f.startpoint.addr for f in non_syscall_functions])
    print "additional:",map(hex,function_entrypoints-legitimate_functions)
    print "skipped:",map(hex,legitimate_functions-function_entrypoints)
    nose.tools.assert_equal(function_entrypoints == legitimate_functions, True)

    sane_functions = [v for k,v in cfg.functions.iteritems() if is_sane_function(v)]
    function_entrypoints = set([f.startpoint.addr for f in sane_functions])
    print "additional:",map(hex,function_entrypoints-legitimate_functions)
    print "skipped:",map(hex,legitimate_functions-function_entrypoints)
    nose.tools.assert_equal(function_entrypoints == legitimate_functions, True)

    #all sane functions ends with ret in CADET_00003
    for ff in sane_functions:
        node = cfg.get_any_node(ff.addr, is_syscall=False)
        nose.tools.assert_equal(node!=None,True)
        nose.tools.assert_equal(len(node.instruction_addrs)>0,True)
        node = cfg.get_any_node(ff.addr+1, is_syscall=False,anyaddr=True)
        nose.tools.assert_equal(node!=None,True)
        nose.tools.assert_equal(len(node.instruction_addrs)>0,True)
        nose.tools.assert_equal(ff.startpoint!=None,True)
        nose.tools.assert_equal(ff.ret_sites!=None,True)
        if ff.addr == 0x080485FC or ff.addr==0x8048607:
            nose.tools.assert_equal(ff.returning==False,True)
        if ff.returning:
            nose.tools.assert_equal(len(ff.ret_sites)>0,True)
        for endpoint in ff.ret_sites:
            bb = backend.project.factory.block(endpoint.addr)
            last_instruction = bb.capstone.insns[-1]
            nose.tools.assert_equal(last_instruction.mnemonic == u"ret", True) 

    syscalls = [v for k,v in cfg.functions.iteritems() if v.is_syscall]

    for ff in syscalls:
        bb1 = cfg.get_any_node(ff.addr)
        nose.tools.assert_equal(len(bb1.predecessors) >= 1, True)
        bb2 = bb1.predecessors[0]
        bb = backend.project.factory.block(bb2.addr)
        ii = bb.capstone.insns[-1]
        nose.tools.assert_equal(ii.mnemonic ==  u"int" and ii.op_str == u"0x80", True)
Exemple #3
0
def test_CADET_00003():
    print "Testing test_CADET_00003..."
    filepath = os.path.join(bin_location, "CADET_00003")
    backend = DetourBackend(filepath)
    cfg = backend.cfg

    #how to get the list of functions from the IDA list:
    #print "["+",\n".join(map(hex,hex,[int(l.split()[2],16) for l in a.split("\n") if l.strip()]))+"]"
    legitimate_functions = set([
        0x80480a0,
        0x8048230,
        0x8048400,
        0x80484f0,
        0x80485fc,
        0x804860c,
        0x804861a,
        0x804863a,
        0x8048705,
        0x8048735,
        0x8048680L,
        0x80486e3L,
        0x80486c8L,
        0x80486aeL,
        0x8048618L,
        0x804865aL,
        0x804869aL])

    non_syscall_functions = [v for k,v in cfg.functions.iteritems() if not v.is_syscall]
    #check startpoints, I know that sometimes they could be None, but this should not happen in CADET_00003
    function_entrypoints = set([f.startpoint.addr for f in non_syscall_functions])
    print "additional:",map(hex,function_entrypoints-legitimate_functions)
    print "skipped:",map(hex,legitimate_functions-function_entrypoints)
    nose.tools.assert_equal(function_entrypoints == legitimate_functions, True)

    sane_functions = [v for k,v in cfg.functions.iteritems() if is_sane_function(v)]
    function_entrypoints = set([f.startpoint.addr for f in sane_functions])
    print "additional:",map(hex,function_entrypoints-legitimate_functions)
    print "skipped:",map(hex,legitimate_functions-function_entrypoints)
    nose.tools.assert_equal(function_entrypoints == legitimate_functions, True)

    #something which was wrong in the past
    n = cfg.get_any_node(0x80485EC)
    nose.tools.assert_true(len(n.instruction_addrs) == 1)
    nose.tools.assert_true(n.instruction_addrs[0] == 0x80485EC)

    #all sane functions ends with ret in CADET_00003
    for ff in sane_functions:
        node = cfg.get_any_node(ff.addr, is_syscall=False)
        nose.tools.assert_equal(node!=None,True)
        nose.tools.assert_equal(len(node.instruction_addrs)>0,True)
        node = cfg.get_any_node(ff.addr+1, is_syscall=False,anyaddr=True)
        nose.tools.assert_equal(node!=None,True)
        nose.tools.assert_equal(len(node.instruction_addrs)>0,True)
        nose.tools.assert_equal(ff.startpoint!=None,True)
        nose.tools.assert_equal(ff.ret_sites!=None,True)
        if ff.addr == 0x080485FC or ff.addr==0x804860C:
            nose.tools.assert_equal(ff.returning==False,True)
        if ff.returning:
            nose.tools.assert_equal(len(ff.ret_sites)>0,True)
        for endpoint in ff.ret_sites:
            bb = backend.project.factory.block(endpoint.addr)
            last_instruction = bb.capstone.insns[-1]
            nose.tools.assert_equal(last_instruction.mnemonic == u"ret", True) 

    syscalls = [v for k,v in cfg.functions.iteritems() if v.is_syscall]

    for ff in syscalls:
        bb1 = cfg.get_any_node(ff.addr)
        nose.tools.assert_equal(len(bb1.predecessors) >= 1, True)
        bb2 = bb1.predecessors[0]
        bb = backend.project.factory.block(bb2.addr)
        ii = bb.capstone.insns[-1]
        nose.tools.assert_equal(ii.mnemonic ==  u"int" and ii.op_str == u"0x80", True)

    endpoint_set = set(map(lambda x:(x.addr,x.size),cfg.functions[0x08048230].endpoints))
    nose.tools.assert_equal(set([(0x080483F4,12),(0x080483D5,20)]),endpoint_set)
    ret_set = set(map(lambda x:(x.addr,x.size),cfg.functions[0x08048230].ret_sites))
    nose.tools.assert_equal(set([(0x080483F4,12)]),ret_set)

    # the following is a case of a bb that should be split by normalization
    # because the bb is split by a "subsequent" jump 
    bb = cfg.get_any_node(0x804824F)
    nose.tools.assert_equal(bb != None, True)
    nose.tools.assert_equal(bb.size == 13, True)
    bb = cfg.get_any_node(0x08048230)
    nose.tools.assert_equal(bb != None, True)
    nose.tools.assert_equal(bb.size == 31, True)
# parse command line arguments
parser = ArgumentParser()
parser.add_argument("original")
parser.add_argument("patched")
parser.add_argument("patchinfo", nargs="?")
args = parser.parse_args()

# setup logging options
logging.getLogger("angr").propagate = False
logging.getLogger("cle").propagate = False
logging.getLogger("pyvex").propagate = False
logging.getLogger("patcherex").setLevel(logging.DEBUG)

# initialize backend
backend = DetourBackend(args.original, replace_note_segment=True, try_reuse_unused_space=True)
patches = []

# replace the original hash function (using CRC-32) with a modified version of it (using SHA-256)
digest_message = '''
#include <stdlib.h>
typedef void EVP_MD_CTX;
void digest_message(const unsigned char *message, size_t message_len, unsigned char **digest, unsigned int *digest_len)
{
	EVP_MD_CTX *mdctx;

	if((mdctx = EVP_MD_CTX_new()) == NULL)
		handleErrors();

	if(1 != EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL))
		handleErrors();