Cobalt Strike Bof开发以及实际遇到的问题

前言:Cobalt Strike Bof开发笔记,这边简单的学习下什么是bof,如何编写和编译bof

参考文章:https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/beacon-object-files_main.htm
参考文章:https://hstechdocs.helpsystems.com/kbfiles/cobaltstrike/attachments/beacon.h
参考文章:https://www.trustedsec.com/blog/a-developers-introduction-to-beacon-object-files
参考文章:https://github.com/evilashz/Visual-Studio-BOF-template
参考文章:https://github.com/dtmsecurity/bof_helper
参考文章:https://tttang.com/archive/1786/
参考文章:https://blog.csdn.net/weixin_41115751/article/details/89817123
参考文章:https://github.com/EncodeGroup/BOF-RegSave

关于Bof

Beacon Object File(BOF) 从Cobalt Strike4.1开始所添加的新功能,它允许你使用C语言编写扩展来扩展Beacon的功能。这些扩展可以在运行时直接加载到Beacon的内存中并执行,无需在目标机器的磁盘上创建任何文件

BOF的一个关键特性是它的运行时环境非常有限。它不能直接调用Windows API,而只能通过Cobalt Strike提供的一组函数来与操作系统进行交互。这样做的原因是为了防止BOF在运行时出错导致Beacon崩溃。

然而,尽管这种限制使得编写BOF相对复杂一些,但BOF仍然是一个非常强大的工具,可以用来添加各种自定义功能到Beacon中。

Bof开发

参考文章:https://github.com/evilashz/Visual-Studio-BOF-template

将Github中Visual-Studio-BOF-template项目下载,其中的模板文件解压至visualstudio的模板目录(%UserProfile%\Documents\Visual Studio 2022\Templates\ProjectTemplates)

这边重启VisualStuido之后就可以手动创建Bof项目了,如下图所示

创建完项目之后通过批处理生成Bof的x64和x86配置,这样后续一次编译就能生成x64和x86的obj文件,如下图所示

接着将项目改为Bof,这边写一个测试代码,输出当前电脑的DomainName信息,如下图所示

将上面的obj文件直接在cs中进行运行测试,如下图所示,当前机器没有处于域环境,输出error符合预期

inline-execute C:\Users\join\Desktop\demo\Bof.x64.obj

实现安装软件查询

参考文章:https://github.com/dtmsecurity/bof_helper

这边通过注册表查看软件安装情况,需要用到注册表相关的API,如果不知道这些API是在哪个DLL中实现的,这边可以通过bof_helper来进行查看

python bof_helper.py RegOpenKeyExA

main.cpp

#include "bofdefs.h"

extern "C" {
#ifdef BOF

	BOOL EnumInstalledSoft(CHAR* subKey, CHAR* subKeyName) {

		//DFR_LOCAL(NETAPI32, DsGetDcNameA);
		//DFR_LOCAL(NETAPI32, NetApiBufferFree);
		//DFR_LOCAL(KERNEL32, WinExec);

		DFR_LOCAL(ADVAPI32, RegOpenKeyExA);
		DFR_LOCAL(ADVAPI32, RegOpenKeyA);
		DFR_LOCAL(ADVAPI32, RegQueryValueExA);
		DFR_LOCAL(ADVAPI32, RegEnumKeyExA);
		DFR_LOCAL(ADVAPI32, RegCloseKey);

		//add ...
		HKEY hKey = NULL;
		HKEY hSubKey = NULL;
		DWORD dwIndexs = 0;
		CHAR keyName[MAX_PATH] = { 0 };
		DWORD dwLength = 256;
		CHAR subKeyValue[MAX_PATH] = { 0 };

		if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
		{
			while (RegEnumKeyExA(hKey, dwIndexs, keyName, &dwLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
			{
				RegOpenKeyA(hKey, keyName, &hSubKey);
				RegQueryValueExA(hSubKey,
					subKeyName,
					NULL,
					NULL,
					(LPBYTE)subKeyValue,
					&dwLength);
				BeaconPrintf(CALLBACK_OUTPUT, "%s : %s  \n", keyName, subKeyValue);
				RegCloseKey(hSubKey);
				hSubKey = 0;
				++dwIndexs;
				dwLength = 256;
			}
		}
		else
		{
			return FALSE;
		}
		if (hKey != NULL)
		{
			RegCloseKey(hKey);
			return TRUE;
		}
	}
#endif

void go(char* buff, int len) {

    //PDOMAIN_CONTROLLER_INFOA pdcInfo;
    //DWORD dwRet = DsGetDcNameA(NULL, NULL, NULL, NULL, 0, &pdcInfo);
    //if (ERROR_SUCCESS == dwRet) {
    //    BeaconPrintf(CALLBACK_OUTPUT, "%s", pdcInfo->DomainName);
    //}

    //NetApiBufferFree(pdcInfo);
	EnumInstalledSoft("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "DisplayName");
	EnumInstalledSoft("Software\\Classes\\Installer\\Products", "ProductName");
}


}
#ifndef BOF

void main(int argc, char* argv[]) {

    go(NULL, 0);
}

#endif

这边通过inline-execute来加载我们编译好的obj文件

inline-execute C:\Users\join\Desktop\demo\reg\BofDemo.x64.obj

运行结果如下图所示

Github Bof项目编译

可以使用Visual Studio或者MinGW进行编译生成.obj文件。

cl.exe /c /GS- hello.c /Fo hello.obj
i686-w64-mingw32-gcc -c hello.c -o hello.o
x86_64-w64-mingw32-gcc -c hello.c -o hello.o

cl编译中出现的-不包括路径集问题

参考文章:https://blog.csdn.net/weixin_41115751/article/details/89817123
参考文章:https://github.com/EncodeGroup/BOF-RegSave

在cl.exe生成obj文件的时候,可能遇到fatal error C1034: windows.h: 不包括路径集问题,产生这个的原因是没有设置对应的INCLUDE和LIB环境变量。

这里的还需要设置Visual Studio的Include的路径和SDK(windows kits)的路径。

这边即便是把Visual Studio的Include和SDK(windows kits)的环境变量都弄好了,发现还是会出现"不包括路径集问题"的问题,如下图所示

这边应该还缺少了其他的配置,所以我这边就直接通过VS自带的CMD工具vcvars64.bat进行编译,这边发现是可以正常编译的

cl.exe /c /GS- entry.c /Fo hello.obj

在生成.obj之后,先查看目前权限,因为当前bof实现的是导出sam文件

在CS控制台中直接执行getuid即可,如下图所示

确认了是高权限之后,这边通过加载obj文件,通过ls命令查看可以看到成功导出sam文件

inline-execute entry.obj

开发中遇到的问题

第一个问题:发现堆栈长度超出MAX_PATH之后,bof脚本就无法正常使用

解决方法:默认存在限制,将该变量通过calloc堆生成或者直接定义为全局变量即可解决

posted @ 2024-04-02 03:04  zpchcbd  阅读(1241)  评论(0)    收藏  举报