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

用 C 語言操作主開機記錄建立多重 PRI DOS 分區:原理、實作與風險控管

     編輯:C 語言基礎

動機:訓練環境的資料隔離需求

在 DOS 時期的電腦教室,學員誤刪系統檔或重要資料屢見不鮮。作者提出一套「多重 PRI DOS 分區 + 動態切換」方案:硬碟建立多個主分區,每次開機僅啟用一個,其餘隱藏,達到資料隔離與快速還原目的。核心在於直接操作主開機記錄 (MBR) 分區表。

MBR 分區表結構深度解析

MBR 位於磁柱 0、磁頭 0、扇區 1 (LBA 0),共 512 位元組:

  • 0x0000~0x01BD (446 bytes):開機程式碼
  • 0x01BE~0x01FD (64 bytes):分區表,4 筆記錄,每筆 16 bytes
  • 0x01FE~0x01FF (2 bytes):結束標誌 0x55 0xAA

單筆分區記錄結構 (位移/長度/含義):

位移長度欄位備註
01啟動旗標0x80=啟動, 0x00=非啟動
13起始 CHS柱面/磁頭/扇區
41分區類型0x01=FAT12, 0x04/0x06=FAT16, 0x05=Extended, 0x0B/0x0C=FAT32
53結束 CHS同上
84起始 LBA相對起始扇區號
124分區大小扇區數

建立多重 PRI DOS 分區的駭客技巧

  1. 用 FDISK 建立 1 個 PRI DOS + 1 個 Extended (含 1 邏輯分區)。
  2. 讀取 MBR,將第 2 筆記錄 (Extended) 的 類型 0x05 → 0x06 (FAT16 大分區),並將其 啟動旗標 0x00 → 0x80;同時將原 PRI DOS 的旗標 0x80 → 0x00。
  3. 寫回 MBR,以開機磁片啟動並 FORMAT C:,原 C: 變為 D:,新分區成為 C:。
  4. 重複上述步驟可建立第 3、4 個 PRI DOS 分區 (受限於 4 筆記錄上限)。

動態隱藏/還原分區:利用 MBR 保留區

MBR 保留區 0x00DB~0x01BD (228 bytes) 通常全 0。作者將 4 筆分區記錄備份於此區尾端 64 bytes。切換時:

  • 隱藏:僅保留目標分區記錄,其餘 3 筆清零 → BIOS/OS 僅看見 1 個分區。
  • 還原:從備份區寫回 4 筆記錄 → 全部重現。

核心原始碼 PDOS.CPP 解讀 (關鍵函數)

/* 結構定義 */
struct HSC { char hd, sc, cy; };           /* CHS 地址 */
struct PartitionTable {
    char Flag;        /* 啟動旗標 */
    HSC begin;        /* 起始 CHS */
    char Type;        /* 分區類型 */
    HSC end;          /* 結束 CHS */
    long lba_start;   /* 起始 LBA */
    long size;        /* 扇區數 */
};
struct note {                    /* MBR 完整映射 */
    char boot1[366];             /* 開機碼 + 保留區 */
    PartitionTable PT[1];        /* 未使用 */
    PartitionTable PT1[4];       /* 備份區 */
    PartitionTable PT2[4];       /* 作用中分區表 */
    char sig[2];                 /* 0x55 0xAA */
} dosboot;

/* 將 Extended 分區改為 PRI DOS 並設為啟動 */
void create_pri_dos()
{
    biosdisk(2, 0x80, 0, 0, 1, 1, &dosboot);  /* 讀 MBR */
    for (int i = 0; i < 4; i++) {
        if (dosboot.PT2[i].Type != 0 && dosboot.PT2[i].Type != 5)
            dosboot.PT2[i].Flag = 0x00;         /* 關閉其他啟動旗標 */
        if (dosboot.PT2[i].Type == 5) {         /* 找到 Extended */
            dosboot.PT2[i].Type = 6;            /* 改為 FAT16 大分區 */
            dosboot.PT2[i].Flag = 0x80;         /* 設為啟動 */
        }
    }
    biosdisk(3, 0x80, 0, 0, 1, 1, &dosboot);  /* 寫 MBR */
}

/* 備份 4 筆分區記錄到 PT1 */
void set_hidde_dos()
{
    biosdisk(2, 0x80, 0, 0, 1, 1, &dosboot);
    for (int i = 0; i < 4; i++)
        if (dosboot.PT2[i].Type != 0 && dosboot.PT2[i].Type != 5)
            dosboot.PT1[i] = dosboot.PT2[i];
    biosdisk(3, 0x80, 0, 0, 1, 1, &dosboot);
}

/* 從 PT1 還原到 PT2 */
void recall_dos()
{
    biosdisk(2, 0x80, 0, 0, 1, 1, &dosboot);
    for (int i = 0; i < 4; i++)
        if (dosboot.PT1[i].Type != 0) {
            dosboot.PT2[i] = dosboot.PT1[i];
            dosboot.PT1[i] = dosboot.PT[0];    /* 清空備份 */
        }
    biosdisk(3, 0x80, 0, 0, 1, 1, &dosboot);
}

/* 僅保留第 n 筆分區 (n=0..3) */
void change_dos(char n)
{
    int idx = n - '1';  /* '1'→0, '2'→1... */
    biosdisk(2, 0x80, 0, 0, 1, 1, &dosboot);
    if (dosboot.PT1[idx].Type != 0) {
        for (int i = 0; i < 4; i++)
            if (dosboot.PT1[i].Type != 0)
                dosboot.PT2[i] = dosboot.PT[0];  /* 全清零 */
        dosboot.PT2[idx] = dosboot.PT1[idx];     /* 還原目標 */
        dosboot.PT2[idx].Flag = 0x80;            /* 設為啟動 */
    }
    biosdisk(3, 0x80, 0, 0, 1, 1, &dosboot);
}

實戰範例:1.2 GB 硬碟建立 300/400/500 MB 三分區

  1. FDISK 建 300 MB PRI DOS + 400 MB Extended → 啟動 PRI DOS → FORMAT C: → PDOS S (Extended→PRI) → 重開機 FORMAT C: (原 C: 變 D:)。
  2. FDISK 在剩餘空間建 500 MB Extended → PDOS S → 重開機 FORMAT C:。
  3. 最終對應:C: 500 MB、D: 300 MB、E: 400 MB。

關鍵部署細節與風險警示

  • PDOS.EXE 必須複製到每個 PRI DOS 分區,否則切換後無法執行切換程式。
  • 輸入參數務必精確:PDOS C/S/R/1/2/3/4,錯誤操作直接破壞 MBR 導致全盤資料不可存取。
  • 僅適用 MBR 傳統分區,GPT/UEFI 環境完全不適用。
  • 現代替代方案:虛擬機快照、VHDX 差異磁碟、BitLocker + 還原精靈、雲端備份,安全性與彈性遠勝底層分區切換。

此技術展示了對 x86 開機流程與磁碟結構的深度掌控,雖已成歷史,但「直接操作區塊裝置中繼資料」的思維在韌體開發、資料救援、惡意軟體分析等領域依然核心。

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