Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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)
Esempio n. 6
0
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)
Esempio n. 7
0
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
Esempio n. 8
0
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)
Esempio n. 9
0
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)))
Esempio n. 10
0
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
Esempio n. 11
0
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
Esempio n. 12
0
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
Esempio n. 13
0
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
Esempio n. 14
0
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)
Esempio n. 15
0
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())
Esempio n. 16
0
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'