iOS逆向(8)-Monkey、Logos

因爲最近微信大佬發飆,罰了紅包外掛5000萬大洋,這就讓人很慌了,別說罰我5000萬,5000塊我都吃不消。因此筆者決定之後不用微信作例子了。換成優酷了😈。php

本文會對優酷的設置頁面增長一個開啓/關閉屏蔽廣告的Cell(僅UI)。效果可見下文配圖。git

在以前的幾篇文章裏已經介紹了APP重簽名代碼注入Hook原理,能夠發現,將工程建好,腳本寫好,咱們就能夠以代價很是小的方式對一個第三方的APP進行分析。 那麼是否一種工具,能夠將重簽名,代碼注入,Hook源代碼,class-dump,Cydia Substrate,甚至是恢復符號表這些功能,集成在一個工程裏面,讓真正的逆向小白也能享受逆向的樂趣呢?
答案是確定的,Monkey就是這樣的一個非越獄插件開發集成神器!github

老規矩,片頭先上福利:點擊下載demo。 這篇文章會用到的工具備:xcode

1、Monkey

什麼是Monkey? 原有iOSOpenDev的升級,非越獄插件開發集成神器!bash

可使用Xcode開發CaptainHook Tweak、Logos Tweak 和 Command-line Tool,在越獄機器開發插件,這是原來iOSOpenDev功能的遷移和改進。微信

  • 只需拖入一個砸殼應用,自動集成class-dump、restore-symbol、* Reveal、Cycript和注入的動態庫並重簽名安裝到非越獄機器。
  • 支持調試本身編寫的動態庫和第三方App
  • 支持經過CocoaPods第三方應用集成SDK以及非越獄插件,簡單來講就是經過CocoaPods搭建了一個非越獄插件商店。
環境要求

使用工具前確保以下幾點:架構

sudo git clone --recursive https://github.com/theos/theos.git /opt/theos
複製代碼
  • 安裝ldid(如安裝theos過程安裝了ldid,跳過)
brew install ldid
複製代碼
安裝

你能夠經過如下命令選擇指定的Xcode進行安裝:app

sudo xcode-select -s /Applications/Xcode-beta.app
複製代碼

默認安裝的Xcode爲:框架

xcode-select -p
複製代碼

執行安裝命令:curl

sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-install)"
複製代碼
卸載
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-uninstall)"
複製代碼
更新

若是沒有發佈特殊說明,使用以下命令更新便可:

sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-update)"
複製代碼

安裝/更新以後重啓下Xcode再新建項目。若是看到以下選項,即表明安裝成功,若是沒有,重複上面步驟再來一遍。

MonkeyDev

具體使用方法能夠直接查看官網,固然下文也會對其部分的實用用法進行介紹。

2、Logos

Logos是Thoes開發的一套組件,可很是方便用於的Hook OC代碼。

接下來咱們就介紹下Logos的簡單用法,最後運用Monkey和Logos給優酷增長一點UI。

一、建立一個簡單的工程

建立工程SimpleAppDemo,裏面只有一個按鈕,點擊按鈕彈出一個Alert。 點擊下載:SimpleAppDemo 按鈕對應的方法爲:

- (IBAction)tapAction:(id)sender {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"來啦" message:@"老弟😁😁😁" delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil, nil];
    [alert show];
}
複製代碼

二、砸殼

對SimpleAppDemo參數的ipa文件進行砸殼,砸殼過程就不在這詳細描述了,這裏有筆者已經砸殼好的ipa:SimpleAppDemo.ipa 提取碼: afnc

三、新建一個Monkey工程

取名LogosDemo,將下面下載好的SimpleAppDemo.ipa,放到工程對應的目錄下:

ipa地址

配好證書(隨意一個能在手機上運行的證書便可),Run。運行成功~

四、玩轉Logos

在上一步建好的Monkey工程中,能夠發如今目錄有一個Logos目錄:

Logos目錄

默認有兩個文件LogosDemoDylib.xmLogosDemoDylib.mm
其中Logos語句就是寫在LogosDemoDylib.xm中的,LogosDemoDylib.mm是根據LogosDemoDylib.xm中的內容自動生成的。
接下來,我們根據幾個需求來介紹Logos的一些經常使用的用法。

  • 更改點擊按鈕的彈框內容(hook) 因爲須要更改彈窗,因此首先導入UIKit框架。
