反汇编mbr

MBR 相关的开机过程。以及我们经常用的U盘自启动 
程序到底值怎么玩的。
window开机流程
流程
加电-->BIOS--> MBR--> DPT--> pbr--> Bootmgr--> bcd--> Winload.exe---
—-> 内核加载–> 整个windows7系统
细节
在CPU上电之后,若由硬盘启动,则BIOS将硬盘的主引导记录(位于0柱面、0磁道、1扇区)读入7C00处 
然后将控制权交给主引导代码。主引导代码的任务包括: 
扫描分区表,找到一个激活(可引导)分区; 
找到激活分区的起始扇区; 
将激活分区的引导扇区装载到内存7C00处; 
将控制权交给引导扇区代码;
如果主引导代码无法完成上述任务,它将显示以下错误信息之一: 
No active partition. 
Invalid partition table. 
Error loading operating system. 
Missing operating system.
机器加电或按reset键后都要进行系统复位,复位后CS=FFFFH,IP=0000H,那么自然就从FFFF:0000H 
处开始执行指令,这个地方只有一条JMP指令跳转到系统自检程序处,系统自检完成后把软盘的第一 
个扇区(如果由软盘启动)或者硬盘的第一个扇区,即MBR扇区(如果由硬盘启动)读入到0:7C00H处 
然后把控制权交出,从0:7C00H处继续执行。
下面就是硬盘的MBR代码分析: 
其中的引导扇区是指硬盘相应分区的第一个扇区,是和操作系统有关的。操作系统的引导是由它来完成的,而MBR并不负责,MBR和操作系统无关。引导扇区的任务是把控制权转交给操作系统的引导程序。
程序流程: 
1 将程序代码由0:7C00H移动到0:0600H(注,BIOS把MBR放在0:7C00H处) 
2 搜索可引导分区,即80H标志 
成功:goto 3 
失败:跳入ROM BASIC 
无效分区表:goto 5 
3 读引导扇区 
失败:goto 5 
成功:goto 4 
4 验证引导扇区最后是否为55AAH 
失败:goto 5 
成功:goto 6 
5 打印错误进入无穷循环 
6 跳到0:7C00H进行下一步启动工作
获取
获取mbr
window可以直接用hex打开,然后直接拷贝成文件linux一条dd 命令搞定,参数不明白就 --help look dd if =/dev/sda of =~/Desktop/mbr.bin bs= 512 count= 1

安装
安装nasm sudo apt-get install nasms

反汇编mbr
//把mbr .bin 反汇编到mbr .asm ndisasm mbr .bin > mbr .asm

分析
二进制mbr
od -x mbr.bin 0000000 c033 d08e 00 bc 8e7 c 8 ec0 bed8 7 c00 00 bf 0000020 b906 0200 f3fc 50 a4 1 c68 cb06 b9fb 0004 0000040 bebd 8007 007 e 7 c00 0f 0b 0e85 8301 10 c5 0000060 f1e2 18 cd 5688 5500 46 c6 0511 46 c6 0010 0000100 41 b4 aabb cd55 5 d13 0f 72 fb81 aa55 0975 0000120 c1f7 0001 0374 46f e 6610 8060 107 e 7400 0000140 6626 0068 0000 6600 76f f 6808 0000 0068 0000160 687 c 0001 1068 b400 8 a42 0056 f48b 13 cd 0000200 839f 10 c4 eb9e b814 0201 00 bb 8 a7c 0056 0000220 768 a 8 a01 024 e 6e8 a cd03 6613 7361 fe1c 0000240 114 e 0 c75 7e80 8000 840f 008 a 80 b2 84 eb 0000260 3255 8 ae4 0056 13 cd eb5d 819 e fe3e 557 d 0000300 75 aa ff6e 0076 8 de8 7500 fa17 d1b0 64e6 0000320 83e8 b000 e6df e860 007 c ffb0 64e6 75e8 0000340 fb00 00 b8 cdbb 661 a c023 3 b75 8166 54f b 0000360 5043 7541 8132 02f 9 7201 662 c 0768 00 bb 0000400 6600 0068 0002 6600 0868 0000 6600 6653 0000420 6653 6655 0068 0000 6600 0068 007 c 6600 0000440 6861 0000 cd07 5 a1a f632 00 ea 007 c cd00 0000460 a018 07 b7 08 eb b6a0 eb07 a003 07 b5 e432 0000500 0005 8 b07 acf0 003 c 0974 07 bb b400 cd0e 0000520 eb10 f4f2 fdeb c92b 64e4 00 eb 0224 f8e0 0000540 0224 49 c3 766 e 6 c61 6469 7020 7261 6974 0000560 6974 6e6 f 7420 6261 656 c 4500 7272 726f 0000600 6 c20 616f 6964 676 e 6f 20 6570 6172 6974 0000620 676 e 7320 7379 6574 006 d 694 d 7373 6e69 0000640 2067 706f 7265 7461 6e69 2067 7973 7473 0000660 6 d65 0000 6300 9 a7b d681 4 aef 0101 2080 0000700 0021 fe07 ffff 0800 0000 b000 0760 fe00 0000720 ffff fe07 ffff b800 0760 3800 001f 0000 0000740 0000 0000 0000 0000 0000 0000 0000 0000 0000760 0000 0000 0000 0000 0000 0000 0000 aa55

