iOS逆向學習之七(命令行工具開發)

命令行工具開發

在逆向過程當中,咱們使用了不少快捷工具,例如***Clutch***、class-dump等等,這些工具都是在終端執行。而這些工具的本質其實就是Mach-O類型的可執行文件,若是想要開發屬於咱們本身的命令行工具,應該怎麼作呢?xcode

建立命令行項目

在iOS開發中。咱們編譯一個項目,在生成的.app包中就能找到項目的可執行文件,經過這種方式生成的可執行文件能夠直接運行在iPhone上。因此,若是咱們要本身開發命令行工具,而且能在iPhone上使用,最簡單的方式就是使用xcode建立iOS項目。bash

  • 建立iOS項目,刪除項目中多餘的文件,僅保留***info.plist***和***main.m***文件,而且去掉***main.m***文件中的***UIApplication***相關方法

  • 編譯項目,在***Products/.app***中能夠找到生成的可執行文件
  • 將可執行文件經過iFunBox拷貝到iPhone的/usr/bin目錄下。
  • 鏈接iPhone,在命令行輸入工具名,就可以使用剛剛建立的命令行工具

獲取可執行文件的架構

給定一個iPhone上的可執行文件路徑,利用咱們本身開發的命令行工具,讀取可執行文件,而且判斷出可執行文件包含的架構類型,並打印。微信

  • 在完成需求以前,咱們首先要了解Mach-O文件的內部構造,使用MachOView工具,查看Mach-O文件的內部構造

能夠發現,Mach-O文件的頭部Header裏,第一行就表示當前Mach-O文件是胖二進制文件,也叫作通用二進制文件。而第二行則表示當前Mach-O文件包含哪幾種架構。因此咱們想要判斷當前的Mach-O文件是何種類型,只須要讀取Mach-O文件的前四個字節的數據進行判斷便可。

  • 根據什麼條件來判斷Mach-O文件屬於哪一種架構類型?經過查看xnu源碼,在EXTERNAL_HEADERS/mach-o/fat.hEXTERNAL_HEADERS/mach-o/loader.h文件中能夠發現對應幾種經常使用架構類型的定義

上圖中FAT_MAGICFAT_CIGAM表明通用二進制文件類型,經過如下結構體能夠看出FAT_MAGICFAT_CIGAMuint32_t類型架構

上圖是loader.h中定義的文件類型,其中MH_MAGICMH_CIGAM表明非64位的架構類型,也就是armv7或者armv7s類型的架構,MH_MAGIC_64MH_CIGAM_64表明64位類型的架構,也就是arm64架構app

經過查看源碼能夠發現一個問題,上圖類型定義都有兩種,並且對應的值徹底相反。其實這就是大小端模式:
大端模式:數據的高字節保存到內存的低地址中,數據的低字節保存到內存的高地址中。
小端模式:數據的高字節保存到內存的高地址中,數據的低字節保存到內存的低地址中。
這就致使在讀取數據的時候能夠從高地址向低地址讀取,也能夠從低地址向高地址讀取,因此就存在上圖兩種定義工具

  • 拿到了具體架構的定義,咱們就能夠拿到咱們所讀取到的Mach-O文件的前四個字節,與以上定義作對比,就能夠判斷當前Mach-O文件的具體架構模式ui

  • 首先建立命令行項目,去除多餘文件以後,在***main.m***中添加以下代碼spa

#import <UIKit/UIKit.h>
#import <mach-o/loader.h>
#import <mach-o/fat.h>

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSString *path = @"/var/mobile/Containers/Bundle/Application/048B71C8-42E4-4EE0-8E50-EF262251DE17/WeChat.app/WeChat";
        NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
        NSUInteger len = sizeof(uint32_t);
        //讀取uint32_t長度的字節數
        NSData *data = [fileHandle readDataOfLength:len];
        //將data數據存放到magicNumber中
        uint32_t magicNumber;
        [data getBytes:&magicNumber length:len];

        if (magicNumber == FAT_MAGIC || magicNumber == FAT_CIGAM) {
            printf("Universal Binary\n");
        }else if (magicNumber == MH_MAGIC_64 || magicNumber == MH_CIGAM_64){
            printf("64bit Binary\n");
        }else if (magicNumber == MH_MAGIC || magicNumber == MH_CIGAM){
            printf("32bit Binary\n");
        }else{
            printf("讀取失敗\n");
        }
        
        printf("magicNumber = 0x%x\n", magicNumber);
        
        [fileHandle closeFile];
        return 0;
    }
}
複製代碼
  • Products/.app中找到可執行文件,複製到iPhone的/usr/bin/目錄下,而後鏈接iPhone,進入終端,執行TestCommand(這裏是你的可執行文件的名稱),這時候會發現無執行權限==permission denied==,解決方式就是爲咱們的可執行文件增長可執行權限
chmod +x /usr/bin/TestCommand
複製代碼

增長完可執行權限以後,再次執行此命令,會在終端打印出如下信息命令行

508SC:~ root# TestCommand
64bit Binary
magicNumber = 0xfeedfacf
508SC:~ root#
複製代碼

能夠看出微信App的可執行文件是arm64架構的code

爲命令行工具增長權限

以前寫的命令行工具能夠獲取到指定了路徑的可執行文件的架構類型,可是這種方式不穩定,在大多數狀況下會獲取失敗。緣由是咱們沒有爲命令行工具增長足夠的權限。那麼如何爲可執行文件增長權限呢?

簽名工具ldid的使用

以前在安裝Theos的時候咱們安裝了ldid工具,能夠直接在命令行輸入==ldid==就能夠查看==ldid==的具體用法

  • ldid -e MobileSafari表示導出可執行文件的權限信息到指定的文件中
ldid -e TestCommand > TestCommand.entitlements
複製代碼

在iOS中,權限信息通常存放到entitlements文件中

  • 在==TestCommand.entitlements==文件中增長相應的權限
get-task-allow :YES
複製代碼

若是想要更多權限,能夠找一個具備不少權限的可執行文件,導出它的權限信息,而後將全部權限設置到咱們本身的==TestCommand.entitlements==文件中

  • 使用添加好權限的==TestCommand.entitlements==文件從新對可執行文件進行簽名,以下
ldid -STestCommand.entitlements TestCommand
複製代碼

-S 命令後要緊跟權限文件,不能有空格

  • 將簽名好的權限文件複製到iPhone的/usr/bin/目錄中,而後就能在終端使用==TestCommand==指令了
相關文章
相關標籤/搜索