Example #1
0
 def bupextract():
     # Check for valid OLE
     if not OleFileIO_PL.isOleFile(__sessions__.current.file.path):
         print_error("Not a valid BUP File")
         return
     ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
     # We know that BUPS are xor'd with 6A which is dec 106 for the decoder
     print_info("Switching Session to Embedded File")
     data = xordata(ole.openstream('File_0').read(), 106)
     # this is a lot of work jsut to get a filename.
     data2 = xordata(ole.openstream('Details').read(), 106)
     ole.close()
     lines = data2.split('\n')
     for line in lines:
         if line.startswith('OriginalName'):
             fullpath = line.split('=')[1]
             pathsplit = fullpath.split('\\')
             filename = str(pathsplit[-1][:-1])
     # now lets write the data out to a file and get a session on it
     if data:
         tempName = os.path.join('/tmp', filename)
         with open(tempName, 'w') as temp:
             temp.write(data)
         __sessions__.new(tempName)
         return
     else:
         print_error("Unble to Switch Session")
Example #2
0
def printDump(bupname, DumpFunction=IdentityFunction, allfiles=False):
    #
    #Print Hex dump/Hex-ASCII dump of first or all streams
    #
    if sys.platform == 'win32' and DumpFunction == IdentityFunction:
        import msvcrt
        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
    try:
        if OleFileIO_PL.isOleFile(bupname) is not True:
            print('Error - %s is not a valid OLE file.' % bupname,
                  file=sys.stderr)
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(bupname)
        printNewline = False
        for entry in ole.listdir():
            if entry[0] != "Details":
                if printNewline:
                    print()
                printNewline = True
                StdoutWriteChunked(
                    DumpFunction(decryptStream(
                        ole.openstream(entry[0]).read())))
                if not allfiles:
                    break
        ole.close()
    except Exception as e:
        print('Error - %s' % e, file=sys.stderr)
        sys.exit(1)
Example #3
0
def getHashes(bupname, htype):
    #
    #Return a dictionary of stream name and hash.
    #
    try:
        if OleFileIO_PL.isOleFile(bupname) is not True:
            print >> sys.stderr, 'Error - %s is not a valid OLE file.' % bupname
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(bupname)
        hashes = {}
        for entry in ole.listdir():
            if entry[0] != "Details":
                fdata = ole.openstream(entry[0]).read()
                ptext = decryptStream(fdata)
                if htype == 'md5':
                    m = hashlib.md5()
                elif htype == 'sha1':
                    m = hashlib.sha1()
                elif htype == 'sha256':
                    m = hashlib.sha256()
                m.update(ptext)
                hashes[entry[0]] = m.hexdigest()
        ole.close()
        return hashes
    except Exception as e:
        print >> sys.stderr, 'Error - %s' % e
        sys.exit(1)
Example #4
0
def readRSF(filePath, fileName):
    '''Parses the information stored in the RecoveryStore file.
    Accepts single argument: the file name of the RecoveryStore file.'''
    fname = os.path.join(filePath, fileName)
    print("\n" + fileName + ":")
    try:
        #Check if file is the correct format
        if not (OleFileIO_PL.isOleFile(fname)):
            print("    Error: Unable to parse file '%s'. Incorrect format!" %
                  fname)
            return
        path = os.path.dirname(fname)
        rs = OleFileIO_PL.OleFileIO(fname)
        #Get list of streams
        streams = rs.listdir()
        sStreams = []
        for s in (streams):
            sStreams.append(s[0])
        p = rs.getproperties('\x05KjjaqfajN2c0uzgv1l4qy5nfWe')
        #Get session times
        closed = (buildTime(p[3]))
        opened = (buildTime(p[7]))
        print("    Opened:             " + opened + " UTC")
        if (opened != closed):
            print("    Closed:             " + closed + " UTC")
        else:
            print("    Closed:             N/A")
        #Check for InPrivate Browsing
        if (int("5") in p):
            print("    InPrivate Browsing: YES")
        else:
            print("    InPrivate Browsing: No")
        #Get all open tabs (TS#)
        print("\n    Open Tabs:")
        for s in streams:
            if ((s[0][:2] == "TS")):
                tempStream = rs.openstream(s[0])
                data = tempStream.read()
                tsStr = "".join("{:02x}".format(c) for c in data)
                b = 0
                while b < len(tsStr):
                    tdName = "{" + buildGUID(tsStr[b:b + 32]) + "}.dat"
                    readTDF(filePath, tdName, "        ")
                    b += 32
        #Get all closed tabs
        print("\n    Closed Tabs:")
        for s in streams:
            if (s[0] == "ClosedTabList"):
                tempStream = rs.openstream(s[0])
                data = tempStream.read()
                tempStream = rs.openstream(s[0])
                data = tempStream.read()
                tsStr = "".join("{:02x}".format(c) for c in data)
                b = 0
                while b < len(tsStr):
                    tdName = "{" + buildGUID(tsStr[b:b + 32]) + "}.dat"
                    readTDF(filePath, tdName, "        ")
                    b += 32
    except:
        print("\nError reading '" + fname + "': ", sys.exc_info()[1])
Example #5
0
def extract(infile, dirname=None):
    if dirname is None:
        dirname = os.getcwd()
    try:
        if OleFileIO_PL.isOleFile(infile) is not True:
            print('Error - %s is not a valid OLE file.' % infile,
                  file=sys.stderr)
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(infile)
        filelist = ole.listdir()
        for fname in filelist:
            if not ole.get_size(fname[0]):
                print(
                    'Warning: The "%s" stream reports a size of 0. Possibly a corrupt bup.'
                    % fname[0])
            data = ole.openstream(fname[0]).read()
            fp = open(os.path.join(dirname, fname[0]), 'wb')
            fp.write(data)
            fp.close()
        ole.close()
        return filelist
    except Exception as e:
        print('Error - %s' % e, file=sys.stderr)
        sys.exit(1)
Example #6
0
def OLEDump(filename):
    if OleFileIO_PL.isOleFile(filename) is not True:
        print >> sys.stderr, 'Error - %s is not a valid OLE file.' % infile
        sys.exit(1)
    ole = OleFileIO_PL.OleFileIO(filename)

    for fname in ole.listdir():
        stream = ole.openstream(fname).read()
        if '\x00Attribut' in stream:
            StdoutWriteChunked(SearchAndDecompress(stream))
    ole.close()
    return
Example #7
0
    def run(self):
        super(Office, self).run()
        if self.args is None:
            return

        if not __sessions__.is_set():
            self.log('error', "No session opened")
            return

        if not HAVE_OLE:
            self.log(
                'error',
                "Missing dependency, install OleFileIO (`pip install OleFileIO_PL`)"
            )
            return

        # Tests to check for valid Office structures.
        OLE_FILE = OleFileIO_PL.isOleFile(__sessions__.current.file.path)
        XML_FILE = zipfile.is_zipfile(__sessions__.current.file.path)
        if OLE_FILE:
            ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
        elif XML_FILE:
            zip_xml = zipfile.ZipFile(__sessions__.current.file.path, 'r')
        else:
            self.log('error', "Not a valid office document")
            return

        if self.args.export is not None:
            if OLE_FILE:
                self.export(ole, self.args.export)
            elif XML_FILE:
                self.xml_export(zip_xml, self.args.export)
        elif self.args.meta:
            if OLE_FILE:
                self.metadata(ole)
            elif XML_FILE:
                self.xmlmeta(zip_xml)
        elif self.args.streams:
            if OLE_FILE:
                self.metatimes(ole)
            elif XML_FILE:
                self.xmlstruct(zip_xml)
        elif self.args.oleid:
            if OLE_FILE:
                self.oleid(ole)
            else:
                self.log('error', "Not an OLE file")
        elif self.args.vba or self.args.code:
            self.parse_vba(self.args.code)
        else:
            self.log('error', 'At least one of the parameters is required')
            self.usage()
Example #8
0
def OLEDump(filename, options):
    if options.raw:
        print SearchAndDecompress(File2String(filename))
        return

    if filename == '':
        IfWIN32SetBinary(sys.stdin)
        ole = OleFileIO_PL.OleFileIO(cStringIO.StringIO(sys.stdin.read()))
    elif IsZIPFile(filename):
        oZipfile = zipfile.ZipFile(filename, 'r')
        oZipContent = oZipfile.open(oZipfile.infolist()[0], 'r',
                                    C2BIP3(MALWARE_PASSWORD))
        ole = OleFileIO_PL.OleFileIO(cStringIO.StringIO(oZipContent.read()))
        oZipContent.close()
    else:
        if OleFileIO_PL.isOleFile(filename) is not True:
            print >> sys.stderr, 'Error - %s is not a valid OLE file.' % infile
            sys.exit(1)
        ole = OleFileIO_PL.OleFileIO(filename)

    if options.select == '':
        counter = 1
        for fname in ole.listdir():
            stream = ole.openstream(fname).read()
            print('%2d: %s %6d %s' %
                  (counter, IFF('\x00Attribut' in stream, 'M',
                                ' '), len(stream), PrintableName(fname)))
            counter += 1
    else:
        if options.dump:
            DumpFunction = lambda x: x
            IfWIN32SetBinary(sys.stdout)
        elif options.hexdump:
            DumpFunction = HexDump
        elif options.vbadecompress:
            DumpFunction = SearchAndDecompress
        elif options.extract:
            DumpFunction = Extract
            IfWIN32SetBinary(sys.stdout)
        elif options.info:
            DumpFunction = Info
        else:
            DumpFunction = HexAsciiDump
        counter = 1
        for fname in ole.listdir():
            if counter == int(options.select):
                StdoutWriteChunked(DumpFunction(ole.openstream(fname).read()))
                break
            counter += 1
    ole.close()
Example #9
0
def getDetails(bupname):
    try:
        if OleFileIO_PL.isOleFile(bupname) is not True:
            print >> sys.stderr, 'Error - %s is not a valid OLE file.' % bupname
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(bupname)
        #clean this up later by catching exception
        data = ole.openstream("Details").read()
        ptext = decryptStream(data)
        ole.close()
        return ptext
    except Exception as e:
        print >> sys.stderr, 'Error - %s' % e
        sys.exit(1)
Example #10
0
def checkFile(name):  
    try:  
        if not converter.isOleFile(name):
            sys.exit()       
    except:
        print "ERROR: %s is not a *.msg format file" % name
        sys.exit()
Example #11
0
    def makeMutationList_(self):
        fuzz_offset = []
        fuzzing_list = []
        mutate_position = []
        ole = OLE.OleFileIO(self.targetFile)
        ole_list = ole.listdir()
        for entry in ole_list:
            if "BodyText" in entry:
                sections = entry[1:]
                for sec in sections:
                    stream = entry[0] + "/" + sec
                    size = ole.get_size(stream)
                    fuzzing_list.append(
                        (ole.openstream(stream).read(16), size))
            if "BinData" in entry:
                sections = entry[1:]
                for sec in sections:
                    stream = entry[0] + "/" + sec
                    size = ole.get_size(stream)
                    fuzzing_list.append(
                        (ole.openstream(stream).read(16), size))

        ole.close()
        for magic, size in fuzzing_list:
            if self.data.find(magic) != -1:
                offset = self.data.find(magic)
                mutate_position.append((offset, size))
        for offset, size in mutate_position:
            fuzz_offset += sample(xrange(offset, offset + size),
                                  int(size *
                                      uniform(0.001, 0.003)))  # 0.1% ~ 0.3%
        for index in fuzz_offset:
            self.mutationList.append([index])
            self.mutationList[-1].append(chr(randrange(256)))
Example #12
0
 def bupextract():
     # Check for valid OLE
     if not OleFileIO_PL.isOleFile(__sessions__.current.file.path):
         print_error("Not a valid BUP File")
         return
     ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
     # We know that BUPS are xor'd with 6A which is dec 106 for the decoder
     print_info("Switching Session to Embedded File")
     data = xordata(ole.openstream('File_0').read(), 106)
     # this is a lot of work jsut to get a filename.
     data2 = xordata(ole.openstream('Details').read(), 106)
     ole.close()
     lines = data2.split('\n')
     for line in lines:
         if line.startswith('OriginalName'):
             fullpath = line.split('=')[1]
             pathsplit = fullpath.split('\\')
             filename = str(pathsplit[-1][:-1])
     # now lets write the data out to a file and get a session on it
     if data:
         tempName = os.path.join('/tmp', filename)
         with open(tempName, 'w') as temp:
             temp.write(data)
         __sessions__.new(tempName)
         return
     else:
         print_error("Unble to Switch Session")
