免越狱版 iOS 微信抢红包插件

在参考了论坛里的“APP逆向分析之钉钉抢红包插件的实现-iOS篇”这篇文章之后,发现他实现了免越狱版本的 tweak,但是里面关于免越狱部分讲得太过简略,新手根本无法照着操作。所以,我就在参考原文的基础上经过自己的一番摸索,并成功将自己的iOS抢红包插件实现了免越狱版本,下面就是我在学习过程中做的一些总结,希望对大家能有帮助。

由于新注册用户只能在一篇文章添加两个链接,所以我将下面文章中的超链接以及图片链接都去掉了,完整版本可以参看我的原文。

原文地址:http://www.swiftyper.com/2016/12/26/wechat-redenvelop-tweak-for-non-jailbroken-iphone/


又到年末,微信红包又开始成为大家所关心的话题了,不管是公司年会,还是朋友聚会,似乎不发红包就没办法继续聊下去了。因此,值此新年来临之际,我对我的iOS 微信抢红包 tweak 进行了一下改进。主要增加了插件开关,以及随机延迟功能,让你在新一轮红包大战中无往而不利。

但是,这毕竟是一个 tweak,只有少数有越狱机器的小伙伴才能使用这个插件,无疑门槛是太高了。到目前为止,已经有无数朋友在问到底有没有免越狱版本的插件了。

今天,我们就要讨论下如果制作免越狱版本的微信抢红包插件。

注意:本篇文章只讲我在自己摸索过程中的一点总结,并不深入讲解原理。我对 iOS 逆向也只是初窥门径,对很多原理也还未达到深入理解的程序,国内关于这方面的文章也是在少数,我也不希望我写出语焉不详的文章导致读者被我误导。同时,也不排除将来我研究得够深入的时候,再回过头来写关于原理的文章。

原理

虽然这里并不深入讲解,但是最基本的原理我们还是要理解的,因为后面所做的工作,都是基于这个原理来进行开发的。越狱机器之所以能使用 tweak,主要是因为在越狱的时候,手机里就安装了 mobilesubstrate 这个库,这个库的作用就是能在程序运行的时候动态加载我们自己写的 dylib 动态运行库。而由于非越狱手机系统里面是没有这个库的,所以我们需要直接将这个库打包进 ipa 当中,使用它的 API 实现注入。

关于注入的原理,可以参考这篇文章:移动App入侵与逆向破解技术-iOS篇。

好了,这就是目前为止我们所需要了解的东西。下面就可以开始动手了。

获取砸壳版本的微信 ipa

因为在 AppStore 上面下载得到的应用都是经过加密的,可以执行文件上已经被加过一层壳,所以我们需要先拿到砸过壳版本的微信应用。

有两种方法:

  1. 直接在 PP 助手下载
  2. 使用 Clutch 对越狱手机上应用进行砸壳

第一种方法没什么好说的,这里主要讲讲第二种方法。

首先,将 Cluth 仓库 clone 到本地:

$ git clone https://github.com/KJCracks/Clutch
$ cd Clutch

接着,使用 Xcode 进行构建,得到可执行文件:

$ xcodebuild -project Clutch.xcodeproj -configuration Release ARCHS="armv7 armv7s arm64" build

生成出来的可执行文件就在 Clutch 目录下,将其拷贝到手机上:

scp Clutch/clutch root@<your.device.ip>:/usr/bin/

之后,就可以使用这个工具来进行砸壳了。

先 ssh 到越狱手机上,然后列出当前安装的应用:

$ ssh root@<your.device.ip>
$ clutch -i

# Installed apps:
# 1:   WeChat <com.tencent.xin>
# 2:   DingTalk <com.laiwang.DingTalk>
# 3:   喜马拉雅FM(听书社区)电台有声小说相声英语 <com.gemd.iting>

可以得到 clutch 把相应的包名也显示出来了,这时我们就可以进行砸壳了:

$ clutch -d com.tencent.xin

