class GlobalContext(): def __init__(self): # TODO : let globally ? plasma.lib.utils.gctx = self plasma.lib.colors.gctx = self self.comments = True # always True, will be removed # For info() messages self.quiet = False self.is_interactive = False # Command line options self.print_andif = True self.color = True self.max_data_size = 30 self.filename = None self.syms = False self.calls_in_section = None self.entry = None # string : symbol | EP | 0xNNNN self.do_dump = False self.vim = False self.nb_lines = 30 self.graph = False # Print graph != gph -> object self.interactive_mode = False self.debug = False self.raw_base = 0 self.raw_big_endian = False self.list_sections = False self.print_bytes = False self.raw_type = None self.print_data = False self.capstone_string = 0 # See lib.ui.visual.main_cmd_inst_output self.show_mangling = True self.autoanalyzer = True self.debugsp = False # Built objects self.dis = None # Disassembler self.libarch = None # module lib.arch.<BIN_ARCH> self.db = None # Database self.api = None # Api def parse_args(self): parser = ArgumentParser(description= 'Reverse engineering for x86/ARM/MIPS binaries. Generation of pseudo-C. ' 'Supported formats : ELF, PE. More commands available in the interactive' ' mode. https://github.com/joelpx/plasma') parser.add_argument('filename', nargs='?', metavar='FILENAME') parser.add_argument('-nc', '--nocolor', action='store_true') parser.add_argument('-g', '--graph', action='store_true', help='Generate a file graph.dot.') parser.add_argument('--noandif', action='store_true', help="Print normal 'if' instead of 'andif'") parser.add_argument('--datasize', type=int, default=30, metavar='N', help='default 30, maximum of chars to display for strings or bytes array.') parser.add_argument('-x', '--entry', metavar='SYMBOLNAME|0xXXXXX|EP', help='Pseudo-decompilation, default is main. EP stands for entry point.') parser.add_argument('--vim', action='store_true', help='Generate syntax colors for vim') parser.add_argument('-s', '--symbols', action='store_true', help='Print all symbols') parser.add_argument('--sections', action='store_true', help='Print all sections') parser.add_argument('--dump', action='store_true', help='Dump asm without decompilation') parser.add_argument('-l', '--lines', type=int, default=30, metavar='N', help='Max lines used with --dump') parser.add_argument('--nbytes', type=int, default=0, metavar='N', help='Print n bytes.') parser.add_argument('-i', '--interactive', action='store_true', help='Interactive mode') parser.add_argument('-d', '--opt_debug', action='store_true') parser.add_argument('--raw', metavar='x86|x64|arm|mips|mips64', help='Consider the input file as a raw binary') parser.add_argument('--rawbase', metavar='0xXXXXX', help='Set base address of a raw file (default=0)') parser.add_argument('--rawbe', action='store_true', help='If not set it\'s in little endian') parser.add_argument('-na', '--noautoanalyzer', action='store_true', help='Disable analysis on the entry point / symbols and don\'t scan memmory. You can force it with the command push_analyze_symbols.') parser.add_argument('--debugsp', action='store_true', help="Print the stack offset on each instructions. Warning: these values will not be saved in the database.") args = parser.parse_args() self.debug = args.opt_debug self.print_andif = not args.noandif self.color = not args.nocolor self.max_data_size = args.datasize self.filename = args.filename self.raw_type = args.raw self.raw_base = args.rawbase self.syms = args.symbols self.entry = args.entry self.do_dump = args.dump self.vim = args.vim self.interactive_mode = args.interactive self.nb_lines = args.lines self.graph = args.graph self.raw_big_endian = args.rawbe self.list_sections = args.sections self.autoanalyzer = not args.noautoanalyzer self.debugsp = args.debugsp if args.nbytes == 0: self.nbytes = 4 self.print_bytes = False else: self.nbytes = int(args.nbytes) self.print_bytes = True if self.raw_base is not None: try: self.raw_base = int(self.raw_base, 16) except: error("--rawbase must be in hex format") die() else: self.raw_base = 0 def load_file(self, filename=None): if filename is None: filename = self.filename if not os.path.exists(filename): error("file {self.filename} doesn't exist".format(self=self)) if self.interactive_mode: return False die() if not os.path.isfile(filename): error("this is not a file".format(self=self)) if self.interactive_mode: return False die() self.db = Database() self.db.load(filename) if self.raw_base != 0: self.db.raw_base = self.raw_base if self.raw_type is not None: self.db.raw_type = self.raw_type if self.raw_big_endian is not None: self.db.raw_is_big_endian = self.raw_big_endian if self.db.loaded: self.raw_base = self.db.raw_base self.raw_type = self.db.raw_type self.raw_big_endian = self.db.raw_is_big_endian try: dis = Disassembler(filename, self.raw_type, self.raw_base, self.raw_big_endian, self.db) except ExcArch as e: error("arch %s is not supported" % e.arch) if self.interactive_mode: return False die() except ExcFileFormat: error("the file is not PE or ELF binary") if self.interactive_mode: return False die() except ExcPEFail as e: error(str(e.e)) error("it seems that there is a random bug in pefile, you shoul retry.") error("please report here https://github.com/joelpx/plasma/issues/16") if self.interactive_mode: return False die() self.dis = dis self.libarch = dis.load_arch_module() return True def get_addr_context(self, ad, quiet=False): adctx = AddrContext(self) if isinstance(ad, int): adctx.entry = self.db.mem.get_head_addr(ad) return adctx ret = adctx.init_address(ad, quiet=quiet) # here ad is a string if not ret: return None adctx.entry = self.db.mem.get_head_addr(adctx.entry) return adctx
class GlobalContext(): def __init__(self): # TODO : let globally ? plasma.lib.utils.gctx = self plasma.lib.colors.gctx = self self.comments = True # always True, will be removed # For info() messages self.quiet = False self.is_interactive = False # Command line options self.print_andif = True self.color = True self.max_data_size = 30 self.filename = None self.syms = False self.calls_in_section = None self.entry = None # string : symbol | EP | 0xNNNN self.do_dump = False self.vim = False self.nb_lines = 30 self.graph = False # Print graph != gph -> object self.interactive_mode = False self.debug = False self.raw_base = 0 self.raw_big_endian = False self.list_sections = False self.print_bytes = False self.raw_type = None self.print_data = False self.capstone_string = 0 # See lib.ui.visual.main_cmd_inst_output self.show_mangling = True self.autoanalyzer = True self.debugsp = False # Built objects self.dis = None # Disassembler self.libarch = None # module lib.arch.<BIN_ARCH> self.db = None # Database self.api = None # Api def parse_args(self): parser = ArgumentParser( description= 'Reverse engineering for x86/ARM/MIPS binaries. Generation of pseudo-C. ' 'Supported formats : ELF, PE. More commands available in the interactive' ' mode. https://github.com/joelpx/plasma') parser.add_argument('filename', nargs='?', metavar='FILENAME') parser.add_argument('-nc', '--nocolor', action='store_true') parser.add_argument('-g', '--graph', action='store_true', help='Generate a file graph.dot.') parser.add_argument('--noandif', action='store_true', help="Print normal 'if' instead of 'andif'") parser.add_argument( '--datasize', type=int, default=30, metavar='N', help= 'default 30, maximum of chars to display for strings or bytes array.' ) parser.add_argument( '-x', '--entry', metavar='SYMBOLNAME|0xXXXXX|EP', help= 'Pseudo-decompilation, default is main. EP stands for entry point.' ) parser.add_argument('--vim', action='store_true', help='Generate syntax colors for vim') parser.add_argument('-s', '--symbols', action='store_true', help='Print all symbols') parser.add_argument('--sections', action='store_true', help='Print all sections') parser.add_argument('--dump', action='store_true', help='Dump asm without decompilation') parser.add_argument('-l', '--lines', type=int, default=30, metavar='N', help='Max lines used with --dump') parser.add_argument('--nbytes', type=int, default=0, metavar='N', help='Print n bytes.') parser.add_argument('-i', '--interactive', action='store_true', help='Interactive mode') parser.add_argument('-d', '--opt_debug', action='store_true') parser.add_argument('--raw', metavar='x86|x64|arm|mips|mips64', help='Consider the input file as a raw binary') parser.add_argument('--rawbase', metavar='0xXXXXX', help='Set base address of a raw file (default=0)') parser.add_argument('--rawbe', action='store_true', help='If not set it\'s in little endian') parser.add_argument( '-na', '--noautoanalyzer', action='store_true', help= 'Disable analysis on the entry point / symbols and don\'t scan memmory. You can force it with the command push_analyze_symbols.' ) parser.add_argument( '--debugsp', action='store_true', help= "Print the stack offset on each instructions. Warning: these values will not be saved in the database." ) args = parser.parse_args() self.debug = args.opt_debug self.print_andif = not args.noandif self.color = not args.nocolor self.max_data_size = args.datasize self.filename = args.filename self.raw_type = args.raw self.raw_base = args.rawbase self.syms = args.symbols self.entry = args.entry self.do_dump = args.dump self.vim = args.vim self.interactive_mode = args.interactive self.nb_lines = args.lines self.graph = args.graph self.raw_big_endian = args.rawbe self.list_sections = args.sections self.autoanalyzer = not args.noautoanalyzer self.debugsp = args.debugsp if args.nbytes == 0: self.nbytes = 4 self.print_bytes = False else: self.nbytes = int(args.nbytes) self.print_bytes = True if self.raw_base is not None: try: self.raw_base = int(self.raw_base, 16) except: error("--rawbase must be in hex format") die() else: self.raw_base = 0 def load_file(self, filename=None): if filename is None: filename = self.filename if not os.path.exists(filename): error("file {self.filename} doesn't exist".format(self=self)) if self.interactive_mode: return False die() if not os.path.isfile(filename): error("this is not a file".format(self=self)) if self.interactive_mode: return False die() self.db = Database() self.db.load(filename) if self.raw_base != 0: self.db.raw_base = self.raw_base if self.raw_type is not None: self.db.raw_type = self.raw_type if self.raw_big_endian is not None: self.db.raw_is_big_endian = self.raw_big_endian if self.db.loaded: self.raw_base = self.db.raw_base self.raw_type = self.db.raw_type self.raw_big_endian = self.db.raw_is_big_endian try: dis = Disassembler(filename, self.raw_type, self.raw_base, self.raw_big_endian, self.db) except ExcArch as e: error("arch %s is not supported" % e.arch) if self.interactive_mode: return False die() except ExcFileFormat: error("the file is not PE or ELF binary") if self.interactive_mode: return False die() except ExcPEFail as e: error(str(e.e)) error( "it seems that there is a random bug in pefile, you shoul retry." ) error( "please report here https://github.com/joelpx/plasma/issues/16" ) if self.interactive_mode: return False die() self.dis = dis self.libarch = dis.load_arch_module() return True def get_addr_context(self, ad, quiet=False): adctx = AddrContext(self) if isinstance(ad, int): adctx.entry = self.db.mem.get_head_addr(ad) return adctx ret = adctx.init_address(ad, quiet=quiet) # here ad is a string if not ret: return None adctx.entry = self.db.mem.get_head_addr(adctx.entry) return adctx