android hook截取其他程序的按钮事件_Hook技术
生活随笔
收集整理的這篇文章主要介紹了
android hook截取其他程序的按钮事件_Hook技术
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
概述
Hook,英文直譯是”鉤子“的意思。在程序中將其理解為”劫持“可能會更好理解,我們可以通過hook技術來劫持某個對象,從而控制它與其他對象的交互。Hook技術分類
Hook原理
創建一個代理對象,然后把原始對象替換為我們的代理對象,這樣就可以在這個代理對象為所欲為,修改參數或替換返回值。正常的調用和返回:
Hook的調用和返回:
Hook的過程
Step1. 尋找Hook點,原則是靜態變量或者單例對象,盡量Hook public的對象和方法,非public不保證每個版本都一樣,需要適配。Step2. 選擇合適的代理方式,如果是接口可以用動態代理;如果是類可以用靜態代理。
Step3. 偷梁換柱——用代理對象替換原始對象。
Hook Activity的startActivity
尋找Hook點:
Activity的startActivity方法的調用鏈:
// android/app/Activity.java// Step1 @Override public void startActivity(Intent intent) {this.startActivity(intent, null); }// Step2 @Override public void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);} else {startActivityForResult(intent, -1);} }// Step3 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {if (mParent == null) {options = transferSpringboardActivityOptions(options);// Hook點Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);if (ar != null) {mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData());}if (requestCode >= 0) {mStartedActivity = true;}cancelInputsAndStartExitTransition(options);} else {if (options != null) {mParent.startActivityFromChild(this, intent, requestCode, options);} else {mParent.startActivityFromChild(this, intent, requestCode);}} }Hook點分析:
當調用Activity的startActivity方法時,最后會調用mInstrumentation的execStartActivity方法來完成Activity的開啟,而mInstrumentation是Activity的成員變量,所以是一個很好的Hook點,用代理Instrumentation來替代原始的Instrumentation完成Hook。
Hook代碼:
代理類:InstrumentationProxy.java
/*** 1. InstrumentationProxy繼承Instrumentation* 2. InstrumentationProxy持有Instrumentation實例的引用* 3. 實現execStartActivity方法,并在內部通過反射調用Instrumentation的execStartActivity方法*/ public class InstrumentationProxy extends Instrumentation {private static final String TAG = "InstrumentationProxy";private Instrumentation的 mInstrumentation;public InstrumentationProxy(Instrumentation instrumentation) {mInstrumentation = instrumentation;}public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {Log.i(TAG, "Hook成功" + "--who:" + who);try {Method execStartActivityMethod = Instrumentation.class.getDeclaredMethod("execStartActivity",Context.class, IBinder.class, IBinder.class, Activity.class,Intent.class, int.class, Bundle.class);return (ActivityResult) execStartActivityMethod.invoke(mInstrumentation, who, contextThread, token, target,intent, requestCode, options);} catch (Exception e) {throw new RuntimeException(e);}} }用InstrumentationProxy來替換Instrumentation:
public class HookHelper {public static void hookActivityInstrumentation(Activity activity) {try {// 得到Activity的mInstrumentation字段Field field = Activity.class.getDeclaredField("mInstrumentation");field.setAccessible(true);// 得到Activity中的Instrumentation對象Instrumentation instrumentation = (Instrumentation) field.get(activity);// 創建InstrumentationProxy對象來代理Instrumentation對象InstrumentationProxy instrumentationProxy = new InstrumentationProxy(instrumentation);// 用代理去替換Activity中的Instrumentation對象field.set(activity, instrumentationProxy);} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}} }執行Hook:
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// HookHookHelper.hookActivityInstrumentation(this);Intent intent = new Intent(this, DetailActivity.class);startActivity(intent);} }運行結果:
I/InstrumentationProxy: Hook成功--who:com.github.xch168.hooktest.MainActivity@bd3e1b1Hook Context的startActivity
Context的實現類為ContextImpl。尋找Hook點:
ContextImpl中startActivity的調用鏈:
// Step1 @Override public void startActivity(Intent intent) {warnIfCallingFromSystemProcess();startActivity(intent, null); }// Step2 @Override public void startActivity(Intent intent, Bundle options) {warnIfCallingFromSystemProcess();final int targetSdkVersion = getApplicationInfo().targetSdkVersion;if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0&& (targetSdkVersion < Build.VERSION_CODES.N|| targetSdkVersion >= Build.VERSION_CODES.P)&& (options == null|| ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {throw new AndroidRuntimeException("Calling startActivity() from outside of an Activity "+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."+ " Is this really what you want?");}// Hook點mMainThread.getInstrumentation().execStartActivity(getOuterContext(), mMainThread.getApplicationThread(), null, (Activity) null, intent, -1, options); }Hook點分析:
- 調用ActivityThread的getInstrumentation方法獲取Instrumentation。
- ActivityThread是主線程的管理類,Instrumentation是ActivityThread的成員變量,一個進程只有一個ActivityThread。
- 選擇Instrumentation作為Hook點,通過代理類進行替換。
Hook代碼:
public class HookHelper {public static void hookContextInstrumentation() {try {// 獲取ActivityThread類Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");// 獲取ActivityThread類中的靜態變量sCurrentActivityThreadField currentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");currentActivityThreadField.setAccessible(true);// 獲取sCurrentActivityThread字段的值,即ActivityThread的對象Object currentActivityThread = currentActivityThreadField.get(null);// 獲取ActivityThread的mInstrumentation字段Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");mInstrumentationField.setAccessible(true);// 獲取mInstrumentation對象Instrumentation instrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);// 創建Instrumentation的代理對象InstrumentationProxy instrumentationProxy = new InstrumentationProxy(instrumentation);// 用InstrumentationProxy替換ActivityThread中的InstrumentationmInstrumentationField.set(currentActivityThread, instrumentationProxy);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}} }執行Hook:
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// HookHookHelper.hookContextInstrumentation();Intent intent = new Intent(this, DetailActivity.class);getApplicationContext().startActivity(intent);} }運行結果:
I/InstrumentationProxy: Hook成功--who:android.app.Application@7e13696參考鏈接
總結
以上是生活随笔為你收集整理的android hook截取其他程序的按钮事件_Hook技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ae抠像插件_AE抠像背景残留去除
- 下一篇: atoi函数_吊打面试官 | 腾讯经典考