# com.tencent.xin contains watchOS 2 compatible application. It's not possible to dump watchOS 2 apps with Clutch 2.0.4 at this moment.
# Zipping WeChat.app
# Swapping architectures..
# ASLR slide: 0xb3000
# ...
# writing new checksum
# DONE: /private/var/mobile/Documents/Dumped/com.tencent.xin-iOS7.0-(Clutch-2.0.4).ipa
# Finished dumping com.tencent.xin in 76.9 seconds

可以看到,clutch 将砸过后的 ipa 文件放到了 /private/var/mobile/Documents/Dumped/ 目录下。

我们将它改成一个比较简单的名字,然后拷回电脑上:

$ mv /private/var/mobile/Documents/Dumped/com.tencent.xin-iOS7.0-\(Clutch-2.0.4\).ipa /private/var/mobile/Documents/Dumped/wechat.ipa
$ scp root@<your.device.ip>:/private/var/mobile/Documents/Dumped/wechat.ipa ~/Desktop

这里,我把它拷到了电脑桌面上。之后就可以进行下一步操作了。

准备 dylib 动态链接库

这步就很简单了,直接到我的 WeChatRedEnvelop 上把源码 clone 下来,然后执行 make 命令,就能拿到 dylib 文件了。

$ git clone https://github.com/buginux/WeChatRedEnvelop.git
$ cd WeChatRedEnvelop
$ make 

# > Making all for tweak WeChatRedEnvelop…
# ==> Preprocessing Tweak.xm…
# ==> Compiling Tweak.xm (armv7)…
# ==> Compiling XGPayingViewController.m (armv7)…
# ...
# ==> Signing WeChatRedEnvelop…

$ cp .theos/obj/debug/WeChatRedEnvelop.dylib ~/Desktop # 注意是 .theos 目录,这是个隐藏目录

将生成的 dylib 文件拷贝到桌面,跟刚刚砸过壳的微信应用放到一个目录层级。

检查依赖项

因为这个代码是我自己写的,所以我知道这个 dylib 除了 mobilesustrate 外没有依赖其它的库。但是如果我们拿到的是别人的 dylib,就需要先进行一下依赖项检查,以确保之后我们将所有的依赖库都打包进 ipa 当中。

使用 macOS 自带的 otool 工具就可以进行依赖项检查:

$ otool -L WeChatRedEnvelop.dylib
WeChatRedEnvelop.dylib (architecture armv7):
	/Library/MobileSubstrate/DynamicLibraries/WeChatRedEnvelop.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1349.1.0)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1348.0.0)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3600.5.2)
	/usr/lib/libsubstrate.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 307.4.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)
WeChatRedEnvelop.dylib (architecture arm64):
	/Library/MobileSubstrate/DynamicLibraries/WeChatRedEnvelop.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1349.1.0)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1348.0.0)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3600.5.2)
	/usr/lib/libsubstrate.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 307.4.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)

可以看到除了 substrate 库,其它依赖的都是系统自带的库。我们将 libsubstrate.dylib 拷出,使用 install_name_tool 命令修改动态库的路径,指向 app 二进制文件的同级目录。

$ scp root@<your.device.ip>:/usr/lib/libsubstrate.dylib ~/Desktop
$ install_name_tool -change /usr/lib/libsubstrate.dylib @loader_path/libsubstrate.dylib WeChatRedEnvelop.dylib
$ otool -L WeChatRedEnvelop.dylib
WeChatRedEnvelop.dylib (architecture armv7):
	/Library/MobileSubstrate/DynamicLibraries/WeChatRedEnvelop.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1349.1.0)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1348.0.0)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3600.5.2)
	@loader_path/libsubstrate.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 307.4.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)
WeChatRedEnvelop.dylib (architecture arm64):
	/Library/MobileSubstrate/DynamicLibraries/WeChatRedEnvelop.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1349.1.0)
	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1348.0.0)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 3600.5.2)
	@loader_path/libsubstrate.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 307.4.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)

可以看到 libsubstrate.dylib 的路径已经变更了。

将动态链接库注入二进制文件中

接下来,就需要将我们的库注入到微信的二进制文件中,可以使用开源的 optool 工具。

编译安装 optool 工具:

# 因为 optool 添加了 submodule,因为需要使用 --recuresive 选项,将子模块全部 clone 下来
$ git clone --recursive https://github.com/alexzielenski/optool.git
$ cd optool
$ xcodebuild -project optool.xcodeproj -configuration Release ARCHS="i386 x86_64" build

将砸壳过的 ipa 文件解压,然后将 libsubstrate.dylib 与 WeChatRedEnvelop.dylib 拷贝到解压后的 WeChat.app 目录下。

$ cd ~/Desktop
$ unzip wechat.ipa -d wechat
$ cp libsubstrate.dylib WeChatRedEnvelop.dylib wechat/Payload/WeChat.app

使用 optool 把 WeChatRedEnvelop.dylib 注入到二进制文件中:

$ /path/to/optool install -c load -p "@executable_path/WeChatRedEnvelop.dylib" -t wechat/Payload/WeChat.app/WeChat

打包并重签名

打包 ipa 与重签名可以直接使用图形化工具 ios-app-signer 来完成。

这个工具可以自动加载出本机的证书以及 Provisioning Profile 文件,使用起来十分方便,当然也可以手动选择证书文件。

如果是使用个人开发者证书,需要先将设备的 UUID 加到 Provisioning Profile 中。

我这里是直接从一个 archive 过的应用中提取 embedded.mobileprovision 文件,并在 Provisioning Profile 一栏中选择 Choose Custom File 使用这个文件。

点击 start 后,指定保存路径,iOS App Signer 就会帮你搞定所有事情。

安装

在 iOS App Signer 完成打包与重签名后,我们就可以进行安装了。

安装有两种方法,一种是使用 iTool 工具安装 ipa 文件。

另外一种是针对有 XCode 的同学,在菜单 - Window - Devices 中打开设置窗口。点击 Installed Apps 栏下面的 + 号就可以选择 ipa 文件进行安装了。

11 个赞

Here we go again

#WhatATimeToBeAlive

1 个赞

I’m sorry but I don’t quite catch you.

现在微信严打多开,抢红包。我之前做的抢红包,被迫都删掉了

1 个赞

他们都是如何进行检测的呢?

秒抢 bundle id 这种了

1 个赞

我之前的应该是秒抢的原因。让我都不能玩朋友圈了

要hook bundleid

你拉进hopper看xref,我记得是有个地方调nsbundle拿bundleid

哦哦,明白了。看来这个问题已经很普遍了,微信都做处理了,怪我孤陋寡闻,用了两天没被封以为就可以用了。:joy:

1 个赞

秒抢可以使用随机延迟来解决。

1 个赞

为什么我make出的WeChatRedEnvelop.dylib里面没有/usr/lib/libsubstrate.dylib,而是这个/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate

1 个赞

是同一个东西

1 个赞

那修改动态库路径这一步,我还要拷出CydiaSubstrate?然后$ install_name_tool -change @loader_path/CydiaSubstrate WeChatRedEnvelop.dylib?

1 个赞

拷出来,改名成 libsubstrate.dylib,然后在 -change 后面把 /usr/lib/libsubstrate.dylib 改成你的 /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate。

其它不变。

1 个赞

明白了,谢谢

1 个赞

optool的工程在xcode中可以编译成功(但无法使用optool install命令),而在命令行中编译却失败了,提示:
CPShiftReduceParsers/CPShiftReduceAction.m:29:16: error:
inconsistent number of instance variables specified
ActionType type;
^

1 个赞

optool 依赖了一个库,那个库又依赖了另一个库。它们都是用 submodule 来引用的,你要确保这些依赖库都下下来了。

1 个赞

嗯,确实是依赖的问题。现在重签名后发现安装不上,提示watchkit,我现在把watch相关的都删掉试试

1 个赞

我的原文应该是将怎么制作越狱版本说清楚了呀,你看我的github上的源码说明没?

1 个赞