Restoring a McAfee quarantined file

Learn how to decompress, decrypt and restore the original content of a McAfee .BUP quarantine file.

Introduction

McAfee VirusScan Enterprise quarantined files are stored with the .BUP file extension.
If you need to recover the content of the original file for digital forensics or reverse engineering purposes, you can use the Quarantine Manager.

But In some situations you might not be able to restore the .BUP file with the Quarantine Manager.

Quarantine file Structure

McAfee VirusScan Enterprise .BUP files are simple Zip archives containing at least two files.

Details - This file contains all the details about the quarantine.
File_0 - The first original file inside the quarantine file.

Obviously, if this files were only compressed McAfee VirusScan Enterprise would still acknowledge them as a threat to the system.
Therefore to make them harmless all the files contained in a .BUP file are encrypted using XOR with a one byte key 0x6A.

Extraction script

To make life easier we developed a small Python script which automate the process of extracting files and information from a .BUP file.

#!/usr/bin/env python
import argparse
from zipfile import ZipFile

def xor(data):
    result = ""
    for c in data:
        result += chr(ord(c) ^ 0x6A)
    return result

def save_file(name, data):
    try:
        with open(name, "wb") as f:
            f.write(data)
    except:
        print("Error : Cannot restore", name)

def decrypt_file(bup, name):
    try:
        data = bup.read(name)
        data = xor(data)
        return data
    except:
        print("Error : Cannot decrypt", name)

def restore_all(bup, files):
    for name in files:
        print("Restoring", name)
        data = decrypt_file(bup, name)
        save_file(name, data)

def main():
    parser = argparse.ArgumentParser(description="Extract quarantined files from a McAfee VirusScan Enterprise .BUP file.")
    parser.add_argument("file", help="The .BUP file that you wish to restore.")
    parser.add_argument("-d", "--details", dest="print_details", action="store_true", default=False, help="Print the contents of the Details file.")
    args = parser.parse_args()

    try:
        with ZipFile(args.file, "r") as bup:
            filenames = bup.namelist()

            if args.print_details:
                details = decrypt_file(bup, "Details")
                print(details)
            else:
                restore_all(bup, filenames)
    except:
        print("Error : Cannot restore", args.file)

if __name__ == "__main__":
    main()