bof小测

    渗透测试 lz520520 9个月前 (03-19) 287次浏览

    一个正常C程序,如何转换成bof文件,这里记录下过程

    bof的原理实现就不多讲了,简单来说就是编译成一个object文件(COFF格式,exe是PE格式),然后传输给beacon后在终端上完成链接过程,这也就导致bof文件非常小,一般只有几K。

    参考

    https://wbglil.gitbook.io/cobalt-strike/cobalt-strike-yuan-li-jie-shao/untitled-3

    编写bof代码

    在github有几个不错的开源项目,可以以此为模板进一步开发,而不需要完全重头开始。

    https://github.com/trustedsec/CS-Situational-Awareness-BOF

    https://github.com/securifybv/Visual-Studio-BOF-template

    我是基于第一个项目开发,这个项目有很多已实现的案例,可作为参考。

    SA目录就是编译成object的文件,用于直接提供cs使用

    src是源码目录,除了已实现功能的源码,还提供了一个base_template作为模板。

    bof小测

    将base_template拷贝一份到src/SA下,改成如useradd,BOFNAME也修改一下,方便发布。

    bof小测

    然后看下核心代码部分,这里其实考虑到了两种使用场景了,bof提供cs使用,exe供独立使用,也方便调试功能是否正常,编译的时候只需要带上-DBOF即可编译成bof。

    bof和exe入口区别如下,exe固定是main函数入口,bof会由加载器扫描go函数的地址作为入口,当然也可以是其他名字,默认是go。

    bof小测

    bof编写,一般会导入一个beacon.h,有一些内置的函数提供,比如我要打印内容给teamsever显示,就可以调用BeaconPrintf,其他函数和使用可参考这个官方链接

    https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/beacon-object-files_main.htm

    接着就是编写功能了,比如添加用户,这里有个C项目,有现成代码。

    https://github.com/newsoft/adduser

    代码比较简单,调用NetUserAdd添加用户,然后调用NetLocalGroupAddMembers加administrators组

    bof小测

    但这些都是直接调用的win32api,如果看了上面提供的bof官方文档,就会知道这些api需要动态加载调用,不像是PE文件有导入表,那官方提供了两种方法,一是调用loadlibrary等函数动态加载,二是动态函数解析(DFR),我这里选择后者,这个方便些。

    bof小测

    在src\common\bofdefs.h添加宏定义,用于动态函数解析

    并添加函数声明,用于外部调用

    如上操作即可完成动态函数解析。然后在我们要编写的代码里替换成带有lib名称的函数即可。

    bof小测

    繁琐的地方主要在于要查微软官方文档,然后才知道函数签名。

    这个项目自动完成这个过程了,通过一个本地函数库获取函数签名,再通过微软在线查询该函数对应的lib文件名是什么,拼接实现上面声明代码。

    https://github.com/dtmsecurity/bof_helper

    效果如下,然后最后一行复制到bofdefs.h里即可

    bof小测

    把需要打印回显的位置替换成BeaconPrintf,bof的项目还做了一个封装,更方便使用,internal_printf

    bof小测

    使用make bof尝试编译是否正常

    bof小测

    然后用cs调用,可以正常加载,但有个问题,这样是无法传参的。

    bof小测

    比如这样是无法传参的

    参数解析问题

    看下go的入口解析参数代码,这个是参考其他功能的代码,cs内置一个datap数据类型,用于数据解析,先调用BeaconDataParse将缓存放入parser,再通过BeaconDataExtract提取。

    bof小测

    参看官方手册,提供了五种函数用于数据提取,也就是说数据类型也5种,int/char/wchar_t/short等,那如果是命令行传递是不可能知道数据类型的。仔细看文档第一行,提示了,需要结合cna脚本的bof_pack函数来pack格式化参数传递,所以需要编写cna脚本了。

    bof小测

    cna脚本编写

    这个bof项目也提供了现成的cna脚本,所以只需要参考改一下即可

    代码如下,很简单,添加一个函数useradd,然后通过beacon_command_register注册

    PS: readbof是这个项目自定义的函数,用于读取bof完整文件名。

    bof_pack参考

    https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#bof_pack

    这里也和bof里的函数关联起来了,你怎么格式化,bof里就怎么解析。

    bof小测

    bof_pack

    $1: beacon id

    $2: format string for the packed data

    ...: args

    格式化参考

    TypeDescriptionUnpack With (C)
    bbinary dataBeaconDataExtract
    i4-byte integerBeaconDataInt
    s2-byte short integerBeaconDataShort
    zzero-terminated+encoded stringBeaconDataExtract
    Zzero-terminated wide-char string(wchar_t *)BeaconDataExtract

    bof解析参数时注意事项

    1. 如果是BeaconDataExtract赋值给某个char变量 ,一定要是const char,否则会crash。
    2. 如果调用了bofstart,解析一定要在这后面,否则也会crash

     

     

    beacon_inline_execute

    $1 - the id for the Beacon

    $2 - a string containing the BOF file

    $3 - the entry point to call

    $4 - packed arguments to pass to the BOF file

    重新加载cna脚本

    bof小测

    bof文件大小写和PE文件相比,这个demo中差了近百倍。

    bof小测

    参考

    https://www.cobaltstrike.com/help-beacon-object-files

    https://gitee.com/sh3llsas/CobaltStrike-BOF

    https://wbglil.gitbook.io/cobalt-strike/cobalt-strike-yuan-li-jie-shao/untitled-3

    https://github.com/ajpc500/BOFs/

    https://github.com/boku7/spawn

    cna参考链接

    https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm

     


    Security , 版权所有丨如未注明 , 均为原创丨
    转载请注明原文链接:bof小测
    喜欢 (1)