『楼 主』:
DOS病毒原理
使用 LLM 解释/回答一下
自磁芯大战以来,病毒从DOS时代的病毒发展到WINDOS系统的病毒,从变形、加密到智能化现在的病毒是让人防不胜防,现在网络上病毒大肆泛滥,给人们带来的很大的危害,本人在此仅做抛砖引玉,介绍病毒的原理,希望大家共同研究交流。(本文参考了网络上的部分文章,并引用了部分内容。)
要学DOS下的病毒,首先你必须要学会或掌握汇编语言。DOS下病毒一般分为引导型病毒、文件型病毒、混合型病毒等。大部分病毒是感染COM和EXE文件,因此你必须了解COM文件和EXE文件结构。
一 .COM文件结构及原理
.COM 文件比较简单,.COM文件包含程序的一个绝对映像──-就是说,为了运行程序准确的处理器指令和内存中的数据,MS-DOS通过直接把该映像从文件拷贝到内存而加载.COM程序,它不作任何改变。为加载一个.COM程序,MS-DOS首先试图分配内存,因为.COM程序必须位于一个64K的段中,所以.COM文件的大小不能超过65,024(64K减去用于PSP的256字节和用于一个起始堆栈的至少256字节)。如果MS-DOS不能为程序、一个PSP、一个起始堆栈分配足够内存,QQ:9750406则分配尝试失败。否则,MS-DOS分配尽可能多的内存(直至所有保留内存),即使.COM程序本身不能大于64K。在试图运行另一个程序或分配另外的内存之前,大部分.COM程序释放任何不需要的内存。
分配内存后,MS-DOS在该内存的头256字节建立一个PSP,如果PSP中的第一个FCB含有一个有效驱动器标识符,则置AL为00h,否则为0FFh。MS-DOS还置AH为00h或0FFh,这依赖于第二个FCB是否含有一个有效驱动器标识符。建造PSP后,MS-DOS在PSP后立即开始(偏移100h)加载.COM文件,它置SS,DS和ES为PSP的段地址,接着创建一个堆栈.为创建一个堆栈,MS-DOS置SP为0000h,若已分配了至少64K内存;否则,它置寄存器为比所分配的字节总数大2的值.最后,它把0000h推进栈(这是为了保证与在早期MS-DOS版本上设计的程序的兼容性)。MS-DOS通过把控制传递偏移100h处的指令而启动程序.程序设计者必须保证.COM文件的第一条指令是程序的入口点。注意,因为程序是在偏移100h处加载,因此所有代码和数据偏移也必须相对于100h.汇编语言程序设计者可通过置程序的初值为100h而保证这
一点(例如通过在原程序的开始使用语句org 100h).
二 EXE文件结构
EXE 文件比较复杂,每个EXE文件都有一个文件头,结构如下:
EXE文件头信息
──────────────────-
├ 偏移量 ┤ 意义 ┤
├00h-01h ┤MZ『EXE文件标记 ┤
├2h-03h ┤文件长度除512的余数 ┤
├04h-05h ┤...............商 ┤
├06h-07h ┤复位位项的个数 ┤
├08h-09h ┤文件头除16的商 ┤
├0ah-0bh ┤程序运行所需最小段数 ┤
├0ch-0dh ┤..............大.... ┤
├oeh-0fh ┤堆栈段的段值 (SS) ┤
├10h-11h ┤........sp ┤
├12h-13h ┤文件校验和 ┤
├14h-15h ┤IP ┤
├16h-17h ┤CS ┤
├18h-19h ┤............ ┤
├1ah-1bh ┤............ ┤
├1ch ┤............ ┤
────────────────────────-
.EXE文件包含一个文件头和一个可复位位程序映像。文件头包含MS-DOS用于加载程序的信息,例如程序的大小和寄存器的初始值。文件头还指向一个复位位表,该表包含指向程序映像中可复位位段地址的指针链表。文件头的形式与EXEHEADER结构对应:
EXEHEADER STRUC
exSignature dw 5A4Dh ;.EXE标志
exExraBytes dw ? ;最后(部分)页中的字节数
exPages dw ? ;文件中的全部和部分页数
exRelocItems dw ? ;复位位表中的指针数
exHeaderSize dw ? ;以字节为单位的文件头大小
exMinAlloc dw ? ;最小分配大小
exMaxAlloc dw ? ;最大分配大小
exInitSS dw ? ;初始SS值
exInitSP dw ? ;初始SP值
exChechSum dw ? ;补码校验值
exInitIP dw ? ;初始IP值
exInitCS dw ? ;初始CS值
exRelocTable dw ? ;复位位表的字节偏移量
exOverlay dw ? ;覆盖号
EXEHEADER ENDS程序映像,包含处理器代码和程序的初始数据,紧接在文件头之后。它的大小以字节为单位,等于.EXE文件的大小减去文件头的大小,也等于exHeaderSize的域的值乘以16。MS-DOS通过把该映像直接从文件拷贝到内存加载.EXE程序然后调整定位表中说明的可复位位段地址。
定位表是一个复位位指针数组,每个指向程序映像中的可复位位段地址。文件头中的exRelocItems域说明了数组中指针的个数,exRelocTable域说明了分配表的起始文件偏移量。每个复位位指针由两个16位值组成:偏移量和段值。 为加载.EXE程序,MS-DOS首先读文件头以确定.EXE标志并计算程序映像的大小。然后它试图申请内存。首先,它计算程序映像文件的大小加上PSP的大小再加上EXEHEADER结构中的exMinAlloc域说明的内存大小这三者之和,如果总和超过最大可用内存块的大小。则MS-DOS停止加载程序并返回一个出错值。否则面,它计算程序映像的大小加上PSP的大小再加上EXEHEADER结构中exMaxAlloc域说明的内存大小之和,如果第二个总和小于最大可用内存块的大小,则MS-DOS 分配计算得到的内存量。否则,它分配最大可用内存块。分配完内存后,MS-DOS确定段地址,也称为起始段地址,MS-DOS从此处加载程序映像。如果exMinAlloc域和exMaxAlloc域中的值都为零,则MS-DOS把映像尽可能地加载到内存最高端。否则,它把映像加载到紧挨着PSP域之上。接下来,MS-DOS读取复位位表中的项目调整所有由可复位位指针说明的段地址。对于复位位表中的每个指针,MS-DOS寻找程序映像中相应的可复位位段地址,并把起始段地址加到它之上。一旦调整完毕,段地址便指向了内存中被加载程序的代码和数据段。 MS-DOS在所分配内存的最低部分建造256字节的PSP,把AL和AH设置为加载 .COM程序时所设置的值。MS-DOS使用文件头中的值设置SP与SS,调整SS初始值,把起始地址加到它之上。MS-DOS还把ES和DS设置为PSP的段地址.最后,MS-DOS从程序文件头读取CS和IP的初始值,把起始段地址加到CS之 上,把控制转移到位于调整后地址处的程序。
三、引导型病毒原理
了解引导型病毒的原理,首先要了解引导区的结构。软盘只有一个引导区,称为DOS BOOT SECTER ,只要软盘做了格式化,就会存在。其作用为查找盘上有无IO.SYS DOS.SYS,若有则引导,若无则显示『NO SYSTEM DISK...』等信息。硬盘有两个引导区,在0面0道1扇区的称为主引导区,内有主引导程序和分区表,主引导程序查找激活分区,该分区的第一个扇区即为DOS BOOT SECTER。绝大多数病毒感染硬盘主引导扇区和软盘DOS引导扇区。
***3.5」软盘格式***
3.5」软盘是双面的,所以零磁道有正反两面,正面为0-17扇区,
反面是18-35扇区。
0 扇区: Boot area (引导扇区);
1 - 9 扇区: 1st FAT area (第一张文件分配表);
10 - 18 扇区: 2st FAT area (第二张文件分配表);
19 - 32 扇区: Root dir area(也叫 File Directory Table,FDT)
文件目录表(根目录)
33-2879 扇区: Data area (数据区)
***硬盘的主引导记录结构***
硬盘的主引导记录结构
偏移 机器码 符号指令 说明
0000 FA CLI ;屏蔽中断
0001 33C0 XOR AX,AX
0003 8ED0 MOV SS,AX ;(SS)=0000H
0005 BC007C MOV SP,7C00 ;(SP)=7C00H
0008 8BF4 MOV SI,SP ;(SI)=7C00H
000A 50 PUSH AX
000B 07 POP ES ;(ES)=0000H
000C 50 PUSH AX
000D 1F POP DS ;(DS)=0000H
000E FB STI
000F FC CLD
0010 BF0006 MOV DI,0600
0013 B90001 MOV CX,0100 ;共512字节
0016 F2 REPNZ
0017 A5 MOVSW ;主引导程序把自己从0000:7C00处搬到
;0000:0600处,为Dos分区的引导程序腾
;出空间
0018 EA1D060000 JMP 0000:061D ;跳到0000:061D处继续执行,实际上就是
;执行下面的MOV指令(001D偏移处)
001D BEBE07 MOV SI,07BE ;07BE-0600=01BE,01BE是分区表的首址
0020 B304 MOV BL,04 ;分区表最多4项,即最多4个分区
0022 803C80 CMP BYTE PTR [SI],80 ;80H表示活动分区
0025 740E JZ 0035 ;找到活动分区则跳走
0027 803C00 CMP BYTE PTR [SI],00 ;00H为有效分区的标志
002A 751C JNZ 0048 ;既非80H亦非00H则分区表无效
002C 83C610 ADD SI,+10 ;下一个分区表项,每项16字节
002F FECB DEC BL ;循环计数减一
0031 75EF JNZ 0022 ;检查下一个分区表项
0033 CD18 INT 18 ;4个都不能引导则进入ROM Basic
0035 8B14 MOV DX,[SI]
0037 8B4C02 MOV CX,[SI+02] ;取活动分区的引导扇区的面,柱面,扇区
003A 8BEE MOV BP,SI ;然后继续检查后面的分区表项
003C 83C610 ADD SI,+10
003F FECB DEC BL
0041 741A JZ 005D ;4个都查完则去引导活动分区
0043 803C00 CMP BYTE PTR [SI],00 ;00H为分区有效标志
0046 74F4 JZ 003C ;此分区表项有效则继续查下一个
0048 BE8B06 MOV SI,068B ;068B-0600=018B,取"无效分区"字符串
004B AC LODSB ;从字符串中取一字符
004C 3C00 CMP AL,00 ;00H表示串尾
004E 740B JZ 005B ;串显示完了则进入死循环
0050 56 PUSH SI
0051 BB0700 MOV BX,0007
0054 B40E MOV AH,0E
0056 CD10 INT 10 ;显示一个字符
0058 5E POP SI
0059 EBF0 JMP 004B ;循环显示下一个字符
005B EBFE JMP 005B ;此处为死循环
005D BF0500 MOV DI,0005 ;读入活动分区的引导扇,最多试读5次
0060 BB007C MOV BX,7C00
0063 B80102 MOV AX,0201
0066 57 PUSH DI
0067 CD13 INT 13 ;读
0069 5F POP DI
006A 730C JNB 0078 ;读盘成功则跳走
006C 33C0 XOR AX,AX
006E CD13 INT 13 ;读失败则复位磁盘
0070 4F DEC DI
0071 75ED JNZ 0060 ;不到5次则再试读
0073 BEA306 MOV SI,06A3 ;06A3-0600=00A3,即"Error loading"串
0076 EBD3 JMP 004B ;去显示字符串,然后进入死循环
0078 BEC206 MOV SI,06C2 ;06C2-0600=00C2,即"Missing.."串
0076 EBD3 JMP 004B ;去显示字符串,然后进入死循环
0078 BEC206 MOV SI,06C2 ;06C2-0600=00C2,即"Missing.."串
007B BFFE7D MOV DI,7DFE ;7DFE-7C00=01FE,即活动分区的引导扇
;区的最后两字节的首址
007E 813D55AA CMP WORD PTR [DI],AA55;最后两字节为AA55H则有效
0082 75C7 JNZ 004B ;无效则显示字符串并进入死循环
0084 8BF5 MOV SI,BP
0086 EA007C0000 JMP 0000:7C00 ;有效则跳去引导该分区
0080 49 6E 76 61 6C Inval
0090 69 64 20 70 61 72 74 69-74 69 6F 6E 20 74 61 62 id partition tab
00A0 6C 65 00 45 72 72 6F 72-20 6C 6F 61 64 69 6E 67 le.Error loading
00B0 20 6F 70 65 72 61 74 69-6E 67 20 73 79 73 74 65 operating syste
00C0 6D 00 4D 69 73 73 69 6E-67 20 6F 70 65 72 61 74 m.Missing operat
00D0 69 6E 67 20 73 79 73 74-65 6D 00 00 FB 4C 38 1D ing system...L8.
00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0100 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0180 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0190 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 80 01 ................;分区表
01C0 01 00 06 0F 7F 9C 3F 00-00 00 F1 59 06 00 00 00 ......?....Y....
01D0 41 9D 05 0F FF 38 30 5A-06 00 40 56 06 00 00 00 A....80Z..@V....
01E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............U.
使用INT 13H的02功能调用把位于硬盘保留扇区中0道0头1扇区处的硬盘主引导记录读到内存的ES:BX处。现在把读出程序代码进行如下分析:
1、移动主引导记录程序
0E74:7C00 33C0 XOR AX,AX ;AX清零
0E74:7C02 8ED0 MOV SS,AX ;SS清零
0E74:7C04 BC007C MOV SP,7C00 ;SP=7C00,堆栈设在0:7C00H
0E74:7C07 FB STI ;开中断
0E74:7C08 50 PUSH AX
0E74:7C09 07 POP ES ;ES=0
0E74:7C0A 50 PUSH AX
0E74:7C0B 1F POP DS ;DS=0
0E74:7C0C FC CLD
0E74:7C0D BE1B7C MOV SI,7C1B ;源地址为0:7C1BH
0E74:7C10 BF1B06 MOV DI,061B ;目的地址为0:061BH
0E74:7C13 50 PUSH AX
0E74:7C14 57 PUSH DI
0E74:7C15 B9E501 MOV CX,01E5 ;移动01E5字节
0E74:7C18 F3 REPZ ;将主引导记录从0:7C1B-0:7DFF
0E74:7C19 A4 MOVSB ;移至0:061B-0:07FF
0E74:7C1A CB RETF ;转移到0:061B,继续执行程序
2、顺序查找四个硬盘分区表,寻找自举标志
0E74:061B BEBE07 MOV SI,07BE ;SI指向硬盘分区表1的自举标志
0E74:061E B104 MOV CL,04 ;查找四个分区
0E74:0620 382C CMP [SI],CH
0E74:0622 7C09 JL 062D ;如果[SI]的第7位为1,即为自
;举标志,转062DH
0E74:0624 7515 JNZ 063B ;如果[SI]不为0,出错,转063BH
0E74:0626 83C610 ADD SI,+10 ;依次检验四个分区表,直至找到
0E74:0629 E2F5 LOOP 0620 ;自举标志
0E74:062B CD18 INT 18 ;找不到自举标志,进入BOOT异
;常处理程序。
0E74:062D 8B14 MOV DX,[SI] ;保存自举驱动器号于DL中
0E74:062F 8BEE MOV BP,SI ;保存自举分区地址指针于BP
0E74:0631 83C610 ADD SI,+10 ;继续检验自举分区后的分区
0E74:0634 49 DEC CX ;自举标志,直至四个分区都
0E74:0635 7416 JZ 064D ;检查完
0E74:0637 382C CMP [SI],CH ;若其余的自举标志不为0,出错
0E74:0639 74F6 JZ 0631
3、出错,写屏幕程序段
0E74:063B BE1007 MOV SI,0710 ;错误信息输出,死循环
0E74:063E 4E DEC SI
0E74:063F AC LODSB
0E74:0640 3C00 CMP AL,00
0E74:0642 74FA JZ 063E
0E74:0644 BB0700 MOV BX,0007
0E74:0647 B40E MOV AH,0E
0E74:0649 CD10 INT 10
0E74:064B EBF2 JMP 063F
硬盘主引导记录程序的功能是读出自举分区的BOOT程序,并把控制转移到分区BOOT程序。整个程序流程如下:
1 将本来读入到0:7C00H处的硬盘主引导记录程序移至0:61BH处;
2 顺序读入四个分区表的自举标志,以找出自举分区,若找不到,转而执行INT18H的BOOT异常执行中断程序;
3 找到自举分区后,检测该分区的系统标志,若为32位FAT表或16位FAT表但支持13号中断的扩展功能,就转到执行13号中断的41号功能调用进行安装检验,检验成功,就执行42号扩展读功能调用把BOOT区程序读入到内存0:7C00H处,成功,跳到第5步,若读失败或系统标志为其它,就调用13号中断的读扇区功能调用把BOOT读到0:7C00H;
4 用13号中断的读扇区功能时,用两种方式分别进行5次试读。第一种方式是直接从自举分区的头扇区读入BOOT程序,若读成功,但结束标志不是55AA,则改用第二种方式,又如果用第一种方式试读五次均不成功,就改用第二种方式。若两种方式试读均失败,就转到出错处理程序;
5 读入BOOT区程序成功,转至0:7C00H处执行BOOT程序
Since the core war, viruses have evolved from DOS-era viruses to Windows system viruses. From deformation, encryption to intelligent viruses, they are now hard to guard against. Currently, viruses are rampant on the network, causing great harm to people. Here, I just start a discussion, introducing the principles of viruses, hoping that everyone can study and communicate together. (This article refers to some articles on the network and quotes some content.)
To learn DOS viruses, you must first learn or master assembly language. DOS viruses are generally divided into boot viruses, file viruses, hybrid viruses, etc. Most viruses infect COM and EXE files, so you must understand the structures of COM and EXE files.
I. COM file structure and principle
The.COM file is relatively simple. The.COM file contains an absolute image of the program──that is, in order to run the program accurately, the processor instructions and data in memory, MS-DOS loads the.COM program by directly copying the image from the file to memory without making any changes. To load a.COM program, MS-DOS first tries to allocate memory. Since the.COM program must be in a 64K segment, the size of the.COM file cannot exceed 65,024 (64K minus 256 bytes for the PSP and at least 256 bytes for an initial stack). If MS-DOS cannot allocate enough memory for the program, a PSP, and an initial stack, the allocation attempt fails. Otherwise, MS-DOS allocates as much memory as possible (up to all reserved memory), even if the.COM program itself cannot be larger than 64K. Most.COM programs release any unnecessary memory before attempting to run another program or allocate additional memory.
After allocating memory, MS-DOS creates a PSP in the first 256 bytes of the memory. If the first FCB in the PSP contains a valid drive identifier, AL is set to 00h; otherwise, it is set to 0FFh. MS-DOS also sets AH to 00h or 0FFh, depending on whether the second FCB contains a valid drive identifier. After building the PSP, MS-DOS starts loading the.COM file immediately after the PSP (offset 100h). It sets SS, DS, and ES to the segment address of the PSP, and then creates a stack. To create a stack, MS-DOS sets SP to 0000h if at least 64K of memory has been allocated; otherwise, it sets the register to 2 more than the total number of bytes allocated. Finally, it pushes 0000h onto the stack (this is to ensure compatibility with programs designed on early versions of MS-DOS). MS-DOS starts the program by transferring control to the instruction at offset 100h. Program designers must ensure that the first instruction of the.COM file is the entry point of the program. Note that since the program is loaded at offset 100h, all code and data offsets must also be relative to 100h. Assembly language program designers can ensure this by setting the initial value of the program to 100h (for example, by using the statement org 100h at the beginning of the original program).
II. EXE file structure
The.EXE file is more complex. Each.EXE file has a file header, the structure is as follows:
EXE file header information
──────────────────-
├ Offset ┤ Meaning ┤
├00h-01h ┤MZ『EXE file mark ┤
├2h-03h ┤File length remainder when divided by 512 ┤
├04h-05h ┤............... quotient ┤
├06h-07h ┤Number of relocation items ┤
├08h-09h ┤Quotient of file header divided by 16 ┤
├0ah-0bh ┤Minimum number of segments required to run the program ┤
├0ch-0dh ┤.............. large.... ┤
├oeh-0fh ┤Segment value of the stack segment (SS) ┤
├10h-11h ┤........sp ┤
├12h-13h ┤File checksum ┤
├14h-15h ┤IP ┤
├16h-17h ┤CS ┤
├18h-19h ┤............ ┤
├1ah-1bh ┤............ ┤
├1ch ┤............ ┤
────────────────────────-
The.EXE file contains a file header and a relocatable program image. The file header contains information for MS-DOS to load the program, such as the size of the program and the initial values of registers. The file header also points to a relocation table, which contains a linked list of pointers to the segment addresses of relocatable segments in the program image. The form of the file header corresponds to the EXEHEADER structure:
EXEHEADER STRUC
exSignature dw 5A4Dh ;.EXE mark
exExraBytes dw ? ;Number of bytes in the last (partial) page
exPages dw ? ;Total and partial number of pages in the file
exRelocItems dw ? ;Number of pointers in the relocation table
exHeaderSize dw ? ;Size of the file header in bytes
exMinAlloc dw ? ;Minimum allocation size
exMaxAlloc dw ? ;Maximum allocation size
exInitSS dw ? ;Initial SS value
exInitSP dw ? ;Initial SP value
exChechSum dw ? ;Complement checksum value
exInitIP dw ? ;Initial IP value
exInitCS dw ? ;Initial CS value
exRelocTable dw ? ;Byte offset of the relocation table
exOverlay dw ? ;Overlay number
EXEHEADER ENDS The program image contains processor code and initial data of the program, immediately following the file header. Its size in bytes is equal to the size of the.EXE file minus the size of the file header, and also equal to the value of the exHeaderSize field multiplied by 16. MS-DOS loads the.EXE program by directly copying the image from the file to memory and then adjusting the relocatable segment addresses described in the relocation table.
The relocation table is an array of relocation pointers, each pointing to a relocatable segment address in the program image. The exRelocItems field in the file header indicates the number of pointers in the array, and the exRelocTable field indicates the starting file offset of the allocation table. Each relocation pointer consists of two 16-bit values: offset and segment value. To load the.EXE program, MS-DOS first reads the file header to determine the.EXE mark and calculate the size of the program image. Then it tries to apply for memory. First, it calculates the sum of the size of the program image file, the size of the PSP, and the memory size indicated by the exMinAlloc field in the EXEHEADER structure. If the sum exceeds the size of the largest available memory block, MS-DOS stops loading the program and returns an error value. Otherwise, it calculates the sum of the size of the program image, the size of the PSP, and the memory size indicated by the exMaxAlloc field in the EXEHEADER structure. If the second sum is less than the size of the largest available memory block, MS-DOS allocates the calculated amount of memory. Otherwise, it allocates the largest available memory block. After allocating memory, MS-DOS determines the segment address, also called the starting segment address, from which it loads the program image. If the values in the exMinAlloc field and the exMaxAlloc field are both zero, MS-DOS loads the image as high as possible in memory. Otherwise, it loads the image immediately above the PSP area. Next, MS-DOS reads the items in the relocation table to adjust all segment addresses indicated by the relocation pointers. For each pointer in the relocation table, MS-DOS finds the corresponding relocatable segment address in the program image and adds the starting segment address to it. Once adjusted, the segment address points to the code and data segments of the loaded program in memory. MS-DOS creates a 256-byte PSP in the lowest part of the allocated memory, setting AL and AH to the values set when loading the.COM program. MS-DOS uses the values in the file header to set SP and SS, adjusts the initial value of SS, and adds the starting address to it. MS-DOS also sets ES and DS to the segment address of the PSP. Finally, MS-DOS reads the initial values of CS and IP from the program file header, adds the starting segment address to CS, and transfers control to the program at the adjusted address.
III. Boot virus principle
To understand the principle of the boot virus, first, you need to understand the structure of the boot sector. A floppy disk has only one boot sector, called the DOS BOOT SECTER. As long as the floppy disk is formatted, it will exist. Its function is to find whether there are IO.SYS and DOS.SYS on the disk. If there are, it boots; otherwise, it displays messages like 'NO SYSTEM DISK...'. A hard disk has two boot sectors. The master boot sector at sector 1 of track 0, side 0 contains the master boot program and the partition table. The master boot program finds the active partition, and the first sector of this partition is the DOS BOOT SECTER. The vast majority of viruses infect the hard disk master boot sector and the floppy disk DOS boot sector.
***3.5-inch floppy disk format***
A 3.5-inch floppy disk is double-sided, so the zero track has two sides, the front side has sectors 0-17, and the back side has sectors 18-35.
Sector 0: Boot area (boot sector);
Sectors 1-9: 1st FAT area (first file allocation table);
Sectors 10-18: 2st FAT area (second file allocation table);
Sectors 19-32: Root dir area (also called File Directory Table, FDT)
File directory table (root directory)
Sectors 33-2879: Data area (data area)
***Structure of the hard disk master boot record***
Structure of the hard disk master boot record
Offset Machine code Symbolic instruction Description
0000 FA CLI ;Mask interrupt
0001 33C0 XOR AX,AX
0003 8ED0 MOV SS,AX ;(SS)=0000H
0005 BC007C MOV SP,7C00 ;(SP)=7C00H
0008 8BF4 MOV SI,SP ;(SI)=7C00H
000A 50 PUSH AX
000B 07 POP ES ;(ES)=0000H
000C 50 PUSH AX
000D 1F POP DS ;(DS)=0000H
000E FB STI
000F FC CLD
0010 BF0006 MOV DI,0600
0013 B90001 MOV CX,0100 ;Total 512 bytes
0016 F2 REPNZ
0017 A5 MOVSW ;The master boot program copies itself from 0000:7C00 to
;0000:0600 to make space for the DOS partition boot program
0018 EA1D060000 JMP 0000:061D ;Jump to 0000:061D to continue execution, actually
;execute the following MOV instruction (at offset 001D)
001D BEBE07 MOV SI,07BE ;07BE-0600=01BE, 01BE is the start address of the partition table
0020 B304 MOV BL,04 ;There are up to 4 partition tables, i.e., up to 4 partitions
0022 803C80 CMP BYTE PTR ,80 ;80H indicates an active partition
0025 740E JZ 0035 ;Jump if an active partition is found
0027 803C00 CMP BYTE PTR ,00 ;00H is the flag of a valid partition
002A 751C JNZ 0048 ;Jump if neither 80H nor 00H, the partition table is invalid
002C 83C610 ADD SI,+10 ;Next partition table entry, each entry is 16 bytes
002F FECB DEC BL ;Decrement the loop count by one
0031 75EF JNZ 0022 ;Check the next partition table entry
0033 CD18 INT 18 ;If none can boot, enter ROM Basic
0035 8B14 MOV DX,
0037 8B4C02 MOV CX, ;Take the surface, cylinder, and sector of the boot sector of the active partition
003A 8BEE MOV BP,SI ;Then continue to check the subsequent partition table entries
003C 83C610 ADD SI,+10
003F FECB DEC BL
0041 741A JZ 005D ;Jump to boot the active partition if all 4 are checked
0043 803C00 CMP BYTE PTR ,00 ;00H is the valid partition flag
0046 74F4 JZ 003C ;If this partition table entry is valid, continue to check the next one
0048 BE8B06 MOV SI,068B ;068B-0600=018B, take the "invalid partition" string
004B AC LODSB ;Take a character from the string
004C 3C00 CMP AL,00 ;00H indicates the end of the string
004E 740B JZ 005B ;Jump if the string is displayed completely, then enter an infinite loop
0050 56 PUSH SI
0051 BB0700 MOV BX,0007
0054 B40E MOV AH,0E
0056 CD10 INT 10 ;Display a character
0058 5E POP SI
0059 EBF0 JMP 004B ;Loop to display the next character
005B EBFE JMP 005B ;Here is an infinite loop
005D BF0500 MOV DI,0005 ;Read the boot sector of the active partition, up to 5 attempts
0060 BB007C MOV BX,7C00
0063 B80102 MOV AX,0201
0066 57 PUSH DI
0067 CD13 INT 13 ;Read
0069 5F POP DI
006A 730C JNB 0078 ;Jump if the read is successful
006C 33C0 XOR AX,AX
006E CD13 INT 13 ;Reset the disk if the read fails
0070 4F DEC DI
0071 75ED JNZ 0060 ;Try to read again if less than 5 times
0073 BEA306 MOV SI,06A3 ;06A3-0600=00A3, i.e., the "Error loading" string
0076 EBD3 JMP 004B ;Go to display the string, then enter an infinite loop
0078 BEC206 MOV SI,06C2 ;06C2-0600=00C2, i.e., the "Missing.." string
0076 EBD3 JMP 004B ;Go to display the string, then enter an infinite loop
0078 BEC206 MOV SI,06C2 ;06C2-0600=00C2, i.e., the "Missing.." string
007B BFFE7D MOV DI,7DFE ;7DFE-7C00=01FE, i.e., the start address of the last two bytes of the boot sector of the active partition
007E 813D55AA CMP WORD PTR ,AA55 ;The last two bytes are AA55H, which is valid
0082 75C7 JNZ 004B ;Jump to display the string and enter an infinite loop if invalid
0084 8BF5 MOV SI,BP
0086 EA007C0000 JMP 0000:7C00 ;Jump to boot this partition if valid
0080 49 6E 76 61 6C Inval
0090 69 64 20 70 61 72 74 69-74 69 6F 6E 20 74 61 62 id partition tab
00A0 6C 65 00 45 72 72 6F 72-20 6C 6F 61 64 69 6E 67 le.Error loading
00B0 20 6F 70 65 72 61 74 69-6E 67 20 73 79 73 74 65 operating syste
00C0 6D 00 4D 69 73 73 69 6E-67 20 6F 70 65 72 61 74 m.Missing operat
00D0 69 6E 67 20 73 79 73 74-65 6D 00 00 FB 4C 38 1D ing system...L8.
00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0100 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0180 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0190 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 80 01 ................;Partition table
01C0 01 00 06 0F 7F 9C 3F 00-00 00 F1 59 06 00 00 00 ......?....Y....
01D0 41 9D 05 0F FF 38 30 5A-06 00 40 56 06 00 00 00 A....80Z..@V....
01E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 55 AA ..............U.
Use the 02 function call of INT 13H to read the hard disk master boot record at sector 1 of track 0, side 0 in the hard disk reserved sector to ES:BX in memory. Now, the read program code is analyzed as follows:
1. Move the master boot record program
0E74:7C00 33C0 XOR AX,AX ;Clear AX
0E74:7C02 8ED0 MOV SS,AX ;SS clear
0E74:7C04 BC007C MOV SP,7C00 ;SP=7C00, the stack is set at 0:7C00H
0E74:7C07 FB STI ;Enable interrupts
0E74:7C08 50 PUSH AX
0E74:7C09 07 POP ES ;ES=0
0E74:7C0A 50 PUSH AX
0E74:7C0B 1F POP DS ;DS=0
0E74:7C0C FC CLD
0E74:7C0D BE1B7C MOV SI,7C1B ;Source address is 0:7C1BH
0E74:7C10 BF1B06 MOV DI,061B ;Destination address is 0:061BH
0E74:7C13 50 PUSH AX
0E74:7C14 57 PUSH DI
0E74:7C15 B9E501 MOV CX,01E5 ;Move 01E5 bytes
0E74:7C18 F3 REPZ ;Move the master boot record from 0:7C1B-0:7DFF
0E74:7C19 A4 MOVSB ;Move to 0:061B-0:07FF
0E74:7C1A CB RETF ;Transfer to 0:061B to continue executing the program
2. Sequentially search the four hard disk partition tables to find the boot flag
0E74:061B BEBE07 MOV SI,07BE ;SI points to the boot flag of hard disk partition table 1
0E74:061E B104 MOV CL,04 ;Search for four partitions
0E74:0620 382C CMP ,CH
0E74:0622 7C09 JL 062D ;If the 7th bit of is 1, it is the boot flag, jump to 062DH
0E74:0624 7515 JNZ 063B ;If is not 0, an error occurs, jump to 063BH
0E74:0626 83C610 ADD SI,+10 ;Successively check the four partition tables until found
0E74:0629 E2F5 LOOP 0620 ;Boot flag
0E74:062B CD18 INT 18 ;If the boot flag is not found, enter the BOOT exception handling program.
0E74:062D 8B14 MOV DX, ;Save the boot drive number in DL
0E74:062F 8BEE MOV BP,SI ;Save the boot partition address pointer in BP
0E74:0631 83C610 ADD SI,+10 ;Continue to check the partitions after the boot partition
0E74:0634 49 DEC CX ;Boot flag, until all four partitions are checked
0E74:0635 7416 JZ 064D ;Check完
0E74:0637 382C CMP ,CH ;If the remaining boot flag is not 0, an error occurs
0E74:0639 74F6 JZ 0631
3. Error, write screen program segment
0E74:063B BE1007 MOV SI,0710 ;Error message output, infinite loop
0E74:063E 4E DEC SI
0E74:063F AC LODSB
0E74:0640 3C00 CMP AL,00
0E74:0642 74FA JZ 063E
0E74:0644 BB0700 MOV BX,0007
0E74:0647 B40E MOV AH,0E
0E74:0649 CD10 INT 10
0E74:064B EBF2 JMP 063F
The function of the hard disk master boot record program is to read the BOOT program of the boot partition and transfer control to the partition BOOT program. The entire program flow is as follows:
1. Move the hard disk master boot record program originally read into 0:7C00H to 0:61BH;
2. Sequentially read the boot flags of the four partition tables to find the boot partition. If not found, transfer to execute the BOOT exception execution interrupt program of INT18H;
3. After finding the boot partition, detect the system flag of this partition. If it is a 32-bit FAT table or a 16-bit FAT table but supports the extended function of interrupt 13, transfer to execute the 41st function call of interrupt 13 for installation and inspection. If the inspection is successful, execute the 42nd extended read function call to read the BOOT area program into memory 0:7C00H. If successful, jump to step 5. If the read fails or the system flag is other, call the read sector function call of interrupt 13 to read the BOOT to 0:7C00H;
4. When using the read sector function of interrupt 13, perform 5 attempts in two ways. The first way is to directly read the BOOT program from the first sector of the boot partition. If the read is successful but the end flag is not 55AA, use the second way. Also, if the first way of trial reading fails five times, use the second way. If both ways of trial reading fail, transfer to the error handling program;
5. If the BOOT area program is read successfully, transfer to execute the BOOT program at 0:7C00H
|