分享
 
 
 

用Delphi在2000和XP/2003下从Ring3进入Ring0的无驱动解决方法by LYSoft LiuYang

王朝delphi·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

这段代码很有意义的父亲纪念版,它是在我一生人中最痛苦的时期所开发的。唉,一切都成为永恒的怀念......

需要JEDI Win32 API(JWA)库支持

uses

Windows, Dialogs, SysUtils, NTDDK,

JwaWinNT, JwaWinType, JwaNtStatus, JwaAccCtrl, JwaAclApi, ntdll;

const

KGDT_NULL = 0;

KGDT_R0_CODE = 8;

KGDT_R0_DATA = 16;

KGDT_R3_CODE = 24;

KGDT_R3_DATA = 32;

KGDT_TSS = 40;

KGDT_R0_PCR = 48;

KGDT_R3_TEB = 56;

KGDT_VDM_TILE = 64;

KGDT_LDT = 72;

KGDT_DF_TSS = 80;

KGDT_NMI_TSS = 88;

type

TGDT = record

Limit,

BaseLow,

BaseHigh : Word;

end;

PHYSICAL_ADDRESS = Large_Integer;

CALLGATE_DESCRIPTOR = record

Offset_0_15, Selector: Word;

GateDescriptor:Word;

Offset_16_31: Word;

end;

implementation

function ZwOpenSection; external 'ntdll.dll';

function ZwClose; external 'ntdll.dll';

function SetDebugPrivilege(CanDebug: boolean): Boolean;

function EnablePrivilege(hToken: Cardinal; PrivName: string; bEnable: Boolean): Boolean;

var

TP: Windows.TOKEN_PRIVILEGES;

Dummy: Cardinal;

begin

TP.PrivilegeCount := 1;

LookupPrivilegeValue(nil, pchar(PrivName), TP.Privileges[0].Luid);

if bEnable then

TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED

else TP.Privileges[0].Attributes := 0;

AdjustTokenPrivileges(hToken, False, TP, SizeOf(TP), nil, Dummy);

Result := GetLastError = ERROR_SUCCESS;

end;

var

hToken: Cardinal;

begin

OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);

Result := EnablePrivilege(hToken, SE_DEBUG_NAME, CanDebug);

CloseHandle(hToken);

end;

function SetPhyscialMemorySectionCanBeWrited(hSection: THandle): boolean;

label CleanUp;

var

pDacl, pNewDacl: JwaWinNT.PACL;

pSD: JwaWinNT.PSECURITY_DESCRIPTOR;

dwRes: DWORD;

ea: EXPLICIT_ACCESS;

begin

Result := false;

pDacl := nil; pNewDacl := nil; pSD := nil;

dwRes := GetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,

nil, nil, @pDacl, nil, pSD);

if dwRes <> ERROR_SUCCESS then

begin

MessageDlg(Format('GetSecurityInfo Error %d', [dwRes]), mtError, [mbOK], 0);

goto CleanUp;

end;

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';

dwRes := SetEntriesInAcl(1, @ea, pDacl, pNewDacl);

if dwRes <> ERROR_SUCCESS then

begin

MessageDlg(Format('SetEntriesInAcl Error : %d', [dwRes]), mtError, [mbOK], 0);

goto CleanUp;

end;

dwRes := SetSecurityInfo(hSection, SE_KERNEL_OBJECT,

DACL_SECURITY_INFORMATION, nil, nil, pNewDacl, nil);

if dwRes <> ERROR_SUCCESS then

begin

MessageDlg(Format('SetSecurityInfo Error : %d', [dwRes]), mtError, [mbOK], 0);

goto CleanUp;

end;

Result := true;

CleanUp:

if pSD<>nil then LocalFree(Cardinal(pSD));

if pNewDacl<>nil then LocalFree(Cardinal(pNewDacl));

end;

function OpenPhysicalMemory: THandle;

var

hSection : THandle;

status: NTSTATUS;

objName: UNICODE_STRING;

objectAttributes: OBJECT_ATTRIBUTES;

begin

Result := 0;

RtlInitUnicodeString(@objName, '\Device\PhysicalMemory');

InitializeObjectAttributes(@objectAttributes, @objName,

OBJ_CASE_INSENSITIVE or OBJ_KERNEL_HANDLE, 0, nil);

