安装签名工具ldid
- 安装
Homebrew
1
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- 利用
brew
安装ldid
1
$ brew install ldid
修改环境变量
1
2
ls -l
ls -al // 查看目录文件(详细)
1
2
3
4
5
6
7
8
9
10
viw ~/.bash_profile
// 输入i
export THEOS=~/theos
export PATH=$THEOS/bin:$PATH
// 退出
esc
:wq
// 配置环境有可能无效,需要执行一下.bash_profile
让.bash_profile配置的环境表里立即生效(或者重新打开终端)
$ source ~/.bash_profile
注意: source .bash_profile有可能出错
rm -f ~/.bash_profile.swp
source .bash_profile
下载theos
1
2
// --recursive: 递归下载,会把依赖也下载下来
git clone --recursive https://github.com/theos/theos.git $THEOS
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
$ cd ~/Desktop
$ nic.pl
NIC 2.0 - New Instance Creator
------------------------------
[1.] iphone/activator_event
[2.] iphone/activator_listener
[3.] iphone/application_modern
[4.] iphone/application_swift
[5.] iphone/cydget
[6.] iphone/flipswitch_switch
[7.] iphone/framework
[8.] iphone/library
[9.] iphone/notification_center_widget
[10.] iphone/notification_center_widget-7up
[11.] iphone/preference_bundle_modern
[12.] iphone/theme
[13.] iphone/tool
[14.] iphone/tool_swift
[15.] iphone/tweak
[16.] iphone/tweak_with_simple_preferences
[17.] iphone/xpc_service
Choose a Template (required): 15
Project Name (required): tingtweak
Package Name [com.yourcompany.tingtweak]: com.jovins.tingtweak
Author/Maintainer Name [Jovins]:
[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.gemd.iting
[iphone/tweak] List of applications to terminate upon installation (space-separated. '_' for none) [SpringBoard]: Springboard
Instantiating iphone/tweak in springboardtest/...
Done.
填写项目信息
Project Name
: 项目名称Package Name
: 项目ID(随便写,如: com.jovins.tingtweak)Author/Maintainer Name
: 作者,直接回车默认就行(默认电脑用户名)[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]
- 需要修改的App的Bundle identifier (喜马拉雅FM的是com.gemd.iting)
- 可以通过Cycript查看App的Bunlde Identifier
- iphone/tweak] List of applications to terminate upon installation: 直接回车
编辑Makefile
- 在前面加入环境变量,写清楚通过那个IP和端口访问手机
THEOS_DEVICE_IP
THEOS_DEVICE_PORT
1
2
3
4
5
6
7
8
9
export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10010
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = ting_tweak
ting_tweak_FILES = Tweak.xm
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
install.exec "killall -9 SpringBoard"
如果不希望每个项目的
Makefile
都编写IP和端口环境变量,也可以添加到用户配置文件中。- 编辑完毕后
source ~/.bash_profile
让配置生效(或重启终端)
1 2 3 4 5 6
$ vim ~/.bash_profile export THEOS=~/theos export PATH=$THEOS/bin:$PATH export THEOS_DEVICE_IP=127.0.0.1 export THEOS_DEVICE_PORT=10010 $ source ~/.bash_profile
- 编辑完毕后
编写代码
- 打开
Tweak.x
文件
1
2
3
4
5
6
7
8
9
10
11
%hook XMAdAnimationView
- (id)initWithImageUrl:(id)arg1 title:(id)arg2 iconType:(long long)arg3
jumpType:(long long)arg4
{
return nil; }
%end
%hook XMSoundPatchPosterView
- (id)initWithFrame:(struct CGRect)arg1
{
return nil; }
%end
编译-打包-安装
编译
1
make
打包成deb
1
make package
安装(默认会自动重启SpringBoard)
1
make install
可能遇到的错误
1.
make package
的错误1 2 3 4 5 6 7 8 9 10 11
$ make package Can't locate IO/Compress/Lzma.pm in @INC (you may need to install the IO::Compress::Lzma module) (@INC contains: /Library/Perl/5.18/darwin- thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin- thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.2 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread- multi-2level /System/Library/Perl/Extras/5.18 .) at /Users/mj/theos/bin/dm.pl line 12. BEGIN failed--compilation aborted at /Users/mj/theos/bin/dm.pl line 12. make: *** [internal-package] Error 2
是因为打包压缩方式有问题,改成gzip压缩就行
修改
dm.pl
文件,将#号注释掉下面两句1 2 3
$ vim $THEOS/vendor/dm.pl/dm.pl #use IO::Compress::Lzma; #use IO::Compress::Xz;
修改deb.mk文件第6行的压缩方式为gzip
1 2
$ vim $THEOS/makefiles/package/deb.mk _THEOS_PLATFORM_DPKG_DEB_COMPRESSION ?= gzip
2.make的错误
1 2 3 4
$ make Error: You do not have an SDK in /Library/Developer/CommandLineTools/Platforms/iPhoneOS.platform/Developer/S DKs
是因为多个xcode导致路径有可能安装了好几个xcode,需要指定一下Xcode
1 2
$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer/
1 2 3
$ make > Making all for tweak xxx... make[2]: Nothing to be done for `internal-library-compile'.
是因为之前已经变异过,有缓存导致的,clean一下即可
1 2
$ make clean $ make
练习
将iPhone桌面的更新红色数字去掉
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10010
TARGET := iphone:clang:latest:7.0
INSTALL_TARGET_PROCESSES = SpringBoard
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = tweak_sb
tweak_sb_FILES = Tweak.x
tweak_sb_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk
1
2
3
4
5
6
7
8
%hook SBIconBadgeView
- (id)init
{
return nil;
}
%end
1
2
3
4
5
tweak_sb $ make
tweak_sb $ make package
tweak_sb $ make install
或者
tweak_sb $ make && make package && make install
给微信的"发现"界面增加2行功能
#define ADUserDefaults [NSUserDefaults standardUserDefaults]
#define ADAutoKey @"ad_auto_key"
#define ADFile(path) @"/Library/PreferenceLoader/Preferences/ADWeChat/" #path
%hook FindFriendEntryViewController
// 一共多少组
- (long long)numberOfSectionsInTableView:(id)tableView {
return %orig + 1;
}
// 每组多少行
- (long long)tableView:(id)tableView numberOfRowsInSection:(long long)section {
if (section == [self numberOfSectionsInTableView:tableView] - 1) {
return 2;
} else {
return %orig;
}
}
// cell内容布局
- (id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath {
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1) {
return %orig;
}
static NSString *cellId = [indexPath row] == 0 ? @"autoCellId" : @"exitCellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
cell.backgroundColor = [UIColor whiteColor];
cell.imageView.image = [UIImage imageWithContentsOfFile:ADFile(AppIcon@2x.png)];
}
if ([indexPath row] == 0) {
cell.textLabel.text = @"自动抢红包";
UISwitch *switchView = [[UISwitch alloc] init];
[switchView addTarget:self action:@selector(ad_valueChange:) forControlEvents:UIControlEventValueChanged];
switchView.on = [ADUserDefaults boolForKey:ADAutoKey];
cell.accessoryView = switchView;
} else if ([indexPath row] == 1) {
cell.textLabel.text = @"退出微信";
}
return cell;
}
// 自动抢红包按钮打开/关闭(如果是新方法, 需要加上%new)
%new
- (void)ad_valueChange:(UISwitch *)switchView {
[ADUserDefaults setBool:switchView.isOn forKey:ADAutoKey];
[ADUserDefaults synchronize];
}
// 返回cell的高度
- (double)tableView:(id)tableView heightForRowAtIndexPath:(id)indexPath {
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1) {
return %orig;
}
return 44;
}
// 选中cell
- (void)tableView:(id)tableView didSelectRowAtIndexPath:(id)indexPath {
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1) {
%orig;
return;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([indexPath row] == 1) {
// exit(); // 这种方式有卡顿,不推荐
abort(); // 终止进程, 使用这种方式退出无卡顿
}
}
1
$ make package debug=0 // release版本
去掉内涵段子的广告
- 首页的广告
- 评论区的广告
%hook SSTipModel
- (id)initWithDictionary:(id)arg1 location:(long long)arg2 {
return nil;
}
%end
%hook EssayDetailTipModel
- (id)initWithDictionary:(id)arg1 error:(id *)arg2
{
return nil;
}
%end
- 腾讯视频广告
// 去掉启动页广告
@interface TADSplashWindow
- (void)hideSplash;
@end
%hook TADSplashWindow
- (void)showSplash
{
[self hideSplash];
}
%end
// 去掉视频广告
%hook QNBPlayerVideoAdsViewController
- (id)initWithEventProxy:(id)arg1 withPlayerInfo:(id)arg2
withParentViewController:(id)arg3 withPageViewController:(id)arg4
withAddToParentViewControllerNow:(_Bool)arg5
{
return nil;
}
- (id)initWithEventProxy:(id)arg1 withPlayerInfo:(id)arg2
withParentViewController:(id)arg3 withParentEventViewController:(id)arg4
withAddToParentViewControllerNow:(_Bool)arg5
{
return nil;
}
%end
theos资料查询
目录结构: https://github.com/theos/theos/wiki/Structure
环境变量: http://iphonedevwiki.net/index.php/Theos
Logos
语法: http://iphonedevwiki.net/index.php/Logos%hook、%end : hook一个类的开始和结束
%log: 打印方法调用详情
- 可以通过
Xcode -> Window -> Devices and Simulators
查看日志
- 可以通过
HBDebuglog
: 跟NSLog类似%new: 添加一个新的方法
%c(className):生成一个Class对象,比如%c(NSObject),类似于NSStringFromClass()、objc_getClass()
%orig : 函数原来的代码逻辑
%ctor: 加载动态库时调用
%dtor: 在程序退出时调用
logify.pl : 可以将一个头文件快速转换成已经包含打印信息的xm文件
1
logify.pl xx.h > xx.xm
如果有额外的资源文件(比如图片),放在项目的layout文件夹中,对应着文件夹中,对应着手机的根路径/
theos-tweak的实现过程
- 编写Tweak代码
$ make
: 编译Tweak代码为动态库(*.dylib)$ make package
: 将dylib打包为deb文件$ make install
: 将deb文件传送到手机上,通过Cydia安装deb- 插件将会安装在
/Library/MobileSubstrate/DynamicLibraries
文件夹中*.dylib
: 编译后的Tweak代码*.plist
: 存放着需要hook的APP ID
- 当打开App时
- Cydia Substrate(Cydia已自动安装的插件)会让App去加载对应的dylib
- 修改App内存中的代码逻辑,去执行dylib中的函数代码
- 所以,theos的tweak并不会对App原来的可执行文件进行修改,仅仅是修改了内存中的代码逻辑
- 疑问
- 未脱壳的App是否支持tweak?
- 支持,因为是在内存中实现的,并没有修改.app包中的可执行文件
- tweak效果是否永久性的?
- 取决于tweak中用到的App代码是否被修改过
- 未越狱的手机是否支持tweak?
- 不支持
- 能不能对Swift/C函数进行tweak?
- 可以,方式跟OC不一样
- 能不能对游戏项目进行tweak?
- 可以
- 但是游戏大多是通过C++/C编写的,而且类名、函数名会进行混淆操作
- 未脱壳的App是否支持tweak?
logify.pl
注意点
生成的xm文件
1 2
// > 覆盖,>> 追加 $ logify.pl BaseTest.h > Test.h
logify.pl
生成的xm文件,you很多时候是编译不通过的,需要进行一些处理- 删掉__weak
- 删掉inout
- 删掉协议,比如
- 或者声明一下一些信息@protocol TestDelegate
- 删掉- (void).cxx_destruct { %log; %orig; }
- 删掉HBLogDebug(@” = 0x%x”, (unsigned int)r);
- 替换类型为void,比如将XXPerson *替换为 *void **
- 或者声明一下类信息@class XXPerson
命令行工具
权限
给可执行文件签上一定的权限,让它可以访问其他App的可执行文件。
权限: entitlements
1 2 3
// > 代表覆盖文件,>> 代表追加 // 导出可执行文件权限 $ ldid -e TestCL > TestCL.entitilements
- SpringBoard拥有所有访问权限,可以通过获取SpringBoard赋给可执行文件访问权限。
1 2 3 4
// 导出SpringBoard可执行文件权限 $ ldid -e SpringBoard > SpringBoard.entitilements // 将权限赋给TestCL $ ldid -SSpringBoard.entitilements TestCL