|  | 
更新:制作显隐藏分区功能的软盘镜像文件工具,真正启动隐藏分区里的操作系统
| 感谢各位朋友的关注,为方便感兴趣的朋友改进,源程序开放。先公开引导区模块(HFBOOT.ASM)的源程序。 在写这个程序之前,我看到了很多“一键恢复”的介绍,这些工具里面以IBM技术为基础的为多。网上搜索到关于IBM“F11”键恢复的文章很多,可是多数是讲如何修复IBM的,觉得程序写在MBR里面是不妥的,很容易被破坏。另外IBM虽然没有追究大家的盗版使用责任,可是这也不是长久的。我于是决定写一个与之功能相似的程序,让大家测试和使用。我在写程序时思考了IBM“F11”键恢复的原理,可是我并没有反汇编和阅读IBM的代码,因此完全是自己写的,没有那些多麻烦。但是正因为只是自己一个人写的,所以不一定象IBM一样有过充分的测试,尽管我在程序中没有任何写硬盘的代码(可参看源代码),但使用此程序的风险还是存在的。希望朋友们在充分测试(虚拟机、空闲硬盘……)后再正式使用它!
 还是那句老话,本人保留对原始程序的所有权。你可以自由阅读和修改你认为可以改进的地方,但是请在重新发布时保留原作者的信息,并且我希望你能将源文件公开并告诉我(turboy@163.com),保持这个工具的一贯作风。
 这里是本人网站上语法加亮的源程序:http://yisir.softhome.cn/yiarticle/act.php?obj=article&id=136
 下面是引导区模块(HFBOOT.ASM)的源程序:
 ; ==========================================================================; 这是一个用来引导我的系统备份/恢复光盘的启动软盘的程序,将会放在软盘的第一
 ; 个扇区内。此程序引导系统时,出现一个提示,用户可选择按任意键启动工具软盘,
 ; 也可以在等待8秒后引导硬盘上的操作系统。在选择由工具软盘启动DOS后,在MBR中
 ; 隐藏的FAT32主分区(0B/0C)将会分配盘符变得可见,这就可以用常规工具来做备
 ; 份了——备份在隐藏分区里,看谁能删得掉!
 ; 最后版本:2005/9/5
 ; ==========================================================================
 ; 编程记录:
 ; 6月29日的版本只处理了传统INT13的2号功能,所以在虚拟机中的小硬盘(1B-FAT32)
 ; 中调试正常,一到了用LBA方式读取的分区(1C-FAT32LBA,1E-FAT16LBA)就完了。可是
 ; 现在的硬盘已经没有8GB以下的了,读取也几乎全是用LBA方式了。
 ;
 ; 7月23日:
 ;     加入对扩展INT3读取(42号)功能的接管,实现对隐藏LBA分区的读取,由于现
 ; 在硬盘分区几乎没有用FAT16的了,所以只处理了FAT32的。
 ;     由于新代码的加入,我原来的提示信息也不得已剪了一部分。
 ;
 ; 8月22日:
 ;     加入一个可识别分区标志码列表(FlagTable),逐一判断处理。
 ; 在FlagTable DW xxyy中,每一个字中的xx代表原始分区标志码,yy代表隐藏时的分区标志码
 ; 如0414h代表原始分区为04h(FAT12),隐藏时的分区标志码为14h
 ; 现在,可以无限扩充了。
 ;
 ; 8月28日:
 ;     试验加入从隐藏分区启动的功能。
 ; 1、在启动后利用自己的INT13将原分区激活标志改为00,将能改为正常分区的原隐
 ;藏分区的激活标志改为80。
 ; 2、在安装前判断按键,用DX寄存器作为标志,无按键DX=0XFFFF,按F7时DX=1,
 ; INT13中CH=1,按其他键时DX=0,INT13中CH=0。
 ; 3、在INT13中,使用CH作为是否激活隐藏分区的判断标志,为1时从隐藏分区启动。
 ; 3、由于BOCHS虚拟机使用了F11和F12两个键,故设定按F7键由隐藏分区启动。
 ;
 ; 8月31日:
 ;     crshen发现了几个BUG,现在一一解决。从隐藏分区启动的功能。
 ; 1、读不出F11是因为INT10H的0号功能不支持扩展键盘,现在改为10H号功能。可是
 ; 在QEMU中10号功能也不能读F11,而VPC却可以,可能是两者的BIOS不同或QEMU拦截
 ; 了F11/F12吧。
 ; 2、在安装前判断按键,如果按ESC键,则直接进入硬盘启动。
 ; 3、有一个判断跳转有误,致使INT13H的42H功能处理无效,我大意了,在加入处理
 ; 42H功能代码时忘了改前面的代码。
 ; 4、不能从8G以后的隐藏分区启动是因为在我的INT13过程中有一个严重的错误,这
 ; 个错误是由于我参考的资料有误而引入的。 在INT13H扩展功能中是用DS:SI来指向
 ; DAP的, 而不是那篇资料中说的DS:DI。这可真是……
 ;  在MS-FDISK、FREE-FDISK、AEFDISK、PQMAGIC、Acronis Disk Editor等大多数
 ; 程序中隐藏分区都会以正常分区显示,但GDISK却可以看出此分区为隐藏分区,
 ; GDISK一定有超越BIOS中断的独特存取硬盘方法。
 ; 9月1日:
 ;  目前9-2 0:47我已经将可能想到的BUG全部排除了, 而程序的长度也接近512字节的
 ; 极限了。
 ; 1、又发现原来的程序中有一处死码,是在调用原INT13中断后,AH已被作为返回值
 ; 了,却还在用AH判断扩展INT13,所以后面处理扩展INT13功能的代码就不会运行了。
 ; 修改成将AX压栈保存,但代码就更乱了,于是重写了前面的代码。
 ; 2、跟踪、思考了两天,才发现不能在机房的P4上启动隐藏分区上的OS的原因竟是原
 ; 来玩的一个技巧。真是聪明反被聪明误啊!
 ; 3、改变了开始时判断方式,DX中,DH=0安装INT13,DH=FFH不安装;DL=0载入软盘
 ; 引导记录启动,DL=80H载入硬盘MBR启动
 ; 4、新加入一个功能ESC键:可以不加载本程序,正常从硬盘盘启动,以用于一般情
 ; 况。
 ; 5、新加入一个功能F5键:可以不加载本程序,正常从软盘盘启动,以用于一般情况。
 ; ==========================================================================
 ;GoodFlag1 equ 0bh
 ;HideFlag1 equ 1bh
 ;GoodFlag2 equ 0ch
 ;HideFlag2 equ 1ch
 ;GoodFlag3 equ 0eh
 ;HideFlag3 equ 1eh
 ORIGIN EQU 7C00H; Origin of bootstrap LOADER
 BIO_MEMEQU 0413H; BIOS Memory size =640(KB)
 BIO_CLKEQU 046CH; BIOS Clock (1/18.2 seconds)
 DSK_PARMSEQU 1EH*4;POINTER TO DRIVE PARAMETERS
 KEY_BOOTHIDDENEQU 41H;Scancode: F7=41H, F11=85H, F12=86H
 KEY_BOOTFLOPPYEQU 3FH;Scancode: F5=3FH
 KEY_ESCAPEEQU 01H;Scancode: ESC=01H
 BOOTHIDDENFLAGEQU 80h
 ORG0000h
 START:
 ; WARNING -- Don change this to a short jmp
 jmp short main; Jump to start of code
 nop
 ; ==========================================================================
 ; Start of BPB area of the boot record
 OemName         DB "MSDOS"
 OsVersion DB "5.0"; DOS version number
 BPB:
 BytesPerSector DW 512; Size of a physical sector
 SecsPerClust DB 1; Sectors per allocation unit
 ReservedSecs DW 1; Number of reserved sectors
 NumFatsDB 2; Number of fats
 NumDirEntries DW 00E0h; Number of direc entries
 TotalSectors DW 0B40H; Number of sectors - number of hidden
 ; sectors (0 when 32 bit sector number)
 MediaByte DB 0F0H; MediaByte byte
 NumFatSecs DW 9; Number of fat sectors
 SecPerTrack DW 18; Sectors per track
 NumHeads DW 2; Number of drive heads
 HiddenSecs DD 0; Number of hidden sectors
 BigTotalSecs DD 0; 32 bit version of number of sectors
 BootDrv DB 0h
 CurrentHead DB 0h; Current Head
 ExtBootSig DB 41
 SerialNum DD 20050628h
 VolumeLabel DB "YISIR_LOADER"
 FatId DB "FAT12"
 ; =========================================================================
 ; First thing is to reset the stack to a better and more known
 ; place. The ROM may change, but wed like to get the stack
 ; in the correct place.
 main:
 cli;Stop interrupts till stack ok
 xor AX,AX
 mov ds,ax
 mov es,ax
 mov SS,AX;Work in stack just below this routine
 mov ax,ORIGIN
 mov sp,ax
 sti
 PUSH AX
 ;Show message
 mov ax,1301h
 mov bx,000ah
 mov cx,MyMsgLen
 mov dx,1500h
 mov bp,MyMsg+ORIGIN
 int 10h
 ;Hide the cursor
 mov ah,1
 mov cx,2000h
 int 10h
 ;Wait 10 seconds
 mov si, BIO_CLK
 mov edx, dword [si]
 mov ecx, edx
 add edx, 159;18.2*10 seconds
 ReadKB:
 ;Change 5 bytes with install option
 ;Case Option:/f   Boot from floppy disk directly, do not waiting 8 seconds
 ;31H D2Hxor dx,dx
 ;E9H xxH 00Hjmp BiosMemory
 ;
 ;Case Option:/b   Boot from HIDDEN parition derectly (activate it and load it)
 ;31H D2Hxor dx,dx
 ;E9H xxH 00Hjmp Key_F7
 ;
 ;Case Default:       Show message and wait 8 second
 mov ah, 11h;Get keyboard status
 int 16h
 jz NoKeyPress
 mov ah,10h;Read a key (In old code, AH=0, can not read F11/F12...)
 int 16h
 xor dx,dx
 cmp ah, KEY_ESCAPE
 jz DX_HD;Press ESC to BOOT from Harddisk
 cmp ah, KEY_BOOTFLOPPY
 jnz RKB_1
 mov dh, 0ffh;dh=0 Install INT13, else do not Install. Now DX=FF00H
 jmp BiosMemory
 RKB_1:
 cmp ah, KEY_BOOTHIDDEN
 jnz BiosMemory
 Key_F7:
 ;If press Hot key, Boot From Hidden Partition. Now DX=0001H
 ;modify CH=80h in Int13 procedure
 mov byte[ORIGIN+2+BootHiddenCode], BOOTHIDDENFLAG
 jmp DX_HD
 NoKeyPress:
 cmp ecx, dword [si]
 jae L_0
 test cl,1
 jz  L_0
 mov ax,0e3eh; write ">" to show progressing
 mov bx,0004h
 int 10h
 L_0:
 mov ecx, dword [si]
 cmp edx,ecx
 jae ReadKB
 mov dh,0ffh;Do not install INT13. Now DX=FF00
 DX_HD:
 mov dl,080h;Boot from HD.
 ;DH=0 Install INT13, DH=FFH do not Install
 ;DL=0 Boot Floppy, DL=80H Boot HD
 ;Now:
 ;  ESC DX=FF80, F5 DX=FF00H, F7 DX=0080H, ANYKEY DX=0000H, TIMEOUT DX=FF80H
 BiosMemory:
 ;Show the cursor
 mov ah,1
 mov cx,0d0eh
 int 10h
 ;BIOS MEMORY - 2KB
 mov bx,BIO_MEM;bx=280H (KB)
 mov ax,word [bx]
 dec ax
 cmp dh,0
 jnz L_1
 mov word [bx],ax;If DH=FF, Do not install
 L_1:
 ;Move to High Memory. ex. 9fc0:0000
 shl ax,6;ax=9fc0h SEG of top memory
 mov es,ax;es=9fc0h
 pop si;si=7c00h
 push es;ready to RETF
 xor di,di;di=0
 cld
 mov cx,100h
 repnz movsw;move code to 9fc0:0000
 cmp dh,0
 jnz L_2;If DH=0ffh, Do not install
 ;modify Int13
 mov si,4ch;Int13 13h*4
 mov di,OLDINT13
 ;Save Old
 mov eax,[si]
 mov [es:di],eax
 ;cmp dh,0
 ;jnz L_2;If DH=0ffh, Do not install
 push es
 pop ax
 shl eax,16
 mov ax, MyInt13
 mov [si],eax
 L_2:;Jump to high address, 9fc0:00xx
 push ds
 pop es
 mov bx,word Entre2
 push bx;push 9fc0:Entre2
 retf;跳到高端执行
 Entre2:
 cmp dl,0;If DX <> 0, Load HD-MBR
 jnz L_3
 ReadFD:;Read old boot sector from Floppy H1 T79 S18
 mov cx,4f12h
 mov dx,0100h
 jmp RunInt13
 L_3:;Read from Harddisk H0 T0 S1 MBR
 mov cx,1
 mov dx,80h
 RunInt13:
 mov ax,0201h
 mov bx,ORIGIN
 push ds
 push bx
 int 13h
 retf
 ; 2005-9-1
 ; 这里是原来用的花哨技巧代码,就是它们导致使用F7启动不了隐藏分区。因为这里读到的是原始的MBR
 ;        pushf        ;int 13h
 ;        push ds
 ;        push bx
 ; ------------------------------------------
 ;Jump to Old INT 13H
 JmpFarInt13:
 DB 0eah ;JMP far OLDINT13
 OLDINT13 DW 0,0
 ;End of Install-code
 ;Partition Flag Table  normal and hidden
 FlagTable:
 dw 0111h, 0414h, 0616h, 0717h, 0b1bh, 0c1ch, 0e1eh
 FlagTableEnd:
 ;My INT13h code
 MyInt13:
 cmp ah,2        ;Is Read?
 jz Func2
 cmp ah,42h      ;Is ExtRead?
 jz Func42
 JmpOldInt13:
 jmp JmpFarInt13
 Func2:
 CMP DX,0080H;Is Harddisk and Head 0?
 jnz JmpOldInt13
 cmp cx,0001H;Is Track 0 Sector 1?
 jnz JmpOldInt13
 pushf;Simulate INT operator
 push cs
 CALL JmpFarInt13;Call old INT13
 jc exit;Flase then Exit
 push bx
 push es
 jmp EditFlag
 Func42:
 cmp dl,80h;Is Harddisk
 jnz JmpOldInt13
 push eax
 xor eax,eax
 cmp dword [si+8],eax;Is Sector 0, Low 32bit
 jnz ExitFunc42
 cmp dword [si+12],eax;Is Sector 0, Hight 32bit
 jnz ExitFunc42
 pop eax
 pushf;Simulate INT operator
 push cs
 CALL JmpFarInt13;Call old INT13
 jc exit;If flase then Exit
 push bx
 push es
 mov bx, [si+4]; Fix BX,ES like Int13h Func02
 mov es, [si+6]
 jmp EditFlag
 ExitFunc42:
 pop eax
 jmp JmpOldInt13
 EditFlag:
 push ax
 push cx
 push si; DS:SI -> DAP
 push ds
 push cs
 pop ds
 add bx, 01c2h; ES:BX -> Partition Flag
 BootHiddenCode:
 mov cx, 4; CL=4, CH will can be change by Makeimg.c with 1 to Modify the ActiveFlag
 cmp1:
 mov si, FlagTable
 cmp ch, BOOTHIDDENFLAG;If CH=BOOTHIDDENFLAG, Boot from hidden Partition
 jnz nextFlag
 mov byte [es:bx-4], 0;Clear Active Flag for boot from hidden partition
 nextFlag:
 cld
 lodsw
 cmp si, FlagTableEnd
 jae nextPart
 cmp byte [es:bx], al
 jnz nextFlag
 mov byte [es:bx], ah
 cmp ch,BOOTHIDDENFLAG;If CH=BOOTHIDDENFLAG, Boot from hidden Partition
 jnz JmpNextFlag
 mov byte [es:bx-4], 80h
 xor ch, ch;Set CH=0h, Don';t modify the next.
 JmpNextFlag:
 jmp nextFlag
 nextPart:
 add bx,10h
 dec cl
 ja cmp1
 pop ds
 pop si
 pop cx
 pop ax
 pop es
 pop bx
 exit:
 iret
 ; End of INT13H code
 MyMsg    db "PartUnhide Loader, yisir.9126.com, 2005-9-5",13,10
 ;         db "Press any key to load RESTORE FLOPPY DISK...",13,10
 MyMsgLen equ $-MyMsg
 times 510 -($-$$) db 0
 BOOTFLAG db 55h,0aah
 | 
 |