Example #13
0
def getHashes(bupname,htype):
    #
    #Return a dictionary of stream name and hash. 
    #
    try:
        if OleFileIO_PL.isOleFile(bupname) is not True:
            print >>sys.stderr, 'Error - %s is not a valid OLE file.' % bupname
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(bupname)                
        hashes = {}
        for entry in ole.listdir():
            if entry[0] != "Details":
                fdata = ole.openstream(entry[0]).read()
                ptext = decryptStream(fdata)
                if htype == 'md5':
                    m = hashlib.md5() 
                elif htype == 'sha1':
                    m = hashlib.sha1() 
                elif htype == 'sha256':
                    m = hashlib.sha256() 
                m.update(ptext)
                hashes[entry[0]] = m.hexdigest()                    
        ole.close()        
        return hashes
    except Exception as e:
        print >>sys.stderr, 'Error - %s' % e
        sys.exit(1)
def extract(filename):
    out = os.popen(
        "PYTHONPATH= python /Users/adam/code/unoconv/unoconv -T 3 -o tmp.txt -f txt %s"
        % filename).read()
    txt = file("tmp.txt").read().split('\n')
    end = 0
    start = len(txt)
    date = None
    for i, line in enumerate(txt):
        if 'בברכה' in line: end = i
        if 'בכבוד רב' in line: end = i
        if 'הנדון' in line: start = i
        dates = date_re.findall(line)
        if len(dates) > 0:
            date = dates[0]
    if date is None:
        ole = OleFileIO_PL.OleFileIO(filename)
        meta = ole.get_metadata()
        date = meta.last_saved_time
    else:
        date = parser.parse(date)
    explanation = None
    if start < end:
        explanation = "".join(txt[start + 1:end]).decode('utf8')
    return date, explanation
Example #15
0
def printDump(bupname, DumpFunction=IdentityFunction, allfiles=False):
    #
    #Print Hex dump/Hex-ASCII dump of first or all streams
    #
    if sys.platform == 'win32' and DumpFunction == IdentityFunction:
        import msvcrt
        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
    try:
        if OleFileIO_PL.isOleFile(bupname) is not True:
            print >>sys.stderr, 'Error - %s is not a valid OLE file.' % bupname
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(bupname)
        printNewline = False
        for entry in ole.listdir():
            if entry[0] != "Details":
                if printNewline:
                    print
                printNewline = True
                StdoutWriteChunked(DumpFunction(decryptStream(ole.openstream(entry[0]).read())))
                if not allfiles:
                    break
        ole.close()
    except Exception as e:
        print >>sys.stderr, 'Error - %s' % e
        sys.exit(1)
Example #16
0
def zvi_read(fname, plane, ole=None):
    """ returns ZviItemTuple of the plane from zvi file fname """
    if ole is None:
        ole = OleFileIO_PL.OleFileIO(fname)
    s = ['Image', 'Item(%d)' % plane, 'Contents']
    stream = ole.openstream(s)
    return read_item_storage_content(stream)
Example #17
0
def readRSF(filePath, fileName): 
    '''Parses the information stored in the RecoveryStore file.
    Accepts single argument: the file name of the RecoveryStore file.'''
    fname = os.path.join(filePath, fileName)
    print("\n" + fileName + ":")
    try:
        #Check if file is the correct format
        if not (OleFileIO_PL.isOleFile(fname)):
            print("    Error: Unable to parse file '%s'. Incorrect format!" % fname)
            return
        path = os.path.dirname(fname)
        rs = OleFileIO_PL.OleFileIO(fname)
        #Get list of streams
        streams = rs.listdir()
        sStreams = []
        for s in (streams):
            sStreams.append(s[0])
        p = rs.getproperties('\x05KjjaqfajN2c0uzgv1l4qy5nfWe')
        #Get session times
        closed = (buildTime(p[3]))
        opened = (buildTime(p[7]))
        print("    Opened:             " + opened + " UTC")
        if (opened != closed) :
            print("    Closed:             " + closed + " UTC")
        else:
            print("    Closed:             N/A")
        #Check for InPrivate Browsing
        if (int("5") in p):
            print("    InPrivate Browsing: YES") 
        else:
            print("    InPrivate Browsing: No") 
        #Get all open tabs (TS#)
        print("\n    Open Tabs:")
        for s in streams:
            if((s[0][:2] == "TS") ):
                tempStream = rs.openstream(s[0])
                data = tempStream.read()
                tsStr = "".join("{:02x}".format(c) for c in data)
                b = 0
                while b < len(tsStr):
                    tdName = "{" + buildGUID(tsStr[b:b + 32]) + "}.dat"
                    readTDF(filePath, tdName, "        ")
                    b += 32
        #Get all closed tabs
        print("\n    Closed Tabs:")
        for s in streams:
            if(s[0] == "ClosedTabList"):
                tempStream = rs.openstream(s[0])
                data = tempStream.read()
                tempStream = rs.openstream(s[0])
                data = tempStream.read()
                tsStr = "".join("{:02x}".format(c) for c in data)
                b = 0
                while b < len(tsStr):
                    tdName = "{" + buildGUID(tsStr[b:b + 32]) + "}.dat"
                    readTDF(filePath, tdName, "        ")
                    b += 32
    except:
        print("\nError reading '" + fname + "': ", sys.exc_info()[1])
Example #18
0
def get_layer_count(file_name, ole=None):
    """ returns the number of image planes"""
    if ole is None:
        ole = OleFileIO_PL.OleFileIO(file_name)
    s = ['Image', 'Contents']
    stream = ole.openstream(s)
    zvi_image = read_image_container_content(stream)
    return zvi_image.Count
