首页
社区
课程
招聘
[绝对爆料]NTRing3级下使用API直接读写硬盘[原创]
发表于: 2006-8-31 18:05 13331

[绝对爆料]NTRing3级下使用API直接读写硬盘[原创]

2006-8-31 18:05
13331
相信此贴一出,NT下的操作硬盘软件会满天飞,试问,如果简简单单使用一个API函数就可以读写硬盘,还会有人抱着Windows的DDK去编驱动吗?
  而今Windows对各类资源的保护可以说是无孔不入,Windows 为实现其可靠性,严格将系统划分为内核模式与用户模式,在i386系统中分别对应CPU的Ring0与Ring3级别,在Ring3级下执行的程序是不可能直接访问到硬件的。就以读写硬盘的扇区来说吧,在9X下还可以使用INT中断来读取,但是在NT下只有进入了Ring0级才可对硬盘进行操作,而进入Ring0级的方法有:设备驱动程序,中断门,调用门等等。但是今天我们要说的是在NT下Ring3级下使用API直接读写扇区。如果不相信请跟我来!
  今天API函数的主角就是CreateFile。看到这里大家有可能想拿鸡蛋扔我了,CreateFile怎么能和硬盘有关系呢。起初我也难以相信,就像我大一学习C语言时,老师告诉我fprintf,printf都是向一个文件进行输出时,我在台下也想扔他。但事实确实如此,Windows将所以的资源都看成文件,无论是真正存储在硬盘上的文件还是硬件(硬盘,显示器等)。在这里不得不佩服Windows的创新理念,文件管理一向是Windows的核心之一。在这里我是没有能力给大家讲述文件管理的,我们打开Win32Help找到CreateFile:

HANDLE CreateFile(

    LPCTSTR lpFileName,        // pointer to name of the file
    DWORD dwDesiredAccess,        // access (read-write) mode
    DWORD dwShareMode,        // share mode
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,        // pointer to security attributes
    DWORD dwCreationDistribution,        // how to create
    DWORD dwFlagsAndAttributes,        // file attributes
    HANDLE hTemplateFile         // handle to file with attributes to copy  
   );
  大家注意第一个参数的说明:
    lpFileName

      Points to a null-terminated string that specifies the name of the object (file, pipe, mailslot, communications resource, disk device, console, or directory) to create or open.

      If *lpFileName is a path, there is a default string size limit of MAX_PATH characters. This limit is related to how the CreateFile function parses paths.

      Windows NT: You can use paths longer than MAX_PATH characters by calling the wide (W) version of CreateFile and prepending "\\?\" to the path. The "\\?\" tells the function to turn off path parsing. This lets you use paths that are nearly 32,000 Unicode characters long. You must use fully-qualified paths with this technique. This also works with UNC names. The "\\?\" is ignored as part of the path. For example, "\\?\C:\myworld\private" is seen as "C:\myworld\private", and "\\?\UNC\tom_1\hotstuff\coolapps" is seen as "\\tom_1\hotstuff\coolapps".
  上面的意思大概是说"\\?\"可以引用路径(英语垃圾,大家最好自己看)。
  尤其是下面的这一段:
    Disk Devices
    Windows NT: You can use the CreateFile function to open a disk drive or a partition on a disk drive. The function returns a handle to the disk device; that handle can be used with the DeviceIOControl function. The following requirements must be met in order for such a call to succeed:

    The caller must have administrative privileges for the operation to succeed on a hard disk drive.
   
    The lpFileName string should be of the form \\.\PHYSICALDRIVEx to open the hard disk x. Hard disk numbers start at zero.For example:

    String                    Meaning
    \\.\PHYSICALDRIVE2            Obtains a handle to the third physical drive on the user's computer.

    The lpFileName string should be \\.\x: to open a floppy drive x or a partition x on a hard disk.For example:

    String        Meaning
    \\.\A:        Obtains a handle to drive A on the user's computer.
    \\.\C:        Obtains a handle to drive C on the user's computer.
  没有骗大家吧,上面说如果你拥有管理员权限,那么lpFileName ==\\.\PHYSICALDRIVE2就是表示打开第三块硬盘,\\.\PHYSICALDRIVE0指的就是第一块硬盘了。lpFileName ==\\.\C:就是打开C盘了。并且返回的句柄还可以用于DeviceIOControl函数,相信大家看到这里应该放下手中的鸡蛋了吧。
  由此可以管中窥豹Windows文件管理这个核心是多么的强大。希望对大家有所帮助。

{另附上一段演示读硬盘第一扇区 保存为 Project1.dpr WinXP+Delphi7编译通过}
program Project1;

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

{$R *.RES}

const
  BytesPerSector =512;
  SectorCount =1;
  SectorStart =0;
  drive ='\\.\PHYSICALDRIVE0';

var
  str :string;
  p :pchar;
  i :Cardinal;
  hDeviceHandle :Thandle;

begin                        
  hDeviceHandle := CreateFile(drive, GENERIC_READ,
    FILE_SHARE_READ OR FILE_SHARE_WRITE, nil, OPEN_EXISTING,0, 0);
  if (hDeviceHandle <> INVALID_HANDLE_VALUE) then
  begin
    p:=allocmem(SectorCount*BytesPerSector);

    FileSeek(hDevicehandle,SectorStart*BytesPerSector,0);
    if FileRead(hDevicehandle,p[0],SectorCount*BytesPerSector)<>SectorCount*BytesPerSector then
       raise exception.create('读取错误');

    str:='';
    for i:=0 to 512-1 do
    begin
      if i mod 16=0 then
      str:=str+format('0x%.8x ',[i]);
      str:=str+format('  %.2x',[integer(p[i])]);
      if i mod 16=15 then
      str:=str+#13#10;
    end;
    ShowMessage( str);

    freemem(p,SectorCount*BytesPerSector);
    closehandle(hDeviceHandle);
  end;
