def main(filename=None): if filename is None: filename = fileopenbox(msg="Select PDF file", default="*.pdf", filetypes=["*.pdf"]) if filename is None: return pyew = CPyew(batch=True) pyew.loadFile(filename) streams = pyew.plugins["pdfilter"](pyew, doprint=True) if len(streams) == 0: msgbox(title="PDF Streams",msg="No encoded streams found") l = [] l.append("About PDF Streams Viewer") l.append("See all streams (both encoded and unencoded)") for x in streams: l.append("Stream %d encoded with %s" % (x, streams[x])) l.append("Quit") while 1: c = choicebox(msg="Select one stream to view it decoded", title="Stream Viewer", choices=l) if c is None: break elif c.lower() == "quit": break elif c.lower().startswith("about"): msgbox(title="About PDF Streams Viewer", msg="Example usage of the Pyew APIs to see PDF streams. Written by Joxean Koret") elif c.lower().startswith("see all"): pyew.plugins["pdfview"](pyew, doprint=False, stream_id=-1) else: stream_id = int(c.split(" ")[1]) pyew.plugins["pdfview"](pyew, stream_id=stream_id)
def __init__(self, binary, sc, out): self.binary = binary self.sc = sc self.out = out self.pyew = CPyew(False, False) self.sc_buf = None
def check_file(self, filename): self.current_file = filename pyew = CPyew(batch=True, plugins=True) pyew.codeanalysis = True pyew.deepcodeanalysis = self.deep try: pyew.loadFile(filename) except: raise Exception("Error loading file: %s" % str(sys.exc_info()[1])) if pyew.format not in ["PE", "ELF", "BOOT", "BIOS"]: sys.stderr.write("[INFO] Ignoring non supported executable file\n") sys.stderr.flush() return program_stats = pyew.program_stats md5_hash = md5(pyew.getBuffer()).hexdigest() if self.check_or_update(md5_hash, program_stats): print "[OK] Test %s (%s)" % (filename, md5_hash) else: msg = "[FAILED] *** Test %s (%s)" print msg % (filename, md5_hash) self.show_reason(program_stats)
def processFile(self, filename): #print "[+] Analyzing file %s" % filename pyew = CPyew(batch=True) pyew.deepcodeanalysis = self.deep pyew.analysis_timeout = 0 pyew.loadFile(filename) if pyew.format in ["PE", "ELF"]: hash = sha256(pyew.getBuffer()).hexdigest() self.data.append({hash: pyew}) else: sys.stderr.writelines("Not a PE/ELF file") sys.stderr.flush()
def checkMebroot(path): pyew = CPyew(batch=True) pyew.codeanalysis = True try: pyew.loadFile(path) except: print "ERROR loading file %s" % path return if pyew.format == "PE": # Get 6 bytes at offset 0xB8 if pyew.getBytes(0xB8, 6) != "Rich;\x2E": return printData(pyew, path, "Mebroot downloader") print
def entryPointCalls(path): pyew = CPyew(batch=True) pyew.codeanalysis = True try: pyew.loadFile(path) except KeyboardInterrupt: print "Abort" sys.exit(0) except: print "ERROR loading file %s" % path return if pyew.format != "PE": return calls = [] # Get the disassembl of the first 100 lines l = pyew.disasm(pyew.ep, processor=pyew.processor, type=pyew.type, lines=100, bsize=1600) for i in l: mnem = str(i.mnemonic) # Is it a direct or indirect jump or call? if mnem == "CALL" or mnem.startswith("J") or mnem.startswith("LOOP"): operands = str(i.operands).replace("[", "").replace("]", "") try: if pyew.imports.has_key(int(operands, 16)): x = pyew.imports[int(operands, 16)] if x not in calls: calls.append(x) except: pass if len(calls) > 0: printData(pyew, path, "Library calls at Entry Point") print "Library Calls:", ",".join(calls) print
def checkAntidebug(path): t = time.time() pyew = CPyew(batch=True) pyew.codeanalysis = True try: pyew.loadFile(path) except KeyboardInterrupt: print "Abort" sys.exit(0) except: print "ERROR loading file %s" % path return if pyew.format not in ["PE", "ELF"]: return if len(pyew.antidebug) > 0: print printData(pyew, path, pyew.antidebug) print "Time to analyze %f" % (time.time() - t) print
def checkMnemonics(path): pyew = CPyew(batch=True) pyew.codeanalysis = True try: pyew.loadFile(path) except: print "ERROR loading file %s" % path return # Is it a PE file? if pyew.format == "PE": # The most common x86 mnemonics commons = ["PUSH", "MOV", "SUB", "ADD", "LEA", "CALL", "JMP", "JZ", "JNZ", \ "OR", "XOR", "NOT", "POP", "AND", "TEST", "JL", "JG", "JE", \ "JLE", "CMP", "LEAVE", "RET", "NOP", "PUSHF", "POPF", "INC", \ "INT 3", "DEC", "PUSHA", "POPA"] try: # Get the 30 first mnemonics mnems = pyew.GetMnems(pyew.ep, 30) except: print "ERROR scanning file %s" % path return ret = [] for x in mnems: if x not in commons and x not in ret: ret.append(x) if len(ret) > 0: printData(pyew, path, "Uncommon mnemonics") print "Mnemonics:", ",".join(ret) print # Seek to the entry point pyew.seek(pyew.ep) # Hexdump the first 64 bytes at the entry point print pyew.hexdump(pyew.buf, length=16, bsize=64)
def analyse(self, path): filename = path t = time.time() buf = open(filename, "rb").read() sha1_hash = sha1(buf).hexdigest() if self.file_exists(sha1_hash): log("Already existing file %s..." % sha1_hash) return ANALYSIS_ALREADY pyew = CPyew(batch=True) pyew.analysis_timeout = 300 pyew.codeanalysis = True pyew.deepcodeanalysis = True try: pyew.loadFile(path) load_error = False except KeyboardInterrupt: log("Abort") return ANALYSIS_FAILED except: log("ERROR loading file %s" % path) load_error = True if not load_error: if pyew.format not in ["PE", "ELF", "bootsector"]: if pyew.format not in ["PDF", "OLE2"]: log("Not a known executable/document format") load_error = True if load_error: return ANALYSIS_FAILED primes = [] total_functions = len(pyew.function_stats) if not load_error and total_functions > 0: nodes = [] edges = [] ccs = [] callgraph = 1 for x in pyew.function_stats: nodes.append(pyew.function_stats[x][0]) edges.append(pyew.function_stats[x][1]) cc = pyew.function_stats[x][2] ccs.append(cc) prime = self.primes_table[cc] callgraph *= prime primes.append(prime) avg_nodes = abs(sum(nodes) / total_functions) avg_edges = abs(sum(edges) / total_functions) avg_ccs = abs(sum(ccs) / total_functions) elif load_error: total_functions = avg_nodes = avg_edges = avg_ccs = -1 callgraph = -1 msg = "%d-%d-%d-%d" % (total_functions, avg_nodes, avg_edges, avg_ccs) log("File analysed %s, callgraph signature %s" % (msg, callgraph)) log("Time to analyze %f" % (time.time() - t)) callgraph = str(callgraph) primes = ",".join(map(str, primes)) desc = self.get_description(buf) self.db.insert("samples", filename=filename, callgraph=callgraph, \ hash=sha1_hash, total_functions=total_functions, \ format=pyew.format, primes=primes, description=desc,\ analysis_date=time.asctime()) return ANALYSIS_SUCCESS
import os, sys from pyew_core import CPyew sys.path.append("plugins") #import diagrams #import easygui #import graphs #import ole2 #import OleFileIO_PL #import packer #import pdf #import pdfid_PL #import shellcode #import threatexpert #import url #import virustotal #import vmdetect #import xdot filename = sys.argv[1] pyew = CPyew(batch=True) pyew.loadFile(filename, "rb") pyew.offset = 0 #pyew.pe.header for addr in pyew.basic_blocks.keys(): print addr
def main(filename): pyew = CPyew() if os.getenv("PYEW_DEBUG"): pyew.debug=True else: pyew.debug = False pyew.loadFile(filename, "rb") if pyew.format in ["PE", "ELF"]: saveAndCompareInDatabase(pyew) pyew.offset = 0 print pyew.hexdump(pyew.buf, pyew.hexcolumns) oldpyew = None cmd = "" last_cmd = "" pyew.previousoffset = [] # Add global object's references for easier usage pe = pyew.pe elf = pyew.elf # Set AutoCompletion setupAutoCompletion(pyew) # Check if there is runme.py file if os.path.exists('runme.py'): f = open('runme.py', 'r') commands = f.readlines() f.close() while 1: try: last_cmd = cmd if len(pyew.previousoffset) > 0: if pyew.previousoffset[len(pyew.previousoffset)-1] != pyew.offset: pyew.previousoffset.append(pyew.offset) else: pyew.previousoffset.append(pyew.offset) va = None if pyew.virtual: va = pyew.getVirtualAddressFromOffset(pyew.offset) if va: prompt = "[0x%08x:0x%08x]> " % (pyew.offset, va) else: prompt = "[0x%08x]> " % pyew.offset try: cmd = commands[0].rstrip() commands.pop(0) except: cmd = raw_input(prompt) if cmd in ["", "b"] and (last_cmd in ["b", "x", "c", "d", "dump", "hexdump", "dis", "pd", "p", "r", "buf"] or last_cmd.isdigit()): if cmd == "b": tmp = pyew.previousoffset.pop() if len(pyew.previousoffset) > 0: tmp = pyew.previousoffset[len(pyew.previousoffset)-1] else: tmp = 0 pyew.offset = tmp pyew.lastasmoffset = tmp pyew.seek(tmp) if last_cmd.isdigit(): last_cmd = "c" elif cmd == "b" and last_cmd == "b": if len(pyew.previousoffset) < 2: continue tmp = pyew.previousoffset.pop() tmp = pyew.previousoffset[len(pyew.previousoffset)-1] pyew.seek(tmp) continue elif last_cmd in ["c", "d", "pd"] or last_cmd.isdigit(): pyew.offset = pyew.lastasmoffset pyew.seek(pyew.offset) if last_cmd.isdigit(): last_cmd = "c" else: pyew.offset = pyew.offset+pyew.bsize pyew.seek(pyew.offset) cmd = last_cmd except EOFError: break except KeyboardInterrupt: break try: if cmd.strip(" ") == "": continue if cmd.lower() in ["exit", "quit", "q"]: break elif cmd.lower() in ["a", "anal"]: pyew.findFunctions(pyew.processor) print elif cmd.lower() in ["x", "dump", "hexdump"]: print pyew.hexdump(pyew.buf, pyew.hexcolumns, baseoffset=pyew.offset) elif cmd.split(" ")[0] in ["s", "seek"]: data = cmd.split(" ") if len(data) > 1: if data[1].lower() in ["ep", "entrypoint"]: if pyew.ep: pyew.offset = pyew.ep else: pyew.names.has_key(data[1].lower()) if data[1].lower()[0] in ["+", "-"]: pyew.offset += int(data[1]) elif data[1].lower().startswith("0x"): pyew.offset = int(data[1], 16) elif data[1] in pyew.names.values(): for x in pyew.names: if pyew.names[x] == data[1]: pyew.offset = x break else: pyew.offset = int(data[1]) pyew.seek(pyew.offset) elif cmd.lower().split(" ")[0] in ["c", "d", "dis", "pd"]: data = cmd.lower().split(" ") if len(data) > 1: if not data[1].startswith("/"): type = int(data[1]) dis = pyew.disassemble(pyew.buf, pyew.processor, pyew.type, pyew.lines, pyew.bsize, baseoffset=pyew.offset) print dis else: cmd = data[1:] if len(cmd) > 1: ret = pyew.dosearch(pyew.f, cmd[0][1:2], cmd[1], cols=60, doprint=False, offset=pyew.offset) else: ret = pyew.dosearch(pyew.f, cmd[0][1:2], "", cols=60, doprint=False, offset=pyew.offset) for x in ret: dis = pyew.disassemble(x.values()[0], pyew.processor, pyew.type, pyew.lines, pyew.bsize, baseoffset=x.keys()[0]) print dis else: dis = pyew.disassemble(pyew.buf, pyew.processor, pyew.type, pyew.lines, pyew.bsize, baseoffset=pyew.offset) print dis elif cmd.isdigit() and int(cmd) < len(pyew.calls)+1 and int(cmd) > 0: pyew.offset = pyew.calls[int(cmd)-1] pyew.seek(pyew.offset) dis = pyew.disassemble(pyew.buf, pyew.processor, pyew.type, pyew.lines, pyew.bsize, baseoffset=pyew.offset) print dis elif cmd == "buf": lines = 0 line = "" for c in pyew.buf: line += c if len(line) == pyew.hexcolumns: print repr(line) line = "" if line != "": print repr(line) elif cmd == "byte": lines = 0 line = "" for c in pyew.buf: line += "0x%x, " % ord(c) if len(line) >= pyew.hexcolumns / (1.00/4.00): print line line = "" if line != "": print "%s" % line elif cmd.lower().split(" ")[0] in ["r", "repr"]: print repr(pyew.buf) elif cmd.lower().split(" ")[0] in ["p"]: print pyew.buf elif cmd.lower() in ["settings", "options"]: pyew.showSettings() elif cmd.startswith("/"): ret = pyew.dosearch(pyew.f, cmd[1:2], cmd[3:], cols=60, offset=pyew.offset) elif cmd.lower() in ["?", "help"]: showHelp(pyew) elif cmd.lower() in ["imports"]: if pyew.format == "PE": for entry in pyew.pe.DIRECTORY_ENTRY_IMPORT: print entry.dll for imp in entry.imports: print '\t', hex(imp.address), imp.name elif pyew.format == "ELF": for x in pyew.elf.relocs: print x elif cmd.lower() in ["exports"]: if pyew.format == "PE": for exp in pyew.pe.DIRECTORY_ENTRY_EXPORT.symbols: print hex(pyew.pe.OPTIONAL_HEADER.ImageBase + exp.address), exp.name, exp.ordinal elif pyew.format == "ELF": print "Not yet implemented" elif cmd.lower() in ["sections"]: if pyew.format == "PE": for x in pyew.pe.sections: print x elif pyew.format == "ELF": for x in pyew.elf.secnames: print pyew.elf.secnames[x] elif cmd.lower() in ["elf", "pe"]: if cmd.lower() == "elf": print pyew.elf else: print pyew.pe elif cmd.lower() == "g": if cmd == "g": pyew.offset = 0 else: pyew.offset = pyew.maxsize - pyew.bsize if pyew.offset < 0: pyew.offset = pyew.maxsize - 32 pyew.seek(pyew.offset) elif cmd in ["-", "+"]: if cmd == "+": pyew.offset += pyew.bsize else: pyew.offset -= pyew.bsize pyew.seek(pyew.offset) elif pyew.plugins.has_key(cmd.split(" ")[0]): plg = cmd.split(" ") if len(plg) == 1: pyew.plugins[plg[0]](pyew) else: pyew.plugins[plg[0]](pyew, plg[1:]) elif cmd.lower().split(" ")[0] in ["md5", "sha1", "sha224", "sha256", "sha384", "sha512"]: func = eval(cmd) print "%s: %s" % (cmd, func(pyew.getBuffer()).hexdigest()) elif cmd.startswith("!"): os.system(cmd[1:]) elif cmd == "ret" and oldpyew is not None: pyew = oldpyew pyew.seek(pyew.offset) oldpyew = None elif cmd == "file": oldpyew = pyew del pyew pyew = CPyew() buf = oldpyew.getBytes(oldpyew.offset, oldpyew.maxsize) pyew.loadFromBuffer(buf, oldpyew.filename + "[embed]") elif cmd == "interact": code.interact(local=locals()) elif cmd == "edit": pyew.f.close() pyew.f = open(filename, "r+wb") pyew.seek(0) elif cmd.split(" ")[0] in ["ls"]: data = cmd.split(" ") if len(data) == 2: #print "parsing script file:", data[1] f = open('scripts/' + data[1], 'r') commands = f.readlines() f.close() else: scripts = os.listdir('scripts/') print "Scripts available:" for script in scripts: print "\t", script elif cmd.split(" ")[0] in ["wx", "wa"]: if cmd.split(" ")[0] == "wx": data = unhexlify(cmd.split(" ")[1]) else: data = cmd.split(" ")[1] pyew.f.seek(pyew.offset) pyew.f.write(data) pyew.seek(pyew.offset) else: if cmd.find("=") > -1 or cmd.startswith("print") or cmd.startswith("import "): exec(cmd) else: x = eval(cmd) if "hexdigest" in dir(x): print "%s: %s" % (cmd, x.hexdigest()) else: pprint.pprint(x) except: print "Error:", sys.exc_info()[1] if pyew.debug: raise
# Configure some stuff... wine = '/path/to/wine' sigcheck = '/path/to/sigcheck.exe' subfile = '/path/to/hachoir-subfile' # These get passed to PEScanner yrules = 'apt1.yara' peid = 'userdb.txt' clamscan_path = '/path/to/clamscan' # Sanity check just to make sure it's a legit PE file before trying to analyze try: pe = pefile.PE(file) except Exception, msg: print msg sys.exit() # will this exit everything if there's a directory being analyzed? pyew = CPyew() if args['verbose'] == True: verb = True else: verb = False def header(msg): return msg + "\n" + ("=" * 90) def subTitle(msg): return "\n" + msg + "\n" + ("-" * 40) def q(s): quote = "\"" s = quote + s + quote