Chapter 2 软件安全基础知识
2.1 系统引导与控制权
BIOS
Basic Input & Output System:基本输入输出系统,存储在主板BIOS Flash或ROM芯片中,其为计算机提供最为底层和直接的硬件设置和控制。
在启动计算机时,BIOS会进行自检工作:检测系统中的一些关键设备是否存在以及是否能够正常工作,进行初始化并将控制权交给后续引导程序
- 显卡及其他相关设备初始化
- 显示系统BIOS启动画面,含系统BIOS版本号、类型、序列号等
- 检测CPU类型和工作频率,内存容量,将结果显示在屏幕之上
- 检测系统中安装的一些标准硬件设备和即插即用设备(硬盘、光盘、软驱、串并行接口等)
- 根据用户指定顺序从硬盘/软盘/光驱启动,若从硬盘启动,则将控制权交由硬盘主引导程序。
MBR
Master Boot Record:硬盘主引导程序,位于硬盘的第一个扇区。
- 用于从主分区表中定位活动分区
- 装载活动分区的引导程序,并移交控制权
DBR
DOS Boot Record(OBR/PBR):活动分区引导程序,位于分区的第一个扇区。
- 用于加载操作系统引导程序,准备将控制权移交给操作系统。Windows XP的NTLDR和Windows 10的bootmgr
操作系统引导
- 将处理器以16位内存模式扩展为32(64)位内存模式
- 启动小型文件系统驱动,以识别FAT32和NTFS系统
- 读取boot.ini,进行多操作系统选择(或hiberfil.sys恢复休眠)
- 检测和配置硬件(NT或XP系统,则运行:-NTDETECT.COM,将硬件信息提交给NTLDR,写入HKEY_LOCAL_MACHINE中Hardware中)
系统内核加载
- NTLDR加载内核程序NTOSKRNL.EXE以及硬件抽象层HAL.dll等
- 读取并加载HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet下面指定的驱动程序
- NTLDR将把控制权传递给NTOSKRNL.EXE,至此引导过程结束
Windows系统装载
- 创建系统环境变量
- 启动win32.sys(windows子系统内核模式)
- 启动csrss.exe(windows子系统用户模式)
- 启动winlogon.exe等一系列程序,显示图标等
- 启动需要自启动的windows服务
- 启动本地安全认证Lsass.exe
- 显示登录界面等
- 登录后启动当前用户环境下的自启动程序
- 用户自行触发执行各种应用程序
恶意代码获取控制权的方式
- 在计算机系统引导阶段获取控制权
- 在操作系统启动阶段获取控制权
- 在用户应用程序执行阶段获取控制权
2.2 80x86处理器工作模式
实地址模式、保护模式、虚拟8086模式
其中除保护模式外均为向下兼容8086处理器而设计。
实地址模式
- 80x86处理器于复位和加电时使用
- 寻址方式:段地址+偏移地址,可寻址220=1MB空间
- 不能进行内存分页管理
- 没有优先级的定义,所有指令均在ring0状态工作
- 如何切换到保护模式:在实地址模式下初始化控制寄存器,GDTR、LDTR等管理寄存器以及页表,之后置位CR0寄存器的保护模式使能位(第0位)
保护模式
- 80x86的常态工作模式
- 32位的处理器支持32位寻址,可寻址空间:4GB
- 支持内存分页机制,能够支持虚拟内存
- 支持优先级机制,能够进行任务环境隔离
- 如何切换到实模式:修改CR0寄存器的保护模式使能位即可
虚拟8086模式
- 在保护模式下兼容80x86模式
- 作为任务在保护模式下运行,相当于开启了一个8086模式的虚拟机
- 能够使用内存分页机制为每一个虚拟8086模式任务分配1MB的内存
2.3 Windows内存结构和管理
DOS实模式内存管理
Windows虚拟地址空间布局
windows的32位系统共4GB内存中用户空间和内核空间各占2GB,其中用户空间在低地址处(Linux用户空间为3GB)
Windows程序在内存中的映像
CPU特权级别与内存访问
操作系统将处理器存取模式划分为用户模式(ring3)和内核模式(ring0)。用户应用程序仅能访问用户区地址,内核程序可以访问所有内存地址、硬件,使用所有处理器指令。
用户区内存的内容
- 应用程序代码
- dll文件代码
- 全局变量
- 线程栈
不同程序的内存相互隔离,能够从一个程序影响另一个程序很难。
内核区内存的内容
内核区数据为所有进程共享,含操作系统内核、线程调度、内存管理、文件系统、网络系统等支持代码。用户态代码无法访问。
虚拟地址和物理地址的转换
x86 windows使用二级页表的方式进行转换,可将虚拟地址转译为物理地址。
32位地址由:页目录索引(最高10位)、页表索引(中间10位)、字节索引(最低12位)构成。x86系统中默认分页大小为4KB,故页内字节索引为最低12位。
页目录基地址通过CR3寄存器获取,通过页目录索引找到页目录项(PDE),转到相应的页表索引。页目录是一个长度为1024的数组。【注意:页目录中存放的是每一个页表的起始地址,页表的存放可能是离散的】
在页表中通过页表索引找到页表项(PTE),指向虚拟地址所映射的物理地址。每个页表也是一个长度为1024的数组。【页表中存放的就是物理地址】
再加上字节索引,就能够映射到具体的物理地址中的某一个字节。
存放PDE和PTE的地址称为页帧号(PFN)
思考题
- windows编程时malloc实际上能支持的内存大小不大于2GB,因为用户能够分配的空间只有2GB,但这2GB中还包含代码、其他数据、控制信息等,因此这2GB无法全部被分配。
- 不断增加物理内存,不能增加malloc分配的最大内存大小,因为机器字长的限制,每个程序的内存大小均为4GB,与物理地址的大小无关。
- 增加物理内存能够让系统运行更加流畅,因为减少了换页的次数。(换页:在物理内存空间紧张时,操作系统会将目前访问次数不多或正在挂起的进程的内存空间暂时转移到外存中,以提升当前正在运行进程的速度。)
2.4 磁盘的物理和逻辑结构
物理结构
硬盘:控制代码的静态存储仓库,内含系统引导代码和用户存储的各类代码和数据等。同时硬盘也是恶意代码争夺控制权的中心
外部结构:接口(电源接口+数据接口)、硬盘控制电路、固定面板
- 接口:PATA并行接口、SATA串行接口,并行接口传输速度比串行慢
- 固定面板:保证盘片和机构的稳定运行,包括产品基本信息,如版号、生产日期等
内部结构:盘片、磁头、盘片主轴、控制电机、磁头控制器、数据转换器。
逻辑结构
寻址方式:
- CHS寻址:柱面、磁头、扇区。
- 磁头有256个,柱面(磁道)有1024环,扇区有63个,每扇区存储512字节数据,故可以寻址最多8064MB空间。
- 对于老式硬盘而言,每个磁道的扇区数量相等,这样位于外圈的磁道会产生空间浪费,相比内圈的磁道存储密度低得多。因此当前硬盘采用等密度结构,寻址方式采用线性逻辑块寻址:以扇区为单位进行线性寻址(有地址翻译器使两种寻址方式能够兼容)
CHS寻址与线性寻址(LBA)的转换关系
LBA实际上就是给每一个扇区进行编号,使得通过编号能够唯一确定一个扇区的位置。转换时扇区为最小单位,其上为磁头,最高为柱面。相邻扇区的LBA之差为1,相同扇区、相邻磁头的LBA之差为63;相同扇区、相同磁头、相邻柱面的LBA之差为63*255。
硬盘的分区结构
- MBR分区
- 主引导扇区:位于柱面0,磁头0,扇区1(第一个扇区),这个扇区中包含:
- MBR引导程序:前446字节
- DPT(硬盘分区表):之后64字节
- 结束标志:最后两个字节“55AA”
- 基本分区
- 扩展分区
- 主引导扇区:位于柱面0,磁头0,扇区1(第一个扇区),这个扇区中包含:
- GPT分区
- 描述各个分区的基本信息:分区开始位置、总的扇区数、分区类型等,每个分区信息占16字节
2.5 FAT32文件系统
FAT32文件系统由三个部分组成:引导扇区、FAT、数据存储区(以簇为单位,每一簇含多个扇区,存储目录项和文件数据)
簇
将磁盘空间以一定数目(2的整数次方)的扇区为单位进行划分,这样的单位即为簇。是文件空间分配的最小单位。
簇既不能太大,也不能太小。如果太大,存储很小的文件时也需要一整个簇,浪费空间;如果太小,则容易产生磁盘碎片。
FAT表
文件分配表:在FAT文件系统中用于磁盘数据索引和定位而引进的一种单向链表式结构。
FAT表存储所有簇的占用情况,若表项的值为0,则说明这个簇处于空闲状态。
对于FAT32文件系统,32位共可表示4GB大小的簇号空间。
簇链
一个文件占用簇号形成的单向链表。
在文件占用簇对应簇号的FAT项下填写下一个簇的簇号即可实现。若为最后一个簇,则填“0xFFFFFF0F”
文件的存储过程
- 定位足够的空闲簇
- 创建文件目录(文件目录:记录系统中所有文件的名字及其存放地址的目录表,可以理解为需要另外记录下文件的首簇)
- FAT中构建簇链
- 写入文件数据
被删除文件如何恢复
- 文件删除并非将簇中的文件内容全部销毁,而是将文件名首字节修改为E5后删除FAT表项与簇链,实际内容还在,但文件系统已无法索引。
- 即使通过文件恢复程序将删除文件恢复,也不可能得到文件名的第一个字节。
- 若要彻底删除文件,需要将原来文件占有的簇重新覆写,有时需要覆写几次才能够实现真正删除。
2.6 PE文件格式
参见第4章
VA = Image Base + RVA
2.7 ELF文件格式
elf文件是Linux可执行文件,含可执行文件、动态链接库文件.so等。
有段头部表用于将不同段映射到内存中的不同地址。
代码段有:.init、.text、.rodata等,均为只读。其中.rodata存储在C代码中直接定义的数据,如printf(“Hello”)中的字符串"Hello"即存储在.rodata中,不可修改。
数据段有:.data、.bss等,其中.data存放已经初始化的全局变量和静态变量,.bss存放未初始化的。
此外还有如.symtab、.debug、.line等不加载到存储器的符号表和调试信息。
练习题
1. 某程序内存中页目录索引为0x3f的值为0x74465000;则在_______到_______范围内的虚拟内存需要通过0x74465000指向的页表来查找其对应的物理地址;已知0x74465AB8地址处DWORD的值为0x83BF4000,那么物理地址为0x83BF4212对应的虚拟地址为_______(6分)
分析:虚拟地址最高10位对应的是页目录的索引,故最高10位应为0x3f,对应的虚拟内存地址应该为0x0FC00000~0x0FFFFFFF
共0x400000字节的空间(一个页4KB,即0x1000,这里是0x400(1024)页)。(0x74465AB8-0x74465000)/4=0x2AE,则其对应的应该是0x0FC00000+0x2AE*0x1000~0x0FC00000+0x2AF*0x1000-1
的地址空间,即0x0FEAE000~0x0FEAEFFF
这4KB空间,对应的应该是物理地址0x83BF4000~0x83BF4FFF
,故物理地址为0x83BF4212在内存中的映射应该为0x0FEAE212。
2. 在一个FAT文件系统中,一个簇的大小为4KB。现在向该文件系统中存入若干个大小在4~16KB之间的文件,每个文件的大小在这个范围内呈均匀分布。当存入文件足够多时,求该FAT文件系统中被浪费的空间占被占用的所有簇的总空间的比例。(4分)
分析:由于文件大小可能为4~16KB中的任何数,因此其大小在4~8KB的概率为1/3,8~12KB的概率为1/3,12~16KB的概率为1/3。即一个文件需要分配2、3、4个簇的概率均为1/3,对于每一个文件,其最后一个簇中被浪费的空间的期望值应该为簇大小的一半,即1KB,故分配2、3、4个簇时空间利用率的期望值分别为3/4,5/6,7/8。因此总的空间利用率期望值为,被浪费的空间占总占用空间的,超过1/6。