2020年 IOS 逆向 反編譯 注入修改游戲或APP的調用參數新手系列教程——用bfinject脫殼、注入自己的動態framework、cycript的使用

開篇

本篇文章是繼上一篇文章:2020年 IOS 逆向 反編譯 注入修改游戲或APP的調用參數新手系列教程——按鍵精靈腳本來模擬合成燈籠后本繼續分享的教程,一天最多寫一篇了,有時候太懶了沉迷打游戲就沒寫了~

網上很多教程講了一大堆話,最終翻來翻去不知道是想實現什么功能和效果,我覺得一開始把需求&最終效果展示能讓讀者了解個大概和引起興趣,不會不知所以然。后面我會按這種文章思路來分享,先把結果呈現,再詳敘過程,我想是個不錯的分享思路??。

需求&最終效果

bfinject對正在運行的APP脫殼打包成.ipa

脫殼打包成.ipa文件

注入自己的動態framework

動態注入后的效果

cycript的使用

cycript的使用

環境要求與即將使用的工具

之前我的MacOSX版本是10.10,只能安裝xcode7以下的版本,xcode7以下的版本沒有真機調試功能,于是升級了版本到MacOSX Catalina 10.15.4也安裝了最新版xcode,但是這個版本太卡而且有些問題,很多軟件兼容不了了,想以后降級。

環境 版本
操作系統 MacOSX Catalina 10.15.4 版本太新了不太好用很多工具用不了,我后面打算降級
手機系統 Iphone7 IOS11 需要越獄
bfinject 最新版
手機助手傳輸工具或SSH連接操作 -
xcode 11.5
電腦上的cycript 最新版
手機終端工具比如terminal -
電腦工具class-dump用來導出頭文件查看 最新

工具介紹

bfinject是一款注入工具,安裝后坑挺多??梢宰⑷離code開發的framework,也可以注入ios10以前人們用的cycript工具,因為ios11已經不支持cycript的使用了,只能通過這個工具來執行cycript的全部命令,然后用電腦的cycript連接手機cycript提供出來的端口來操作。
電腦上的cycript安裝教程參考這篇文章:http://www.lxweimin.com/p/d93e9fccef4b,這玩意安裝后坑很多,一一填坑吧,而且官網打開好慢~。
cycript是一款動態注入工具,可以動態執行cy代碼,常用來打印ui界面和調試。
ios11的ssh本人用不了,從cydia安裝了openssh,但是用命令行執行ssh報無法打開二進制文件的英文錯誤,不知道為何,誰能在ios11運行ssh并且電腦連接手機ssh的麻煩告知我一下謝謝。

實現過程

bfinject對正在運行的APP脫殼打包成.ipa

安裝bfinject

首先電腦下載bfinject,然后用手機助手等工具把二進制文件bfinject拷貝到iphone手機的隨意位置下,我是放在/User/Media/目錄下。bfinject下載和安裝教程參考github。
這個bfinject的坑還是很多的安裝后執行會出現很多報錯~比如electra和bootstrap目錄問題的坑;還有md5: command not found的報錯,我的做法是把md5sum這個命令復制一個改成md5執行就不報錯,網上有填坑例子,遇到的可以看看。另外說明,這個bfinject的執行需要關閉Tweaks才能運行成功:打開越獄工具Electra,把Tweaks選項禁用,然后重新啟動。
這個bfinject的執行需要關閉Tweaks才能運行成功:打開越獄工具Electra,把Tweaks選項禁用,然后重新啟動。
這個bfinject的執行需要關閉Tweaks才能運行成功:打開越獄工具Electra,把Tweaks選項禁用,然后重新啟動。

手機使用bfinject

以下及下文所有手機命令都是用root用戶來操作。
打開terminal到/User/Media/目錄下執行:

bash bfinject -P test1.app -L test

上圖界面的app是我自己隨便寫的一個demo app ,安裝在了iphone里,我調試用的,這個app叫test1.app,這里拿來演示,-L test 是指調用bfinject內置的framework來注入,用來確定bfinject是否安裝成功和生效,成功界面如下:


運行

打開到app的結果

打包

接下來用這個命令來導出ipa

bash bfinject -P test1.app -L decrypt

回到app界面


脫殼打包成.ipa文件

打包完畢!我們選擇No它會把包存儲到App的文檔目錄。
我們把包找出來:

find /var/mobile/Containers/Data/Application/ -name decrypted-app.ipa
結果

