逆向WeChat(四)
本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18209439
mars
先回顾一下,在上两篇我对wechat如何使用chrome::base框架的分析中存有错漏。首先要指出,逆向分析是一个过程。需要经过不断假设,推断,求证,验证。花费时间一步一步将结果改进完善的循序渐进的过程。当前的内容只代表当前分析的过程跟结果,当前的分析是以当前局限的结果作为前提的。还在逆向分析初期,我只运行少量功能场景,忽略了TaskScheduler除了Pump外。还有就是wechat在初始化时,已经将主线程的TaskRunner保存到了全局变量,用作主线程的dispatch_main_queue,供全局使用。但是EventCenter仍然是中心。
回到本篇内容,mars。
在逆向分析,我发现了StartTask的实际代码,将stn::Task进行了十次copy构造。一个320字节的结构,有10多个string,几个vector<string>,一个map<string,string>。佐证在本篇后面。
作为network模块,先来看SocketSelect。windows基于WASSelect,macos基于kevent,linux android它也看作unix,这个有点偷懒。对于看热闹的人来说linux是类unix系统,但是对于unix系统使用者就不买这个帐,unix跟linux就是两个东西。macos是基于freebsd,是unix分支,内核用kqueue,macos的MachPort就是基于kqueue。linux有它独用的epoll,好像也始于2.6内核的时代,内核并没kqueue。mars在非macos的系统中通通由poll来解决。这不是问题的关键。因为每一个tcp连接开一个线程,没有事件分离器复用。我也是惊了个呆。难怪低配置的安卓手机直接用不起,记得N年前28nm的晓龙425还可以运行微信6,微信7后因为旧版登陆接口不支持,强制升级微信后只能卡死在登陆进行转进入主界面。一个28nm的4cores1.4g的旧cpu且只带2GB运存的破手机,在2024年还可以运行最新版淘宝,大部分功能。不知道这东西,是不是如项目描述那样,在它自家的产品中跨平台使用了。freebsd,darwin-xnu,linux-kernel在github都有源代码。
window需要vc2015,那么姑且需要c++14,clang3.4于2013年就支持了,xcode跟ndk同样适用。c++14已经有不少boost库的东西,而且lambda也很成熟了。用boost::bind看着真的头晕。年轻时我也曾非boost不够cool。boost::bind(method, this, _1, _2, _3, _4, _5, _6),用python言语就是lambda a,b,c,d,e,f: this.method(a, b, c, d, e, f),用c++11的lambda就是[=](auto& a, auto& b, auto& c, auto& d, auto& e, auto& f) { return this->method(a, b, c, d, e, f); },以及std::function<auto(, , , , , , )>。boost::bind也就等同lambda的一种实现方式。调试有boost的项目时有个无尽长的名字我却不知道你是什么的恶梦。
在mars的设计中,mars既是namespace也是目录,mars下一级就是子模块,同样既是namespace也是目录,如mars::comm,mars::sdt,mars::stn。这里不能不说是在参考了java的包层级。
stn,我认为就是简单的首字命名,Strategy,Task,Network。重点就是network,这是一个network模块。至于Strategy就简单理解成ShortLink,LongLink。Task,原本咋一看还以为comm::mq分派Task,这个stn是一个分派中心,包括Task还有socket操作,Strategy类似于scheduler。实质却不是这样。Task就是在一个ShortLink或LongLink上完成一轮Request-Response。这个Task的设计就类似于js的XMLHttpRequest。js中,xhr = new XMLHttpRequest; xhr.onreadystatechange= function() {} ; xhr.open(); xhr.send(request_packet)。再来看mars,tsk = new Task(request_packet); tsk.OnEndTask = lambda; mars::stn::StartTask(tsk); 同一配方。所以我认为stn就是mars核心的network模块。
至于comm目录下的东西。socket跟network子目录只是些底层socket相关的api跟数据结构的封装,Facade模式。thread子目录转到平台对应的子目录。也是同步,TSS等相关的Facade封装。messagequeue子目录,我原来以为会是mars的重要的东西,跟它的线程模型会的密切关联。这个messagequeue的设计,就是在模仿Java的RunLoop。概念是一个线程对应一个messagequeue,线程id作为队列id。由绑定的MessageHandler处理message,只能用MessageHandler投递消息。在java中,handler = new Handler(Loop()); handler.SendMessage();handler.post();。回到mars上。messagequeue必须加上一个RunLoop构成一个Pump在线程中pump。MessageQueueCreater是一个自带线程以及Pump的类,它存在于stn::NetCore,comm::GetDefMessageQueue,还有comm::GetDefTaskQueue。如果你没有InstanllAsyncHandler去安装一个MessageHandler专门将message作为runnable处理,就是有Pump在线程运行也不分派runnable。几乎stn内每个功能类都有一个默认到comm::GetDefMessageQueue的MessageHandler,用来进行AsyncInvoke,但又似乎stn都基本上没有怎么用。(分别只这几处使用:Alarm.cc, BroadcastMessage。signalling_keeper.cc, AsyncInvokeAfter。zombi_task_manager.cc SingletonMessage。netsource_timechecker.cc, AsyncInvokePeriod。ActiveLogic::OnForeground, AsyncInvoke。)。并非,comm::mq::Callback,是可以绑定MessageHandler,用来Handler2Queue投递AsyncInvoke。还有SYNC2ASYNC宏,所以shortlink跟longlink的OnResponse是AsyncInvoke进行的。还有ASYNC_BLOCK_START宏,StartTask也是AsyncInvoke进行的。整个设计有一个核心关键字,就是RunLoop,所有东西都要绕进来,什么类几乎都有一个RunLoop函数。还有就是Breadker,它为Condition又起了一个名。所以有这么一个函数BreakMessageQueueRunloop,从字面上还以为要中断一个线程的RunLoop,但实质是在做相反的事,breaker->notify(),快唤醒那个线程。这个RunLoop跟CFRunLoop,CFSocket的编程好像一个性子。
还有就是,所有线程跟messagequeue共用一个mutex。
* 两个线程的runloop居然还要竞争一个锁,然后才能处理自己的mq。
* mqA的runloop居然还要跟mqB的postmessage竞争一个锁。
* mqA的postmessage居然还要跟mqB的postmessage竞争一个锁。
既然mars是重度使用boost的,不如直接用asio。查看它的boost版本原来是1.60,boost在1.66才将asio重构成我们今天熟悉的executor。我写过一下关于1.66的boost.asio框架设计。
逆向,我扯远了。我只关心应用层的接口就好了。
下面就是应用层的主要接口,还有交互流程。
现在逆向看看闭源的部分有哪些
先来解读一下目录结构
目录参考了java包目录结构。
mars是一级包名。下面的子包app,cdn,magicbox,mmdns,sdt,smc,stn。
每个子包,有一个同名的头文件,定义类结构。有一个同名的logic头文件,导出子包的接口,包括模块生命周期hooking (onCreate,onDestroy),logic.cc初始模块。子包里的功能单元称为Manager。所有功能的实现体单元在子包的src子目录。
目录 | mars | stn | src | ||||
namespace | mars:: | mars::stn | |||||
类 | StnManager | ShortLink | LongLink | ShortLinkManager | LongLinkManager | ||
文件 | stn.h, stn_logic.h, stn_maanger.h | ShortLink.cc | LongLink.cc | ShortLinkManager.cc | LongLinkManager.cc |
再整理一下模块的设计思想,logic是包的接口层,manager是承接层,core是服务层。应用层通过logic调用包的服务,经过manager下达core。包内服务通过core调用应用层的服务,经由manager的callback集回调应用层安置的服务。实现过程是否严格贯彻是另一回事。应用层跟包内都有直接使用manager。
我在逆向分析StartTask时,发现了一个问题,mars::stn::Task总计做了10次copy构造,WTF。
在NetCore::StartTask入口准备AsyncInvoke时,一次
在Message构建过程,总计八次,其中有一个any_cast出来的AysncInvovkeFunction赋值函数无意思地进行了七次。typedef boost::function<void()> AsyncInvokeFunction;
在执行体里面,再一次,就是第十次。
你没有逆向过,也不知道原来这么funny。他们到底有没有跟踪过自己的代码,问号?似乎单靠xlog发现不了问题。没经过逆向分析谁也不清楚any或boost会编译出来什么,也不会在意这些小事的。传参用引用也不是万事大吉的。
本期先到这里,下期再见。
逆向WeChat(四)的更多相关文章
- Python逆向(四)—— Python内置模块dis.py源码详解
一.前言 上一节我们对Python编译及反汇编做了讲解,大家知道dis模块可以将编译好的pyc文件中提取出来的PyCodeObject反汇编为可以阅读字节码形式.本节我们对dis模块中的源码进行详细的 ...
- 南邮攻防训练平台逆向第四题WxyVM
下载文件elf文件,运行输入flag,用ida打开逆向算法: 不是很复杂,可以看出flag长度需要24,最终会和已给出dword_601060进行比较,一致则成功,那么现在只需要看上面的sub_400 ...
- iOS逆向(五)-ipa包重签名
为什么要重签名? 1.在没有源代码的情况下,你已经对某个应用进行了资源修改(比如修改了启动图或图标等).修改完成以后,如果想要让APP可以正常使用,该APP一定要重新签名然后压缩成IPA文件. 2.如 ...
- Python逆向(一)—— 前言及Python运行原理
一.前言 最近在学习Python逆向相关,涉及到python字节码的阅读,编译及反汇编一些问题.经过长时间的学习有了一些眉目,为了方便大家交流,特地将学习过程整理,形成了这篇专题.专题对python逆 ...
- 【二进制】【WP】MOCTF逆向题解
moctf 逆向第一题:SOEASY 这个是个 64 位的软件,OD 打不开,只能用 IDA64 打开,直接搜字符串(shift+F12)就可以看到 moctf 逆向第二题:跳跳跳 这个题当初给了初学 ...
- 逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式
逆向知识第十四讲,(C语言完结)结构体在汇编中的表现形式 一丶了解什么是结构体,以及计算结构体成员的对其值以及总大小(类也是这样算) 结构体的特性 1.结构体(struct)是由一系列具有相同类型或不 ...
- PC逆向之代码还原技术,第四讲汇编中减法的代码还原
目录 PC逆向之代码还原技术,第四讲汇编中减法的代码还原 一丶汇编简介 二丶高级代码对应汇编观看. 1.代码还原解析: 三丶根据高级代码IDA反汇编的完整代码 四丶知识总结 PC逆向之代码还原技术,第 ...
- 逆向libbaiduprotect(四)
百度加固libbaiduprotect.so自身对只读字符串进行了加密保护,防止成为破解和逆向的切入口.一般地认为,只要找出这个解密算法就可以对.rodata段的只读字符串进行破解,从而窥探程序的意图 ...
- IntelliJ IDEA 学习(四)Idea逆向生成数据库实体类
第一步配置 数据库 第二步 配置hibernate,如果没有cfg.xml文件,点击ok后会自动生成 第三步 选择hibernate配置文件生成实体 第四步 设置完点击,选中要生成的实体的表 注意: ...
- hibernate(四)__由表逆向创建Domain对象和对象关系映射文件
之前我们是手写Domain对象和对象关系映射文件->然后生成数据库中的Table. 现在我们反过来先在数据库中建好Table->然后用工具生成Domain对象和对象关系映射文件. 步骤: ...
随机推荐
- HarmonyOS Connect “Device Partner”专场FAQ来啦!
原文链接:https://mp.weixin.qq.com/s/mQJlAso293qgPlA1paxv5g,点击链接查看更多技术内容: Device Partner平台是面向AIoT产业链 ...
- HTC Vive之Unity3d开发日记——手柄交互编程
目录: HTC Vive之Unity3d开发日记 You can fool all the people some of the time,and some of the people ...
- java 读取文本文件超简单的方法
答案是:Scanner读取,初学者大部分都用过这货,然而这货还有这样两个构造方法: public Scanner(File source); public Scanner(InputStream st ...
- 腾讯音乐:说说Redis脑裂问题?
Redis 脑裂问题是指,在 Redis 哨兵模式或集群模式中,由于网络原因,导致主节点(Master)与哨兵(Sentinel)和从节点(Slave)的通讯中断,此时哨兵就会误以为主节点已宕机,就会 ...
- 图片验证码识别,标签中onehot编码对应多个1怎么做?
一张验证码图片直接做整体识别 也就是图片的最后输出节点有4*26=104个,经过一个softmax,使用交叉熵损失,与真实值4*26=104个标签做计算,然后反向传播 104个onehot编码真实值当 ...
- .NET Emit 入门教程:第六部分:IL 指令:9:详解 ILGenerator 指令方法:运算操作指令(指令篇结束)
前言: 经过前面几篇的学习,我们了解到指令的大概分类,如: 参数加载指令,该加载指令以 Ld 开头,将参数加载到栈中,以便于后续执行操作命令. 参数存储指令,其指令以 St 开头,将栈中的数据,存储到 ...
- 力扣326(java)-3的幂(简单)
题目: 给定一个整数,写一个函数来判断它是否是 3 的幂次方.如果是,返回 true :否则,返回 false . 整数 n 是 3 的幂次方需满足:存在整数 x 使得 n == 3x 示例 1: 输 ...
- 先行一步,7大技术创新和突破,阿里云把 Serverless 领域的这些难题都给解了
简介: 函数计算 FC 首创 GPU 实例.业内首发实例级别可观测和调试.率先提供端云联调和多环境部署能力.GB 级别镜像启动时间优化至秒级.VPC 网络建连优化至200ms,Serverless ...
- [FE] Js DOM 操作的几个常见错误
1.setTimeout 匿名函数传参问题,匿名函数形参是不能直接在内部使用的,匿名函数传参需要按顺序从 setTimeout 的第三个参数开始依次传递. 2. Js clone出来的 dom 节点, ...
- dotnet OpenXML 解析 PPT 图表 解析日期时间表示内容
在 OpenXML 里的图表存放的日期时间很多存放的是数值,需要进行转换才能获取到用户可见的字符串 日期在 OpenXML 里可以使用数值存放,需要根据数值和格式化字符串转换为用户可见的字符串 如以下 ...