線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1772
推到 Plurk!
推到 Facebook!

捐一段任意用戶模式下執行 ring 0 的代碼,作共用軟體時用

 
jean2004
初階會員


發表:69
回覆:80
積分:39
註冊:2004-12-18

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-10-23 21:58:14 IP:222.135.xxx.xxx 未訂閱
  任意用戶模式下執行 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 
#include     void main()
{
    WORD farcall[3];        farcall[0] = 0x0;
    farcall[1] = 0x0;
    farcall[2] = 0x4b;  //在我機器上,添加 CALLGATE 的選擇子為 4BH        _asm call fword ptr [farcall]    }       二、通過添加中斷門實現      添加中斷門沒有什麼需要解決的問題。直接在 RING 3 利用 int x
即可切換。想想系統調用 INT 2E 就很容易理解了。    /*****************************************************************
檔案名        : WssMyInt.c
描述          : 添加中斷門
作者          : sinister
最後修改日期  : 2002-11-02
*****************************************************************/    #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 0x76    extern 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);    // 我們得中斷處理函數    VOID _cdecl MyIntFunc()
{
    PHYSICAL_ADDRESS  PhyAdd;
    unsigned int      dwCallNum;
    unsigned int      dwVAddr;        _asm mov dwCallNum,eax         //
     // 這裏可以添加你想要執行的 ring 0 代碼
     //        switch ( dwCallNum )
    {
        case 0x01:        
             DbgPrint("MyIntGate eax = 0x01\n");
             break;            case 0x02:
             DbgPrint("MyIntGate eax = 0x02\n");
             break;            default:break;        }        _asm iretd; //中斷返回
}    NTSTATUS AddMyInt()
{
    PIDTENTRY    Idt;        //得到 IDTR 中得段界限與基底位址
    _asm sidt IDTBuffer        Idt = (PIDTENTRY)idtr->Base; //得到IDT表基底位址        //保存原有得 IDT
    RtlCopyMemory(&OldIdt, &Idt[MYINT], sizeof(OldIdt));        //禁止中斷
    _asm cli        //設置 IDT 表各項添加我們得中斷        Idt[MYINT].OffsetLow   = (unsigned short)MyIntFunc;    //取中斷處理函數低16位元
    Idt[MYINT].Selector    = 8;                            //設置內核段選擇子
    Idt[MYINT].Reserved    = 0;                            //系統保留
    Idt[MYINT].Type        = 0xE;                          //設置0xE表示是中斷門
    Idt[MYINT].Always0     = 0;                            //系統保留必須為0
    Idt[MYINT].Dpl         = 3;                            //描述符許可權,設置為允許 RING 3 進程調用
    Idt[MYINT].Present     = 1;                            //存在位設置為1表示有效
    Idt[MYINT].OffsetHigh  = (unsigned short)((unsigned int)MyIntFunc>>16); //取中斷處理函數高16位元        //開中斷
    _asm sti        return STATUS_SUCCESS;
}    //刪除中斷    void RemoveMyInt()
{
    PIDTENTRY            Idt;
    Idt = (PIDTENTRY)idtr->Base;        _asm cli
    //恢復 IDT 
    RtlCopyMemory(&Idt[MYINT], &OldIdt, sizeof(OldIdt));
    _asm sti
}        // 驅動入口
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;         //卸載驅動
    DriverObject->DriverUnload = DriverUnload;        //建立設備
    RtlInitUnicodeString( &nameString, L"\\Device\\WSSINT" );
    
    status = IoCreateDevice( DriverObject,
                             0,
                             &nameString,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             TRUE,
                             &deviceObject
                           );
                                   if (!NT_SUCCESS( status ))
        return status;
    
    RtlInitUnicodeString( &linkString, L"\\??\\WSSINT" );        //使WIN32應用程式可見
    status = IoCreateSymbolicLink (&linkString, &nameString);        if (!NT_SUCCESS( status ))
    {
        IoDeleteDevice (DriverObject->DeviceObject);
        return status;
    }    
    
    AddMyInt();        DriverObject->MajorFunction[IRP_MJ_CREATE] = MydrvDispatch; 
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = MydrvDispatch;  
     
  return STATUS_SUCCESS; 
}     static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{ 
    NTSTATUS            status;
    
    UNREFERENCED_PARAMETER( DeviceObject );
    
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0L;
    status = STATUS_SUCCESS;        IoCompleteRequest( Irp, 0 );
    return status;
    
}        VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject)
{
    UNICODE_STRING  nameString;
    UNICODE_STRING  deviceString,driveString;
    NTSTATUS        ntStatus;        RemoveMyInt();        //刪除WIN32可見
    IoDeleteSymbolicLink(&nameString);
    //刪除設備
    IoDeleteDevice(pDriverObject->DeviceObject);        return;
}
 
發表人 - jean2004 於 2005/10/23 22:20:10
jean2004
初階會員


發表:69
回覆:80
積分:39
註冊:2004-12-18

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-10-23 22:05:12 IP:222.135.xxx.xxx 未訂閱
有不少程式會根據電腦的硬體配置來製作註冊碼, 但是如果用戶不使用administrator組用戶登陸就無法操作硬體, 上面這兩個源碼就是解決這一問題的,為了豐富論壇所以發上來, 請版主先進將其轉換成BCB版的,以方便使用,不知可否? ------------------------------------------------- 有覺的好用的網友請推薦給分吧! 發表人 - jean2004 於 2005/10/23 22:25:36
jean2004
初階會員


發表:69
回覆:80
積分:39
註冊:2004-12-18

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-10-26 19:35:25 IP:222.135.xxx.xxx 未訂閱
怎麼才兩位網友推薦給分?分好像也沒有增加,本來還要貼的,現在沒有信心了
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-10-27 12:17:38 IP:218.175.xxx.xxx 未訂閱
hi 抱歉啦 因為庵之前有幫你轉貼了啦 【轉貼】任意用戶模式下執行 ring 0 代碼 http://delphi.ktop.com.tw/topic.php?topic_id=50996 台灣災難都是事後算帳 無人飛行載具(Unmanned Aerial Vehicle,UAV)為什麼沒大量應用於救災行列 絲絲有2種 .net有很多種 一種治眼睛是MS 另一種治腦筋是Borland
8866
中階會員


發表:27
回覆:147
積分:69
註冊:2002-10-14

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-10-28 09:07:31 IP:59.120.xxx.xxx 未訂閱
你好 ,    你寫的很好的啊 , 不要如此容易沒有信心喔 ! 我雖然只是一個小會員還是給你鼓掌叫好 .    
jean2004
初階會員


發表:69
回覆:80
積分:39
註冊:2004-12-18

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-10-28 17:08:06 IP:222.135.xxx.xxx 未訂閱
呵呵,謝謝各位的鼓勵,大家這麼支持我,實在是很感動,在論壇上學到不少知識,總想把自己所學回報論壇,現在有信心了,謝謝各位!
系統時間:2024-03-29 16:03:56
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!