Android.Hook框架xposed篇(Http流量监控)
瘦蛟舞 · 2015/08/03 10:30
官方教程:github.com/rovo89/Xpos…
官网:repo.xposed.info/module/de.r…
apk:dl-xda.xposed.info/modules/de.…
源码:github.com/rovo89/Xpos…
模块基本开发流程
1.创建工程android4.0.3(api15,测试发现其他版本也可以),可以不用activity
2.修改AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="de.robv.android.xposed.mods.tutorial"android:versionCode="1"android:versionName="1.0" ><uses-sdk android:minSdkVersion="15" /><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name" ><meta-dataandroid:name="xposedmodule"android:value="true" /><meta-dataandroid:name="xposeddescription"android:value="Easy example" /><meta-dataandroid:name="xposedminversion"android:value="54" /></application>
</manifest>
复制代码
3.在工程目录下新建一个lib文件夹,将下载好的XposedBridgeApi-54.jar包放入其中.
eclipse 在工程里 选中XposedBridgeApi-54.jar 右键–Build Path–Add to Build Path.
IDEA 鼠标右键点击工程,选择Open Module Settings
,在弹出的窗口中打开Dependencies选项卡.把XposedBridgeApi这个jar包后面的Scope属性改成provided.
4.模块实现接口
#!java
package de.robv.android.xposed.mods.tutorial;import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;public class Tutorial implements IXposedHookLoadPackage {public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {XposedBridge.log("Loaded app: " + lpparam.packageName);}
}
复制代码
5.入口assets/xposed_init配置,声明需要加载到 XposedInstaller 的入口类:
#!java
de.robv.android.xposed.mods.tutorial.Tutorial //完整类名:包名+类名
复制代码
6.定位要hook的api
- 反编译目标程序,查看Smali代码
- 直接在AOSP(android源码)中查看
7.XposedBridge to hook it
- 指定要 hook 的包名
- 判断当前加载的包是否是指定的包
- 指定要 hook 的方法名
- 实现beforeHookedMethod方法和afterHookedMethod方法
示例如下:
#!java
package de.robv.android.xposed.mods.tutorial;import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC\_MethodHook; import de.robv.android.xposed.callbacks.XC\_LoadPackage.LoadPackageParam;public class Tutorial implements IXposedHookLoadPackage { public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable { if (!lpparam.packageName.equals("com.android.systemui")) return;findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "updateClock", new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {// this will be called before the clock was updated by the original method}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {// this will be called after the clock was updated by the original method}});}}
复制代码
重写XC_MethodHook的两个方法beforeHookedMethod和afterHookedMethod,这两个方法会在原始的方法的之前和之后执行.您可以使用beforeHookedMethod 方法来打印/篡改方法调用的参数(通过param.args) ,甚至阻止调用原来的方法(发送自己的结果).afterHookedMethod 方法可以用来做基于原始方法的结果的事情.您还可以用它来操纵结果 .当然,你可以添加自己的代码,它将会准确地在原始方法的前或后执行.
关键API
IXposedHookLoadPackage
handleLoadPackage : 这个方法用于在加载应用程序的包的时候执行用户的操作
调用示例
#!java
public class XposedInterface implements IXposedHookLoadPackage {
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
XposedBridge.log("Kevin-Loaded app: " + lpparam.packageName); }
}
复制代码
参数说明|final LoadPackageParam lpparam 这个参数包含了加载的应用程序的一些基本信息。
XposedHelpers
findAndHookMethod ;这是一个辅助方法,可以通过如下方式静态导入:
#!java
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
复制代码
使用示例
#!java
findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "handleUpdateClock", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// this will be called before the clock was updated by the original method }
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// this will be called after the clock was updated by the original method }
});
复制代码
参数说明
findAndHookMethod(Class<?>clazz, //需要Hook的类名
ClassLoader, //类加载器,可以设置为 null
String methodName, //需要 Hook 的方法名
Object... parameterTypesAndCallback
复制代码
该函数的最后一个参数集,包含了:
(1)Hook 的目标方法的参数,譬如:
"com.android.internal.policy.impl.PhoneWindow.DecorView"
复制代码
是方法的参数的类。
(2)回调方法:
a.XC_MethodHook
b.XC_MethodReplacement
复制代码
模块开发中的一些细节
1.Dalvik 孵化器 Zygote (Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育/fork出来的)进程对应的程序是/system/bin/app_process. Xposed 框架中真正起作用的是对方法的 hook。
#!java因为 Xposed 工作原理是在/system/bin 目录下替换文件,在 install 的时候需要 root 权限,但是运行时不需要 root 权限。
复制代码
2.log 统一管理,tag 显示包名
#!javaLog.d(MYTAG+lpparam.packageName, "hello" + lpparam.packageName);
复制代码
3.植入广播接收器,动态执行指令
#!javafindAndHookMethod("android.app.Application", lpparam.classLoader, "onCreate", new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {Context context = (Context) param.thisObject;IntentFilter filter = new IntentFilter(myCast.myAction);filter.addAction(myCast.myCmd);context.registerReceiver(new myCast(), filter);}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);}});
复制代码
4.context 获取
#!javafristApplication = (Application) param.thisObject;
复制代码
5.注入点选择 application oncreate 程序真正启动函数而是 MainActivity 的 onCreate (该类有可能被重写,所以通过反射得到 oncreate 方法)
#!javaString appClassName = this.getAppInfo().className;if (appClassName == null) {Method hookOncreateMethod = null;try {hookOncreateMethod = Application.class.getDeclaredMethod("onCreate", new Class[] {});} catch (NoSuchMethodException e) {e.printStackTrace();}hookhelper.hookMethod(hookOncreateMethod, new ApplicationOnCreateHook());
复制代码
6.排除系统 app,排除自身,确定主线程
#!javaif(lpparam.appInfo == null || (lpparam.appInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) !=0){return;}else if(lpparam.isFirstApplication && !ZJDROID_PACKAGENAME.equals(lpparam.packageName)){
复制代码
7.hook method
#!javaOnly methods and constructors can be hooked,Cannot hook interfaces,Cannot hook abstract methods只能 hook 方法和构造方法,不能 hook 接口和抽象方法抽象类中的非抽象方法是可以 hook的, 接口中的方法不能 hook (接口中的method默认是public abstract 抽象的.field 必须是public static final)
复制代码
8.参数中有 自定义类
#!javapublic void myMethod (String a, MyClass b) 通过反射得到自定义类,也可以用[xposedhelpers](https://github.com/rovo89/XposedBridge/wiki/Helpers#class-xposedhelpers)封装好的方法findMethod/findConstructor/callStaticMethod....
复制代码
9.注入后反射自定义类
#!javaClass<?> hookMessageListenerClass = null;hookMessageListenerClass = lpparam.classLoader.loadClass("org.jivesoftware.smack.MessageListener");findAndHookMethod("org.jivesoftware.smack.ChatManager", lpparam.classLoader, "createChat", String.class , hookMessageListenerClass ,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {String sendTo = (String) param.args[0];Log.i(tag , "sendTo : + " + sendTo );}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);}});
复制代码
10.hook 一个类的方法,该类是子类并且没有重写父类的方法,此时应该 hook 父类还是子类.(hook 父类方法后,子类若没重写,一样生效.子类重写方法需要另外 hook) (如果子类重写父类方法时候加上 spuer ,hook 父类依旧有效)
例如 java.net.HttpURLConnection extends URLConnection ,
复制代码
方法在父类
#!javapublic OutputStream getOutputStream() throws IOException {throw new UnknownServiceException("protocol doesn't support output");}org.apache.http.impl.client.AbstractHttpClient extends CloseableHttpClient ,
复制代码
方法在父类(注意,android的继承的 AbstractHttpClient implements org.apache.http.client.HttpClient)
#!javapublic CloseableHttpResponse execute(final HttpHost target,final HttpRequest request,final HttpContext context) throws IOException, ClientProtocolException {return doExecute(target, request, context);}android.async.http复写HttpGet导致zjdroid hook org.apache.http.impl.client.AbstractHttpClient execute 无法获取到请求 url和method
复制代码
11.hook 构造方法
#!javapublic static XC_MethodHook.Unhook findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback) {return findAndHookConstructor(findClass(className, classLoader), parameterTypesAndCallback);}
复制代码
12.承接4,application 的onCreate 方法被重写,例如阿里的壳,重写为原生 native 方法.
解1:通过反射到 application 类重写后的 onCreate 方法再对该方法进行hook
解2:hook 构造方法(构造方法被重写,继续解1)
13.native 方法可以 hook,不过是在 java 层调用时hook而不是 hook 动态链接库.
实战Hook android 中可能的出现 HTTP 请求
首先确定http 请求的 api,大致分为:
- apache 提供的 HttpClient
- 1) 创建 HttpClient 以及 GetMethod / PostMethod, HttpRequest等对象;
- 2) 设置连接参数;
- 3) 执行 HTTP 操作;
- 4) 处理服务器返回结果.
- java 提供的 HttpURLConnection
- 1) 创建 URL 以及 URLConnection / HttpURLConnection 对象
- 2) 设置连接参数
- 3) 连接到服务器
- 4) 向服务器写数据
- 5) 从服务器读取数据
- android 提供的 webview
- 第三方库:volley/android-async-http/xutils (本质是对前两种的方式的延伸,方法的重写可能对接下来的 hook 产生影响)
不太了解 java 的 hook 前可以先看下基础的代码HttpClient以及HttpURLConnection的基本使用
对 HttpClient的 hook 可以参考 贾志军大牛的Zjdroid
#!javaMethod executeRequest = RefInvoke.findMethodExact("org.apache.http.impl.client.AbstractHttpClient", ClassLoader.getSystemClassLoader(),"execute", HttpHost.class, HttpRequest.class, HttpContext.class);hookhelper.hookMethod(executeRequest, new AbstractBahaviorHookCallBack() {@Overridepublic void descParam(HookParam param) {// TODO Auto-generated method stubLogger.log_behavior("Apache Connect to URL ->");HttpHost host = (HttpHost) param.args[0];HttpRequest request = (HttpRequest) param.args[1];if (request instanceof org.apache.http.client.methods.HttpGet) {org.apache.http.client.methods.HttpGet httpGet = (org.apache.http.client.methods.HttpGet) request;Logger.log_behavior("HTTP Method : " + httpGet.getMethod());Logger.log_behavior("HTTP GET URL : " + httpGet.getURI().toString());Header[] headers = request.getAllHeaders();if (headers != null) {for (int i = 0; i < headers.length; i++) {Logger.log_behavior(headers[i].getName() + ":" + headers[i].getName());}}} else if (request instanceof HttpPost) {HttpPost httpPost = (HttpPost) request;Logger.log_behavior("HTTP Method : " + httpPost.getMethod());Logger.log_behavior("HTTP URL : " + httpPost.getURI().toString());Header[] headers = request.getAllHeaders();if (headers != null) {for (int i = 0; i < headers.length; i++) {Logger.log_behavior(headers[i].getName() + ":" + headers[i].getValue());}}HttpEntity entity = httpPost.getEntity();String contentType = null;if (entity.getContentType() != null) {contentType = entity.getContentType().getValue();if (URLEncodedUtils.CONTENT_TYPE.equals(contentType)) {try {byte[] data = new byte[(int) entity.getContentLength()];entity.getContent().read(data);String content = new String(data, HTTP.DEFAULT_CONTENT_CHARSET);Logger.log_behavior("HTTP POST Content : " + content);} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else if (contentType.startsWith(HTTP.DEFAULT_CONTENT_TYPE)) {try {byte[] data = new byte[(int) entity.getContentLength()];entity.getContent().read(data);String content = new String(data, contentType.substring(contentType.lastIndexOf("=") + 1));Logger.log_behavior("HTTP POST Content : " + content);} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}else{byte[] data = new byte[(int) entity.getContentLength()];try {entity.getContent().read(data);String content = new String(data, HTTP.DEFAULT_CONTENT_CHARSET);Logger.log_behavior("HTTP POST Content : " + content);} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}@Overridepublic void afterHookedMethod(HookParam param) {// TODO Auto-generated method stubsuper.afterHookedMethod(param);HttpResponse resp = (HttpResponse) param.getResult();if (resp != null) {Logger.log_behavior("Status Code = " + resp.getStatusLine().getStatusCode());Header[] headers = resp.getAllHeaders();if (headers != null) {for (int i = 0; i < headers.length; i++) {Logger.log_behavior(headers[i].getName() + ":" + headers[i].getValue());}}}}});
复制代码
对 HttpURLConnection 的 hook Zjdroid 未能提供完美的解决方案,想要取得除了 URL 之外的 data 字段必须对I/O流操作.
#!javaMethod openConnectionMethod = RefInvoke.findMethodExact("java.net.URL", ClassLoader.getSystemClassLoader(), "openConnection");hookhelper.hookMethod(openConnectionMethod, new AbstractBahaviorHookCallBack() {@Overridepublic void descParam(HookParam param) {// TODO Auto-generated method stubURL url = (URL) param.thisObject;Logger.log_behavior("Connect to URL ->");Logger.log_behavior("The URL = " + url.toString());}});
复制代码
我采取的临时解决方法是对I/O 进行正则匹配,类似 url 的 data 字段就打印出来,代码如下(这段代码只能解决前文 HttpUtils而且会有误报,大家有啥好想法欢迎指点一二)
#!javafindAndHookMethod("java.io.PrintWriter", lpparam.classLoader, "print",String.class, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {String print = (String) param.args[0];Pattern pattern = Pattern.compile("(\\w+=.*)");Matcher matcher = pattern.matcher(print);if (matcher.matches())Log.i(tag+lpparam.packageName,"data : " + print);//Log.d(tag,"A :" + print);}});
复制代码
因为Android-async-http重写了 HttpGet 导致 Zjdroidhook 失败(未进入 HttpGet 和 HttpPost 的判读),加入一个else 语句就可以解决这个问题
#!java
else {HttpEntityEnclosingRequestBase httpGet = (HttpEntityEnclosingRequestBase) request;HttpEntity entity = httpGet.getEntity();Logger.log_behavior("HttpRequestBase URL : " + httpGet.getURI().toString());Header[] headers = request.getAllHeaders();if (headers != null) {for (int i = 0; i < headers.length; i++) {Logger.log_behavior(headers[i].getName() + ":" + headers[i].getName());}}if(entity!= null){try {String content = EntityUtils.toString(entity);Logger.log_behavior("HTTP entity Content : "+ content);} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
复制代码
一些常用工具
- zjdroid:脱壳/api监控
- justTrustMe:忽略证书效验
- IntentMonitor:可以监控显/隐意图 intent
- Xinstaller:设置应用/设备属性...
- XPrivacy:权限管理
Android.Hook框架xposed篇(Http流量监控)相关推荐
- Android Hook框架Xposed进阶
上一篇<Android Hook框架Xposed入门>,我们对xposed进行简单的介绍并hook自己写的登录app.这次我们对xposed进行深入的了解并hook系统应用和第三方应用. ...
- Android.Hook框架Cydia篇(脱壳机制作)
瘦蛟舞 · 2015/08/17 14:53 注:框架有风险,使用要谨慎. Cydia Substrate是一个代码修改平台.它可以修改任何主进程的代码,不管是用Java还是C/C++(native代 ...
- Android应用防xposed注入,android hook 框架 xposed 如何实现注入
转:http://www.cnblogs.com/jiayy/p/4305018.html 前面分析的adbi框架和libinject都是使用so注入的方式,实现将指定代码装入目标进程,这种方式有几个 ...
- 面试:Hook框架Xposed、Dexposed、Epic原理
Xposed.Dexposed.Epic对比总结: 1.Xposed框架是需要root的,他的功能很全,能够hook掉系统方法,同时也可以hook掉其他应用的一些方法. 2.Dexposed框架是不需 ...
- android hook 程序,Android hook框架之Xposed插件开发
上一篇讲了Android hook框架Cydia,这一篇是Android hook的另一个框架Xposed,Xposed是一款广泛应用于安卓领域的开源框架. 其原理是Xposed框架主要通过替换/sy ...
- 全能Android HOOK框架 JNI NATIVE JAVA ART DALVIK
OneHook 目前比较流行的几个安卓HOOK方案,都有功能上的欠缺,有的不支持art模式,有的不支持jni层,有的不支持侵入HOOK. 所以OneHook诞生了! 这是一个同时支持ART和Dalvi ...
- android hook之 xposed检测
注意:原文中第3个方法"检测并不应该native的native方法"没有实现. 检测代码如下: import java.io.BufferedReader; import java ...
- android hook技术-Xposed框架 帮你轻松应对支付宝2016晒账单
一.支付宝2016年账单. 最近几天微信朋友圈充斥着各式的支付宝2016账单,对于程序员屌丝来说打开发现年度消费9W+,和他们动辄十几万的消费没得比,细看更有80%的消费还都是还信用卡,顿时万念俱灰啊 ...
- Xposed Android hook框架入门 -开发步骤
原理 Xposed替换了/system/bin/app_process可执行文件,在启动Zygote时加载额外的jar文件(/data/data/de.robv.android.xposed.inst ...
最新文章
- 在IIS中删除ETag的方法
- 使用ultramon调整任务栏高度
- 安卓ps2模拟器_安卓PSP模拟器评测:合金装备 和平步行者
- java关键字 valotile_Java内存模型-jsr133规范介绍,java中volatile关键字的含义
- 强连通图 Tarjan算法
- 什么样的人才容易被骗?
- 23、jQuery九类选择器/jQuery常用Method-API/jQuery常用Event-API
- java 缓存ech_java ehcache 分布式缓存配置实例 .
- 基础03 JVM到底在哪里?
- 知名公司GitHub官网
- 易达园林注册机_科创易达园林绿化插件免费版
- 自适应弹出框-垂直居中
- 十年外贸人的心得:开发国外客户的正确思路和方法
- 计算机二级请假条,单位员工病假请假条范文模板
- 《点燃你,温暖我》 李询爱心代码
- Ubuntu软件仓库源类型:官方源、第三方源、本地源
- 一个c程序的执行是从什么开始的?
- WordPress DUX5.0大前端主题模板
- JSP众筹管理系统myeclipse开发sql数据库web结构计算机java编程
- 计算机领域最新技术视频,浅析计算机技术在视频编辑领域的应用