def handle_command(debugger, command, result, internal_dict): ''' Disassemble with colors! Terminal only ''' command_args = shlex.split(command, posix=False) target = ds.getTarget() parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return output = '' if options.search_functions: query = options.search_functions symbol_context_list = target.FindGlobalFunctions( query, 0, lldb.eMatchTypeRegex) for symContext in symbol_context_list: output += generateAssemblyFromSymbol(symContext.symbol, options) elif len(args) == 0: sym = ds.getFrame().GetSymbol() output += generateAssemblyFromSymbol(sym, options) else: sym = ds.getTarget().ResolveLoadAddress(long(args[0], 16)).GetSymbol() output += generateAssemblyFromSymbol(sym, options) result.AppendMessage(output)
def handle_command(debugger, command, result, internal_dict): ''' Disassemble with colors! Terminal only ''' command_args = shlex.split(command, posix=False) target = ds.getTarget() parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return if len(args) == 0: sym = ds.getFrame().GetSymbol() else: sym = ds.getTarget().ResolveLoadAddress(long(args[0], 16)).GetSymbol() instructions = sym.GetInstructions(target) output = ds.attrStr(sym.addr.module.file.basename + ', ' + sym.name, 'cyan') + '\n' counter = 0 if len(instructions) == 0: return startAddress = instructions.GetInstructionAtIndex( 0).GetAddress().GetLoadAddress(target) frame = ds.getFrame() for inst in instructions: line = ds.attrStr(str(counter).ljust(4), 'grey') counter += 1 offset = str(inst.addr.GetLoadAddress(target) - startAddress) branch = (ds.attrStr('*', 'yellow') if inst.is_branch else ' ') pc = ds.attrStr('-> ', 'grey') if frame.addr == inst.addr else ' ' loadaddr = ds.attrStr( hex(inst.addr.GetLoadAddress(target)) + (' <+' + offset + '>:').ljust(8), 'grey') mnemonic = ds.attrStr(inst.mnemonic.ljust(5), 'red') operands = ds.attrStr(inst.operands, 'bold') comments = ds.attrStr(inst.comment, 'green') if options.memory: tmp = ' '.join([ hex(i).replace('0x', '').zfill(2) for i in inst.GetData(lldb.target).uint8s ]) mem = ds.attrStr(tmp, 'cyan') else: mem = '' output += '{}{}{} {} {} {} {} {}\n'.format(pc, branch, line, loadaddr, mem, mnemonic, operands, comments) result.AppendMessage(output)
def generate_cstring_dict(debugger, command, options): target = ds.getTarget() if options.module: module_name = options.module module = target.FindModule(lldb.SBFileSpec(module_name)) if not module.IsValid(): result.SetError( "Unable to open module name '{}', to see list of images use 'image list -b'" .format(module_name)) return modules = [module] else: modules = ds.getTarget().modules return_string = '' error = lldb.SBError() prog = re.compile(command) for m in modules: section = ds.getSection(m, '__TEXT.__cstring') if section is None: continue data = section.data dataArray = section.data.sint8s sectionAddress = section.addr.GetLoadAddress(ds.getTarget()) moduleString = '' indices = [ i for i, x in enumerate(dataArray) if x > 1 and dataArray[i - 1] == 0 and x != 0 ] returnDict = {} for i in indices: cString = data.GetString(error, i) if prog.search(cString): returnDict[hex(sectionAddress + i)] = cString if len(returnDict) == 0: continue if options.module_summary: return_string += '{} hits in: {}\n'.format(str(len(returnDict)), m.file.basename) else: moduleString = '\n****************************************************\n{} hits in: {}\n****************************************************\n'.format( str(len(returnDict)), m.file.basename) for k, v in returnDict.iteritems(): if options.load_address: moduleString += k + ', ' moduleString += v + '\n' return_string += moduleString return return_string
def getCFAddress(addr): outputStr = '' section = addr.section target = ds.getTarget() fileAddr = addr.file_addr executablePath = addr.module.file.fullpath dataSection = ds.getSection(module=executablePath, name='__DATA.__cfstring') if dataSection is None: return '' size = dataSection.size charPointerType = target.GetBasicType(lldb.eBasicTypeChar).GetPointerType() dataArray = dataSection.data.uint64s # TODO implement 32 bit for i, x in enumerate(dataArray): if i % 4 != 2: continue if x == fileAddr: offset = (i - 2) * 8 # TODO implement 32 bit # size = dataArray[i + 1] # lldb.SBData loadAddress = dataSection.addr.GetLoadAddress(target) + offset startAddr = target.ResolveLoadAddress(loadAddress) straddr = target.ResolveLoadAddress( dataSection.addr.GetLoadAddress(target) + (i * 8)) summary = target.CreateValueFromAddress('somename', straddr, charPointerType).summary outputStr += '[{}] {}\n'.format( hex(startAddr.GetLoadAddress(target)), summary) return outputStr
def generateDescriptionByAddress(addr): target = ds.getTarget() section = addr.section name = '' retDescription = '' loadAddr = hex(addr.GetLoadAddress(target)) while section: name = '.' + section.name + name section = section.GetParent() # return name +'lkjlkj' if '__DATA.__objc_selrefs' in name: string = str(target.EvaluateExpression('*(char **)' + loadAddr)) if len(string.split('"')) > 1: return (False, '"' + string.split('"')[1] + '"') elif '__DATA.__objc_classrefs' in name: idType = ds.getType('id') sbval = target.CreateValueFromAddress('hi', addr, idType) return (False, '(__DATA.__objc_classrefs) {}'.format(sbval.description)) elif '__DATA.__cfstring' in name: charType = ds.getType('char*') newAddr = target.ResolveLoadAddress(addr.GetLoadAddress(target) + 0x10) # TODO, do 32 bit sbval = target.CreateValueFromAddress('hi', newAddr, charType) return (False, '(__DATA.__cfstring) {}'.format(sbval.summary)) retDescription += name return (True, loadAddr + ' ' + str(addr.module.file.basename) + retDescription)
def handle_command(debugger, command, result, internal_dict): ''' Documentation for how to use section goes here ''' command_args = shlex.split(command, posix=False) parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return # Uncomment if you are expecting at least one argument # clean_command = shlex.split(args[0])[0] if len(args) == 0: options.summary = True sections = [i for i in ds.getSection()] elif len(args) == 1: module = args[0] if ds.getTarget().module[args[0]] else None segment = args[0] if not module else None if segment and '.' in segment: if module: sections = ds.getSection(module=args[0], name=None) else: sections = [ds.getSection(module=None, name=args[0])] else: module = args[0] if ds.getTarget().module[args[0]] else None options.summary = True if module: sections = ds.getSection(module=args[0], name=None) else: sections = [i for i in ds.getSection(module=None, name=args[0])] elif len(args) == 2: if '.' in args[1]: sections = [ds.getSection(args[0], args[1])] else: options.summary = True sections = [i for i in ds.getSection(args[0], args[1])] output = parseSection(sections, options) result.AppendMessage(output)
def generate_return_string(debugger, module_dict, options): return_string = '' for key in module_dict: count = len(module_dict[key]) if len(module_dict[key]) == 0: continue tmp = module_dict[key][0] if options.module_summary: return_string += str(count) + ' hits in: ' + key + '\n' continue return_string += '****************************************************\n' return_string += str(count) + ' hits in: ' + key + '\n' return_string += '****************************************************\n' for symbol_context in module_dict[key]: if options.global_var or options.global_var_noeval: name = symbol_context.symbol.name if options.global_var: frame = ds.getFrame() target = ds.getTarget() addr = hex( symbol_context.symbol.addr.GetLoadAddress(target)) val = frame.EvaluateExpression('*(void**)' + addr) name += '\n' + (val.description if val.description else '0x%010x' % val.unsigned) elif symbol_context.function.name is not None: name = symbol_context.function.name if options.mangled_name: mangledName = symbol_context.symbol.GetMangledName() name += ', ' + mangledName if mangledName else '[NONE]' elif symbol_context.symbol.name is not None: name = symbol_context.symbol.name if options.mangled_name: mangledName = symbol_context.symbol.GetMangledName() name += ', ' + mangledName if mangledName else '[NONE]' else: return_string += 'Can\'t find info for ' + str( symbol_context) + '\n\n' continue if options.load_address: str_addr = str( hex(symbol_context.GetSymbol().GetStartAddress(). GetLoadAddress(debugger.GetSelectedTarget()))) end_addr = str( hex(symbol_context.GetSymbol().GetEndAddress(). GetLoadAddress(debugger.GetSelectedTarget()))) return_string += '[' + str_addr + '-' + end_addr + '] ' + name else: return_string += name return_string += '\n\n' return return_string
def handle_command(debugger, command, result, internal_dict): ''' Disassemble with colors! Terminal only ''' command_args = shlex.split(command, posix=False) target = ds.getTarget() parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return output = '' if options.search_functions: query = options.search_functions symbol_context_list = target.FindGlobalFunctions(query, 0, lldb.eMatchTypeRegex) for symContext in symbol_context_list: output += generateAssemblyFromSymbol(symContext.symbol, options) elif len(args) == 0: sym = ds.getFrame().GetSymbol() output += generateAssemblyFromSymbol(sym, options) elif args[0].startswith('0x'): sym = ds.getTarget().ResolveLoadAddress(long(args[0], 16)).GetSymbol() output += generateAssemblyFromSymbol(sym, options) elif args[0].isdigit(): sym = ds.getTarget().ResolveLoadAddress(long(args[0])).GetSymbol() output += generateAssemblyFromSymbol(sym, options) else: cleanCommand = ' '.join(args) symList = target.FindGlobalFunctions(cleanCommand, 0, lldb.eMatchTypeNormal) if symList.GetSize() == 0: result.SetError(ds.attrStr("Couldn't find any matches for \"{}\"".format(cleanCommand), 'red')) return sym = symList output += generateAssemblyFromSymbol(symList.GetContextAtIndex(0).symbol, options) result.AppendMessage(output)
def breakifonfunc(debugger, command, result, internal_dict): ''' usage: biof [ModuleName] regex1 ||| [ModuleName2] regex2 Regex breakpoint that stops only if the second regex breakpoint is in the stack trace For example, to only stop if code in the Test module resulted the setTintColor: being called biof setTintColor: ||| . Test ''' command_args = shlex.split(command, posix=False) parser = generateOptionParser() try: (options, args) = parser.parse_args(command_args) except e: result.SetError(e) return # if len(args) >= 2: # result.SetError(parser.usage) # return target = debugger.GetSelectedTarget() # if len(command.split('|||')) != 2: # result.SetError(parser.usage) t = " ".join(args).split('|||') clean_command = t[0].strip().split() if len(clean_command) == 2: breakpoint = target.BreakpointCreateByRegex(clean_command[0], clean_command[1]) else: breakpoint = target.BreakpointCreateByRegex(clean_command[0], None) target = ds.getTarget() moduleName = t[1].strip().split()[1] module = target.module[moduleName] if not module: result.SetError('Invalid module {}'.format(moduleName)) return searchQuery = t[1].strip().split()[0] s = [i for i in module.symbols if re.search(searchQuery, i.name)] GlobalOptions.addSymbols(s, options, breakpoint) breakpoint.SetScriptCallbackFunction("breakifonfunc.breakpointHandler") if not breakpoint.IsValid() or breakpoint.num_locations == 0: result.AppendWarning( "Breakpoint isn't valid or hasn't found any hits: " + clean_command[0]) else: result.AppendMessage( "\"{}\" produced {} hits\nOnly will stop if the following stack frame symbols contain:\n{}` \"{}\" produced {} hits" .format(clean_command[0], breakpoint.num_locations, module.file.basename, searchQuery, len(s)))
def generateAddressInfo(addresses, options): target = ds.getTarget() outputStr = '' for a in addresses: symbol = a.symbol if symbol: symbolOffset = a.GetLoadAddress( target) - symbol.addr.GetLoadAddress(target) symbolAddress = hex(symbol.addr.GetLoadAddress(target)) outputStr += '[{}] {} + {}\n\n'.format( ds.attrStr(symbolAddress, 'yellow'), ds.attrStr(symbol.name, 'cyan'), symbolOffset) else: outputStr + 'error: ' return outputStr
def generateDescriptionByAddress(addr): target = ds.getTarget() section = addr.section name = '' retDescription = '' loadAddr = hex(addr.GetLoadAddress(target)) while section: name = '.' + section.name + name section = section.GetParent() # return name +'lkjlkj' if '__DATA.__objc_selrefs' in name: string = str(target.EvaluateExpression('*(char **)' + loadAddr)) if len(string.split('"')) > 1: return '"' + string.split('"')[1] + '"' retDescription += name return loadAddr + ' ' + str(addr.module.file.basename) + retDescription
def parseSection(sections, options): output = '' for section in sections: # if section name = ds.getSectionName(section) loadAddr = section.addr.GetLoadAddress(ds.getTarget()) addr = section.addr size = section.size data = section.data endAddr = loadAddr + size addr = section.addr if options.summary: moduleName = addr.module.file.basename # bug TODO figure why pagezero is wonky if name == '__PAGEZERO': loadAddr = 0 endAddr = size output += ds.attrStr('[' + '{0:#016x}'.format(loadAddr) + '-' + '{0:#016x}'.format(endAddr) + '] ', 'cyan') output += ds.attrStr("{0:#012x}".format(size), 'grey') + ' ' output += ds.attrStr(moduleName, 'yellow') + '`' output += ds.attrStr(name, 'cyan') + '\n' continue returnType = ds.getSectionData(section, options.count) # Ok, I really need to rewrite this, but whatever if isinstance(returnType, tuple): (indeces, sectionData) = returnType for index, x in enumerate(sectionData): if options.count != 0 and index >= options.count: break if options.load_address: output += ds.attrStr(hex(loadAddr + indeces[index]), 'yellow') + ' ' output += ds.attrStr(str(x), 'cyan') + '\n' elif isinstance(returnType, str): output += returnType return output
def getObjcMethNameAddress(addr): outputStr = '' section = addr.section target = ds.getTarget() fileAddr = addr.file_addr executablePath = addr.module.file.fullpath dataSection = ds.getSection(module=executablePath, name='__DATA.__objc_selrefs') charPointerType = target.GetBasicType(lldb.eBasicTypeChar).GetPointerType() dataArray = dataSection.data.uint64s # TODO implement 32 bit for i, x in enumerate(dataArray): if x != fileAddr: continue offset = i * 8 # TODO implement 32 bit loadAddress = dataSection.addr.GetLoadAddress(target) + offset startAddr = target.ResolveLoadAddress(loadAddress) straddr = target.ResolveLoadAddress( dataSection.addr.GetLoadAddress(target) + (i * 8)) summary = target.CreateValueFromAddress('somename', straddr, charPointerType).summary outputStr += '[{}] {}\n'.format(hex(startAddr.GetLoadAddress(target)), summary) return outputStr
def handle_command(debugger, command, result, internal_dict): ''' Documentation for how to use xref goes here ''' command_args = shlex.split(command, posix=False) parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return try: addr = int(args[0], 16) except: addr = int(args[0]) target = ds.getTarget() sbaddress = target.ResolveLoadAddress(addr) if len(args) == 2: module = target.module[args[1]] else: module = sbaddress.module section = sbaddress.section resolvedAddresses = [] outputStr = '' if section.name == '__cstring': outputStr += getCFAddress(sbaddress) if section.name == '__objc_methname': outputStr += getObjcMethNameAddress(sbaddress) executablePath = module.file.fullpath pagesizesection = ds.getSection(module.file.basename, name="__PAGEZERO") pagesize = pagesizesection.size if pagesizesection else 0 loadOffset = ds.getSection( module=executablePath, name="__TEXT").addr.GetLoadAddress(target) - pagesize searchAddr = addr - loadOffset otoolCommand = '/usr/bin/otool -tv "{}"'.format(executablePath) output = subprocess.Popen(otoolCommand, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True).communicate()[0] matches = re.findall(".*rip.*\n\w+", output) regex = re.compile( '(?P<initial>\w+)?\t\w+\w.*[^\*](?P<offset>\-?0x\w+).*\n(?P<addr>\w+)') for i, m in enumerate(matches): res = regex.match(m) if not res or not res.group('addr') or not res.group('offset'): continue # result.AppendMessage(m) # result.AppendMessage(res.group('addr') + '\n') try: address = int(res.group('addr'), 16) offset = int(res.group('offset'), 16) except: outputStr += 'error: at {} {}'.format(res.group('addr'), res.group('offset')) continue potential = address + offset if searchAddr == potential: if res.group('initial'): resolved = int(res.group('initial'), 16) + loadOffset else: resolved = int(regex.match(matches[i - 1]).group('addr'), 16) + loadOffset a = target.ResolveLoadAddress(resolved) resolvedAddresses.append(a) # print("match at {}".format(hex(resolved))) outputStr += generateAddressInfo(resolvedAddresses, options) result.AppendMessage(outputStr)
def dclass(debugger, command, result, internal_dict): ''' Dumps all the NSObject inherited classes in the process. If you give it a module that exists on disk, it will dump only the classes within that module. You can also filter out classes to only a certain type and can also generate a header file for a specific class. Examples: # Dump ALL the NSObject classes within the process dclass # Dump all the classes that are a UIViewController within the process dclass -f UIViewController # Dump all classes in CKConfettiEffect NSBundle that are UIView subclasses dclass /System/Library/Messages/iMessageEffects/CKConfettiEffect.bundle/CKConfettiEffect -f UIView # Generate a header file for the class specified: dclass -g UIView # Generate a protocol that you can cast an object to. Ideal when working with private classes at dev time dclass -p UIView ''' command_args = shlex.split(command, posix=False) parser = generate_option_parser() try: (options, args) = parser.parse_args(command_args) except: result.SetError(parser.usage) return if not args: # result.SetError('Usage: find NSObjectSubclass\n\nUse \'help find\' for more details') clean_command = None # return if not args and options.generate_header: result.SetError('Need to supply class for option') return else: clean_command = ('').join(args) res = lldb.SBCommandReturnObject() interpreter = debugger.GetCommandInterpreter() target = debugger.GetSelectedTarget() if options.output_dir: directory = '/tmp/{}_{}/'.format(ds.getTarget().executable.basename, datetime.datetime.now().time()) os.makedirs(directory) modules = ds.getTarget().modules if len(args) > 0 and args[0] == '__all': os.makedirs(directory + 'PrivateFrameworks') os.makedirs(directory + 'Frameworks') modules = [ i for i in ds.getTarget().modules if '/usr/lib/' not in i.file.fullpath and '__lldb_' not in i.file.fullpath ] outputMsg = "Dumping all private Objective-C frameworks" elif len(args) > 0 and args[0]: module = ds.getTarget().module[args[0]] if module is None: result.SetError( "Unable to open module name '{}', to see list of images use 'image list -b'" .format(args[0])) return modules = [module] outputMsg = "Dumping all private Objective-C frameworks" else: modules = [ ds.getTarget().module[ds.getTarget().executable.fullpath] ] for module in modules: command_script = generate_module_header_script( options, module.file.fullpath.replace('//', '/')) interpreter.HandleCommand( 'expression -lobjc -O -u0 -- ' + command_script, res) # debugger.HandleCommand('expression -lobjc -O -- ' + command_script) if '/System/Library/PrivateFrameworks/' in module.file.fullpath: subdir = 'PrivateFrameworks/' elif '/System/Library/Frameworks/' in module.file.fullpath: subdir = 'Frameworks/' else: subdir = '' ds.create_or_touch_filepath( directory + subdir + module.file.basename + '.txt', res.GetOutput()) print('Written output to: ' + directory + '... opening file') os.system('open -R ' + directory) return if options.module is not None: module = target.FindModule(lldb.SBFileSpec(options.module)) if not module.IsValid(): result.SetError( "Unable to open module name '{}', to see list of images use 'image list -b'" .format(options.module)) return if options.conforms_to_protocol is not None: interpreter.HandleCommand( 'expression -lobjc -O -- (id)NSProtocolFromString(@\"{}\")'.format( options.conforms_to_protocol), res) if 'nil' in res.GetOutput() or not res.GetOutput(): result.SetError("No such Protocol name '{}'".format( options.conforms_to_protocol)) return res.Clear() if options.generate_header or options.generate_protocol: command_script = generate_header_script(options, clean_command) else: command_script = generate_class_dump(debugger, options, clean_command) if options.generate_header or options.generate_protocol: interpreter.HandleCommand( 'expression -lobjc -O -- (Class)NSClassFromString(@\"{}\")'.format( clean_command), res) if 'nil' in res.GetOutput(): result.SetError( 'Can\'t find class named "{}". Womp womp...'.format( clean_command)) return res.Clear() if options.generate_protocol: filepath = "/tmp/DS_" + clean_command + "Protocol.h" else: filepath = "/tmp/" + clean_command + ".h" interpreter.HandleCommand('expression -lobjc -O -- ' + command_script, res) # debugger.HandleCommand('expression -lobjc -O -g -- ' + command_script) if res.GetError(): result.SetError(res.GetError()) return contents = res.GetOutput() ds.create_or_touch_filepath(filepath, contents) print('Written output to: ' + filepath + '... opening file') os.system('open -R ' + filepath) else: result.AppendMessage(ds.attrStr('Dumping classes', 'cyan')) interpreter.HandleCommand('expression -lobjc -O -- ' + command_script, res) # debugger.HandleCommand('expression -lobjc -O -g -- ' + command_script) if res.GetError(): result.SetError(ds.attrStr(res.GetError(), 'red')) return result.AppendMessage( ds.attrStr( '************************************************************', 'cyan')) if res.Succeeded(): result.AppendMessage(res.GetOutput())
def generateAssemblyFromSymbol(sym, options): target = ds.getTarget() instructions = sym.GetInstructions(target) output = ds.attrStr(str(sym.addr.module.file.basename) + ', ', 'cyan') + ds.attrStr(str(sym.name), 'yellow') + '\n' counter = 0 if len(instructions) == 0: return startAddress = instructions.GetInstructionAtIndex(0).GetAddress().GetLoadAddress(target) frame = ds.getFrame() branches = [] offsetSizeDict = {} grepSearch = False for inst in instructions: line = ds.attrStr(str(counter).ljust(4), 'grey') offset = str(inst.addr.GetLoadAddress(target) - startAddress) branch = (ds.attrStr('*', 'yellow') if inst.is_branch else ' ') pc = ds.attrStr('-> ', 'red') if frame.addr == inst.addr else ' ' loadaddr = ds.attrStr(hex(inst.addr.GetLoadAddress(target)) + (' <+' + offset + '>:').ljust(8), 'grey') mnemonic = ds.attrStr(inst.GetMnemonic(target).ljust(5), 'red') if len(inst.GetOperands(target).split(',')) > 1: ops = inst.GetOperands(target).split(',') operands = ds.attrStr(ops[0], 'bold') + ', ' + ds.attrStr(ops[1], 'yellow') else: operands = ds.attrStr(inst.GetOperands(target), 'bold') comments = ds.attrStr(inst.GetComment(target), 'cyan') if options.grep_functions: if re.search(options.grep_functions, comments): grepSearch = True # TODO x64 only, need arm64 if 'rip' in inst.GetOperands(target): nextInst = instructions[counter + 1] m = re.search(r"(?<=\[).*(?=\])", inst.GetOperands(target)) pcComment = '' if m and nextInst: nextPCAddr = hex(nextInst.addr.GetLoadAddress(target)) commentLoadAddr = eval(m.group(0).replace('rip', nextPCAddr)) addr = ds.getTarget().ResolveLoadAddress(commentLoadAddr) modName = generateDescriptionByAddress(addr) pcComment += ds.attrStr('; ' + modName, 'green') # interpreter.HandleCommand('image lookup -a ' + nextPCAddr, res) # # m = re.search('(?<=\().*(?=\s)', res.GetOutput()) # # if m: # # pcComment += ds.attrStr(' ' + m.group(0), 'green') # m = re.search('(?<=Summary\:\s).*$', res.GetOutput()) # if m: # pcComment += ds.attrStr(' sum:' + res.GetOutput(), 'blue') # res.Clear() else: pcComment = '' match = re.search('(?<=\<\+)[0-9]+(?=\>)', inst.GetComment(target)) offsetSizeDict[offset] = counter if options.show_branch and inst.is_branch and match: branches.append((counter, int(match.group(0)))) if options.memory: tmp = ' '.join([hex(i).replace('0x', '').zfill(2) for i in inst.GetData(lldb.target).uint8s]) mem = ds.attrStr(tmp, 'cyan') else: mem = '' formatter = '{}' if options.show_branch else '' output += '{}{}{} {}{} {} {} {} {} {}\n'.format(pc, branch, line, formatter, loadaddr, mem, mnemonic, operands, comments, pcComment) counter += 1 if options.show_branch: branchLines = generateBranchLines(branches, counter, offsetSizeDict) for i, line in enumerate(output.split('\n')): output += line.format(branchLines[i]) + '\n' if options.grep_functions: if grepSearch: return output else: return '' return output + '\n'