iOS逆向(4)-代碼注入,非越獄竊取微信密碼

利用LLDB對微信進行分析,而後利用分析的結果,再逐步講解如何Hook微信的登陸過程,截獲微信密碼。ios

在上一篇文章(APP重簽名)中,已經介紹瞭如何對APP重簽名,而且利用XCode將微信跑起來,既然到了這一步,就萬萬不能錯過強大的LLDB。這篇文章就講爲你們講解到如何利用LLDB對微信進行分析,而後利用分析的結果,再逐步講解如何Hook微信的登陸過程,截獲微信密碼。git

老規矩,片頭先給福利:點擊下載Demo:HookWeChat,此次有兩份代碼。因爲越獄版微信體積太大,受到github限制,因此並無將它傳到github,能夠在下方連接單獨下載github

文中所須要用到的工具和文件:
越獄版本微信7.0.2 提取碼: 2w87
MachOView 提取碼: n3hy
yololib 提取碼:e8qs
class-dump 提取碼:v5ku安全

接下來咱們會從一下幾部,讓微信脫下看似安全的外衣,裸露在你們面前。bash

  • Framework的做用
  • 初探MachO (原理分析)
  • 代碼注入 (代碼過程)
  • ViewDebug、LLDB、class-dump分析微信登陸頁面(原理分析)
  • Hook登陸,自動獲取密碼 (代碼過程)
  • 總結

一、Framework的做用(對Framework熟悉的同窗能夠跳過這一步)

什麼是Framework這裏就很少加敘述,我參考這個網站,很是詳細,看不懂你直接@我。點這裏:Framework最強講解微信

廢話很少說,接下來直接演示如何建立一個Framework,而且介紹跟我們Hook微信有關的基礎原理。架構

新建一個工程FrameworkDemo,新建一個Framework,取名FYHook app

建立Framework(1).png

建立Framework(2).png

在新建出來的FYHook文件夾中新建InjectCode(繼承NSObject)對象,而且新建代碼:工具

+ (void)load {
    NSLog(@"來了,老弟😁");
}
複製代碼

新建InjectCode.png

直接運行,會發現來了,老弟😁被輸出,證實用這種方法新建的Framework可以直接運行在咱們的項目中。 網站

NSLog字符串.png

二、初探MachO (若是不想看原理,能夠直接跳到第三部 代碼注入)

根據上篇文章APP重簽名講到的,咱們可使用XCode將微信跑起來,那麼是否是將二者結合起來,就能夠將咱們的代碼注入進微信的APP呢?

Step 1 先思考一個問題。

根據APP重簽名中的結論,利用腳本能夠便捷重籤APP(由於咱們用的WeChat舉例,因此下面簡稱WeChat),那麼咱們在重籤腳本的工程中,直接建立一個Framework,能不能讓咱們Framework中的代碼在WeChat中運行?

很顯然,這是不行的(有興趣的能夠試一下)!爲何? 這個問題下面會回答,先把這個問題記在心中。

Step 2 MachO做用

在咱們用XCode新建HYHook的時候,其實XCode幫咱們作了一部操做:建立HYHook時候,同時將HYHook連接到咱們的項目中(這是後期的XCode新增功能,早年的XCode這一步是須要咱們直接作的)

XCode自動連接.png
common+ b Build一下,會發如今已經Build出來的文件中的Frameworks下已經有FYHook了,已經已經代表FYHook被Copy咱們的ipa文件了。(如何看Build出來的文件?查看: APP重簽名中Step 8 App重簽名)
自動加入Frameworks已經MachO文件.png
可是FYHook在ipa文件中,並不表明着FYHook就能夠被咱們的可執行文件所執行,由於FYHook並無沒導報入咱們的可執行文件,只有在這個可行執行文件的 某一個地方作好標記,告知可執行文件,在適當的時候須要加載外部的FYHook,纔可以正常運行。

而這個地方所說的可執行文件就是MachO文件(具體什麼是MachO,這不是本片文章的重點內容,能夠持續關注筆者以後的文章,下一章詳細介紹這相當重要的MachO),咱們能夠利用工具MachOView來查看MachO中到底有什麼內容。

Step 3 MachOView

MachOView.png
點擊這裏下載: MachOView 提取碼: n3hy

用MachOView打開FrameworkDemo的MachO,能夠看到以下圖

查看MachO.png

能夠看到其中的有個Load Commons組,這裏面就包括全部須要被動態加載的庫。也就是說,若是在Load Commons中沒有對應的FYHook,就不會加載FYHook。

