绕过操作系统提供的API来读取文件,肯定要了解硬盘结构和所用的文件系统。Dos下,设置
好CHS(Cylinder/Header/Sector)参数后,通过调用BIOS提供的13H中断,就可以得到制定扇区的内容,但由于INT 13H的有8.456GB的容量限制,而且CHS的方式要求每柱面扇区数相等,磁盘空间的利用率不高,于是扩展INT 13H出现了。
新式大容量的硬盘,透过扩展INT 13H,指定逻辑块地址后就可访问;为了兼容INT 13H的方式,内部装有一个地址翻译器,把CHS地址转换成LBA(逻辑块地址)。
出于安全的考虑, Windows 98以后,保护模式下的程序(ring 3)已经不能调用BIOS中断了,如果还要读指定扇区的内容,我们只能转而采用其它的方法。在Windows下,所有的设备都被当成一个个的文件,硬盘也不例外,这里我们就会用ReadFile来打开物理硬盘(注意:只是读物理硬盘,而不是读文件)。整个读文件的流程如下:
1. 打开物理硬盘
2. 读取MBR(主引导扇区)的内容
3. 分析MBR的内容,得到各Partition Entry(磁盘分区)的信息
4. 读取磁盘分区的引导记录(Boot Record,引导记录在各磁盘分区的第一扇区)
5. 根据磁盘分区引导记录的内容,得到FAT表的位置所在
6. 按照FAT表项中的簇链表,依次读取文件所用各簇的内容
在介绍MBR前,描述一下电脑的启动过程也有会有帮助,过程共有4步:
1. CPU和BIOS上电自检
2. BIOS决定哪一个设备为“启动设备”
3. BIOS把“启动设备”第一个物理扇区的内容读入内存,让CPU从该内存起始地址开始执
行。如果“启动设备”是硬盘,这一步就是读取MBR的内容,接下来的动作如下:
4. MBR中的代码读入“主活动分区”上的引导记录(Boot Record,注意与MBR的区别)到内
存中,接着CPU由此内存起始处开始执行。
MBR
读文件的流程也说了,启动过程也讲了,接下来就轮到各数据结构了。MBR结构很简单,由
启动电脑的可执行代码、分区入口(共四项)、引导记录结束标志(0x55 0xAA)三部分组成,
共512字节。
Offset |
Description |
Size |
000h |
Executable Code (Boots Computer) |
446 Bytes |
1BEh |
1st Partition Entry (See NextTable) |
16 Bytes |
1CEh |
2nd Partition Entry |
16 Bytes |
1DEh |
3rd Partition Entry |
16 Bytes |
1EEh |
4th Partition Entry |
16 Bytes |
1FEh |
Boot Record Signature (55hAAh) |
2 Bytes |
分区入口(Partiton Entry)
MBR中共有4个分区入口,一个入口代表了一个分区。分区入口结构中,记录了该分区起始和
结束的CHS参数,但由于CHS不适合用于8.456GB的硬盘,于是我们就把偏移(offset)为08h的
项就做它的代替品。
Offset |
Description |
Size |
00h |
Current State of Partition(00h=Inactive, 80h=Active) |
1 Byte |
01h |
Beginning of Partition - Head |
1 Byte |
02h |
Beginning of Partition - Cylinder/Sector (See Below) |
1 Word |
04h |
Type of Partition (See List Below) |
1 Byte |
05h |
End of Partition - Head |
1 Byte |
06h |
End of Partition -Cylinder/Sector |
1 Word |
08h |
Number of Sectors Betweenthe MBR and the First Sector in the Partition |
1 Double Word |
0Ch |
Number of Sectors in thePartition |
1 Double Word |
分区入口只有4个,要支持4个以上的分区怎么办呢?FAT32中,一般第一个分区是主分区,
其它所有的分区都包含在扩展分区(Extended Partiton)中。为了读取主分区外的分区,还
是需要一点技巧的,虽然不多。分区表中的第一项指定了主分区的位置,第二项指定了扩展
分区的位置。为了读取非主分区,你读入扩展分区所在位置的第一个扇区。该扇区内容的格
式与MBR相同,除了“可执行代码”处故意设置为空外。第一项的内容就是驱动器上下一个分
区的信息(D盘的信息),所不同的是,所有的扇区号都是相对于这个新的“MBR”的,扩展分区
就像是一块虚拟的硬盘。也许这样讲很不好理解,一个例子也许能让你更明白,让我们看一
个有三个分区(C,D,E)的硬盘分区表是什么样子的吧!
硬盘的MBR
入口#1 - 指向第一个分区(C盘)
入口#2 - 指向整个扩展分区(包含D盘和E盘)
在你读入扩展分区的第一个扇区后,另一个“MBR”就出现了,
扩展分区的MBR
入口#1 - 指向第二个分区(D盘)
入口#2 - 指向除了第二个分区外的扩展分区
现在,所有入口中的扇区号(特别是入口中偏移位置为08h)不再是针对硬盘的偏移了,而是
针对扩展分区起始位置的偏移。然而,CHS(柱面/磁头/山区)依然正确。
接下来,你再次读入扩展分区所在的第一个扇区,又一个MBR出现了。
剩余扩展分区的MBR
入口#1 - 指向第三个分区(E盘)
入口#2为空,因为这是最后一个分区
一直持续这种方式,直到不再有剩余分区止。
我们已经知道了分区存放的位置,进一步的,就是要分析该分区上的目录和文件。非常幸运
的,我们知道各个分区的第一扇区存放的是引导记录,如果不知道引导记录的格式,游戏也
无法继续下去,而更幸运的,我们还知道引导记录的格式。
这篇够长了,想知道引导记录的格式,请看下一篇:-)
参考资料:
http://www.easeus.com/resource/fat32-disk-structure.htm
http://www.codeproject.com/KB/system/change_drive_sn.aspx
http://support.microsoft.com/kb/140418/en-us
分享到:
相关推荐
ReadFile函数则用于从文件或设备读取数据到内存缓冲区,其函数原型如下: ```cpp WINBASEAPI BOOL WINAPI ReadFile( __in HANDLE hFile, __out_bcount_part(nNumberOfBytesToRead, *lpNumberOfBytesRead) LPVOID ...
1. **文件系统**:文件系统是操作系统用来组织、管理和存储文件的一种方法。它定义了文件如何存储、如何通过文件名进行访问,以及如何通过目录结构来组织文件。常见的文件系统类型有FAT、NTFS、EXT系列(EXT2、EXT3...
在确认文件成功打开后,需要检查文件的大小以确定读取所需的内存空间大小,并使用`ReadFile()`函数读取文件内容至内存。需要注意的是,API不会自动处理文本文件的格式化问题,因此读取后可能需要手动添加NULL终止符...
对于ReadFile,可以设定文件指针的位置来读取特定位置的数据: ```cpp LONG lDistance = 0; DWORD dwPtr = SetFilePointer(hFile, lDistance, NULL, FILE_BEGIN); if (dwPtr != INVALID_SET_FILE_POINTER) { // ...
MP4文件格式,全称为MPEG-4 Part 14,是一种广泛用于存储音频、视频和字幕数据的容器格式,常见于网络流媒体、下载的电影和音乐视频。 在MP4v2库中,"Version.rc"文件是资源脚本文件,用于定义程序的版本信息。这...
此压缩包包含的是该书的上、下两部分的源程序和代码,这部分我们重点关注的是"part1"。下面将详细探讨这个资源中涉及的Windows程序设计相关知识点。 1. **Windows编程基础**: - **API函数**:Windows API是开发...
接下来,我们关注到“Synchronization (Part 1)”这一文件,它可能涉及到多线程环境下的同步问题。在并发编程中,当多个线程同时访问共享资源时,同步机制确保数据的一致性和避免竞态条件。常见的同步原语有锁(如...
- **文件读取**: 使用`os`模块遍历指定目录下的所有EML文件。 - **邮件解析**: 利用`email`库解析EML文件,提取出邮件的内容部分。 - **数据清洗**: 清洗邮件内容,去除无关字符和格式,便于后续的数据处理。 - **...
11.5.5 用ReadFile发送数据包 362 11.6 在内核态完成功能的实现 363 11.6.1 请求的分发与实现 363 11.6.2 等待设备绑定完成与指定设备名 364 11.6.3 指派设备的完成 365 11.6.4 处理读请求 368 11.6.5 处理写请求 ...
11.5.5 用ReadFile发送数据包 362 11.6 在内核态完成功能的实现 363 11.6.1 请求的分发与实现 363 11.6.2 等待设备绑定完成与指定设备名 364 11.6.3 指派设备的完成 365 11.6.4 处理读请求 368 11.6.5 处理写请求 ...
2. 文件流:fs模块还提供了一种流API,如`fs.createReadStream()`和`fs.createWriteStream()`,它们可以高效地处理大文件,因为数据不是一次性读取或写入,而是分块处理。这对处理视频、音频等大型文件特别有用。 3...
$file_list = ['part1.mp4', 'part2.mp4', 'part3.mp4']; // 分片文件列表 $m3u8_content = '#EXTM3U\n'; foreach ($file_list as $file) { $m3u8_content .= "#EXTINF:-1,\n"; $m3u8_content .= $file . "\n"; } ...
11.5.5 用ReadFile发送数据包 362 11.6 在内核态完成功能的实现 363 11.6.1 请求的分发与实现 363 11.6.2 等待设备绑定完成与指定设备名 364 11.6.3 指派设备的完成 365 11.6.4 处理读请求 368 11.6.5 处理写请求 ...
11.5.5 用ReadFile发送数据包 362 11.6 在内核态完成功能的实现 363 11.6.1 请求的分发与实现 363 11.6.2 等待设备绑定完成与指定设备名 364 11.6.3 指派设备的完成 365 11.6.4 处理读请求 368 11.6.5 处理写请求 ...
11.5.5 用ReadFile发送数据包 362 11.6 在内核态完成功能的实现 363 11.6.1 请求的分发与实现 363 11.6.2 等待设备绑定完成与指定设备名 364 11.6.3 指派设备的完成 365 11.6.4 处理读请求 368 11.6.5 处理写请求 ...
11.5.5 用ReadFile发送数据包 362 11.6 在内核态完成功能的实现 363 11.6.1 请求的分发与实现 363 11.6.2 等待设备绑定完成与指定设备名 364 11.6.3 指派设备的完成 365 11.6.4 处理读请求 368 11.6.5 处理写请求 ...
11.5.5 用ReadFile发送数据包 362 11.6 在内核态完成功能的实现 363 11.6.1 请求的分发与实现 363 11.6.2 等待设备绑定完成与指定设备名 364 11.6.3 指派设备的完成 365 11.6.4 处理读请求 368 11.6.5 处理写请求 ...
1. **读取PE文件**:使用Windows API函数(如`CreateFile`, `ReadFile`等)打开并读取目标DLL文件。 2. **解析PE文件**:通过解析PE文件头中的信息,找到Import Table(导入表)的位置。 3. **查找API函数地址**:...
例如,`MP4FileHandle`是与MP4文件交互的核心接口,通过`MP4ReadFile`函数打开文件;`MP4GetMovieTimeScale`可以获取电影的时间比例,这对于时间同步至关重要;`MP4GetTrackId`用于查找特定轨道的ID,而`MP4...
7. **文件操作**:使用CreateFile、ReadFile和WriteFile等API进行文件的打开、读取和写入。 8. **进程与线程**:理解Windows中的进程和线程概念,创建和管理线程,以及同步线程间操作。 9. **对话框程序**:创建和...