代碼注入及微信簡單破壞

我們知道,程序在啟動的時候會把引用到的庫都放在Load commands段當中,所以勘高,通過給這個段增加記錄,就可以注入我們自己寫的庫坟桅。
簡單來說就是通過修改可執(zhí)行文件的Load Commands华望,增加一個LC_LOAD_DYLIB,寫入庫路徑仅乓。這樣程序執(zhí)行的時候就會來編譯這個LC_LOAD_DYLIB找到要注入的庫赖舟。

前期準備:

通過應用重簽完成脫殼應用在手機上的運行,已確保重簽成功夸楣。

一宾抓、framework注入

流程簡介
通過Xcode創(chuàng)建新的framework庫,在庫中新建類裕偿,通過在類中的load方法里完成代碼編寫洞慎。編譯后將framework文件放置重簽應用app包中的Frameworks文件夾中痛单。通過yololib寫入路徑嘿棘。然后打包app包文件。用腳本重簽并運行

詳細流程:

1旭绒、創(chuàng)建framework,完成簡單代碼編寫鸟妙。

新建

選擇framework

新建DyInjectCode類,編寫簡單代碼挥吵,以驗證注入代碼是否執(zhí)行:

#import "DyInjectCode.h"
@implementation DyInjectCode
+ (void)load{
    NSLog(@"");
}
@end

2重父、編譯項目,找到framework文件忽匈。

工程目錄下的framework文件

這時通過查看工程目錄下的app包內(nèi)Frameworks文件夾房午,可見里面存在剛才新建的framework文件。
Frameworks

這里仿佛是已經(jīng)達到了我們的目的丹允,將DyFramework放置到了指定的位置郭厌。但是運行時通過查看可執(zhí)行文件袋倔,并沒有發(fā)現(xiàn)這個玩意兒。
況且因為腳本重簽的原因折柠,我們項目下的app包都會被解壓的脫殼包給替換宾娜,所以究其根本,我們應該將新建的DyFramework放置到脫殼app包文件中的Frameworks文件夾中扇售。

3前塔、通過yololib寫入庫路徑。
yololib的安裝:網(wǎng)上下載yololib可執(zhí)行文件承冰,將其放置到/usr/local/bin文件夾中华弓。(這里固定地址是為了方便后續(xù)腳本編寫)
DyFramework放置脫殼應用包中的Frameworks文件夾中,可得DyFramework的可執(zhí)行文件的路徑(相對于包文件中)是:

Frameworks/DyFramework.framework/DyFramework

將庫可執(zhí)行文件的路徑寫入可執(zhí)行文件中:

yololib WeChat Frameworks/DyFramework.framework/DyFramework

成功標志

接著通過查看項目的可執(zhí)行文件可發(fā)現(xiàn)我們自己創(chuàng)建的庫已經(jīng)存在于load commands里面了巷懈。
MachOView顯示

4该抒、重新打包文件,運行重簽項目顶燕。便可以看到效果了凑保。

//打包命令
zip -ry WeChat.ipa Payload
注入代碼被執(zhí)行
腳本自動化執(zhí)行:

以上創(chuàng)建framework的后續(xù)步驟,可以通過腳本執(zhí)行涌攻,在重簽腳本后面加上:

yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/DyFramework.framework/DyFramework"

一欧引、Dylib注入

是一堆 .o 的集合 ,會被編譯器 編譯成為編譯單元(.o), 每個.o里面有確定的符號和不確定的符號, 所有不確定的符號都在鏈接過程中互相填補恳谎。
dylib在程序編譯的時候, 并沒有被編譯進二進制目標代碼中, 只有當程序里執(zhí)行相應的函數(shù)才調(diào)用該函數(shù)庫里對應的函數(shù)芝此。
所以具有以下特點:
1.文件體積更小。2.升級會更方便因痛。3.減少編譯時間婚苹。

流程簡介:
創(chuàng)建dylib,修改BuildSetting中的部分參數(shù)鸵膏〔采拷貝其文件至脫殼包目錄中的Frameworks,打包運行即可谭企。

詳細流程:

1廓译、創(chuàng)建Dylib

因為DylibMac OS的庫,所以編譯會默認選擇使用Mac的债查。為了讓手機能夠也能夠編譯非区,因此會有如下操作。

  • Build Settings下的Base SDK更改為iOS盹廷。

  • 修改簽名征绸,為了讓其能夠在iOS平臺上使用。


  • 更改target為選擇的動態(tài)庫,修改最低支持版本號管怠,編譯得到庫文件剥汤。

