Task 011: .ACCDB File Format

Task 011: .ACCDB File Format

The .ACCDB file format is a proprietary binary format developed by Microsoft Corporation for Microsoft Access databases, introduced with Access 2007 and utilized in subsequent versions. It replaces the earlier .MDB format and is based on the Access Database Engine (ACE), an evolution of the Jet Database Engine. The format supports advanced features such as multivalued fields, attachments, calculated fields, and data macros, with a maximum file size of 2 gigabytes. The structure is paged, with a fixed page size of 4096 bytes. The file header begins with the byte sequence 0x00 0x01 0x00 0x00, followed by the ASCII string "Standard ACE DB". A compatibility version byte is located at offset 0x14, indicating the minimum Access version required (e.g., 0x02 for Access 2007). No official specification has been released by Microsoft, but partial details have been derived through analysis and reverse engineering, including support for encryption, custom database properties, and relational data storage in tables.

The properties of the .ACCDB file format intrinsic to its file system are as follows:

  • File size (in bytes)
  • Creation time
  • Last modification time
  • Last access time
  • File attributes (e.g., read-only, hidden, system, archive)
  • Owner user ID
  • Group ID
  • Permissions (mode, including read, write, and execute rights for user, group, and others)

Two direct download links for .ACCDB files are:

The following is an HTML document with embedded JavaScript that can be embedded in a Ghost blog post. It provides a drag-and-drop area for a .ACCDB file and dumps the file system properties to the screen upon drop.

ACCDB File Properties Dumper
Drag and drop .ACCDB file here
  1. The following is a Python class that can open a .ACCDB file, read and decode its file system properties (validating the file extension and basic signature for format confirmation), print them to the console, and support writing changes to modifiable properties such as modification time and permissions.
import os
import time
import stat

class AccdbFileHandler:
    def __init__(self, filepath):
        if not filepath.endswith('.accdb'):
            raise ValueError("File must be of .ACCDB format.")
        self.filepath = filepath
        with open(self.filepath, 'rb') as f:
            header = f.read(21)
            if header[:4] != b'\x00\x01\x00\x00' or header[4:20] != b'Standard ACE DB':
                raise ValueError("Invalid .ACCDB signature.")
        self.properties = os.stat(self.filepath)

    def print_properties(self):
        print(f"File Size: {self.properties.st_size} bytes")
        print(f"Creation Time: {time.ctime(self.properties.st_ctime)}")
        print(f"Last Modification Time: {time.ctime(self.properties.st_mtime)}")
        print(f"Last Access Time: {time.ctime(self.properties.st_atime)}")
        print(f"File Attributes/Mode: {oct(self.properties.st_mode)}")
        print(f"Owner User ID: {self.properties.st_uid}")
        print(f"Group ID: {self.properties.st_gid}")
        print(f"Permissions: {stat.filemode(self.properties.st_mode)}")

    def set_modification_time(self, new_mtime):
        os.utime(self.filepath, (self.properties.st_atime, new_mtime))
        self.properties = os.stat(self.filepath)  # Refresh properties

    def set_permissions(self, new_mode):
        os.chmod(self.filepath, new_mode)
        self.properties = os.stat(self.filepath)  # Refresh properties
  1. The following is a Java class that can open a .ACCDB file, read and decode its file system properties (validating the file extension and basic signature), print them to the console, and support writing changes to modifiable properties such as modification time and permissions.
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.Date;

public class AccdbFileHandler {
    private Path filepath;
    private BasicFileAttributes properties;