Example #19
0
def mutation(dest_file):
    """

    :param dest_file: 뮤테이션 할 파일 경로 전달
    """
    find_list = []
    mutate_position = []
    # HWP파일의 OLE구조에서 Bindata, BodyText, BinOLE 스토리지 하위 스트림 분석
    # 해당 스트림의 상위 16바이트를 Magic으로 사용하고 사이즈를 구함
    ole = OLE.OleFileIO(dest_file)
    ole_list = ole.listdir()

    for entry in ole_list:
        if "BinData" in entry and entry[1].find("OLE") != -1:
            find_list.append((ole.openstream("BinData/" + entry[1]).read(16),
                              ole.get_size("BinData/" + entry[1])))
        if "BodyText" in entry:
            find_list.append((ole.openstream("BodyText/" + entry[1]).read(16),
                              ole.get_size("BodyText/" + entry[1])))
        if "BinOLE" in entry:
            find_list.append((ole.openstream("BinOLE/" + entry[1]).read(16),
                              ole.get_size("BinOLE/" + entry[1])))
        if "Workbook" in entry:
            find_list.append((ole.openstream("Workbook").read(16),
                              ole.get_size("Workbook")))
    ole.close()

    fuzz_offset = []
    fuzz_byte = xrange(256)
    with open(dest_file, 'rb') as f:
        hwp = f.read()

    hwp_write = bytearray(hwp)
    hwp_length = len(hwp)
    # 파일에서 Magic의 오프셋을 검색하여 리스트에 저장
    for magic, size in find_list:
        if hwp.find(magic) != -1:
            offset = hwp.find(magic)
            mutate_position.append((offset, size))

    # 해당 스트림 사이즈의 1 ~ 10% 변조 할 오프셋 선택
    for offset, size in mutate_position:
        fuzz_offset += sample(xrange(offset, offset + size),
                              int(size * uniform(0.01, 0.1)))

    # 변조
    for index in fuzz_offset:
        if index >= hwp_length: continue
        hwp_write[index] = choice(fuzz_byte)
    # 파일로 저장
    try:
        with open(dest_file, 'wb') as f:
            f.write(hwp_write)
        return True
    except IOError as error:
        print error
        return False
Example #20
0
def test_isOleFile_true():
    # Arrange
    ole_file = "Tests/images/test-ole-file.doc"

    # Act
    is_ole = OleFileIO.isOleFile(ole_file)

    # Assert
    assert_true(is_ole)
Example #21
0
def test_isOleFile_false():
    # Arrange
    non_ole_file = "Tests/images/flower.jpg"

    # Act
    is_ole = OleFileIO.isOleFile(non_ole_file)

    # Assert
    assert_false(is_ole)
Example #22
0
def test_get_size():
    # Arrange
    ole_file = "Tests/images/test-ole-file.doc"
    ole = OleFileIO.OleFileIO(ole_file)

    # Act
    size = ole.get_size('worddocument')

    # Assert
    assert_greater(size, 0)
Example #23
0
def load_image(path_img):
    ole = OleFileIO_PL.OleFileIO(path_img)
    nb = get_layer_count('', ole=ole)
    # logging.debug('Count layers = %i', nb)
    image = []
    for i in range(nb):
        zvi = zvi_read('', i, ole=ole)
        image.append(zvi.Image.Array)
    image = np.array(image)
    return image
Example #24
0
def test_get_rootentry_name():
    # Arrange
    ole_file = "Tests/images/test-ole-file.doc"
    ole = OleFileIO.OleFileIO(ole_file)

    # Act
    root = ole.get_rootentry_name()

    # Assert
    assert_equal(root, "Root Entry")
Example #25
0
def test_exists_no_vba_macros():
    # Arrange
    ole_file = "Tests/images/test-ole-file.doc"
    ole = OleFileIO.OleFileIO(ole_file)

    # Act
    exists = ole.exists('macros/vba')

    # Assert
    assert_false(exists)
Example #26
0
def test_get_type():
    # Arrange
    ole_file = "Tests/images/test-ole-file.doc"
    ole = OleFileIO.OleFileIO(ole_file)

    # Act
    type = ole.get_type('worddocument')

    # Assert
    assert_equal(type, OleFileIO.STGTY_STREAM)
Example #27
0
def test_exists_worddocument():
    # Arrange
    ole_file = "Tests/images/test-ole-file.doc"
    ole = OleFileIO.OleFileIO(ole_file)

    # Act
    exists = ole.exists('worddocument')

    # Assert
    assert_true(exists)
Example #28
0
def get_dir(file_name, ole=None):
    """ returns the content structure(streams) of the zvi file
    + length of each streams """
    dirs = []
    if ole is None:
        ole = OleFileIO_PL.OleFileIO(file_name)
    for s in ole.listdir():
        stream = ole.openstream(s)
        dirs.append('%10d %s'%(len(stream.read()), s))
    return dirs
def OLEDump(filename):
    if OleFileIO_PL.isOleFile(filename) is not True:
          print >>sys.stderr, 'Error - %s is not a valid OLE file.' % infile
          sys.exit(1)
    ole = OleFileIO_PL.OleFileIO(filename)

    
    for fname in ole.listdir():
            stream = ole.openstream(fname).read()
            if '\x00Attribut' in stream:
                line = SearchAndDecompress(stream)
 		line = re.sub (r'[cC][hH][rR][wW\$]*\(([\d+\+\-\s\.]*)\)', do_chr, line)
		line = re.sub (" & ", "", line)
		line = re.sub ("& ", "", line)
		line = line.replace("\"","")
		line = re.sub (r'[sS][tT][rR][rR][eE][vV][eE][rR][sS][eE]\(([^)]*)\)', do_strme, line)
		line = line.rstrip ()        
                StdoutWriteChunked(line)
    ole.close()
    return 
Example #30
0
def test_meta():
    # Arrange
    ole_file = "Tests/images/test-ole-file.doc"
    ole = OleFileIO.OleFileIO(ole_file)

    # Act
    meta = ole.get_metadata()

    # Assert
    assert_equal(meta.author, b"Laurence Ipsum")
    assert_equal(meta.num_pages, 1)
Example #31
0
def extract(infile, dirname=None):
    if dirname is None:
        dirname = os.getcwd()
    try:
        if OleFileIO_PL.isOleFile(infile) is not True:
            print >> sys.stderr, 'Error - %s is not a valid OLE file.' % infile
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(infile)
        filelist = ole.listdir()
        for fname in filelist:
            data = ole.openstream(fname[0]).read()
            fp = open(os.path.join(dirname, fname[0]), 'wb')
            fp.write(data)
            fp.close()
        ole.close()
        return filelist
    except Exception as e:
        print >> sys.stderr, 'Error - %s' % e
        sys.exit(1)
