def CiscoIOSImageFileParser(filename, options): global oMD5Database image = naft_uf.File2Data(filename) if image == None: print('Error reading %s' % filename) return oIOSImage = naft_iipf.cIOSImage(image) oIOSImage.Print() if options.md5db: md5hash = hashlib.md5(image).hexdigest() filenameCSV, filenameDB = oMD5Database.Find(md5hash) if filenameCSV == None: print('File not found in md5 database') else: print('File found in md5 database %s %s' % (filenameCSV, filenameDB)) if options.verbose: for oSectionHeader in oIOSImage.oELF.sections: print(' %2d %-7s %d %d %08X %10d %s' % (oSectionHeader.nameIndex, oSectionHeader.nameIndexString, oSectionHeader.type, oSectionHeader.flags, oSectionHeader.offset, oSectionHeader.size, repr(oSectionHeader.sectionData[0:8]))) if options.extract: naft_uf.Data2File(oIOSImage.imageUncompressed, oIOSImage.imageUncompressedName) if options.idapro: naft_uf.Data2File(oIOSImage.ImageUncompressedIDAPro(), oIOSImage.imageUncompressedName)
def CiscoIOSImageFileScanner(filewildcard, options): if options.resume == None: filenames = GlobFilelist(filewildcard, options) countFilenames = len(filenames) counter = 1 if options.log != None: f = open(options.log, 'w') f.close() else: fPickle = open(options.resume, 'rb') filenames, countFilenames, counter = pickle.load(fPickle) fPickle.close() print('Pickle file loaded') while len(filenames) > 0: filename = filenames[0] try: line = [str(counter), str(countFilenames), filename] image = naft_uf.File2Data(filename) if image == None: line.extend(['Error reading']) else: oIOSImage = naft_iipf.cIOSImage(image) if oIOSImage.oCWStrings != None and oIOSImage.oCWStrings.error == '': line.extend([naft_uf.cn(vn(oIOSImage.oCWStrings.dCWStrings, 'CW_VERSION')), naft_uf.cn(vn(oIOSImage.oCWStrings.dCWStrings, 'CW_FAMILY'))]) else: line.extend([naft_uf.cn(None), naft_uf.cn(None)]) line.extend([str(len(image)), '%.2f' % Entropy(image), str(oIOSImage.error), str(oIOSImage.oELF.error), str(oIOSImage.oELF.countSections), str(naft_uf.cn(oIOSImage.oELF.stringTableIndex)), naft_uf.cn(oIOSImage.checksumCompressed, '0x%08X'), str(oIOSImage.checksumCompressed != None and oIOSImage.checksumCompressed == oIOSImage.calculatedChecksumCompressed), naft_uf.cn(oIOSImage.checksumUncompressed, '0x%08X'), str(oIOSImage.checksumUncompressed != None and oIOSImage.checksumUncompressed == oIOSImage.calculatedChecksumUncompressed), naft_uf.cn(oIOSImage.imageUncompressedName), naft_uf.cn(oIOSImage.embeddedMD5)]) if options.md5db: md5hash = hashlib.md5(image).hexdigest() filenameCSV, filenameDB = oMD5Database.Find(md5hash) line.extend([md5hash, naft_uf.cn(filenameCSV), naft_uf.cn(filenameDB)]) strLine = ';'.join(line) print(strLine) if options.log != None: f = open(options.log, 'a') f.write(strLine + '\n') f.close() counter += 1 filenames = filenames[1:] except KeyboardInterrupt: print('KeyboardInterrupt') PickleData([filenames, countFilenames, counter]) return except: traceback.print_exc() PickleData([filenames, countFilenames, counter]) return
def IOSCheckText(coredumpFilename, imageFilename, options): oIOSCoreDump = naft_impf.cIOSCoreDump(coredumpFilename) if oIOSCoreDump.error != '': print(oIOSCoreDump.error) return else: textAddress, textCoredump = oIOSCoreDump.RegionTEXT() if textCoredump == None: print('Error extracting text region from coredump %s' % coredumpFilename) return sysdescrCoredump = '' dataAddress, dataCoredump = oIOSCoreDump.RegionDATA() if dataCoredump != None: oCWStrings = naft_impf.cCiscoCWStrings(dataCoredump) if oCWStrings.error == '' and 'CW_SYSDESCR' in oCWStrings.dCWStrings: sysdescrCoredump = oCWStrings.dCWStrings['CW_SYSDESCR'] image = naft_uf.File2Data(imageFilename) if image == None: print('Error reading image %s' % imageFilename) return oIOSImage = naft_iipf.cIOSImage(image) if oIOSImage.error != 0: return sysdescrImage = '' if oIOSImage.oCWStrings != None and oIOSImage.oCWStrings.error == '' and 'CW_SYSDESCR' in oIOSImage.oCWStrings.dCWStrings: sysdescrImage = oIOSImage.oCWStrings.dCWStrings['CW_SYSDESCR'] if sysdescrCoredump != '' or sysdescrImage != '': if sysdescrCoredump == sysdescrImage: print('CW_SYSDESCR are identical:\n') print(sysdescrCoredump) elif sysdescrCoredump == sysdescrImage.replace('-MZ', '-M', 1): print('CW_SYSDESCR are equivalent:\n') print(sysdescrCoredump) else: print('CW_SYSDESCR are different:\n') print(sysdescrCoredump) print print(sysdescrImage) print oELF = naft_iipf.cELF(oIOSImage.imageUncompressed) if oELF.error != 0: print('ELF parsing error %d.' % oELF.error) return countSectionExecutableInstructions = 0 for oSectionHeader in oELF.sections: if oSectionHeader.flags & 4: # SHF_EXECINSTR executable instructions textSectionData = oSectionHeader.sectionData countSectionExecutableInstructions += 1 if countSectionExecutableInstructions != 1: print('Error executable sections in image: found %d sections, expected 1' % countSectionExecutableInstructions) return start = textAddress & 0xFF # to be further researched textImage = textSectionData[start:start + len(textCoredump)] if len(textCoredump) != len(textImage): print('the text region is longer than the text section') countBytesDifferent = 0 shortestLength = min(len(textCoredump), len(textImage)) for iIter in range(shortestLength): if textCoredump[iIter] != textImage[iIter]: if countBytesDifferent == 0: print('text region and section are different starting 0x%08X in coredump (iter = 0x%08X)' % ((textAddress + iIter), iIter)) countBytesDifferent += 1 if countBytesDifferent == 0: print('text region and section are identical') else: print('number of different bytes: %d (%.2f%%)' % (countBytesDifferent, (countBytesDifferent * 100.0) / shortestLength))
def IOSCheckText(coredumpFilename, imageFilename, options): returnString = '' oIOSCoreDump = naft_impf.cIOSCoreDump(coredumpFilename) if oIOSCoreDump.error != '': returnString += (oIOSCoreDump.error) + '<br>' return returnString else: textAddress, textCoredump = oIOSCoreDump.RegionTEXT() if textCoredump == None: returnString += ( 'Error extracting text region from coredump %s<br>' % coredumpFilename) return returnString sysdescrCoredump = '' dataAddress, dataCoredump = oIOSCoreDump.RegionDATA() if dataCoredump != None: oCWStrings = naft_impf.cCiscoCWStrings(dataCoredump) if oCWStrings.error == '' and 'CW_SYSDESCR' in oCWStrings.dCWStrings: sysdescrCoredump = oCWStrings.dCWStrings['CW_SYSDESCR'] image = naft_uf.File2Data(imageFilename) if image == None: returnString += ('Error reading image %s' % imageFilename) return returnString oIOSImage = naft_iipf.cIOSImage(image) if oIOSImage.error != 0: return sysdescrImage = '' if oIOSImage.oCWStrings != None and oIOSImage.oCWStrings.error == '' and 'CW_SYSDESCR' in oIOSImage.oCWStrings.dCWStrings: sysdescrImage = oIOSImage.oCWStrings.dCWStrings['CW_SYSDESCR'] if sysdescrCoredump != '' or sysdescrImage != '': if sysdescrCoredump == sysdescrImage: returnString += ('CW_SYSDESCR are identical:<br>') returnString += (sysdescrCoredump) + '<br>' elif sysdescrCoredump == sysdescrImage.replace('-MZ', '-M', 1): returnString += ('CW_SYSDESCR are equivalent:<br>') returnString += (sysdescrCoredump) + '<br>' else: returnString += ('CW_SYSDESCR are different:<br>') returnString += (sysdescrCoredump) + '<br>' returnString += '<br>' returnString += (sysdescrImage) + '<br>' returnString += '<br>' oELF = naft_iipf.cELF(oIOSImage.imageUncompressed) if oELF.error != 0: returnString += ('ELF parsing error %d.' % oELF.error) return returnString countSectionExecutableInstructions = 0 countSectionSRELOC = 0 for oSectionHeader in oELF.sections: if oSectionHeader.flags & 4: # SHF_EXECINSTR executable instructions textSectionData = oSectionHeader.sectionData countSectionExecutableInstructions += 1 if oSectionHeader.nameIndexString == 'sreloc': countSectionSRELOC += 1 if countSectionExecutableInstructions != 1: returnString += ( 'Error executable sections in image: found %d sections, expected 1' % countSectionExecutableInstructions) return returnString if countSectionSRELOC != 0: returnString += ( 'Error found %d sreloc section in image: checktext command does not support relocation' % countSectionSRELOC) return returnString start = textAddress & 0xFF # to be further researched textImage = textSectionData[start:start + len(textCoredump)] if len(textCoredump) != len(textImage): returnString += ('the text region is longer than the text section<br>') returnString += ('len(textCoredump) = %d<br>' % len(textCoredump)) returnString += ('len(textImage) = %d<br>' % len(textImage)) countBytesDifferent = 0 shortestLength = min(len(textCoredump), len(textImage)) for iIter in range(shortestLength): if textCoredump[iIter] != textImage[iIter]: if countBytesDifferent == 0: returnString += ( 'text region and section are different starting 0x%08X in coredump (iter = 0x%08X)<br>' % ((textAddress + iIter), iIter)) countBytesDifferent += 1 if countBytesDifferent == 0: returnString += ('text region and section are identical <br>') else: returnString += ('number of different bytes: %d (%.2f%%)<br>' % (countBytesDifferent, (countBytesDifferent * 100.0) / shortestLength)) return returnString
def CiscoIOSImageFileScanner(filewildcard, options): if options.resume == None: filenames = GlobFilelist(filewildcard, options) countFilenames = len(filenames) counter = 1 if options.log != None: f = open(options.log, 'w') f.close() else: fPickle = open(options.resume, 'rb') filenames, countFilenames, counter = pickle.load(fPickle) fPickle.close() print('Pickle file loaded') while len(filenames) > 0: filename = filenames[0] try: line = [str(counter), str(countFilenames), filename] image = naft_uf.File2Data(filename) if image == None: line.extend(['Error reading']) else: oIOSImage = naft_iipf.cIOSImage(image) if oIOSImage.oCWStrings != None and oIOSImage.oCWStrings.error == '': line.extend([ naft_uf.cn( vn(oIOSImage.oCWStrings.dCWStrings, 'CW_VERSION')), naft_uf.cn( vn(oIOSImage.oCWStrings.dCWStrings, 'CW_FAMILY')) ]) else: line.extend([naft_uf.cn(None), naft_uf.cn(None)]) line.extend([ str(len(image)), '%.2f' % Entropy(image), str(oIOSImage.error), str(oIOSImage.oELF.error), str(oIOSImage.oELF.countSections), str(naft_uf.cn(oIOSImage.oELF.stringTableIndex)), naft_uf.cn(oIOSImage.checksumCompressed, '0x%08X'), str(oIOSImage.checksumCompressed != None and oIOSImage.checksumCompressed == oIOSImage.calculatedChecksumCompressed), naft_uf.cn(oIOSImage.checksumUncompressed, '0x%08X'), str(oIOSImage.checksumUncompressed != None and oIOSImage.checksumUncompressed == oIOSImage.calculatedChecksumUncompressed), naft_uf.cn(oIOSImage.imageUncompressedName), naft_uf.cn(oIOSImage.embeddedMD5) ]) if options.md5db: md5hash = hashlib.md5(image).hexdigest() filenameCSV, filenameDB = oMD5Database.Find(md5hash) line.extend([ md5hash, naft_uf.cn(filenameCSV), naft_uf.cn(filenameDB) ]) strLine = ';'.join(line) print(strLine) if options.log != None: f = open(options.log, 'a') f.write(strLine + '\n') f.close() counter += 1 filenames = filenames[1:] except KeyboardInterrupt: print('KeyboardInterrupt') PickleData([filenames, countFilenames, counter]) return except: traceback.print_exc() PickleData([filenames, countFilenames, counter]) return