2、拷貝文件至Frameworks中排惨。
這里可以通過添加依賴的方式吭敢,選擇所生成的庫文件,編譯就會把相應的庫文件拷貝至目標文件夾中暮芭。

這時通過查看包文件中的Frameworks便可以發(fā)現(xiàn)它鹿驼。
這個步驟也可以通過手動拷貝完成。

3辕宏、通過yololib寫入路徑畜晰。
這里可以通過編寫腳本的方式,在重簽腳本中添加如下代碼:

//同理framework的寫入路徑也可以用腳本完成瑞筐。
yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/libDyounggg.dylib"

也可以手動寫入:

yololib WeChat Frameworks/libDyounggg.dylib

4凄鼻、打包。運行項目聚假,效果如下


三块蚌、通過Swizzle破壞微信注冊

完成以上任何一種代碼注入的方式之后,我們便可以分析微信運行過程膘格,注入我們的代碼峭范,修改其中功能了。

前期準備:

  • 完成之前的任何一種代碼注入方式瘪贱。
  • class-dump工具纱控,以及其導出微信項目的所有頭文件。
  • sublime text工具菜秦,完成頭文件的查看甜害。

流程簡介:
運行項目,通過Xcodeview debug球昨,選擇注冊按鈕尔店,通過查看或分析其所屬的類以及綁定的方法,完成對方法的替換褪尝。

詳細流程:
1闹获、運行項目期犬,通過view debug分析河哑。
進入界面,選擇注冊按鈕龟虎,會有如下顯示:

image.png

分析可知:

  • 通過上紅框處我們可看到注冊按鈕所屬的類以及其對應的地址璃谨。
  • 通過下方紅框我們可見按鈕方法所屬的響應者、方法以及它們的地址。在某些Xcode版本會有直接響應者和方法名的顯示佳吞。這里沒有拱雏,我們便可以通過命令查看其具體信息:
(lldb) po 0x281563e00
{
    className = WCAccountLoginControlLogic;
    memoryAddress = 0x28280bed0;
}

(lldb) po 0x281563bc0
{
    className = "__NSCFString";
    memoryAddress = 0x280ba81e0;
}

(lldb) po 0x280ba81e0
onFirstViewRegester

通過打印地址信息,我們便可以知道按鈕綁定方法的targetWCAccountLoginControlLogic底扳,綁定的方法名為:onFirstViewRegester铸抑。

驗證
class-dump導出的所有頭文件導入到sublime text中。搜索WCAccountLoginControlLogic類衷模,可見:

image.png

確定了我們要hook的方法鹊汛,接下來便是對以前的方法做交換了。

2阱冶、通過swizzle交換注冊方法刁憋。

//class_getInstanceMethod:得到類的實例方法。
//objc_getClass  參數(shù)是類名的字符串木蹬,返回的就是這個類的類對象
//object_getClass  參數(shù)是id類型至耻,它返回的是這個id的isa指針所指向的Class,如果傳參是Class镊叁,則返回該Class的metaClass尘颓。
+ (void)load{
    Method systemMethod = class_getInstanceMethod(objc_getClass("WCAccountLoginControlLogic"), NSSelectorFromString(@"onFirstViewRegester"));
    Method newMethod = class_getInstanceMethod(self, @selector(newAction));
    method_exchangeImplementations(systemMethod, newMethod);
}

//將注冊方法替換為下面的方法.
- (void)newAction{
    NSLog(@"");
}

四、竊取登錄時的密碼

我們需要在用戶點擊登錄時晦譬,獲取的用戶密碼泥耀,然后繼續(xù)微信的登錄流暢。
根據(jù)平時的正向開發(fā)經(jīng)驗蛔添,登錄流程大致為輸入賬號痰催、密碼,點擊登錄按鈕迎瞧,獲取密碼輸入框中的密碼夸溶,調(diào)用登錄方法。
所以凶硅,我們這里只需要獲取密碼輸入框的所屬類缝裁,然后再登錄按鈕綁定的Action里面完成hook

1足绅、分析并確定相關類及相關方法捷绑。

同破壞用戶注冊流程相似,先運行重簽代碼氢妈,進入登錄界面粹污,調(diào)出view debug界面。
選中登錄按鈕首量,得到其相關信息壮吩。


