需求1:把手機桌面APP的提示數(shù)字都去掉纵菌。
思路:桌面也應(yīng)該是個應(yīng)用SpringBoard,找到這個應(yīng)用休涤。
步驟:
- 連接登錄手機
-
ps -A
, 確定有/System/Library/CoreServices/SpringBoard.app/SpringBoard這個應(yīng)用咱圆; - 監(jiān)視
cycript -p SpringBoard
- 用iFunBox導(dǎo)出SpringBoard的Mach-O頭文件
- 確定是否加殼,方式一:
otool -l 可執(zhí)行文件路徑 | grep crypt
,如果沒有打印闷堡,說明沒加殼隘膘;方式二:用MachOView工具查看,在Load Commands下沒有LC_ENCRYPTION_INFO_64這項杠览,也可說明沒加殼弯菊; - 脫殼:
Clutch -i
,Clutch -d APP序號或BundleId
踱阿,脫殼后的文件在 - 導(dǎo)出頭文件
class-dump -H SpringBoard -o headers/
- 找到是哪個類是設(shè)置app右上角數(shù)字提示的(靠經(jīng)驗猜)管钳。1、沒法用reveal查看到手機桌面app的數(shù)字提示view软舌;2才漆、用MJTool打印,找到keyWindow:
MJKeyWin()
佛点,打印keyWindow的子view:MJSubviews (#0x1271867a0)
醇滥,根據(jù)名字觀察,把SBIconView
的屬性hidden設(shè)置為1#0x1281b25a0.hidden = 1
超营,發(fā)現(xiàn)有app的圖標(biāo)消失鸳玩,這說明SBIconView下的SBIconParallaxBadgeView可能是數(shù)字提示的,設(shè)置它的屬性hidden為隱藏#0x1276d7fb0.hidden = 1
演闭,發(fā)現(xiàn)紅色背景提示的view消失了不跟,說明0x1276d7fb0對應(yīng)的那個類SBIconParallaxBadgeView
是管桌面app數(shù)字提示的; - 打開該類的頭文件米碰,hook它的init方法窝革,讓它return nil;
- 創(chuàng)建tweak項目吕座,cd到SpringBoardTweak文件夾下虐译,
nic.pl
(用MJAppId獲取bundleId) -
開始編輯Tweak.xm
- 編譯-打包-安裝
make && make package && make install
(順便在~/文件夾下vim tweak.sh,把make && make package && make install放在tweak.sh中米诉,方便以后執(zhí)行)
需求2:在『發(fā)現(xiàn)-小程序』下面增加兩行
思路:hook tableView數(shù)據(jù)源方法菱蔬。
- 分析界面:
通過reveal和MJTool確定,MMMainTableView界面繼承自UITableView史侣,當(dāng)前類是FindFriendEntryViewController(MJFrontVc()
),數(shù)據(jù)源代理是FindFriendEntryViewController(#0x12e133600.dataSource
) - 導(dǎo)出頭文件:
-->a. 導(dǎo)出Mach-O文件(ps-A
確定位置)魏身;
-->b. 確定是否有加殼(otool -l 可執(zhí)行文件路徑 | grep crypt
惊橱;或用MachOView工具查看,在Load Commands下看是否有LC_ENCRYPTION_INFO_64這項進(jìn)入看看)箭昵;Clutch -i
能列出來就是加了密要脫殼税朴;
-->c.脫殼,Clutch -d 3
脫殼失敗(此非官方方法)正林;DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib 可執(zhí)行文件路徑
(ps-A查看路徑)泡一,得到的脫殼文件就在手機/root/文件夾下 ;
-->d.導(dǎo)出頭文件觅廓,class-dump -H WeChat -o headers/
- 編寫hook代碼:
找到數(shù)據(jù)源控制器FindFriendEntryViewController鼻忠,hook數(shù)據(jù)源方法。
-->a.nic.pl
創(chuàng)建tweak項目杈绸;
-->b. 拖拽項目到Sublime編寫Tweak.xm帖蔓,多少組、每組多少行瞳脓、cell返回方法塑娇、cell高度、點擊方法劫侧、添加UISwitch(注意返回以前的實現(xiàn)%orig)
3.1 實現(xiàn)優(yōu)雅閃退:exit(0)有點卡的感覺埋酬,abort()可立即閃退。
3.2 加載圖片:
a. 在Tweak.xm文件夾下新建layout/PreferenceLoader/Preferences/LFWeChat
或layout/Library/Caches/LFWeChat/
(推薦后者路徑)烧栋,這里的layout文件夾就相當(dāng)于手機上的Device根路徑奇瘦;
b. 加載圖片API:
[UIImage imageWithContentsOffFile:@"/Library/Caches/LFWeChat/skullo.png"];
c. 把圖片加載路徑寫成宏
#define LFFile(path) @"/Library/Caches/LFWeChat/" #path
圖片資源路徑:
舊:#define LFFile(path) @"/Library/PreferenceLoader/Perferences/MJWeChat/"
新:(推薦)#define LFFile(path) @"/Library/Caches/MJWeChat/" #path
3.3 本地存儲
取
#define LFDefaults [NSUserDefaults standardUserDefaults]
s.on = [LFDefaults boolForKey:LFStorageKey];
存
%new
- (void)lf_switchChange:(UISwitch *)switchView {
[LFDefaults setBool:switchView.on forKey:LFStorageKey];
[LFDefaults synchronize];
}
3.4 如何添加新方法
Tweak.xm中寫的方法會認(rèn)為是替換原有的方法
如果要新增新方法劲弦,前面要加%new耳标;
看一個崩潰信息:點擊UISwitch的時候奔潰了,查看控制臺:
WeChat -[FindFriendEntryViewController lf_switchChange:]: unrecognized selector sent to instance 0x12e9c3800邑跪,控制器不認(rèn)識UISwitch綁定的方法次坡,是因為原來的FindFriendEntryViewController控制器里面沒有這個方法,lf_switchChange:屬于新的方法画畅,方法前加%new即可砸琅。
3.5 代碼 Tweak.xm
#define LFDefaults [NSUserDefaults standardUserDefaults]
#define LFStorageKey @"lf_storage_key"
// #define LFFile(path) @"/Library/PreferenceLoader/Perferences/LFWeChat/" #path
#define LFFile(path) @"/Library/Caches/LFWeChat/" #path
%hook FindFriendEntryViewController
- (long long)numberOfSectionsInTableView:(UITableView *)arg1
{
return %orig + 1;
}
- (long long)tableView:(UITableView *)tableView numberOfRowsInSection:(long long)section
{
if (section != [self numberOfSectionsInTableView:tableView] - 1)
{
return %orig;
} else {
return 2;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath section] != [self numberOfSectionsInTableView:tableView] - 1)
{
return %orig;
}
UITableViewCell *cell = nil;
if ([indexPath row] == 0)
{
NSString *autoCellId = @"autoCellId";
cell = [tableView dequeueReusableCellWithIdentifier:autoCellId];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:autoCellId];
}
UISwitch *s = [[UISwitch alloc] init];
s.on = [LFDefaults boolForKey:LFStorageKey];
[s addTarget:self action:@selector(lf_switchChange:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = s;
cell.textLabel.text = @"自動搶紅包";
cell.accessoryView.hidden = NO;
} else if ([indexPath row] == 1) {
NSString *exitCellId = @"exitCellId";
cell = [tableView dequeueReusableCellWithIdentifier:exitCellId];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:exitCellId];
}
cell.textLabel.text = @"退出微信";
cell.accessoryView.hidden = YES;
}
cell.backgroundColor = [UIColor whiteColor];
cell.imageView.image = [UIImage imageWithContentsOfFile:LFFile(skullo.png)];
return cell;
}
- (double)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath section] != ([self numberOfSectionsInTableView:tableView] - 1))
{
return %orig;
} else {
return 44;
}
}
// 修復(fù)點擊崩潰的問題
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath section] != ([self numberOfSectionsInTableView:tableView] - 1))
{
return %orig;
} else {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([indexPath row] == 1)
{
// exit(0);
//終止進(jìn)程
abort();
}
}
}
%new
- (void)lf_switchChange:(UISwitch *)switchView {
[LFDefaults setBool:switchView.on forKey:LFStorageKey];
[LFDefaults synchronize];
}
%end
需求3:theos - tweak的原理
——Tweak.xm中的代碼是怎么影響到微信的呢?
01 安裝過程
最初文件夾中有這些東西:
make
編譯操作后:
有個weChatTweak.dylib動態(tài)庫轴踱,由Tweak.xm中代碼編譯而來症脂。動態(tài)庫是沒辦法直接裝到手機上的,下一步打包
make package
操作打包:
將動態(tài)庫打包成deb插件淫僻。
> Making stage for tweak weChatTweak…
dm.pl: building package `com.lf.wechattweak:iphoneos-arm' in `./packages/com.lf.wechattweak_0.0.1-1+debug_iphoneos-arm.deb'
告訴你包的位置./packages/com.lf.wechattweak_0.0.1-1+debug_iphoneos-arm.deb
make install
:
會SSH遠(yuǎn)程登錄手機诱篷,根據(jù)~/.bash_profile中的export THEOS_DEVICE_IP=127.0.0.1
和export THEOS_DEVICE_PORT=10010
找到IP地址和端口,去登錄和傳遞數(shù)據(jù)雳灵,由于我們做了端口映射棕所,當(dāng)訪問127.0.0.1的10010端口的時候,就相當(dāng)于訪問遠(yuǎn)程的22端口悯辙,就相當(dāng)于能登錄到手機琳省,就能傳遞數(shù)據(jù)迎吵。
手機接收到deb包的時候,就會讓Cydia去安裝deb包针贬,安裝好后击费,會將weChatTweak.dylib動態(tài)庫放到/Library/MobileSubstrate/DynamicLibraries文件夾
1、weChatTweak.plist:里面的內(nèi)容就是創(chuàng)建Tweak項目時候填的appId——com.tencent.xin桦他;
2蔫巩、weChatTweak.dylib:在Tweak.xm里面寫的代碼
DynamicLibraries這個文件夾是誰在管呢?
是Cydia中的Cydia Substrate插件
瞬铸,就是通過它來安裝從Mac端傳來的的deb包批幌,把weChatTweak.dylib動態(tài)庫和plist文件安裝到/Library/MobileSubstrate/DynamicLibraries下。
02運行過程
weChatTweak.dylib動態(tài)庫又是怎么影響到微信呢嗓节?
點擊微信app荧缘、
啟動微信app,啟動的時候Cydia Substrate插件
就會去看DynamicLibraries文件夾下的.plist文件中的AppID拦宣,如果發(fā)現(xiàn)和啟動的app的appID是一樣的截粗,Cydia Substrate插件
就會讓微信加載對應(yīng)的動態(tài)庫,接著Cydia Substrate插件
就會改變內(nèi)存中的一些代碼鸵隧,改變代碼的一些執(zhí)行流程绸罗,比如控制器原本調(diào)用numberOfSectionsInTableView:
方法,那他會調(diào)用到動態(tài)庫中的對應(yīng)函數(shù)豆瘫。
微信的可執(zhí)行文件我們沒有改過珊蟀,并沒有注入到微信原來的可執(zhí)行文件中去,目前僅是Cydia Substrate插件
改了內(nèi)存中的一些代碼外驱。
--> 驗證weChatTweak.dylib動態(tài)庫被加載到內(nèi)存:
打開控制臺:
只要是MS開頭的育灸,就是Cydia Substrate插件
在幫助做的事情。
--> 如何驗證內(nèi)存中的代碼發(fā)生了改變
——從匯編的角度分析
- 創(chuàng)建一個XCode測試項目昵宇;
- 斷點step into查看匯編代碼磅崭,保留著對比;
- 創(chuàng)建Tweak項目瓦哎;
- deb包安裝到手機砸喻;
- 斷點step into查看匯編代碼,保留著對比蒋譬;
對比前后是否有變割岛。
從前后的匯編代碼的不同可以看出,內(nèi)存中的代碼確實發(fā)生了改變羡铲,調(diào)用了動態(tài)庫里面的方法蜂桶。究竟是怎么調(diào)用的,后面再看也切。
需求4:Tweak多文件開發(fā)
4.1 代碼的格式不一定要是.xm扑媚、.x,也可以是.m或.h雷恃。
4.2 分文件夾:但要指定所有要編譯的文件疆股,由Makefile中的TweakTest_FILES變量來指定文件路徑,用空格拼接倒槐,路徑從Makefile文件當(dāng)前位置開始找旬痹。可用*做為通配符讨越,后綴不能柿讲小(經(jīng)驗證,通配符*不好使把跨,只能通配一個文件人弓,無法通配多個文件,還是不要用吧)着逐。
4.3 導(dǎo)入頭文件:Tweak.xm中導(dǎo)入頭文件崔赌,頭文件的路徑是從Tweak.xm當(dāng)前位置開始找。
需求5:Tweak細(xì)節(jié)-發(fā)布release版本
release包比debug包會小一點耸别。
打包release版本的指令:
make package debug=0
修改tweak.sh:
make clean && make package debug=0 && make install