07-4-iOS逆向之自定義命令行工具

需求

做一個自定命令行, 能夠打印Mach-O文件的架構

1. main 函數處理

1.1 通過Xcode創建一個Single View App 項目

int main(int argc, char * argv[]) {
    @autoreleasepool {
//        printf("%s\n", argv[0]);
        
        // 查看參數個數
        if (argc == 1) {
            printf("-l 查看 Mach-O 信息\n");
            return 0;
        }
        
        // 比較參數的值
        if (strcmp(argv[1], "-l") != 0) {
            printf("-l 查看 Mach-O 信息\n");
            return 0;
        }
        
        // Mach-O路徑
        NSString *machOPath = @"/private/var/containers/Bundle/Application/2036E1A7-46E6-4205-BD0A-9A305598315A/Fission.app/Fission";
        
        // 1. 創建文件句柄
        // 文件句柄是一個字節一個字節地讀取, 不需要把整個文件都加載到內存中, 節省內存
        NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:machOPath];
        NSLog(@"%@", handle);
    
        // 2. 處理文件內容
        // ...
        
        // 3. 關閉文件
        [handle closeFile];
        
        return 0;
    }
}

1.2 編譯命令行

  • 選擇真機設備編譯
    在這裏插入圖片描述
  • 運行環境選擇release
    在這裏插入圖片描述

1.3 編譯, 找到命令行

在這裏插入圖片描述

1.4 測試命令行

  • 將可執行文件 TestCL 導入手機路徑/usr/bin/
  • 注意 : 如果存在 TestCL 文件, 1. 先刪除 2. 再導入, 不要直接拖進去替換
    在這裏插入圖片描述
  • 直接使用會報權限問題
    在這裏插入圖片描述
    • 給文件添加執行權限
    chmod +x /usr/bin/TestCL
    
  • 測試成功
    在這裏插入圖片描述

2. 讀取魔數(magic number)

2.1 magic number: 魔數, 用來標識架構類型

2.2 查看可執行文件的魔數

  • 通過MachOView查看在這裏插入圖片描述

3. 通過內核源碼比對魔數的值

  • 內核源碼傳送門

  • 下載最新的就可以了

  • 文件路徑: xnu-xxx -> EXTERNAL_HEADERS -> mach-o -> fat.h 和 loader.h
    在這裏插入圖片描述
    在這裏插入圖片描述

  • 爲啥有兩個值? 大小端問題

  • 魔數對應代碼

// 字節長度
/**
	按照posix標準,一般整形對應的*_t類型爲:
	1字節     uint8_t
	2字節     uint16_t
	4字節     uint32_t
	8字節     uint64_t
  */
int length = sizeof(uint32_t);

// 讀出最前面的4個字節(magic number)
NSData *magicData = [handle readDataOfLength:length];

// magic number : 魔數, 用來標識架構類型
uint32_t magicNumber;
[magicData getBytes:&magicNumber length:length];

// 輸出架構類型
if (magicNumber == FAT_CIGAM || magicNumber == FAT_MAGIC) {
    printf("FAT文件\n");
} else if (magicNumber == MH_CIGAM_64 || magicNumber == MH_MAGIC_64) {
    printf("arm_64文件\n");
} else if (magicNumber == MH_MAGIC || magicNumber == MH_CIGAM) {
    printf("非arm_64文件\n");
} else {
    printf("讀取失敗\n");
}

4. 給TestCL文件添加SpringBoard權限

4.1 權限相關的問題

  • 爲啥添加SpringBoard的權限,因爲它的權限非常高, 可以任意訪問其他App的文檔路徑
  • SpringBoard的路徑:
    在這裏插入圖片描述
  • 蘋果的權限文件大多以 .entitlements 結尾
.entitlements == .xml == .plist文件

4.2 導出Mach-O文件的權限

// -e : export 導出
// >  : 覆蓋
// >> : 追加
ldid -e 可執行文件 > 可執行文件.entitlements

4.3 給可執行文件重新簽上權限

// 注意: -S和可執行文件的權限文件要緊跟着,沒有空格
ldid -S可執行文件權限文件 可執行文件

5. 報錯總結

5.1 Bad CPU type in executable

  • 沒有選擇真機編譯
    在這裏插入圖片描述

5.2 Killed: 9

  • 原因1 : 沒有選擇發佈版本(release), 而選擇了測試版本(debug)
  • 原因2 : 將TestCL文件導入手機時, 直接拖進去替換了原來的TestCL文件在這裏插入圖片描述

5.3 -sh: /usr/bin/ TestCL: Permission denied

  • 沒有執行權限, 添加即可
chmod +x /usr/bin/TestCL

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章