    public AccdbFileHandler(String filepathStr) throws IOException {
        this.filepath = Paths.get(filepathStr);
        if (!filepathStr.endsWith(".accdb")) {
            throw new IllegalArgumentException("File must be of .ACCDB format.");
        }
        try (InputStream is = Files.newInputStream(filepath)) {
            byte[] header = new byte[21];
            is.read(header);
            byte[] sig = {(byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00};
            byte[] type = "Standard ACE DB".getBytes("US-ASCII");
            for (int i = 0; i < 4; i++) {
                if (header[i] != sig[i]) throw new IllegalArgumentException("Invalid .ACCDB signature.");
            }
            for (int i = 0; i < 16; i++) {
                if (header[i+4] != type[i]) throw new IllegalArgumentException("Invalid .ACCDB type.");
            }
        }
        this.properties = Files.readAttributes(filepath, BasicFileAttributes.class);
    }

    public void printProperties() {
        System.out.println("File Size: " + properties.size() + " bytes");
        System.out.println("Creation Time: " + new Date(properties.creationTime().toMillis()));
        System.out.println("Last Modification Time: " + new Date(properties.lastModifiedTime().toMillis()));
        System.out.println("Last Access Time: " + new Date(properties.lastAccessTime().toMillis()));
        // Note: Attributes, owner, group, and permissions require additional views (e.g., PosixFileAttributes).
        PosixFileAttributes posix = null;
        try {
            posix = Files.readAttributes(filepath, PosixFileAttributes.class);
            System.out.println("Owner: " + posix.owner().getName());
            System.out.println("Group: " + posix.group().getName());
            System.out.println("Permissions: " + PosixFilePermissions.toString(posix.permissions()));
        } catch (IOException e) {
            System.out.println("Advanced attributes not available on this file system.");
        }
    }

    public void setModificationTime(long newMtime) throws IOException {
        Files.setLastModifiedTime(filepath, FileTime.fromMillis(newMtime));
        this.properties = Files.readAttributes(filepath, BasicFileAttributes.class);
    }

    public void setPermissions(String permissionsStr) throws IOException {
        PosixFileAttributeView view = Files.getFileAttributeView(filepath, PosixFileAttributeView.class);
        if (view != null) {
            view.setPermissions(PosixFilePermissions.fromString(permissionsStr));
            this.properties = Files.readAttributes(filepath, BasicFileAttributes.class);
        } else {
            throw new UnsupportedOperationException("Permissions not supported on this file system.");
        }
    }
}
  1. The following is a JavaScript class that can open a .ACCDB file (using Node.js for file system access, as browser JS has limitations), read and decode its file system properties (validating the signature), print them to the console, and support writing changes to modifiable properties.
const fs = require('fs');
const path = require('path');

class AccdbFileHandler {
    constructor(filepath) {
        if (!filepath.endsWith('.accdb')) {
            throw new Error('File must be of .ACCDB format.');
        }
        this.filepath = filepath;
        const header = fs.readFileSync(this.filepath, {encoding: null, flag: 'r'}).slice(0, 21);
        const sig = Buffer.from([0x00, 0x01, 0x00, 0x00]);
        const type = Buffer.from('Standard ACE DB');
        if (!header.slice(0, 4).equals(sig) || !header.slice(4, 20).equals(type)) {
            throw new Error('Invalid .ACCDB signature.');
        }
        this.properties = fs.statSync(this.filepath);
    }

    printProperties() {
        console.log(`File Size: ${this.properties.size} bytes`);
        console.log(`Creation Time: ${this.properties.birthtime}`);
        console.log(`Last Modification Time: ${this.properties.mtime}`);
        console.log(`Last Access Time: ${this.properties.atime}`);
        console.log(`File Mode: ${this.properties.mode.toString(8)}`);
        console.log(`Owner User ID: ${this.properties.uid}`);
        console.log(`Group ID: ${this.properties.gid}`);
        // Permissions can be derived from mode.
    }

    setModificationTime(newMtime) {
        fs.utimesSync(this.filepath, this.properties.atime, new Date(newMtime));
        this.properties = fs.statSync(this.filepath);
    }

    setPermissions(newMode) {
        fs.chmodSync(this.filepath, newMode);
        this.properties = fs.statSync(this.filepath);
    }
}
  1. The following is a C++ class (since standard C does not have classes, using C++ for object-oriented structure) that can open a .ACCDB file, read and decode its file system properties (validating the signature), print them to the console, and support writing changes to modifiable properties.
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <utime.h>
#include <cstring>
#include <ctime>

class AccdbFileHandler {
private:
    std::string filepath;
    struct stat properties;

public:
    AccdbFileHandler(const std::string& fp) : filepath(fp) {
        if (fp.substr(fp.find_last_of(".") + 1) != "accdb") {
            throw std::invalid_argument("File must be of .ACCDB format.");
        }
        std::ifstream file(fp, std::ios::binary);
        char header[21];
        file.read(header, 21);
        char sig[4] = {0x00, 0x01, 0x00, 0x00};
        char type[] = "Standard ACE DB";
        if (std::memcmp(header, sig, 4) != 0 || std::memcmp(header + 4, type, 16) != 0) {
            throw std::invalid_argument("Invalid .ACCDB signature.");
        }
        if (stat(fp.c_str(), &properties) != 0) {
            throw std::runtime_error("Failed to retrieve file properties.");
        }
    }

    void printProperties() {
        std::cout << "File Size: " << properties.st_size << " bytes" << std::endl;
        std::cout << "Creation Time: " << std::ctime(&properties.st_ctime);
        std::cout << "Last Modification Time: " << std::ctime(&properties.st_mtime);
        std::cout << "Last Access Time: " << std::ctime(&properties.st_atime);
        std::cout << "File Mode: " << std::oct << properties.st_mode << std::endl;
        std::cout << "Owner User ID: " << properties.st_uid << std::endl;
        std::cout << "Group ID: " << properties.st_gid << std::endl;
        // Permissions can be derived from st_mode.
    }

    void setModificationTime(time_t newMtime) {
        struct utimbuf ut;
        ut.actime = properties.st_atime;
        ut.modtime = newMtime;
        utime(filepath.c_str(), &ut);
        stat(filepath.c_str(), &properties);
    }

    void setPermissions(mode_t newMode) {
        chmod(filepath.c_str(), newMode);
        stat(filepath.c_str(), &properties);
    }
};