一段nt下不用驱动进入ring0层的C代码,寻高手转成Delphi(100分)

  • 主题发起人 主题发起人 ypy
  • 开始时间 开始时间
Y

ypy

Unregistered / Unconfirmed
GUEST, unregistred user!
代码:
extern "C" {
#include "ntddk.h"
}

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

#define ENTERRING0   _asm pushad /
                     _asm pushf /
                     _asm cli

#define LEAVERING0   _asm popf /
                     _asm popad  /
                     _asm retf

typedef struct gdtr {
        unsigned short Limit;
        unsigned short BaseLow;
        unsigned short BaseHigh;
} Gdtr_t, *PGdtr_t;

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;



void PrintWin32Error( DWORD ErrorCode )
{
	LPVOID lpMsgBuf;
 
	FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
					NULL, ErrorCode, 
					MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
					(LPTSTR) &lpMsgBuf, 0, NULL );
	printf("%s/n", lpMsgBuf );
	LocalFree( lpMsgBuf );
}

ULONG MiniMmGetPhysicalAddress(ULONG virtualaddress)
{
    if(virtualaddress<0x80000000||virtualaddress>=0xA0000000)
       return 0;
    return virtualaddress&0x1FFFF000;
}

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);
}

BOOL ExecRing0Proc(ULONG Entry,ULONG seglen)
{
   Gdtr_t gdt;
   __asm sgdt gdt;
     
   ULONG mapAddr=MiniMmGetPhysicalAddress(gdt.BaseHigh<<16U|gdt.BaseLow);
   if(!mapAddr) return 0;

   HANDLE   hSection=NULL;
   NTSTATUS status;
   OBJECT_ATTRIBUTES        objectAttributes;
   UNICODE_STRING objName;
   CALLGATE_DESCRIPTOR *cg;

   status = STATUS_SUCCESS;
   
   RtlInitUnicodeString(&objName,L"//Device//PhysicalMemory");

   InitializeObjectAttributes(&objectAttributes,
                              &objName,
                              OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                              NULL,
                             (PSECURITY_DESCRIPTOR) NULL);

   status = ZwOpenSection(&hSection,SECTION_MAP_READ|SECTION_MAP_WRITE,&objectAttributes);

   if(status == STATUS_ACCESS_DENIED){
      status = ZwOpenSection(&hSection,READ_CONTROL|WRITE_DAC,&objectAttributes);
      SetPhyscialMemorySectionCanBeWrited(hSection);
      ZwClose(hSection);
      status =ZwOpenSection(&hSection,SECTION_MAP_WRITE|SECTION_MAP_WRITE,&objectAttributes);
   }

   if(status != STATUS_SUCCESS)
     {
        printf("Error Open PhysicalMemory Section Object,Status:%08X/n",status);
        return 0;
     }
      
   PVOID BaseAddress;

   BaseAddress=MapViewOfFile(hSection,
                 FILE_MAP_READ|FILE_MAP_WRITE,
                 0,
                 mapAddr,    //low part
                 (gdt.Limit+1));

   if(!BaseAddress)
      {
         printf("Error MapViewOfFile:");
         PrintWin32Error(GetLastError());
         return 0;
      }

   BOOL setcg=FALSE;

   for(cg=(CALLGATE_DESCRIPTOR *)((ULONG)BaseAddress+(gdt.Limit&0xFFF8));(ULONG)cg>(ULONG)BaseAddress;cg--)
       if(cg->type == 0){
         cg->offset_0_15 = LOWORD(Entry);
         cg->selector = 8;
         cg->param_count = 0;
         cg->some_bits = 0;
         cg->type = 0xC;          // 386 call gate
         cg->app_system = 0;      // A system descriptor
         cg->dpl = 3;             // Ring 3 code can call
         cg->present = 1;
         cg->offset_16_31 = HIWORD(Entry);
         setcg=TRUE;
         break;
      }

   if(!setcg){
        ZwClose(hSection);
        return 0;
   }

   short farcall[3];

   farcall[2]=((short)((ULONG)cg-(ULONG)BaseAddress))|3;  //Ring 3 callgate;

   if(!VirtualLock((PVOID)Entry,seglen))
      {
         printf("Error VirtualLock:");
         PrintWin32Error(GetLastError());
         return 0;
      }

   SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);

   Sleep(0);

   _asm call fword ptr [farcall]

   SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL);

   VirtualUnlock((PVOID)Entry,seglen);

   //Clear callgate
   *(ULONG *)cg=0;
   *((ULONG *)cg+1)=0;

   ZwClose(hSection);
   return TRUE;

}

