def decrypt_resource(verbose=True): if verbose: print("\n%s\n\tStarting the decryption of the resource\n%s\n" % ('~'*60, '~'*60)) # Get information on all resources in JSON format rsrcs = cutter.cmdj('iRj') rsrc_101 = {} # Locate resource 101 and dump it to an array for rsrc in rsrcs: if rsrc['name'] == 101: rsrc_101 = cutter.cmdj("pxj %d @ %d" % (rsrc['size'], rsrc['vaddr'])) # Decompress the zlibbed array decompressed_data = zlib.decompress(bytes(rsrc_101)) decrypted_payload = [] # Decrypt the payload for b in decompressed_data: decrypted_payload.append((ror(b, 3, 8))) # Write the payload (a PE binary) to a file open(r'./decrypted_rsrc.bin', 'wb').write(bytearray(decrypted_payload)) if verbose: print("Saved the PE to ./decrypted_rsrc.bin")
def smart_rename_function(location, name): # Get function info function_info = cutter.cmdj('afij @%s' % location) if not len(function_info): # no function at location, trigger analysis # and refetch function info cutter.cmd('af @ %s' % location) function_info = cutter.cmdj('afij @%s' % location) old_fn_name = function_info[0]['name'] # Sometimes the vivisect feature extractor identifies # adresses in the middle of functions as function starts # for some reason. We get the actual addr with r2. actual_offset = function_info[0]['offset'] if old_fn_name.startswith('fcn.'): # Function has default name, replace all of it. cutter.cmd('afn {} @ {}'.format(name, actual_offset)) else: # Function does not have generic name keep old name as prefix name = f'{old_fn_name}__{name}' cutter.cmd('afn {} @ {}'.format(name, actual_offset))
def update_content(self): current_line = cutter.cmdj("pdj 1")[0] # Running "ij" during DockWidget init causes a crash if not self.cutterref: info = cutter.cmdj("ij")["bin"] arch = info["arch"] self.cutterref = CutterRef(info["arch"] + "-" + str(info["bits"])) try: inst = current_line["disasm"].split()[0] except: return # Don't update the text box for the same instruction if inst != self.previous_inst: doc = self.cutterref.get_instruction_doc(inst) # Use r2's documentation if the instruction wasn't found in the loaded manual if not doc: doc = cutter.cmd("aod @ " + str(current_line["offset"])) self.view.setHtml(doc) self.previous_inst = inst return
def test_analyse_function(self, _): # Here, checking if cutter works as expected is out of scope but rather # what I am checking is given that cutter works as expected does my code # work as expected as well or not _, bbs = drcov.load("test_files/drcov2.4.log") function = cutter.cmdj("aflj")[0] base = cutter.cmdj("ij")['bin']['baddr'] entry, hits = covtable.analyse_function(function, base, bbs[0]) hardcoded_entry = ['76.923%', 'entry0', '0x08048060', '10/13', '3/4'] self.assertEqual(entry, hardcoded_entry) self.assertEqual(hits, {0x8048060, 0x804808a, 0x8048074})
def analyse(config): functions = cutter.cmdj("aflj") module = Path(cutter.cmdj("ij")['core']['file']).name idx = getModuleIdx(config['modules'], module) # [coverage, name, address, instruction hits, basic block hits] config['bb_hits'] = set() config['table'] = [] for function in functions: entry, hits = analyse_function(function, config['bbs'][idx]) if entry == None: continue config['table'].append(entry) config['bb_hits'].update(hits)
def get_string(self, start_address, end_address) -> list: result = [] data = cutter.cmdj("Csj") # get single line strings : C*.@addr for i in data: if i["offset"] >= start_address and i["offset"] <= end_address: result.append(base64.b64decode(i["name"]).decode()) return result
def export_db(self): filename = self.file_dialog("Open new file for export", True) if not filename: return cutter.message("[x64dbg-cutter]: Exporting database to %s" % filename) db = {} base_addr = cutter.cmdj("elJ bin.baddr")[0]["value"] cutter.message("[x64dbg-cutter]: baddr is %d" % base_addr) # We can only export items from the main binary currently module = os.path.basename(cutter.cmdj("ij")["core"]["file"]).lower() # ref: {"addr":5368778842,"size":1,"prot":"--x","hw":false,"trace":false,"enabled":true,"data":"","cond":""} db["breakpoints"] = [{ "address": hex(bp["addr"] - base_addr), # Comment address relative to the base of the module "enabled": bp["enabled"], # Whether the breakpoint is enabled "type": BPHARDWARE if bp["hw"] else BPNORMAL, # see https://github.com/x64dbg/x64dbg/blob/development/src/dbg/breakpoint.h#L13 "module": module, # The module that the comment is in } for bp in cutter.cmdj("dbj")] cutter.message("[x64dbg-cutter]: %d breakpoint(s) exported" % len(db["breakpoints"])) # ref: {"offset":5368713216,"type":"CCu","name":"[00] -rwx section size 65536 named .textbss"} db["comments"] = [{ "module": module, # The module that the comment is in "address": hex(c["offset"] - base_addr), # Comment address relative to the base of the module "manual": True, # Whether the comment was created by the user - set to True to show it in the comments window "text": c["name"], # Comment text } for c in cutter.cmdj("CCj")] cutter.message("[x64dbg-cutter]: %d comment(s) exported" % len(db["comments"])) # Set flagspace to all before iterating over fj to show all of the flags cutter.cmd("fs *") # ref: {"name":"fcn.1400113de","size":5,"offset":5368779742} db["labels"] = [{ "module": module, # The module that the label is in "address": hex(label["offset"] - base_addr), # Label address relative to the base of the module "manual": False, # Whether the label was created by the user "text": label["name"], # Label text } for label in cutter.cmdj("fj") if (label["offset"] - base_addr) >= 0] cutter.message("[x64dbg-cutter]: %d labels(s) exported" % len(db["labels"])) with open(filename, "w") as outfile: json.dump(db, outfile, indent=1)
def get_disasm(location): feature_disasm = cutter.cmdj("pdj 1 @%s" % location) if feature_disasm[0].get('disasm'): disasm = feature_disasm[0].get('disasm') else: disasm = 'N/A' return disasm
def get_comment_hex(self, start_address, end_address) -> list: result = [] current_start = start_address while current_start < end_address: cutter_data = cutter.cmdj(f"i. @ {current_start}") result.append(self.get_hex(current_start, cutter_data["next"])) current_start = cutter_data["next"] return result
def buildDecoderTable(self): self.decoder = { 'addr': 0x41ba3c, 'len': 0x41ba79 - 0x41ba3c, 'fcn': 0x4012a0, } self.decoder['tbl'] = cutter.cmdj("pxj %d @ %d" % (self.decoder['len'], self.decoder['addr']))
def analyse(config): config['bb_hits'] = set() config['table'] = [] functions = cutter.cmdj("aflj") info = cutter.cmdj("ij") module = file_name(info['core']['file']) base = info["bin"]["baddr"] idx = get_module_idx(config['modules'], module) if idx == -1: return # [coverage, name, address, instruction hits, basic block hits] for function in functions: entry, hits = analyse_function(function, base, config['bbs'][idx]) if entry is None: continue config['table'].append(entry) config['bb_hits'].update(hits)
def get_name(location): function_info = cutter.cmdj('afij @%s' % location) if len(function_info): fn_name = function_info[0]['name'] match_name = f"{fn_name}" else: match_name = 'undefined.%s' % location return match_name
def decode_strings(verbose=True): if verbose: print("\n%s\n\tStarting the decode of the encrypted strings\n%s\n\n" % ('~'*60, '~'*60)) # Declaration of decryption-table related variables decryption_table = 0x41BA3C decryption_table_end = 0x41BA77 decryption_table_len = decryption_table_end - decryption_table decryption_function = 0x4012A0 # Analyze the binary to better detect functions and x-refs cutter.cmd('aa') # Rename the decryption function cutter.cmd('afn decryption_function %d' % decryption_function) # Dump the decryption table to a variable decryption_table_content = cutter.cmdj( "pxj %d @ %d" % (decryption_table_len, decryption_table)) # Iterate x-refs to the decryption function for xref in cutter.cmdj('axtj %d' % decryption_function): # Get the arguments passed to the decryption function: length and encrypted string length_arg, offsets_arg = cutter.cmdj('pdj -2 @ %d' % (xref['from'])) # String variable to store the decrypted string decrypted_string = "" # Guard rail to avoid exception if (not 'val' in length_arg): continue # Manually decrypt the encrypted string for i in range(0, length_arg['val']): decrypted_string += chr(decryption_table_content[cutter.cmdj( 'pxj 1 @ %d' % (offsets_arg['val'] + (i*2)))[0]]) # Print the decrypted and the address it was referenced to the console if verbose: print(decrypted_string + " @ " + hex(xref['from'])) # Add comments to each call of the decryption function cutter.cmd('CC Decrypted: %s @ %d' % (decrypted_string, xref['from']))
def get_disasm(self, start_address, end_address) -> list: result = [] start = int(start_address, 16) end = int(end_address, 16) while start <= end: cutter_data = cutter.cmdj("aoj @ " + str(start)) result.append(cutter_data[0]["disasm"]) start += cutter_data[0]["size"] return result
def get_hex(self, start_address, end_address) -> list: result = [] start = int(start_address, 16) end = int(end_address, 16) while start <= end: cutter_data = cutter.cmdj("aoj @ " + str(start)) # or p8j size @ addr result.append(cutter_data[0]["bytes"]) start += cutter_data[0]["size"] return result
def before_stateshot(self): self.vmmap = self._get_vmmap() self.base_addr = self.image_base() for sec in cutter.cmdj("iSj"): if sec["name"] == load_project( ).arch.got_section_name or sec["name"] == ".plt.got": self.got = (sec["vaddr"], sec["vaddr"] + sec["vsize"]) elif sec["name"] == ".plt": self.plt = (sec["vaddr"], sec["vaddr"] + sec["vsize"]) elif sec["name"] == ".idata": self.plt = (sec["vaddr"], sec["vaddr"] + sec["vsize"])
def decodeAll(self): # Start with analysis cutter.cmd('aa') # Build the decoder table self.buildDecoderTable() # Dump all the strings passed to decoder function for xref in cutter.cmdj("axtj %d" % self.decoder['fcn']): xref_addr = xref['from'] arg_len, arg_offsets = cutter.cmdj("pdj -2 @ %d" % xref_addr) if not 'val' in arg_len: continue indexes = cutter.cmdj("pxj %d @ %d" % (arg_len['val'] * 2, arg_offsets['val'])) decoded_str = self.decode(indexes) #print("%s @ %s" % (decoded_str, hex(xref_addr))) cutter.cmd("CC Decoded: %s @ %d" % (decoded_str, xref_addr)) # Refresh interface cutter.refresh()
def generate_callgraph(self): # TODO: get user settings for the .dot graph instead of using this hardcoded settings self.graph_dot = """digraph code { rankdir=LR; outputorder=edgesfirst; graph [bgcolor=azure fontname="Courier" splines="curved"]; node [fillcolor=white style=filled fontname="Courier New Bold" fontsize=14 shape=box]; edge [arrowhead="normal" style=bold weight=2];""" self.used_nodes = [] function_name = cutter.cmd('afi.') function_name = function_name.replace("\n", "") self.functions_list = cutter.cmdj('aflmj') self.get_calls(function_name) self.graph_dot += '\n}'
def _get_vmmap(self): memory_map = cutter.cmdj("dmj") maps = [] for m in memory_map: start = m["addr"] end = m["addr_end"] mapperm = 0 if "r" in m["perm"]: mapperm |= SEG_PROT_R if "w" in m["perm"]: mapperm |= SEG_PROT_W if "x" in m["perm"]: mapperm |= SEG_PROT_X maps += [(start, end, mapperm, m["name"])] return maps
def resolve_name(self, name): try: modules = cutter.cmdj("dmmj") for m in modules[1:]: addr = m["address"] lib = os.path.basename(m["name"]).split(".")[0].split("-")[0] o = cutter.cmd("dmi* %s %s" % (lib, name)) for line in o.split("\n"): line = line.split() if len(line) < 4: continue if line[1] == name or line[3] == "sym." + name: return int(line[3], 16) except: pass return None
def get_disassembly_of(self, address): #disasm_callee = cutter.cmdj("pdrj @ $F") if address == 0x0: return '' disassembly = cutter.cmdj("pdrj @ " + str(address)) disassembly_str = '' offset = '' fcn_addr = '' opcode = '' size = '' oldsize = 0 for dis_dict in disassembly: for key in dis_dict: if key == 'offset': offset = dis_dict['offset'] elif key == 'fcn_addr': fcn_addr = dis_dict['fcn_addr'] elif key == 'size': size = dis_dict['size'] elif key == 'opcode': opcode = dis_dict['opcode'] elif key == 'disasm': disasm = dis_dict['disasm'] ## 0x0000000000001394 <+18>: callq 0x1289 <my_function(int, char)> ## 0x00001394 call fcn.00001289 ##{"offset":5012,"esil":"4745,rip,8,rsp,-=,rsp,=[],rip,=","refptr":false,"fcn_addr":4994, ##"fcn_last":5019,"size":5,"opcode":"call 0x1289","disasm":"call fcn.00001289","bytes":"e8f0feffff", ##"family":"cpu","type":"call","reloc":false,"type_num":3,"type2_num":0,"jump":4745,"fail":5017, ##"refs":[{"addr":4745,"type":"CALL"}]} if offset and fcn_addr and opcode and size: #disassembly_str = disassembly_str + f"{offset:#0{18}x}" + ' <+' + str(oldsize) + '>: ' + opcode + '\n' disassembly_str = disassembly_str + opcode + '\n' oldsize += size offset = '' fcn_addr = '' opcode = '' size = '' return disassembly_str
def updateContents(self): try: registers = cutter.cmdj("drj gpr") except Exception as e: return self.setRowCount(0) for reg, value in registers.items(): row_position = self.rowCount() self.insertRow(row_position) self.setItem(row_position, 0, QTableWidgetItem(reg)) self.setItem(row_position, 1, QTableWidgetItem(str(value))) if reg in self.symRegs: # Color symbolic register in light blue self.item(row_position, 0).setBackground(QColor(52, 152, 219)) self.item(row_position, 1).setBackground(QColor(52, 152, 219))
def analyse_function(function, base, covbbs): entry = ["", function['name'], hex_pad(function['offset'], 8), "", ""] bbs = cutter.cmdj("afbj @" + function['name']) inst_count = 0 inst_hits = 0 bbs_count = 0 bbs_hits = 0 hit_set = set() to_be_added = {} for bblock in bbs: # radare2's basic block can't have jump inside it while that is # possible in DynamoRIO, for this reason we first need to check # if the size of the 2 basic block matches, if radare2's basic block # size is smaller thant we would add the next block untill the sizes # match. If dynamoRIO size is smaller then something is wrong with # r2 analysis or dynamoRIO coverage. bbs_count += 1 inst_count += bblock['ninstr'] dynamorio_size = 0 covbbaddr = bblock['addr'] - base if covbbaddr in covbbs: dynamorio_size = covbbs[covbbaddr] if bblock['addr'] in to_be_added: dynamorio_size = to_be_added[bblock['addr']] if dynamorio_size == 0: continue bbs_hits += 1 inst_hits += bblock['ninstr'] hit_set.add(bblock['addr']) r2_size = bblock['size'] if dynamorio_size > r2_size: to_be_added[bblock['addr'] + r2_size] = dynamorio_size - r2_size if bbs_hits == 0: return (None, hit_set) entry[3] = str(inst_hits) + "/" + str(inst_count) entry[4] = str(bbs_hits) + "/" + str(bbs_count) entry[0] = str(round(inst_hits * 100 / inst_count, 3)) + "%" return (entry, hit_set)
def file_dialog(self, title, new=False): if new: filename = QtWidgets.QFileDialog.getSaveFileName( self.main, title, self._last_directory, X64DBG_FILE_FILTERS)[0] # Append x64dbg's file prefix to the saved file # NOTE: This solution isn't ideal but preferred filename isn't available in # PySide's QtFileDialog constructor if not re.findall(".dd(64|32)", filename): bitness = cutter.cmdj("elJ asm.bits")[0]["value"] filename += f".dd{bitness}" else: filename = QtWidgets.QFileDialog.getOpenFileName( self.main, title, self._last_directory, X64DBG_FILE_FILTERS)[0] # Remember the last directory we were in (parsed from a selected file) # for the next time the user comes to load coverage files if filename: self._last_directory = os.path.dirname(filename) + os.sep cutter.message("[w64dbg-cutter] Received filename from file dialog:") cutter.message(" - %s" % filename) return filename
def update_contents(self): ### get actual loaded bin-filename ### cmdj('ij').get('Core').get('file') or something like that self.set_new_radare2_e() ## find data/code references to this address with $F curr_pos = cutter.cmd('s') #print(f'curr_pos >{curr_pos}<') if curr_pos.strip() == '0x0': return current_func_disas = cutter.cmdj("pdrj $F") disas_str = '' offset = '' fcn_addr = '' opcode = '' size = '' oldsize = 0 for dis_dict in current_func_disas: for key in dis_dict: if key == 'offset': #print(f"offset >{dis_dict['offset']}<") offset = dis_dict['offset'] #print(f"esil >{dis_dict['esil']}<") #print(f"refptr >{dis_dict['refptr']}<") elif key == 'fcn_addr': #print(f"fcn_addr >{dis_dict['fcn_addr']}<") fcn_addr = dis_dict['fcn_addr'] #elif key == 'fcn_last': #print(f"fcn_last >{dis_dict['fcn_last']}<") elif key == 'size': #print(f"size >{dis_dict['size']}<") size = dis_dict['size'] elif key == 'opcode': #print(f"opcode >{dis_dict['opcode']}<") opcode = dis_dict['opcode'] #elif key == 'disasm': #print(f"disasm >{dis_dict['disasm']}<") #print(f"bytes >{dis_dict['bytes']}<") #print(f"family >{dis_dict['family']}<") #print(f"type >{dis_dict['type']}<") #print(f"reloc >{dis_dict['reloc']}<") #print(f"type_num >{dis_dict['type_num']}<") #print(f"type2_num >{dis_dict['type2_num']}<") #print(f"flags >{dis_dict['flags']}<") #print(f"comment >{dis_dict['comment']}<") #f"{addr2:#0{18}x}" if offset and fcn_addr and opcode and size: disas_str = disas_str + f"{offset:#0{18}x}" + ' <+' + str(oldsize) + '>: ' + opcode + '\n' oldsize += size offset = '' fcn_addr = '' opcode = '' size = '' #a = current_func_disas. self._disasTextEdit.setPlainText("gdb-like disassembly:\n{}".format(disas_str))
def import_db(self): filename = self.file_dialog("Open x64dbg (Uncompressed) JSON database") if not filename: return cutter.message("[x64dbg-cutter]: Importing database %s" % filename) with open(filename) as dbdata: db = json.load(dbdata) # We can only import symbols for the main binary currently module = os.path.basename(cutter.cmdj("ij")["core"]["file"]).lower() base_addr = cutter.cmdj("evj bin.baddr")[0]["value"] count = 0 breakpoints = db.get("breakpoints", []) for bp in breakpoints: try: if bp["module"] != module: continue address = int(bp["address"], 16) + base_addr cutter.cmd("dbs " + str(address)) # Breakpoints created by dbs are enabled by default if not bp["enabled"]: cutter.cmd("dbd " + str(address)) count += 1 except: cutter.message("[x64dbg-cutter]: " + traceback.format_exc()) cutter.message("[x64dbg-cutter]: %d/%d breakpoints(s) imported" % (count, len(breakpoints))) count = 0 comments = db.get("comments", []) for comment in comments: try: if comment["module"] != module: continue address = int(comment["address"], 16) + base_addr text = base64.b64encode( comment["text"].encode("utf-8")).decode() cutter.cmd("CCu base64:" + text + " @ " + str(address)) count += 1 except: cutter.message("[x64dbg-cutter]: " + traceback.format_exc()) cutter.message("[x64dbg-cutter]: %d/%d comment(s) imported" % (count, len(comments))) # Create a new flagspace for x64dbg labels and bookmarks to allow easy removal cutter.cmd("fs x64dbgcutter.labels") count = 0 labels = db.get("labels", []) for label in labels: try: if label["module"] != module: continue address = int(label["address"], 16) + base_addr # Spaces don't show up in flags, use underscore instead text = label["text"].replace(" ", "_") cutter.cmd("f " + text + " @ " + str(address)) count += 1 except: cutter.message("[x64dbg-cutter]: " + traceback.format_exc()) cutter.message("[x64dbg-cutter]: %d/%d label(s) imported" % (count, len(labels))) cutter.cmd("fs x64dbgcutter.bookmarks") count = 0 bookmarks = db.get("bookmarks", []) for bookmark in bookmarks: try: if bookmark["module"] != module: continue address = int(bookmark["address"], 16) + base_addr cutter.cmd("f " + "bookmark_" + str(address) + " @ " + str(address)) count += 1 except: cutter.message("[x64dbg-cutter]: " + traceback.format_exc()) cutter.message("[x64dbg-cutter]: %d/%d bookmark(s) imported" % (count, len(bookmarks))) cutter.message("[x64dbg-cutter]: Done!")
def run(self): self.updateProgressBar.emit(1) curr_pos = cutter.cmd('s') if curr_pos.strip() == '0x0': print('runInference not from addr 0x0') return self.set_new_radare2_e() ### get name of current function current_func_name = cutter.cmdj("afdj $F").get('name') #print(f'current_func_name >{current_func_name}<') ## find data/code references to this address with $F current_func_header = cutter.cmdj("axtj $F") ## get addr of callee caller_addr = 0 for item_dicts in current_func_header: print(f'item_dicts >{item_dicts}<') for elem in item_dicts: if elem == 'from': caller_addr = item_dicts[elem] #print(f'address of caller >{item_dicts[elem]}<') ## get disassembly of current/callee function address = cutter.cmd('s').strip() #print(f'address >{address}<') if address == '0x0': self.updateProgressBar.emit(100) self.resultReady.emit('') self.summaryReady.emit('Current address is 0x0, choose other function') #print(f'address kicked >{address}<') return disasm_callee_str = self.get_disassembly_of(address) #print(f'disasm_callee_str >{disasm_callee_str}<') ### get disassembly of caller function disasm_caller_str = self.get_disassembly_of(caller_addr) #print(f'disasm_caller_str >{disasm_caller_str}<') ### split disas for the tf-model disasm_caller_str = disassembly_lib.split_disassembly(disasm_caller_str) disasm_callee_str = disassembly_lib.split_disassembly(disasm_callee_str) ##check if we got caller and callee disassembly if (len(disasm_caller_str) == 0) or (len(disasm_callee_str) == 0): self.updateProgressBar.emit(100) self.resultReady.emit('') self.summaryReady.emit('No caller disassembly found, choose other function') #print(f'Not found callee and caller disassembly.') return ### the path were we cloned git repo to self._userHomePath = os.path.expanduser('~') #print(f'userHomePath >{self._userHomePath}<') func_sign_prob_git_path = self._userHomePath + "/git/func_sign_prob/" self.updateProgressBar.emit(9) callee_addr_split = [char if char != '0' else 'null' for char in address] callee_addr = ' '.join(callee_addr_split) disasm_caller_callee_predict_str = disasm_caller_str + ' caller_callee_separator ' + callee_addr + ' ' + disasm_callee_str ### predict now ret-type ret_type_prediction_summary_str = self.get_prediction('return_type/words_100000', disasm_caller_callee_predict_str, func_sign_prob_git_path) ## store for later, will be overridden ret_type_model_summary_str = self.model_summary_str ret_type_biggest_prob = self.biggest_prob ret_type_biggest_prob_type = self.biggest_prob_type ret_type_biggest_prob_percent = 100 * ret_type_biggest_prob self.updateProgressBar.emit(10) ### predict now nr_of_args nr_of_args_prediction_summary_str = self.get_prediction('nr_of_args/words_100000', disasm_caller_callee_predict_str, func_sign_prob_git_path) ## store for later, will be overridden nr_of_args_model_summary_str = self.model_summary_str nr_of_args_biggest_prob = self.biggest_prob nr_of_args_biggest_prob_type = self.biggest_prob_type self.updateProgressBar.emit(20) ###predict now arg_one arg_one_prediction_summary_str = self.get_prediction('arg_one', disasm_caller_callee_predict_str, func_sign_prob_git_path) ## store for later, will be overridden arg_one_model_summary_str = self.model_summary_str arg_one_biggest_prob = self.biggest_prob arg_one_biggest_prob_type = self.biggest_prob_type arg_one_biggest_prob_percent = 100 * arg_one_biggest_prob #nr_of_args_biggest_prob_type = 1 if nr_of_args_biggest_prob_type == 1: self.set_stored_radare2_e() self.updateProgressBar.emit(100) self.summaryReady.emit(f"tf return type model summary:\n \ {ret_type_model_summary_str}\n \ {ret_type_prediction_summary_str}\n \ tf nr_of_args model summary:\n \ {nr_of_args_model_summary_str}\n \ {nr_of_args_prediction_summary_str}\n \ tf arg_one model summary:\n \ {self.model_summary_str}\n \ {arg_one_prediction_summary_str}") self.resultReady.emit(f'{ret_type_biggest_prob_type} \ <span style=\"background-color:red;\">({ret_type_biggest_prob_percent:3.1f}%)</span> \ {current_func_name} ( \ {arg_one_biggest_prob_type} \ <span style=\"background-color:red;\">({arg_one_biggest_prob_percent:3.1f}%)</span> \ )') return else: self.updateProgressBar.emit(30) ###if more one args ###predict now arg_two arg_two_prediction_summary_str = self.get_prediction('arg_two', disasm_caller_callee_predict_str, func_sign_prob_git_path) ## store for later, will be overridden arg_two_model_summary_str = self.model_summary_str arg_two_biggest_prob = self.biggest_prob arg_two_biggest_prob_type = self.biggest_prob_type arg_two_biggest_prob_percent = 100 * arg_two_biggest_prob #nr_of_args_biggest_prob_type = 2 if nr_of_args_biggest_prob_type == 2: self.updateProgressBar.emit(100) self.summaryReady.emit(f"tf return type model summary:\n \ {ret_type_model_summary_str}\n \ {ret_type_prediction_summary_str}\n \ tf nr_of_args model summary:\n \ {nr_of_args_model_summary_str}\n \ {nr_of_args_prediction_summary_str}\n \ tf arg_one model summary:\n \ {arg_one_model_summary_str}\n \ {arg_one_prediction_summary_str}\n \ tf arg_two model summary:\n \ {arg_two_model_summary_str}\n \ {arg_two_prediction_summary_str}") self.resultReady.emit(f'{ret_type_biggest_prob_type} \ <span style=\"background-color:red;\">({ret_type_biggest_prob_percent:3.1f}%)</span> \ {current_func_name} ( \ {arg_one_biggest_prob_type} \ <span style=\"background-color:red;\">({arg_one_biggest_prob_percent:3.1f}%)</span> , \ {arg_two_biggest_prob_type} \ <span style=\"background-color:red;\">({arg_two_biggest_prob_percent:3.1f}%)</span> \ )') self.set_stored_radare2_e() return else: self.updateProgressBar.emit(40) ###if more than two args ###predict now arg_three arg_three_prediction_summary_str = self.get_prediction('arg_three', disasm_caller_callee_predict_str, func_sign_prob_git_path) ## store for later, will be overridden arg_three_model_summary_str = self.model_summary_str arg_three_biggest_prob = self.biggest_prob arg_three_biggest_prob_type = self.biggest_prob_type arg_three_biggest_prob_percent = 100 * arg_three_biggest_prob #nr_of_args_biggest_prob_type = 3 if nr_of_args_biggest_prob_type >= 3: #hack, if more args, need more models self.updateProgressBar.emit(100) self.summaryReady.emit(f"tf return type model summary:\n \ {ret_type_model_summary_str}\n \ {ret_type_prediction_summary_str}\n \ tf nr_of_args model summary:\n \ {nr_of_args_model_summary_str}\n \ {nr_of_args_prediction_summary_str}\n \ tf arg_one model summary:\n \ {arg_one_model_summary_str}\n \ {arg_one_prediction_summary_str}\n \ tf arg_two model summary:\n \ {arg_two_model_summary_str}\n \ {arg_two_prediction_summary_str}\n \ tf arg_three model summary:\n \ {arg_three_model_summary_str}\n \ {arg_three_prediction_summary_str}") self.resultReady.emit(f'{ret_type_biggest_prob_type} \ <span style=\"background-color:red;\">({ret_type_biggest_prob_percent:3.1f}%)</span> \ {current_func_name} ( \ {arg_one_biggest_prob_type} \ <span style=\"background-color:red;\">({arg_one_biggest_prob_percent:3.1f}%)</span> , \ {arg_two_biggest_prob_type} \ <span style=\"background-color:red;\">({arg_two_biggest_prob_percent:3.1f}%)</span> , \ {arg_three_biggest_prob_type} \ <span style=\"background-color:red;\">({arg_three_biggest_prob_percent:3.1f}%)</span> \ )') self.set_stored_radare2_e() return else: self.updateProgressBar.emit(50) #for debug print('over') self.set_stored_radare2_e() # /* ... here is the expensive or blocking operation ... */ self.resultReady.emit('')
def get_function_boundries_at_current_location(): function_info = cutter.cmdj('afij') if len(function_info): return (function_info[0]['minbound'], function_info[0]['maxbound']) else: return None
def get_filename(self): """Returns working project from Cutter pipe.""" binary_information = cutter.cmdj('ij') filename = binary_information['core']['file'] return filename
def get_md5(self) -> str: return cutter.cmdj("itj").get("md5", None)