PC微信逆向) 定位微信浏览器打开链接的call

首发地址: https://mp.weixin.qq.com/s/Nik8fBF3hxH5FPMGNx3JFw

前言

最近想写一个免费的微信公众号自动采集的工具,我看公众号文章下载需求还挺多的。搜了下github,免费的工具思路大多都是使用浏览器打开公众号主页获取到需要的请求参数,例如key、uin等,然后再用参数请求历史。

优化

这些工具都需要自己复制公众号主页的链接发给文件传输助手然后打开,才能拦截到请求参数,那么能不能让这一步也让程序来完成呢?

简单的方式可以使用模拟点击,这个有兴趣的自行实现。这篇文章我说下基于逆向的方式在微信内置浏览器打开某个链接,这样实现可以更自动化一点,下面是具体的逆向和分析过程。

其他采集方案

在之前的一篇文章里我也说了其他一些采集方案,例如微信公众平台、微信读书等,有兴趣的可以看【Python微信机器人】写一个监控采集公众号文章的插件。不过听说微信读书已经开始加密了,而且采集的历史也不是很全,较早的文章可能获取不到。

对于微信公众平台来采集的可以参考aardio爬虫) 实战篇:采集自己的公众号粉丝列表,原理基本类似,都是先扫码获取到cookie,请求对应的接口,公众平台的接口都没加密。

还有基于逆向hook的采集方案,这个暂不公开。如果只是平时下载一下公众号文章的话,上面两种足够用了

方案优缺点

拦截参数对比逆向来说优点在于不需要固定微信的版本,更适合普通用户。因为逆向hook只能适用于特定版本,想不限版本,需要为每个版本做一遍适配,这明显不太可能。

而且基于逆向的方式采集还有可能有封号的风险,对于只想下几篇公众号文章的人来说,这个代价还是挺大的。当然逆向采集优点也很明显:稳定、无需人工操作、采集的数据量更多等。

逆向过程

下面逆向的版本选择的是3.9.6.32,选这个版本主要是之前的写的机器人用的这个版本,很多东西有现成的。最新的也没变,想看64位最新版的翻到最后,也会提几句。

日志定位

微信定位一个功能call最好也最方便的方式就是日志(肯定不是因为我只会这个)。打开链接的地方有多处,比如以下两个:

还有就是点击聊天记录里的链接来打开,这三种方式都试一下,看看日志之间有什么共同点,这样更容易定位到关键日志点。

方式1打开链接

方式2打开链接

聊天界面点击链接

前两个都有openUrlWithExtraWebview,看名称应该就是微信在调用打开浏览器,但是这里还处于比较上层的位置,如果你在这里打断点的话,会触发多次,不止打开浏览器才触发,并且看了下参数比较复杂,有一堆句柄和回调不好处理,所以这里先不考虑了。

WebViewMgr:user setting这个日志比较重要,因为三个日志里都有它,而且正好处于openUrlWithExtraWebviewAddTab的中间位置,看上去像是打开浏览器时初始化配置。

感觉在这里打上断点应该能在调用堆栈里找到打开浏览器的call。先在IDA里搜索user setting(x64dbg里搜索这个字符串也可以,我比较喜欢看IDA,有伪C代码看比汇编直观一点),然后定位到下面的位置:

接着翻到函数头,在x64dbg里函数头的位置打上断点,接着打开一个链接让断点断下

右键右下角堆栈的返回地址选择在反汇编中转到指定DWORD(也就是函数调用的地方),然后在IDA中查看这个地址,翻到函数头的位置看到了比较关键的日志信息(showWebView),在函数头继续打上断点

查看调用的位置,先看看IDA里这里所在的函数在做些什么操作,看上去是在解析json,而且看到了日志有OpenUrlWithExtraWebviewHandler,看名称这里就是处理OpenUrlWithExtraWebview事件的回调,那前面解析json就是在解析之前日志里的json

在头部打上断点,看看传入的参数是不是就是之前的json。如下图,虽然参数不是之前看到的json字符串,但是和json内容基本一样,估计上层函数又对json做了解析,那这里肯定是处理OpenUrlWithExtraWebview事件的回调函数,也就是在这个函数里打开的链接

