利用 MS-DOS 檔案時間 16 位元結構(時 5 位、分 6 位、秒 5 位)中的「分」欄位存放試用次數,隱蔽性佳,一般使用者難以察覺。
| 功能 | 說明 |
|---|---|
| 3Dh | 開啟檔案 (AL=0 唯讀) |
| 3Eh | 關閉檔案 |
| 57h/00h | 讀取檔案時間/日期 (CX=時間, DX=日期) |
| 57h/01h | 設定檔案時間/日期 |
int count() {
union REGS inregs, outregs;
struct SREGS segs;
unsigned handle, times;
inregs.h.ah = 0x3D; inregs.h.al = 0;
inregs.x.dx = (unsigned)"test.exe";
segread(&segs);
intdosx(&inregs, &outregs, &segs);
if (outregs.x.cflag) return 0;
handle = outregs.x.ax;
inregs.x.ax = 0x5700; inregs.x.bx = handle;
intdosx(&inregs, &outregs, &segs);
times = (outregs.x.cx & 0x07E0) >> 5; // 取出分欄位
if (times < 40) { // 試用上限
inregs.x.ax = 0x5701; inregs.x.bx = handle;
inregs.x.cx = outregs.x.cx + 0x20; // 分+1 (bit 5)
inregs.x.dx = outregs.x.dx;
intdosx(&inregs, &outregs, &segs);
inregs.h.ah = 0x3E; inregs.x.bx = handle;
intdosx(&inregs, &outregs, &segs);
return 2; // 允許試用
}
inregs.h.ah = 0x3E; inregs.x.bx = handle;
intdosx(&inregs, &outregs, &segs);
return 1; // 次數用盡
}
main() {
int flag = count();
if (flag==0) printf("試用版,請勿修改!");
if (flag==1) printf("試用次數已滿!");
if (flag==2) printf("歡迎試用!");
}
註:此為 16-bit DOS 時代技術,現代 Windows 檔案系統 (NTFS) 時間精度較高 (100ns),原理仍可借鑑但需調整 API (GetFileTime/SetFileTime)。