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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容