既存のアプリに「オブジェクト」を追加するにはどうすればよいですか?
たとえば、Chrome の微調整の EasyRefresh は、他の多くの微調整と同様に、iOS Chrome アプリ内の新しいボタンを有効にします。
UIButton
たとえば、Twitter アプリに簡単に追加するにはどうすればよいですか?
それがどのように行われたかを理解するのに役立つかもしれないGitHubプロジェクトはありますか?
画像ソース: ModMyI
ありがとう。
このトリックには、いくつかの (非常に基本的な) リバース エンジニアリングが含まれており、いくつかの手順で構成されています。私はそれらをできるだけ明確に説明しようとします。
ステップ ゼロ:アプリが AppStore からダウンロードされた場合、アプリは暗号化されます。アプリのクラックに通常使用されるスクリプト/アプリケーションのいずれかを使用して復号化する必要があります。1 つのコマンド ライン スクリプトは poedCrack.sh (Google で検索すると、貼り付けサイトの 1 つですぐに見つかります) であり、1 つの GUI アプリケーションは Crakculous (Cydia で利用可能) です。これらの 1 つは簡単な (自動) 復号化に必要であることに注意してください。手動の復号化方法は、StackOverflow の回答を入れるにはあまりにも複雑です。そのため、これらのツールを提案しています)。あなたはアプリをクラックする!(基本的に、これらのツールを本来の目的で使用しないでください:) 手動の復号化プロセスを見たい場合は、ここに進んでください。
ステップ 1:アプリケーションが使用/作成するクラスを実行する必要があります。これには、class-dump または class-dump-z ユーティリティが必要です。このコマンドライン アプリケーションは、アプリのバイナリ実行可能ファイルを反転し、アプリが使用して内部に持つすべての Objective-C クラスのインターフェイス宣言を生成します。ここでは、より高度で推奨されるバリアントである class-dump-z を見つけることができます。
ステップ 2:クラス宣言を行った後、どのクラスがいつ何を行うかを推測する必要があります (はい、少し混乱します)。たとえば、上記のアプリである Google Chrome から class-dump-z によって生成されたファイルの 1 つで、次のようなものが見つかる場合があります。
@interface ChromeUrlToolbar: UIToolbar {
UISearchBar *urlBar;
}
- (id)initWithFrame:(CGRect)frame;
- (void)loadURL:(NSURL *)url;
@end
いいですね。その実装に initWithFrame: メソッドがあることがわかります (すべての UIView サブクラスと同様) -- 変更してみませんか?
ステップ 3:この変更には、 MobileSubstrateが必要です。MobileSubstrate は、アプリへのコード インジェクションを簡単にするために、Cydia の作成者である Saurik によって作成された開発者ライブラリです。このチュートリアルを含め、ウェブ上でいくつかの非常に優れたチュートリアルを見つけることができます。クラスがあり、それを「フック」したい場合は、次のようなコードを記述します。
static IMP __original_init; // A
id __modified_init(id __self, SEL __cmd, CGRect frame) // B
{
__self = __original_init(__self, __cmd, frame); // C
// D
UIButton *newButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[newButton setTitle:@"Chrome Pwned"];
newButton.frame = CGRectMake(0, 0, 100, 40);
[__self addSubview:newButton];
return __self;
}
// E
__attribute__((constructor))
void init()
{
Class clazz = objc_getClass("ChromeUrlToolbar"); // F
MSHookMessageEx(clazz, @selector(initWithFrame:), __modified_init, &__original_init); // G
}
説明:最後から始めましょう。init
関数 (E) が宣言されてい__attribute__((constructor))
ます。つまり、このコードから作成するライブラリが Chrome に読み込まれるときに、自動的に呼び出されます。アプリケーションを開始する前にアプリケーションの動作を変更したいので、まさにそれが必要です。
とマークされた行で// F
、変更したいクラス オブジェクト自体をキャプチャします。Objective-C は非常に動的な言語です。つまり、実行時にクラスとオブジェクトに関する情報を取得および変更できます。と記された行// G
では、MobileSubstrate API の最も重要な関数である MSHookMessageEx を使用します。それがどのように機能するか (それが何をするかではなく) を理解するには、次のことを知っておく必要があります: Objective-C 自体はプレーンな C ライブラリとして実装されています。 -C は実際には C 関数呼び出しです。これらの C 関数には、次の 2 つの特別な引数がself
あります。cmd
-- 前者はメッセージが送信されるオブジェクトへのポインターであり、後者はセレクター (送信されるメッセージの名前への特別な一意のポインター) です。__modified_init
したがって、MSHookMessageEx が行うことは、クラスとセレクターを取り、それらに対応する関数の実装を見つけて、その関数を 3 番目の引数自体 (この場合) で提供される関数と交換することです。データを失わないようにするために、4 番目のパラメーター (ここでは__original_init
) で関数も返します。
これで、Chrome URL ツールバーの初期化が関数にリダイレクトされました。次に何をすればよいでしょうか? 特別なことは何もありません: 最初に元の初期化関数を呼び出すだけです (最初の 2 つの特別な引数 __self と __cmd に注目してください! // C
)。次に、実際の変更を行います。セクション// D
で、UIButton を作成し、そのタイトルと場所を設定し、新しく作成したツールバーにサブビューとして追加します。次に、これが初期化関数であることを認識して、ボタンのコードを挿入した元のインスタンスを返します。
基本的には、これについて知っておく必要があります。Objective-C がどのように機能するか、および iOS のクールな微調整を作成する方法の詳細に興味がある場合は、このトピックに関する Apple の公式ドキュメントを読むことをお勧めします。同じように。
これがお役に立てば幸いです。
これを行うには、Objective-C ランタイムがどのように機能するかを理解する必要があります。特にメッセージング システム (つまり、メソッドの呼び出し)。特に、呼び出すメソッドは実行時に決定されますが、他の言語ではコンパイル時に決定されます。これにより、特定のメソッドのグローバルな変更、別名メソッドの入れ替えが可能になります。
Mobile Substrate ライブラリを使用すると、任意のメソッド実装を独自のものに置き換えることができ、元の実装を呼び出すことさえできます。もちろん、そのためには、メソッドの名前とそれが取る引数、およびそれが属するクラスを知る必要があります。
したがって、たとえば SpringBoard を変更するには、含まれるクラスとメソッドを知る必要があります。class-dump
それを行うorclass-dump-z
ユーティリティを使用する必要があります(class-dump-z
最近では iOS dev でより多く使用されており、class-dump
より用途が広く、古いバイナリや 64 ビットと互換性があります)。
したがって、SpringBoard をクラスダンプするには、Terminal.app に入力する必要があります。
class-dump -H /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard
class-dump-z の場合、-p
オプションは@property
ゲッター/セッターの代わりに生成されます。これはより明確であるため、おそらく入力します
class-dump-z -p -H /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard
この行により、SpringBoard のすべてのクラス定義を含むフォルダーがデスクトップに作成されます。もちろん、パスをシステムに適したものに変更する必要があるかもしれません (それについては、Xcode の最近のバージョンでは、Developer フォルダーはXcodeにあるため、次のようなものが必要です。
/Applications/Xcode/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard
既存のフレームワークのほとんどでそれを行った人をインターネットで見つけることもできます。これは、システムに適したバージョンであることを確認する場合に非常に便利です。
現在、AppStore アプリケーションの場合、保護されているため、最初に復号化する必要があります。これはおそらく Stack Overflow の ToS に反するため、自分でその名前とリンクを見つける必要がありますが、使用gdb
するとその目的を達成できます。
作業を容易にするために、 Logos (おそらくTheosも参照する必要があるでしょう)などのいくつかのツールが作成され、必要なボイラープレート コードが削減されました。また、良い助けを提供するmobilesubstrate 用の (かなり古い) xcode テンプレートとチュートリアルもあります。
method
Logos を使用すると、クラスからメソッドを簡単にフックできclassname
ます。
%hook classname //declares the class from your application you're going to override
-(void)method {
dosomethingnew(); //put all your new code for the method here
return %orig; //this calls the original definition of the method
}
%end //end hooking classname
システム内のフレームワークとその有用性のリストについては、こちらを参照してください。
最後に: オープンソース化されている一般的な微調整のリスト (可能な場合は GitHub へのリンク) :
最後に、WeekTweakを見てください。彼らは毎週オープンソースの微調整をリリースしているので、他の人のソースを見て自分のことを試して実行することで学ぶことができます。また、IRC (irc.saurik.com) の #theos chan も親切に頼めば助けてくれます。