status := ZwOpenSection(hSection, SECTION_MAP_READ or SECTION_MAP_WRITE, @objectAttributes);

if (status = STATUS_ACCESS_DENIED) then

begin

status := ZwOpenSection(hSection, READ_CONTROL or WRITE_DAC, @objectAttributes);

if status = STATUS_SUCCESS then SetPhyscialMemorySectionCanBeWrited(hSection);

ZwClose(hSection);

status := ZwOpenSection(hSection, SECTION_MAP_READ or SECTION_MAP_WRITE, @objectAttributes);

end;

if status = STATUS_SUCCESS then Result :=hSection;

end;

procedure ClosePhysicalMemory(hPhysicalMemorySection: THandle);

begin

ZwClose(hPhysicalMemorySection);

end;

function AddressIn4MBPage(Address: ULONG): Boolean;

begin

Result := (Address > 0) and ($80000000<=Address) and (Address<$A0000000)

end;

function MiniMmGetPhysicalAddress(vAddress: ULONG): ULONG;

begin

if AddressIn4MBPage(vAddress)

then Result := vAddress - $80000000

else Result := $FFFFFFFF;

end;

function MiniMmGetPhysicalPageAddress(VirtualAddress: ULONG): ULONG;

begin

if AddressIn4MBPage(VirtualAddress)

then Result := VirtualAddress and $1FFFF000

else Result := $FFFFFFFF;

end;

function ExecRing0Proc(ProcEntryPoint: Pointer; SegmentLength: ULONG): boolean;

var

GDT : TGDT; mapAddr: ULONG;

hSection : THandle;

cg: ^CALLGATE_DESCRIPTOR;

farcall : array [0..2] of Word;

BaseAddress: Pointer;

setcg: boolean;

i: Cardinal;

begin

Result := false;

asm SGDT GDT end;

i := (gdt.BaseHigh shl 16) or gdt.BaseLow;

mapAddr := MiniMmGetPhysicalPageAddress(i);

if mapAddr=$FFFFFFFF then

begin

MessageDlg(Format('Can not convert GDT virtual address of [Base = %s Limit = %s]',

[IntToHex(i, 8), IntToHex(GDT.Limit, 4)]), mtError, [mbOK], 0);

Exit;

end;

hSection := OpenPhysicalMemory;

if hSection=0 then

begin

MessageDlg('Error in open physical memory.', mtError, [mbOK], 0);

Exit;

end;

BaseAddress := MapViewOfFile(hSection, FILE_MAP_READ or FILE_MAP_WRITE, 0, mapAddr, //low part

(gdt.Limit+1));

if BaseAddress = nil then

begin

ZwClose(hSection);