Example #32
0
def analysisMax(filePath, resultPath):
    fileError=0
    settingsPath = resultPath + "/analysis.log"
    settingsFile = open(settingsPath, "w")
    if os.path.exists(filePath):
        if olefile.isOleFile(filePath):
            try:
                maxOle = olefile.OleFileIO(filePath)
            except:
                print "file is error"
                fileError = 1
        else:
            print "file is not a ole2 file"
            fileError = 1
    else:
        print "file is not exist"
        fileError = 1
    if fileError==1:
        settingsFile.write("{\"applications\":{\"fileError\":\"1\"}}")
        settingsFile.close()
        sys.exit(1)
    print "setting info. analyze is start"
    # 配置信息解析
    try:
        summary = maxOle.openstream("\x05DocumentSummaryInformation")
    except:
        fileError=1
        settingsFile.write("{\"applications\":{\"fileError\":\"1\"}}")
        settingsFile.close()
        sys.exit(1)
    rawData = summary.read()
    maxOle.close()
    docSummaryInfo = oleDocumentSummaryInfo(rawData)
    docSummaryInfo.analysisDocSummaryString()
    if not docSummaryInfo.dataDocSummaryDict["applications"]["softwareconfig"].has_key('version'):
        docSummaryInfo.dataDocSummaryDict["applications"]["softwareconfig"]["version"] = 2007
    if not docSummaryInfo.dataDocSummaryDict["applications"]["softwareconfig"].has_key('realVersion'):
        docSummaryInfo.dataDocSummaryDict["applications"]["softwareconfig"]["realVersion"] = 2007
    settingsFile.write(json.dumps(docSummaryInfo.dataDocSummaryDict))
    settingsFile.close()
    print "setting info. analyze is over"
Example #33
0
    def run(self):
        if not __sessions__.is_set():
            print_error("No session opened")
            return

        if not HAVE_OLE:
            print_error("Missing dependency, install OleFileIO (`pip install OleFileIO_PL`)")
            return

        def usage():
            print("usage: office [-hmsoe:]")

        def help():
            usage()
            print("")
            print("Options:")
            print("\t--help (-h)\tShow this help message")
            print("\t--meta (-m)\tGet The Metadata")
            print("\t--struct (-s)\tShow The OLE Structure")
            print("\t--oleid (-o)\tGet The OLE Information")
            print("\t--export (-e)\tExport OLE Objects (specify destination folder)")
            print("")

        if not OleFileIO_PL.isOleFile(__sessions__.current.file.path):
            print_error('This is not a valid OLE File, abort')
            return

        ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)

        try:
            opts, argv = getopt.getopt(self.args[0:], 'hmsoe:', ['help', 'meta', 'struct', 'oleid', 'export:'])
        except getopt.GetoptError as e:
            print(e)
            return

        for opt, value in opts:
            if opt in ('-e', '--export'):
                self.export(ole, value)
                return
            if opt in ('-h', '--help'):
                help()
                return
            if opt in ('-m','--meta'):
                self.metadata(ole)
                return
            if opt in ('-s','--struct'):
                self.metatimes(ole)
                return
            if opt in ('-o','--oleid'):
                self.oleid(ole)
                return

        usage()
Example #34
0
def OLEDump(filename):
    if OleFileIO_PL.isOleFile(filename) is not True:
          print >>sys.stderr, 'Error - %s is not a valid OLE file.' % infile
          sys.exit(1)
    ole = OleFileIO_PL.OleFileIO(filename)

    
    for fname in ole.listdir():
            stream = ole.openstream(fname).read()
            if '\x00Attribut' in stream:
                StdoutWriteChunked(SearchAndDecompress(stream))
    ole.close()
    return 
Example #35
0
    def run(self):
        super(Office, self).run()
        if self.args is None:
            return

        if not __sessions__.is_set():
            self.log('error', "No session opened")
            return

        if not HAVE_OLE:
            self.log('error', "Missing dependency, install OleFileIO (`pip install OleFileIO_PL`)")
            return

        # Tests to check for valid Office structures.
        OLE_FILE = OleFileIO_PL.isOleFile(__sessions__.current.file.path)
        XML_FILE = zipfile.is_zipfile(__sessions__.current.file.path)
        if OLE_FILE:
            ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
        elif XML_FILE:
            zip_xml = zipfile.ZipFile(__sessions__.current.file.path, 'r')
        else:
            self.log('error', "Not a valid office document")
            return

        if self.args.export is not None:
            if OLE_FILE:
                self.export(ole, self.args.export)
            elif XML_FILE:
                self.xml_export(zip_xml, self.args.export)
        elif self.args.meta:
            if OLE_FILE:
                self.metadata(ole)
            elif XML_FILE:
                self.xmlmeta(zip_xml)
        elif self.args.streams:
            if OLE_FILE:
                self.metatimes(ole)
            elif XML_FILE:
                self.xmlstruct(zip_xml)
        elif self.args.oleid:
            if OLE_FILE:
                self.oleid(ole)
            else:
                self.log('error', "Not an OLE file")
        elif self.args.vba or self.args.code:
            self.parse_vba(self.args.code)
        else:
            self.log('error', 'At least one of the parameters is required')
            self.usage()
Example #36
0
    def is_ole(self, f):
        meta = OleFileIO_PL.OleFileIO(f).get_metadata()
        ret = {}

        for prop in (meta.SUMMARY_ATTRIBS + meta.DOCSUM_ATTRIBS):
            value = getattr(meta, prop)
            if value:
                if prop == 'creating_application':
                    ret = self.addto(ret, 'Software', value)

                elif prop == 'security':
                    ret = self.addto(ret, 'security', SEC_VALS[value])

                elif prop in ('create_time', 'last_printed',
                              'last_saved_time'):
                    prop = prop.replace('num_',
                                        '').replace('_',
                                                    ' ').replace(' time',
                                                                 '').title()
                    try:
                        prop += '</b>: ' + value.strftime("%m-%d-%Y %H:%M:%S")
                    except:
                        prop += '</b>: Never'

                    ret = self.addto(ret, 'dates',
                                     "<small><b>" + prop + "</small>")

                elif prop in ('author', 'last_saved_by'):
                    ret = self.addto(ret, 'users', value)

                elif prop in ('codepage', 'codepage_doc'):
                    try:
                        x = self.CODEPAGE_VALS[value]
                    except:
                        x = 'Unknown: ' + str(value)
                    ret = self.addto(ret, 'Encoding', x)

                elif prop in ('paragraphs', 'num_words', 'num_pages',
                              'num_chars', 'lines', 'chars_with_spaces',
                              'slides', 'notes'):
                    ret = self.addto(
                        ret, 'Statistics', "%s: %s  " %
                        (prop.replace('num_', '').replace('_', ' '), value))

                elif prop not in ('content_status', 'thumbnail', 'version',
                                  'bytes', 'total_edit_time'):  # don't care
                    ret = self.addto(ret, prop, str(value))

        return ret
