找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 6202|回复: 3

[原创]驱动里获取指定PID的完整性级别(Integrity Level)

[复制链接]

7

主题

67

回帖

2

精华

钻石会员

积分
2565
发表于 2018-2-9 00:38:54 | 显示全部楼层 |阅读模式

本人菜鸟,大神飘过
背景:有个软件需要在驱动里找一个具有system权限的svchost,借它做点非常正规的事情.此处省略一万字.
本着从贵站也学习也奉贤的原则.开始如下:
首先想到了之前写过用户层的,先发出代码.

'SECURITY_MANDATORY_UNTRUSTED_RID = $00000000;        -0
'SECURITY_MANDATORY_LOW_RID = $00001000;              -4096
'SECURITY_MANDATORY_MEDIUM_RID = $00002000;           -8192 普通用户权限
'SECURITY_MANDATORY_HIGH_RID = $00003000;             -12288 管理员权限
'SECURITY_MANDATORY_SYSTEM_RID = $00004000;           -16384 system权限
'SECURITY_MANDATORY_PROTECTED_PROCESS_RID = $00005000;-20480

Option Explicit
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, ByRef TokenInformationClass As TOKEN_INFORMATION_CLASS, ByRef TokenInformation As Any, ByVal TokenInformationLength As Long, ByRef ReturnLength As Long) As Long
Private Declare Function GetSidSubAuthorityCount Lib "advapi32.dll" (ByVal pSid As Long) As Long
Private Declare Function GetSidSubAuthority Lib "advapi32.dll" (ByVal pSid As Long, ByVal nSubAuthority As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Type SID_AND_ATTRIBUTES
    SID As Long
    Attributes As Long
End Type
Private Type TOKEN_MANDATORY_LABEL
    Label As SID_AND_ATTRIBUTES
End Type
Private Enum TOKEN_INFORMATION_CLASS
    TokenUser = 1
    TokenGroups
    TokenPrivileges
    TokenOwner
    TokenPrimaryGroup
    TokenDefaultDacl
    TokenSource
    tokenType
    TokenImpersonationLevel
    TokenStatistics
    TokenRestrictedSids
    TokenSessionId
    TokenGroupsAndPrivileges
    TokenSessionReference
    TokenSandBoxInert
    TokenAuditPolicy
    TokenOrigin
    TokenElevationType
    TokenLinkedToken
    TokenElevation
    TokenHasRestrictions
    TokenAccessInformation
    TokenVirtualizationAllowed
    TokenVirtualizationEnabled
    TokenIntegrityLevel
    TokenUIAccess
    TokenMandatoryPolicy
    TokenLogonSid
    TokenIsAppContainer
    TokenCapabilities
    TokenAppContainerSid
    TokenAppContainerNumber
    TokenUserClaimAttributes
    TokenDeviceClaimAttributes
    TokenRestrictedUserClaimAttributes
    TokenRestrictedDeviceClaimAttributes
    TokenDeviceGroups
    TokenRestrictedDeviceGroups
    TokenSecurityAttributes
    TokenIsRestricted
    MaxTokenInfoClass
End Enum
Private Const TOKEN_QUERY = &H8
Private Const TOKEN_QUERY_SOURCE = &H10

Public Function GetIntegrityLevel() As Long
    Dim hProcess As Long
    Dim hToken As Long
    Dim dwSize As Long
    Dim pUser As TOKEN_MANDATORY_LABEL
    Dim psaCount As Long
    Dim SubAuthority As Long
    Dim lRet As Long
    Dim lpBuffer() As Long
    hProcess = GetCurrentProcess()
    If hProcess Then
            Call OpenProcessToken(hProcess, TOKEN_QUERY Or TOKEN_QUERY_SOURCE, hToken)
            If hToken Then
                    Call GetTokenInformation(hToken, ByVal TokenIntegrityLevel, ByVal 0&, 0, dwSize)
                    If dwSize Then
                            ReDim lpBuffer(dwSize) As Long
                            lRet = GetTokenInformation(hToken, ByVal TokenIntegrityLevel, lpBuffer(0), dwSize, dwSize)
                            If lRet Then
                                    Call CopyMemory(pUser, lpBuffer(0), LenB(pUser))
                                    psaCount = GetSidSubAuthorityCount(pUser.Label.SID)
                                    If psaCount Then
                                            CopyMemory SubAuthority, ByVal psaCount, 4
                                            SubAuthority = SubAuthority - 1
                                            lRet = GetSidSubAuthority(pUser.Label.SID, SubAuthority)
                                            If lRet Then
                                                    CopyMemory GetIntegrityLevel, ByVal lRet, 4
                                            End If
                                    End If
                            End If
                            Erase lpBuffer()
                    End If
                    CloseHandle hToken
            End If
    End If
End Function

再来c++版

#include<windows.h>
#ifndef _TOKEN_MANDATORY_LABEL
typedef struct _TOKEN_MANDATORY_LABEL {
  SID_AND_ATTRIBUTES Label;
} TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
#endif
#ifndef TokenIntegrityLevel
#define TokenIntegrityLevel 0x19
#endif
DWORD GetIntegrityLevel()
{
    HANDLE hProcess = NULL, hToken = NULL;
    DWORD dwSize = 0, dwRet = 0;
    PTOKEN_MANDATORY_LABEL pTokenInfo = NULL;
    hProcess = GetCurrentProcess();
    if (hProcess != NULL)
    {
        OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_QUERY_SOURCE, &hToken);
        if (hToken != NULL)
        {
            GetTokenInformation(hToken,TokenIntegrityLevel , NULL, 0, &dwSize);
            if (dwSize != 0)
            {
                pTokenInfo = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwSize);
                dwRet = GetTokenInformation(hToken,TokenIntegrityLevel , pTokenInfo, dwSize, &dwSize);
                if (dwRet != 0)
                {
                    dwRet = *GetSidSubAuthority(pTokenInfo->Label.Sid, *GetSidSubAuthorityCount(pTokenInfo->Label.Sid) - 1);
                }
                LocalFree(pTokenInfo);
            }
            CloseHandle(hToken);
        }
    }
    return dwRet;
}
int main()
{
    printf("%d\n",GetIntegrityLevel());
    system("pause");
    return 1;
}