打印TargetAction:

(lldb) po 0x2805b0980
{
    className = WCAccountMainLoginViewController;
    memoryAddress = 0x10b8f6800;
}

(lldb) po 0x2805b0b40
{
    className = NSTaggedPointerString;
    memoryAddress = 0xafff44ac59128b09;
}

(lldb) po 0xafff44ac59128b09
onNext

可以確定的是微信登錄按鈕綁定的是WCAccountMainLoginViewController中的onNext方法进苍。我們可以繼續(xù)通過打印方法的調(diào)用來驗證我們的推斷是否正確。


通過SubLime查看這個類鸭叙,我們也可以找到onNext方法觉啊。同時我們也可以確定這個方法是沒有參數(shù)的。

推斷得出沈贝,密碼是通過控制器來拿的杠人,所以我們應當分析控制器的屬性。接著看頭文件

接著查看WCAccountTextFieldItem的相關信息:

發(fā)現(xiàn)頭文件沒有我們想要的東西宋下,繼續(xù)查看父類信息:

發(fā)現(xiàn)WCUITextField,和下圖我們通過view debug確定的密碼輸入框同屬一個類搜吧。

在微信密碼框輸入密碼,接著我們同樣輸入相關命令驗證自己的推斷杨凑。

(lldb) po 0x2805b0980
    <WCAccountMainLoginViewController: 0x2805b0980>
    (lldb) po [(WCAccountMainLoginViewController *)0x2805b0980 valueForKey:@"_textFieldUserPwdItem"]
    <WCAccountTextFieldItem: 0x282251a40>
    (lldb) po [(WCAccountTextFieldItem *)0x282251a40 valueForKey:@"m_textField"]
    <WCUITextField: 0x10d975200; baseClass = UITextField; frame = (20 0; 345 44); text = 'fasdafds'; opaque = NO; tintColor = UIExtendedSRGBColorSpace 0.00784314 0.733333 0 1; gestureRecognizers = <NSArray: 0x2809de250>; layer = <CALayer: 0x2806b12a0>>
    (lldb) po [[(WCAccountTextFieldItem *)0x282251a40 valueForKey:@"m_textField"] valueForKey:@"text"]
    fasdafds

以上滤奈,便可驗證我們推斷正確。接下來便可以編寫hook代碼撩满。

2蜒程、HOOK代碼編寫的幾種方式。

通過 exchange交換兩個方法的IMP指針伺帘。但是這樣破壞之后調(diào)用原有方法時會崩潰昭躺。因為兩個類的方法編號SEL并沒有改變,所以原有類中并不存在myAction這個方法伪嫁。

+ (void)load{
    Method loginOnNextMethod = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), NSSelectorFromString(@"onNext"));
    Method myLoginMethod = class_getInstanceMethod(self, NSSelectorFromString(@"myAction"));
    method_exchangeImplementations(loginOnNextMethod, myLoginMethod);
}

- (void)myAction{
    NSString * pwd = [[[self valueForKey:@"_textFieldUserPwdItem"]valueForKey :@"m_textField"] performSelector:NSSelectorFromString(@"text")];
    NSLog(@"pwd == %@",pwd);
    //破壞之后繼續(xù)原來的登錄操作领炫。
//    [self myAction];//這里要崩潰,因為WCAccountMainLoginViewController類里面找不到這個方法张咳。
}

針對以上崩潰問題帝洪。我們有以下三種方式解決;

  • 通過給原有類添加方法脚猾。
//MARK => 1-通過給原有類添加方法葱峡。
+ (void)load{
    Class loginClass = objc_getClass("WCAccountMainLoginViewController");
    Method loginOnNextMethod = class_getInstanceMethod(loginClass, NSSelectorFromString(@"onNext"));
    //給原有的登錄類添加一個方法編號,將imp指針指向當前類的函數(shù)龙助。
    BOOL isSuc = class_addMethod(loginClass,NSSelectorFromString(@"Dy_OnNexy"),myAction,"v@:");
    if (isSuc) {
        Method new_method = class_getInstanceMethod(loginClass, NSSelectorFromString(@"Dy_OnNexy"));
        method_exchangeImplementations(loginOnNextMethod, new_method);
    }
}

