android hook截取其他程序的按钮事件_Hook技术
概述
Hook,英文直译是”钩子“的意思。在程序中将其理解为”劫持“可能会更好理解,我们可以通过hook技术来劫持某个对象,从而控制它与其他对象的交互。
Hook技术分类
- 根据Hook的API语言划分,分为Hook Java和Hook Native。
- Hook Java主要通过反射和代理来实现,用于在SDK开发环境中修改Java代码。
- Hook Native则应用于在NDK开发环境和系统开发中修改Native代码。
- 根据Hook的进程划分,分为应用程序进程Hook和全局Hook。
- 应用程序进程Hook只能Hook当前所在的应用程序进程。
- 应用程序进程是Zygote进程fork出来的,如果对Zygote进行Hook,就可以实现Hook系统所有的应用程序进程,这就是全局Hook。
- 根据Hook的实现方式划分,分为如下两种:
- 通过反射和代理实现,只能Hook当前的应用程序进程。
- 通过Hook框架实现,比如Xposed,可以实现全局Hook,但是需要root。
Hook原理
创建一个代理对象,然后把原始对象替换为我们的代理对象,这样就可以在这个代理对象为所欲为,修改参数或替换返回值。
正常的调用和返回:
Hook的调用和返回:
Hook的过程
Step1. 寻找Hook点,原则是
静态变量
或者单例对象
,尽量Hookpublic
的对象和方法,非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@bd3e1b1
Hook 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机制之动态代理
- Android Hook 机制之简单实战
- Android Hook Activity 的几种姿势
- 理解 Android Hook 技术以及简单实战
- 《Android进阶解密》
android hook截取其他程序的按钮事件_Hook技术相关推荐
- 160个CrackMe之108 mfc程序 寻找按钮事件,代码还原(上)
·前言 虽然网上已经有帖子写160个CrackMe,我个人还是以正向的思路来逆向一部分的crackme,还有一些 代码还原的小技巧,挑选出这160个CrackMe中由c,c++,汇编编写的程序来来写 ...
- 小程序监听android返回键,如何监听小程序返回按钮事件?
写在前面 为了能及时的将自己踩到的前端坑(包括ionic,angular,react,ReactNative,小程序,APICloud)分享给大家,以后会逐渐将文章转移到微信公众号:前端e家(fron ...
- 转用特征码秒杀各程序语言按钮事件
作者:小童 工具:OllyDbg.Delphi程序一个.易语言程序一个.MFC程序一个 -------------------------------------------------------- ...
- 用特征码秒杀各程序语言按钮事件
作者:小童 工具:OllyDbg.Delphi程序一个.易语言程序一个.MFC程序一个 -------------------------------------------------------- ...
- 如何监听小程序返回按钮事件?
2020-06-09更新 //--------------------------2020-06-09更新-------------------开始-------------------------- ...
- Android 开发笔记(一) 按钮事件调用Activity
UI创建按钮及事件 Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);mEmailSignInB ...
- .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
原文:.Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化 我们知道资源被注册到R.java我们通过R.java就可以读取到界面中的组件.跟我们.net一样,通过ID来读取组件 ...
- Android按钮事件的4种写法
经过前两篇blog的铺垫,我们今天热身一下,做个简单的例子. 目录结构还是引用上篇blog的截图. 具体实现代码: public class MainActivity extends Activity ...
- android 6.0 权限程序崩溃,扫二维码崩溃与按键事件
1.权限 解决困扰我两天的问题,项目调用一些.so文件,demo,和老版本的在华为 6.0系统运行正常,但是我的项目在6.0以下的手机上运行正常,在6.0系统上程序直接崩溃,6.0系统自然想到了权限问 ...
最新文章
- oracle去掉blob的黑边,oracle Blob处理
- Lyft估值目标近200亿美元 有望成今年来美国最大IPO
- 手机广告投放(phone advertising)唯一标识
- “我工作八年,换了四家小公司,今后的职业生涯该怎么走?”
- [Redis6]常用数据类型_String字符串
- CUDA out of memory. Tried to allocate 14763.13 GiB (GPU 3; 10.73 GiB total capacity; 165.28 MiB alre
- python mysql异常处理_python-处理PyMySql异常-最佳做法
- 深度学习优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)
- 集算器(仓库版)发布,黑科技获得用户好评
- 如果同时需要两张表,但其中一个表中没有另一个表中的字段,该如何正确使用
- 【新征程】1、考研路漫漫
- .NET中对于日文输入法的控制
- NNDL 实验六 卷积神经网络(4) ResNet18实现MINIST
- Linux的开源操作系统
- HttpClient请求https类型的网站接口碰到ssl证书不受信任问题处理
- jzoj2555 雾雨魔理沙
- 颜色迁移之四——模糊聚类(FCM)算法
- 工件SSMwar exploded 部署工件时出错。请参阅服务器日志了解详细信息
- intellij 打开两个窗口
- 真实生活的记录:我三年的外企生涯(1)出处:天涯虚拟社区
热门文章
- Leet Code OJ 4. Median of Two Sorted Arrays [Difficulty: Hard]
- Effective Java之避免创建不必要的对象(五)
- poj 2492 A Bug's Life
- 【最简便解法】1086 就不告诉你 (15分)_13行代码AC
- C语言满分代码:L1-059 敲笨钟 (20分)
- 16行代码AC——紫书| 例题7-3 Fractions Again?! (UVA - 10976)_时间复杂度O(n)
- 举例说明事务隔离级别
- Spring中BeanPostProcessor 执行过程
- (*长期更新)软考网络工程师学习笔记——Section 8 传输层
- Python程序开发——第五章 函数