笔记一主要记录了保护模式的知识,笔记二将从os进入保护模式开始。
1.FAT12文件系统
参考:https://blog.csdn.net/sunpuyizu19/article/details/50667686
http://blog.sina.com.cn/s/blog_3edcf6b80100crz1.html
https://blog.csdn.net/yangyang031213/article/details/79030247
使用diskgenius模拟软盘文件做实验。
FAT12是Microsoft公司DOS操作系统所支持的文件系统之一,此外还有FAT16和FAT32,之后会分别详述这些文件系统。
当软盘被标准格式化后,磁盘被格式化为:每磁头80个柱面(磁道),每个柱面有18个扇区,每个扇区有512字节空间。所以标准软盘的总空间(容量)为:
2*80*18*512=1474560B=1440K=1.44M
每个扇区512字节。
1.1引导扇区
操作系统标识FAT12文件系统是因为在逻辑0扇区(即引导扇区)处还存储着一个特定的数据结构,此结构有固定的格式,在操作系统将此磁盘格式化时自动生成,具体数据结构如下表所示:
偏移13处的是每簇所占用的扇区,类型是字节,簇是数据存储的最小单位,此字段的值取决于分区的大小,在FAT12格式下一般为1,即每簇只有1个扇区(512字节),簇越大,那么分区的容量也就越大,通过增加簇的扇区数,可以支持更大的磁盘分区,标准的簇大小为1、2、4、8、16、32、64和128,FAT12格式下只能管理2^12个簇(4096),所以在FAT12格式下能管理和分配的最大空间为:4096*1*512=2097152B=2M,所以FAT12一般只适合3.5寸高密度软盘(1.44M)。
1.2 文件目录表(分配表)
文件分配表所在的扇区应该是(隐藏扇区+保留扇区)=0+1=第1扇区处,从第1扇区开起到第9扇区结束,第一个文件分配表共占用9个扇区,第二个文件分配表从第10个扇区开始到第18扇区结束,在引导扇区的数据结构中明明确的指出了这些位置。
文件分配表数据结构如下图所示:
在FAT表开始扇区的第1字节是存储介质,0f0h代表软盘,0f8代表硬盘;第2、3这两个字节都是0ffh,代表了FAT文件分配表标识符,从第四个字节开始与用户数据区所有的簇一一对应,应该注意的是,用户数据区的第一个簇的序号是002,而不是000,因为储存介质和标识符占用了这两个序号。
在FAT12格式中用12比特位来代表一个簇的序号,我们知道,每个字节有8位比特,所以每个簇要占用1.5个字节,也就是说,占用了第1字节和第2字节的一半才能表示一个簇的序号,半字节的拆分办法按照下图的方式进行:
最终我们得到了这4个簇号的内容,内容是0ff0-0ff7h代表坏簇,磁道或柱面损坏不可使用,在格式式磁盘时由系统自动填充;内容是0ff8-0fffh代表文件内容结束,到此簇为止;其它的值代表着下一个簇号,接着我们分析一下刚才得到的那4个簇号的内容代表的意义,第2簇号的内容是0fffh,代表这个文件只占用了第2簇,文件的大小在512B(每簇1扇区512字节)之内。第3簇号的内容是004h,代表它的下一个簇是第4簇;第4簇号的内容是005h,代表它的下一个簇是第5簇,第5簇号的内容是0fffh,代表文件内容结束,所以这个文件应该是从第3簇开始到第5簇结束,占据了3簇的空间,文件大小在1536B(每簇1扇区512字节)之内。
1.3 文件目录项
文件目录项最开始位于扇区19(隐藏隐藏+保留扇区+FAT文件分配表占用扇区=0+1+9+9)处,它一共占用了14个扇区的空间,在引导扇区的数据结构中偏移17处的字段BPB_RootEntCnt指出了最大根目录数,在FAT12中的默认值是224,每个文件目录项占用了32字节的空间,那么共占用224*32/512=14扇区。
文件目录项的32字节数据结构如下图所示:
位于偏移11处的是文件属性,使用比特位来设置值:
00000000:普通文件,可随意读写
00000001:只读文件,不可改写
00000010:隐藏文件,浏览文件时隐藏列表
00000100:系统文件,删除的时候会有提示
00001000:卷标,作为磁盘的卷标识符
00010000:目录文件,此文件是一个子目录,它的内容就是此目录下的所有文件目录项
00100000:归档文件
文件的属性可以叠加使用,可以具有多重属性,即设置为只读的时候也可以同时隐藏。
偏移12处的共10字节长的内容没有使用,保留。
偏移22处的是双字节长的文件最后修改时间,使用的方式是分位压缩存储方式,两个字节共16位从高到低分别存储时分秒的数值,其中时占用5位(11-15),值从0-23,代表小时;分占用6位(5-10),值从0-59,代表分钟;秒占用5位(0-4),值为0-29,它的倍数(值*2)就得到秒数。
偏移24处的是双字节长的文件最后修改日期,使用的方式是分位压缩存储方式,两个字节共16位从高到低分别存储年月日的数值,其中年占用7位(9-15),值从0-199,此值加上1980就可以得到年份,代表从1980到2099年;月占用4位(5-8),值从1-12,代表月份;日占用5位(0-4),值从1-31,代表当月天数。
位于偏移26处的是双字节长的文件首簇号,利用此值就可以得到文件内容占用的第一个簇,然后在文件分配表中就可以得到所有的文件簇了。文件分配表中第一个簇号为002,即文件目录项结束后的第一个簇(扇区,若每簇扇区为数为1)。
最后位于偏移28处的双字(4B)长的文件长度(字节)值。
每个文件目录项的长度是32字节,偏移0处的8字节长的文件名,必须是大写的ASCII字符串,不足8字节就以空格(20h)来填充,接着是3字节长的文件后缀名,同样是大写的ASCII字符串,不足3字节以空格填充。如果文件名的第1字节是0E5h表示此文件已经删除,第1字节是0表示此目录项可用。
2. ELF文件格式解析
参考:https://blog.csdn.net/dddxxxx/article/details/80347610
2.1 ELF文件概览
首先,ELF文件格式提供了两种视图,分别是链接视图和执行视图。
链接视图是以节(section)为单位,执行视图是以段(segment)为单位。链接视图就是在链接时用到的视图,而执行视图则是在执行时用到的视图。上图左侧的视角是从链接来看的,右侧的视角是执行来看的。总个文件可以分为四个部分:
-
- ELF header: 描述整个文件的组织。
-
- Program Header Table: 描述文件中的各种segments,用来告诉系统如何创建进程映像的。
-
- sections 或者 segments:segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,也就是说,在链接阶段,我们可以忽略program header table来处理此文件,在运行阶段可以忽略section header table来处理此程序(所以很多加固手段删除了section header table)。从图中我们也可以看出,segments与sections是包含的关系,一个segment包含若干个section。
-
- Section Header Table: 包含了文件各个segction的属性信息,我们都将结合例子来解释。
程序头部表(Program Header Table),如果存在的话,告诉系统如何创建进程映像。
节区头部表(Section Header Table)包含了描述文件节区的信息,比如大小、偏移等。
2.2 ELF header
elf header 结构体:
#define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; ELF32_Half e_type; 文件类型 ELF32_Half e_machine; 机器的体系结构 ELF32_Word e_version; 文件版本 ELF32__Addr e_entry; 程序入口地址 ELF32_Off e_phoff; 程序头部表在文件中的偏移量 ELF32_Off e_shoff; 节区头部表在文件中的偏移量 ELF32_Word e_flags; ELF32_Half e_ehsize; ELF header 大小 ELF32_Half e_phentsize; Programma header table 中每一个条目的大小 ELF32_Half e_phnum; Programma header table中有多少个条目 ELF32_Half e_shentsize; Section header table 中每个条目的大小 ELF32_Half e_shnum; Section header table中有多少条目 ELF32_Half e_shstrndx; 包含节名称的字符串表示第几个节 }Elf32_Ehdr;
常用数据格式:
2.3 Programma header table 数据结构
描述的是段在文件中的位置、大小以及它被放进内存后所在的位置和大小
p_type 当前Programma header所描述的段的类型
p_offset 段的第一个字节在文件中的偏移
p_vaddr 段的第一个字节在内存中的虚拟地址
p_paddr 在物理地址地位相关系统中,此项是为物理地址保留
p_filesz 段在文件中的长度
p_memsz 段在内存中的长度
p_flags 与段相关的标志
p_align 根据此项值来确定段在文件以及内存中如何对齐