如果你也是把《汇编语言全接触》系列一路跟过来的老读者肯定对DOS时代那些会咬引导扇区的老伙计不陌生。Monkey病毒很多安全厂商的样本库里写着Boot.Monkey或Monkey.A就是很有代表性的一款引导区病毒它躲在一小段512字节的引导代码里专门在电脑启动时抢先落地然后接管磁盘中断加密硬盘数据让整台机器在一夜之间变成一块“只亮光标不干活”的砖头。这篇文章就用汇编语言把它从里到外拆一遍聊感染机制、汇编层面的关键逻辑、隔离环境下的分析流程以及实操中怎么防治和恢复。内容偏实战适合正在啃汇编指令、想看真实代码样本的读者也适合那些系统维护多年但没有机会接触老病毒结构的运维朋友。你可以把这篇文章当成一份“引导区病毒入门解剖手册”读完之后再去碰软盘引导区或者MBR修复心里就踏实多了。1. 病毒整体设计与感染机制1.1 先搞清楚Monkey病毒到底做了什么Monkey病毒出现在上世纪90年代中后期那时Windows 95刚出来许多人还是在DOS 6.22下敲命令。它属于典型的引导区病毒传播介质是软盘。一张干净软盘插进已感染的机器只要DOS下执行过dir、copy这类会读目录的操作软盘的引导扇区就可能被改写成病毒代码。下次谁拿这张软盘去开机引导病毒就到了下一台机器。它真正让人头疼的地方不是传染而是落地之后的行为。病毒一旦在引导阶段获得控制权会驻留到内存高端接管int 13h磁盘服务同时会把硬盘的主引导扇区搬走换成一份经过加密的数据。表面上看硬盘分区依然存在实际上所有读写请求在病毒未驻留时都会走样DOS一启动就提示Invalid mediaFDISK看到的也是乱七八糟的容量。很多人以为硬盘低格了其实是引导区和中间某些扇区被“翻译”成了另一套内容。可以说Monkey病毒把引导区病毒的经典套路演了个全套自我复制、内存驻留、中断拦截、扇区加密、隐蔽感染。更重要的是它的一切都发生在512字节以内没有PE头没有壳每一行机器码都摆在明处非常适合用汇编语言来逐指令分析。分析完这么个样本你大概就能明白为什么当年的杀毒软件总是强调“引导区查毒”和“干净DOS环境杀毒”。1.2 引导区病毒赖以生存的实模式启动链路要理解Monkey病毒必须先弄明白一台老电脑是怎么启动的。上电一瞬间BIOS完成自检后会调用int 19h把0面0道1扇区也就是MBR或软盘引导扇区读到内存0x7C00处检查结尾两个字节是不是0x55AA是则跳过去执行。这512字节里既包含了主引导程序、磁盘分区表也可以变成一段恶意代码的入口。引导区病毒的算盘打得很简单既然BIOS无条件信任引导扇区那我就把病毒代码混进这个扇区里抢在真正的引导程序之前运行。Monkey病毒也不例外它的入口代码一开始就做几件事关中断把自己复制到内存高端从预留的隐藏磁道上把原始引导扇区读回来修改int 13h中断向量表然后跳回真正的引导扇区继续执行。这样用户看起来系统正常启动了但病毒已经率先在内存里站稳了脚跟。也正是因为这套机制手工杀毒的顺序才会强调“干净启动”。你从硬盘启动时病毒已经驻留这时候无论用什么工具读写引导区读到的都可能是病毒精心“伪装”过的数据只有用软盘或光盘引导到完全干净的环境int 13h才是真实的中断服务程序你才能看到硬盘上真正的原始面貌。1.3 为什么这门课值得用汇编来“解剖”我经常跟同行说看恶意代码和看年代是有关系的。现在一个勒索软件动辄几MB带壳、混淆、反调试、合法签名一个样本分析三五天很正常。但上世纪的老病毒正好相反它们受限于磁盘容量和处理速度代码恨不得一行掰成两行使没有多余动作。Monkey病毒把汇编语言里最核心的东西全部用上了段寄存器切换、中断调用、标志位操作、内存复制、位运算读它就像在上一堂十几年前的高级汇编课。对于学习汇编的人来说这种样本的价值在于“真实”。教科书里的例子通常是算一个斐波那契或者打印一串字符看着会了但真遇到系统底层问题时没有感觉。而Monkey病毒的所有技巧都是当年真实攻击者在资源极度受限的条件下写出来的每一条指令都有明确目的你能从中学会怎么判断一段引导代码是良性还是恶意怎么顺着int 13h的调用链追到病毒主体怎么根据加密算法反推原始数据。这些能力在后续做逆向、做安全运维甚至写底层驱动时都很管用。2. 核心汇编逻辑拆解2.1 病毒入口从0x7C00开始的引导代码引导扇区被读到0x7C00后CPU开始执行这里的代码。Monkey病毒入口继承了引导扇区程序的简洁风格开头往往是一条短跳转指令比如EB 1E跳过中间的描述信息落到真正的执行代码。病毒接着会关闭中断重新设置数据段寄存器然后把自己往内存高端搬。; 分析样本时还原的概念性流程不适用于构造任何恶意程序 start: cli ; 关闭可屏蔽中断防止执行中被干扰 mov ax, 0x07C0 mov ds, ax ; DS指向当前引导扇区所在段 mov ax, 0x9800 mov es, ax ; 目标段设在内存高端 xor si, si mov di, si mov cx, 0x0100 ; 复制256字512字节到高端 rep movsw jmp word ptr [0x9800:continue]这段逻辑是引导区病毒共通的“搬家”动作。搬完之后病毒才能在高端内存里安全地执行中断服务同时把0x7C00区域腾出来给真正的引导扇区使用。分析人员看这段代码时要留意几个关键数字复制长度是不是一个扇区、目标段是不是落在保留内存区域、后面跳转到的偏移是否与源代码对应稍有偏差就会暴露作者的编码习惯。顺着这个思路在调试器里单步跟踪很快就能把病毒主体段和入口段分开。随后病毒会读取隐藏的原引导扇区。典型做法是在软盘上预留一个磁道或者把原MBR写到某些“不可见”的扇区里。病毒代码里访问软盘或硬盘的指令通常都封装成子程序最终还是通过int 13h完成。如果你用DEBUG的t命令逐条执行看到int 13h参数里CX、DX的值与常见磁盘参数表不符那基本就是病毒在访问它的秘密藏身处。2.2 中断向量表的挂钩与还原中断向量表是实模式下的命脉它从内存地址0x0000:0x0000开始每4个字节保存一个中断号的入口段地址和偏移地址。int 13h对应偏移是0x4C也就是说地址0x0000:0x004C处存放着BIOS磁盘中断服务程序的入口。Monkey病毒驻留时会把这个入口保存到自己的数据区然后往0x4C处写入自己的hook函数地址这样后续所有int 13h调用都会先经过病毒代码。从汇编层面看这个动作其实就几条指令; 概念性示意演示int 13h向量被修改的观察思路 mov ax, 0x0000 mov es, ax mov bx, es:[0x004C] ; 保存原int 13h偏移 mov dx, es:[0x004E] ; 保存原int 13h段地址 mov es:[0x004C], offset hook_func mov es:[0x004E], 0x9800挂钩后病毒每次都能“看见”系统对磁盘的访问请求。它对入口参数进行判断比如是不是要读取引导扇区、是不是有人在做杀毒扫描然后决定是老实转发给BIOS还是先把自己的加密/解密变换做一遍再转发。这个拦截点也是我们手工诊断最容易抓的地方干净系统里int 13h向量通常指向F000段ROM BIOS如果你的机器里这个指针变成了9xxx段之类的内存高端地址十有八九有驻留程序。需要注意的是光看向量表还不够因为有些病毒会直接改写内存里BIOS代码区或者把自己藏在VBR之后的位置。所以诊断时要结合反汇编看看挂钩代码开头是普通磁盘参数处理还是脱壳解密逻辑。Monkey病毒属于相对朴素的一类只要认真u一下hook位置它的数据区、原向量保存点、加密常量都能翻出来。2.3 磁盘扇区加密与“假删除”数据的技术内幕Monkey病毒之所以在当年能造成那么大恐慌是因为它把硬盘上的重要扇区内容进行了变换。表面上用FDISK还能看到分区可是启动时读出来的引导信息全是乱码数据区也可能无法正常访问。这个过程本质上是病毒在int 13h服务里对扇区数据做了一层XOR或加减运算再用变换后的结果去响应真实请求。举个例子病毒可能每读一个扇区时先调用BIOS读取真实数据到缓冲区然后对这个缓冲区逐字节解码再把解码后的数据返回给调用者。反过来当系统或用户程序要写数据时病毒先把数据“改写”一遍再交给BIOS存盘。这么做的效果是只要病毒还在内存里一切读写都好像正常而一旦你用干净软盘启动病毒不复存在int 13h回到BIOS原样处理硬盘上那些加密数据就彻底“现出原形”表现为系统无法识别分区、文件目录丢失。分析这类变换时把两个扇区内容并排比较就够了。拿一份正常的、一份感染态驻留情况下读出来的数据逐字节对比如果发现规律性的差异比如固定偏移上所有字节都被异或了同一个常数那基本就是单字节XOR。Monkey的数据变换并不是特别复杂属于刚开始逆一个下午就能搞定的小项目但就是这个“简单”当年把无数维护人员折腾到想换硬盘。熟悉汇编的位运算指令之后你可以在DEBUG里直接写一小段还原程序把加密扇区解码回来整个过程极大提升对内存数据流的掌控感。提示下面的章节和处理流程均基于隔离环境中的历史样本分析目的是理解引导区病毒的原理和防护手段不要尝试在真实系统、他人设备或生产环境中复现或传播任何恶意代码。3. 隔离环境下的样本分析与手工清除实操3.1 准备一台“装了防弹玻璃”的实验环境分析引导区病毒最好用的环境就是虚拟机。VirtualBox里装一个DOS 6.22或者干脆用FreeDOS再准备一张“救急盘”ISO我通常会把Debug.com、一些磁盘工具和两份干净引导扇区备份一起打包进去。虚拟机的好处只有一个随时可以回滚快照哪怕感染代码把分区表弄得乱七八糟关掉虚拟机再恢复快照就行完全不用心惊胆战。还有一点要注意虚拟机的硬盘镜像最好单独保存一份原始扇区备份。在干净系统里用任意磁盘扇区编辑器把第一个物理硬盘的0面0道1扇区导出成文件这就是后面做恢复对比的基准。有了这张基准盘你就能快速分辨什么地方被改动过。我是建议把分析用的软盘镜像也单独建一个目录不要跟日常文件混在一起防止哪天手滑把样本拷到共享目录里。我自己的习惯是三层隔离虚拟机只开一个仅主机的虚拟网卡甚至直接禁用网络宿主机器上开启文件实时监控但样本目录单独设一个只读权限的文件夹分析完成后马上保存一份快照且不保留原始样本在工作目录之外。这套流程虽然有点繁琐但能让你把所有精力放到汇编指令上而不是担心样本扩散。3.2 用DEBUG一砖一瓦看中断向量和引导区进入干净DOS环境后第一件事就是看int 13h向量有没有被改掉。在DEBUG命令行下输入-d 0:4c 4f这条命令会显示地址0000:004C到0000:004F的四个字节分别对应int 13h的偏移和段。正常情况下你会看到类似F000:xxxx这样的值表示中断指向BIOS ROM如果显示的是9F80:0130之类的地址那基本可以判断已经有驻留程序接管了磁盘中断。接下来读取MBR并检查特征。在DEBUG里敲一段极短的程序把第一个硬盘的0面0道1扇区读进缓冲区0x0200然后dump出来看-a 100 mov ax, 0201 mov bx, 0200 mov cx, 0001 mov dx, 0080 int 13 int 20 -g -d 0200 03ff如果读到的数据开头不是常见的引导程序跳转指令而是到处充满对内存段的修改、对int 13h的重新封装并且结尾还是有55 AA那这就是一个被改过的引导扇区。把这512字节存成文件和干净备份做逐字节diff既能确认感染也能定位病毒代码段。这个方法完全不需要杀毒软件只要会一点DEBUG和汇编就能独立判断。3.3 内存驻留点与病毒代码定位病毒驻留后int 13h入口就是它的hook函数。在DEBUG里用u命令反汇编当前int 13h向量指向的地址会看到一段独立的硬盘服务程序。Monkey病毒以及同代引导区病毒在驻留时还有一个共同特征它们会修改INT 12H返回的内存大小值少报几KB这样DOS就不会注意到高端内存被占用了。你可以用一个小技巧验证这一点在干净系统里先用DEBUG查看INT 12H返回值之后再在感染系统里查看。如果可用的内存大概率少了2KB到几KB那就能佐证驻留。这些手段在今天看来有点原始但你可以清楚体会到恶意程序想要隐蔽自己就必须在资源统计和中断调用上做手脚而这一切都会在汇编指令层面留下痕迹。对于想练汇编眼力的人来说这是最直观的“入侵现场”。定位到hook程序后不要急着把它废除先分析它的逻辑。往前翻它的入口找到它对原int 13h保存值的引用通常是一个位于数据区的双字节变量顺着这个变量继续读还能看到病毒对扇区号的变换表。这个阶段与其大量贴代码不如亲手在DEBUG里一步步t单步跟踪观察AX、BX、CX、DX怎么变化。我建议你准备一张纸把每次int 13h调用前的寄存器值记录下来分析完就能画出病毒的行为流程图比看任何静态分析报告都深刻。3.4 手工清除的完整流程手工清除分两条线一条是已经看清病毒逻辑、想直接恢复另一条是只想快速恢复正常。先说前者。最稳妥的办法是用干净软盘或光盘启动先确保内存中没有任何病毒。在DEBUG下写回你之前备份的干净引导扇区-a 100 mov ax, 0301 mov bx, 0200 mov cx, 0001 mov dx, 0080 int 13 int 20 -g写之前一定要把当前带毒的MBR先存一份命名为infected.bin别急着覆盖。因为一旦写错了备份或者之后需要反过来分析病毒这个文件就是唯一的现场素材。写完之后重启如果硬盘能正常引导说明只是MBR被改装过数据区未受损如果不能就要继续对硬盘上的其他关键扇区做检查必要时把分区表重建出来。如果是那种连分区都看不到的严重情况建议不要用fdisk /mbr这类一键命令因为有些版本会直接重写整个引导代码而Monkey病毒还可能加密了分区表的副本。正确的顺序是先从干净的整盘镜像里恢复分区表或者根据病毒分析得到解密偏移把驻留状态下的int 13h解密算法用到原始数据上还原出真正可读的MBR和DBR。这个工作量大一点但数据安全永远比图省事重要。注意千万不要在带毒的DOS环境下尝试“写回干净MBR”否则你会把病毒加密后的数据当成干净数据写进磁盘越修越乱。正确做法永远是先把系统冷启动到干净环境再动手。4. 常见问题与排查技巧实录4.1 感染后不知所措的表象清单我盘点了这些年遇到过的引导区病毒表现Monkey感染后最常见的症状比较集中表现可能原因初步判断方向硬盘开机卡在Starting MS-DOS之前只有光标闪MBR或VBR被改写读MBR检查引导代码和跳转指令DOS启动后提示Invalid media / No boot device分区表或引导扇区数据被加密对比扇区数据和干净备份软驱指示灯常亮但读出的内容乱码软驱引导扇区被感染用干净的启动盘替换并格式化软盘杀毒软件报Boot.Monkey / MBR.Monkey病毒签名命中进入干净环境手工验证内存常规容量异常减少几个KB驻留代码占据高端内存查看INT 12返回值变化这些现象并不是Monkey独有但组合起来看很容易锁定是引导区问题。我给新人的建议是别一上来就重装系统那会把留在现场的线索全部冲掉。先把引导扇区和分区表保存下来再做后续处理毕竟故障排查的黄金法则是先保“现场”。4.2 从汇编特征入手做快速诊断如果只有二进制文件没有杀毒软件也可以靠几个汇编特征快速判断。引导区病毒代码一般都会包含以下某几个特征开头是短跳转、有对段寄存器的重新赋值、存在指向中断向量表地址0x0000:004C的写入指令、在数据区保存着原始中断向量、出现对扇区的重复读写和字节变换循环。用十六进制查看器打开感染后的MBR搜索对应机器码模式命中率相当高。这里有一个非常实用的实践把感染与未感染的两个引导扇区文件放在同一个十六进制编辑器里进行字节级对比重点看开头32字节、尾部32字节以及中间是否有大段连续相同区域。Monkey这种老样本改动范围有限你很快会看到它只是在原引导程序的外面包了一层自己的代码原引导程序可能被压缩或者被搬到后面原本的跳转偏移和分区表偏移都做了调整。识别了这些你就能手写一条简单的汇编小程序把它恢复原状过程很有成就感。当然这种方法有局限新型Bootkit会把引导代码做得更隐蔽甚至直接修改固件不是字符对比能搞定的。但对于学习阶段从Monkey这样的经典样本练手能帮你打下判断“这到底是不是引导区问题”的基本功。4.3 数据恢复的坑与底线数据恢复方面我踩过不少坑最深的教训是“不要在感染系统里用未经验证的工具”。很多人在Windows下看到杀毒软件报了可疑MBR顺手就下载某个“修复工具”自动清除结果工具把原有分区信息覆盖了数据反而更惨。按照我的经验越是被病毒搞过的盘越要谨慎对待先做镜像备份再做只读分析。另一个坑是以为“格式化C盘就能清干净”。如果病毒在MBR或分区表层面做了加密格式化只能重建文件系统框架底层那些被改写的扇区还是原样你格式化到的其实还是一套被病毒“翻译”过的数据。在Monkey这种加密型引导区病毒面前格式化是无效甚至有害的操作。正确的思路始终是先恢复引导区和分区表必要时用杀毒软件自带的“修复引导扇区”功能但前提是确认内存环境干净。数据恢复的底线就是任何写盘操作都是不可逆的。所以我习惯把原始USB镜像、引导扇区备份、分区表备份都单独存成文件放到另一个地方保存。哪怕排查过程出了岔子也还能回到最初的现场重新分析这个习惯在重大故障时救过我不少次。4.4 长期防护建议防护方面老规矩放在今天依然有效。第一不要用来源不明的软盘或U盘引导系统第二把启动顺序固定为硬盘优先尽量不读可移动介质第三定期备份引导扇区、分区表和重要的数据镜像。放到现代场景下你还可以开启系统的Secure Boot在固件层面把启动设备的信任链管起来同时用支持MBR引导区监控的安全软件做兜底。说回汇编的意义防护的本质是理解攻击路径。你只有知道引导区病毒会在0x7C00执行、会改int 13h向量、会占用内存高端才能在系统异常时快速判断“是引导区还是注册表”。新一代的攻击者其实还在用老思路只是把0x7C00换成了UEFI固件、把int 13h换成了运行时API钩子。所以把Monkey病毒吃透了也就拿到了理解现代Bootkit的钥匙。5. 分析引导区病毒该有的边界与心态5.1 我们是在分析不是在造样本写到这里必须把边界说清楚。我聊Monkey病毒目标是理解它的原理、掌握防御和清除方法而不是教你怎么做一个可以传播的样本。真实工作中拿到恶意样本要在隔离环境、虚拟化沙箱里操作不允许在局域网或生产环境打开。你学习过程中如果产生了好奇心要在合规框架下用已知样本库、教学镜像练习不要拿真实机器做实验更不要拿别人的设备开玩笑。对汇编学习者来说这种心态尤其重要。汇编语言本身是中性的它可以写操作系统驱动也可以被滥用。以防御视角学习时你会更关注中断向量表、内存驻留和启动链路而不是某个病毒到底能破坏到什么程度。分析完一个样本后最有价值的产出不是“我能写病毒了”而是“我知道系统在哪里防得住、在哪里防不住”。5.2 汇编语言和恶意软件分析的关系最后说点和学习路径相关的事。很多人问我现在学汇编还有用吗我的回答始终是如果你想做底层相关的东西汇编永远是地基。Monkey病毒就是个典型例子它简单到可以清楚地展示“计算机如何启动、中断如何转发、内存如何驻留、数据如何变换”但又不简单到让你以为安全分析只是点一点杀毒按钮。把这个样本读明白了以后再看到Bootkit的启动签名、驱动级Rootkit的Hook点你都不会犯怵。回顾整个分析过程你会发现真正解决问题的不是某个图形化工具而是那些看着平淡的DEBUG命令和汇编指令读扇区、改指针、单步执行、比较字节。它们没有界面却能让你直接触摸到系统的神经末梢。学到这个阶段你会慢慢把“汇编语言”从书本上的语法变成自己手里的一张地图哪里是中断向量表、哪里是引导扇区、哪里是保留内存全部了然于心。我个人在实际操作中最大的收获是养成了“先复现、再还原、最后才清理”的处理节奏。遇到任何异常引导或分区问题先拿镜像再比对干净样本接着分析驻留痕迹最后才动手修复。这个节奏帮我处理过不少看起来吓人的“硬盘报废”事件很多其实只是引导扇区被改了一个字节。如果说有什么建议可以送给正在学汇编的朋友那就是拿Monkey这类老样本当练习一行一行地读读完之后再总结成自己的排查清单你会发现系统底层的大门从此就打开了。