Пример #1
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
Пример #2
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")
Пример #3
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
Пример #4
0
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")
Пример #5
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
Пример #6
0
def getAllLoadCommandInfos(filePath, outputPath):
    infos = {}
    logger = utils.setLogger()
    header = utils.getHeader(filePath)
    for (index, (lc, cmd, data)) in enumerate(header.commands):
        command = {}
        desc = cmd.describe()
        lc_name = lc.get_cmd_name()
        if lc_name == 44:
            if utils.is64Bit(filePath):
                lc_name = "LC_ENCRYPTION_INFO_64"
            else:
                lc_name = "LC_ENCRYPTION_INFO"
        if isinstance(data, str):
            desc["Name"] = data.rstrip('\x00')
        command[lc_name] = desc
        infos[index] = command
    infos = collections.OrderedDict(sorted(infos.items()))
    outFinal = json.dumps(infos, encoding='latin1')
    with open(outputPath + "/" + "loadCommands", "w") as f:
        f.write(outFinal)
    logger.info("It has got all infos of load commands sucessfully")
Пример #7
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
Пример #8
0
def createISymbolsNode(sample, symbolsList, path, baseAddr, nindsym):
    endian = utils.getEndianFormat(sample)
    sections = utils.getSections(sample)
    is64 = utils.is64Bit(sample)
    count = 0
    inSymbols = {}
    addr = baseAddr
    offset = 0

    while count < nindsym:
        desc = []
        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(path, 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)
                description = "Symbol"
                value = symbolName
                desc.append(utils.getDict(description, value))
            else:
                description = "Symbol"
                value = []

                if indirectIndex == INDIRECT_SYMBOL_LOCAL:
                    value.append("80000000  INDIRECT_SYMBOL_LOCAL")
                elif indirectIndex == INDIRECT_SYMBOL_ABS:
                    value.append("40000000  INDIRECT_SYMBOL_ABS")
                else:
                    value.append("80000000  INDIRECT_SYMBOL_LOCAL")
                    value.append("40000000  INDIRECT_SYMBOL_ABS")
                desc.append(utils.getDict(description, value))

            description = "Section"
            value = "(" + section.segname.rstrip(
                '\x00') + "," + section.sectname.rstrip('\x00') + ")"
            desc.append(utils.getDict(description, value))

            description = "Indirect Address"
            value = hex(indirectOffset).rstrip("L") + "($+" + str(
                indirectOffset - section.offset) + ")"
            desc.append(utils.getDict(description, value))
            inSymbols[hex(addr)] = desc
            addr += byte

        count += 1

    inSymbols = collections.OrderedDict(sorted(inSymbols.items()))
    return inSymbols
Пример #9
0
def processObjcSections(filePath, outputPath, sections):
    logger = utils.setLogger()
    cfStrings = {}
    cStrings = utils.getCStrings(filePath)
    sectionInfos = utils.getSectionInfoMaps(filePath)
    hasObjCModules = False
    for section in sections:
        sectionName = section.sectname.rstrip("\x00")
        segmentName = section.segname.rstrip("\x00")
        if sectionName == "__cfstring":
            secDesc = section.describe()
            if utils.is64Bit(filePath):
                secDesc["C String Literals"] = objc.createObjCCFStrings64Node(
                    filePath, section, cStrings, sectionInfos)
            else:
                secDesc["C String Literals"] = objc.createObjCCFStringsNode(
                    filePath, section, cStrings, sectionInfos)
            cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

        #first Objective-C ABI
        if sectionName == "__module_info" and segmentName == "__OBJC":
            hasObjCModules = True
            secDesc = section.describe()
            cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

        if sectionName == "__class_ext" and segmentName == "__OBJC":
            secDesc = section.describe()
            cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

        if sectionName == "__protocol_ext" and segmentName == "__OBJC":
            secDesc = section.describe()
            cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

        #second Objective-C ABI
        if not hasObjCModules:
            if (sectionName == "__category_list" and segmentName == "__OBJC2") \
             or (sectionName == "__objc_catlist" and segmentName == "__DATA"):
                secDesc = section.describe()
                if utils.is64Bit(filePath):
                    secDesc[
                        "ObjC2 Category List"] = objc.createObjC2Pointer64ListNode(
                            filePath, section)
                else:
                    secDesc[
                        "ObjC2 Category List"] = objc.createObjC2PointerListNode(
                            filePath, section)
                cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

            if (sectionName == "__class_list" and segmentName == "__OBJC2") \
             or (sectionName == "__objc_classlist" and segmentName == "__DATA"):
                secDesc = section.describe()
                if utils.is64Bit(filePath):
                    secDesc[
                        "ObjC2 Class List"] = objc.createObjC2Pointer64ListNode(
                            filePath, section)
                else:
                    secDesc[
                        "ObjC2 Class List"] = objc.createObjC2PointerListNode(
                            filePath, section)
                cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

            if (sectionName == "__class_refs" and segmentName == "__OBJC2") \
             or (sectionName == "__objc_classrefs" and segmentName == "__DATA"):
                secDesc = section.describe()
                if utils.is64Bit(filePath):
                    secDesc[
                        "ObjC2 References"] = objc.createObjC2Pointer64ListNode(
                            filePath, section)
                else:
                    secDesc[
                        "ObjC2 References"] = objc.createObjC2PointerListNode(
                            filePath, section)
                cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

            if (sectionName == "__super_refs" and segmentName == "__OBJC2") \
             or (sectionName == "__objc_superrefs" and segmentName == "__DATA"):
                secDesc = section.describe()
                if utils.is64Bit(filePath):
                    secDesc[
                        "ObjC2 References"] = objc.createObjC2Pointer64ListNode(
                            filePath, section)
                else:
                    secDesc[
                        "ObjC2 References"] = objc.createObjC2PointerListNode(
                            filePath, section)
                cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

            if (sectionName == "__protocol_list" and segmentName == "__OBJC2") \
             or (sectionName == "__objc_protolist" and segmentName == "__DATA"):
                secDesc = section.describe()
                if utils.is64Bit(filePath):
                    secDesc[
                        "ObjC2 Pointer List"] = objc.createObjC2Pointer64ListNode(
                            filePath, section)
                else:
                    secDesc[
                        "ObjC2 Pointer List"] = objc.createObjC2PointerListNode(
                            filePath, section)
                cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

            if (sectionName == "__message_refs" and segmentName == "__OBJC2") \
             or (sectionName == "__objc_msgrefs" and segmentName == "__DATA"):
                secDesc = section.describe()
                if utils.is64Bit(filePath):
                    secDesc[
                        "ObjC2 Message References"] = objc.createObjC2MsgRefs64Node(
                            filePath, section)
                else:
                    secDesc[
                        "ObjC2 Message References"] = objc.createObjC2MsgRefsNode(
                            filePath, section)
                cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

        if (sectionName == "__image_info" and segmentName == "__OBJC2") \
            or (sectionName == "__objc_imageinfo" and segmentName == "__DATA"):
            secDesc = section.describe()
            secDesc["ObjC2 Image Info"] = objc.createObjCImageInfoNode(
                filePath, section)
            cfStrings[segmentName + "(" + sectionName + ")"] = secDesc

    outFinal = json.dumps(cfStrings, encoding='latin1')
    with open(outputPath + "/" + "objcInfos", "w") as f:
        f.write(outFinal)
    logger.info(
        "It has got all infos of objective-c sections in the mach-o file sucessfully"
    )