Example #37
0
def getDetails(bupname):
    try:
        if OleFileIO_PL.isOleFile(bupname) is not True:
            print >>sys.stderr, 'Error - %s is not a valid OLE file.' % bupname
            sys.exit(1)

        ole = OleFileIO_PL.OleFileIO(bupname)
        #clean this up later by catching exception
        data = ole.openstream("Details").read()
        ptext=decryptStream(data)
        ole.close()
        return ptext
    except Exception as e:
        print >>sys.stderr, 'Error - %s' % e
        sys.exit(1)
Example #38
0
    def get_dataframe(self):
        self.download()
        df = None
        try:
            df = pd.read_excel(self.file_name, **self)
        except CompDocError:
            with open(self.file_name, 'rb') as file:
                ole = OleFileIO_PL.OleFileIO(file)
                if ole.exists('Workbook'):
                    stream = ole.openstream('Workbook')
                    df = pd.read_excel(stream, **self)

        if hasattr(self, 'columns'):
            df = df[self.columns]
        if hasattr(self, "remove_local_files"): self.remove_local_files()
        return df
Example #39
0
    def _process(self, filename):
        """
        Busca imágenes dentro de stream y guarda referencia a su ubicación.
        """
        olefile = OleFile.OleFileIO(filename)

        # Al igual que en pptx esto no es un error
        if not olefile.exists("Pictures"):
            return
            #raise IOError("Pictures stream not found")

        self.__stream = olefile.openstream("Pictures")

        stream = self.__stream
        offset = 0
        # cantidad de imágenes encontradas
        n = 1

        while True:
            header = stream.read(self.headerlen)
            offset += self.headerlen

            if not header: break

            # cabecera
            recInstance, recType, recLen = struct.unpack_from("<HHL", header)

            # mover a siguiente cabecera
            stream.seek(recLen, 1)

            if DEBUG:
                print "%X %X %sb" % (recType, recInstance, recLen)

            extrabytes, ext = formats.get((recType, recInstance))

            # Eliminar bytes extra
            recLen -= extrabytes
            offset += extrabytes

            # Nombre de Imagen
            filename = "{0}{1}{2}".format(self.basename, n, ext)

            self._files[filename] = (offset, recLen)
            offset += recLen

            n += 1
Example #40
0
def extract(infile, dirname=None):
    if dirname is None:
        dirname = os.getcwd()
    try:
        if OleFileIO_PL.isOleFile(infile) is not True:
            print >>sys.stderr, 'Error - %s is not a valid OLE file.' % infile
            sys.exit(1)
        
        ole = OleFileIO_PL.OleFileIO(infile)
        filelist = ole.listdir()
        for fname in filelist:
            data = ole.openstream(fname[0]).read()
            fp = open(os.path.join(dirname, fname[0]),'wb')
            fp.write(data)
            fp.close()
        ole.close()
        return filelist
    except Exception as e:
        print >>sys.stderr, 'Error - %s' % e
        sys.exit(1)
Example #41
0
def extract(infile, dirname=None):
    if dirname is None:
        dirname = os.getcwd()
    try:
        if OleFileIO_PL.isOleFile(infile) is not True:
            print >>sys.stderr, 'Error - %s is not a valid OLE file.' % infile
            sys.exit(1)
        
        ole = OleFileIO_PL.OleFileIO(infile)
        filelist = ole.listdir()
        for fname in filelist:
            if not ole.get_size(fname[0]):
                print 'Warning: The "%s" stream reports a size of 0. Possibly a corrupt bup.' % fname[0]
            data = ole.openstream(fname[0]).read()
            fp = open(os.path.join(dirname, fname[0]),'wb')
            fp.write(data)
            fp.close()
        ole.close()
        return filelist
    except Exception as e:
        print >>sys.stderr, 'Error - %s' % e
        sys.exit(1)
Example #42
0
import sys
import OleFileIO_PL

filename = sys.argv[1]

assert OleFileIO_PL.isOleFile(filename)
# Open OLE file:
ole = OleFileIO_PL.OleFileIO(filename)
# Get list of streams:
#print ole.listdir()
# Test if known streams/storages exist:
if ole.exists('worddocument'):
    print "This is a Word document."
    print "size :", ole.get_size('worddocument')
    if ole.exists('macros/vba'):
         print "This document seems to contain VBA macros."

def get_stream(name):
	result = ole.openstream(name).read()
	try:
		result = result.decode('utf-16')
	except Exception:
		print "Could not decode", name
	return result

names = ole.listdir()
names = map('/'.join, names)
streams = dict(zip(names, map(get_stream, ole.listdir())))
Example #43
0
 def test_isOleFile_false(self):
     is_ole = OleFileIO.isOleFile(self.non_ole_file)
     self.assertFalse(is_ole)
Example #44
0
 def test_isOleFile_true(self):
     is_ole = OleFileIO.isOleFile(self.ole_file)
     self.assertTrue(is_ole)
