示例#1
0
def getDynamicLoaderInfo(filePath, outputPath):
    logger = utils.setLogger()
    desc = utils.getCommandInfos(filePath, "LC_DYLD_INFO")
    if desc is None:
        desc = utils.getCommandInfos(filePath, "LC_DYLD_INFO_ONLY")
    rebase_off = desc.get("rebase_off")
    rebase_size = desc.get("rebase_size")
    if rebase_off is not None and rebase_size is not None:
        utils.getPartOfFile(filePath, rebase_off, rebase_size)
        opcodes = DyldInfo.createRebaseNode(filePath, "temp", rebase_off)
        opcodes = collections.OrderedDict(sorted(opcodes.items()))
        desc["Rebase Info(opcodes)"] = opcodes

    bind_off = desc.get("bind_off")
    bind_size = desc.get("bind_size")
    if bind_off is not None and bind_size is not None:
        utils.getPartOfFile(filePath, bind_off, bind_size)
        opcodes = DyldInfo.createBindingNode(filePath, "temp", bind_off)
        opcodes = collections.OrderedDict(sorted(opcodes.items()))
        desc["Binding Info(opcodes)"] = opcodes

    weak_bind_off = desc.get("weak_bind_off")
    weak_bind_size = desc.get("weak_bind_size")
    if weak_bind_off is not None and weak_bind_size is not None:
        utils.getPartOfFile(filePath, weak_bind_off, weak_bind_size)
        opcodes = DyldInfo.createBindingNode(filePath, "temp", weak_bind_off)
        opcodes = collections.OrderedDict(sorted(opcodes.items()))
        desc["Weak Binding Info(opcodes)"] = opcodes

    lazy_bind_off = desc.get("lazy_bind_off")
    lazy_bind_size = desc.get("lazy_bind_size")
    if lazy_bind_off is not None and lazy_bind_size is not None:
        utils.getPartOfFile(filePath, lazy_bind_off, lazy_bind_size)
        opcodes = DyldInfo.createBindingNode(filePath, "temp", lazy_bind_off)
        opcodes = collections.OrderedDict(sorted(opcodes.items()))
        desc["Lazy Binding Info(opcodes)"] = opcodes

    export_off = desc.get("export_off")
    export_size = desc.get("export_size")
    if export_off is not None and export_size is not None:
        utils.getPartOfFile(filePath, export_off, export_size)
        opcodes = DyldInfo.printSymbols(filePath, "temp", export_off)
        opcodes = collections.OrderedDict(sorted(opcodes.items()))
        desc["Export Info(opcodes)"] = opcodes

    if os.path.exists("temp"):
        os.remove("temp")
    outFinal = json.dumps(desc, encoding='latin1')
    with open(outputPath + "/" + "dynamicLoaderInfo", "w") as f:
        f.write(outFinal)
    logger.info("It has got all infos of dynamic loader info sucessfully")
示例#2
0
def getSymbolsList(sample, strs):
    endian = utils.getEndianFormat(sample)
    count = 0
    symbols = {}
    symbolsList = []
    step = 0
    desc = utils.getCommandInfos(sample, "LC_SYMTAB")
    baseStrAddr = desc.get("stroff")
    symAddress = desc.get("symoff")
    nsym = desc.get("nsyms")
    if utils.is64Bit(sample):
        step = 16
        utils.getPartOfFile(sample, symAddress, nsym * 16)
    else:
        step = 12
        utils.getPartOfFile(sample, symAddress, nsym * 12)
    os.rename("temp", "tmp")
    offset = 0
    while count < nsym:
        count += 1

        byte, data = ReadWrite.readInt32("tmp", endian, offset)
        offset += step
        value = strs.get(hex(baseStrAddr + data).rstrip("L"))
        if value is None:
            value = ""
        symbolsList.append(value)
    os.remove("tmp")
    return symbolsList