其中某個decrypted-app.ipa就是我們打包出來的路徑了,把這個包/User/Media/目錄下,然后用電腦手機助手工具就能拿到啦。接下來就是提取頭文件了。

注入自己的動態framework

提取頭文件

class-dump安裝比較簡單我就不說了,是用來提取match-o格式文件的工具,可以把ios開發的app的頭文件導出來,就能知道app里面的類和方法、變量名。以此來注入指定方法。
電腦命令:

class-dump -H test1 -o test1Headers

test1是我把decrypted-app.ipa解壓后里面的match-o文件,test1Headers是指輸出所有頭文件到這個文件夾。

好了,我打開其中一個頭文件


頭文件

因為這個app是我自己寫的,我知道down是其中一個Button按鈕是點擊后輸出一個彈窗的功能,我就拿這個方法來演示注入把,就是實現點擊Button按鈕后再注入一個彈窗。當然其他app就要靠經驗分析啦,可以用hooper等反編譯工具分析。

編寫注入代碼

打開xcode,新建工程選擇IOS中的Framework & Library 中的Framework。
Product Name 等信息你們自己填,我的命名是snakeGameHacker
創建好工程目錄后,snakeGameHacker.h就是頭文件,我的這樣寫:


#import <UIKit/UIKit.h>

//! Project version number for snakeGameHacker.
FOUNDATION_EXPORT double snakeGameHackerVersionNumber;

//! Project version string for snakeGameHacker.
FOUNDATION_EXPORT const unsigned char snakeGameHackerVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import 
#import <HackerLoader.h>
#import <NSObject+Hacker.h>

然后再創建Cocoa Touch class 文件,HackerLoader,會自動生成HackerLoader.h和HackerLoader.m文件。
HackerLoader.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface HackerLoader : NSObject

@end

HackerLoader.m


#import "HackerLoader.h"
#import "NSObject+Hacker.h"
#import <objc/runtime.h>
@implementation HackerLoader
static void __attribute__((constructor)) entry(void) {
    NSLog(@">>>>> Code Injected 哈哈哈3哈<<<<<");  
    NSObject *obj = [[NSObject alloc] init];
    [obj hack];
}

@end

再創建objective-c File文件,類型選擇Category,名字Hacker
最終產生:NSObject+Hacker.h和NSObject+Hacker.m
NSObject+Hacker.h


#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface NSObject (Hacker)

- (void)hack;

@end

NSObject+Hacker.m
這就是我們的核心文件了

#import "NSObject+Hacker.h"
#import <objc/runtime.h>
@implementation NSObject (Hacker)

- (void)hack {
    NSLog(@">>>>> Code Injected powerby maimai <<<<<");
    NSString *className = @"ViewController";
    [self hookMethod:@"down" ofClass:className hookMethodName:@"down2"];
}

// 封裝方法掛載函數
- (void)hookMethod:(NSString *)oriMethodName ofClass:(NSString *)ClassName hookMethodName:(NSString *)hookMethodName   {
    
    NSLog(@"掛載方法。。。。");
    
           static dispatch_once_t onceToken;
       dispatch_once(&onceToken, ^{
           Class oriMethodClass = NSClassFromString(ClassName);

           Class class = [self class];

          
           SEL originalSelector = NSSelectorFromString([oriMethodName stringByAppendingString:@":"]);
           SEL swizzledSelector = NSSelectorFromString([hookMethodName stringByAppendingString:@":"]);
    
           Method originalMethod = class_getInstanceMethod(oriMethodClass, originalSelector);
           Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    
            BOOL didAddMethod = class_addMethod(oriMethodClass,originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));
    
           if (didAddMethod) {// 判斷是否已經有這個方法了
    
               class_replaceMethod(oriMethodClass,swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));
    
           } else {
    
               method_exchangeImplementations(originalMethod, swizzledMethod);
    
          }
       });
}



// 按鈕按下
- (void)down2:(id)sender{
    NSLog(@"----down2----weirui3----");
    [self showError:@"我在app的方法里注入自己的代碼啦!"];
    return [self down2:sender];
}


- (UIViewController *)_topViewController:(UIViewController *)vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [self _topViewController:[(UINavigationController *)vc topViewController]];
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        return [self _topViewController:[(UITabBarController *)vc selectedViewController]];
    } else {
        return vc;
    }
    return nil;
}


