一、前言
我于2019年5月3号写下本文,今天正好是劳动节,故在此祝各位劳动节快乐,然后呢我来讲一下本文,我呢学习逆向方面没有多久但总归还是有点收获的,于是我就想把我学到的Android逆向Hook方面的知识和技巧分享给大家。我准备分为四篇:Xposed、Cydia Substrate、Android inline hook和FrIDA。同时也请大家指出我的不正确的地方或者补充于你的技巧和知识
Android逆向Hook学习系列:
第一篇:Xposed;第一篇:Android inline Hook;第三篇:Frida(待添加)
二、正文
2.1、Xposed原理介绍
Xposed是一款特殊的Android应用,通过替换system\bin\下面的的app_process等文件来控制zygote进程,进而实现控制手机上所有的app进程;缺点就是不能hook应用的so中的函数。
2.2、Xposed安装
Xposed的GitHub地址:https://github.com/rovo89/XposedInstaller
环境:OPPO R11、Android Studio3.3.1、Java1.8.0_201 注:可以使用模拟器、但是Android4.0-4.4和Android5.0以上的Android系统安装的版本是不同的
Xposedinstaller的apk下载页面:https://repo.xposed.info/module/de.robv.android.xposed.installer
下载完APK安装后,刷入Xposed框架,如果成功就会是我这样子。如果你已经成功了,那么你就推开了Xposed的大门
2.3、Xposed代码的编写
新建一个项目,请注意如果你只是hook,那么可以选择add no activity,但是如果有和自身app交互,那么就选择empty activity。我为了给大家演示,是有展示的,所以我选择empty activity。
创建成功后找到AndroidManifest,xml,在文件里面添加如下代码。
第一个xposedmodule的属性为ture,证明这是一个xposed的module;第二个xposeddescription,这是介绍项目的话语;第三个xposedminversion则是说明该xposedmodule所支持的最小版本,而最低版本就是30。
我们新建一个Java类并且继承接口IXposedHookLoadPackage和重写handleLoadPackage方法。
package com.yymjr.android.xposedproject;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
public class HookMain implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
}
}
在src/mian目录下添加一个assets目录,目录下添加一个xposed_init文件,里面的代码是你的Hook类的包名+类名。
而本项目就是:com.yymjr.android.xposedproject.HookMain。
编写MainActivity代码如下:
package com.yymjr.android.xposedproject;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.HelloWorldTV);
textView.setText(getInfmation());
}
private String getInfmation(){
return "666666666";
}
}
大家就可以看到结果就是这样子,而Hook代码我们现在写上。
package com.yymjr.android.xposedproject;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
public class HookMain implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if(!lpparam.packageName.equals("com.yymjr.android.xposedproject")) return;
XposedHelpers.findAndHookMethod("com.yymjr.android.xposedproject.MainActivity", lpparam.classLoader, "getInfmation", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
param.setResult("6666666");
}
});
}
}
重新编译,而且在XposedInstaller里面把该APP选上并且重启
2.4、Xposed技巧
注:paramTypes是指函数传参的类---来自一位不愿暴露的网友的提醒
1.通过Class.getName获取clazz。
XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
if (param.hasThrowable()) return;
Class> clazz = (Class>) param.getResult();
if (clazz.getName().equals("")){ //判断类名
XposedHelpers.findAndHookMethod(clazz, "methodName", paramTypes, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
});
}
}
});
2.通过Hook Application的attachBaseContext/onCreate/attach来获取DexClassLoader
XposedHelpers.findAndHookMethod(Application.class, "attch", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
if (param.hasThrowable()) return;
ClassLoader classLoader = ((Context) param.args[0]).getClassLoader();
XposedHelpers.findAndHookMethod("className", classLoader, "methodName", paramTypes, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
});
}
});
3.打印方法堆栈。
XposedHelpers.findAndHookMethod("className", lpparam.classLoader, "methodName", paramTypes, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
try {
throw new NullPointerException();
}catch (NullPointerException e) {
Log.getStackTraceString(e);
}
}
});
4.构造函数。 注:Jadx反编译apk后,看不出来是构造函数,直接hook将会导致classnotfound,使用apktool反编译打开smali文件。
本帖最后由 一夜梦惊人 于 2019-5-2 22:51 编辑
一、前言 我于2019年2月19号写下本文,今天正好是元宵节,故在此祝各位元宵节快乐,新的一年里万事如意、步步高升和发大财!然后呢我来讲一下本文,我呢学习逆向方面没有多久但总归还是有点收获的,于是我就想把我学到的Android逆向Hook方面的知识和技巧分享给大家。我准备分为四篇:Xposed、Cydia Substrate、Android inline hook和FrIDA。同时也请大家指出我的不正确的地方或者补充于你的技巧和知识(我将会说明于你的论坛ID) Android逆向Hook学习系列: 第一篇:Xposed;第一篇:Android inline Hook;第三篇:Frida(待添加) 二、正文 2.1、Xposed原理介绍 Xposed是一款特殊的Android应用,通过替换system\bin\下面的的app_process等文件来控制zygote进程,进而实现控制手机上所有的app进程;缺点就是不能hook应用的so中的函数。 2.2、Xposed安装 Xposed的GitHub地址:https://github.com/rovo89/XposedInstaller 环境:OPPO R11、Android Studio3.3.1、Java1.8.0_201 注:可以使用模拟器、但是Android4.0-4.4和Android5.0以上的Android系统安装的版本是不同的 Xposedinstaller的apk下载页面:https://repo.xposed.info/module/de.robv.android.xposed.installer 下载完APK安装后,刷入Xposed框架,如果成功就会是我这样子。如果你已经成功了,那么你就推开了Xposed的大门,但是任重而道远,还需努力!
2.3、Xposed代码的编写 新建一个项目,请注意如果你只是hook,那么可以选择add no activity,但是如果有和自身app交互,那么就选择empty activity。我为了给大家演示,是有展示的,所以我选择empty activity。
创建成功后找到AndroidManifest,xml,在文件里面添加如下代码。 [Java] 纯文本查看 复制代码 ?
1 2 3 4 5 6 7 8 9 |
android:name= "xposedmodule" android:value= "true" />
android:name= "xposeddescription" android:value= "XposedProject" />
android:name= "xposedminversion" android:value= "30" /> |
第一个xposedmodule的属性为ture,证明这是一个xposed的module;第二个xposeddescription,这是介绍项目的话语;第三个xposedminversion则是说明该xposedmodule所支持的最小版本,而最低版本就是30。
接下来找到buile.gradle(module:app)文件,在里面添加如下代码。 [Asm] 纯文本查看 复制代码 ?
1 2 3 |
compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82:sources' |
我们新建一个Java类并且继承接口IXposedHookLoadPackage和重写handleLoadPackage方法。 [Java] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 |
package com.yymjr.android.xposedproject; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookMain implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { } } |
在src/mian目录下添加一个assets目录,目录下添加一个xposed_init文件,里面的代码是你的Hook类的包名+类名。 而本项目就是:com.yymjr.android.xposedproject.HookMain。 编写MainActivity代码如下: [Java] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package com.yymjr.android.xposedproject; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.HelloWorldTV); textView.setText(getInfmation()); } private String getInfmation(){ return "吾爱破解论坛——by 一夜梦惊人" ; } } |
大家就可以看到结果就是这样子,而Hook代码我们现在写上。 [Java] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package com.yymjr.android.xposedproject; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookMain implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { if (!lpparam.packageName.equals( "com.yymjr.android.xposedproject" )) return ; XposedHelpers.findAndHookMethod( "com.yymjr.android.xposedproject.MainActivity" , lpparam.classLoader, "getInfmation" , new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super .afterHookedMethod(param); param.setResult( "破解成功——by 一夜梦惊人" ); } }); } } |
重新编译,而且在XposedInstaller里面把该APP选上并且重启。
成功破解! 2.4、Xposed技巧 注:paramTypes是指函数传参的类---来自一位不愿暴露的网友的提醒 1.通过Class.getName获取clazz。 [Java] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
XposedHelpers.findAndHookMethod(ClassLoader. class , "loadClass" , String. class , new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super .afterHookedMethod(param); if (param.hasThrowable()) return ; Class> clazz = (Class>) param.getResult(); if (clazz.getName().equals( "" )){ //判断类名 XposedHelpers.findAndHookMethod(clazz, "methodName" , paramTypes, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super .afterHookedMethod(param); } }); } } }); |
2.通过Hook Application的attachBaseContext/onCreate/attach来获取DexClassLoader。 来源:据说是非虫大佬提出的思路,无从查证。如若错误请指正。 参考:支付宝订单监控 [Java] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
XposedHelpers.findAndHookMethod(Application. class , "attch" , Context. class , new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super .afterHookedMethod(param); if (param.hasThrowable()) return ; ClassLoader classLoader = ((Context) param.args[ 0 ]).getClassLoader(); XposedHelpers.findAndHookMethod( "className" , classLoader, "methodName" , paramTypes, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super .afterHookedMethod(param); } }); } }); |
3.打印方法堆栈。 [Java] 纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 |
XposedHelpers.findAndHookMethod( "className" , lpparam.classLoader, "methodName" , paramTypes, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super .afterHookedMethod(param); try { throw new NullPointerException(); } catch (NullPointerException e) { Log.getStackTraceString(e); } } }); |
4.构造函数。 注:Jadx反编译apk后,看不出来是构造函数,直接hook将会导致classnotfound,使用apktool反编译打开smali文件。
看见constructor就可以知道这是一个构造函数,而构造函数则是不需要输入methodName的。 XposedHelpers.findAndHookConstructor("className", lpparam.classLoader, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
}); 5.免重启。 Xposed每次更新或者安装module都需要重启,本技巧就是免于重启。<该代码未经任何修改> /**
* @author DX
* 这种方案建议只在开发调试的时候使用,因为这将损耗一些性能(需要额外加载apk文件),调试没问题后,直接修改xposed_init文件为正确的类即可
* 可以实现免重启,由于存在缓存,需要杀死宿主程序以后才能生效
* 这种免重启的方式针对某些特殊情况的hook无效
* 例如我们需要implements IXposedHookZygoteInit,并将自己的一个服务注册为系统服务,这种就必须重启了
* Created by DX on 2017/10/4.
*/
public class HookLoader2 implements IXposedHookLoadPackage {
//按照实际使用情况修改下面几项的值
/**
* 当前Xposed模块的包名,方便寻找apk文件
*/
private final String modulePackage = "com.xxx.plugin";
/**
* 宿主程序的包名(允许多个),过滤无意义的包名,防止无意义的apk文件加载
*/
private static List hostAppPackages = new ArrayList<>();
static {
// TODO: Add the package name of application your want to hook!
hostAppPackages.add("com.eg.android.AlipayGphone");
hostAppPackages.add("com.xxx.plugin");
}
/**
* 实际hook逻辑处理类
*/
private final String handleHookClass = TargetHook.class.getName();
/**
* 实际hook逻辑处理类的入口方法
*/
private final String handleHookMethod = "handleLoadPackage";
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (hostAppPackages.contains(loadPackageParam.packageName)) {
//将loadPackageParam的classloader替换为宿主程序Application的classloader,解决宿主程序存在多个.dex文件时,有时候ClassNotFound的问题
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Context context=(Context) param.args[0];
loadPackageParam.classLoader = context.getClassLoader();
invokeHandleHookMethod(context,modulePackage, handleHookClass, handleHookMethod, loadPackageParam);
}
});
}
}
/**
* 安装app以后,系统会在/data/app/下备份了一份.apk文件,通过动态加载这个apk文件,调用相应的方法
* 这样就可以实现,只需要第一次重启,以后修改hook代码就不用重启了
* @param context context参数
* @param modulePackageName 当前模块的packageName
* @param handleHookClass 指定由哪一个类处理相关的hook逻辑
* @param loadPackageParam 传入XC_LoadPackage.LoadPackageParam参数
* @throws Throwable 抛出各种异常,包括具体hook逻辑的异常,寻找apk文件异常,反射加载Class异常等
*/
private void invokeHandleHookMethod(Context context, String modulePackageName, String handleHookClass, String handleHookMethod, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
File apkFile=findApkFile(context,modulePackageName);
if (apkFile==null){
throw new RuntimeException("寻找模块apk失败");
}
//加载指定的hook逻辑处理类,并调用它的handleHook方法
PathClassLoader pathClassLoader = new PathClassLoader(apkFile.getAbsolutePath(), ClassLoader.getSystemClassLoader());
Class> cls = Class.forName(handleHookClass, true, pathClassLoader);
Object instance = cls.newInstance();
Method method = cls.getDeclaredMethod(handleHookMethod, XC_LoadPackage.LoadPackageParam.class);
method.invoke(instance, loadPackageParam);
}
/**
* 根据包名构建目标Context,并调用getPackageCodePath()来定位apk
* @param context context参数
* @param modulePackageName 当前模块包名
* @return return apk file
*/
private File findApkFile(Context context, String modulePackageName){
if (context==null){
return null;
}
try {
Context moudleContext = context.createPackageContext(modulePackageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
String apkPath=moudleContext.getPackageCodePath();
return new File(apkPath);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
} 6.主动调用函数。 提醒:@$喂人民服雾 参考:Xposed模块编写那些事--https://www.freebuf.com/articles/terminal/114910.html Class> clazz = XposedHelpers.findClass("className",lpparam.classLoader);
XposedHelpers.callMethod(clazz.newInstance(),"methodName",paramTypes, paramValue); |
注:第一个参数是hook类的对象,在本代码获取了类,但是没有实例化,所以调用newInstance;paramValue是传入参数的值。
7.内部类(inner_class)hook
首先获取class,而内部类则是用$连接。
XposedHelpers.findAndHookMethod("className$inner_class", lpparam.classLoader, "methodName", paramTypes, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
});
8.调用静态函数
Class[] clazz = new Class[1];
clazz[0] = Clazz;
XposedHelpers.callStaticMethod(XposedHelpers.findClass("[/size][/font][font=黑体][size=3]className[/size][/font][font=黑体][size=3]", classLoader),
"[/size][/font][font=黑体][size=3]methodName[/size][/font][font=黑体][size=3]",[/size][/font][/align][align=left][font=黑体][size=3] clazz,
[/size][/font][font=黑体][size=3]paramValue[/size][/font][font=黑体][size=3]);
请注意这里如果要传入参数的Clazz,请传为数组类,而参数的值则是可变,否则将会出错!
三、后言
本贴来源转载,如有违规请联系删帖!!!
×
注意!
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。