在上圖中能夠看到FYHook已經被加入了Load Commons,而且圖右側也標記了FYHook所屬的目錄(和MachO文件同級的Frameworks下FYHook.framework中 ,FYHook.framework實際上是個文件夾,裏面的FYHook也是個MachO

因此這裏就獲得了「爲何咱們直接將FYHook加入咱們的從重籤腳本工程,不能直接運行FYHook」的答案。 由於在在咱們Build出來的MachO文件中的Load Commons中沒有加入FYHook的路徑。因此沒法運行FYHook中的代碼。

那麼咱們直接將FYHook加入咱們Build出的MachO文件行嗎? 顯然也是不行的,由於咱們Build出的MachO文件始終會被原始包(WeChat)中的MachO給替換掉。咱們須要將FYHook加入原始包(WeChat)中的MachO中。

Step 4 將FYHook標記入MachO中

這裏咱們就須要用到終端命令行工具:yololib 提取碼:e8qs

將下載下來的yololib.zip解壓後獲得的yololib放在‎⁨目錄/usr⁩/local⁩/bin⁩下,這樣咱們在終端中就可使用yololib命令了

yololib.png

如下命令就是將FYHook注入WeChat的命令

// yololib 「MachO路徑」 「FYHook相對MachO的路徑」
yololib WeChat Frameworks/FYHook.framework/FYHook
複製代碼

三、代碼注入

Step 1 創建重籤腳本工程

新建工程,取名InjectFrameWork,過程可參照上一篇文章(APP重簽名) 最後獲得以下工程:

重籤工程.png

Step 2 建立Framework文件

新建一個Framework文件,取名FYHook,在FYHook中新建文件InjectCode,在InjectCode加入以前提到的一樣的load代碼, 等到以下工程:

建立Framework(3).png

Step 3 修改源文件的MachO文件

找到WeChat的MachO文件,打開終端,進入此目錄下 執行命令

// yololib 「MachO路徑」 「FYHook相對MachO的路徑」
yololib WeChat Frameworks/FYHook.framework/FYHook
複製代碼

yololib注入成功.png

Step 4 從新打包WeChat.ipa

zip -ry WeChat.ipa Payload
複製代碼

從新打包WeChat.ipa.png

Step 5 加入新的WeChat.ipa,運行工程

將新獲得的WeChat.ipa從新加入APP文件(這一步其實能夠只加入文件,而不用加入工程),刪除原來的Wechat7.0.2越獄.ipa。

新WeChat.ipa.png
新WeChat.ipa-2.png

common + R運行代碼,會發現微信跑起來了,咱們的來了,老弟😁也被輸出了!

Step 6 新的思考

以前分析了咱們建立了FYHook,可是沒有對MachO注入,獲得的答案是來了,老弟😁不能被輸出,WeChat能跑起來。
那麼若是咱們對MachO注入FYHook,卻沒有建立對應的FYHook.framework,會怎麼樣呢?
這就留給你們思考,再去驗證了,有答案的同窗也能下方留言,並說出緣由哦。

四、 ViewDebug、LLDB、class-dump分析微信登陸頁面

Step 1 ViewDebug

XCode跑起微信以後,跳轉到登陸頁面,利用ViewDebug查看具體的詳細的UI

ViewDebug.png
能夠看到,登陸按鈕是一個FixTitleColorButton對象,他的Target的名字存在地址0x280afaa40中,他的Action名字存在地址0x280afac00中。 用一樣的方法查看帳號密碼的輸入框,會發現他們都屬於一個對象,叫作WCUITextField
帳號輸入框WCUITextField.png

Step 2 LLDB

利用LLDB查看登陸按鈕具體的Target和Action名稱

LLDB查看Target和Action.png
得知: 登陸按鈕處於WCAccountMainLoginViewController這個頁面之中 登陸按鈕的點擊方法叫作onNext

Step 3 class-dump

class-dump,是能夠把Objective-C運行時的聲明的信息導出來的工具。其實就是能夠導出.h文件。用class-dump能夠把未經加密的app的頭文件導出來。

點擊這下載命令行工具:class-dump 提取碼:v5ku 一樣的,將class-dump拷貝到Mac的目錄/usr⁩/local⁩/bin⁩下,這樣咱們在終端中就可使用yololib命令了

class-dump目錄.png

運行命令將WeChat全部的頭文件導出來。

// class-dump -H 「app的MachO文件」 -o 「輸入的目錄」
class-dump -H WeChat -o /Users/dengbin/Code/GitHub/HookWeChat/InjectFrameWork/APP/WeChat-H
複製代碼

class-dump.png
WeChat-H.png

Step 4 找到輸入框裏面的內容

利用文本工具,例如Sublime查看WeChat的頭文件,找到前面發現的WCAccountMainLoginViewController

WCAccountMainLoginViewController.png

發現裏面確實有方法- (void)onNext;,還有長得很像帳號輸入框,密碼輸入框的對象_textFieldUserNameItem,_textFieldUserPwdItem

接下來就是找到密碼輸入框裏面的字符串了,能夠發現這兩個都是WCAccountTextFieldItem對象,全部咱們繼續在導出的文件裏面找到WCAccountTextFieldItem

WCAccountTextFieldItem.png

在其中只發現一個tips對象m_labelTip,沒有發現對應的textfiled,可是能夠看到WCAccountTextFieldItem是繼承於WCBaseTextFieldItem的,因此繼續查找WCBaseTextFieldItem

WCBaseTextFieldItem.png

從這就能夠看到一個m_textField對象,這是個WCUITextField對象,疑似咱們的目標textField,繼續查看WCUITextField

WCUITextField.png

果真,這就是一個UITextField文件,那麼咱們就能夠經過text字段取出其string。

接下來在用LLDB試試看,驗證下咱們的猜測:
隨便在帳號欄輸入:qwerty
而後在密碼欄輸入:123456

po [(WCAccountMainLoginViewController *)0x1128bbc00 valueForKey:@"_textFieldUserPwdItem"]
po [(WCAccountTextFieldItem *)0x28328e880 valueForKey:@"m_textField"]
po [(WCUITextField *)0x112163a00 text]
複製代碼

其中第一個地址0x1128bbc00是在前兩部利用ViewDubg找到的。

找到輸入的密碼.png

能夠發現最後確實找到了咱們輸入的密碼123456,證實咱們的分析是正確的。

五、Hook登陸,自動獲取密碼

接下來又是代碼Coding了。原理分析完,其實代碼就很簡單了,直接上代碼:

+ (void)load {
    NSLog(@"來了,老弟😁");
    Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), sel_registerName("onNext"));
    //1.保存原始的IMP
    old_onNext = method_getImplementation(onNext);
    //2.SET
    method_setImplementation(onNext, (IMP)my_next);
}

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

