軟體銷售模式演進催生「先試用、後註冊」的電子授權需求。本文提出一套跨越 DOS、Windows 3.x、Windows 95 的通用電子註冊方案:採集 ROM 區 (F000H:FFF5H-FFFFH) 機器唯一資訊(出廠日期、主機標識、主板序號等)作為加密種子,經位運算演算法生成註冊碼,嵌入應用程式多處關鍵邏輯,實現功能限制與防破解。
傳統透過埠 1F6H/1F7H 讀取硬碟資訊,在 Win95 保護模式下被禁止,無法跨平台。
F000:FFF0H 前 5 字節為熱啟動入口 (Ctrl+Alt+Del 處理),三平台處理不同,內容不一致,不可作為種子。
利用語言提供的位運算(XOR、SHIFT、ADD/SUB)對種子進行多輪變換,演算法可自行設計,長度任意。將驗證邏輯分散在程式多處關鍵路徑,增加逆向難度。即使多程式共用同種子,演算法不同則註冊碼不同;知曉種子無演算法亦無法破解。
READKEY.EXE 依相同註冊演算法生成註冊碼READKEY.EXE 三種模式:
// 從 ROM 讀取種子
unsigned int far *pt = (unsigned int far *)0xf000fff6L;
// 形成解密密鑰
sum = 0x2020;
for (sumj=0; sumj<4; sumj++) {
for (sumi=0; sumi<5; sumi++)
sum -= (*(pt+sumi) - 0x2020);
sum ^= 0x0404;
sprintf(Buff+4*sumj, "%04x", sum);
}
// 產出 16 字元註冊碼
ImeCmpkey
void ImeCmpkey(void) {
// Win95 保護模式下需用 Selector 映射實體地址
__asm mov Sel1, ds;
Sel2 = AllocSelector(Sel1);
SetSelectorBase(Sel2, 0xF0000); // F000:0000
SetSelectorLimit(Sel2, 0xFFFF);
pt = (unsigned int far*)(((DWORD)Sel2<<16) | 0xFFF6); // F000:FFF6
// 同樣演算法生成註冊碼並比對
if (lstrcmpi(calcKey, storedKey)==0) UseFlag=FALSE; // 已註冊
}
IsDebuggerPresent、時間檢查、自我校驗和雜湊執行速度極快 (直接記憶體讀取),對程式效能幾無影響,碼長增加微乎其微。
ROM 種子 + 自訂位運算演算法 + 分散式驗證 + 開發者/用戶雙向密鑰流程,構建了一套實用、跨平台、低成本的電子註冊體系。雖非軍用級加密,但足以阻擋絕大多數非專業破解,保護開發者勞動成果並降低銷售環節成本。