プロジェクトアドレス:フックメソッドプラグイン
Androidメソッドフック用のプラグインです メソッドの出入り時に現在実行中のパラメータがすべて固定インターフェースにコールバックされます これを利用することでメソッドスライスの開発が可能になります フックポイントを設定することでフック監視が可能になります目的を達成することができます。
このプラグインを使用すると、次のことが可能になります。
- Android の完全な埋め込みポイント、ページの閲覧、クリックなど。痕跡の埋め込みポイントはありません。必要に応じてフック ポイントを設定するだけです。設定方法は次のとおりです。
- Android メソッドは時間がかかり、パフォーマンス統計
- さまざまなインターセプター、たとえばメソッドをインターセプトする場合、メソッドが実行される前に、まず権限を決定したり、準備をしたりします。
- 参照されたサードパーティの jar パッケージにコードを追加し、スレッドの作成、ファイル IO 関連の監視などを追加します。
- サードパーティの SDK を参照する実行ロジックを確認します。たとえば、どの SDK が位置情報、imei を取得するか、バックグラウンドで頻繁に実行されるかを確認します。
結果を示す
例えば、日々の開発において、どうしてもクリックイベントの埋め込み作業が必要になることがありますが、このプラグインを使えば、一度にすべてのクリックイベントの埋め込みポイントを直接設定してカウントすることができますので、具体的な方法を見てみましょう。
- まずフック ポイントを定義します。このフック ポイントの目的は、すべてのクリック イベントを監視することです。アプリモジュールのbuild.gradleに以下のコードを追加します。詳細フィールドの意味は後述します。
apply plugin: 'com.miqt.plugin.hookmethod'
hook_method {
buildLog = true
injectJar = false //是否hook引用的第三方jar包
enable = true
hookTargets {
hook_onclick {
// <-- 定义Hook点
interfaces = "android/view/View\$OnClickListener"//<-- hook条件1,继承了这个接口
methodName = "onClick" //<-- hook条件2,方法名
descriptor = "(Landroid/view/View;)V" //<-- hook条件3,方法参数和返回值类型
hookTiming = "Enter" //<-- hook条件4,指定是在方法进入时进行Hook
}
}
}
hook_method はプラグイン全体の構成、hookTargets はフックポイントの構成です。コンパイル時に、定義されたフィルタ条件に従ってフィルタリングされます。4 つの条件が同時に満たされた場合にのみ、インストルメンテーションが実行されます。実行されました。
これはバイトコード操作であるため、ここでの定義はフィールド記述子とバイトコード記述子の
descriptor
両方であることに注意してください。知らない場合は、Baidu で見つけることができます。非常に簡単です。知りたくなくても大丈夫ですので、メソッドのバイトコード情報を直接見る方法を紹介します。注釈を使用する@HookInfo
上記の設定を行った後、何気なくボタンを記述し、クリックイベントを追加します。
public class MainActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "onClick", Toast.LENGTH_SHORT).show();
}
});
}
}
同期ボタンをクリックしてプロジェクトをコンパイルすると、プラグインはクリック イベントのフック転送ハンドラー処理クラスを自動的に生成します。
このようなもの: HookHandler
この時点で、Apk 逆コンパイルを開いて表示すると、スタブ コードが表示されます。
public class MainActivity extends Activity {
/* access modifiers changed from: protected */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
/* class com.asm.code.MainActivity.AnonymousClass1 */
public void onClick(View view) {
HookHandler.hook_onclickEnter(this, "com/asm/code/MainActivity$1", "onClick", "[android.view.View]", "void", new Object[]{
view});//<--插桩的代码
Toast.makeText(MainActivity.this, "onClick", 0).show();
}
});
}
}
この時点では、hook_onclickEnter
このメソッドにグローバル クリック イベントの監視と処理ロジックを記述するだけです。これはすべてプラグインによって自動的に行われます。フック ルールを設定するだけです。非常に簡単ではありませんか。
構成ポータルの例: https://github.com/miqt/android-plugin/blob/master/app/build.gradle
同様に、プラグインは、フック ルールとフック プロジェクト内のメソッドのコードをカスタマイズすることによって、アスペクト プログラミングの目的を達成することもできます。
設定方法を使用する
-
Mavenリポジトリを追加
maven { url 'https://raw.githubusercontent.com/miqt/maven/master' } maven { url 'https://gitee.com/miqt/maven/raw/master' }
まだライブラリをプルできないのですか?
maven { url 'https://raw.fastgit.org/miqt/maven/master' }
または、ウェアハウスのgit アドレスにアクセスしてダウンロードし、ローカルで依存します。
最初はこれを使用していました
jcenter()
が、後にこのライブラリは正式に非推奨になりましたが、現在バージョン 0.3.5 は引き続きこのライブラリから取得でき、以降のバージョンのウェアハウス ストレージ アドレスとして gitee と github を使用しています。 -
プラグインの依存関係を追加する
プロジェクトのルート ディレクトリ: build.gradle 次のコードを追加します
dependencies { classpath 'com.miqt:hook-method-plugin:0.4.1' }
プラグインは対応するモジュールで有効になっています。これは、
application
またはlibrary
apply plugin: 'com.miqt.plugin.hookmethod' hook_method { buildLog = true injectJar = false //是否hook引用的第三方jar包 enable = true hookTargets { hook_onclick { // <-- 自定义Hook点 interfaces = "android/view/View\$OnClickListener" //<-- hook条件1,继承了这个接口 methodName = "onClick" //<-- hook条件2,方法名 descriptor = "(Landroid/view/View;)V" //<-- hook条件3,方法参数和返回值类型 hookTiming = "Enter" //<-- hook条件4,指定是在方法进入时进行Hook } } }
-
対応するモジュールにクラス ライブラリの依存関係を追加します。
dependencies { implementation 'com.miqt:hook-method-lib:0.4.1' }
プロジェクトをクリーンアップして実行し、logcat フィルターを実行する
MethodHookHandler
と、印刷結果が表示されます。
プラグイン設定パラメータの説明
hook_method {} のパラメータ
プラグインに関する設定を定義します。
パラメータ | 必要ですか? | タイプ | 意味 | デフォルト |
---|---|---|---|---|
有効 | いいえ | ブール | 有効にするかどうか | 真実 |
ランバリアント | いいえ | 弦 | プラグインの実行環境では、デバッグ環境にスタブを挿入するだけで、リリース環境には必要ない場合があります。このとき、DEBUG に設定できます。つまり、DEBUG が実行されるときのみ、 DEBUG : ランタイム インスツルメンテーションのデバッグのみ RELEASE : RELEASE ランタイム インスツルメンテーションのみ ALWAYS : すべてのランタイム (デフォルト) NEVER : インストルメンテーションを行わない、enable = false と同等 |
いつも |
Jar を注入する | いいえ | ブール | 参照されるすべてのサードパーティ依存の jar および aar のルールに従ってフック挿入を実装するかどうか | 間違い |
ビルドログ | いいえ | ブール | プラグインのコンパイルログを .\app\build\plugin フォルダに出力するかどうか コンパイルでエラーが発生した場合に開いてください | 真実 |
ハンドラ | いいえ | 弦 | インストルメンテーションフックによって転送されるクラスを受け取るHandlerがインストルメンテーション処理クラスで、例えばxxx.xxx.Aを渡すと、コンパイル後にクラスA.javaが自動生成され、以下のようにメソッドが自動生成されます。 : | com.miqt.hookplugin.HookHandler |
ハンドラーディレクトリ | いいえ | 弦 | インストルメント化されたフックによって転送されるクラスを受信するハンドラーはそのパスに生成されます。通常、デフォルトは.\src\main\java カスタマイズする必要はありません。 |
.\src\main\java |
HookTargets {} のパラメータ
構造:
hook_method {
hookTargets {
name1 {
条件1 = value1
条件2 = value2
条件3 = value3
}
name2 {
条件1 = value1
条件2 = value2
条件3 = value3
}
}
}
フード ポイント フィルター条件の定義は次のとおりです。ロジックは、ステークを挿入する前にパラメーター 1、2、および 3 で設定された条件が満たされる必要があるというものです。
注: これが設定されている場合:hook_All{ }
この無条件パラメータは、すべてのメソッドがスタブ化されることを意味します。
パラメータ | 必要ですか? | タイプ | 意味 | デフォルト |
---|---|---|---|---|
名前 | はい | 弦 | 上記のname1とname2の位置はフックポイントの名前を意味しており、この名前が最終的にこの時点でのフック受け取りメソッドの名前となり、自分で定義することができます。 | ヌル |
アクセス | いいえ | 整数 | 制限事項: private、public、static、final などのメソッドのアクセス修飾子は、Opcodes.ACC_PRIVATE|Opcodes.ACC_STATIC この形式で定義されます。 |
-1 |
インターフェース | いいえ | 弦 | 制限条件: メソッドが配置されているクラスでどのインターフェイスを実装する必要があるか。たとえば、OnClickListener インターフェイスは次のように記述されます。interfaces = "android/view/View\$OnClickListener" ここではドットは使用されず、/ はこれがバイトコード識別子であることを示すために使用されます。@HookInfo アノテーションをメソッドまたはクラスに追加すると、プラグインは、対応するバイトコード識別子をコンパイル コンソールおよびコンパイル ログ ログ ファイルに自動的に表示します。 |
ヌル |
スーパーネーム | いいえ | 弦 | 制限事項: メソッドのクラスは superName のサブクラスである必要があります。 | ヌル |
クラス名 | いいえ | 弦 | 制限: メソッドが配置されているクラスの名前。ここは完全名です (com/xxx/A など)。通常の制限がサポートされています。 | ヌル |
メソッド名 | いいえ | 弦 | 制限: メソッド名、通常の制限のサポート | ヌル |
ディスクリプタ | いいえ | 弦 | 制限事項: メソッドフィールド記述子。記述方法がわからない場合は、 @HookInfo タグを使用して出力を確認してください。 | ヌル |
注釈 | いいえ | 弦 | 制限事項: メソッドまたはクラスにはこのアノテーションが含まれている必要があります | ヌル |
サイン | いいえ | 弦 | 制限: メソッドまたはクラスには、このジェネリックが含まれている必要があります。 | ヌル |
例外 | いいえ | 弦 | 制限事項: メソッドは例外をスローする形式に準拠している必要があります。 | ヌル |
フックタイミング | いいえ | 弦 | 制限条件: メソッドがスタブに入るときまたは出るときEnter : メソッドが入るときReturn : メソッドが出るときEnter|Return : 入るときと出るとき (デフォルト) |
Enter|Return |
組み込みの注釈
@HookInfo:対応するバイトコード制限条件情報を出力します。これは、同じタイプのフック メソッドに対してコピーして出力できます。
@HookMethod:フックメソッドをマークします。hookTargets を記述する必要はありません。組み込みの @HookMethodInherited として理解できます
。フック メソッドをマークします。クラスの継承があり、hookTargets を記述する必要はありません。組み込みの
@IgnoreMethodHook として理解できます。無視メソッドをマークします。最も優先度が高くなります。
读都读到这里了,如果觉得还不错就帮我点个star吧,你的肯定是我持续维护的动力!
如果有使用问题欢迎提交Issues ,或者加我微信一起交流,微信号在我的主页。
最后贴个Demo中的示例:
apply plugin: 'com.miqt.plugin.hookmethod'
hook_method {
buildLog = true
injectJar = true
enable = true
hookTargets {
hook_onclick {
//<-- 所有点击事件
interfaces = "android/view/View\$OnClickListener"
methodName = "onClick"
descriptor = "(Landroid/view/View;)V"
hookTiming = "Enter|Return"
}
hook_activity_lifeCycle {
//<-- 所有activity生命周期方法
access = 4
superName = "android/app/Activity"
//这里是个正则表达式
methodName = "(onCreate)|(onResume)|(onPause)|(onStart)|(onDestroy)|(onStop)"
hookTiming = "Enter|Return"
}
hook_thread_run{
//<-- 线程run方法
access = 1
superName = "java/lang/Thread"
methodName = "run"
descriptor = "()V"
}
hook_Runnable_run{
//<-- 线程run方法
access = 1
interfaces = "java/lang/Runnable"
methodName = "run"
descriptor = "()V"
}
}
}
demo打印结果:
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[3]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[Thread-5]
I/MethodHookHandler: └com/asm/code/[email protected]():[1]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
I/MethodHookHandler: ┌com/asm/code/[email protected]():[main]
I/MethodHookHandler: └com/asm/code/[email protected]():[0]
致谢
这个插件是借鉴了很多大佬的代码,并结合自己的想法进行了一些调整,在此感谢他们付出的努力。
https://github.com/novoda/bintray-release
https://github.com/JeasonWong/CostTime
https://github.com/MegatronKing/StringFog