Пример #10
0
def getAllPointersOfMacho(filePath, outputPath):
    logger = utils.setLogger()
    pointers = {}
    sections = utils.getSections(filePath)
    symbolNames = utils.getMethodNames(filePath)
    inSymbols = SymbolContents.getISymbols(filePath)
    for section in sections:
        flag = section.flags & SECTION_TYPE
        if flag == S_4BYTE_LITERALS:
            secDesc = section.describe()
            secDesc[
                "Floating Point Literals"] = SectionContents.createLiteralsNode(
                    filePath, section, 4)
            pointers[section.sectname.rstrip('\x00')] = secDesc

        elif flag == S_8BYTE_LITERALS:
            secDesc = section.describe()
            secDesc[
                "Floating Point Literals"] = SectionContents.createLiteralsNode(
                    filePath, section, 8)
            pointers[section.sectname.rstrip('\x00')] = secDesc

        elif flag == S_16BYTE_LITERALS:
            secDesc = section.describe()
            secDesc[
                "Floating Point Literals"] = SectionContents.createLiteralsNode(
                    filePath, section, 8)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        #================ sections with pointer content ============================
        elif flag == S_LITERAL_POINTERS:
            secDesc = section.describe()
            secDesc["Literal Pointers"] = SectionContents.createPointersNode(
                filePath, section, symbolNames)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        elif flag == S_MOD_INIT_FUNC_POINTERS:
            secDesc = section.describe()
            secDesc[
                "Module Init Func Pointers"] = SectionContents.createPointersNode(
                    filePath, section, symbolNames)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        elif flag == S_MOD_TERM_FUNC_POINTERS:
            secDesc = section.describe()
            secDesc[
                "Module Term Func Pointers"] = SectionContents.createPointersNode(
                    filePath, section, symbolNames)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        elif flag == S_LAZY_SYMBOL_POINTERS:
            secDesc = section.describe()
            if utils.is64Bit(filePath):
                secDesc[
                    "Lazy Symbol Pointers"] = SectionContents.createIndPointers64Node(
                        filePath, section, inSymbols)
            else:
                secDesc[
                    "Lazy Symbol Pointers"] = SectionContents.createIndPointersNode(
                        filePath, section, inSymbols)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        elif flag == S_NON_LAZY_SYMBOL_POINTERS:
            secDesc = section.describe()
            if utils.is64Bit(filePath):
                secDesc[
                    "Non-Lazy Symbol Pointers"] = SectionContents.createIndPointers64Node(
                        filePath, section, inSymbols)
            else:
                secDesc[
                    "Non-Lazy Symbol Pointers"] = SectionContents.createIndPointersNode(
                        filePath, section, inSymbols)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        elif flag == S_LAZY_DYLIB_SYMBOL_POINTERS:
            secDesc = section.describe()
            if utils.is64Bit(filePath):
                secDesc[
                    "Lazy Dylib Symbol Pointers"] = SectionContents.createIndPointers64Node(
                        filePath, section, inSymbols)
            else:
                secDesc[
                    "Lazy Dylib Symbol Pointers"] = SectionContents.createIndPointersNode(
                        filePath, section, inSymbols)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        elif flag == S_SYMBOL_STUBS:
            secDesc = section.describe()
            secDesc["Symbol Stubs"] = SectionContents.createIndStubsNode(
                filePath, section, inSymbols)
            pointers[section.sectname.rstrip('\x00')] = secDesc
        else:
            pass
    outFinal = json.dumps(pointers, encoding='latin1')
    with open(outputPath + "/" + "pointers", "w") as f:
        f.write(outFinal)