def main(keyspace): graph = Graph(uri='http://localhost:4567', keyspace=keyspace) # Get address of printf to use for next query query1 = 'match $func isa function, has func-name contains "printf", has asm-address $a; offset 0; limit 100; select $a;' result1 = graph.execute(query1) if len(result1) > 0: print("Found potential calls at the following addresses:") for addr in result1: print(addr['a']['value']) # If printf is found continue query for printf_func in result1: # Pull any instructions that use printf and don't use a modifier (have var type and not data type) func_addr = int(printf_func['a']['value'], 16) print("Scanning address {}".format(hex(func_addr))) query2 = 'match $x isa instruction, has operation-type "MLIL_CALL_SSA", has asm-address $a; $y isa "MLIL_CONST_PTR"; ($x,$y); $z isa constant, has constant-value {}; ($y,$z); $l isa list, has list-size 1; ($x,$l); $s isa "MLIL_VAR_SSA"; ($l,$s); offset 0; limit 500; select $x, $a;'.format( func_addr) result2 = graph.execute(query2) # If there is an instruction that uses printf without modifier, output instruction if result2: for instr in result2: asm_addr = instr['a']['value'] print("CWE-134: Uncontrolled Format String possible at {} ". format(asm_addr))
def main(keyspace): global graph graph = Graph(uri='http://localhost:4567', keyspace=keyspace) #Find a variable being compared query1 = graph.execute('match {$comp isa MLIL_CMP_SGE;} or {$comp isa MLIL_CMP_SLE;} or {$comp isa MLIL_CMP_SLT;} or {$comp isa MLIL_CMP_SGT;};$node isa MLIL_VAR_SSA;$cons isa MLIL_CONST;($comp, $node);($comp, $cons);$varssa isa variable-ssa has var $var;($node, $varssa);select $comp, $var;offset 0;') #Parse the output of query1 into the compare statements and varaible names comp, var = [], [] if query1: for entry in query1: comp.append(entry['comp']['id']) var.append(entry['var']['value']) else: fail() for entry in comp: #Do upper bound check if ('SGE' or 'SGT') in entry: lower = lowerCheck() if lower: for item in lower: if item['var']['value'] not in var: #failed to find upper bound check addr = get_addr(entry) print('CWE-129: Missing upper bound check at ' + str(addr[0]['addr']['value'])) else: adddr = get_addr(entry) else: addr = get_addr(entry) print('CWE-129: Missing upper bound check at ' + str(addr[0]['addr']['value'])) #Do lower bound check else: upper = upperCheck() if upper: for item in upper: if item['var']['value'] not in var: #failed to find lower bound check addr = get_addr(entry) print('CWE-129: Missing lower bound check at ' + str(addr[0]['addr']['value'])) else: addr = get_addr(entry) else: addr = get_addr(entry) print('CWE-129: Missing lower bound check at ' + str(addr[0]['addr']['value']))
def main(keyspace): graph = Graph(uri='http://localhost:4567', keyspace=keyspace) # Check for gets() function # Get address of function to use for next query function_name = 'gets' query1 = 'match $func isa function, has func-name contains "{}", has asm-address $a; select $a;'.format( function_name) result1 = graph.execute(query1) # If the function is found continue query if result1: # Get all instructions that have function name func_addr = int(result1[0]['a']['value'], 16) query2 = 'match $x has operation-type "MLIL_CALL_SSA" has asm-address $a; $y isa"MLIL_CONST_PTR"; ($x,$y); $z isa constant, has constant-value {}; ($y,$z); select $x, $a;'.format( func_addr) result2 = graph.execute(query2) # If there are instructions that use the function check the instructions for instr in result2: ins_addr = instr['a']['value'] print( "CWE-120: Buffer Copy Without Checking Size of Input at {}\n". format(ins_addr))
# CWE-134 Uncontrolled Format String # # Vuln Info: This vulnerability comes from using printf without a modifier # Ex: cgc_printf(message); <--Bad # cgc_printf("%s", message); <--Good # # Methodology: # 1. Check if file has a printf function # 2. Check if any instructions use printf # 3. Check if params in printf are data type(correct) or var_type(incorrect, no modifier i.e. %s used) # # Try it on: Barcoder, Checkmate, *Kaprica_Go #============================================================================================================ from grakn.client import Graph graph = Graph(uri='http://localhost:4567', keyspace='grakn') # Get address of printf to use for next query query1 = 'match $func isa function, has name contains "printf", has asm-address $a; select $a;' result1 = graph.execute(query1) # If printf is found continue query for printf_func in result1: printf_addr = printf_func['a']['value'] # Pull any instructions that use printf and don't use a modifier (have var type and not data type) func_addr = int(result1[0]['a']['value'], 16) query2 = 'match $x has operation-type "MLIL_CALL_SSA", has asm-address $a; $y isa "MLIL_CONST_PTR"; ($x,$y); $z isa constant, has constant-value {}; ($y,$z); $l isa "list", has list-size != 2; ($x,$l); $s isa "MLIL_VAR_SSA"; ($l,$s); offset 0; limit 30;select $x, $a;'.format( func_addr) result2 = graph.execute(query2)
#======================================================================================= # CWE-788: Access of Memory Location After End of Buffer # # Vuln Info: The software reads or writes to a buffer using an index or pointer that # references a memory location after the end of the buffer. # # Methodology: # 1.Find any arrays # 2.Find indexing variables for said arrays # 3.Look to see if those variables are used in a comparison (bounds check) #======================================================================================= import sys from grakn.client import Graph graph = Graph(uri='http://localhost:4567', keyspace='grakn') #Exits script def fail(): return 0 sys.exit() #Searches for potential array declarations def query1(): result = graph.execute( 'match $set isa instruction, has operation-type "MLIL_SET_VAR_SSA";$ptr isa MLIL_CONST_PTR;($set, $ptr);$reg isa variable-ssa, has var $index;($set, $reg);offset 0;' ) return result
def main(keyspace): graph = Graph(uri='http://localhost:4567', keyspace=keyspace) # Functions with indexes for (dest, sizeof(dest)) stored in dict functions = {"receive_delim": (1,2), "fgets": (0,1), "strncpy": (0,2), "receive_until": (0,2), "memcpy": (0,2), "freaduntil": (1,2)} # Check for potential vuln in each function for function_name in functions: # Get address of function to use for next query query1 = 'match $func isa function, has func-name contains "{}", has asm-address $a; select $a;'.format(function_name) result1 = graph.execute(query1) # If the function is found continue query if result1: # Get all instructions that have function name func_addr = int(result1[0]['a']['value'], 16) query2 = 'match $x has operation-type "MLIL_CALL_SSA"; $y isa"MLIL_CONST_PTR"; ($x,$y); $z isa constant, has constant-value {}; ($y,$z); select $x;'.format(func_addr) result2 = graph.execute(query2) # If there are instructions that use the function check the instructions if result2: buff_index = functions[function_name][0] + 1 size_index = functions[function_name][1] + 1 for instr in result2: Id = instr['x']['id'] query3 = 'match $x id "' + Id + '"; $l isa list; ($x,$l); (from-node: $l, $q); $q has edge-label $e; (from-node: $q, $v); {$v has var $s;} or {$v has constant-value $s;}; select $e, $s;' result3 = graph.execute(query3) # This section grabs instrution params and insert into an array param_array = [0, 0, 0, 0, 0, 0, 0, 0] for ele in result3: index = int(ele['e']['value']) val = ele['s']['value'] param_array[index] = val # Get var name - This is done to determine how many bytes the variable is var_name = param_array[buff_index] var_name = var_name.split('#',1)[0].lstrip() # NOTE Enhancement Make finding buff_size the same as string_size # This assumes that buffer_size is a number, breaks when its a var or register # Get buffer size try: buff_size = int(param_array[size_index]) except ValueError as err: continue # Get size of string in by finding initialization Ex. var_88 = &var_58 # Find where string is initialzed query4 = 'match $x id "{}"; $y isa basic-block; ($x,$y); $z isa instruction, has operation-type "MLIL_SET_VAR_SSA"; ($y,$z); {{$v1 isa variable, has var "{}";}} or {{$v1 isa variable-ssa, has var "{}";}}; ($z, $v1); $w isa MLIL_ADDRESS_OF; ($w, $z); $v isa variable, has var-size $s; ($w, $v); offset 0; limit 30;offset 0; limit 30;'.format(Id, var_name, var_name) result4 = graph.execute(query4) if (result4): string_size = result4[0]['s']['value'] # Finally Determine if buffer size == sizeof(str) if string_size != buff_size: instruction_ID = result4[0]['x']['id'] query5 = 'match $i id {}, has asm-address $a; select $a;'.format(instruction_ID) result5 = graph.execute(query5) instr_addr = result5[0]['a']['value'] print("CWE-121: Stack-based Overflow possible at {}".format(instr_addr))
def main(keyspace): global graph graph = Graph(uri='http://localhost:4567', keyspace=keyspace) # Find possible arrays array = [] q1 = query1() if q1: i = 0 for item in q1: array.append(q1[i]['index']['id']) i += 1 else: fail() # Find loops involving the array block = [] q2 = query2() if q2: i = 0 for item in q2: if q2[i]['index']['id'] in array: block.append(q2[i]['block']['id']) i += 1 else: fail() # Do the 'loop' blocks contain if statements? if_id = [] block2 = block.copy() for item in block2: q3 = query3(item) if not q3: block.remove(item) # Find the loop counters var, version, var_id, reg, reg_type, block2 = [], [], [], [], [], block.copy() for entry in block2: q4 = query4(entry) if q4: i = 0 for item in q4: reg.append(item['reg']['id']) reg_type.append(item['reg']['isa']) var.append(item['index']['value']) version.append(item['version']['value']) var_id.append(item['index']['id']) i += 1 else: block.remove(entry) i = len(var) - 1 # Find is the bounds of the loop counter are checked var2 = [] q5 = query5() i = 0 for entry in q5: var2.append(q5[i]['var']['value']) i += 1 # Any variables in var[] but not var2[] are potential vulnerabilities i = 0 for entry in var: if entry not in var2: q6 = query6(reg_type[i], reg[i]) print('CWE-788: Array index missing bounds check at ' + q6[0]['adr']['value'] + ' associated with '+ var[i] + '#' + str(version[i]) + ' id = ' + var_id[i] + ' sub of ' + reg_type[i] + ' id = ' + reg[i]) i += 1