Ring 0 code in any user mode

xiaoxiao2021-03-06  53

Transfer from Jiakang

It is well known that in non-Admin user mode, it is not allowed to load the drive to execute Ring 0 code. This article provides a method that adds its own CallGate and Intgate to the system by modifying the system GDT, IDT. We can use this back door to execute Ring 0 code in any user mode. In order to ensure we added CallGate and Intgate permanent. You can use the service API or INF file to start with the system during the first installation. However, this method also has a defect, which still needs admin privacy when installing CallGate or intGate. The specific code to add CallGate and Intgate is given below. 1. Adding a call door implementation In order to invoke any user to call our CallGate, you need to solve a small problem. Because you need to know the class of CallGate, you can call. The BASE Address and Limit that can get GDT cannot be accessed in Ring 3. I want to save Selector to the file in Ring 0. Read it in Ring 3 and then call it. After being discussed with Wowocock. His proposed idea is to get NTDLL.DLL's module base by ZWQuerySystemInformation under Ring 0 and store Selector according to the idle place in PE Header. This is easily obtained in any user mode of Ring 3. I would like to thank WowOcock here. The following code is convenient for demonstration, using the Selector of the first idle descriptor in my machine.

driver:/********************************************** ****************** File Name: WSSADDCallgate.c Description: Add Pixabay: SINISTER Last Modified Date: 2002-11-02 ******* *********************************************************** ******* / # include "ntddk.h" #include "string.h" # ifndef dword # define dword unsigned int # Endif # ifndef word # define word unsigned short # endif # define loword (L) (( Unsigned Short (L)) # Define HiWord ((Unsigned SHORT) >> 16) & 0xfff)) Typedef unsigned long ulong; static ntstatus mydrvdispatch IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject); # pragma pack (push, 1) typedef struct tagGDTR {WORD wLimit; DWORD * dwBase;} GDTR, * PGDTR; typedef struct tagGDT_DESCRIPTOR {unsigned limit: 16 Unsigned Baselo: 16; Unsigned BaseMID: 8; Unsigned Type: 4; Unsigned System: 1; Unsigned DPL: 2; Unsigned Present: 1; unsigned limithi: 4; unsigned available: 1; unsigned zero: 1; unsigned size: 1; unsigned granularity: 1; unsigned basehi: 8;} GDT_DESCRIPTOR, * PGDT_DESCRIPTOR; typedef struct tagCALLGATE_DESCRIPTOR {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, * PCALLGATE_DESCRIPTOR; #pragma pack (pop) Void __declspec (naked) Ring0Call () {physical_address phyadd;

__ASM {Pushad Pushfd Cli} DBGPrint ("WSS - My Callgate / N"); // Here you can add the Ring 0 code you want to perform.

// __asm ​​{popfd popad retf}} VOID AddCallGate (ULONG FuncAddr) {GDTR gdtr; PGDT_DESCRIPTOR gdt; PCALLGATE_DESCRIPTOR callgate; WORD wGDTIndex = 1; __asm ​​{sgdt gdtr // get GDT base address and limit} gdt = (PGDT_DESCRIPTOR) (gdtr .dwbase 8); // Skip Empty Selection Son While (WGDTINDEX present == 0) // Find an empty descriptor {Callgate = from GDT = (PCallgate_Descriptor ) gdt; callgate-> offset_0_15 = loword (funcaddr); callgate-> selector = 8; // internal core selection sub-calgate-> param_count = 0; // Parameter copy quantity CallGate-> Some_bits = 0; callgate-> type = 0xc; // 386 call door Callgate-> app_system = 0; // System Descriptor Callgate-> DPL = 3; // Ring 3 can call CallGate-> present = 1; // Set the presence position Callgate-> offset_16_31 = HiWord (funcaddr); DBGPrint ("add callgate / n"); return;} gdt ; WGDTIDEX ;} } // drive inlet NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {UNICODE_STRING nameString, linkString; PDEVICE_OBJECT deviceObject; NTSTATUS status; HANDLE hHandle; int i; // unload drive DriverObject-> DriverUnload = DriverUnload;

// Create apparatus RtlInitUnicodeString (& nameString, L "// Device // WssAddCallGate"); status = IoCreateDevice (DriverObject, 0, & nameString, FILE_DEVICE_UNKNOWN, 0, TRUE, & deviceObject); if (! NT_SUCCESS (status)) return status; RtlInitUnicodeString (& linkString, L "// DosDevices // WssAddCallGate"); status = IoCreateSymbolicLink (& linkString, & nameString); if (NT_SUCCESS (status)!) {IoDeleteDevice (DriverObject-> DeviceObject); return status;} AddCallGate ((ULONG) Ring0Call ); for (i = 0; i MajorFunction [i] = MydrvDispatch;} DriverObject-> DriverUnload = DriverUnload; return STATUS_SUCCESS;} // object operation processing apparatus static NTSTATUS MydrvDispatch (IN PDEVICE_O BJECT DeviceObject, IN PIRP Irp) {Irp-> IoStatus.Status = STATUS_SUCCESS; Irp-> IoStatus.Information = 0L; IoCompleteRequest (Irp, 0); return Irp-> IoStatus.Status;} VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject) { UNICODE_STRING nameString; RtlInitUnicodeString (& nameString, L "// DosDevices // WssAddCallGate"); IoDeleteSymbolicLink (& nameString); IoDeleteDevice (pDriverObject-> DeviceObject); return;} application: #include #include void main () {Word Farcall [3]; farcall [0] = 0x0; Farcall [1] = 0x0; Farcall [2] = 0x4b; // On my machine,

Add CallGate's Selecto to 4BH_ASM Call Fword Ptr [Farcall]} II. If you implement the interrupt gate, there is nothing to solve. Switch directly in Ring 3 with int x. Think about the system call INT 2E is easy to understand.

/ ************************************************** *************** File Name: WSSMYINT.C Description: Add Interrupt Gate Author: sinister last modification date: 2002-11-0********** *********************************************************** **** / # include "ntddk.h" #pragma pack (1) typedef struct tagIDTR {short Limit; unsigned int Base;} IDTR, * PIDTR; typedef struct tagIDTENTRY {unsigned short OffsetLow; unsigned short Selector; unsigned char Reserved ; unsigned char Type: 4; unsigned char Always0: 1; unsigned char Dpl: 2; unsigned char Present: 1; unsigned short OffsetHigh;} IDTENTRY, * PIDTENTRY; #pragma pack () # define MYINT 0x76extern VOID _cdecl MyIntFunc (); CHAR IDTBuffer [6]; IDTENTRY OldIdt; PIDTR idtr = (PIDTR) IDTBuffer; static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject); // we must interrupt handler VOID _cdecl MyIntFunc () {Physical_address phyadd; unsigned int dwcallnum Unsigned int dwvaddr; _ASM MOV dwcallnum, eax // // // Switch (DWCallnum) {Case 0x01: DBGPrint ("MyIntgate Eax = 0x01 / N"); Break; Case 0x02 : DBGPrint ("MyIntgate EAX = 0x02 / N"); Break; default: Break;} _ASM IRETD; / / Interrupt Return} NTSTATUS ADDMYINT () {pIDTENTRY IDT; / / Get Idtr Division Difference and Base Add_ASM SIDTBuffer IDT = (PIDTENTRY) IDTR-> base; // Get the IDT Subterite Address // Save the original Idt RTLCopyMemory (& OldiDT, & IDt [Myint], SIZEOF (OldIDT)); // Disable interrupt _ASM CLI // Setting IDT table Add us to interrupt ID [myint] .offsetlow = (unsigned short) MyintFunc;

// Take the interrupt processing function lower 16-bit IDT [Myint] .Selector = 8; // Set the internal core selection sub-idt [myint] .ReServed = 0; // System reserved idt [Myint] .type = 0xE; // Setting 0xE is indicated by interrupt gate ID [myint] .always0 = 0; // System reserves must be 0 IDt [myint] .dpl = 3; // Descriptor permission, set to allow RING 3 process call idt [Myint] .present = 1; // The presence bit is set to 1 means a valid IDT [Myint] .OffSethiGH = (unsigned int) ((unsigned int) MyintFunc >> 16); // Take the interrupt processing function 16-bit // open interrupt _ASM STI RETURN STATUS_SUCCESS } // Remove the interrupt void removemyint () {pidtenTry idt; idt = (pidten) idtr-> base; _ASM CLI // Restore IDT RTLCopyMemory (& IDT [Myint], & OldIDT, SIZEOF (OldIDT)); _ASM STI} // driving an inlet NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {UNICODE_STRING nameString, linkString; // UNICODE_STRING deviceString; PDEVICE_OBJECT deviceObject; NTSTATUS status ; WCHAR wBuffer [200]; nameString.Buffer = wBuffer; nameString.MaximumLength = 200; // unload drive DriverObject-> DriverUnload = DriverUnload; // build equipment RtlInitUnicodeString (& nameString, L "// Device // WSSINT"); status = IOCREATEDEVICE (DriverObject, 0, & nameString, File_Device_unknown, 0, true, & deviceObject); if (! Nt_success (status)) Return Status;

转载请注明原文地址:https://www.9cbs.com/read-118129.html

New Post(0)