windows系統下Smss.exe加載win32k.sys過程詳解

windows操作系統初始化

windows操作系統再初始化的過程中,當內核完全初始化而且各個組件也已經準備好後會加載一個個用戶進程smss.exe(會話管理器),此進程會接著調用NtSetSystemInformation並傳入SystemRegistryAppendStringInformation == 38參數加載win32k.sys這個模塊,接著就會調用win32k.sys的DriverEntry入口。接著smss.exe便會啟動Windows 子系統進程csrss.exe。

win32k.sys加載ShadowSSDT表

當smss.exe在加載win32k.sys模塊後,win32k.sys這個模塊會緊接著執行其模塊入口DriverEntry,緊接著其會執行AddSystemServiceTable為系統增加一張ShadowSSDT表。我們可以在smss.exe剛剛加載win32k.sys是將ntoskrnl.exe所導出的KeAddSystemServiceTable給EAThook瞭,然後在我們自己的MyKeAddSystemServiceTable()中判斷通過判斷加載的表的基地址是否在win32k.sys模塊地址范圍中,如果不在證明不是正確的ShadowSSDT表。

關於win32k.sys所在地址有效性的問題

win32k.sys包含ShadowSSDT表,隻要線程中調用GUI函數最後都會調用ShadowSSDT表中的服務。但並不是隻有GUI線程才會將win32k.sys加載到內存中,參考教主的帖子是說win32k.sys模塊的加載與會話有關,所以隻要不是System和smss.exe(會話管理器不屬於任意一個繼承)進程其他任何一個進程都會加載win32k.sys。
我們看一下在System進程中win32k.sys模塊的地址,發現確實是無效的。


 

所以如果我們想要在內核中修改win32k.sys模塊(IAT_hook)就必須保證當前進程上下文不在System和smss.exe中,也就是需要將進程上下文切換到除瞭兩個進程之外的任意一個進程地址空間中。

獲得csrss.exe進程的PID

當我們需要IAT_HOOKwin32k.sys模塊時可以將地址空間切換到csrss.exe進程地址空間中,再這之前我們需要先獲得csrss.exe進程的PID,然後通過其PID得到對應的EPROCESS,然後切換到對應的進程地址空間中。一種獲得csrss.exe的方法是通過枚舉系統中所有的句柄然後,尋找名為"\Windows\ApiPort"的ALPC port句柄然後得到其對應的進程PID(csrss.exe進程會創建一個名為"\Windows\ApiPort"的ALPC port對象)。

 HANDLE GetCsrssPid()
 {
    HANDLE Process, hObject;
    HANDLE CsrssId;
    OBJECT_ATTRIBUTES obj;
    CLIENT_ID cid;
    UCHAR Buff[0x1000];
    POBJECT_NAME_INFORMATION pObjName = (PVOID)&Buff;
    PSYSTEM_HANDLE_INFORMATION_EX Handles;
    
 
    Handles = QueryHandleInfo(SystemHandleInformation);              //通過調用ZwQuerySystemInformation獲得所有的句柄信息返回SYSTEM_HANDLE_INFORMATION_EX結構體
 
    if (!Handles) 
        return CsrId;
 
    for (ULONG i = 0; i < Handles->NumberOfHandles; i++)
    {
        if (Handles->Information[r].ObjectTypeNumber == 21)         //ALPC Port object
        {
            InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);

            cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
            cid.UniqueThread = 0;
            if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
            {
                if (NT_SUCCESS(ZwDuplicateObject(Process, (HANDLE)Handles->Information[r].Handle,NtCurrentProcess(), &hObject, 0, 0,DUPLICATE_SAME_ACCESS)))    //將句柄復制到當前進程中
                {
                    if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, ObjName, 0x100, NULL)))                            //傳入參數ObjectNameInformation得到對象的名稱信息
                    {
                        if (pObjName->Name.Buffer && !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20))
                        {
                            CsrssId = (HANDLE)Handles->Information[r].ProcessId;
                        } 
                    }

                    ZwClose(hObject);
                }

                ZwClose(Process);
            }
      }
}
ExFreePool(Handles);
return CsrssId;
}

ZwQuerySystemInformation的參數SystemInformationClass等於SystemHandleInformation(16),SystemInformation會返回SYSTEM_HANDLE_INFORMATION_EX結構體,其第一個NumbreOfHandles字段為獲得的句柄的總數目,然後SYSTEM_HANDLE_INFORMATION數組為各個句柄的信息。

typedef struct _SYSTEM_HANDLE_INFORMATION_EX 
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_INFORMATION Information[1];
}SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;

SYSTEM_HANDLE_INFORMATION結構包含瞭句柄的一些基本信息,例如所屬進程PID等等。

typedef struct _SYSTEM_HANDLE_INFORMATION 
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
}SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

到此這篇關於windows系統下Smss.exe加載win32k.sys過程詳解的文章就介紹到這瞭,更多相關Smss.exe加載win32k.sys內容請搜索GuideAH以前的文章或繼續瀏覽下面的相關文章,希望大傢以後多多支持GuideAH!

閱讀更多: