def print_macho_header(header, oid, opts, embedded=False): src = api.source(oid) file_size = api.get_field("file_meta", oid, "size") names = api.get_names_from_oid(oid) indent = False tab = "" if embedded: indent = True tab = "\t" if embedded: print "%s Embedded Macho-O Header for %s %s" % (tab, name(oid), oid) else: print " Macho-O Header for %s %s" % (name(oid), oid) if not header: print " <EMPTY>" print " --------------------------" return entry_string = "" for e in header.get_entries(): entry_string += "%s (%s) " % (hex(e), (e)) print "%s - File Size: %s" % (tab, file_size) # FIXME get embedded file size print "%s - Addr Size: %s" % (tab, header.insn_mode) print "%s - Magic: %s" % (tab, header.magic) print "%s - Big Endian: %s" % (tab, header.big_endian) print "%s - Machine: %s" % (tab, header.machine) print "%s - UUID: %s" % (tab, header.uuid) print "%s - Entry points: %s" % (tab, entry_string) print_sections(header, opts, indent) macho_import_table(header, opts)
def elf_header(oid, opts): header = api.get_field("object_header", [oid], "header") src = api.source(oid) file_size = api.get_field("file_meta", oid, "size") names = api.get_names_from_oid(oid) print " ELF Header for %s %s" % (name(oid), oid) if not header: print " <EMPTY>" print " --------------------------" return addr_size = "32 bit" if header.is_64bit(): addr_size = "64 bit" entry_string = "" for e in header.get_entries(): entry_string += "%s (%s) " % (hex(e), (e)) print " - File Size: %s" % (file_size) print " - Addr Size: %s" % (addr_size) print " - Image Base: %s (%s)" % (hex(header.image_base), header.image_base) print " - Image Size: %s " % (header.image_size) print " - Code Size: %s " % (header.code_size) print " - Code Base: %s (%s)" % (hex(header.code_base), header.code_base) print " - Machine: %s" % (header.machine) print " - OS Version: %s" % (header.os_version) print " - Entry points: %s" % (entry_string) print_sections(header, opts) elf_import_table(header, opts)
def mapper(oid, opts, jobid=False): logger.debug("mapper()") src = api.source(oid) if api.documentation(src)["set"]: return None if api.exists(name, oid, opts): return oid out_histo = build_ngrams(api.retrieve(src, oid, opts)["data"], opts["n"]) api.store(name, oid, out_histo, opts) return oid
def mapper(oid, opts, jobid=False): logger.debug("mapper()") src = api.source(oid) if api.exists(name, oid, opts): return oid data = api.get_field(src, oid, "data") if not data: return None out_histo = build_histo(data) api.store(name, oid, out_histo, opts) return oid
def process(oid, opts=None): logger.debug("process()") src = api.source(oid) src_type = {"source":src} logger.debug("Processing file %s", str(oid)) if src == "collections": src_type["type"] = "collection" else: src_type["type"] = file_type(api.get_field(src, oid, "data")) api.store(name, oid, src_type, opts) return True
def mapper(oid, opts, jobid=False): logger.debug("mapper()") src = api.source(oid) if api.documentation(src)["set"]: return None if api.exists(name, oid, opts): return oid opcodes = api.get_field("opcodes", oid, "opcodes") if not opcodes: return None out_histo = build_histo(opcodes) api.store(name, oid, out_histo, opts) return oid
def mapper(oid, opts, jobid=False): logger.debug("mapper()") src = api.source(oid) if api.documentation(src)["set"]: return None if api.exists(name, oid, opts): return oid nops = api.retrieve("nops", oid, opts) if not nops: return None out_histo = nop_histo(nops) api.store(name, oid, out_histo, opts) return oid
def mapper(oid, opts, jobid=False): logger.debug("mapper()") src = api.source(oid) if api.exists(name, oid, opts): return oid map_imports = api.get_field("map_calls", oid, "system_calls") if not map_imports: return None out_histo = defaultdict(int) for addr in map_imports: out_histo[map_imports[addr]] = out_histo[map_imports[addr]] + 1 api.store(name, oid, out_histo, opts) return oid
def process(oid, opts): logger.debug("process()") src_type = api.get_field("src_type", oid, "type") if src_type != "DEX": return False src = api.source(oid) data = api.get_field(src, oid, "data") if not data: logger.debug("Not able to process %s",oid) return False result = parse_dex(data, oid) if result: api.store(name, oid, result, opts) return True return False
def process(oid, opts): logger.debug("process()") data = api.get_field(api.source(oid), oid, "data") if not data: return False strings = {} offset = 0 for c in data: i = ord(c) if i >= 32 and i <= 126: strings[offset] = c offset += 1 api.store(name, oid, strings, opts) return True
def unarchive(args, opts): """ Try in unarchive (unzip and untar), passes a list of ununarchived oids Syntax: unarchive <oid_1> <oid_2> ... <oid_n> """ valid, invalid = api.valid_oids(args) if not valid: raise ShellSyntaxError("No valid oids found") oids = api.expand_oids(valid) unarchived = [] newfiles = [] print " - Attempting to unarchive (zip, tar) %d files" % len(oids) p = progress.progress(len(oids)) for oid in oids: data = api.get_field(api.source(oid), oid, "data") if not data: print "Not able to process %s" % (oid) p.tick() continue tmp = tmp_file(oid, data) if not tmp: continue aoids = [] noids = [] if tarfile.is_tarfile(tmp): # tar print " - Unpacking a tar file" aoids, noids = import_tarfile(tmp, parent_oid=oid) elif zipfile.is_zipfile(tmp): # zip print " - Unpacking a zip file" aoids, noids = import_zipfile(tmp, parent_oid=oid) unarchived.extend(aoids) newfiles.extend(noids) os.remove(tmp) p.tick() if unarchived: unarchived.extend(unarchive(unarchived, opts)) # Unpacked children print " - Extracted %d files %d are new" % (len(unarchived), len(newfiles)) return unarchived
def process(oid, opts): logger.debug("process()") src_type = api.retrieve("src_type", oid, {}) if src_type["type"] != "MACHO" and src_type["type"] != "OSX Universal Binary": return False src = api.source(oid) data = api.get_field(src, oid, "data", {}) if not data: logger.debug("Not able to process %s",oid) return False result = process_macho(data, oid) if result: api.store(name, oid, result, opts) return True return False
def process(oid, opts): logger.debug("process()") functions = api.retrieve("function_extract", oid) if not functions: return False header = api.get_field("object_header", oid, "header") if not header: return False data = api.get_field(api.source(oid), oid, "data") if not data: return False g = build_basic_blocks(functions, header, data) api.store(name, oid, g, opts) return True
def process(oid, opts): logger.debug("process()") src_type = api.retrieve("src_type", oid, {}) if src_type["type"] != "ELF": return False src = api.source(oid) data = api.get_field(src, oid, "data", {}) if not data: logger.debug("Not able to process %s",oid) return False result = parse_elf(data, oid) if result: api.store(name, oid, result, opts) return True return False
def crypto(args, opts): """ Plugin: Looks for cryptographic methods inside binary files Synatax: crypto %oid --<cryptographic functions>|show Example: crypto %oid --sha1 --sha256 --aes """ args, invalid = api.valid_oids(args) if not args: raise ShellSyntaxError("Must provide an oid") args = api.expand_oids(args) allData = {} if not opts: opts['sha1'] = "" opts['sha256'] = "" opts['aes'] = "" for oid in args: src = api.source(oid) file_data = api.get_field(src, oid, "data") asm = api.retrieve('function_extract', [oid]) if not asm: continue #print asm retVal = {} if 'sha1' in opts: sha1Percent = findSha1(asm,file_data,retVal) retVal['SHA1']['Percent']=sha1Percent*100 if 'sha256'in opts: sha256Percent = findSha256(asm,file_data,retVal) retVal['SHA256']['Percent']=sha256Percent*100 if 'aes' in opts: aesPercent = findAES(asm,file_data,retVal) retVal['AES']['Percent']=aesPercent*100 allData[oid] = retVal return allData
def osx_header(oid, opts): header = api.get_field("object_header", [oid], "header") src = api.source(oid) file_size = api.get_field("file_meta", oid, "size") names = api.get_names_from_oid(oid) print " OSX Universal Header for %s %s" % (name(oid), oid) if not header: print " <EMPTY>" print " --------------------------" return print " - File Size: %s" % (file_size) print " - Magic: %s" % (header.magic) print " - Big Endian: %s" % (header.big_endian) print " - Embedded Files: %s" % (header.num_embedded) for header in header.embedded: print " -------------------------------------" print_macho_header(header, oid, opts, embedded=True) print " -------------------------------------" print
def dump_js(args, opts): valid, invalid = api.valid_oids(args) oids = api.expand_oids(valid) if not oids: raise ShellSyntaxError("No valid oids") for o in oids: type = api.get_field("src_type", o, "type") if type != "PDF": continue src = api.source(o) data = api.get_field(src, o, "data") i = data.find("<script") while i > -1: j = data.find("</script>") if j > -1: print "Found script:" print data[i:j+9] data = data[j:] i = data.find("<script")
def process(oid, opts): logger.debug("process()") src = api.source(oid) file_data = api.get_field(src, oid, "data") hopts = {"fake":opts['force']} header = api.get_field("object_header", [oid], "header", hopts) if not file_data or not header: return False # do not disassemble under certain conditions if (not opts['force'] and not header.known_format): logger.debug("Not processing oid %s: unrecognized file type", oid) return False logger.debug("calling (python-based) disassemble_linear on %s", oid) insns = disassemble_linear(file_data, header, logger) data = {"insns":insns, "num_insns":len(insns), "insn_mode":header.insn_mode} api.store(name, oid, data, opts) return True
def untar(args, opts): """ Try to untar items passed, passes a list of untarred oids Syntax: untar <oid_1> <oid_2> ... <oid_n> """ valid, invalid = api.valid_oids(args) if not valid: raise ShellSyntaxError("No valid oids found") oids = api.expand_oids(valid) untarred = [] newfiles = [] p = progress.progress(len(oids)) print " - Attempting to untar %d files" % len(oids) for oid in oids: src = api.source(oid) data = api.get_field(src, oid, "data") if not data: print "No data found for %s" % (oid) p.tick() continue tmpname = oid + ".tar.tmp" tmp = tmp_file(tmpname, data) if not tmp: continue if tarfile.is_tarfile(tmp): toids, nfiles = import_tarfile(tmp, parent_oid=oid) untarred.extend(toids) newfiles.extend(nfiles) os.remove(tmp) p.tick() if untarred: untarred.extend(untar(untarred, opts)) # Untar children print " - %d files extracted, %d files are new" % (len(untarred), len(newfiles)) return untarred
def results(oid_list, opts): logger.debug("results()") if len(oid_list) != 1: logger.error("%s called incorrectly with an invalid list of IDs."%name) oid = oid_list[0] header = None src_type = api.get_field("src_type", oid, "type") if src_type == "PE": header = api.get_field("pe", oid, "header") elif src_type == "ELF": header = api.get_field("elf", oid, "header") elif src_type == "MACHO" or src_type == "OSX Universal Binary": header = api.get_field("macho", oid, "header") if opts["fake"] == True and header == None: data = api.get_field(api.source(oid), oid, "data") if data: header = fake_header(data) if not header: return None return {"header":header}
def upx(args, opts): """ Try to upx unpack items passed, passes a list of unpacked oids Syntax: upx <oid_1> <oid_2> ... <oid_n> """ valid, invalid = api.valid_oids(args) if not valid: raise ShellSyntaxError("No valid oids found") oids = api.expand_oids(valid) unupx = [] newfiles = [] p = progress.progress(len(oids)) print " - Attempting to UPX unpack %d files" % len(oids) for oid in oids: data = api.get_field(api.source(oid), oid, "data") if not data: print "No data found for %s" % (oid) p.tick() continue meta = api.retrieve("file_meta", oid) name = meta["names"].pop() tmpname = name + ".unpacked_upx" tmp = tmp_file(tmpname, data) if not tmp: continue if is_upx(tmp): uoids, noids = import_upxfile(tmp, parent_oid=oid) unupx.extend(uoids) newfiles.extend(noids) os.remove(tmp) p.tick() print " - %d files extracted, %d are new" % (len(unupx), len(newfiles)) return unupx
def hex_view(args, opts): """ Print the hex values of a file and the disassebmly Syntax: hex_print %<oid> --slice=<start>:<stop> --width=<int> --height=<int> --less [--module=[linear_disassembler]] """ args, invalid = api.valid_oids(args) args = api.expand_oids(args) if not args: if current_file: args = [current_file] else: raise ShellSyntaxError("Must provide an oid or use re_init to set file.") oid = args[0] labels = [] new_args = [] mod_opts = {} if "module" in opts: mod_opts["module"] = opts["module"] if "interactive" in opts: mod_opts["interactive"] = opts["interactive"] disassm = api.get_field("disassembly", [oid], "insns", mod_opts) comments = api.get_field("disassembly", [oid], "comments", mod_opts) if comments: labels.append(comments) start = stop = 0 width = default_width height = default_height if "slice" in opts: start, stop = get_slice(opts) if "width" in opts: try: width = int(opts["width"]) except ValueError: raise ShellSyntaxError("Invalid width") if "height" in opts: try: height = int(opts["height"]) except ValueError: raise ShellSyntaxError("Invalid height") less = False if "less" in opts: less = True heatoid = None if "heatmap" in opts: heatoid, invalid = api.valid_oids([opts["heatmap"]]) for arg in args: # First separate lables from other items if isinstance(arg, dict) and "data" not in arg: labels.append(arg) else: new_args.append(arg) for arg in new_args: src = api.source(arg) if isinstance(arg, dict) and "data" in arg: # arg is the output of 'run files <oid>' print_hex_string(arg["data"], labels, disassm, heatoid, start, stop, width, height, less) elif isinstance(arg, str) and src and api.exists(src, arg): # oid was passed data = api.get_field(src, arg, "data") print_hex_string(data, labels, disassm, heatoid, start, stop, width, height, less) elif isinstance(arg, str): print_hex_string(arg, labels, disassm, heatoid, start, stop, width, height, less) else: print " - Can't print arg %s" % arg
def process(oid, opts): logger.debug("process()") header = api.get_field("object_header", oid, "header") if not header: return False disasm = api.get_field("disassembly", oid, "insns") if not disasm: return False file_data = api.get_field(api.source(oid), oid, "data") if not file_data: return False internal_functions = api.retrieve("function_extract", oid) mapping = {} imps = {} ord_map = api.load_reference("ordinal_map") src_type = api.get_field("src_type", oid, "type") if src_type == "PE": imports = header.symbol_table for i in imports: if isinstance(imports[i]['name'], str): # we have a name imps[i] = imports[i]['name'] else: # we have an ordinal dll_name = imports[i]["dll"].lower() if dll_name in ord_map: if imports[i]['name'] in ord_map[dll_name]: imps[i] = ord_map[dll_name][imports[i]['name']] if i not in imps: imps[i] = dll_name + ":Ordinal " + str(imports[i]['name']) data = { "system_calls":{}, "internal_functions":{}, "unresolved_calls":{} } # Find location of jump table. Calls in program will call these stubs which then # jump to external functions. for i in disasm: insn = disasm[i] if insn["mnem"] in ("jmp"): target_op = insn.get("d_op", None) if not target_op: continue if isinstance(target_op["data"], int): target = target_op["data"] elif "disp" in target_op["data"]: target = target_op["data"]["disp"] else: continue if target in imps: mapping[insn["addr"]] = imps[target] data["system_calls"][i] = imps[target] for i in disasm: insn = disasm[i] target = 0 if insn["mnem"] in ("call", "callcc"): if insn['d_op']['type'] == 'eff_addr' and not insn['d_op']['data']['base']: target = insn['d_op']['data']['disp'] else: target = re_lib.resolve_target_operand(insn, header, file_data, internal_functions) if target in mapping: data["system_calls"][i] = mapping[target] elif target in imps: data["system_calls"][i] = imps[target] elif target in internal_functions: data["internal_functions"][i] = internal_functions[target]["name"] else: data["unresolved_calls"][i] = target api.store(name, oid, data, opts) return True