- (UIViewController *)topViewController {
    UIViewController *resultVC;
    resultVC = [self _topViewController:[[UIApplication sharedApplication].keyWindow rootViewController]];
    while (resultVC.presentedViewController) {
        resultVC = [self _topViewController:resultVC.presentedViewController];
    }
    return resultVC;
}



- (void)showError:(NSString *)errorMsg {
    UIViewController *uvc = [self topViewController];
    NSLog(@"----weirui3----當前vc%@", NSStringFromClass([uvc class]));
    // 1.彈框提醒
    // 初始化對話框
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:errorMsg preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil]];
    // 彈出對話框
    [uvc presentViewController:alert animated:true completion:nil];
    NSLog(@"uvc show");
}

@end

代碼講解

static void attribute((constructor)) entry(void) {}
這個方法會被進程注入的時候執行到這里。我們實例化一個NSObject執行NSObject+Hacker.m.hack()方法,hack方法里面有一段

NSString *className = @"ViewController";
    [self hookMethod:@"down" ofClass:className hookMethodName:@"down2"];
    

hookMethod是我封裝的函數調用hook方法,是利用OC語言中swizzledMethod實現方法替換和注入,theos 中tweak的%orig原理就是用了swizzledMethod實現hook。后面我會分享tweak注入的教程,我覺得比bfinject穩定靠譜。
意思是ViewController類下面的down()方法掛載一個我們指定的方法down2()
接下來我們編寫down2方法。

// 按鈕按下
- (void)down2:(id)sender{
    NSLog(@"----down2----weirui3----");
    [self showError:@"我在app的方法里注入自己的代碼啦!"];
    return [self down2:sender];
}

攔截了down的執行,插入了一段代碼 [self showError:@"我在app的方法里注入自己的代碼啦!"];
就是彈窗代碼,在本頁面彈窗的實現,具體你們自己看彈窗實現代碼吧,這個網上很多類似代碼。然后再 return [self down2:sender];
就是真正的%orig那段代碼了,看似是遞歸調用,實際不會。

編譯

我們先測試一下報錯沒有吧。如果要用單例測試要讓編譯目標 改為 iOS Simulators,我選ios8,然后按command+U,運行,證實不報錯跑通到
hack()方法里面:


單例測試

當然down2方法是不會被執行的,因為down2是動態執行,需要利用bfinject注入后啟動對應app觸發down那個方法才會被執行。
我們編譯代碼。
注意,編譯目標 切換為Generic iOS Device。
注意,編譯目標 切換為Generic iOS Device
注意,編譯目標 切換為Generic iOS Device
注意,編譯目標 切換為Generic iOS Device
其他證書相關配置改為None,目標版本改為你手機能執行的版本,等一些手續。
然后按下Command+B編譯。
Products/目錄下產生snakeGameHacker.framework目錄,用finder打開進入找到里面的snakeGameHacker的 Unix可執行文件,就是我們注入的對象了。

注入

把snakeGameHacker上傳到手機目錄。
手機里執行

bash bfinject -P test1.app -l snakeGameHacker

注意這里的 -l 和上面不同,這里的是小寫的。
執行后回到app按一下Button按鈕(down方法的執行觸發)
結果注入成功:


動態注入后的效果

至此,framework注入講解完畢。

cycript的使用

手機執行:

bash bfinject -P test1.app -L cycript
cycript的使用

然后電腦打開終端,輸入對應地址:

cycript -r 192.168.0.101:1337

不過我經常連接好久或失敗,感覺不好用。多試幾次才能成功。
本來想寫幾個命令的,現在連接不上,算了~

結束

此教程僅做學習交流和知識記錄方便以后查看使用,如果涉及到利益相關的請告知本人進行刪帖處理。

本人想通過這些博客記錄自己這兩周內折騰的過程以及分享最后成功的成果。另外想結交志同道合對IT行業感興趣的盆友,互相交流學習。可以通過博客聯系我或加QQ號:1321691245

今天就先寫到這,后面我再把我學習的其他相關知識分享給大家。下一篇就介紹theos 中編寫tweak實現修改游戲數據的文章吧。

博文主索引目錄入口

我會把這系列的文章更新到這個入口里面,分享我的心得,大家互相學習。
2020年 IOS 逆向 反編譯 注入修改游戲或APP的調用參數新手系列教程主目錄入口

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,412評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,514評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,373評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,975評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,743評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,199評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,262評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,414評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,951評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,780評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,527評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,218評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,649評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,889評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,673評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374