通过读取微信进程内存提取公众号信息流广告视频下载地址

背景

2026-03-15-18-47-23
在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 CacheIndexedDBGPUCache 等 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-processGPU渲染进程
–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.comwxsnsdy.wxs.qq.com(腾讯视频CDN)
  • 路径包含 ads_svp_video 标识这是广告视频
  • 参数 dis_t 是时间戳,可以用来判断哪个是最近的广告
  • 参数 dis_ksha256 用于鉴权

第四步:确认目标视频

有多个广告视频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下载

整个过程的关键点:

  1. 公众号信息流广告视频不缓存到本地磁盘,只在进程内存中存在
  2. 新版微信(xwechat)基于 Chromium 内核(RadiumWMPF),视频URL以明文形式保存在进程内存中
  3. 使用 Windows API OpenProcess + VirtualQueryEx + ReadProcessMemory 可以遍历读取目标进程的内存
  4. 广告视频URL的特征是域名为 wxsmw.wxs.qq.com,路径包含 ads_svp_video
  5. URL中的鉴权参数(dis_ksha256m)有时效性,需要在有效期内下载

注意事项

  • 需要以当前用户权限运行,不需要管理员权限(因为微信也是当前用户启动的)
  • 视频URL中的鉴权token有时效性,过期后需要重新扫描
  • 扫描过程中微信需要保持运行,且目标广告页面需要已加载过
  • 此方法同样适用于提取微信中其他流式加载的媒体内容的URL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值