def main(): #Setup Machine for arm, get filename machine = Machine('armtl') parser = ArgumentParser("Description") parser.add_argument('filename', help='filename') args = parser.parse_args() #Setup disassembly stream in container, get blocks and draw the graph cont = Container.from_stream(open(args.filename)) bin_stream = cont.bin_stream mdis = machine.dis_engine(bin_stream) blocks = mdis.dis_multibloc(0x614) open("cfg.dot", "w").write(blocks.dot()) #Create a template for matching blocks in the control flow graph #Requirement 1) Don't get block 0xdf8, it can't disassemble #Requirement 2) Get ones that start with LDR #Requirement 3) Get ones where the second to last instruction is CMP #No restructions for in going and out going edges mblock = MatchGraphJoker( name='mblock', restrict_in=False, restrict_out=False, filt=lambda block: block.label.offset != 0xdf8 and "LDR" in block. lines[0].name and "CMP" in block.lines[-2].name) #Basic block matcher nblock = MatchGraphJoker(name="next", restrict_in=False, restrict_out=False) #Now it should match the blocks we want with the checks matcher = nblock >> mblock flag_storage = {} #Loop through matching template blocks for sol in matcher.match(blocks): try: #Grab position line pline = sol[mblock].lines[3] #Grab character check line cline = sol[mblock].lines[-2] #Transform character and position to integer pos = int(pline.arg2str(pline.args[1]), 16) c = int(cline.arg2str(cline.args[1]), 16) #If its NULL, ignore if c != 0: flag_storage.update({pos: c}) except ValueError: #The F at the beginning is a NULL check pass #Print Flag flag = "".join(map(lambda x: chr(flag_storage[x]), sorted(flag_storage))).replace("F", "I") print "F" + flag pass
assert len(preds) == 2 assert entry_block in preds assert tob in preds assert blocks.edges2constraint[(entry_block, newb)] == AsmConstraint.c_next assert blocks.edges2constraint[(tob, newb)] == AsmConstraint.c_to # Check double block split data = "74097405b8020000007405b803000000b804000000c3".decode('hex') cont = Container.from_string(data) mdis = dis_x86_32(cont.bin_stream) blocks = mdis.dis_multiblock(0) ## Check resulting disasm assert len(blocks.nodes()) == 6 blocks.sanity_check() ## Check graph structure bbl0 = MatchGraphJoker(name="0") bbl2 = MatchGraphJoker(name="2") bbl4 = MatchGraphJoker(name="4") bbl9 = MatchGraphJoker(name="9") bblB = MatchGraphJoker(name="B") bbl10 = MatchGraphJoker(name="10") matcher = bbl0 >> bbl2 >> bbl4 >> bbl9 >> bblB >> bbl10 matcher += bbl2 >> bbl9 >> bbl10 matcher += bbl0 >> bblB solutions = list(matcher.match(blocks)) assert len(solutions) == 1 solution = solutions.pop() for jbbl, block in solution.iteritems(): assert block.label.offset == int(jbbl._name, 16)
#open('AsmCFG_input.dot','w+').write(blocks.dot()) ''' for head in blocks.heads(): for child in blocks.reachable_sons(head): print child ''' filter_block = lambda block: (len(block.lines)==2 and \ block.lines[0].name == 'PUSH' and \ block.lines[1].name == 'MOV') #parent joker node for the first block in MatchGraph / defining a filter for #first two consecutive lines in block.lines[i].name (PUSH,MOV) parent = MatchGraphJoker(restrict_in=False, filt=filter_block, name='root') middle = MatchGraphJoker(restrict_in=False, filt=lambda block: (block.lines[0].name == 'XOR'), name='middle') last = MatchGraphJoker(restrict_out=False, name='end') # MatchGraph with a loop on middle joker node expgraph = parent >> middle >> last expgraph += middle >> middle #open('MatchGraphJoker.dot','w').write(expgraph.dot()) def pass_remove_junkcode(dgs, graph):