那关键位置基本就是上面提到的showWebView函数了,下面开始分析函数的参数和几个需要调用的call。

分析参数

这里只有ecx是未知的,看了下ebp-0x90C在上面就有,估计是上面赋值的,打上断点看一下,一般复制的结构体都有函数可以生成,不需要去关心怎么构造。当然,如果构造的call离的太远且结构体也不负责的话也可以自己构造。

分析的结果如上,这里没什么复杂的参数,只需要传一个url就可以。前面在查看函数引用的时候,看到有的地方调用6CC52610时不是push的这几个值,也就是说这四个值并不是固定的,而是用于控制某些变量。

比如用系统默认浏览器打开则是下面的参数:

可能的组合(每行一种,最后一位是edx)

0 1 0 0 4
0 1 1 0 4
0 1 0 0 2
0 1 0 1 4
0 1 0 0 0
0 1 0 1 2
1 1 0 0 4
0 1 1 0 5
0 1 1 0 8
1 1 0 0 0
1 1 0 0 4

可以自己都测试一遍,不过看日志有的可能是打开小程序相关的,参数不一样也许会崩溃,具体案例具体分析吧。还有一个点,调用这四个call,堆栈不平衡,需要加上add esp, 0x10;(不一定这么处理,也可能是少call,单步走看看到哪个call平栈了),我看其他地方调用这个call都是使用的add esp, 0x10;,所以猜测这里加上这个也能运行。下面还有一个call是释放ebp-0x90C结构体里的内存,也需要调用一下。

完整代码
DWORD ShowVebView(wchar_t* url) {
    size_t urlLen = wcslen(url);

    DWORD WeChatWinBase = GetWeChatWinBase();
    DWORD dwCall1 = WeChatWinBase + 0x77A430;
    DWORD dwCall2 = WeChatWinBase + 0xF67310;
    DWORD dwCall3 = WeChatWinBase + 0x76CC70;
    DWORD dwCall4 = WeChatWinBase + 0x1602610;
    DWORD dwCall5 = WeChatWinBase + 0x77A790;

    DWORD ebp_0x90C[0x500] = { 0 };

    __asm {
        pushad;
        lea ecx, ebp_0x90C;
        call dwCall1;
        push urlLen;
        push url;
        lea eax, ebp_0x90C;
        lea ecx, [eax + 0x56C];
        call dwCall2;
        call dwCall3;
        push 0x0;
        push 0x1;
        push 0x0;
        push 0x0;
        xor edx, edx;
        lea ecx, ebp_0x90C;
        call dwCall4;
        add esp, 0x10;
        lea ecx, ebp_0x90C;
        call dwCall5;
        popad;
    }

    return 0;
}

编译成dll注入到进程,调用ShowVebView正常打开链接。

64位

以能下载到的最新版为例(3.9.10.27),其实32位和64位微信逻辑是一样的,同样在x64dbg里搜索user setting,在引用的函数头打断点找到调用点,然后接着在函数头打断点找到调用点,关键位置如下图(基址是00007FF86A160000):

逻辑一模一样,只是64位无法内联汇编,可以用函数指针来调用。大概代码如下:

typedef UINT64 (*dwCall1Ptr)(UINT64);
dwCall1Ptr dwCall1 = (dwCall1Ptr)0x7FF86BD82C70;
DWORD rbp_0x100[0x500] = {0};
UINT64 addr = dwCall1(&rbp_0x100);

typedef UINT64 (*dwCall2Ptr)(UINT64,wchar_t*,UINT64);
dwCall2Ptr dwCall2 = (dwCall2Ptr)0x7FF86C840C10;
wchar_t* url = (wchar_t*)L"";
dwCall2(addr+0x***, url, wcslen(url));

typedef UINT64 (*dwCall3Ptr)();
dwCall3Ptr dwCall3 = (dwCall3Ptr)0x7FF86BD72AE0;
dwCall3();

typedef UINT64 (*dwCall4Ptr)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
dwCall4Ptr dwCall4 = (dwCall4Ptr)0x7FF86D24E9B0;
dwCall4(addr, 0,0,0,1,0);

