目标
- 修改爱奇艺App
- 将这个修改过的App重签名
- 安装在未越狱手机上
准备:
- 越狱手机和一台未越狱手机
- Mac电脑
1. 修改爱奇艺App
- 步骤1. 在越狱手机AppStore上下载爱奇艺App.
- 步骤2. 在越狱手机上找到爱奇艺的AppID, 这里可以通过MJAppTools, 快速查询(这里也可以通过Cycript来找到),代码如下:
1
2
3
4
5
6
7
8
// 终端
MJAppTools -l
// 显示
【爱奇艺】 <com.qiyi.iphone>
/private/var/mobile/Containers/Bundle/Application/C8575DD1-889E-4E70-AF66-4E4CC920F6AC/iQiYiPhoneVideo.app
/private/var/mobile/Containers/Data/Application/CD9280DD-C4C3-4CF2-84E0-5F484596E211
arm_64 加壳
- 步骤3. 创建一个名叫libReveal.plist的文件,将刚才的AppIDcopy进plist中,如下:
1
2
3
4
5
6
7
{
Filter = {
Bundles = (
"com.qiyi.iphone"
);
};
}
- 步骤4. 打开Reveal
1
2
3
4
//1. 找到
Helpe -> Show Reveal Library in Finder -> iOS Library
//2. 重命名
RevealServer -> libReveal
- 步骤5. 将libReveal.plist 和 libReveal.dylib 同时上传到越狱机器以下路径(可以通过iFunBox):
1
Device/Library/MobileSubStrate/DynamicLibraries
-
步骤6. 此时打开Reveal和越狱机器上的爱奇艺App,结合Cycript或者mjcript, 可以找到你想要修改的东西所属的类,这里如果我们需要修改播放的广告。
-
步骤7. 通过Reveal可以找到启动页面相关的广告View是
QYStartADView, 它所属的类是QYStartADViewController -
步骤8. 通过Clutch或dumpdecrypted脱壳,得到脱壳后的新App。我用的是Clutch,代码如下:
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
// 罗列手机上可以脱壳的App
Clutch -i
// 脱壳指定App
Clutch -d x(爱奇异的前面的数字)
// 返回
com.qiyi.iphone contains watchOS 2 compatible application. It's not possible to dump watchOS 2 apps with Clutch 2.0.4 at this moment.
Zipping iQiYiPhoneVideo.app
ASLR slide: 0x100004000
Dumping <QiYiUserNotification> (arm64)
Patched cryptid (64bit segment)
ASLR slide: 0x1000dc000
Dumping <QYToday> (arm64)
Patched cryptid (64bit segment)
ASLR slide: 0x1000bc000
Dumping <QYSiriShortCuts> (arm64)
Patched cryptid (64bit segment)
Writing new checksum
Writing new checksum
Writing new checksum
objc[4015]: Class ZipArchive is implemented in both /var/tmp/clutch/1C8BA028-6FC4-4975-B4E9-644D2935FB55/clutch and /private/var/mobile/Containers/Bundle/Application/C8575DD1-889E-4E70-AF66-4E4CC920F6AC/iQiYiPhoneVideo.app/Frameworks/QYUniversalFramework.framework/QYUniversalFramework. One of the two will be used. Which one is undefined.
Dumping <QYUniversalFramework> arm64
ASLR slide: 0x100054000
Dumping <iQiYiPhoneVideo> (arm64)
Patched cryptid (64bit segment)
Successfully dumped framework QYUniversalFramework!
Child exited with status 0
Zipping QYUniversalFramework.framework
Zipping QYSiriShortCuts.appex
Zipping QYToday.appex
Zipping QiYiUserNotification.appex
Writing new checksum
DONE: /private/var/mobile/Documents/Dumped/com.qiyi.iphone-iOS9.0-(Clutch-2.0.4).ipa
Finished dumping com.qiyi.iphone in 38.5 seconds
- 步骤9. copy出来已经脱壳了的App,然后找到包中的Mach-O文件,最后运用class-dump, 执行以下的命令得到相应的头文件:
1
class-dump -H -o iqiHeaders iQiYiPhoneVideo.app
- 步骤10. 通过查看类
QYStartADView的相关头文件,代码如下:
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//
// Generated by class-dump 3.5 (64 bit).
//
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//
#import "UIView.h"
#import "QYStartADViewControllerDelegate.h"
#import "QYStartAdPlayerControllerDelegate.h"
@class AdsClient, CupidAd, NSString, NSTimer, QYStartADViewController, QYStartAdPlayerController, QYWebContainer, UILabel, UIWindow;
@interface QYStartADView : UIView <QYStartAdPlayerControllerDelegate, QYStartADViewControllerDelegate>
{
UIWindow *_window;
NSTimer *_adTimer;
float _iAdTime;
_Bool _shouldRun;
long long _addedTime;
float _adShowTime;
_Bool _isFullScreenAd;
int _type;
id <QYPhoneStartADViewDelegate> _delegate;
UILabel *_secords;
long long _duration;
double _logoBackHeight;
double _needToCut;
UIView *_adImageView;
QYWebContainer *_webView;
AdsClient *_adClient;
CupidAd *_adCupid;
QYStartAdPlayerController *_player;
QYStartADViewController *_startAdViewController;
}
@property(retain, nonatomic) QYStartADViewController *startAdViewController; // @synthesize startAdViewController=_startAdViewController;
@property(retain, nonatomic) QYStartAdPlayerController *player; // @synthesize player=_player;
@property(nonatomic) int type; // @synthesize type=_type;
@property(retain, nonatomic) CupidAd *adCupid; // @synthesize adCupid=_adCupid;
@property(retain, nonatomic) AdsClient *adClient; // @synthesize adClient=_adClient;
@property(retain, nonatomic) QYWebContainer *webView; // @synthesize webView=_webView;
@property(retain, nonatomic) UIView *adImageView; // @synthesize adImageView=_adImageView;
@property(nonatomic) double needToCut; // @synthesize needToCut=_needToCut;
@property(nonatomic) double logoBackHeight; // @synthesize logoBackHeight=_logoBackHeight;
@property(nonatomic) long long duration; // @synthesize duration=_duration;
@property(retain, nonatomic) UILabel *secords; // @synthesize secords=_secords;
@property(nonatomic) _Bool isFullScreenAd; // @synthesize isFullScreenAd=_isFullScreenAd;
@property(nonatomic) __weak id <QYPhoneStartADViewDelegate> delegate; // @synthesize delegate=_delegate;
- (void).cxx_destruct;
- (id)imageFromImage:(id)arg1 inRect:(struct CGRect)arg2;
- (void)playToEnd;
- (void)playError;
- (void)h5WillJumpToPage;
- (void)userInteractWithHtml;
- (void)sendH5AdClickPingback;
- (void)finishDisplayHtml;
- (void)keyboardDidHide;
- (id)labelWithFrame:(struct CGRect)arg1 backgroundColor:(id)arg2 textColor:(id)arg3 font:(id)arg4 text:(id)arg5 textAlignment:(long long)arg6;
- (id)imageViewWithFrame:(struct CGRect)arg1 image:(id)arg2;
- (void)delegateCallStartADViewDidEnd;
- (void)showEnds;
- (void)updateTime;
- (void)updateUI:(id)arg1;
- (void)finishAdShowForHtml;
- (void)prepareForEndAd;
- (void)secondChange;
- (void)timerStart;
- (void)showAdDetail;
- (void)skipAd;
- (id)createTouchScreenPromptView;
- (id)createViewWithType:(int)arg1 withURL:(id)arg2;
- (void)addBottomView;
- (void)addTimeBg;
- (id)initWithType:(int)arg1 withURL:(id)arg2 withDur:(long long)arg3 withAdData:(id)arg4 withADCupid:(id)arg5;
- (void)dealloc;
// Remaining properties
@property(readonly, copy) NSString *debugDescription;
@property(readonly, copy) NSString *description;
@property(readonly) unsigned long long hash;
@property(readonly) Class superclass;
@end
这里的代码量不是很多,我们看到这个
- (id)initWithType:(int)arg1 withURL:(id)arg2 withDur:(long long)arg3 withAdData:(id)arg4 withADCupid:(id)arg5;有可能就是一个实例化方法,我们可以覆写这个方法来达到取消启动广告的效果(这里只是一个猜测!)
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
51
52
53
54
55
/*------1-------*/
// 在合适的位置执行,下面的命令
nic.pl
/*------2-------*/
// 终端的显示
NIC 2.0 - New Instance Creator
------------------------------
[1.] iphone/activator_event
[2.] iphone/application_modern
[3.] iphone/application_swift
[4.] iphone/cydget
[5.] iphone/flipswitch_switch
[6.] iphone/framework
[7.] iphone/ios7_notification_center_widget
[8.] iphone/library
[9.] iphone/notification_center_widget
[10.] iphone/preference_bundle_modern
[11.] iphone/tool
[12.] iphone/tool_swift
[13.] iphone/tweak
[14.] iphone/xpc_service
Choose a Template (required):
/*------3-------*/
// 这里我们选择13,然后回车, 这里唯一需要注意的就是这个AppID,必须要填写爱奇艺的AppID, 其他的可以随便填写、或者直接回车
Choose a Template (required): 13
Project Name (required): ghiqyTest
Package Name [com.yourcompany.ghiqytest]: com.ghcoder.ghiqyTest
Author/Maintainer Name [龚欢]:
[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.qiyi.iphone
[iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]:
Instantiating iphone/tweak in ghiqytest/...
Done.
/*------4-------*/
// 创建完成之后,会发现自动创建了一个名叫ghiqytest的文件夹,里面存在四个文件,依次是:control(相关的配置信息)、ghiqyTest.plist(你需要修改的应用的AppID)、Makefile(配置文件)、Tweak.xm(需要修改的相关类)
// 下面是我对Tweak.xm修改的内容如下:
%hook QYStartADView
- (id)initWithType:(int)arg1 withURL:(id)arg2 withDur:(long long)arg3 withAdData:(id)arg4 withADCupid:(id)arg5 {
return nil;
}
%end
/*------5-------*/
// ssh到越狱手机,并且要在Makefile的开头加上下面两行配置
export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10010
/*------6-------*/
// 如果一切正常的话,执行完成之后,越狱机器就会自动重启了
make clean && make package && make install
2. 将这个修改过的App重签名
- 步骤1. 要完成这个重签名,我们需要有如下几个文件
- 我们刚才编写的xxx.xm文件,其实刚才在我们重启之后,它就生成一个动态库文件,这个文件存放在越狱机的如下路径中:(Device->Library->MobileSubstrate->DynamicLibraries->ghiqyTest.dylib).
- 在越狱机器中加载这个动态库的Framework(CydiaSubstrate) [路径如下Device->Library->Frameworks->CydiaSubstrate.framework->CydiaSubstrate]
- 已经脱壳了的App
- xxx.mobileprovision文件,这个是需要一年99美金才可以,可以通过创建一个空的Xcode项目,编译之后在Target的App中找到这个xxx.mobileprovision文件(或者可以去apple.developer.com后台去下载)
-
步骤2. 然后将上面提到三个文件ghiqyTest.dylib、CydiaSubstrate、xxx.mobileprovision一起拷贝到已经脱壳了的App中。
-
步骤3. 在脱壳了的App中找到info.plist文件,把里面的UISupportedDevices这一栏统一删除掉。
- 步骤4. 此时我们需要查看一些动态库,以及我们的Mach-O文件依赖的库是否配置正确:
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*------1-------*/
// 查看爱奇艺Mach-O依赖的动态库
otool -L iQiYiPhoneVideo
// 终端显示
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 274.20.0)
/usr/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.9.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
/System/Library/Frameworks/AVFoundation.framework/AVFoundation (compatibility version 1.0.0, current version 2.0.0)
/System/Library/Frameworks/Accelerate.framework/Accelerate (compatibility version 1.0.0, current version 4.0.0)
/System/Library/Frameworks/AdSupport.framework/AdSupport (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CFNetwork.framework/CFNetwork (compatibility version 1.0.0, current version 974.2.1)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1556.0.0)
/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 1245.8.0)
/System/Library/Frameworks/CoreLocation.framework/CoreLocation (compatibility version 1.0.0, current version 2245.4.104)
/System/Library/Frameworks/CoreMotion.framework/CoreMotion (compatibility version 1.0.0, current version 2245.4.104)
/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony (compatibility version 1.0.0, current version 0.0.0)
/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1556.0.0)
/System/Library/Frameworks/ImageIO.framework/ImageIO (compatibility version 1.0.0, current version 0.0.0)
/System/Library/Frameworks/MapKit.framework/MapKit (compatibility version 1.0.0, current version 14.0.0)
/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices (compatibility version 1.0.0, current version 932.2.0)
/System/Library/Frameworks/OpenAL.framework/OpenAL (compatibility version 1.0.0, current version 1.0.0)
@rpath/QYUniversalFramework.framework/QYUniversalFramework (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.11.0)
/System/Library/Frameworks/SceneKit.framework/SceneKit (compatibility version 1.0.0, current version 470.0.0)
/System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 58286.202.3)
/System/Library/Frameworks/StoreKit.framework/StoreKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration (compatibility version 1.0.0, current version 963.200.27)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
/System/Library/Frameworks/WebKit.framework/WebKit (compatibility version 1.0.0, current version 606.1.36)
/System/Library/Frameworks/Intents.framework/Intents (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/IntentsUI.framework/IntentsUI (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/ReplayKit.framework/ReplayKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/UserNotifications.framework/UserNotifications (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Speech.framework/Speech (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreData.framework/CoreData (compatibility version 1.0.0, current version 865.0.0)
/System/Library/Frameworks/EventKit.framework/EventKit (compatibility version 1.0.0, current version 100.0.0)
/System/Library/Frameworks/WatchConnectivity.framework/WatchConnectivity (compatibility version 1.0.0, current version 175.0.0)
/System/Library/Frameworks/PassKit.framework/PassKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/GLKit.framework/GLKit (compatibility version 1.0.0, current version 103.2.0)
/System/Library/Frameworks/Photos.framework/Photos (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreSpotlight.framework/CoreSpotlight (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication (compatibility version 1.0.0, current version 425.202.1)
/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AVKit.framework/AVKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/MessageUI.framework/MessageUI (compatibility version 1.0.0, current version 3445.100.35)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/System/Library/Frameworks/CoreText.framework/CoreText (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.5)
/System/Library/Frameworks/CoreMedia.framework/CoreMedia (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox (compatibility version 1.0.0, current version 492.0.0)
/usr/lib/libicucore.A.dylib (compatibility version 1.0.0, current version 62.1.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/System/Library/Frameworks/CoreImage.framework/CoreImage (compatibility version 1.0.0, current version 5.0.0)
/System/Library/Frameworks/CoreML.framework/CoreML (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreVideo.framework/CoreVideo (compatibility version 1.2.0, current version 1.5.0)
/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 606.1.36)
/System/Library/Frameworks/OpenGLES.framework/OpenGLES (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/SpriteKit.framework/SpriteKit (compatibility version 1.0.0, current version 2.0.0)
/*------2-------*/
// 需要把我们刚才创建的动态库链接进来,执行如下的命令
insert_dylib @executable_path/ghiqyTest.dylib iQiYiPhoneVideo iQiYiPhoneVideo --all-yes
/*------3-------*/
// 再次执行第一步的命令,会发现最下多了一行,就代表链接成功
@executable_path/ghiqyTest.dylib (compatibility version 0.0.0, current version 0.0.0)
/*------4-------*/
// 此时我们再看一下ghiqyTest.dylib, 这个动态库有没有依赖的其他动态库
otool -L ghiqyTest.dylib
// 终端显示
ghiqyTest.dylib (architecture arm64):
/Library/MobileSubstrate/DynamicLibraries/ghiqyTest.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 1560.10.0)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1560.10.0)
/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/*------5-------*/
// 这里需要修改/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate路径,执行下面的命令就可以修改了
install_name_tool -change /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate @loader_path/CydiaSubstrate ghiqyTest.dylib
// 再次执行第四部:就会发现之前路径修改了
ghiqyTest.dylib (architecture arm64):
/Library/MobileSubstrate/DynamicLibraries/ghiqyTest.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 1560.10.0)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1560.10.0)
@loader_path/CydiaSubstrate (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
- 步骤5. 我们要先找到我们签名证书的Identity,通过如下的命令可以找到
1
2
3
4
5
6
security find-identity -v -p codesigning
// 终端显示
1) E797391C5ABBC9FB40EE04252C5679A6FEC1B351 "iPhone Developer: ******"
2) EF3725BCB7AB3C3F12AFC9C3A82C16B84A2925EC "iPhone Developer: *******" (CSSMERR_TP_CERT_REVOKED)
2 valid identities found
- 步骤6. 开始签名:
1
2
3
4
➜ iQiYiPhoneVideo.app codesign -fs E797391C5ABBC9FB40EE04252C5679A6FEC1B351 ghiqyTest.dylib
ghiqyTest.dylib: replacing existing signature
➜ iQiYiPhoneVideo.app codesign -fs E797391C5ABBC9FB40EE04252C5679A6FEC1B351 CydiaSubstrate
CydiaSubstrate: replacing existing signature
- 步骤7. 最后我们对App整体签名,这里可以使用一个方便工具iOSAppSinger 步骤7.1 也可以通过codesign,来完成对App的整体签名:
1
2
3
4
5
6
7
8
9
10
11
/*------1-------*/
// 先从xxx.mobileprovision导出xxx.entitlements
security cms -D -i embedded.mobileprovision > temp.plist
/usr/libexec/PlistBuddy -x -c 'Print:Entitlements' temp.plist > entitlements.plist
/*------2-------*/
// 生成完成之后的entitlements.plist,配合codeSign进行重签名
codesign -fs E797391C5ABBC9FB40EE04252C5679A6FEC1B351 --entitlements entitlements.plist xxx.app
/*------3-------*/
// 生成之后的xxx.app,放到Payload的文件夹中,然后进行压缩,然后再修改后缀名为.ipa
3. 安装在未越狱手机上
直接通过iFunbox安装在非越狱机器上。