前段時間做了個游戲內購xposed 插件,但是當前的游戲部分都加殼了,並且最新的游戲支付sdk也進行加密了,這樣就尷尬了
於是到網上搜索了下:看到"非蟲"大大在看雪上發的部分代碼如何hook 360加固的應用:原帖貌似被刪了,在網上找了部分代碼
鏈接地址:http://www.jianshu.com/p/0d74461ea199
大概原理:拿到殼的ClassLoader 然后再根據殼的ClassLoader 拿到對應的Class 然后在hook
if (loadPackageParam.packageName.equals("com.package.name")) {
XposedHelpers.findAndHookMethod("com.qihoo.util.StubAppxxxxxxxx", loadPackageParam.classLoader,
"getNewAppInstance", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Context context = (Context) param.args[0];
ClassLoader classLoader =context.getClassLoader();
XposedHelpers.findAndHookMethod("com.amap.api.location.AMapLocation", classLoader, "getLongitude", new XC_MethodHook(){
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
param.setResult(123.123123);
}
});
XposedHelpers.findAndHookMethod("com.amap.api.location.AMapLocation", classLoader, "getLatitude", new XC_MethodHook(){
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
param.setResult(33.333333);
}
});
}
});
}
根據這個原理 查看xposed源碼 XposedHelpers.findAndHookMethod方法
public static Unhook findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) {
return findAndHookMethod(findClass(className, classLoader), methodName, parameterTypesAndCallback);
}
在查看:其中findclass方法
public static Class<?> findClass(String className, ClassLoader classLoader) {
if(classLoader == null) {
classLoader = XposedBridge.BOOTCLASSLOADER;
}
try {
return ClassUtils.getClass(classLoader, className, false);
} catch (ClassNotFoundException var3) {
throw new XposedHelpers.ClassNotFoundError(var3);
}
}
也就是通過ClassLoader 加載Class 然后在進行hook,想到一個辦法就是
在類加載的時候進行hook
對於加固的應用 xposed 拿到的Classloader 不一定能加載到Class
於是根據android 源碼 加載Class用到的一個是BootClassLoader(系統啟動的時候創建的),另一個是PathClassLoader(應用啟動時創建的),所以只用看PathClassLoader的源碼
public class PathClassLoader extends BaseDexClassLoader
接着看BaseDexClassLoader
public class BaseDexClassLoader extends ClassLoader {
private final DexPathList pathList;
/**
* Constructs an instance.
*
* @param dexPath the list of jar/apk files containing classes and
* resources, delimited by {@code File.pathSeparator}, which
* defaults to {@code ":"} on Android
* @param optimizedDirectory directory where optimized dex files
* should be written; may be {@code null}
* @param libraryPath the list of directories containing native
* libraries, delimited by {@code File.pathSeparator}; may be
* {@code null}
* @param parent the parent class loader
*/
public BaseDexClassLoader(String dexPath, File optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(parent);
this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
Class c = pathList.findClass(name, suppressedExceptions);
if (c == null) {
ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
for (Throwable t : suppressedExceptions) {
cnfe.addSuppressed(t);
}
throw cnfe;
}
return c;
}
//......
}
於是一路分析下去:
得到:BaseDexClassLoader.findClass(String name)
----->DexPathList.findClass(String name, List<Throwable> suppressed)
----->DexFile.loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed)
---->DexFile.defineClass(String name, ClassLoader loader, Object cookie,List<Throwable> suppressed)
---->defineClassNative(name, loader, cookie);
defineClassNative(name, loader, cookie);方法為native方法 xposed 無法hook
最后如果給想在類加載完成時進行hook那么就要在DexFile.defineClass(String name, ClassLoader loader, Object cookie,List<Throwable> suppressed)這個方法上做文章:
使用xposed hook dalvik.system.DexFile.defineClass方法在然后在hook 后方法里進行過濾拿到想要的Class
public void hookDefineClass() {
try {
/*get DexFile Class*/
Class clazz = loadPackageParam.classLoader.loadClass("dalvik.system.DexFile");
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
String name = methods[i].getName();
if (name.equalsIgnoreCase("defineClass")) {
hookhelper.hookMethod(methods[i], new MethodHookCallBack() {
@Override
public void beforeHookedMethod(HookParam param) throws IOException, ClassNotFoundException {
}
@Override
public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, JSONException {
//ClassName
String ClassName = (String) param.args[0];;
if(ClassName.equalsIgnoreCase("xxxx")){
//here do something
//get Class
Class clazz = (Class) param.getResult();
// do something you want
XposedHelpers.findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)
}
}
});
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
一個例子(由於使用自己封裝的xposed方法):
UnicomPay.java(聯通支付sdk)
package com.xiaobai.viptools.xposedpay;
import com.xiaobai.viptools.impl.PayOrderHook;
import com.xiaobai.viptools.xposed.HookParam;
import com.xiaobai.viptools.xposed.MethodHookCallBack;
import java.io.IOException;
import java.lang.reflect.Method;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
*
* Created by xiaobai on 2017/2/3.
*/
public class UnicomPay implements PayOrderHook {
private XC_LoadPackage.LoadPackageParam lpparam;
public UnicomPay(XC_LoadPackage.LoadPackageParam loadPackageParam) {
this.lpparam = loadPackageParam;
}
@Override
public void Hookpay(Class clazz) throws ClassNotFoundException {
Method[] methods=clazz.getMethods();
for (int i = 0; i <methods.length; i++) {
String name=methods[i].getName();
if (name.equalsIgnoreCase("pay")){
Method paymethod=methods[i];
HookPayMethond(paymethod);
}
}
}
private void HookPayMethond(Method method){
hookhelper.hookMethod(method, new MethodHookCallBack() {
@Override
public void beforeHookedMethod(HookParam param) throws IOException {
XposedBridge.log("paymethod arg size:"+param.args.length);
Class clazz= param.args[param.args.length-1].getClass();
HookPayresult(clazz);
}
@Override
public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
}
});
}
private void HookPayresult(Class clazz){
Method[] methods=clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equalsIgnoreCase("PayResult")){
hookhelper.hookMethod(methods[i], new MethodHookCallBack() {
@Override
public void beforeHookedMethod(HookParam param) throws IOException {
XposedBridge.log("arg[1]:code "+param.args[1]);
param.args[1]=1;
XposedBridge.log("payhook success");
}
@Override
public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
}
});
}
}
}
}
HookPayMethod.java
package com.xiaobai.viptools.XposedModule;
import android.content.Context;
import com.xiaobai.viptools.helper.JsonHelper;
import com.xiaobai.viptools.impl.HookHelperInterface;
import com.xiaobai.viptools.util.ContextHolder;
import com.xiaobai.viptools.xposed.HookHelperFacktory;
import com.xiaobai.viptools.xposed.HookParam;
import com.xiaobai.viptools.xposed.MethodHookCallBack;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
* Created by xiaobai on 2017/2/3.
*/
public class HookPayMethod {
private XC_LoadPackage.LoadPackageParam loadPackageParam;
private HookHelperInterface hookhelper = HookHelperFacktory.getHookHelper();
public HookPayMethod(XC_LoadPackage.LoadPackageParam loadPackageParam) {
this.loadPackageParam = loadPackageParam;
}
/*針對加殼app hook defineclass 過濾app*/
public void hookDefineClass() {
try {
/*獲取DexFile Class*/
Class clazz = loadPackageParam.classLoader.loadClass("dalvik.system.DexFile");
Method[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
String name = methods[i].getName();
if (name.equalsIgnoreCase("defineClass")) {
hookhelper.hookMethod(methods[i], new MethodHookCallBack() {
@Override
public void beforeHookedMethod(HookParam param) throws IOException, ClassNotFoundException {
}
@Override
public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, JSONException {
selectPayMethod(param);
}
});
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void selectPayMethodDebug(HookParam param) throws ClassNotFoundException {
String ClassName = (String) param.args[0];
// System.out.println(ClassName);
if (unicompay && ClassName.equalsIgnoreCase("com.unicom.dcLoader.Utils")) {
Class PayClass = (Class) param.getResult();
UnicomPay unicomPay = new UnicomPay(loadPackageParam);
unicomPay.Hookpay(PayClass);
}
}
}
對付簡單的加固應該沒問題:有任何問題聯系:xiaobaiyey@outlook.com