struct _RING0DATA
{
    DWORD mcr0,mcr2,mcr3;
    unsigned short BaseMemory;
    unsigned short ExtendedMemory;
}r0Data;

void __declspec (naked) Ring0Proc1()
{
       ENTERRING0;
	_asm {
		mov eax, cr0
		mov r0Data.mcr0, eax;
		mov eax, cr2
		mov r0Data.mcr2, eax;
		mov eax, cr3
		mov r0Data.mcr3, eax;
	}
       LEAVERING0;
}

void __declspec (naked) Ring0Proc2()
{
        ENTERRING0;
	outp( 0x70, 0x15 );
      
        _asm 
           {
             mov ax,0
             in al,71h
             mov r0Data.BaseMemory,ax
           }
       
	outp( 0x70, 0x16 );
	r0Data.BaseMemory += inp(0x71) << 8;
	outp( 0x70, 0x17 );
	r0Data.ExtendedMemory = inp( 0x71 ); 
	outp( 0x70, 0x18 );
	r0Data.ExtendedMemory += inp(0x71) << 8;
        LEAVERING0;
}

void main(void)
{
   ZeroMemory(&r0Data,sizeof(struct _RING0DATA));
   VirtualLock((PVOID)&r0Data,sizeof(struct _RING0DATA));
   ExecRing0Proc((ULONG)Ring0Proc1,0x100);
   ExecRing0Proc((ULONG)Ring0Proc2,0x100);
   VirtualUnlock((PVOID)&r0Data,sizeof(struct _RING0DATA));
   printf("CR0             = %x/n", r0Data.mcr0);
   printf("CR2             = %x/n", r0Data.mcr2);
   printf("CR3             = %x/n", r0Data.mcr3);
   printf("Base memory     = %dK/n", r0Data.BaseMemory);
   printf("Extended memory = %dK/n", r0Data.ExtendedMemory);
}
 
买书或下载去吧 书名叫 Delphi下深入Windows核心编程
里面有详细介绍 2000 98都有介绍
随书原码
2000下用了个控件 有源码 这是个变速器 2000下的

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses UnitPortTalk;

{$R *.DFM}

procedure Speed(count:word);
begin
if not OpenPortTalk then exit;
outportb($43,$34); {写入8253控制寄存器,设置写0号定时器}
outportb($40,lo(count)); {写定时值低位}
outportb($40,hi(count)); {写定时值高位}
ClosePortTalk;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Speed($6000); //慢
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Speed($2ea5);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Speed($500); //快
end;

end.

unit UnitPortTalk;

interface

uses
Windows, SysUtils, Dialogs,WinSvc;

const
PORTTALK_TYPE = 40000; { 32768-65535是保留给用户使用的}
METHOD_BUFFERED = 0;
FILE_ANY_ACCESS = 0;
IOCTL_IOPM_RESTRICT_ALL_ACCESS = PORTTALK_TYPE shl 16 +
$900 shl 2 +
METHOD_BUFFERED +
FILE_ANY_ACCESS shl 14;

IOCTL_IOPM_ALLOW_EXCUSIVE_ACCESS = PORTTALK_TYPE shl 16 +
$901 shl 2 +
METHOD_BUFFERED +
FILE_ANY_ACCESS shl 14;