现在的问题是需要在驱动里面实现,乍一碰到,有点手麻,不知道杂去搜索。可以想到搜出来的内容要是没点关键词那肯定是毛用都没。
既然没办法了,那就自己手动分析处理。
先看关键函数GetSidSubAuthority,一搜知道是advapi32.dll里面的。那么来看看。代码如下
.text:77DB5550 ; PDWORD __stdcall GetSidSubAuthority(PSID pSid, DWORD nSubAuthority)
.text:77DB5550                 public _GetSidSubAuthority@8
.text:77DB5550 _GetSidSubAuthority@8 proc near         ; DATA XREF: .text:off_77DA16CCo
.text:77DB5550
.text:77DB5550 pSid            = dword ptr  8
.text:77DB5550 nSubAuthority   = dword ptr  0Ch
.text:77DB5550
.text:77DB5550                 mov     edi, edi
.text:77DB5552                 push    ebp
.text:77DB5553                 mov     ebp, esp
.text:77DB5555                 push    0               ; dwErrCode
.text:77DB5557                 call    ds:__imp__SetLastError@4 ; SetLastError(x)
.text:77DB555D                 pop     ebp
.text:77DB555E                 jmp     ds:__imp__RtlSubAuthoritySid@8 ; RtlSubAuthoritySid(x,x)
.text:77DB555E _GetSidSubAuthority@8 endp