示例#3
0
def getSymbolTables(filePath, outputPath):
    logger = utils.setLogger()
    strs = utils.getSymbolStrs(filePath)
    desc = utils.getCommandInfos(filePath, "LC_SYMTAB")
    strAddress = desc.get("stroff")
    symAddress = desc.get("symoff")
    if utils.is64Bit(filePath):
        utils.getPartOfFile(filePath, desc.get("symoff"),
                            desc.get("nsyms") * 16)
        os.rename("temp", "tmp")
        symbolStrs = SymbolContents.createSymbols64Node(
            filePath, strs, "tmp", symAddress, strAddress, desc.get("nsyms"))
    else:
        utils.getPartOfFile(filePath, desc.get("symoff"),
                            desc.get("nsyms") * 12)
        os.rename("temp", "tmp")
        symbolStrs = SymbolContents.createSymbolsNode(filePath, strs, "tmp",
                                                      symAddress, strAddress,
                                                      desc.get("nsyms"))

    desc["symbols"] = symbolStrs
    os.remove("tmp")
    outFinal = json.dumps(desc, encoding='latin1')
    with open(outputPath + "/" + "symbolTables", "w") as f:
        f.write(outFinal)
    logger.info("It has got all infos of symbol tables sucessfully")
示例#4
0
def getISymbols(sample):
    endian = utils.getEndianFormat(sample)
    symbols = utils.getSymbolStrs(sample)
    symbolsList = getSymbolsList(sample, symbols)
    sections = utils.getSections(sample)
    is64 = utils.is64Bit(sample)
    count = 0
    inSymbols = {}
    offset = 0
    desc = utils.getCommandInfos(sample, "LC_DYSYMTAB")
    inSymAddress = desc.get("indirectsymoff")
    nSymbol = desc.get("nindirectsyms")
    utils.getPartOfFile(sample, inSymAddress, nSymbol * 4)
    os.rename("temp", "tmp")
    while count < nSymbol:
        nsect = len(sections)
        while nsect > 0:
            nsect -= 1
            section = sections[nsect]
            flag = section.flags
            #             print(section.reserved1)
            if (flag & SECTION_TYPE != S_SYMBOL_STUBS \
            and flag & SECTION_TYPE != S_LAZY_SYMBOL_POINTERS \
            and flag & SECTION_TYPE != S_LAZY_DYLIB_SYMBOL_POINTERS \
            and flag & SECTION_TYPE != S_NON_LAZY_SYMBOL_POINTERS) \
            or section.reserved1 > count:
                #section type or indirect symbol index mismatch
                continue

            nsect = 0
            #calculate stub or pointer length
            if section.reserved2 > 0:
                length = section.reserved2
            else:
                if is64:
                    length = 8
                else:
                    length = 4

            #calculate indirect value location
            indirectOffset = section.offset + (count -
                                               section.reserved1) * length

            #read indirect symbol index
            byte, indirectIndex = ReadWrite.readInt32("tmp", endian, offset)
            offset += byte

            if indirectIndex & (INDIRECT_SYMBOL_LOCAL
                                | INDIRECT_SYMBOL_ABS) == 0:
                if indirectIndex >= len(symbolsList):
                    raise Exception("index is out of range " +
                                    str(indirectIndex))
                symbolName = utils.getSymbolByIndex(symbolsList, indirectIndex)
                inSymbols[hex(indirectOffset).rstrip("L")] = symbolName

        count += 1
    os.remove("tmp")
    return inSymbols
def createTextNode(sample, section, outputPath):
    #prepare disassembler params
    header = utils.getHeader(sample)
    strs = utils.getSymbolStrs(sample)
    inSymbols = SymbolContents.getISymbols(sample)
    names = SymbolContents.getFunctionNames(sample, strs)
    #open capstone
    target_arch = 0
    target_mode = 0
    if header.header.cputype == CPU_TYPE_ARM:
        target_arch = CS_ARCH_ARM
        target_mode = CS_MODE_ARM
    elif header.header.cputype == CPU_TYPE_ARM64:
        target_arch = CS_ARCH_ARM64
        target_mode = CS_MODE_ARM
    else:
        print("NO CPU FOUND!")

    md = Cs(target_arch, target_mode)
    md.skipdata = True
    md.detail = True
    #set or not thumb mode for 32 bits ARM targets
    if header.header.cputype == CPU_TYPE_ARM:
        if header.header.cpusubtype == CPU_SUBTYPE_ARM_V7 \
            or header.header.cpusubtype == CPU_SUBTYPE_ARM_V7F \
            or header.header.cpusubtype == CPU_SUBTYPE_ARM_V7S \
            or header.header.cpusubtype == CPU_SUBTYPE_ARM_V7K \
            or header.header.cpusubtype == CPU_SUBTYPE_ARM_V8 :
            md.mode = CS_MODE_THUMB
        else:
            md.mode = CS_MODE_ARM

    code = Codes(md)
    utils.getPartOfFile(sample, section.offset, section.size)
    os.rename("temp", "codes")
    if section.sectname.rstrip('\x00') == "__text":
        desc = utils.getCommandInfos(sample, "LC_FUNCTION_STARTS")
        utils.getPartOfFile(sample, desc.get("dataoff"), desc.get("datasize"))
        if utils.is64Bit(sample):
            getFunctions(code, inSymbols, names, "temp", section.offset,
                         outputPath)
        else:
            getFunctions(code, inSymbols, names, "temp", section.offset,
                         outputPath)
        os.remove("temp")
    else:
        fcode = open("codes", "rb")
        CODE = fcode.read()
        code.disAssembly(md, inSymbols, CODE, section.offset, outputPath)
        fcode.close()

    os.remove("codes")