IOCTL_SET_IOPM = PORTTALK_TYPE shl 16 +
$902 shl 2 +
METHOD_BUFFERED +
FILE_ANY_ACCESS shl 14;

IOCTL_ENABLE_IOPM_ON_PROCESSID = PORTTALK_TYPE shl 16 +
$903 shl 2 +
METHOD_BUFFERED +
FILE_ANY_ACCESS shl 14;

IOCTL_READ_PORT_UCHAR = PORTTALK_TYPE shl 16 +
$904 shl 2 +
METHOD_BUFFERED +
FILE_ANY_ACCESS shl 14;

IOCTL_WRITE_PORT_UCHAR = PORTTALK_TYPE shl 16 +
$905 shl 2 +
METHOD_BUFFERED +
FILE_ANY_ACCESS shl 14;

function OpenPortTalk:boolean;
procedure ClosePortTalk;
procedure outportb(PortAddress:word;byte1:byte);
function inportb(PortAddress:word):byte;

function StartPortTalkDriver:boolean;
procedure InstallPortTalkDriver;

var
PortTalk_Handle:THANDLE; {PortTalk句柄}

implementation


procedure outportb(PortAddress:word;byte1:byte);
var
error:boolean;
BytesReturned:DWORD;
Buffer:array[0..2]of byte;
pBuffer:pword;
begin
pBuffer := pword(@Buffer[0]);
pBuffer^ := PortAddress;
Buffer[2] := byte1;

error := DeviceIoControl(PortTalk_Handle,
Cardinal(IOCTL_WRITE_PORT_UCHAR),
@Buffer,
3,
nil,
0,
BytesReturned,
nil);

if (not error) then showmessagefmt('从PortTalk输出端口数据时出错:%d',[GetLastError]);
end;

function inportb(PortAddress:word):byte;
var
error:boolean;
BytesReturned:DWORD;
Buffer:array[0..2]of byte;
pBuffer:pword;
begin
pBuffer := pword(@Buffer[0]);
pBuffer^ := PortAddress;

error := DeviceIoControl(PortTalk_Handle,
cardinal(IOCTL_READ_PORT_UCHAR),
@Buffer,
2,
@Buffer,
1,
BytesReturned,
nil);

if (not error) then showmessagefmt('从PortTalk输入端口数据时出错:%d',[GetLastError]);
result:=Buffer[0];
end;

function OpenPortTalk:boolean;
begin
{打开PortTalk,如果不能打开,则安装它}
PortTalk_Handle := CreateFile('//./PortTalk',
GENERIC_READ,
0,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);

if(PortTalk_Handle = INVALID_HANDLE_VALUE) then
begin
{启动驱动程序}
StartPortTalkDriver;
{再次打开PortTalk}
PortTalk_Handle := CreateFile('//./PortTalk',
GENERIC_READ,
0,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);

if(PortTalk_Handle = INVALID_HANDLE_VALUE) then
begin
showmessage('PortTalk: 不能存取PortTalk,请确保驱动程序已安装。');
result:=false;
exit;
end;
end;
result:=true;
end;

procedure ClosePortTalk;
begin
CloseHandle(PortTalk_Handle);
end;

function StartPortTalkDriver:boolean;
type
TNewStartService=function (hService: SC_HANDLE; dwNumServiceArgs: DWORD;
lpServiceArgVectors: PPChar): BOOL; stdcall;
var
SchSCManager:SC_HANDLE;
schService:SC_HANDLE;
ret:BOOL;
err:DWORD;
begin

