腾讯加固脱壳使用事例

概述

本文只介绍具体的原理和实现,不涉及Xposed相关技术点。想要了解Xposed具体配置和实现的请参考Xposed的配置与简单使用

直接反编译apk

apk-jadx

脱壳工具FDex2

fdex2
dexpath

脱壳流程

第一步、激活

FDex2和需要脱壳的应用都安装到手机上。在Xposed install模块中勾选FDex2,重启手机。

第二步、选择软件

然后打开FDex2应用,在应用列表中选择需要脱壳的应用,保存dex即可。

第三步、运行软件

运行要脱壳的软件,不打开运行软件是无法脱出壳的

第四步、dex目录

找到dex目录,这里的dex就是脱壳后的dex文件,也就是我即将hook的dex文件。目录一般是/data/user/0/com.luhu.package.xxx。

hook过程

由于被腾讯加固,所以第一步是需要获取对应ClassLoader;在之后的逆向过程中使用的ClassLoader都是这个ClassLoader。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if(lpparam.packageName.startsWith("com.luhu.livexiuwu")){
try {
//腾讯加固,需要获取对应classloader
XposedHelpers.findAndHookMethod("com.tencent.StubShell.TxAppEntry", lpparam.classLoader,
"attachBaseContext", Context.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
//获取到Context对象,通过这个对象来获取classloader
Context context = (Context) param.args[0];
//获取classloader,之后hook加固后的就使用这个classloader
SecApp.hookLuhu(lpparam,context.getClassLoader());


}

});
}catch (Exception e){
}

}

脱壳原理

通过Hook ClassLoader的loadClass方法,反射调用getDex方法取得Dex(com.android.dex.Dex类对象),在将里面的dex写出。
脱壳获取dex的关键代码:

1
2
3
4
5
6
7
8
9
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private static  void fDex(XC_LoadPackage.LoadPackageParam loadPackageParam2){

if(loadPackageParam2.packageName.equals("com.luhu.livexiuwu")){

try {
Class Dex=Class.forName("com.android.dex.Dex");
Method Dex_getBytes=Dex.getDeclaredMethod("getBytes", new Class[0]);
Method getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]);


XposedHelpers.findAndHookMethod("java.lang.ClassLoader", loadPackageParam2.classLoader, "loadClass", String.class,boolean.class,new XC_MethodHook(){
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {

Class cls = (Class) param.getResult();


if (cls != null) {

try {
byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]);


if (bArr != null) {

File apkFileDir = new File(CompatUtil.getSdcardSharedDir(), "lulu");

if (!apkFileDir.exists()) {
apkFileDir.mkdirs();
}

String name = "com.luhu.livexiuwu"+bArr.length+".dex";
File file2 = new File(apkFileDir, name);

if (!file2.exists()) {
FileUtil.writeToFileBy(bArr, file2);
}
}
} catch (Exception e3) {

}

}
}
});
} catch (Throwable e) {
XposedBridge.log(e);

}
}
}

参考资料

java and android 架构