typedef UINT64 (*dwCall5Ptr)(UINT64);
dwCall5Ptr dwCall5 = (dwCall5Ptr)0x7FF86BD82EA0;
dwCall5(addr);

上面只是伪代码,需要自己调试改成能运行的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/706193.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

云化XR什么意思,Cloud XR是否有前景?

云化XR(CloudXR)什么意思? 云化XR(CloudXR)是一种基于云计算技术的扩展现实(XR)应用方式,将XR体验从本地设备转移到云端进行处理和交付。它通过将计算和渲染任务放置在云端服务器上…

Linux基础IO【II】真的很详细

目录 一.文件描述符 1.重新理解文件 1.推论 2.证明 2.理解文件描述符 1.文件描述符的分配规则 3.如何理解文件操作的本质? 4.输入重定向和输出重定向 1.原理 2.代码实现重定向 3.dup函数 ​编辑 4.命令行中实现重定向 二.关于缓冲区 1.现象 …

Modbus转Profinet网关的IP地址怎么设置

在工业自动化领域,Modbus和Profinet是两种常用的通信协议,而网关可以实现不同协议之间的转换,使得不同设备能够互相通信。本文将详细介绍如何设置Modbus转Profinet网关(XD-MDPN100)的IP地址,让您轻松实现设…

vue相关的2个综合案例,网页打字练习

for循环的应用 /* 1. 用for循环控制台打印0到100 */ for (var i 0; i < 100; i) {console.log(i) } /* 2. 用for循环控制台打印100到0 */ for (var i 100; i > 0; i--) {console.log(i) }网页打字练习案例练习 <template><div class"main"><…

洛谷P1305 新二叉树(树的基本遍历)

题目描述 输入一串二叉树&#xff0c;输出其前序遍历。 输入格式 第一行为二叉树的节点数 &#x1d45b;。(1≤&#x1d45b;≤26) 后面 &#x1d45b; 行&#xff0c;每一个字母为节点&#xff0c;后两个字母分别为其左右儿子。特别地&#xff0c;数据保证第一行读入的节点…

IPTCP知识

1. IP&#xff1a; IP地址是一个32位的二进制数&#xff0c;通常被分割为4个“8位二进制数”IP地址分类&#xff1a;A类地址、B类地址、C类地址、D类地址、E类地址 A类地址分配给规模特别大的网络使用&#xff0c;B类地址分配给一般的中型网络&#xff0c;C类地址分配给小型网…

STM32无法烧写程序的故障排除

如果你在使用STM32微控制器时遇到无法烧写程序的问题&#xff0c;可以按以下步骤进行故障排除&#xff1a; 1. 确认硬件连接 检查电源&#xff1a;确保STM32板子正确供电。调试器连接&#xff1a;确认ST-LINK调试器或其他编程工具与STM32开发板的连接无误&#xff0c;尤其是S…

如何基于 Python 快速搭建 QQ 开放平台 QQ 群官方机器人详细教程(更新中)

注册 QQ 开放平台账号 账号注册 QQ 机器人&#xff1a;一个机器人可以被添加到 群聊/频道 内对话&#xff0c;QQ 用户也可以直接跟机器人 单独对话。 开发者账号主体要求 单聊对话&#xff1a;【定向邀请】 群聊场景&#xff1a;仅支持企业主体【个人主体暂不支持】 频道场…

基于uni-app与图鸟UI打造的各领域移动端模板大赏

随着移动互联网的迅猛发展&#xff0c;各类移动端应用层出不穷&#xff0c;为了帮助企业快速搭建高效、美观的移动平台&#xff0c;我们基于强大的uni-app与图鸟UI&#xff0c;精心打造了不下于40套覆盖多个领域的移动端模板。今天&#xff0c;就让我们一起领略这些模板的风采吧…

淘宝镜像地址失效

1. 使用nvm安装node时候报错 报错内容 Get "https://npm.taobao.org/mirrors/node/latest/SHASUMS256.txt": tls: failed to verify certificate: x509: certificate has expired or is not yet valid:报错原因 淘宝镜像地址的证书过期了 解决 找到nvm安装的根目…

