首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Access MDB 密碼破解原理解析:從 Access 97 到 2000/2002 的演進與對策

     編輯:關於C++

Access MDB 檔案密碼保護機制在 Access 97 到 2000/2002 版本間發生重大變化。本文揭示其加密演算法細節,並提供 C++Builder 參考實作,旨在協助開發者理解資料庫安全弱點以加強防護。

Access 97:固定金鑰 XOR

  • 偏移量:0x42 起始,連續 13 位元組
  • 固定金鑰:{0x86,0xFB,0xEC,0x37,0x5D,0x44,0x9C,0xFA,0xC6,0x5E,0x28,0xE6,0x13}
  • 解密:password[i] = file[0x42+i] ^ key[i]

Access 2000/2002:動態金鑰 + 交錯儲存

經 UltraEdit 二進位比對發現:

  1. 密碼位元組隔一個位元組儲存一個(交錯模式)
  2. 金鑰不再固定,含動態加密標誌位(位移 0x62)
  3. 解密需兩階段 XOR

解密演算法步驟

// 參考空密碼檔案基準值(需隨機器/時間動態取得)
char PassSource2k[13] = {0xA1,0xEC,0x7A,0x9C,0xE1,0x28,0x34,0x8A,0x73,0x7B,0xD2,0xDF,0x50};
// 對應加密標誌位:0x13

// 解密流程
BYTE encFlag = file[0x62] ^ emptyFile[0x62];  // 取得動態加密標誌
for (int i = 0; i < 13; ++i) {
    BYTE encByte = file[0x42 + i*2];          // 交錯讀取
    BYTE baseByte = emptyFile[0x42 + i*2];
    BYTE half = encByte ^ baseByte;           // 第一階段
    
    if (i % 2 == 0)                           // 隔一個位元組
        password[i] = half ^ encFlag;         // 第二階段:與標誌位 XOR
    else
        password[i] = half;                   // 奇數索引僅第一階段
    
    if (password[i] < 0x20 || password[i] > 0x7E) break;  // 遇非可列印字元結束
}

完整 C++Builder 實作

void __fastcall TMainForm::GetMdbPass() {
    char PassStrTemp[26], Ver, EncrypFlag;
    int FileHandle = FileOpen(MdbFileName, fmOpenRead);
    if (FileHandle < 0) { ShowMessage("檔案開啟錯誤!"); return; }

    // 讀取版本標誌 (0x14: 0=Access97, 1=Access2000/2002)
    FileSeek(FileHandle, 0x14, 0);
    FileRead(FileHandle, &Ver, 1);

    // 讀取加密標誌 (0x62)
    FileSeek(FileHandle, 0x62, 0);
    FileRead(FileHandle, &EncrypFlag, 1);

    // 讀取加密密碼區塊 (0x42, 26 bytes)
    FileSeek(FileHandle, 0x42, 0);
    FileRead(FileHandle, &PassStrTemp, 26);
    FileClose(FileHandle);

    AnsiString MdbPassword, MdbVersion;
    if (Ver < 1) {  // Access 97
        MdbVersion = "Access 97";
        if ((PassStrTemp[0] ^ PassSource97[0]) == 0)
            MdbPassword = "密碼為空!";
        else {
            for (int i = 0; i < 13; ++i)
                MdbPassword += char(PassStrTemp[i] ^ PassSource97[i]);
        }
    } else {  // Access 2000/2002
        MdbVersion = "Access 2000 or 2002";
        for (int i = 0; i < 13; ++i) {
            char t1;
            if (i % 2 == 0)
                t1 = char(0x13 ^ EncrypFlag ^ PassStrTemp[i*2] ^ PassSource2k[i]);
            else
                t1 = char(PassStrTemp[i*2] ^ PassSource2k[i]);
            MdbPassword += t1;
        }
    }

    // 簡易驗證:首字元是否可列印
    if (MdbPassword[1] < 0x20 || MdbPassword[1] > 0x7E)
        MdbPassword = "密碼為空!";

    EditMdbPassword->Text = MdbPassword;
    EditMdbVersion->Text = MdbVersion;
}

安全性評估與防護建議

弱點影響緩解措施
靜態/半靜態金鑰離線破解極易改用 Access 2007+ ACCDB 格式(AES-256 加密)
密碼長度限制 13 字元暴力破解空間小啟用資料庫層級加密而非僅用戶級密碼
無鹽值/雜湊彩虹表攻擊有效應用層自行雜湊存儲,不依賴 Jet 引擎密碼
檔案層級權控缺失複製檔案即可離線攻擊部署於受管伺服器,配合 NTFS/EFS 加密

結論:MDB 密碼機制本質上是混淆而非加密。生產環境務必遷移至 ACCDB (ACE 引擎) 或 SQL Server Express / SQLite (SQLCipher) 等現代儲存方案,並在應用層實施強雜湊與存取控制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved