接上篇《手把手教你逆向微信之朋友圈小视频转发(上)》

代码编写及重签名打包安装 (下篇)

小视频的转发支持4个功能,转发至朋友圈、转发至好友、保存到本地相册、拷贝小视频链接到粘贴板。如果小视频没有下载长按时只会出现拷贝url链接。

转载请注明出处:来自LeonLei的博客http://www.gaoshilei.com

(非越狱机和不想利用tweak安装的越狱机点我跳到第二节
### 1.越狱机打包安装(tweak安装)
1> 新建tweak工程
2> 编写tweak文件

这里要hook两个类,分别是WCContentItemViewTemplateNewSight和SightMomentEditViewController,在WCContentItemViewTemplateNewSight中hook住onLongTouch方法然后添加menu弹出菜单,依次添加响应的方法,具体的代码如下:

  • 拷贝小视频的url链接
1
2
3
  NSString *localPath = [[self iOSREMediaItemFromSight] pathForSightData];
UISaveVideoAtPathToSavedPhotosAlbum(localPath, nil, nil, nil);
}
  • 保存小视频到本地相册
1
2
NSString *localPath = [[self iOSREMediaItemFromSight] pathForSightData];
UISaveVideoAtPathToSavedPhotosAlbum(localPath, nil, nil, nil);
  • 转发到朋友圈
1
2
3
4
5
6
7
8
9
10
SightMomentEditViewController *editSightVC = [[%c(SightMomentEditViewController) alloc] init];
NSString *localPath = [[self iOSREMediaItemFromSight] pathForSightData];
UIImage *image = [[self valueForKey:@"_sightView"] getImage];
[editSightVC setRealMoviePath:localPath];
[editSightVC setMoviePath:localPath];
[editSightVC setRealThumbImage:image];
[editSightVC setThumbImage:image];
[WCTimelineVC presentViewController:editSightVC animated:YES completion:^{

}];
  • 转发给好友
1
[self sendSightToFriend];
  • 长按手势
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
UIMenuController *menuController = [UIMenuController sharedMenuController];
if (menuController.isMenuVisible) return;//防止出现menu闪屏的情况
[self becomeFirstResponder];
NSString *localPath = [[self iOSREMediaItemFromSight] pathForSightData];
BOOL isExist =[[NSFileManager defaultManager] fileExistsAtPath:localPath];
UIMenuItem *retweetMenuItem = [[UIMenuItem alloc] initWithTitle:@"朋友圈" action:@selector(SLRetweetSight)];
UIMenuItem *saveToDiskMenuItem = [[UIMenuItem alloc] initWithTitle:@"保存到相册" action:@selector(SLSightSaveToDisk)];
UIMenuItem *sendToFriendsMenuItem = [[UIMenuItem alloc] initWithTitle:@"好友" action:@selector(SLSightSendToFriends)];
UIMenuItem *copyURLMenuItem = [[UIMenuItem alloc] initWithTitle:@"复制链接" action:@selector(SLSightCopyUrl)];
if(isExist){
[menuController setMenuItems:@[retweetMenuItem,sendToFriendsMenuItem,saveToDiskMenuItem,copyURLMenuItem]];
}else{
[menuController setMenuItems:@[copyURLMenuItem]];
}
[menuController setTargetRect:CGRectZero inView:self];
[menuController setMenuVisible:YES animated:YES];

具体的tweak文件我放在了github上,WCSightRetweet传送门

3> 编写WCTimelineRetweet.h头文件
编写这个头文件的目的是防止tweak在编译期间报错,我们可以在编写好tweak试着编译一下,然后根据报错信息来添加这个头文件的内容,在这个文件中要声明在tweak我们用到的微信的类和方法,具体请看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@interface WCUrl : NSObject
@property(retain, nonatomic) NSString *url;
@end
@interface WCContentItem : NSObject
@property(retain, nonatomic) NSMutableArray *mediaList;
@end
@interface WCDataItem : NSObject
@property(retain, nonatomic) WCContentItem *contentObj;
@end
@interface WCMediaItem : NSObject
@property(retain, nonatomic) WCUrl *dataUrl;
- (id)pathForSightData;
@end
@interface MMServiceCenter : NSObject
+ (id)defaultCenter;
- (id)getService:(Class)arg1;
@end
@interface WCFacade : NSObject
- (id)getTimelineDataItemOfIndex:(long long)arg1;
@end
@interface WCSightView : UIView
- (id)getImage;
@end
@interface WCContentItemViewTemplateNewSight : UIView{
WCSightView *_sightView;
}
- (WCMediaItem *)iOSREMediaItemFromSight;
- (void)iOSREOnSaveToDisk;
- (void)iOSREOnCopyURL;
- (void)sendSightToFriend;
@end
@interface SightMomentEditViewController : UIViewController
@property(retain, nonatomic) NSString *moviePath;
@property(retain, nonatomic) NSString *realMoviePath;
@property(retain, nonatomic) UIImage *thumbImage;
@property(retain, nonatomic) UIImage *realThumbImage;
- (void)makeInputController;
@end
@interface MMWindowController : NSObject
- (id)initWithViewController:(id)arg1 windowLevel:(int)arg2;
- (void)showWindowAnimated:(_Bool)arg1;
@end
@interface WCTimeLineViewController : UIViewController
- (long long)calcDataItemIndex:(long long)arg1;
@end
@interface MMTableViewCell : UIView
@end
@interface MMTableView : UIView
- (id)indexPathForCell:(id)cell;
@end

