- #include <stdio.h>
- #include <stdlib.h>
- #include <tchar.h>
- #include <windows.h>
- #pragma pack(1)
- #define MAX_MBR_PARTITIONS 4
- #define MBR_DISK_SIGNATURE_OFFSET 440
- #define MBR_DISK_PPT_OFFSET 446
- #define MBR_SIGNATURE_OFFSET 510
- //
- // MBR Partition Entry
- //
- typedef struct {
- UINT8 BootIndicator;
- UINT8 StartHead;
- UINT8 StartSector;
- UINT8 StartTrack;
- UINT8 OSType;
- UINT8 EndHead;
- UINT8 EndSector;
- UINT8 EndTrack;
- UINT32 StartingLBA;
- UINT32 SizeInLBA;
- } MBR_PARTITION_RECORD;
- //
- // MBR Partition table
- //
- typedef struct {
- UINT8 BootCode[440];
- UINT32 UniqueMbrSignature;
- UINT16 Unknown;
- MBR_PARTITION_RECORD PartitionRecord[MAX_MBR_PARTITIONS];
- UINT16 Signature;
- } MASTER_BOOT_RECORD;
- #pragma pack()
- #define MBR_SIGNATURE 0xAA55
- #define EXTENDED_DOS_PARTITION 0x05
- #define EXTENDED_WINDOWS_PARTITION 0x0F
- BOOL ReadMBR(LPVOID *pBuffer)
- {
- HANDLE hDevice;
- DWORD dwSize;
- DWORD dwOverRead;
- BOOL bRet = TRUE;
- hDevice = CreateFile(TEXT("\\\\.\\PhysicalDrive2"),
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL);
- if (hDevice == INVALID_HANDLE_VALUE) {
- printf("Open \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
- return FALSE;
- }
- if (!DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL)) {
- CloseHandle(hDevice);
- printf("FSCTL_LOCK_VOLUME \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
- return FALSE;
- }
- DISK_GEOMETRY Geometry;
- if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &Geometry, sizeof(DISK_GEOMETRY), &dwSize, NULL)) {
- bRet = FALSE;
- printf("IOCTL_DISK_GET_DRIVE_GEOMETRY \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
- goto _out;
- }
- *pBuffer = (LPVOID)GlobalAlloc(GPTR, Geometry.BytesPerSector);
- if (*pBuffer) {
- if (!ReadFile(hDevice, *pBuffer, Geometry.BytesPerSector, &dwOverRead, NULL)) {
- printf("ReadFile \\\\.\\PhysicalDrive0 %u bytes failed. Error=%u\n", Geometry.BytesPerSector, GetLastError());
- bRet = FALSE;
- }
- }
- _out:
- DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
- CloseHandle(hDevice);
- return bRet;
- }
- BOOL WriteMBR(LPVOID pBuffer, DWORD nNumberOfBytesToWrite)
- {
- HANDLE hDevice;
- DWORD dwBytesReturned = 0;
- DWORD dwNumberOfBytesWritten = 0;
- BOOL bRet = TRUE;
- if (!pBuffer || IsBadReadPtr(pBuffer, nNumberOfBytesToWrite)){
- return FALSE;
- }
- hDevice = CreateFile(TEXT("\\\\.\\PhysicalDrive2"),
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL);
- if (hDevice == INVALID_HANDLE_VALUE) {
- printf("Open \\\\.\\PhysicalDrive2 failed. Error=%u\n", GetLastError());
- return FALSE;
- }
- if (!DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL)) {
- CloseHandle(hDevice);
- printf("FSCTL_LOCK_VOLUME \\\\.\\PhysicalDrive2 failed. Error=%u\n", GetLastError());
- return FALSE;
- }
- DISK_GEOMETRY pdg;
- if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &pdg, sizeof(DISK_GEOMETRY), &dwBytesReturned, NULL)) {
- bRet = FALSE;
- printf("IOCTL_DISK_GET_DRIVE_GEOMETRY \\\\.\\PhysicalDrive2 failed. Error=%u\n", GetLastError());
- goto _out;
- }
- printf("Write %u bytes to \\\\.\\PhysicalDrive2\n", pdg.BytesPerSector);
- if (nNumberOfBytesToWrite != pdg.BytesPerSector) {
- bRet = FALSE;
- printf("\\\\.\\PhysicalDrive2 nNumberOfBytesToWrite %u != BytesPerSector %u.\n",
- nNumberOfBytesToWrite, pdg.BytesPerSector);
- goto _out;
- }
- if (!WriteFile(hDevice, pBuffer, pdg.BytesPerSector, &dwNumberOfBytesWritten, NULL)) {
- printf("WriteFile \\\\.\\PhysicalDrive2 %u bytes failed. Error=%u\n", pdg.BytesPerSector, GetLastError());
- bRet = FALSE;
- }
- _out:
- DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
- CloseHandle(hDevice);
- return bRet;
- }
- int main(int argc, char **argv)
- {
- LPVOID lpMBRBuffer = NULL;
- UINT nIdx = 0x1BE;
- UINT nCnt = 0;
- UCHAR *pBuf = NULL;
- MASTER_BOOT_RECORD *lpMbr = NULL;
- if (ReadMBR(&lpMBRBuffer)){
- pBuf = (UCHAR *)lpMBRBuffer;
- lpMbr = (MASTER_BOOT_RECORD *)lpMBRBuffer;
- for (; nIdx < 0x1FE; nIdx ++){
- printf("%02X ", pBuf[nIdx]);
- nCnt ++;
- if (nCnt >= 0x10){
- nCnt = 0;
- printf("\n");
- }
- }
- for (nIdx = 0; nIdx < MAX_MBR_PARTITIONS; nIdx ++){
- printf("Part %u Type 0x%x\n", nIdx + 1, lpMbr->PartitionRecord[nIdx].OSType);
- }
- lpMbr->PartitionRecord[1].OSType = 0x5;
- WriteMBR(pBuf, sizeof(MASTER_BOOT_RECORD));
- GlobalFree(lpMBRBuffer);
- lpMBRBuffer = NULL;
- }
- printf("*******************************************\n");
- if (ReadMBR(&lpMBRBuffer)){
- pBuf = (UCHAR *)lpMBRBuffer;
- lpMbr = (MASTER_BOOT_RECORD *)lpMBRBuffer;
- nIdx = 0x1BE;
- nCnt = 0;
- for (; nIdx < 0x1FE; nIdx ++){
- printf("%02X ", pBuf[nIdx]);
- nCnt ++;
- if (nCnt >= 0x10){
- nCnt = 0;
- printf("\n");
- }
- }
- for (nIdx = 0; nIdx < MAX_MBR_PARTITIONS; nIdx ++){
- printf("Part %u Type 0x%x\n", nIdx + 1, lpMbr->PartitionRecord[nIdx].OSType);
- }
- GlobalFree(lpMBRBuffer);
- lpMBRBuffer = NULL;
- }
- return 0;
- }
编译
执行结果:
参考:
http://en.wikipedia.org/wiki/Master_boot_record
http://thestarman.pcministry.com/asm/mbr/index.html
http://en.wikipedia.org/wiki/Disk_partitioning
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363986(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363979(v=vs.85).aspx
读取硬盘的MBR引导扇区(Windows各系统通用)
原文:
http://bbs.fishc.com/thread-18255-1-1.html
http://bbs.fishc.com/thread-18256-1-1.html
-----------------------------------------------------------------------------------------------------------
知识普及:
硬盘的引导扇区位于 0 磁道 0 磁头 1 扇区位置,该扇区存放着系统的引导程序和硬盘的分区表等重要信息。另外小甲鱼八卦一下,该扇区常常是病毒的重点攻击目标!
实现要求:读取硬盘引导扇区并保存为boot.ini文件
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
实现原理:
上节课小甲鱼不是说会告诉大家如何在用户模式下直接访问硬盘么?嗯,而且承诺绝对简单通俗。好吧,事实上,硬盘内核驱动程序将硬盘作为一个文件,文件名为:"\\.\\physicaldrive0"
我们可以利用这个鲜为人知的文件名,通过 CreateFile, ReadFile, WriteFile 和 DeviceIoControl API 来进行访问硬盘。
代码及详细注释:
- ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- ; by 小甲鱼, http://www.fishc.com
- ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- ; 功能:读取硬盘引导扇区并保存于boot.ini文件中
- ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- .386
- .model flat,stdcall
- option casemap:none
- include windows.inc
- include comdlg32.inc
- include user32.inc
- include kernel32.inc
- includelib comdlg32.lib
- includelib user32.lib
- includelib kernel32.lib
- .data
- szFileName db '\\.\\physicaldrive0', 0 ; 硬盘设备名
- .data?
- szBuffer db 512 dup (?)
- @hFile dd ?
- @dwBytesRead dd ?
- @szLogFile db MAX_PATH dup (?)
- .const
- szNewFile db 'boot.ini', 0
- szErrOpenFile db '无法打开硬盘文件!', 0
- szErrCreateFile db '无法创建boot.ini文件!', 0
- szSuccess db '成功读取硬盘引导区并写入boot.ini文件!', 0
- szCaption db '鱼C工作室', 0
- .code
- start:
- invoke CreateFile, ; 打开或创建文件
- addr szFileName, ; 文件的名字
- GENERIC_READ, ; 允许读访问
- FILE_SHARE_READ, ; 允许对文件进行共享访问
- 0, ; 指向一个SECURITY_ATTRIBUTES结构的指针
- OPEN_EXISTING, ; 文件必须存在
- FILE_ATTRIBUTE_NORMAL, ; 默认属性
- 0
- .if eax == INVALID_HANDLE_VALUE ; 打开文件错误
- invoke MessageBox,
- NULL,
- addr szErrOpenFile,
- addr szCaption,
- MB_OK
- jmp exit
- .endif
- mov @hFile, eax ; 返回文件句柄,这时候硬盘被看成是一个文件的哦~
- invoke ReadFile, ; 从文件中读取数据
- @hFile, ; 文件句柄
- addr szBuffer, ; 用于保存读入数据的缓冲区
- sizeof szBuffer, ; 需要读入的字符数
- addr @dwBytesRead, ; 实际读入的字节数
- 0
- invoke CloseHandle, @hFile ; 小甲鱼温馨提醒:记得文件打开后要擦屁股->关闭文件,否则造成内存泄漏
- invoke lstrcpy, ; 拷贝字符串
- addr @szLogFile,
- addr szNewFile
- invoke CreateFile, ; 创建boot.ini文件
- addr @szLogFile,
- GENERIC_WRITE,
- FILE_SHARE_READ,
- 0,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- 0
- .if eax != INVALID_HANDLE_VALUE
- mov @hFile, eax
- invoke WriteFile, ; 将数据写入boot.ini文件
- @hFile,
- addr szBuffer,
- sizeof szBuffer,
- addr @dwBytesRead,
- 0
- invoke CloseHandle, @hFile ; 擦屁股
- invoke wsprintf, ; 这个事实上常用的函数,如果有问题的鱼油可以在论坛搜索下,有篇文章中小甲鱼已经做好了详细的解释给大家。
- addr szBuffer,
- addr szSuccess
- invoke MessageBox,
- NULL,
- addr szBuffer,
- addr szCaption,
- MB_OK
- .else
- invoke MessageBox,
- NULL,
- addr szErrCreateFile,
- addr szCaption,
- MB_OK
- .endif
- exit:
- invoke ExitProcess, NULL
- end start