#import <UIKit/UIKit.h>
複製代碼

因爲我們手上有源碼,因此能夠直接跳過動態分析的這一步,直接就知道按鈕所處的頁面是叫作ViewController,按鈕的響應方法是:

- (IBAction)tapAction:(id)sender
複製代碼

利用hook命令:

#import <UIKit/UIKit.h>

// hook + 類名
%hook ViewController
// IBAction == void
- (void)tapAction:(id)sender {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"來什麼來" message:@"😡😡😡" delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil, nil];
    [alert show];
}

%end
複製代碼

運行項目,發現按鈕已經被成功hook了。

😡😡😡

  • 調用原方法(orig)
#import <UIKit/UIKit.h>

%hook ViewController

- (void)tapAction:(id)sender {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"來什麼來" message:@"😡😡😡" delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil, nil];
    [alert show];
    // 調用原方法
    %orig;
}

%end
複製代碼
  • 新增一個方法,而且調用(new) 因爲在Monkey工程裏面是編譯不到源碼的,因此不管是新增的方法,仍是調用原工程中的方法,都是沒法經過編譯的,因此都須要使用interface申明每個方法。
#import <UIKit/UIKit.h>

// 這裏只是爲了申明
@interface ViewController

- (void)newFunC;

@end

%hook ViewController

// 新增方法關鍵字new
%new
- (void)newFunC{
    NSLog(@"newFunC");
}

// IBAction == void
- (void)tapAction:(id)sender {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"來什麼來" message:@"😡😡😡" delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil, nil];
    [alert show];
    [self newFunC];
    // 調用原方法關鍵字orig
    %orig;
}

%end
複製代碼

文中全部的Demo都在這能夠下載到:Dmoe

Logos除了以上hook,end,orig,new這幾種關鍵字,還有:
%subclass:增長一個類
%log:打印,相似NSLog
%group: 給代碼分組,能夠用於在不一樣環境加載不一樣的代碼,好比iOS8加載group1,iOS9加載group2,若是部分中,默認全部代碼在名爲「_ungrouped」的隱藏分組中。
...

全部的Logos語法均可以在官方文檔中查詢獲得。

五、給優酷加UI

首先在這裏下載筆者本身砸殼後優酷ipa包(arm64架構的):優酷(砸殼).ipa 提取碼: xtua

Step 一、新建工程YouKu

一樣的新建一個Monkey工程,取名YouKu,將下載好的ipa包放入工程對應的TargetApp目錄下。Run。一樣是重簽名成功。

在上面的Demo中,咱們是對咱們直接的工程進行HOOK,因爲咱們手上有源碼,因此咱們越過了最難的一個步驟:動態分析。
而咱們如今要對優酷進行Hook,但咱們手上是沒有優酷的源碼的,因此此時此刻就須要對其進行動態分析了。 下面我將結合Xcode和class dump對優酷的設置頁面簡單的進行分析。

Step 二、class dump

class-dump is a command-line utility for examining the Objective-C segment of Mach-O files. It generates declarations for the classes, categories and protocols. This is the same information provided by using 'otool -ov', but presented as normal Objective-C declarations.
簡單說就是一個能夠導出一個MachO文件的全部頭文件信息(包括Extension)

在文首有提到Monkey除了重簽名,還集成了class dump的功能,因此咱們須要作的就僅僅是開啓這個功能:

開啓class dump

Run!成功以後能夠發如今工程目錄下多了一個文件夾Youkui4Phone_Headers,其中就是優酷的全部的頭文件了。

Youkui4Phone_Headers

Step 三、分析優酷設置頁面

工程Run成功後,點擊進入設置頁面(不用登陸),以下圖:

優酷設置

咱們如今要作的就是在這個頁面的TableView的最後一行加上Cell,裏面有個Switch,用於打開/關閉屏蔽廣告功能(只是UI,這篇文章不牽扯到屏蔽廣告的具體實現,若是你須要,點個當心心,持續關注我哦😀😀😀)。

利用偉大的Xcode咱們能夠很是清晰的看到,設置頁面的DataSourceDelegate都是在SettingViewController中,

SettingViewController

我們就找到Hook的類名:SettingViewController 須要Hook的方法天然就是TableView的那些DataSourceDelegate了。