4> Makefile文件修改

1
2
3
4
5
6
7
8
9
10
THEOS_DEVICE_IP = 192.168.0.115//手机所在的IP
include $(THEOS)/makefiles/common.mk
ARCHS = arm64//支持的CPU架构
TWEAK_NAME = WCTimelineSightRetweet
WCTimelineSightRetweet_FILES = Tweak.xm
WCTimelineSightRetweet_FRAMEWORKS = UIKit CoreGraphics//导入系统的framework
include $(THEOS_MAKE_PATH)/tweak.mk

after-install::
install.exec "killall -9 WeChat"//安装完成杀掉的进程

control文件不需要做修改,然后执行命令make package install安装到手机,微信会被杀掉,然后再次打开微信转发小视频的功能已经加上了。

2.微信重签名打包安装

准备工作

(1) 安装iOSOpenDev

1> 安装 macports (安装过程需要连接VPN,否则无法安装成功)

2> 安装完MacPorts后打开终端,输入 sudo port -v selfupdate 更新MacPorts到最新版本,时间可能比较长。

3> 更新完MacPorts后安装DPKG文件,在终端输入sudo port -f install dpkg

4> 下载安装 iOSOpendev 如果安装失败,可以通过 Command + L 查看安装中出现的问题。

1
2
3
4
5
6
PackageKit: Install Failed: Error Domain=PKInstallErrorDomain Code=112 "运行软件包“iOSOpenDev-1.6-2.pkg”的脚本时出错。" UserInfo={NSFilePath=./postinstall, NSURL=file://localhost/Users/ice/Downloads/iOSOpenDev-1.6-2.pkg#iodsetup.pkg, PKInstallPackageIdentifier=com.iosopendev.iosopendev162.iod-setup.pkg, NSLocalizedDescription=运行软件包“iOSOpenDev-1.6-2.pkg”的脚本时出错。} {
NSFilePath = "./postinstall";
NSLocalizedDescription = "\U8fd0\U884c\U8f6f\U4ef6\U5305\U201ciOSOpenDev-1.6-2.pkg\U201d\U7684\U811a\U672c\U65f6\U51fa\U9519\U3002";
NSURL = "file://localhost/Users/ice/Downloads/iOSOpenDev-1.6-2.pkg#iodsetup.pkg";
PKInstallPackageIdentifier = "com.iosopendev.iosopendev162.iod-setup.pkg"
}

这里有一个解决方案:下载iOSOpenDevInstallSolve中的Specifications文件夹

修复安装失败问题
打开步骤4下载的Specifications文件夹,里面应该有8个文件,如果你有安装多个xcode注意放到对应的xcode里面。
1. iPhoneOS开头的四个文件放到/应用程序/Xcode/Content/Developer/Platforms/IphoneOS.platform/Developer/Library/Xcode/Specifications文件夹下(如果没有,请自己创建一个Specifications文件夹)
2. iPhone Simulator 开头的另外四个文件放入/应用程序/Xcode/Content/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications文件夹下(如果没有,请同样创建一个)
3. 在/应用程序/Xcode/Content/Developer/Platforms/iPhoneSimulator.platform/Developer/文件夹下创建usr文件夹,usr文件夹下再创建一个名为bin的文件夹。
注意:有时候会提示安装失败,打开Xcode新建工程,如果在工程的选项菜单中有iOSOpenDev就表示安装成功了,不用管那个安装提示。

(2) 安装ideviceinstaller

安装ipa包用的,也可以通过itool之类的工具,不过ideviceinstaller可以看到安装过程的过程,方便我们找到出错原因。

执行命令

1
brew install ideviceinstaller

如果提示brew命令找不到,那就是你的Mac还没有安装Homebrew
常见的报错信息:

1
ERROR: Could not connect to lockdownd, error code -5

这个时候只要重新安装libimobiledevice就可以了(因为ideviceinstaller依赖很多其他插件)
执行下面的命令:

1
2
$   brew uninstall libimobiledevice
$ brew install --HEAD libimobiledevice

下载iOS App Signer重签名工具(省去很多命令行操作,一键重签名!)

(3) 下载砸壳的微信应用

因为AppStore的包是被加密(有壳),无法进行重签名,所以要用砸壳的,可以用dumpdecrypted自己砸壳,也可以直接利用PP助手或者itool助手下载越狱版已经砸过壳的微信应用。

(4) 安装yololib
yololib可以将dylib注入进WeChat二进制文件中,这样才能是你的Hook有作用,下载之后编译得到yololib

代码注入以及打包安装

(1)生成静态库