end.
{END}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (17)
雪    币: 329
活跃值: (343)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
2
这个让我说什么好呢……
2006-8-31 19:00
0
雪    币: 117
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
http://developer.51cto.com/art/200511/11137.htm

http://developer.51cto.com/art/200511/11137.htm

http://www.csdn.net/develop/article/22/22762.shtm

http://www.twt.edu.cn/netclass/computer/textinfo.php?myid=371

不好意思,我只找了这几个,更多的大家自己找下。
2006-8-31 19:22
0
雪    币: 254
活跃值: (126)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
纯属巧合
2006-8-31 19:59
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
5
最初由 doskey 发布
这个让我说什么好呢……


你就说这么高级的技术,把微软都淘汰了。
2006-8-31 20:32
0
雪    币: 253
活跃值: (250)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
6
听说有这么回事儿,一直不知道怎么操作。
2006-9-1 20:49
0
雪    币: 1309
活跃值: (232)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
早就用过拉, 还用它写过工具结合手工, 恢复硬盘分区
2006-9-3 10:24
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
8
用VC实现改编了下,发现确实好用
真不懂这属于BUG,还是MS故意留一线

#include <windows.h>
#include <stdio.h>

const UINT uSectorSize	= 512 ;
const UINT uBegSector	= 0 ;
const UINT uSectorNum	= 1 ;

const UINT uReadSize	= uSectorSize * uSectorNum ;

BYTE bBuffer[uReadSize] = {0} ;
const char pDiskPath[] = "\\\\.\\PHYSICALDRIVE0" ;

void ShowByteInform ( PBYTE pBuf, UINT uSize )
{
	for ( UINT i = 1 ; i <= uSize; i++ )
	{
		printf ( " %02X", pBuf[i-1] ) ;
		if ( i % 16 == 0 )
			printf ( "\n" ) ;
		else if ( i % 8 == 0 )
			printf ( " " ) ;
	}
}

int main()
{
	HANDLE hDisk ;
	__try {
		
		hDisk = CreateFile ( pDiskPath, GENERIC_READ, \
			FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ) ;
		if ( hDisk == INVALID_HANDLE_VALUE )
		{
			MessageBox ( 0, "磁盘打开错误!", 0, 0 ) ;
			return 0;
		}
		
		SetFilePointer ( hDisk, uBegSector * uSectorSize, 0, FILE_BEGIN ) ;
		DWORD dwReadByte ;
		ReadFile ( hDisk, (LPVOID)bBuffer, uReadSize, &dwReadByte, NULL ) ;
		if ( dwReadByte == 0 )
		{
			MessageBox ( 0, "磁盘读取错误!", 0, 0 ) ;
			return 0;
		}
		
		ShowByteInform ( bBuffer, uReadSize ) ;
	}
	__finally {
		CloseHandle ( hDisk ) ;
	}
	return 0;
}
2006-9-8 19:11
0
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
虽然很多人知道,但是如果这个是楼主自己单独发现的话,那很佩服楼主的思维。正所谓学无前后。重复的例子比比皆是,但是只要是自己想出来的就应该赞一个。
2006-9-9 12:37
0
雪    币: 234
活跃值: (104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
这个,岂不是普通用户变administrator很容易了!
2006-9-12 17:47
0
雪    币: 291
活跃值: (213)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
11
最初由 北极星2003 发布
用VC实现改编了下,发现确实好用
真不懂这属于BUG,还是MS故意留一线

[CODE]
#include <windows.h>
........

大概只有以管理员账户登陆才可以吧
否则这个Bug早该被发现了
2006-9-12 18:43
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
12
不是BUG,楼主的文章摘自MSDN。
2006-9-12 21:45
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
13
最初由 yanjun 发布
相信此贴一出,NT下的操作硬盘软件会满天飞,试问,如果简简单单使用一个API函数就可以读写硬盘,还会有人抱着Windows的DDK去编驱动吗?


一点也不惊讶, winhex早就可以读写硬盘,不信可以下载一个去看看
2006-9-13 18:32
0
雪    币: 238
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
14
这个方法一直都有人使用的,例如大部分软件读取硬盘参数所使用的就是这个方法。
2006-9-13 23:12
0
雪    币: 225
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
15
感谢各位大侠的批评和指正!小弟纯属菜鸟一个,有什么不对的地方还望各位大侠多多指点!
2006-9-14 18:22
0
雪    币: 77
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
中国人早就知道了
2006-9-21 15:38
0
雪    币: 290
活跃值: (645)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
只在administrator或等同身份下使用!
2006-9-24 23:35
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
试了试,好像不能读MBR
写我不敢试
大家看看情况跟我一样吗
Windows 2000 SP4

int 3
                invoke CreateFile,CTXT("\\.\PHYSICALDRIVE0"),GENERIC_READ,FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
                mov hPhy,eax
                ;invoke SetFilePointer,eax,1234567,0,FILE_BEGIN
                invoke ReadFile,hPhy,offset buff,512,ADDR JuNk,NULL
                int 3
2006-10-15 14:21
0
游客
登录 | 注册 方可回帖
返回
//