這裏須要額外提到的一點是,在文章開始的時候就說了Monkey已經將Cydia Substrate集成進去了,因此咱們能夠直接使用Cydia Substrate的相關功能了。

在這裏咱們須要拿到這個頁面TableView的對應的變量,咱們就須要使用到Cydia Substrate的功能了。打開上文中獲取到優酷的全部的頭文件,全部SettingViewController,發現其只有一個TableView變量:_tabview
那麼毫無疑問,就是他了!
而獲取它的方法是:

MSHookIvar <UITableView *>(self,"_tabview")
複製代碼

一個reloadData的簡單使用:

[MSHookIvar <UITableView *>(self,"_tabview") reloadData];
複製代碼

其餘的UI代碼在這裏就不一一解釋了,所有代碼以下,固然在Demo中也是有的,其中包括了數據的簡單持久化功能:

#import <UIKit/UIKit.h>
#define FYDefaults [NSUserDefaults standardUserDefaults]
#define FYSwitchUserDefaultsKey @"FYSwitchUserDefaultsKey"

@interface SettingViewController
- (long long)numberOfSectionsInTableView:(id)arg1;
@end

%hook SettingViewController

%new
-(void)switchChangeAction:(UISwitch *)switchView{
    [FYDefaults setBool:switchView.isOn forKey:FYSwitchUserDefaultsKey];
    [FYDefaults synchronize];
    [MSHookIvar <UITableView *>(self,"_tabview") reloadData];
}

//多少組
- (long long)numberOfSectionsInTableView:(id)arg1{
    UITableView * tableView = MSHookIvar <UITableView *>(self,"_tabview");
    NSLog(@"fy_numberOfSectionsInTableView:");
    // 額外增長一個
    return %orig+1;
}

//每組多少行
- (long long)tableView:(UITableView *)tableView numberOfRowsInSection:(long long)section{
    NSLog(@"fy_numberOfRowsInSection:");
    //定位設置界面,而且是最後一個
    if(section == [self numberOfSectionsInTableView:tableView]-1){
        return 1;
    }
    else{
        return %orig;
    }
}

//返回高度
- (double)tableView:
(UITableView *)tableView heightForRowAtIndexPath:(id)indexPath{
    NSLog(@"fy_heightForRowAtIndexPath:");
    //定位設置界面,而且是最後一個
    if([indexPath section] ==[self numberOfSectionsInTableView:tableView]-1){
        return 44;
    }
    else{
        return %orig;
    }
}


//每個Cell
- (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(id)indexPath{
    NSLog(@"fy_cellForRowAtIndexPath:");
    //定位設置界面,而且是最後一組
    if([indexPath section] == [self numberOfSectionsInTableView:tableView]-1){
        UITableViewCell * cell = nil;
        if([indexPath row] == 0){
            static NSString *swCell = @"SwCellIdentifier";
            cell = [tableView dequeueReusableCellWithIdentifier:swCell];
            if(!cell){
                cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:nil];
            }
            cell.textLabel.text = @"免廣告";
            // 免廣告開關
            UISwitch *switchView = [[UISwitch alloc] init];
            switchView.on = [FYDefaults boolForKey:FYSwitchUserDefaultsKey];
            [switchView addTarget:self action:@selector(switchChangeAction:) forControlEvents:(UIControlEventValueChanged)];
            cell.accessoryView = switchView;
            cell.imageView.image = [UIImage imageNamed:([FYDefaults boolForKey:FYSwitchUserDefaultsKey] == 1) ? @"unlocked" : @"locked"];
        }
        cell.backgroundColor = [UIColor whiteColor];
        return cell;
        
    }else{
        return %orig;
    }
}

%end

複製代碼

最後的效果

最後的效果

六、爲何Monkey這麼牛逼

查看從新編譯後的app文件,能夠發現其中的Framework多了不少東西:

Framework
從這能夠得知,原來Monkey其實也是經過將諸多的動態庫(包括本身的工程)注入的形式,實現了這些功能。

3、總結

在這片文章中主要介紹了Monkey的一些用法已經Logos的基本語法。而在上一篇其實留了一個小尾巴,就是Cycript,筆者將要在下一篇文章中重點講解Cycript的安裝,基礎用法和高級用法。之因此放在下一篇,是由於Cycript配合Monkey將會有事半功倍的效果。

相關文章
相關標籤/搜索