Java-集合类-Arrays.asList()使用需要注意的大坑

Arrays.asList使用需要注意的大坑 大坑1.不可修改列表大小&&原始数组与列表共享数据2.对于基本类型数组的使用限制 两个错误案例wrong1wrong2 ​ Arrays.asList() 是 Java 中一个常用的方法&#xff0c;它 用于将数组转换为列表&#xff08;List&#xff09;。这个方…

Bybatis动态SQL的绑定和公共sql语句片段

Mybatis除了大部分动态标签&#xff0c;最后还有三个标签&#xff0c;分别是bind&#xff0c;sql和include&#xff1a; ①bind&#xff1a;这个标签作用就是将OGNL标签里的值&#xff0c;进行二次加工&#xff0c;在绑定到另一个变量里&#xff0c;供其他标签使用 调用getUse…

Java—集合简述

集合类继承结构图 Collection|---------------------| | | Set List Queue| | | SortedSet ArrayList Deque| LinkedList | NavigableSet Vector ArrayDeque| Stack | TreeSet …

数据结构笔记-2、线性表

2.1、线性表的定义和基本操作 如有侵权请联系删除。 2.1.1、线性表的定义&#xff1a; ​ 线性表是具有相同数据类型的 n (n>0) 个数据元素的有限序列&#xff0c;其中 n 为表长&#xff0c;当 n 0 时线性表是一个空表。若用 L 命名线性表&#xff0c;则其一般表示为&am…

【软件工程导论】——期末复习(冲刺篇)

&#x1f4d6; 前言&#xff1a;快考试了&#xff0c;做篇期末总结&#xff0c;都是重点与必考点。 题型&#xff1a;材料分析题、简答题、看图分析题 课本&#xff1a; 目录 &#x1f552; 1. 软件生存周期与软件过程&#x1f558; 1.1 软件生存周期&#x1f558; 1.2 传统…

Java老人护理上门服务类型系统小程序APP源码

&#x1f338; 老人上门护理服务系统&#xff1a;温暖与专业并存 &#x1f338; 一、&#x1f3e0; 走进老人上门护理服务系统 随着社会的快速发展&#xff0c;我们越来越关注老年人的生活质量。老人上门护理服务系统应运而生&#xff0c;它结合了现代科技与人性化服务&#…

webpack代码分割

webpack代码分割方式 entry配置&#xff1a;通过多个 entry 文件来实现动态加载(按需加载)&#xff1a;通过主动使用import来动态加载抽取公共代码&#xff1a;使用splitChunks配置来抽取公共代码 基础概念 概念含义Entry入口&#xff0c;Webpack 执行构建的第一步将从 Entr…

Adobe Illustrator (AI)小技巧总结

AI2024(64bit) Adobe Illustrator 软件安装包下载地址&#xff1a; 百度网盘下载https://pan.baidu.com/s/1C10-2JVN1rxFF5VFRuV2Yw?pwdSIMS 1.效果-扭曲与变换-变换&#xff0c;两个图形组合&#xff08;CtrlG&#xff09;中心点在中间 例&#xff1a;角度7.5副本24半圆48格…

pdf格式转成jpg图片,pdf格式如何转jpg

pdf转图片的方法&#xff0c;对于许多人来说可能是一个稍显陌生的操作。然而&#xff0c;在日常生活和工作中&#xff0c;我们有时确实需要将pdf文件转换为图片格式&#xff0c;以便于在特定的场合或平台上进行分享、展示或编辑。以下&#xff0c;我们将详细介绍一个pdf转成图片…

网工内推 | 外企、上市公司运维工程师,有软考中高项证书优先

01 优尼派特&#xff08;苏州&#xff09;物流有限公司 &#x1f537;招聘岗位&#xff1a;软件运维测试工程师 &#x1f537;任职要求&#xff1a; 1、负责公司自主研发的软件售后服务工作, 包括软件的安装, 调试, 升级,培训, 参数配置, 需求与Bug的处理; 2、负责数据库升级及…