反汇编mbr
00000000 33 C0 xor ax,ax //设置ax寄存器的值为0 00000002 8 ED0 mov ss,ax 00000004 BC007C mov sp, 0x7c00 // 设置栈值 * copying the mbr from 0x7c00 to 0x600 * 200 转为十进制是 512 */ 00000007 8 EC0 mov es,ax 00000009 8 ED8 mov ds,ax 0000000 B BE007C mov si, 0x7c00 0000000 E BF0006 mov di, 0x600 00000011 B90002 mov cx, 0x200 00000014 FC cld // 设置寄存器为自增 00000015 F3A4 rep movsb //拷贝 00000017 50 push ax //入栈 16bit 00000018 681 C06 push word 0x61c //入栈 0000001 B CB retf //0x61c 出栈,并且调到0x61c即下一行代码处 0000001 C FB sti /* 下面开始循环扫描分区表(Partition Table),寻找活动分区 0x80 总共4次 */ 0000001 D B90400 mov cx, 0x4 //总共四个分区表项 00000020 BDBE07 mov bp, 0x7be //分区表开始位置 偏移量是 1be + 600 = 7be 00000023 807E0000 cmp byte [bp+ 0x0 ], 0x0 // 第一个字节和 0比较 /** jl 小于(有符号),0x80 有符号是-8 成功表示找到活动分区,失败则是普通分区* 找到活动分区,跳转到0x34 */ 00000027 7 C0B jl 0x34 //因为要么是 0x80 要么是0x0 别的情况表示分区表损坏输出错误信息 00000029 0 F850E01 jnz word 0x13b 0000002 D 83 C510 add bp, byte + 0x10 //每个分区16字节,也就是0x10 ,调到下一个分区 00000030 E2F1 loop 0x23 //跳转到循环开始的地方,继续检测 /** 没有发现活动分区,无法启动OS,按照规范调用Int 18h* 早期的BIOS的Int 18h中断服务程序就是启动ROM-Basic,* 现在的BIOS一般是打印错误信息*/ 00000032 CD18 int 0x18 //调用 终断 18 /** 找到活动分区后,还要检查剩余分区的启动标志是否为0* 不允许存在多个活动分区*/ /** 在 win7 的 MBR 中使用 int 0x13 扩展功能来读取磁盘* http://m.wendangku.net/doc/29a5f911a76e58fafab00369-7.html 详细介绍int 13* 因为找到0x80字段才调转的,因为dl是1byte,所以传送1byte数据到dl寄存器 * dl 是磁盘驱动器号,第一次读取mbr肯定需要磁盘驱动器号,所以这里接着用读mbr的磁盘驱动器号*/ 00000034 885600 mov [bp+ 0x0 ],dl 00000037 55 push bp //入栈 /* 如果不成功的反复读 5 次 */ 00000038 C6461105 mov byte [bp+ 0x11 ], 0x5 /* 此处是一个标志位,用来记录是否支持int 0x13 扩展 */ 0000003 C C6461000 mov byte [bp+ 0x10 ], 0x0 /* 测试是否支持 int 0x13 扩展功能 */ 00000040 B441 mov ah, 0x41 /* 设置扩展int 13的 参数固定 */ 00000042 BBAA55 mov bx, 0x55aa /* 设置扩展int 13的 参数固定 */ 00000045 CD13 int 0x13 00000047 5 D pop bp 00000048 720 F jc 0x59 /* 进位标志1 则表示不支持扩展int 13 */ 0000004 A 81 FB55AA cmp bx, 0xaa55 /* bx 等于 0xaa55 则表示支持 */ 0000004 E 7509 jnz 0x59 /* 不支持 */ /** cx 等于 0x1 表示支持第一个子集* 第一个子集提供了访问大硬盘所必须的功能,包括检查扩展In13H是否存在(41h)* 扩展读(42h),扩展写(43h),校验扇区(44h),扩展定位(47h)和取得驱动器参数(48h)*/ 00000050 F7C10100 test cx, 0x1 /* and cx, 0x1*/ 00000054 7403 jz 0x59 /* 不支持 */ 00000056 FE4610 inc byte [bp+ 0x10 ] /* 走到这一步表示支持 ,把标志位加1 */ 00000059 6660 pushad /* 通用寄存器入栈,为了检查是否遍历完4个分区表 */ 0000005 B 807E1000 cmp byte [bp+ 0x10 ], 0x0 /* 查看是否支持 */ 0000005 F 7426 jz 0x87 /* 不支持,则调用原始 int 13 0x87处是原始int 13 */ /* 以下是使用 int 0x13 扩展功能读 disk */ 00000061 666800000000 push dword 0x0 /* 32bit 入栈*/ /* * 磁盘起始位置,我们知道dpt第八字节开始存放逻辑起始扇区号* 这是要去读取活动分区的,第一个扇区分区表记录 即 :ptr* push 的数据,其实是一个数据结构* 下面是用 c 描述为:*
struct buffer_packet 
short buffer_packet_size;/* struct’s size */ 
short sectors; /* 读多少个 sectors */ 
char  buffer; /  buffer address(segment:offset 形式)*/ 
long long start_sectors; /* 从哪个 sector 开始读 */ 
} buffer;
00000067 66 FF7608 push dword [bp+ 0x8 ] 0000006 B 680000 push word 0x0 0000006 E 68007 C push word 0x7c00 /* 传输缓冲区地址 */ 00000071 680100 push word 0x1 /* 读取扇区的个数 */ 00000074 681000 push word 0x10 /* 数据包尺寸一般是/ 16字节 */ 00000077 B442 mov ah, 0x42 /* 读磁盘 */ 00000079 8 A5600 mov dl,[bp+ 0x0 ] /* 驱动器号 */ 0000007 C 8 BF4 mov si,sp /* buffer_packet 的 address */ 0000007 E CD13 int 0x13 00000080 9 F lahf 00000081 83 C410 add sp,byte + 0x10 00000084 9 E sahf 00000085 EB14 jmp short 0x9b /* 跳转到原int 13 之后 */ /* 使用 int 0x13 原有功能来读取磁盘 */ /* ah= 0x2 功能读 al=0x1 读一个扇区*/ 00000087 B80102 mov ax, 0x201 0000008 A BB007C mov bx, 0x7c00 /* es:bx = buffer */ 0000008 D 8 A5600 mov dl,[bp+ 0x0 ] /* hard disk */ 00000090 8 A7601 mov dh,[bp+ 0x1 ] /* 从哪个 head 开始读 */ 00000093 8 A4E02 mov cl,[bp+ 0x2 ] /* 从哪个 sector 开始读 */ /* 其中低 6 bits 是 sector,高2位是cylinder */ 00000096 8 A6E03 mov ch,[bp+ 0x3 ] /* 从哪个 cylinder 开始读 */ 00000099 CD13 int 0x13 /* 活动分区已经找到,并且读取了活动分区的第一个分区表记录到 0x7c00 */ 0000009 B 6661 popad /* 通用寄存器出栈 */ 0000009 D 731 C jnc 0xbb /* 读取成功则跳转 */ 0000009 F FE4E11 dec byte [bp+ 0x11 ] /* 5-1 ,通过这个变量来完成五次对磁盘的读 */ 000000 A2 750 C jnz 0xb0 /* 不等于0 就继续*/ /* 读完五次后 ,还找不到活动分区就输出错误信息*/ 000000 A4 807E0080 cmp byte [bp+ 0x0 ], 0x80 000000 A8 0 F848A00 jz word 0x136 /* 找到则去读取分区表记录信息 */ 000000 AC B280 mov dl, 0x80 000000 AE EB84 jmp short 0x34 /* 读信息 */ 000000 B0 55 push bp /**/ 000000 B1 32E4 xor ah,ah 000000 B3 8 A5600 mov dl,[bp+ 0x0 ] 000000 B6 CD13 int 0x13 000000 B8 5 D pop bp 000000 B9 EB9E jmp short 0x59 /**代码中再次核对,是否 55aa 标志,如果不是将打印出错信息后 hlt*代码中还将测试键盘读/写缓冲区,然后往键盘端口 0x60 写命令字。*call word 0x156 这个子过程就是测试读/写缓冲区过程。*代码最终将转去 0x127 执行*/ 000000 BB 813 EFE7D55AA cmp word [ 0x7dfe ], 0xaa55 000000 C1 756 E jnz 0x131 /* 不是,打印错信息,hlt */ 000000 C3 FF7600 push word [bp+ 0x0 ] 000000 C6 E88D00 call word 0x156 /* 从 64H 读 1 byte */ 000000 C9 7517 jnz 0xe2 /* 缓冲区满,不能写*/ 000000 CB FA cli 000000 CC B0D1 mov al, 0xd1 000000 CE E664 out 0x64 ,al 000000 D0 E88300 call word 0x156 000000 D3 B0DF mov al, 0xdf 000000 D5 E660 out 0x60 ,al 000000 D7 E87C00 call word 0x156 000000 DA B0FF mov al, 0xff 000000 DC E664 out 0x64 ,al 000000 DE E87500 call word 0x156 000000E1 FB sti 000000E2 B800BB mov ax, 0xbb00 000000E5 CD1A int 0x1a 000000E7 6623 C0 and eax,eax 000000 EA 753 B jnz 0x127 000000 EC 6681 FB54435041 cmp ebx, 0x41504354 000000 F3 7532 jnz 0x127 000000 F5 81 F90201 cmp cx, 0x102 000000 F9 722 C jc 0x127 /** 不明白 int 0x1a 中断的*/ 000000 FB 666807 BB0000 push dword 0xbb07 00000101 666800020000 push dword 0x200 00000107 666808000000 push dword 0x8 0000010 D 6653 push ebx 0000010 F 6653 push ebx 00000111 6655 push ebp 00000113 666800000000 push dword 0x0 00000119 6668007 C0000 push dword 0x7c00 0000011 F 6661 popad 00000121 680000 push word 0x0 00000124 07 pop es 00000125 CD1A int 0x1a /* * 代码最终回到0x7c00 ,继续执行从活动分区的第一个扇区拷贝的代码*/ 00000127 5 A pop dx 00000128 32 F6 xor dh,dh 0000012 A EA007C0000 jmp word 0x0 : 0x7c00 0000012 F CD18 int 0x18 /* 不明白 */ /* 打印出错信息,hlt */ 00000131 A0B707 mov al,[ 0x7b7 ] /* 索引号为 9A */ 00000134 EB08 jmp short 0x13e 00000136 A0B607 mov al,[ 0x7b6 ] /* 索引号为 7B */ 00000139 EB03 jmp short 0x13e 0000013 B A0B507 mov al,[ 0x7b5 ] /* 索引号为 63 */ 0000013 E 32E4 xor ah,ah 00000140 050007 add ax, 0x700 00000143 8 BF0 mov si,ax 00000145 AC lodsb 00000146 3 C00 cmp al, 0x0 00000148 7409 jz 0x153 0000014 A BB0700 mov bx, 0x7 0000014 D B40E mov ah, 0xe 0000014 F CD10 int 0x10 00000151 EBF2 jmp short 0x145 00000153 F4 hlt 00000154 EBFD jmp short 0x153 00000156 2 BC9 sub cx,cx 00000158 E464 in al, 0x64 0000015 A EB00 jmp short 0x15c 0000015 C 2402 and al, 0x2 0000015 E E0F8 loopne 0x158 00000160 2402 and al, 0x2 00000162 C3 ret /********** 下面的区域是 mbr 常量符: mbr_str **************/ /** 163----1b2char *mbr_str = "Invalid partition table.""Error loading operation system.""Missing operation system."*/ 00000163 49 dec cx 00000164 6 E outsb 00000165 7661 jna 0x1c8 00000167 6 C insb 00000168 6964207061 imul sp,[si+ 0x20 ],word 0x6170 0000016 D 7274 jc 0x1e3 0000016 F 6974696 F6E imul si,[si+ 0x69 ],word 0x6e6f 00000174 207461 and [si+ 0x61 ],dh 00000177 626 C65 bound bp,[si+ 0x65 ] 0000017 A 004572 add [di+ 0x72 ],al 0000017 D 726 F jc 0x1ee 0000017 F 7220 jc 0x1a1 00000181 6 C insb 00000182 6 F outsw 00000183 61 popaw 00000184 64696E67206 F imul bp,[fs:bp+ 0x67 ],word 0x6f20 0000018 A 7065 jo 0x1f1 0000018 C 7261 jc 0x1ef 0000018 E 7469 jz 0x1f9 00000190 6 E outsb 00000191 67207379 and [ebx+ 0x79 ],dh 00000195 7374 jnc 0x20b 00000197 656 D gs insw 00000199 004 D69 add [di+ 0x69 ],cl 0000019 C 7373 jnc 0x211 0000019 E 696E67206 F imul bp,[bp+ 0x67 ],word 0x6f20 000001 A3 7065 jo 0x20a 000001 A5 7261 jc 0x208 000001 A7 7469 jz 0x212 000001 A9 6 E outsb 000001 AA 67207379 and [ebx+ 0x79 ],dh 000001 AE 7374 jnc 0x224 000001 B0 656 D gs insw /** 下面是字符串索引值 * 在出错处理过程里,根据索引值找到相应的出错信息* 然后使用 int 0x10 打印出错信息,最后是 hlt 停机指令。*/ 000001 B2 0000 add [bx+si],al 000001 B4 00637 B add [bp+di+ 0x7b ],ah 000001 B7 9 A81D6EF4A call word 0x4aef : 0xd681 000001 BC 0101 add [bx+di],ax /*下面是磁盘分区表 64byte*/ 000001 BE 802021 and byte [bx+si], 0x21 000001 C1 0007 add [bx],al 000001 C3 FE db 0xfe 000001 C4 FF db 0xff 000001 C5 FF00 inc word [bx+si] 000001 C7 0800 or [bx+si],al 000001 C9 0000 add [bx+si],al 000001 CB B060 mov al, 0x60 000001 CD 07 pop es 000001 CE 00 FE add dh,bh 000001 D0 FF db 0xff 000001 D1 FF07 inc word [bx] 000001 D3 FE db 0xfe 000001 D4 FF db 0xff 000001 D5 FF00 inc word [bx+si] 000001 D7 B86007 mov ax, 0x760 000001 DA 0038 add [bx+si],bh 000001 DC 1 F pop ds 000001 DD 0000 add [bx+si],al 000001 DF 0000 add [bx+si],al 000001E1 0000 add [bx+si],al 000001E3 0000 add [bx+si],al 000001E5 0000 add [bx+si],al 000001E7 0000 add [bx+si],al 000001E9 0000 add [bx+si],al 000001 EB 0000 add [bx+si],al 000001 ED 0000 add [bx+si],al 000001 EF 0000 add [bx+si],al 000001 F1 0000 add [bx+si],al 000001 F3 0000 add [bx+si],al 000001 F5 0000 add [bx+si],al 000001 F7 0000 add [bx+si],al 000001 F9 0000 add [bx+si],al 000001 FB 0000 add [bx+si],al 000001 FD 0055 AA add [di- 0x56 ],dl 0x56 u

参考的博客 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值