CS BOF文件编写/改写

在这里插入图片描述

Beacon Object File(BOF) cs 4.1后添加的新功能,

Beacon在接收执行obj前,Cobalt Strike会先对这个obj文件进行一些处理,比如解析obj文件中一些需要的段.text,.data,在处理一些表比如IMAGE_RELOCATION,IMAGE_SYMBOL等等,然后在经过一系列的处理后,会把需要的部分按照一定格式打包起来随后在发送给Beacon,这时Beacon接收到的是Cobalt Strike已经解析处理过的obj文件数据,并非是原本的obj文件,所以Beacon主要做的是必须是在进程内才能确定并完成的事情比如处理重定位,填充函数指针等等,最后去执行go入口点

obj 目标文件就是源代码编译之后但是未进行链接的那些中间文件(Windows 下的 .obj 和 Linux 下的 .o,本文主要指windows 下的 obj )

使用BOF框架开发

很多大佬在 GitHub 发了一些模板,可以去参照

  • bof的visual studio模板:https://github.com/securifybv/Visual-Studio-BOF-template
  • bof所需的头文件:https://github.com/trustedsec/CS-Situational-Awareness-BOF
  • 整理好的,通过DLL名称将WindowsApi函数进行了归类:https://github.com/evilashz/Visual-Studio-BOF-template

将下载的模板文件解压至visualstudio的模板目录(%UserProfile%\Documents\Visual Studio 2022\Templates\ProjectTemplates),随后重启VisualStuido

image-20240102103237373

在创建项目时选择类型为Beacon Object File的项目

image-20240102103310526

在头文件列表可以看到beacon.hbofdefs.h

image-20240102103350426

build->batch build 打开项目的 Batch 生成,勾选上 BOF 配置

image-20240102103506658

配置管理器的编译环境也需设置为BOF

image-20240102103532153

一个简单的 bof 项目,用于实现向控制台输出字符串

  • BOF 入口:代码定义了 BOF 的入口函数 go,当你在 Cobalt Strike 中使用 inline-execute 命令加载并执行你的 BOF时,这个函数将被调用。你可以在这个函数中添加你的 BOF 代码
  • 非 BOF 入口:这部分代码定义了非 BOF 的入口函数 main。当你在非 Cobalt Strike 环境中运行你的代码时,这个函数将被调用。你可以在这个函数中添加你的非 BOF 代码
#include "bofdefs.h"

extern "C" {

#ifdef BOF
void go(char* buff, int len) {
    BeaconPrintf(CALLBACK_OUTPUT, "Hello, World!");
#endif
}

}
#ifndef BOF

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

    go(NULL, 0);
}

#endif

项目生成后会生成一个.obj文件,也就是编译未链接的目标文件,在CobaltStrike中你可以使用inline-execute命令来加载并执行你的.obj文件,此命令将你的 .obj 文件加载到 Beacon 的内存中,然后调用你的 go 函数,命令格式如下所示

beacon> inline-execute your_bof.obj

image-20240102145032414

修改为BOF格式

在原有利用代码基础上修改为 BOF 代码步骤

  1. 引入 beacon.h 头文件,beacon.h 定义了与 Cobalt Strike Beacon 交互所需要的各种数据类型和函数
  2. 把所有字符串和函数改成 ascii 的
  3. 把所有函数改成 beacon.h 定义的编写约定
  4. 入口函数由 main 修改为 go
  5. 生成 bof 文件

将 get-computer-installed-software 修改为 bof 加载,代码通过查询注册表获取当前机器安装的程序,这种方式仅对完整安装的软件有效,如果是绿色版的软件则只能通过手工或自动化搜索的方式查找,如果是x64位系统则需要对32位程序也进行遍历(x64系统存在注册表重定位)

#include <stdio.h>
#include <Windows.h>
#include <tchar.h>