MessageDlg(Format('MapViewOfFile Error : %s%sGDT : Address = %s Limit = %s',

[SysErrorMessage(GetLastError), #13#10, IntToHex(mapAddr, 8), IntToHex(GDT.Limit, 4)]), mtError, [mbOK], 0);

Exit;

end;

setcg := false;

i := Cardinal(BaseAddress)+8; // skip first empty entry

while i < Cardinal(BaseAddress)+(gdt.Limit and $FFF8) do

begin

cg:=Ptr(i);

with cg^ do

begin

if IntToHex(GateDescriptor, 4)[2] = '0' then // call gate not present

begin // install callgate

Offset_0_15 := LOWORD(Integer(ProcEntryPoint));

Selector := KGDT_R0_CODE; // ring 0 code

// [Installed flag=1] [Ring 3 code can call=11] 0 [386 call gate=1100] 00000000

GateDescriptor := $EC00;

Offset_16_31 := HIWORD(Integer(ProcEntryPoint));

setcg := TRUE;

Break;

end;

end;

Inc(i, 8);

end;

if not setcg then

begin

UnMapViewOfFile(BaseAddress);

ZwClose(hSection);

MessageDlg('Can not install CallGate in your system GDT', mtError, [mbOK], 0);

Exit;

end;

farcall[0] := 0; farcall[1] := 0;

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

if not VirtualLock(ProcEntryPoint, SegmentLength) then

begin

MessageDlg(SysErrorMessage(GetLastError), mtError, [mbOK], 0);

Exit;

end;

try

SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);

Sleep(0);

asm // call callgate

// push arg1 ... argN // call far fword ptr [farcall]

LEA EAX, farcall // load to EAX

DB 0FFH, 018H // hardware code, means call fword ptr [eax]

end;

SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_NORMAL);

Result := true;

except

on e: Exception do MessageDlg(e.Message, mtError, [mbOK], 0);

end;

VirtualUnlock(ProcEntryPoint, SegmentLength);

// Clear callgate

FillChar(cg^, 8, 0);

UnMapViewOfFile(BaseAddress);

ClosePhysicalMemory(hSection);

end;

使用示例,读取CMOS时钟:

unit NTRing0_Unit;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, Buttons;

type

TForm1 = class(TForm)

BitBtn1: TBitBtn;

procedure BitBtn1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

tHour, tMin, tSec: byte;

implementation

{$R *.dfm}

uses NTRing0;

procedure Ring0Proc; stdcall;

begin

asm // ring0 prolog

PUSHAD // push eax,ecx,edx,ebx,ebp,esp,esi,edi onto the stack

PUSHFD // decrement stack pointer by 4 and push EFLAGS onto the stack

CLI // disable interrupt

// execute your ring0 code here ...

MOV AH,0

MOV DX,$70

MOV AL,AH

OUT DX,AL

INC DX

IN AL,DX

MOV tSec,AL

//

MOV AH,2

MOV DX,$70

MOV AL,AH

OUT DX,AL

INC DX

IN AL,DX

MOV tMin,AL

//

MOV AH,4

MOV DX,$70

MOV AL,AH

OUT DX,AL

INC DX

IN AL,DX

MOV tHour,AL

// ring0 epilog

POPFD // restore registers pushed by pushfd

POPAD // restore registers pushed by pushad

RETF // you may retf <sizeof arguments> if you pass arguments

end;

end;

procedure TForm1.BitBtn1Click(Sender: TObject);

begin

// execute ring 0

if ExecRing0Proc(@Ring0Proc, 100) then

ShowMessage(Format('CMOS Time is %d:%d:%d',

[10*(tHour shr 4) + tHour and $F,

10*(tMin shr 4) + tMin and $F,

10*(tSec shr 4) + tSec and $F]));

end;

end.

调用NTOSKrnl.exe中的Ring0函数实现VA->PA(虚拟地址到物理地址)的转换

type

TMemoryAddress = record

PhysicalAddress : PHYSICAL_ADDRESS; //*000

VirtualAddress : DWord; //*008

end;

var

MemoryAddress : TMemoryAddress;

_MmGetPhysicalAddress : Cardinal;

NTOSBaseAddr : Cardinal;

// NTOSkern.exe的加载地址,2003系统默认是$804DE000

procedure Ring0Func; stdcall;

begin

asm

pushad

pushf

cli

mov esi, MemoryAddress.VirtualAddress

push esi

call _MmGetPhysicalAddress

mov MemoryAddress.PhysicalAddress.LowPart, eax // save low part of LARGE_INTEGER

mov MemoryAddress.PhysicalAddress.HighPart, edx // save high part of LARGE_INTEGER

popf

popad

retf

end;

end;

procedure MmGetPhysicalAddress;

var hNTDll: THandle;

begin

_MmGetPhysicalAddress := 0;

hNTDll := LoadLibrary('ntoskrnl.exe');

if hNTDll <> 0 then

begin

_MmGetPhysicalAddress := NTOSBaseAddr + Cardinal(GetProcAddress(hNTDll, 'MmGetPhysicalAddress')) - hNTDll;

FreeLibrary(hNTDll);

// ShowMessage(Format('Virtual address of MmGetPhysicalAddress in Kernel Mode : %s', [IntToHex(_MmGetPhysicalAddress, 8)]));

end;

if _MmGetPhysicalAddress > 0 then ExecRing0Proc(@Ring0Func, 32);

end;

......

MemoryAddress.VirtualAddress := StrToInt64Def(Edit1.Text, $806AB000);

MmGetPhysicalAddress;

Memo1.Lines.Add(Format('(Ring 0 Mode) Virtual address : $%s = Physical address : $%s',

[IntToHex(MemoryAddress.VirtualAddress, 8),

IntToHex(MemoryAddress.PhysicalAddress.LowPart, 8)]));

powered by LYSoft LiuYang

http://lysoft.7u7.net

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有