This code is very meaningful to the father's commemorative version, which is developed in the most painful period in my life. Oh, everything is eternal nostalgic ...
Note: Jedi Win32 API (JWA) support is required
In addition, this method is not suitable for PAE mode (WinXP SP2 is equipped with AMD64 or EMT64 processor system), and cannot support Win2003 SP1
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 Zwopense; External 'NTDLL.DLL';
Function ZWClose; External 'NTDLL.DLL';
Function setDebugprivilege (Candebug: Boolean): Boolean
Function EnablePrivilege (HTOKEN: Cardinal; Privname: String; Benable: Boolean;
VAR
TP: windows.token_privileges;
Dummy: cardinal
Begin
Tp.privilegecount: = 1;
LookuppprivileGeValue (Nil, Pchar (Privname), TP.Privileges [0] .luid);
IF Benable Then
Tp.privileges [0] .attributes: = SE_PRIVILE_ENABED
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 setPhyscialMemorysectioncanbewrite: 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 the
Begin
Messagedlg (Format ('getSecurityInfo Error% D', [dwres]), mTerror, [Mbok], 0);
Goto cleanup;
END;
ZeromeMory (@ea, sizeof (expected_access));
Ea.grfaccesspermissions: = section_map_write
Ea.grfaccessmode: = GRANT_ACCESS;
Ea.grfinheritance: = no_inheritance;
Ea.trustee.trusteeform: = trustee_is_name;
Ea.trustee.trustetype: = trustee_use_user;
Ea.trustee.ptstrname: = 'current_user';
DWRES: = STENTRIESINACL (1, @ea, pdacl, pnewdacl);
IF dwres <> error_success the
Begin
Messagedlg (Format ('STENTRIESINACL 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 the
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 damalfree (Cardinal (PNewDACL);
END;
Function openphysicalmemory: thandle;
VAR
HSECTION: THANDLE;
Status: NTSTATUS;
Objname: unicode_string;
Objectttributes: 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, @Objectattribute);
IF (status = status_access_denied) THEN
Begin
Status: = zwopensection (HSECTION, RONCONTROL or WRITE_DAC, @Objecttributes);
If status = status_success the setphyscialMemorysectioncanbewrite;
ZWClose (HSECTION);
Status: = zwopensection (HSECTION, section_map_read or section_map_write, @Objectattribute);
END;
IF status = status_success the result: = HSECTION;
END;
Procedure ClosephysicalMemory (HPHYSICALMORYSECTION: 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: = $ fffffff;
END;
Function MinimmgetPhysicalPageAddress (VirtualAddress: Ulong): Ulong;
Begin
IF addressin4mbpage (VirtualAddress)
Then Result: = VirtualAddress and $ 1FFF000
Else Result: = $ fffffff;
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.blelow;
MapAddr: = minimmgetphysicalPageAddress (i);
IF mapAddr = $ fffffffff
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;
BaseEaddress: = MapViewoffile (HSECTION, FILE_MAP_READ OR File_MAP_WRITE, 0, MAPADDR, / / LOW PART
(GDT.LIMIT 1));
If BaseAddress = nil dam
Begin
ZWClose (HSECTION);
Messagedlg (Format ('MapViewOffile Error:% 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 Begin CG: = PTR (i); With cg ^ do Begin IF INTTOHEX (GateDescriptor, 4) [2] = '0' TEN // Call Gate Not Present Begin // Install Callgate OFFSET_0_15: = LOWORD (Integer (Integer "); 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 (BaseEaddress); 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) Thenbegin 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 // loading 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 (BaseEaddress); Closephysicalmemory (HSECTION); END; Use an example to read the CMOS clock: 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, EPX, 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 thor, Al // Ring0 Epilog POPFD // Restore Registers Pushed by Pushfd POPAD // Restore Registers Pushed by Pushadretf // You May Retf 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 the call NTOSKrnl.exe Ring0 function implementation VA-> PA (virtual addresses into physical addresses) conversion type TMemoryAddress = record PhysicalAddress: PHYSICAL_ADDRESS; // * 000 VirtualAddress: DWord; // * 008 end; var MemoryAddress: TMemoryAddress ; _MMGETPHYSICALALADDRESS: cardinal NtosbaseAddr: cardinal; // Ntoskern.exe load address, 2003 system default is $ 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;