找回密码
 立即注册
注册 登录
×
热搜: 活动 交友 discuz
查看: 153|回复: 11

Android APK脱壳--腾讯乐固、360加固一键脱壳

[复制链接]

1

主题

1

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2022-9-24 07:35:09 | 显示全部楼层 |阅读模式
概述

现在使用Proguard进行混淆的代码,也很容易被破解,所以就出现了加固工具,让反编译的难度更大。但是有了加固技术,就会有反加固技术,正所谓道高一尺魔高一丈。
经过加固后的apk,通过dex2jar反编译:
腾讯乐固:


360加固:


从上面可以看出,经过加固后的apk,通过常规方法反编译无法获取到源码。
下载工具

脱壳工具FDex2

通过Hook ClassLoader的loadClass方法,反射调用getDex方法取得Dex(com.android.dex.Dex类对象),在将里面的dex写出。
下载地址:
链接:https://pan.baidu.com/s/1smxtinr 密码:dk4v
VirtualXposed

VirtualXposed:无需root手机即可使用xp框架。
下载地址:
https://vxposed.com/
脱壳

Step1:
将VirtualXposed、FDex2和需要脱壳的应用都安装到手机上。
Step2:
启动VirtualXposed,并在VirtualXposed中安装FDex2:


Step3:
在VirtualXposed中激活FDex2:


Step4:
在VirtualXposed中安装要脱壳的应用,方法和Step2一样。
Step5:
启动VirtualXposed中的FDex2,并配置要脱壳的应用。


Step6:
在VirtualXposed中运行要脱壳的应用。
Step7:
脱壳后的dex文件:


导出脱壳的dex文件:
root设备:
adb root
adb pull /data/user/0/iv.va.exposed/virtual/data/user/0/{packageName}   {电脑上的目录}未root设备:
在VirtualXposed中,设置-->高级设置-->文件管理,安装文件管理器,然后通过文件管理器进入到指定的目录,通过分享功能发到电脑上。
Step8:
通过dex2jar对 脱壳的dex进行反编译:


从上图就可以看到脱壳后的dex文件被成功的反编译。
FDex2核心代码MainHook

package com.ppma.xposed;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XSharedPreferences;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class MainHook implements IXposedHookLoadPackage {

    XSharedPreferences xsp;
    Class Dex;
    Method Dex_getBytes;
    Method getDex;
    String packagename;


    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        xsp = new XSharedPreferences("com.ppma.appinfo", "User");
        xsp.makeWorldReadable();
        xsp.reload();
        initRefect();
        packagename = xsp.getString("packagename", null);
        XposedBridge.log("设定包名:"+packagename);
        if ((!lpparam.packageName.equals(packagename))||packagename==null) {
            XposedBridge.log("当前程序包名与设定不一致或者包名为空");
            return;
        }
        XposedBridge.log("目标包名:"+lpparam.packageName);
        String str = "java.lang.ClassLoader";
        String str2 = "loadClass";

        XposedHelpers.findAndHookMethod(str, lpparam.classLoader, str2, String.class, Boolean.TYPE, new XC_MethodHook() {
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Class cls = (Class) param.getResult();
                if (cls == null) {
                    //XposedBridge.log("cls == null");
                    return;
                }
                String name = cls.getName();
                XposedBridge.log("当前类名:" + name);
                byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]);
                if (bArr == null) {
                    XposedBridge.log("数据为空:返回");
                    return;
                }
                XposedBridge.log("开始写数据");
                String dex_path = "/data/data/" + packagename + "/" + packagename + "_" + bArr.length + ".dex";
                XposedBridge.log(dex_path);
                File file = new File(dex_path);
                if (file.exists()) return;
                writeByte(bArr, file.getAbsolutePath());
            }
            } );
    }

    public void initRefect() {
        try {
            Dex = Class.forName("com.android.dex.Dex");
            Dex_getBytes = Dex.getDeclaredMethod("getBytes", new Class[0]);
            getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }

    public  void writeByte(byte[] bArr, String str) {
        try {
            OutputStream outputStream = new FileOutputStream(str);
            outputStream.write(bArr);
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            XposedBridge.log("文件写出失败");
        }
    }
}参考链接


  • 【手机端】腾讯乐固,360加固一键脱壳
  • 安卓xposed脱壳工具FDex2
回复

使用道具 举报

0

主题

6

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2022-9-24 07:35:34 | 显示全部楼层
很不错,目前看来,切实可以脱壳。设备如果没有root 的话不能获取到 dex。如果 dex 可以放到普通用户可以访问到的目录的话就完美了。可以写一篇文章分析享一下其中的原理吗?
回复

使用道具 举报

0

主题

2

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-9-24 07:36:30 | 显示全部楼层
在vivo NEX s 中的VirtualXposed上运行FDex2失败,"这台设备不支持本软件"。。。
[疑惑]
回复

使用道具 举报

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-9-24 07:36:43 | 显示全部楼层
脱壳时间很长
回复

使用道具 举报

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-9-24 07:36:57 | 显示全部楼层
安卓模拟器都不支持这玩意
回复

使用道具 举报

0

主题

2

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2022-9-24 07:37:51 | 显示全部楼层
没有root的设备是分享不了的, 请问有解决方案吗
回复

使用道具 举报

2

主题

3

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2022-9-24 07:38:50 | 显示全部楼层
进入Xpposed 后点击下方的那个圆形按键,点击高级设置,点击文件管理,安装Amase,在Xposed里运行Amaze,在Amaze的左边的侧滑栏里点击,Private Storage,按照之前Fdex显示的路径找到dex,点击item右边的那个更多按钮,点击复制,再点击左边侧滑栏的External Storage,选择某个路径,点击顶部的那个像记事本一样的按钮,就复制到该目录下了,然后点击item右边的更多按钮,我用分享里的蓝牙分享出去的。我用的是一加5的救砖rom,也没root的。
回复

使用道具 举报

2

主题

4

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2022-9-24 07:39:26 | 显示全部楼层
Android版本的问题吧,这个只能弄到Android7,8是不行的
回复

使用道具 举报

0

主题

5

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2022-9-24 07:40:20 | 显示全部楼层
好的,谢谢,我试试
回复

使用道具 举报

0

主题

3

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2022-9-24 07:41:19 | 显示全部楼层
感谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋| 黑客通

GMT+8, 2025-4-7 18:17 , Processed in 0.984268 second(s), 73 queries .

Powered by Discuz! X3.4

Copyright © 2020, LianLian.

快速回复 返回顶部 返回列表