BOOL EnumInstalledSoft(TCHAR* subKey, TCHAR* subKeyName) {
    HKEY hKey = NULL;
    HKEY hSubKey = NULL;
    DWORD dwIndexs = 0;
    TCHAR keyName[MAX_PATH] = { 0 };
    DWORD dwLength = MAX_PATH;  // 修改为合适的长度
    TCHAR subKeyValue[MAX_PATH] = { 0 };

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
    {
        while (RegEnumKeyEx(hKey, dwIndexs, keyName, &dwLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
        {
            RegOpenKey(hKey, keyName, &hSubKey);

            if (RegQueryValueEx(hSubKey, subKeyName, NULL, NULL, (LPBYTE)subKeyValue, &dwLength) == ERROR_SUCCESS)
            {
                _tprintf(_T("%s : %s  \n"), keyName, subKeyValue);
            }

            RegCloseKey(hSubKey);
            hSubKey = NULL;
            ++dwIndexs;
            dwLength = MAX_PATH;  // 重置为合适的长度
        }

        RegCloseKey(hKey);
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

int main()
{
    EnumInstalledSoft((TCHAR*)_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"), (TCHAR*)_T("DisplayName"));
    EnumInstalledSoft((TCHAR*)_T("Software\\Classes\\Installer\\Products"), (TCHAR*)_T("ProductName"));
    system("pause");
    return 0;
}

接下来导入 beacon.h 和替换 BOF 约定的写法,函数原型使用 bof_helper 自动化帮我们生成好bof约定的函数原型和写法,如把 GetProcAddress 换成 KERNEL32$GetProcAddress 的写法,这里直接使用工具,同时也需要把输出函数换成 beacon 导出的函数

BOF 格式代码

#include <stdio.h>
#include <windows.h>
// 1.添加 beacon.h 头
#include "beacon.h"

// 2.添加函数引入约定,可以去找找其他项目中有没有使用相同的函数
DECLSPEC_IMPORT WINADVAPI LONG WINAPI ADVAPI32$RegOpenKeyExA(HKEY, LPCWSTR, DWORD, REGSAM, PHKEY);
DECLSPEC_IMPORT WINADVAPI LONG WINAPI ADVAPI32$RegOpenKeyA(HKEY, LPCWSTR, PHKEY);
DECLSPEC_IMPORT WINADVAPI LONG WINAPI ADVAPI32$RegCloseKey(HKEY);
DECLSPEC_IMPORT WINADVAPI LONG WINAPI ADVAPI32$RegEnumKeyExA(
	HKEY,
	DWORD,
	LPWSTR,
	LPDWORD,
	LPDWORD,
	LPWSTR,
	LPDWORD,
	PFILETIME
);
DECLSPEC_IMPORT WINADVAPI LONG WINAPI ADVAPI32$RegQueryValueExA(
	HKEY,
	LPCWSTR,
	LPDWORD,
	LPDWORD,
	LPBYTE,
	LPDWORD
);

BOOL EnumInstalledSoft(CHAR* subKey, CHAR* subKeyName) {
	HKEY hKey = NULL;
	HKEY hSubKey = NULL;
	DWORD dwIndexs = 0;
	CHAR keyName[MAX_PATH] = { 0 };
	DWORD dwLength = 256;
	CHAR subKeyValue[MAX_PATH] = { 0 };

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

int go()
{
	EnumInstalledSoft((CHAR*)"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", (CHAR*)"DisplayName");
	EnumInstalledSoft((CHAR*)"Software\\Classes\\Installer\\Products", (CHAR*)"ProductName");
	return 0;
}

其余的 bof 格式差异

  • 参数传入

    目前代码没有传入参数,如果有参数传入,需要先声明参数

    void go(char* args,int length){
        datap parser;
        char* str_arg;
        int num_arg;
        
        str_arg = BeaconDataExtract(&parser,NULL);
    }
    
  • 输出

    使用 BeaconPrintf 替换 printf

    BeaconPrintf(CALLBACK_ERROR,"ERROR");
    

编译

使用 gcc 进行编译,需要提前安装

gcc -c 源文件.c -o 输出文件.o

ps:注意需要安装 64 位的程序,才能编译 64 位的 obj 文件,MinGW-w64安装教程

inline-execute 在 cs 中直接使用 bof 文件

bof 缺点

  1. 似乎无法使用初始化为0的全局变量
  2. 不太适合跑驻留型的任务,跑大量循环会崩溃
  3. 一旦引发崩溃整个beacon就会崩掉
  4. 不易调试
  5. 似乎输出不能使用unicode

参考文章

  • Beacon Object File(BOF实现原理)
  • 内网渗透神器CobaltStrike之BOF编写(十一)
  • Cobalt Strike BOF原理分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/347916.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT入门篇---无门槛学习

1.1 什么是 Qt Qt 是⼀个 跨平台的 C 图形⽤⼾界⾯应⽤程序框架 。它为应⽤程序开发者提供了建⽴艺术级图形界⾯所需的所有功能。它是完全⾯向对象的&#xff0c;很容易扩展。Qt 为开发者提供了⼀种基于组件的开发模式&#xff0c;开发者可以通过简单的拖拽和组合来实现复杂的…

RUST笔记 FireDBG| Rust 代码调试器

安装https://firedbg.sea-ql.org/blog/2023-12-12-introducing-firedbg/ 更新VSCODE sudo dpkg -i code_1.85.2-1705561292_amd64.deb 安装FireDBG binaries (base) pddpdd-Dell-G15-5511:~$ curl https://raw.githubusercontent.com/SeaQL/FireDBG.for.Rust/main/install.sh …

[极客大挑战 2019]PHP1

知识点&#xff1a; 1.序列化的属性个数大于实际属性个数可以绕过_wakeup() 详见[CTF]PHP反序列化总结_ctf php反序列化-CSDN博客 2.private属性类名和属性名前都会有多一个NULL&#xff0c;phpstorm运行结果可以显示出来&#xff0c;但是复制出去会变成空格&#xff0c;要手动…

【Single Cell Genomics】Part2 Deep representation learning (form theislab)

文章目录 7 Deep representation learning in single cell genomics7.1 scanpy7.2 DCA7.3 scGen: predicting single-cell perturbation effects7.4 Human cell atlas 来自Manolis Kellis教授&#xff08;MIT计算生物学主任&#xff09;的课 YouTube&#xff1a;Single Cell Ge…

关于达梦认证DCA DCP,TIDB认证PCTA PCTP考试那点事儿

文章最后有彩蛋&#xff0c;一定要看到最后... 一、正确的道路上遇到正确的你 伴随中国数据库领域的快速技术进步&#xff0c;国内数据库生态蓬勃发展&#xff0c;并不断涌现出极具创新力的产品&#xff0c;推动了数据库应用的遍地开花。截至2024年1月&#xff0c;墨天轮数据社…

SWMM模型INP解析

.INP文件解析 [OPTIONS]&#xff1a;SWMM软件运行前需要设置的参数 [RAINGAGES]雨水节点&#xff0c;核心设置雨水时间序列&#xff0c;可为INP内部数据也可为外部txt数据&#xff0c;TIMESERIES对应【TIMESERIES】模块&#xff0c;TS_1为时间序列名称 [TIMESERIES]&#xff0…

红黑树底层实现

什么是红黑树 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red&#xff08;红&#xff09;或Black&#xff08;黑&#xff09;&#xff0c;它是一种比AVL树在使用上更优秀的树&#xff0c;通过对任何一条从根…

微信小程序开发position等于static、relative、absolute、fixed、stricky时元素显示详细介绍

No Position 不设置position时显示,以红色元素做测试: Static 元素根据界面正常流进行定位。top、right、bottom、left 和 z-index 属性不起作用。这是默认值。 红色元素设置position: static,显示如下: Relative 元素根据界面正常流进行定位。以元素当前位置为基准,根…

g2o--ba代码解析

概要 g2o是常用的图优化理论c库&#xff0c;其自带了很多example讲解如何使用该库文件&#xff0c;本文分析其中ba的示例代码。 所谓的图优化&#xff0c;就是把一个常规的优化问题&#xff0c;以图&#xff08;Graph&#xff09;的形式来表述。 在图中&#xff0c;以顶点表…

单片机介绍

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

Spring Boot 模块工程(通过 Maven Archetype)建立

前言 看到我身边的朋友反馈说&#xff0c;IDEA 新建项目时&#xff0c;如果通过 Spring Initializr 来创建 Spring Boot , 已经无法选择 Java 8 版本&#xff0c;通过上小节的教程&#xff0c;不知道该如何创建 Spring Boot 模块工程。如下图所示&#xff1a; 一.IDEA 搭建 …

记录一下uniapp 集成腾讯im特别卡(已解决)

uniapp的项目运行在微信小程序 , 安卓 , ios手机三端 , 之前这个项目集成过im,不过版本太老了,0.x的版本, 现在需要添加客服功能,所以就升级了 由于是二开 , 也为了方便 , 沿用之前的webview嵌套腾讯IM的方案 , 选用uniapp集成ui ,升级之后所有安卓用户反馈点击进去特别卡,几…

【深度学习】CodeFormer训练过程,如何训练人脸修复模型CodeFormer

文章目录 BasicSR介绍环境数据阶段 I - VQGAN阶段 II - CodeFormer (w0)阶段 III - CodeFormer (w1) 代码地址&#xff1a;https://github.com/sczhou/CodeFormer/releases/tag/v0.1.0 论文的一些简略介绍&#xff1a; https://qq742971636.blog.csdn.net/article/details/134…

Mysql索引相关学习笔记:B+ Tree、索引分类、索引优化、索引失效场景及其他常见面试题

前言 索引是Mysql中常用到的一个功能&#xff0c;可以大大加快查询速度&#xff0c;同时面试中也是经常碰到。本文是学习Mysql索引的归纳总结。 索引采用的数据结构——B 树 本部分主要是参考自小林Coding B树的由来 二分查找可以每次缩减一半&#xff0c;从而提高查找效率…

【mongoDB】数据库的创建和删除

目录 1. 查看所有数据库 2.创建数据库 3.查看当前连接的数据库 4.删除数据库 1. 查看所有数据库 show dbs 2.创建数据库 use 数据库名 例如创建一个名为 aaa 的数据库 3.查看当前连接的数据库 db 4.删除数据库 use 数据库名 db.dropDataBase() 比如删除数据库 aaa

1.25号c++

1.引用 引用就是给变量起别名 格式&#xff1a; 数据类型 &引用名 同类型的变量名 &#xff08;& 引用符号&#xff09; eg: int a 10; int &b a; //b引用a,或者给a变量取个别名叫b int *p; //指针可以先定义 后指向 p &a; //int &a…

【MySQL】如何通过DDL去创建和修改员工信息表

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-fmKISDBsFq74ab2Z {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

docker(第二部分)

来自尚硅谷杨哥 少一点胡思乱想&#xff0c;心中无女人&#xff0c;编码自然神&#xff0c;忘掉心上人&#xff0c;抬手灭红尘。人间清醒&#xff0c;赚钱第一。好好学习&#xff0c;天天向上。听懂六六六。 7.Dokcer容器数据卷 1,&#xff09;坑&#xff1a;容器卷记得加入 …

shared_ptr 与 unique_ptr 的转换 笔记

推荐B站文章&#xff1a; 6.shared_ptr与unique_ptr_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV18B4y187uL?p6&vd_sourcea934d7fc6f47698a29dac90a922ba5a3我的往期文章&#xff1a; 独占指针&#xff1a;unique_ptr 与 函数调用-CSDN博客https://blog.csdn.n…

银行数据仓库体系实践(5)--数据转换

数据转换作业主要是指在数据仓库内的结构化数据批量加工&#xff0c;对于非结构化数据以及在线查询接口、数据流的开发主要是遵循代码开发规范以及各中间件的开发规范&#xff0c;如使用java来开发遵守java开发规范&#xff0c;使用Kafka需要遵循Kafka的使用和设计规范。同时做…