背景

在PC端微信的公众号列表中,经常会看到信息流广告视频,比如游戏广告。这些广告视频有时候挺有意思,想下载下来,但微信并没有提供下载按钮。比如看到这个广告视频的妹妹很好看🤪,那么应该怎么下载呢?本文以这个"三国冰河时代"游戏广告为例,介绍如何通过读取微信进程内存来提取广告视频的下载地址。
尝试一:寻找本地缓存文件(失败)
首先想到的思路是微信可能把视频缓存到了本地磁盘。微信PC端的数据目录一般在:
C:\Users\{用户名}\Documents\WeChat Files\{微信ID}\FileStorage\
该目录下有这些子目录:
Cache、Video、Image、Temp、Sns、MsgAttach ...
其中 Video 目录按月份分文件夹存放:
2024-04、2024-05、... 2025-08
但逐个检查后发现这些目录要么为空,要么只有聊天中收发的视频。公众号信息流广告的视频并不会被缓存到这里。
同样检查了 AppData 下的微信目录:
C:\Users\{用户名}\AppData\Roaming\Tencent\WeChat\
C:\Users\{用户名}\AppData\Roaming\Tencent\xwechat\
新版微信(xwechat)使用了 Chromium 内核(RadiumWMPF),有类似浏览器的缓存结构:
xwechat\radium\web\profiles\webview_{用户hash}\
xwechat\radium\web\profiles\multitab_{用户hash}\
里面有 Code Cache、IndexedDB、GPUCache 等 Chromium 标准缓存目录,但也没找到视频文件。
结论:公众号信息流广告视频是流式加载的,不会完整缓存到本地磁盘。
尝试二:通过开发者工具/远程调试(失败)
既然新版微信使用 Chromium 内核,理论上可以通过 --remote-debugging-port 参数连接 DevTools 来抓取网络请求。
查看微信进程的命令行参数:
Get-CimInstance Win32_Process -Filter "Name='WeChatAppEx.exe'" | Select-Object ProcessId, CommandLine
发现主进程的启动参数中并没有 --remote-debugging-port,说明远程调试未开启,这条路也走不通。
尝试三:进程内存扫描(成功)
既然视频是流式加载的,那视频的URL一定在微信进程的内存中。思路是:直接读取微信进程内存,搜索视频URL模式。
第一步:定位微信进程
Get-Process | Where-Object { $_.ProcessName -match 'wechat' } |
Select-Object Id, ProcessName, Path
发现微信运行了多个 WeChatAppEx.exe 进程,这是典型的 Chromium 多进程架构:
| 进程类型 | 说明 |
|---|---|
| 主进程(无 --type 参数) | 浏览器主进程,包含页面数据 |
| –type=gpu-process | GPU渲染进程 |
| –type=renderer | 页面渲染进程 |
| –type=utility --utility-sub-type=network | 网络服务进程 |
我们要扫描的是主进程(没有 --type 参数的那个)。
第二步:编写内存扫描脚本
通过 PowerShell 调用 Windows API 来读取进程内存:
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
public class MemoryReader {
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(
int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(
IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer,
int dwSize, ref int lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern int VirtualQueryEx(
IntPtr hProcess, IntPtr lpAddress,
out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hObject);
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION {
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public uint AllocationProtect;
public IntPtr RegionSize;
public uint State;
public uint Protect;
public uint Type;
}
}
'@
核心逻辑是遍历进程的所有已提交内存区域(MEM_COMMIT = 0x1000),读取内容后用正则匹配视频URL:
$targetPid = 42172 # 微信主进程PID
$handle = [MemoryReader]::OpenProcess(0x0410, $false, $targetPid)
# 0x0410 = PROCESS_VM_READ | PROCESS_QUERY_INFORMATION
$address = [IntPtr]::Zero
$mbi = New-Object MemoryReader+MEMORY_BASIC_INFORMATION
while ([MemoryReader]::VirtualQueryEx(
$handle, $address, [ref]$mbi,
[uint32][Runtime.InteropServices.Marshal]::SizeOf($mbi)) -ne 0)
{
# 只扫描已提交的、大小合理的内存区域
if ($mbi.State -eq 0x1000 -and
$mbi.RegionSize.ToInt64() -lt 10MB -and
$mbi.RegionSize.ToInt64() -gt 0)
{
$buffer = New-Object byte[] ($mbi.RegionSize.ToInt64())
$bytesRead = 0
if ([MemoryReader]::ReadProcessMemory(
$handle, $mbi.BaseAddress, $buffer,
$buffer.Length, [ref]$bytesRead))
{
$text = [System.Text.Encoding]::UTF8.GetString($buffer)
# 匹配广告视频URL模式
$regex = 'https?://[^\x00\s"<>]{10,500}' +
'(?:\.mp4|mpvideo|finder.*video|wxv_|video\.qq|findermp)' +
'[^\x00\s"<>]{0,200}'
$matches = [regex]::Matches($text, $regex)
foreach ($m in $matches) {
$url = $m.Value -replace '[\x00-\x1f]', ''
if ($url.Length -gt 20) {
Write-Host $url
}
}
}
}
$address = [IntPtr](
$mbi.BaseAddress.ToInt64() + $mbi.RegionSize.ToInt64())
if ($address.ToInt64() -lt 0) { break }
}
[MemoryReader]::CloseHandle($handle)
第三步:扫描结果
扫描了 2357 个内存区域,找到了 115 个视频URL,去重后主要是以下几个广告视频(来自 wxsmw.wxs.qq.com 域名):
http://wxsmw.wxs.qq.com/.../ads_svp_video__0bc3qyabeaaacyapvlro4zurvbqeckdaaesa.f142000.mp4?dis_k=...&dis_t=1764683224&...
http://wxsmw.wxs.qq.com/.../ads_svp_video__0b53xabuuaad6aap6xr4u5ubtoaejk4agssa.f142000.mp4?dis_k=...&dis_t=1749005722&...
http://wxsmw.wxs.qq.com/.../ads_svp_video__0b53qiaowaaapmaabparcrubvaqe5obab22a.f142000.mp4?dis_k=...&dis_t=1746007401&...
URL的规律:
- 域名:
wxsmw.wxs.qq.com或wxsnsdy.wxs.qq.com(腾讯视频CDN) - 路径包含
ads_svp_video标识这是广告视频 - 参数
dis_t是时间戳,可以用来判断哪个是最近的广告 - 参数
dis_k和sha256用于鉴权
第四步:确认目标视频
有多个广告视频URL,需要确认哪个是"三国冰河时代"。用同样的内存扫描方法,搜索中文关键词"三国"(注意要同时搜索 UTF-8 和 UTF-16LE 两种编码,因为 Windows 进程内存中两种编码都可能存在):
# UTF-8 编码的"三国"
$searchUtf8 = [System.Text.Encoding]::UTF8.GetBytes('三国')
# UTF-16LE 编码的"三国"
$searchUtf16 = [System.Text.Encoding]::Unicode.GetBytes('三国')
在内存中确实找到了多处"三国冰河时代"的引用,包括:
- 公众号文章元数据:
"三国冰河时代挥师定山河活动解析" - 搜索记录:
"query": "三国 冰河时代" - 视频播放记录:
kVideoTracks...三国 冰河时代 - 搜一搜,编码格式h264 high
通过 dis_t 时间戳判断,最新的广告视频URL就是目标视频。
第五步:下载视频
直接用 curl 下载:
curl -o "三国冰河时代_广告视频.mp4" "http://wxsmw.wxs.qq.com/131/20210/snssvpdownload/SH/reserved/ads_svp_video__0bc3qyabeaaacyapvlro4zurvbqeckdaaesa.f142000.mp4?dis_k=...&dis_t=...&sha256=...&m=...&posid=..."
返回 HTTP 200,文件大小约 7MB,Content-Type: video/mp4,下载成功。
原理总结
微信公众号信息流
↓ 加载广告
腾讯CDN(wxsmw.wxs.qq.com)
↓ 流式传输视频
WeChatAppEx.exe 进程内存
↓ ReadProcessMemory
提取视频URL → curl下载
整个过程的关键点:
- 公众号信息流广告视频不缓存到本地磁盘,只在进程内存中存在
- 新版微信(xwechat)基于 Chromium 内核(RadiumWMPF),视频URL以明文形式保存在进程内存中
- 使用 Windows API
OpenProcess+VirtualQueryEx+ReadProcessMemory可以遍历读取目标进程的内存 - 广告视频URL的特征是域名为
wxsmw.wxs.qq.com,路径包含ads_svp_video - URL中的鉴权参数(
dis_k、sha256、m)有时效性,需要在有效期内下载
注意事项
- 需要以当前用户权限运行,不需要管理员权限(因为微信也是当前用户启动的)
- 视频URL中的鉴权token有时效性,过期后需要重新扫描
- 扫描过程中微信需要保持运行,且目标广告页面需要已加载过
- 此方法同样适用于提取微信中其他流式加载的媒体内容的URL
4万+

被折叠的 条评论
为什么被折叠?