Example #45
0
    def run(self):
        if not __sessions__.is_set():
            print_error("No session opened")
            return

        if not HAVE_OLE:
            print_error("Missing dependency, install OleFileIO (`pip install OleFileIO_PL`)")
            return

        def usage():
            print("usage: office [-hmsoe:]")

        def help():
            usage()
            print("")
            print("Options:")
            print("\t--help (-h)\tShow this help message")
            print("\t--meta (-m)\tGet the metadata")
            print("\t--oleid (-o)\tGet the OLE information")
            print("\t--streams (-s)\tShow the document streams")
            print("\t--export (-e)\tExport all objects (specify destination folder)")
            print("")

        # Tests to check for valid Office structures.
        OLE_FILE = OleFileIO_PL.isOleFile(__sessions__.current.file.path)
        XML_FILE = zipfile.is_zipfile(__sessions__.current.file.path)
        if OLE_FILE:
            ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
        elif XML_FILE:
            zip_xml = zipfile.ZipFile(__sessions__.current.file.path, 'r')
        else:
            print_error("Not a valid office document")
            return

        try:
            opts, argv = getopt.getopt(self.args[0:], 'hmsoe:', ['help', 'meta', 'streams', 'oleid', 'export:'])
        except getopt.GetoptError as e:
            print(e)
            return

        for opt, value in opts:
            if opt in ('-e', '--export'):
                if OLE_FILE:
                    self.export(ole, value)
                    return
                elif XML_FILE:
                    self.xml_export(zip_xml, value)
                    return
            if opt in ('-h', '--help'):
                help()
                return
            if opt in ('-m','--meta'):
                if OLE_FILE:
                    self.metadata(ole)
                    return
                elif XML_FILE:
                    self.xmlmeta(zip_xml)
                    return
            if opt in ('-s','--streams'):
                if OLE_FILE:
                    self.metatimes(ole)
                    return
                elif XML_FILE:
                    self.xmlstruct(zip_xml)
                    return
            if opt in ('-o','--oleid'):
                if OLE_FILE:
                    self.oleid(ole)
                    return
                else:
                    return

        usage()
Example #46
0
import OleFileIO_PL

oleFile = "C:\\Users\\morrj140\\Dev\\GitRepository\\DirCrawler\\Introduction to GBTS - v1.1.pptx"

# Test if a file is an OLE container:
assert OleFileIO_PL.isOleFile(oleFile)

# Open an OLE file:
ole = OleFileIO_PL.OleFileIO(oleFile)

# Get list of streams:
print ole.listdir()

# Test if known streams/storages exist:
if ole.exists('worddocument'):
    print "This is a Word document."
    print "size :", ole.get_size('worddocument')
    if ole.exists('macros/vba'):
         print "This document seems to contain VBA macros."

# Extract the "Pictures" stream from a PPT file:
if ole.exists('Pictures'):
    pics = ole.openstream('Pictures')
    data = pics.read()
    f = open('Pictures.bin', 'w')
    f.write(data)
    f.close()

# Extract metadata (new in v0.24) - see source code for all attributes: meta = ole.get_metadata()
print 'Author:', meta.author
print 'Title:', meta.title
Example #47
0
    for o, a in opts:
        if o == "-h":
            usage(sys.argv[0])
        if o == "-O":
            streamOffset = int(a)
        elif o == "-x":
            extractStream = a
        elif o == "-f":
            fName = a
        elif o == "-o":
            outputFile = a
        elif o == "-v":
            verbose = True
        elif o == "-d":
            OleFileIO_PL.set_debug_mode(True)
        elif o == "-X":
            extractOLE = True
        else:
            usage(sys.argv[0])

    if not fName:
        usage(sys.argv[0])

    # Test if a file is an OLE container:
    if not OleFileIO_PL.isOleFile(fName):
        print "File %s is not an OLE file" % (fName)
        sys.exit(1)

    print "[*]Opening file %s" % (fName)
Example #48
0
import OleFileIO_PL as stickyread
import re
from os.path import expanduser


home = expanduser("~")
home = home + "\\AppData\\Roaming\\Microsoft\\Sticky Notes\\StickyNotes.snt"
assert stickyread.isOleFile(home)
ole = stickyread.OleFileIO(home)
print'Root mtime=%s ctime=%s' % (ole.root.getmtime(), ole.root.getctime())
i=0
for obj in ole.listdir(streams=True, storages=False):
    if(len(obj) == 2 and obj[1] == '0'):
        strm = ole.openstream(obj)
        print "obj %d" % i
        note =  strm.read()
        note = note.replace("\n", "")
        note = note.replace("\\par", "\n")
        note = note[note.find("\\fs22 ")+6:]
        note = note[:note.find("}")]
        note = re.sub(r"\\.*\s", "", note)
        print note #re.search(r'\\fs22[\s.]*', note).group(0)
        i+=1
# Close the OLE file:
ole.close()
Example #49
0
 def is_valid_format(cls, filename):
     return OleFile.isOleFile(filename)
Example #50
0
    def run(self):
        if not __sessions__.is_set():
            print_error("No session opened")
            return

        if not HAVE_OLE:
            print_error("Missing dependency, install OleFileIO (`pip install OleFileIO_PL`)")
            return

        def usage():
            print("usage: office [-hmsoe:]")

        def help():
            usage()
            print("")
            print("Options:")
            print("\t--help (-h)\tShow this help message")
            print("\t--meta (-m)\tGet The Metadata")
            print("\t--struct (-s)\tShow The Document Structure")
            print("\t--oleid (-o)\tGet The OLE Information")
            print("\t--export (-e)\tExport All Objects (specify destination folder)")
            print("")

        # Tests to check for valid Office structures
        OLE_FILE = OleFileIO_PL.isOleFile(__sessions__.current.file.path)
        XML_FILE = zipfile.is_zipfile(__sessions__.current.file.path)
        if OLE_FILE:
            ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
        elif XML_FILE:
            zip_xml = zipfile.ZipFile(__sessions__.current.file.path, "r")
        else:
            print_error("Not A Valid Office Document")
            return

        try:
            opts, argv = getopt.getopt(self.args[0:], "hmsoe:", ["help", "meta", "struct", "oleid", "export:"])
        except getopt.GetoptError as e:
            print(e)
            return

        for opt, value in opts:
            if opt in ("-e", "--export"):
                if OLE_FILE:
                    self.export(ole, value)
                    return
                elif XML_FILE:
                    self.xml_export(zip_xml, value)
                    return
            if opt in ("-h", "--help"):
                help()
                return
            if opt in ("-m", "--meta"):
                if OLE_FILE:
                    self.metadata(ole)
                    return
                elif XML_FILE:
                    self.xmlmeta(zip_xml)
                    return
            if opt in ("-s", "--struct"):
                if OLE_FILE:
                    self.metatimes(ole)
                    return
                elif XML_FILE:
                    self.xmlstruct(zip_xml)
                    return
            if opt in ("-o", "--oleid"):
                if OLE_FILE:
                    self.oleid(ole)
                    return
                else:
                    return

        usage()
	key = hashlib.md5(real_key + '\x00\x00\x00\x00').digest()
	dec = rc4_crypt(key, verifier + verifierHash)
	if hashlib.md5(dec[:16]).digest() == dec[16:]:
		print "valid pass"
	else:
		print "invalid pass"

	