void myAction(id self,SEL _cmd){
    NSString * pwd = [[[self valueForKey:@"_textFieldUserPwdItem"]valueForKey :@"m_textField"] performSelector:NSSelectorFromString(@"text")];
    NSLog(@"pwd == %@",pwd);
    //破壞之后繼續(xù)原來的登錄操作砰奕。
    if ([self respondsToSelector:NSSelectorFromString(@"Dy_OnNexy")]) {
        [self performSelector:NSSelectorFromString(@"Dy_OnNexy")];
    }
}
  • 第一種方式稍顯麻煩。我們可以通過replace直接替換原有方法的IMP指針提鸟。但是這樣的缺點是如果原有方法找不到军援,replace的內(nèi)部會自動創(chuàng)建一個方法。
+ (void)load{
    Class loginClass = objc_getClass("WCAccountMainLoginViewController");
    //拿到原有的IMP称勋,并暫時保存胸哥。
    old_onNext = method_getImplementation(class_getInstanceMethod(loginClass, NSSelectorFromString(@"onNext")));
    //交換原有方法的IMP
    class_replaceMethod(loginClass, NSSelectorFromString(@"onNext"), myAction, "v@:");
}

IMP (*old_onNext)(id self,SEL _cmd);

void myAction(id self,SEL _cmd){
    NSString * pwd = [[[self valueForKey:@"_textFieldUserPwdItem"]valueForKey :@"m_textField"] performSelector:NSSelectorFromString(@"text")];
    NSLog(@"pwd == %@",pwd);
    old_onNext(self,_cmd);
}
  • 通過getImp拿到原有方法的Imp,并保存到自己定義的Imp指針中。再通過setImp給原有方法設置新的Imp指針铣缠。
+ (void)load{
    Class loginClass = objc_getClass("WCAccountMainLoginViewController");
    //1烘嘱、拿到原有的method
    Method oldMethod = class_getInstanceMethod(loginClass, NSSelectorFromString(@"onNext"));
    //2、拿到原有method對應的IMP
    old_onNext = method_getImplementation(oldMethod);
    //3蝗蛙、給原有的method設置新的IMP
    method_setImplementation(oldMethod, myAction);
}

IMP (*old_onNext)(id self,SEL _cmd);

void myAction(id self,SEL _cmd){
    NSString * pwd = [[[self valueForKey:@"_textFieldUserPwdItem"]valueForKey :@"m_textField"] performSelector:NSSelectorFromString(@"text")];
    NSLog(@"pwd == %@",pwd);

    old_onNext(self,_cmd);
}

參考鏈接

Type Encodings

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蝇庭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子捡硅,更是在濱河造成了極大的恐慌哮内,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壮韭,死亡現(xiàn)場離奇詭異北发,居然都是意外死亡,警方通過查閱死者的電腦和手機喷屋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門琳拨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人屯曹,你說我怎么就攤上這事狱庇。” “怎么了恶耽?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵密任,是天一觀的道長。 經(jīng)常有香客問我偷俭,道長浪讳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任涌萤,我火速辦了婚禮淹遵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘负溪。我一直安慰自己合呐,他們只是感情好,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布笙以。 她就那樣靜靜地躺著淌实,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猖腕。 梳的紋絲不亂的頭發(fā)上拆祈,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音倘感,去河邊找鬼放坏。 笑死,一個胖子當著我的面吹牛老玛,可吹牛的內(nèi)容都是我干的淤年。 我是一名探鬼主播钧敞,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼麸粮!你這毒婦竟也來了溉苛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤弄诲,失蹤者是張志新(化名)和其女友劉穎愚战,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體齐遵,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡寂玲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了梗摇。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拓哟。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖伶授,靈堂內(nèi)的尸體忽然破棺而出彰檬,到底是詐尸還是另有隱情,我是刑警寧澤谎砾,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布既忆,位于F島的核電站山上,受9級特大地震影響盒卸,放射性物質(zhì)發(fā)生泄漏搪缨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一挚币、第九天 我趴在偏房一處隱蔽的房頂上張望亮蒋。 院中可真熱鬧,春花似錦妆毕、人聲如沸慎玖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趁怔。三九已至,卻和暖如春薪前,著一層夾襖步出監(jiān)牢的瞬間润努,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工示括, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留铺浇,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓垛膝,卻偏偏與公主長得像鳍侣,于是被迫代替她去往敵國和親丁稀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容