{打开Service Control Manager}
SchSCManager := OpenSCManager (nil, { 机器 (nil = 本机) }
nil, { 数据库 (nil = 默认 }
SC_MANAGER_ALL_ACCESS); { 访问权 }

if (SchSCManager = 0) then
if (GetLastError = ERROR_ACCESS_DENIED) then
begin
{ 没有权限打开SCM管理,必须是poor用户}
showmessage('PortTalk: 没有权限访问Service Control Manager,'#$D#$A+
'不能安装和启动PortTalk,请使用超级用户来安装。');
result:=false;
exit;
end;

repeat begin
{打开PortTalk服务数据库}
schService := OpenService(SchSCManager, {服务数据库句柄}
'PortTalk', {要启动的服务名}
SERVICE_ALL_ACCESS); {存取的权限}

if (schService = 0) then
case (GetLastError) of
ERROR_ACCESS_DENIED:
begin
showmessage('PortTalk: 没有权限访问PortTalk服务数据库');
result:=false;
exit;
end;
ERROR_INVALID_NAME:
begin
showmessage('PortTalk: 指定的服务名无效');
result:=false;
exit;
end;
ERROR_SERVICE_DOES_NOT_EXIST:
begin
showmessage('PortTalk: PortTalk驱动程序不存在');
InstallPortTalkDriver;
end;
end;
end until (schService <> 0);

{启动PortTalk驱动程序,如果发生错误,一般是由于PortTalk.SYS不存在。}

ret := TNewStartService(@StartService) (schService, {服务标识}
0, {参数个数}
nil); {参数}

if (ret) then //showmessage('PortTalk: PortTalk安装成功!')
else begin
err := GetLastError;
if (err = ERROR_SERVICE_ALREADY_RUNNING) then
showmessage('PortTalk: PortTalk已经安装')
else begin
showmessage('PortTalk: 启动PortTalk时发生未知错误。'+#$D#$A+
'PortTalk.SYS没有放入/System32/Drivers目录吗?');
result:=false;
exit;
end;
end;

{关闭Service Control Manager}
CloseServiceHandle (schService);
result:=TRUE;
end;

procedure InstallPortTalkDriver;
var
SchSCManager:SC_HANDLE;
schService:SC_HANDLE;
err:DWORD;
DriverFileName:array[0..79]of CHAR;
begin
if (GetSystemDirectory(DriverFileName, 55)=0) then
begin
showmessage('PortTalk: 取System目录出错');
exit;
end;

{加入驱动程序文件名}
lstrcat(DriverFileName,'/Drivers/PortTalk.sys');
showmessagefmt('PortTalk: 拷贝驱动程序到%s',[DriverFileName]);

{拷贝驱动程序到System32/drivers目录,如果出错,一般是因为文件不存在。}

if (not CopyFile('PortTalk.sys', DriverFileName, FALSE)) then
begin
showmessagefmt('PortTalk: 拷贝驱动程序到以下位置出错:%s'+#$D#$A+
'请手工拷贝到system32/driver目录',
[DriverFileName]);
exit;
end;

{打开Service Control Manager}
SchSCManager := OpenSCManager (nil, { 机器 (nil = 本机) }
nil, { 数据库 (nil = 默认 }
SC_MANAGER_ALL_ACCESS); { 访问权 }

schService := CreateService (SchSCManager, { SCManager数据库 }
'PortTalk', { 服务个数 }
'PortTalk', { 显示名 }
SERVICE_ALL_ACCESS, { 权限 }
SERVICE_KERNEL_DRIVER, { 服务类别 }
SERVICE_DEMAND_START, { 启动类别 }
SERVICE_ERROR_NORMAL, { 出错控件类别 }
'System32/Drivers/PortTalk.sys', { 服务二进制文件 }
nil, { 加入的组 }
nil, { 标识 }
nil, { 隶属 }
nil, { 本地帐户 }
nil { 密码 }
);

if (schService = 0) then
begin
err := GetLastError;
if (err = ERROR_SERVICE_EXISTS) then
showmessage('PortTalk: 驱动程序不存在。')
else showmessage('PortTalk:建立服务时发生未知的错误。');
end
else showmessage('PortTalk: 成功安装!');

{ 关闭Service Control Manager }
CloseServiceHandle (schService);
end;
end.

 
这段代码进入ring0层还是用的驱动,我想不用驱动,用delphi直接进入ring0层。
 
你想做什么呢
 
接受答案了.
 
后退
顶部