if len(sys.argv) != 3:
	print "Usage: %s <xls file> <password>" % sys.argv[0]
	sys.exit(1)
	
xlsfile = sys.argv[1]

# Test if a file is an OLE container:
if not OleFileIO_PL.isOleFile(xlsfile):
	print "Invalid XLS file"
	sys.exit(1)

# Open OLE file:
ole = OleFileIO_PL.OleFileIO(xlsfile)

workbookStream = ole.openstream('Workbook')
if workbookStream == None:
	print "Invalid XLS file"
	sys.exit(1)
	
passinfo = find_rc4_passinfo(workbookStream)
if passinfo == None:
	print "Cannot find RC4 pass info"
else:
Example #52
0
def readTDF(filePath, fileName, pad): 
    '''Parses the information stored in the tab data file.
    Accepts single argument: the file name of the tab data file.'''
    if fileName == "{00000000-0000-0000-0000-000000000000}.dat":
        return
    tdName = os.path.join(filePath, fileName)
    print(pad + fileName + ":")
    try:
        #Check if file is the correct format
        if not (OleFileIO_PL.isOleFile(tdName)):
            print("Unable to parse file '%s'. Incorrect format!" % tdname)
            return
        rs = OleFileIO_PL.OleFileIO(tdName)
        #Get list of streams
        streams = rs.listdir()
        #Get tab created time
        tGuid = fileName.replace("{", "").replace("}.dat", "")
        print(pad + "    Tab Created:  " + buildTime(tGuid) + " UTC")
        #Get travel order
        for s in streams:
            if(s[0] == "TravelLog"):
                tempStream = rs.openstream(s[0])
                data = tempStream.read()
                pos = 0
                travel = []
                while (pos < len(data)):
                    travel.append(struct.unpack('B', data[pos:pos+1])[0])
                    pos = pos + 4
                print(pad + "    Page Order:   " + '%s' % ', '.join(map(str, travel)))
        #Get all pages (TL#)
        sStreams = []
        for s in (streams):
            sStreams.append(s[0])
        p = rs.getproperties('\x05KjjaqfajN2c0uzgv1l4qy5nfWe')    
        print(pad + "    Current Page: " + p[3].rstrip('\0'))
        for s in (natural_sort(sStreams)):
            if((s[:2] == "TL") and (len(s[0]) < 6)):
                #Get page number
                tabNo = re.findall(r'\d+', s)
                tempStream = rs.openstream(s)
                data = tempStream.read()
                #Get URL info
                data_sub = bytes()
                i = 0
                while(i < len(data)) :
                    if (i % 2 == 0) :
                        data_sub += (data[i:i+1]) 
                    i = i + 1
                pattern = re.compile(b"[A-Za-z0-9/\-+:.,_$%?'()[\]=<> &]{5,500}")
                strings = pattern.findall(data_sub, 4)
                if (len(strings) > 0) :
                    print(pad + "    Page " + tabNo[0] + ":")
                    print(pad + "        URL:      " + strings[0].decode("ascii"))
                    print(pad + "        Title:    " + strings[1].decode("ascii"))
                    global verbose
                    if (verbose == 1):
                        ustrings = set(strings)
                        ustrings = list(ustrings)
                        print (pad + "        Strings:  " + ustrings[0].decode("ascii"))
                        n = 1
                        while n < len(ustrings):
                            print(pad + "                  " + ustrings[n].decode("ascii"))
                            n += 1
    except:
        print(pad + "Error reading '" + tdName + "': ", sys.exc_info()[1])
Example #53
0
    def run(self):
        if not __sessions__.is_set():
            print_error("No session opened")
            return

        if not HAVE_OLE:
            print_error("Missing dependency, install OleFileIO (`pip install OleFileIO_PL`)")
            return
        
        def xordata(data, key):
            encoded = bytearray(data)
            for i in range(len(encoded)):
                encoded[i] ^= key
            return encoded

        def bupextract():
            # Check for valid OLE
            if not OleFileIO_PL.isOleFile(__sessions__.current.file.path):
                print_error("Not a valid BUP File")
                return
            ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
            # We know that BUPS are xor'd with 6A which is dec 106 for the decoder
            print_info("Switching Session to Embedded File")
            data = xordata(ole.openstream('File_0').read(), 106)
            # this is a lot of work jsut to get a filename.
            data2 = xordata(ole.openstream('Details').read(), 106)
            ole.close()
            lines = data2.split('\n')
            for line in lines:
                if line.startswith('OriginalName'):
                    fullpath = line.split('=')[1]
                    pathsplit = fullpath.split('\\')
                    filename = str(pathsplit[-1][:-1])
            # now lets write the data out to a file and get a session on it
            if data:
                tempName = os.path.join('/tmp', filename)
                with open(tempName, 'w') as temp:
                    temp.write(data)
                __sessions__.new(tempName)
                return
            else:
                print_error("Unble to Switch Session")

        # Run Functions
        try:
            opts, argv = getopt.getopt(self.args[0:], 'hs', ['help', 'session'])
        except getopt.GetoptError as e:
            print(e)
            return

        for opt, value in opts:
            if opt in ('-h', '--help'):
                help()
                return
            if opt in ('-s','--session'):
                bupextract()
                return

        # Check for valid OLE
        if not OleFileIO_PL.isOleFile(__sessions__.current.file.path):
            print_error("Not a valid BUP File")
            return

        ole = OleFileIO_PL.OleFileIO(__sessions__.current.file.path)
        # We know that BUPS are xor'd with 6A which is dec 106 for the decoder
        details = xordata(ole.openstream('Details').read(), 106)
        # the rest of this is just formating
        lines = details.split('\n')
        rows = []

        for line in lines:
            try:
                k,v = line.split('=')
                rows.append([k,v[:-1]]) #Strip the \r from v
            except:
                pass

        print_info("BUP Details:")
        print(table(header=['Description', 'Value'], rows=rows))

        ole.close()