还真是够简单的。啥也没有,直接就是调用 RtlSubAuthoritySid
心想这下有更进一步的关键词了。下来看看 ntkrnlpa.exe(我在xp里实验)  其他环境得(ntoskrnl.exe)
看了一下导出表如下
序列 地址 名字
00000486 00456160 RtlSplay
00000487 00511E3C RtlStringFromGUID
00000488 0050BF36 RtlSubAuthorityCountSid
00000489 0050BF1E RtlSubAuthoritySid
0000048A 004562F0 RtlSubtreePredecessor
0000048B 004562CC RtlSubtreeSuccessor
0000048C 00454DDE RtlTestBit
心里想肯定就是它了。同样的方法OpenProcessToken和GetTokenInformation也可以进一步的得到
ZwOpenProcessTokenEx和ZwQueryInformationToken
于是就有了完整的代码如下:
BOOLEAN IsSystemIntegrity(HANDLE pid)
{
NTSTATUS ret;
PEPROCESS proc;
HANDLE hProcHandle;
HANDLE hToken;
BOOLEAN bSystemIntegrity = FALSE;
ULONG size;
TOKEN_MANDATORY_LABEL *pLabel;
DWORD dwIntegrityLevel = 0;

if (NT_SUCCESS(ret = PsLookupProcessByProcessId(pid, &proc)))
{
  if (NT_SUCCESS(ret = ObOpenObjectByPointer(proc, OBJ_KERNEL_HANDLE, NULL, 0, *PsProcessType, KernelMode, &hProcHandle)))
  {
   if (NT_SUCCESS(ret = ZwOpenProcessTokenEx(hProcHandle, TOKEN_QUERY, OBJ_KERNEL_HANDLE, &hToken)))
   {
    if (STATUS_BUFFER_TOO_SMALL == (ret = ZwQueryInformationToken(hToken, TokenIntegrityLevel, NULL, 0, &size)))
    {
     if (pLabel = ExAllocatePoolWithTag( PagedPool ,size,'_EL_'))
     {
      if (NT_SUCCESS(ret = ZwQueryInformationToken(hToken, TokenIntegrityLevel, pLabel, size, &size)))
      {
       dwIntegrityLevel = *RtlSubAuthoritySid(pLabel->Label.Sid,(DWORD)(UCHAR)(*RtlSubAuthorityCountSid(pLabel->Label.Sid)-1));
       DbgPrint(("DEMO:%-4d [INFO] dwIntegrityLevel = %d.\n", __LINE__,dwIntegrityLevel));
       if (SECURITY_MANDATORY_SYSTEM_RID == dwIntegrityLevel)
        bSystemIntegrity = TRUE;
      }
      ExFreePoolWithTag(pLabel, '_EL_');
     }
    }
   }
  }
}

return bSystemIntegrity;
}
HANDLE PsGetSystemSvchost()
{
NTSTATUS ret = STATUS_SUCCESS;
PSYSTEM_PROCESS_INFORMATION pInfo = NULL, buf;
ULONG len = 0;
HANDLE dwPid = 0;
ULONG os;

PsGetVersion(NULL, NULL, &os, NULL);
if (STATUS_INFO_LENGTH_MISMATCH == (ret = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, pInfo, len, &len)))
{
  if (!(pInfo = (PSYSTEM_PROCESS_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, len, '_EL_')))
  {
   DbgPrint(("DEMO:%-4d [ERRO] ExAllocatePoolWithTag failed with size %d.\n", __LINE__, len));
  }
  else
  {
   buf = pInfo;
   if (NT_SUCCESS(ret = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, pInfo, len, &len)))
   {
    for (;;)
    {
     LPWSTR pszProcessName = pInfo->ImageName.Buffer;
     if (pszProcessName == NULL)
      pszProcessName = L"NULL";
     if (_wcsnicmp(pszProcessName,L"svchost.exe",wcslen(L"svchost.exe")) == 0)
     {
      if (os < 6000)
      {
       dwPid = pInfo->ProcessId;
       break;
      }
      else
      {
       if (IsSystemIntegrity(pInfo->ProcessId))
       {
        dwPid = pInfo->ProcessId;
        break;
       }
      }
     }
     if (!pInfo->NextEntryOffset)
      break;
     pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo) + pInfo->NextEntryOffset);
    }
   }
   ExFreePoolWithTag(buf, '_EL_');
  }
}
else
{
  DbgPrint(("DEMO:%-4d [ERRO] ZwQuerySystemInformation failed with 0x%p.\n", __LINE__, ret));
}

return dwPid;
}
事后根据自己写好的关键词去一搜索,哎呀,网上还真不少。都是自己孤漏寡闻。
写代码的事情就是这个样子,自认为需要研究的东西,或者是自己觉的很有难度的东西,曾经在n年前,都被n个大牛研究的烂了,都不稀罕研究了
写代码最大的悲哀或许就是如此~没啥成就感。。。

评分

参与人数 1水晶币 +20 收起 理由
Tesla.Angela + 20 赞一个!

查看全部评分

2

主题

32

回帖

0

精华

铜牌会员

积分
68
发表于 2018-2-9 15:24:16 | 显示全部楼层
赞一个哦楼主~
信息很详细,我感觉现在最需要提升的就是搜索能力,我搜一个知识点搜半天,同事一下就搜到了,真的是尴尬。实现代码感觉都是次要的,因为能找到相关信息就一定能弄好,只是时间问题罢了。
向楼主学习,我也要好好钻研vt(T_T)

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
发表于 2018-2-10 11:23:13 | 显示全部楼层
这个不错,稍加改造还可以获取【该进程】【所属用户的】【所属HKCU】。

0

主题

3

回帖

0

精华

铜牌会员

积分
124
发表于 2018-7-2 18:09:52 | 显示全部楼层
很好 支持下,学习了
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表