需求
- 给微信的"发现”界面增加2行功能
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e1ea280686229b3c8f2822fa2f23cf0e.png)
此教程所需要的工具/文件
- class-dump
- iTools
- OpenSSH(Cydia)
- iFile(Cydia)
- Cycript(Cydia)
- Reveal
- dumpdecrypted
- 一台越狱的iPhone
分析
- 找到
发现
界面的数据源 - 获取微信的脱壳的Mach-O文件
- 用
class-dump
将Mach-O的头文件导出, 找到对应的头文件 - 用theos编写插件
1. 根据TableView找到它的数据源, 修改数据源方法
- 主TableView: MMMainTableView
cy# #0x15e9bfa00.dataSource
#"delegate[0x15ea09e00], class[FindFriendEntryViewController]"
cy# MJFrontVc()
#"<FindFriendEntryViewController: 0x15ea09e00>"
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/2f222bf262efb83f0bd009a7b5a66e4d.png)
2. 获取微信的脱壳的Mach-O文件
2.1 获取微信的存储路径
ps -A
/var/containers/Bundle/Application/62F0E867-833E-44A6-8900-A3E98B303807/WeChat.app/WeChat
- 通过iFunBox获取Mach-O文件
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/98c23a705e11d4e74bc72b4456983074.png)
2.2 查看Mach-O文件是否加密
otool -l WeChat | grep crypt
cryptoff 16384
cryptsize 65617920
cryptid 1
2.3 脱壳
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/containers/Bundle/Application/62F0E867-833E-44A6-8900-A3E98B303807/WeChat.app/WeChat
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/496012e33fea67426912c38c93e4cf3b.png)
- 脱壳成功的文件在
/var/root/
下, 默认 xxx.decrypt
, 验证是否脱壳成功
otool -l WeChat | grep crypt
cryptoff 16384
cryptsize 65617920
cryptid 0
- 脱壳成功,文件就是在
var/root/WeChat.decrypted
3. 用 class-dump
将Mach-O的头文件导出
class-dump -H WeChat -o Headers
4. 用theos编写插件
4.1 获取微信的bundle Id
cy# MJAppId
@"com.tencent.xin"
4.2 编写tweak文件
nic.pl
4.2.1 返回cell个数和cell内容
%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;
}
}
- (id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath {
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1) {
return %orig;
}
UITableViewCell *cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:nil];
cell.backgroundColor = [UIColor whiteColor];
cell.textLabel.text = @"666";
return cell;
}
- (double)tableView:(id)tableView heightForRowAtIndexPath:(id)indexPath {
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1) {
return %orig;
}
return 44;
}
%end
4.2.2 界面调整和退出微信
- (id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath {
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1) {
return %orig;
}
UITableViewCell *cell = nil;
if ([indexPath row] == 0) {
static NSString *autoCellId = @"autoCellId";
cell = [tableView dequeueReusableCellWithIdentifier:autoCellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:autoCellId];
cell.backgroundColor = [UIColor whiteColor];
}
cell.textLabel.text = @"自动抢红包";
UISwitch *s = [[UISwitch alloc] init];
cell.accessoryView = s;
} else if ([indexPath row] == 1) {
static NSString *exitCellId = @"exitCellId";
cell = [tableView dequeueReusableCellWithIdentifier:exitCellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:exitCellId];
cell.backgroundColor = [UIColor whiteColor];
}
cell.textLabel.text = @"退出微信";
}
return 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) {
abort();
}
}
4.2.3 数据存储
#define ADUserDefaults [NSUserDefaults standardUserDefaults]
#define ADAutoKey @"ad_auto_key"
UISwitch *switchView = [[UISwitch alloc] init];
[switchView addTarget:self action:@selector(valueChange:) forControlEvents:UIControlEventValueChanged];
switchView.on = [ADUserDefaults boolForKey:ADAutoKey];
cell.accessoryView = switchView;
%new
- (void)ad_valueChange:(UISwitch *)switchView {
[ADUserDefaults setBool:switchView.isOn forKey:ADAutoKey];
[ADUserDefaults synchronize];
}
4.2.4 加载图片资源
- 新建一个layout文件夹,相当于手机的根文件夹,将文件放在手机的资源文件夹
/Library/PreferenceLoader/Preferences/
, 并再新建一个XXApp文件夹,防止重名 - 如果想让路径简单点,也可以放到缓存文件夹
Library/Caches/
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3c8ccfeb7f8e4bd6307688b5d895f674.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ea9cd38c983ff6c72951a416a3187b39.png)
- 加载图片代码
cell.imageView.image = [UIImage imageWithContentsOfFile:@"/Library/PreferenceLoader/Preferences/ADWeChat/AppIcon@2x.png"];
- 重新安装插件
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/61e6ac01353fe372798a213d501099c0.jpeg)
4.2.5 宏定义资源路径
#define ADFile(path) @"/Library/PreferenceLoader/Preferences/ADWeChat/" #path
cell.imageView.image = [UIImage imageWithContentsOfFile:ADFile(AppIcon@2x.png)];
5. 最终代码
#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;
}
}
- (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
- (void)ad_valueChange:(UISwitch *)switchView {
[ADUserDefaults setBool:switchView.isOn forKey:ADAutoKey];
[ADUserDefaults synchronize];
}
- (double)tableView:(id)tableView heightForRowAtIndexPath:(id)indexPath {
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1) {
return %orig;
}
return 44;
}
- (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) {
abort();
}
}
%end