怎么在WINDOWS下对CMOS进行读写?就是怎么去读/写CMOS用VISUAL C++ 6.0来做.DOS下的我知道,70和71端口,但WINDOWS编程本人一壳不同,请各位大狭多多指教了.
解决方案 »
- 请问怎样打开VC++的下面报错的窗口了?
- SQLGetDiagField函数中的SQL_DIAG_SS_LINE定义头文件是什么?
- 如何在窗体中的控件上绘BMP图
- c++,mysql,插入中文记录,乱码,经过一天半的搜索与寻找还是没有把问题搞清楚。
- 有谁有VC自带的TEST CONTAINER 的应用程序代码?
- 我在VC6下用MFC做的控件,在VC7下添加包装类,结果属性没了!
- 好奇怪的一个现象:为什么到处都找不到《win 32 程序员参考大全》?
- 大家来说一说,人人有分
- 为什么用exitwindowsex(1,9)不能关闭系统?若要修改特权级,adjusttokenprivileges怎么用?
- 新版论坛已经上线,欢迎帮忙测试,散分
- 请问 __stdcall和__cdecl的意义和用法
- 怎样使一个按钮按下后不弹起?
Port access under Windows 9x is possible as long as you refrain from accessing trapped ports. Several VxDs hook I/O ports to virtualize hardware and will block any attempt to modify these ports from a Windows application. If you wish to control a piece of hardware which is mapped to free addresses such as 300h, you can use the inp/outp functions with no fear. However, any attempt to access system ports (such as those reserved for the DMA chip, HD controller, etc.) will be to no avail. To control such ports from your application, you'll need to use the WinIo library which executes in ring 0 and bypasses Windows port trapping mechanism. Under Windows NT/2000, user mode applications are completely prohibited from accessing I/O ports. Any attempt to access an I/O port from a ring 3 application is terminated with a protection fault. Thus, the only way to overcome this limitation is by using a kernel-mode device driver, such as the one supplied with the WinIo library.
2.在Win2000下,您可以使用CreateFile()或ReadFile()读写70,71;
在Win2000下,您也可以使用楼上提供的WinIO,
address:http://www.internals.com/
Windows NT/2000下不用驱动的Ring0代码实现
WebCrazy(http://webcrazy.yeah.net/)
大家知道,Windows NT/2000为实现其可靠性,严格将系统划分为内核模式与用户模式,在i386系统中分别对应CPU的Ring0与Ring3级别。Ring0下,可以执行特权级指令,对任何I/O设备都有访问权等等。要实现从用户态进入核心态,即从Ring 3进入Ring 0必须借助CPU的某种门机制,如中断门、调用门等。而Windows NT/2000提供用户态执行系统服务(Ring 0例程)的此类机制即System Service的int 2eh中断服务等,严格的参数检查,只能严格的执行Windows NT/2000提供的服务,而如果想执行用户提供的Ring 0代码(指运行在Ring 0权限的代码),常规方法似乎只有编写设备驱动程序。本文将介绍一种在用户态不借助任何驱动程序执行Ring0代码的方法。
Windows NT/2000将设备驱动程序调入内核区域(常见的位于地址0x80000000上),由DPL为0的GDT项8,即cs为8时实现Ring 0权限。本文通过在系统中构造一个指向我们的代码的调用门(CallGate),实现Ring0代码。基于这个思路,为实现这个目的主要是构造自己的CallGate。CallGate由系统中叫Global Descriptor Table(GDT)的全局表指定。GDT地址可由i386指令sgdt获得(sgdt不是特权级指令,普通Ring 3程序均可执行)。GDT地址在Windows NT/2000保存于KPCR(Processor Control Region)结构中(见《再谈Windows NT/2000环境切换》)。GDT中的CallGate是如下的格式:
typedef struct
{
unsigned short offset_0_15;
unsigned short selector;
unsigned char param_count : 4;
unsigned char some_bits : 4;
unsigned char type : 4;
unsigned char app_system : 1;
unsigned char dpl : 2;
unsigned char present : 1;
unsigned short offset_16_31;
} CALLGATE_DESCRIPTOR;
GDT位于内核区域,一般用户态的程序是不可能对这段内存区域有直接的访问权。幸运的是Windows NT/2000提供了一个叫PhysicalMemory的Section内核对象位于\Device的路径下。顾名思义,通过这个Section对象可以对物理内存进行操作。用objdir.exe对这个对象分析如下:
C:\NTDDK\bin >objdir /D \Device
PhysicalMemory
Section
DACL -
Ace[ 0] - Grant - 0xf001f - NT AUTHORITY\SYSTEM
Inherit:
Access: 0x001F and ( D RCtl WOwn WDacl )
Ace[ 1] - Grant - 0x2000d - BUILTIN\Administrators
Inherit:
Access: 0x000D and ( RCtl )
从dump出的这个对象DACL的Ace可以看出默认情况下只有SYSTEM用户才有对这个对象的读写权限,即对物理内存有读写能力,而Administrator只有读权限,普通用户根本就没有权限。不过如果我们有Administrator权限就可以通过GetSecurityInfo、SetEntriesInAcl与SetSecurityInfo这些API来修改这个对象的ACE。这也是我提供的代码需要Administrator的原因。实现的代码如下:
VOID SetPhyscialMemorySectionCanBeWrited(HANDLE hSection)
{
PACL pDacl=NULL;
PACL pNewDacl=NULL;
PSECURITY_DESCRIPTOR pSD=NULL;
DWORD dwRes;
EXPLICIT_ACCESS ea;
if(dwRes=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,
NULL,NULL,&pDacl,NULL,&pSD)!=ERROR_SUCCESS)
{
printf( "GetSecurityInfo Error %u\n ", dwRes );
goto CleanUp;
}
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = SECTION_MAP_WRITE;
ea.grfAccessMode = GRANT_ACCESS;
ea.grfInheritance= NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
ea.Trustee.ptstrName = "CURRENT_USER ";
if(dwRes=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl)!=ERROR_SUCCESS)
{
printf( "SetEntriesInAcl %u\n ", dwRes );
goto CleanUp;
}
if(dwRes=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL)!=ERROR_SUCCESS)
{
printf( "SetSecurityInfo %u\n ",dwRes);
goto CleanUp;
}
CleanUp:
if(pSD)
LocalFree(pSD);
if(pNewDacl)
LocalFree(pSD);
}
这段代码对给定HANDLE的对象增加了如下的ACE:
PhysicalMemory
Section
DACL -
Ace[ 0] - Grant - 0x2 - WEBCRAZY\Administrator
Inherit:
Access: 0x0002 //SECTION_MAP_WRITE
这样我们在有Administrator权限的条件下就有了对物理内存的读写能力。但若要修改GDT表实现Ring 0代码。我们将面临着另一个难题,因为sgdt指令获得的GDT地址是虚拟地址(线性地址),我们只有知道GDT表的物理地址后才能通过\Device\PhysicalMemory对象修改GDT表,这就牵涉到了线性地址转化成物理地址的问题。我们先来看一看Windows NT/2000是如何实现这个的:
kd > u nt!MmGetPhysicalAddress l 30
ntoskrnl!MmGetPhysicalAddress:
801374e0 56 push esi
801374e1 8b742408 mov esi,[esp+0x8]
801374e5 33d2 xor edx,edx
801374e7 81fe00000080 cmp esi,0x80000000
801374ed 722c jb ntoskrnl!MmGetPhysicalAddress+0x2b (8013751b)
801374ef 81fe000000a0 cmp esi,0xa0000000
801374f5 7324 jnb ntoskrnl!MmGetPhysicalAddress+0x2b (8013751b)
801374f7 39153ce71780 cmp [ntoskrnl!MmKseg2Frame (8017e73c)],edx
801374fd 741c jz ntoskrnl!MmGetPhysicalAddress+0x2b (8013751b)
801374ff 8bc6 mov eax,esi
80137501 c1e80c shr eax,0xc
80137504 25ffff0100 and eax,0x1ffff
80137509 6a0c push 0xc
8013750b 59 pop ecx
8013750c e8d3a7fcff call ntoskrnl!_allshl (80101ce4)
80137511 81e6ff0f0000 and esi,0xfff
80137517 03c6 add eax,esi
80137519 eb17 jmp ntoskrnl!MmGetPhysicalAddress+0x57 (80137532)
8013751b 8bc6 mov eax,esi
8013751d c1e80a shr eax,0xa
80137520 25fcff3f00 and eax,0x3ffffc
80137525 2d00000040 sub eax,0x40000000
8013752a 8b00 mov eax,[eax]
8013752c a801 test al,0x1
8013752e 7506 jnz ntoskrnl!MmGetPhysicalAddress+0x44 (80137536)
80137530 33c0 xor eax,eax
80137532 5e pop esi
80137533 c20400 ret 0x4