在上一步中已经安装好iOSOpendev,此时打开Xcode新建项目,在选择工程界面会出现iOSOpendev的工程,这里我们要选择CaptainHook Tweak项目
iOSOpenDev
新建好的工程只有一个.mm文件,我们只需要把所有hook方法写在这个文件中即可。
因为非越狱机不能像越狱机一样可以安装tweak插件对原来的应用进行hook,CaptainHook使用的Runtime机制实现,利用宏命令封装类定义、方法替换等功能,简单介绍它的使用方法:

  1. hook某个类
1
CHDeclareClass(WCContentItemViewTemplateNewSight); 

CHDeclareClass(ClassName)表示要hook哪个类,一般写在对这个类操作的最前面。

  1. 在hook的类种新建方法
1
CHDeclareMethod0(id, WCContentItemViewTemplateNewSight, SLSightDataItem){......}

CHDeclareMethod(count, return_type, class_type, name1, arg1, ....)表示新建一个方法,count表示这个方法的参数个数,return_type表示返回类型,class_type填写这个方法所在的类名,name1表示方法名,arg1表示第一个参数,如果没有参数则不填,以此类推。

  1. hook原来的方法
1
2
3
4
CHOptimizedMethod0(self, void, WCContentItemViewTemplateNewSight, onLongTouch){
CHSuper(0, className, Method);//可选
......
}

CHOptimizedMethod(count, optimization, return_type, class_type, name1, type1, arg1) 表示hook原来的方法(如果不加CHSuper(0, className, Method)表示复写原来的方法,CHSuper表示在当前位置调用原来的方法实现),count表示hook的方法参数个数,optimization一般填self,return_type即方法返回值类型,class_type填当前类的类名,name1是方法名,arg1是参数,如果没有参数不同填写arg,以此类推。

  1. 构造函数
1
2
3
4
5
6
7
8
CHConstructor
{
@autoreleasepool
{
CHLoadLateClass(WCContentItemViewTemplateNewSight);
CHHook(0, WCContentItemViewTemplateNewSight, onLongTouch);
}
}

这是CaptainHook的入口函数,所有被hook的类必须在这里声明加载,类里面的方法要在这里声明hook。
然后就可以往类和方法中写代码了,代码太长不贴了,请自行下载
MMPlugin传送门
这个项目中包含了小视频转发、自动抢红包、修改微信运动步数功能,自动抢红包和修改微信运动步数功能可以手动关闭。

注意:如果用到了系统的类记住要导入相应的类库(比方说UIKit)和头文件否则编译的时候会报错。

编译成功之后就可以在Products文件夹中找到编译好的静态库了
编译好的静态库
在finder中找到它,拷贝出来待用。
##### (2) 签名+打包+安装
进行到这里目前应该有的材料有:

  • 砸壳的微信app
  • 编译好的MMPlugin.dylib
    
  • 安装好的iOS App Signer
  • 编译好的yololib文件
  • ideviceinstaller

从原来的微信app中找到WeChat二进制文件拷贝出来待用,删除weChat.app中的Watch文件夹、PlugIns文件夹中的WeChatShareExtensionNew.appex,这步操作必须要做,不然安装的时候会报签名错误。
执行下面的命令将MMPlugin.dylib注入到WeChat二进制文件中,命令如下:

1
LeonLei-MBP:WeChat gaoshilei$ ./yololib WeChat MMPlugin.dylib

执行这个命令时要确保yololib、WeChat、WeChat.app处于同一目录下。

完成之后将MMPlugin.dylib和WeChat拷贝到原来的WeChat.app中,覆盖掉原来的WeChat文件。
打开iOS App Signer按照下图选择好各项参数:
iOS App Signer
我这里选择的是企业级证书,个人开发者证书也是可以的,个人开发者一定要选择开发环境的并且要将需要安装的机器udid添加到prov文件里面去,选好之后点击start,稍等片刻一个经过重签名的ipa包就生成了。
连上你的手机执行下面的命令查看ideviceinstaller是否连接上手机:

1
LeonLei-MBP:WeChat gaoshilei$ ideviceinfo

如果打印出一大堆手机的信息表示连接成功可以安装ipa包,如果不成功请根据错误提示进行调整。执行下面的命令进行安装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
LeonLei-MBP:WeChat gaoshilei$ ideviceinstaller -i WeChat.ipa 
WARNING: could not locate iTunesMetadata.plist in archive!
WARNING: could not locate Payload/WeChat.app/SC_Info/WeChat.sinf in archive!
Copying 'WeChat.ipa' to device... DONE.
Installing 'com.xxxxxxxxxxxx'
- CreatingStagingDirectory (5%)
- ExtractingPackage (15%)
- InspectingPackage (20%)
- TakingInstallLock (20%)
- PreflightingApplication (30%)
- InstallingEmbeddedProfile (30%)
- VerifyingApplication (40%)
- CreatingContainer (50%)
- InstallingApplication (60%)
- PostflightingApplication (70%)
- SandboxingApplication (80%)
- GeneratingApplicationMap (90%)
- Complete

安装完成,在手机上打开微信试试我们添加的新功能吧!如果某个环节卡住会报错,请根据报错信息进行修改。请看效果图:
小视频转发

有任何问题请在文章评论区留言,或者在博客首页点击邮件联系我。