前言
Logos 是 Theos 的一個元件,它允許程式設計師使用一組特殊的前處理器指令來編寫鉤子,簡潔高效。 做過 iOS 逆向開發的朋友應該非常熟悉,這裡筆者將介紹如何在 Mac app 上使用 Logos。
可能用到的工具
- Theos
- optool/insert_dylib
- unsign (optional)
一個簡單的例子
-
編寫一個簡單的 demo,大概就是 軟體正中一個按鈕,點選之後 alert("hi!")。核心程式碼如下:
#import "ViewController.h" @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (IBAction)sayHi:(NSButton *)sender { NSAlert *alert = NSAlert.new; alert.messageText = @"hi!"; alert.alertStyle = NSAlertStyleInformational; [alert runModal]; } - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; // Update the view, if already loaded. } @end 複製程式碼
我們的目標是注入 sayHi 這個方法,使點選按鈕之後不再說“hi!”,而是“hello world!”
-
編寫 Logos
%config(generator=internal) // You don't need to #include <substrate.h>, it will be done automatically, as will // the generation of a class list and an automatic constructor. #import <Foundation/Foundation.h> %hook ViewController // Hooking an instance method with an argument. - (void)sayHi:(id)argument { NSAlert *r15 = [[NSAlert alloc] init]; [r15 setMessageText:@"hello world!"]; [r15 setAlertStyle:0x1]; [r15 runModal]; } // Always make sure you clean up after yourself; Not doing so could have grave consequences! %end %ctor { NSLog(@"!!!!!!inject success!!!!!!!"); } 複製程式碼
將以上程式碼儲存為一個 Tweak.xm 檔案(名字字尾名隨意),放在與 SayHi.app 同級目錄下,便於後續操作。
-
然後我們使用 Theos 的語法分析來把 Logos 轉換成普通程式碼
$THEOS/bin/logos.pl Tweak.xm > abc.mm
注意 abc 應該有 mm 作為字尾名,用於告訴 clang 目標語言型別 -
使用 clang 編譯轉換後的普通程式碼,並將結果放到 app 包內
clang -shared -undefined dynamic_lookup -o ./SayHi.app/Contents/MacOS/lib.dylib ./abc.mm
-
使用 optool/insert_dylib 往 SayHi 的 MachO 頭部新增我們剛剛編譯的 lib.dylib
optool install -c load -p @executable_path/lib.dylib -t ./SayHi.app/Contents/MacOS/SayHi
如果你的 Mac app 沒有簽名的話,此時應該已經達成我們的需求了。但是實踐中我們肯定不是對自己匯出的未簽名 Mac app 下黑手。所以需要去掉這個簽名或重簽名。因為筆者沒有錢買開發者賬號,故不知道如何重簽名。
- 使用 codesign 去除簽名
codesign --remove-signature SayHi.app
此時我們的需求已經達成
但是 codesign 有一個 bug,在刪除程式碼簽名之後沒有修復 MachO Header 的偏移,會導致生成的 MachO 檔案畸形。筆者曾經就遇見一個不到 1m 的小程式在移除簽名後膨脹到 2g 大小。 所以筆者建議使用開源社群的代替方案——unsign
後記
筆者把上面的繁瑣命令列操作整合為一個指令碼,在這裡也順便分享出來
#!/usr/bin/env bash
#將xm和檔案app包放在同一個目錄,執行本腳步進行注入
path=`ls | grep *.app | head -1`
tweak=`ls | grep *.xm | head -1`
temp='x11901'
name=${path%.app}
$THEOS/bin/logos.pl "./${tweak}" > "./${temp}.m"
clang -shared -undefined dynamic_lookup -o "./${path}/Contents/MacOS/lib.dylib" "./${temp}.mm"
optool install -c load -p @executable_path/lib.dylib -t "./${path}/Contents/MacOS/${name}"
rm -f ${temp}.m
# 使用unsign效果可能更好,codesign --remove-signature 在刪除程式碼簽名之後沒有修復MachO Header的偏移,導致生成的MachO檔案畸形
# codesign --remove-signature ${name}
if [ ! -e "./${path}/Contents/MacOS/${name}.ori" ]; then
unsign "./${path}/Contents/MacOS/${name}"
mv "./${path}/Contents/MacOS/${name}" "./${path}/Contents/MacOS/${name}.ori"
mv "./${path}/Contents/MacOS/${name}.unsigned" "./${path}/Contents/MacOS/${name}"
fi
open "./${path}/Contents/MacOS/${name}"
複製程式碼