示例#6
0
def getDynamicSymbolTables(filePath, outputPath):
    logger = utils.setLogger()
    strs = utils.getSymbolStrs(filePath)
    symbolsList = SymbolContents.getSymbolsList(filePath, strs)
    desc = utils.getCommandInfos(filePath, "LC_DYSYMTAB")
    inSymAddress = desc.get("indirectsymoff")
    nSymbol = desc.get("nindirectsyms")
    utils.getPartOfFile(filePath, inSymAddress, nSymbol * 4)
    os.rename("temp", "tmp")
    desc["inSymbols"] = SymbolContents.createISymbolsNode(
        filePath, symbolsList, "tmp", inSymAddress, nSymbol)
    os.remove("tmp")
    outFinal = json.dumps(desc, encoding='latin1')
    with open(outputPath + "/" + "dynamicSymbolTables", "w") as f:
        f.write(outFinal)
    logger.info("It has get all infos of dynamic symbol tables sucessfully")
示例#7
0
def getFunctionNames(sample, strs):
    endian = utils.getEndianFormat(sample)
    sectionInfos = utils.getSectionInfoMaps(sample)
    desc = utils.getCommandInfos(sample, "LC_SYMTAB")
    baseStrAddr = desc.get("stroff")
    symAddress = desc.get("symoff")
    nsym = desc.get("nsyms")
    if utils.is64Bit(sample):
        step = 16
        utils.getPartOfFile(sample, symAddress, nsym * 16)
    else:
        step = 12
        utils.getPartOfFile(sample, symAddress, nsym * 12)
    os.rename("temp", "tmp")
    count = 0
    names = {}
    offset = 0
    is64 = utils.is64Bit(sample)
    while count < nsym:
        count += 1

        byte, data = ReadWrite.readInt32("tmp", endian, offset)
        offset += 8
        value = strs.get(hex(baseStrAddr + data).rstrip("L"))
        if value is None:
            continue

        if is64:
            byte, n_value = ReadWrite.readInt64("tmp", endian, offset)
        else:
            byte, n_value = ReadWrite.readInt32("tmp", endian, offset)
        offset += byte
        key = utils.addressToFileOffset(sample, sectionInfos, n_value)
        names[hex(key)] = value
    os.remove("tmp")
    return names
示例#8
0
def getClassSymbols(sample):
    endian = utils.getEndianFormat(sample)
    strs = utils.getSymbolStrs(sample)
    desc = utils.getCommandInfos(sample, "LC_SYMTAB")
    baseStrAddr = desc.get("stroff")
    symAddress = desc.get("symoff")
    nsym = desc.get("nsyms")
    is64 = utils.is64Bit(sample)
    if is64:
        utils.getPartOfFile(sample, symAddress, nsym * 16)
    else:
        utils.getPartOfFile(sample, symAddress, nsym * 12)
    count = 0
    classSymbols = {}
    offset = 0
    while count < nsym:
        count += 1

        byte, data = ReadWrite.readInt32("temp", endian, offset)
        offset += byte
        description = "String Table Index"
        value = strs.get(hex(baseStrAddr + data).rstrip("L"))
        if value is None:
            value = ""

        offset += 4

        if is64:
            byte, n_value = ReadWrite.readInt64("temp", endian, offset)
        else:
            byte, n_value = ReadWrite.readInt32("temp", endian, offset)
        offset += byte
        classSymbols[hex(n_value).rstrip("L")] = value

    classSymbols = collections.OrderedDict(sorted(classSymbols.items()))
    return classSymbols