一个基于xposed和inline hook的一代壳脱壳工具

注:

1.手机要api  21版本以上xposed要支持art模式才可以,手机脱壳时要在art模式下

2.E/Xposed(28813):  java.lang.UnsatisfiedLinkError:  dlopen  failed:  couldn't  map ;/data/local/tmp/libhook.so;  segment  1:  Permission  denied

setenforce  0是这个保护问题

转:http://bbs.pediy.com/thread-218936.htm

1. 我为啥要写这个工具

虽然一代壳比较古老了,但是市面上还是比较多。用ida脱的话有点累。然后我就写了个xposed插件,来快速的帮我们完成脱壳。(这种方法比较省事,不用去修改系统什么的,也不用动态调试)

2. 原理

原理就是去hook libart.so里面的art::DexFile::OpenMemory,然后再把内存中的dex写到文件中去。就是这么简单,最主要的就是hook的时机,大部分的壳都是在attachBaseContext这个方法里面去完成代码的解密。所以呢,我们就去hook Application的attach方法,在这个方法执行之前,将我们的动态库加载起来,动态库里面实现的就是对art::DexFile::OpenMemory方法的劫持。这样的话在他解密代码前art::DexFile::OpenMemory就已经被我们给控制了,所以就可以为所欲为了。这里要感谢ele7enxxh提供的Android-Inline-Hook来让我可以对native层的hook。

3. 需要怎么改才能脱抽类壳

略。(你现在都能够hook native层和java层了,那你就可以为所欲为了)

4. 怎么使用的

首先下载libhook.so和xposed插件的apk文件,然后把libhook.so放到/data/local/tmp下面,并且改权限为777.然后安装xposed插件,重启并且激活插件。之后去xposed插件的界面里面去勾选需要脱壳的apk。选好之后干掉你要脱壳的应用的进程,然后重新打开你需要脱壳的应用的进程,脱壳成功的话就会在/data/data/应用包名 下生产脱下的dex文件



5. 源码

https://github.com/smartdone/dexdump

上传的附件:

问题一:

/data/local/tmp/libhook.so;  segment  1:  Permission  denied; 这个是文件路径权限文件,换一个帅一点儿的姿势:
        XposedHelpers.findAndHookMethod("dalvik.system.BaseDexClassLoader", ClassLoader.getSystemClassLoader(), "findLibrary", String.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                Log.i("weijia", "加载lib" + (String) param.args[0]);
                if (HOOKLIB.equals(param.args[0]) && param.getResult() == null) {
                    param.setResult("/data/data/com.smartdone.dexdump/lib/lib" + HOOKLIB + ".so");
                }
            }
        });

这段代码,参考ZJDroid,不会出问题

问题二
小米5安卓6打开没程序列表,
 private void getInstallAppList() {
        try {
            List<PackageInfo> packageInfos = getPackageManager().getInstalledPackages(0);
            for (PackageInfo packageInfo : packageInfos) {
                if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 && (!StringUtils.equals(packageInfo.packageName, "com.smartdone.dexdump"))) {
                    Appinfo info = new Appinfo();
                    info.setIcon(zoomDrawable(packageInfo.applicationInfo.loadIcon(getPackageManager()), DensityUtil.dip2px(this, 128), DensityUtil.dip2px(this, 128)));
                    info.setAppName(packageInfo.applicationInfo.loadLabel(getPackageManager()).toString());
                    info.setAppPackage(packageInfo.packageName);
                    if (XSharePreferenceConfig.contains(selected, info.getAppPackage())) {
                        info.setChecked(true);
                    } else {
                        info.setChecked(false);
                    }
                    appinfos.add(info);
                }
            }
            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //原工程少了这一步,可能导致数据无法刷新
                    adapter.notifyDataSetChanged();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

嗯,model更新后,记得notify


问题3,

你可能还会遇到,可能选择要脱壳,然后等会取消选择,然后划一下页面,再然后取消选择的又出现了。
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    appinfos.get(posi).setChecked(b);
                    if (b) {
                        xSharePreferenceConfig.addOne(appinfos.get(posi).getAppPackage());
                        //Config.addOne(appinfos.get(posi).getAppPackage(), MainActivity.this);
                    } else {
                        xSharePreferenceConfig.removeOne(appinfos.get(posi).getAppPackage());
                        //Config.removeOne(appinfos.get(posi).getAppPackage(), MainActivity.this);
                    }
                }
需要同步修改model的数据。否则view销毁重建,拿内存的数据不是最新的。
问题4.
可能遇到没有sdcard权限问题。不是所有的app都申请了sdcard权限,这样会崩溃。如何解?
/**
 * Created by virjar on 2018/2/24.<br>
 * 原方案,在宿主apk无sd卡权限时,无法hook无法读取配置,所以使用XSharePreference来处理多apk配置通信问题,这是因为shardPreference可以开放读取权限,绕开了不同app私有文件通信问题
 */
 
class XSharePreferenceConfig {
    private static final String pluginPackage = "com.smartdone.dexdump";
    private static final String configName = "dumpapps";
    //可写的XSharedPreferences对象,这个可以使用在插件自己的apk里面使用
    private SharedPreferences writeXSharedPreferences = null;
    //只读的XSharedPreferences,这个可以让插件在宿主里面访问
    private SharedPreferences readXSharedPreferences = null;
 
    @SuppressLint("WorldReadableFiles")
    void initWriteSharedPreference(Context pluginHostContext) {
        if (!StringUtils.equals(pluginHostContext.getApplicationInfo().packageName, pluginPackage)) {
            throw new IllegalStateException("can not create write sharedPreference in host app");
        }
        if (writeXSharedPreferences != null) {
            return;
        }
        writeXSharedPreferences = pluginHostContext.getSharedPreferences(configName, Context.MODE_WORLD_READABLE);
    }
 
    void initReadSharePreference() {
        if (readXSharedPreferences != null) {
            return;
        }
        readXSharedPreferences = new XSharedPreferences(pluginPackage, configName);
    }
 
    private SharedPreferences getBindSharePreference() {
        if (writeXSharedPreferences != null) {
            return writeXSharedPreferences;
        }
        if (readXSharedPreferences != null) {
            return readXSharedPreferences;
        }
        throw new IllegalStateException("not inited");
    }
 
 
    void addOne(String name) {
        SharedPreferences bindSharePreference = getBindSharePreference();
        Set<String> stringSet = Sets.newHashSet(Splitter.on(",").splitToList(bindSharePreference.getString(configName, "")));
        stringSet.add(name);
        bindSharePreference.edit().putString(configName, Joiner.on(",").join(stringSet)).apply();
    }
 
    void removeOne(String name) {
        SharedPreferences bindSharePreference = getBindSharePreference();
        Set<String> stringSet = Sets.newHashSet(Splitter.on(",").splitToList(bindSharePreference.getString(configName, "")));
        stringSet.remove(name);
        bindSharePreference.edit().putString(configName, Joiner.on(",").join(stringSet)).apply();
    }
 
    Set<String> getConfig() {
        return Sets.newHashSet(Splitter.on(",").splitToList(getBindSharePreference().getString(configName, "")));
    }
 
    static boolean contains(Set<String> lists, String name) {
        if (lists == null) {
            return false;
        }
        for (String l : lists) {
            if (l.equals(name)) {
                return true;
            }
        }
        return false;
    }
 
}

换成xposed提供的XsharedPreference实现,那个Config模块
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值