void my_next(id self,SEL _cmd){
    // 獲取密碼
    NSString *pwd = [[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"] performSelector:@selector(text)];
    NSString *accountTF = [[[self valueForKey:@"_textFieldUserNameItem"] valueForKey:@"m_textField"] performSelector:@selector(text)];
    NSLog(@"密碼是!%@",pwd);
    // 將密碼追加在帳號欄的後面
    [[[self valueForKey:@"_textFieldUserNameItem"] valueForKey:@"m_textField"] performSelector:@selector(setText:) withObject:[NSString stringWithFormat:@"%@+%@",accountTF,pwd]];
    //調用原來的方法
    old_onNext(self,_cmd);
}
複製代碼

稍微解釋一下,在前面咱們發現登陸的響聲事件是onNext,全部咱們利用Objective-C的Runtime特性,對onNext進行方法替換,在響應原有的onNext以前,咱們加上咱們本身的方法,好比代碼中的,在帳號欄中直接輸入密碼。
運行後結果如圖:

運行結果.PNG

我這用的是setIMP和getIMP的方式,對原方法進行HOOK,其實方法有多種:如:class_replaceMethod(),method_exchangeImplementations(),這裏只是舉一個例子供你們參考。

這篇文章的全部代碼均可以在這下載到:HookWeChat

六、總結:

  • 先對APP重簽名,讓APP能在XCode運行起來
  • 利用yololib注入Framework,讓APP能夠運行咱們直接的代碼
  • 利用ViewDebug、LLDB、class-dump分析登陸事件和密碼框所在位置
  • 利用Runtime的MethodSwizzle,Hook登陸事件

此次只是簡單的微信的一個靜態頁面進行了初步接觸,雖然思路簡單,但這運用到的工具,倒是無數大神前輩們爲咱們鋪好的路,感謝!

MachO文件在本文中只是初略的說起,其實在咱們逆向過程當中MachO是一個相當重要的存在,如:

  • 對app的砸殼,其實就是對MachO解密
  • 全部的方法名,靜態字符串都是存在MachO中
  • app的架構(arm64,arm7...)也是在MachO中區分的
  • app加載其實也是對MachO的一步步操做
  • ...

因此,在下篇文章,筆者將會對MachO文件進行詳細的講解。請持續關注,以爲有幫助的點個收藏,留言評估了哦。

相關文章
相關標籤/搜索