目录

  • 一、加固后的APK包
    • 1)为什么要加固?
    • 2)加固方式?
    • 3)查看app是否被加固
  • 二、了解加固后的app启动流程
  • 三、FDex2脱壳工具使用
    • 1、打开xposed模块下面的FDex2
    • 2、选择要脱壳的app
    • 3、找到对应路径下脱壳后的dex文件
    • 4、利用adb工具将脱壳后的dex文件导出到pc
    • 5、利用jadx反编译脱壳后的dex查看源码
  • 四、分析加密参数signature
    • 1、全局搜索参数signature
    • 2、定位关键代码
    • 3、跟进查看代码
  • 五、将Java代码编译成jar包
  • 六、python调用jar包

一、加固后的APK包

1)为什么要加固?
  • 一定程度保护源代码

加壳又称加固技术为了加强Android保护强度,随着安全技术的发展,又出现了新型的“加固技术”。Dex加固是对Dex文件进行加壳防护,防止被静态反编译工具破解而泄露源码,


整体加固技术的原理如上所示,包括替换application/classes.dex、解密/动态加载原classes.dex、调用原application相关方法、将原application对象/名称设置到系统内部相关变量四大环节。其中最为关键的一步就是解密/动态加载原classes.dex,通过加密编译好的最终Dex源码文件,然后在一个新项目中用新项目的application启动来解密原项目代码并加载到内存中,再把当前进程替换为解密后的代码,能够很好地隐藏源码并防止直接性的反编译。

2)加固方式?
  • .dex加固
  • .so加固

一般在哪家应用市场发布,就要用哪家的加固方案。

APP常用加固厂商特征:

娜迦: libchaosvmp.so, libddog.so,libfdog.so
爱加密:libexec.so,libexecmain.so,ijiami.dat
梆梆: libsecexe.so,libsecmain.so , libDexHelper.so
360:libprotectClass.so,libjiagu.so, libjiagu_art.so,libjiagu_x86.so
通付盾:libegis.so,libNSaferOnly.so
网秦:libnqshield.so
百度:libbaiduprotect.so
腾讯:libshellx-2.10.6.0.so,libBugly.so,libtup.so, libexec.so,libshell.so
阿里聚安全:aliprotect.dat,libsgmain.so,libsgsecuritybody.so
腾讯御安全:libtosprotection.armeabi.so,libtosprotection.armeabi-v7a.so,libtosprotection.x86.so
网易易盾:libnesec.so
APKProtect:libAPKProtect.so
几维安全:libkwscmm.so, libkwscr.so, libkwslinker.so
3)查看app是否被加固

使用反编译工具,比如:apktool或者Android Killer 反编译一下代码就知道了,能否看到源代码或者看到的源代码是不是有意义,没意义就是代码被混淆过了,比如全是a,b,c,d这样的代码或者方法名,你看不懂就是被混淆过了,没有源代码就是被加固了。




加壳还会加入特定的so文件进入。所以可以根据包名或者SO名来判断是否加壳以及加了什么壳(但不是说apk中有so就是加壳的,很多apk为了提升性能,增强安全性,也会用so来实现一些重要的功能)。用一些工具比如GDA(自己写的)、apk查壳PKiDApk、Detecter查壳工具等等可以直接识别出壳,甚至还能识别版本号。

例如我们将apk文件后缀改为zip后解压缩:


如果该目录下没有显示加固特征可以进入\lib\armeabi目录下查看.so文件


借助搜索引擎直接搜索

二、了解加固后的app启动流程

app启动流程:https://www.jianshu.com/p/910df9643d8c

加固后APK运行

  • 先加载壳APP
  • 壳APP读取Dex文件末尾的源APK大小
  • 在内存中壳APP解密出源APP
  • 运行源APP

壳有自己的Application对象

源APK有自己的Application对象

没有加固的app在程序启动后首先会进入自己的application然后找到入口函数android:name="com.xxx.xxx.xxx

经过加固后的app首先会进入壳的application然后找到壳的入口函数进行相关的解密(脱壳)操作,解密后在进入apk自己的application然后找到入口函数


解密源码


三、FDex2脱壳工具使用

实验环境

  • 夜神模拟器6.2.1.1
  • xposed2.7
  • FDex2(Hook ClassLoader loadClass方法 通用脱壳 )

1、打开xposed模块下面的FDex2

2、选择要脱壳的app


注意:点击ok后需要打开目标app后脱壳后的dex才会保存在对应的路径下。

3、找到对应路径下脱壳后的dex文件

4、利用adb工具将脱壳后的dex文件导出到pc
adb pull /data/data/com.iCitySuzhou.suzhou001/com.iCitySuzhou.suzhou001191572.dex D:\工具\安卓反编译


5、利用jadx反编译脱壳后的dex查看源码


可以看到在导出的5个dex文件中,该文件是这个app的源码,且代码进行了混淆。

四、分析加密参数signature

1、全局搜索参数signature

2、定位关键代码

我们通过抓包工具获取的数据包


之所以定位到如下代码,因为代码中的参数正是我们通过抓包工具获取的其中包含了signature

3、跟进查看代码



注意:反混淆并不是将代码完全还原,只是将原有相同的方法名(a/b)进行重命名

import android.os.Build.VERSION;
import com.hualong.framework.C2407a;
import com.hualong.framework.LibApplication;
import com.hualong.framework.p170b.C2408a;
import com.hualong.framework.p172d.C2415a;
import java.io.IOException;
import p001a.C0002u;
import p001a.C0002u.C0003a;
import p001a.C0121aa;
import p001a.C0127ac;/* renamed from: com.iCitySuzhou.suzhou001.d.d */
public class C2651d implements C0002u {/* renamed from: a */public C0127ac mo4a(C0003a c0003a) throws IOException {C0121aa a = c0003a.mo5a();String udid = LibApplication.getInstance().getUDID();String valueOf = String.valueOf(System.currentTimeMillis() / 1000);C0127ac a2 = c0003a.mo6a(a.mo317e().mo311b("sys", "Android").mo311b("sysVersion", VERSION.RELEASE).mo311b("appVersion", LibApplication.getInstance().getAppVersion()).mo311b("appVersionCode", String.valueOf(LibApplication.getInstance().getAppVersionCode())).mo311b("udid", udid).mo311b("clientType", "android").mo311b("timestamp", valueOf).mo311b("signature", C2651d.m12099a(udid, valueOf)).mo309a());if (C2407a.m11253a()) {float l = ((float) (a2.mo352l() - a2.mo351k())) / 1000.0f;C2415a.m11307c("LoggingInterceptor", " ");C2415a.m11307c("LoggingInterceptor", " ");C2415a.m11307c("LoggingInterceptor", String.format("[%s] %s, %d in %.2f ms", new Object[]{a.mo314b(), a.mo312a(), Integer.valueOf(a2.mo341b()), Float.valueOf(l)}));C2415a.m11307c("LoggingInterceptor", "-----------------------------------");C2415a.m11307c("LoggingInterceptor", "          Request Headers          ");C2415a.m11307c("LoggingInterceptor", "-----------------------------------");C2415a.m11307c("LoggingInterceptor", String.format("%s", new Object[]{a.mo315c()}));C2415a.m11307c("LoggingInterceptor", "-----------------------------------");C2415a.m11307c("LoggingInterceptor", "          Response Headers          ");C2415a.m11307c("LoggingInterceptor", "-----------------------------------");C2415a.m11307c("LoggingInterceptor", String.format("%s", new Object[]{a2.mo346f()}));C2415a.m11307c("LoggingInterceptor", " ");C2415a.m11307c("LoggingInterceptor", " ");}return a2;}/* renamed from: a */public static String m12099a(String str, String str2) {return C2408a.m11256a(String.format("%s&&%s&&%s", new Object[]{str, str2, "f1190aca-d08e-4041-8666-29931cd89dde"}));}
}

分析如下代码:

C0127ac a2 = c0003a.mo6a(a.mo317e().mo311b("sys", "Android").mo311b("sysVersion", VERSION.RELEASE).mo311b("appVersion", LibApplication.getInstance().getAppVersion()).mo311b("appVersionCode", String.valueOf(LibApplication.getInstance().getAppVersionCode())).mo311b("udid", udid).mo311b("clientType", "android").mo311b("timestamp", valueOf).mo311b("signature", C2651d.m12099a(udid, valueOf)).mo309a());

结合抓包情况进行分析,大概猜出上述代码实际上就是给参数进行赋值操作。

例如:

  • sys=Android
  • sysVersion=VERSION.RELEASE(获取版本)

关键参数signature:

  • ignature=C2651d.m12099a(udid, valueOf)

该参数调用了m12099a方法并传入了两个参数udidvalueOf

由上面代码可查看到:

String udid = LibApplication.getInstance().getUDID();  // 抓包中可以获取(不变的值)
String valueOf = String.valueOf(System.currentTimeMillis() / 1000);  // 时间戳

两个参数已经明确,接下来需要找到m12099a方法:


 public static String m12099a(String str, String str2) {return C2408a.m11256a(String.format("%s&&%s&&%s", new Object[]{str, str2, "f1190aca-d08e-4041-8666-29931cd89dde"}));
}

分析上述代码可知是将传入的两个参数(udidvalueOf)与"f1190aca-d08e-4041-8666-29931cd89dde"进行格式化拼接后传给m11256a方法进行处理,处理后的结果返回。

IMEI8661740 10682363-IMSI4600 768236 19756 && 当前时间戳 && f1190aca-d08e-4041-8666-29931cd89dde

查找m11256a方法



import java.security.MessageDigest;/* renamed from: com.hualong.framework.b.a */
public class C2408a {/* renamed from: a */public static String m11256a(String str) {if (str == null) {return null;}StringBuffer stringBuffer = new StringBuffer();try {MessageDigest instance = MessageDigest.getInstance("MD5");instance.update(str.getBytes());for (byte b : instance.digest()) {stringBuffer.append(Integer.toString((b >>> 4) & 15, 16)).append(Integer.toString(b & 15, 16));}} catch (Exception e) {}return stringBuffer.toString();}
}

分析可以发现上面代码就是最后将格式化字符串加密的地方,也就是signature生成的地方。

如果代码实现原理简单我们完全可以用python实现,如果过于复杂我们可以将上面的代码编译成jar包使用python进行调用。

五、将Java代码编译成jar包


import java.security.MessageDigest;/* renamed from: com.hualong.framework.b.a */
public class MySig {/* renamed from: a */public static String m11256a(String str) {if (str == null) {return null;}StringBuffer stringBuffer = new StringBuffer();try {MessageDigest instance = MessageDigest.getInstance("MD5");instance.update(str.getBytes());for (byte b : instance.digest()) {stringBuffer.append(Integer.toString((b >>> 4) & 15, 16)).append(Integer.toString(b & 15, 16));}} catch (Exception e) {}return stringBuffer.toString();}
}/*javac MySig.java编译时类名和文件名要一致*/

上面代码复制到文本文件重命名为MySig.java

注意:类名要和java文件名相同

1、编译Java成class

  • javac MySig.java

2、把class做成jar

  • jar cvf MySig.jar 打包目录


六、python调用jar包

参考文章:
https://blog.csdn.net/xqtesting/article/details/79895829

https://blog.csdn.net/zhusongziye/article/details/92066686

参考文章:

https://www.zhihu.com/question/26438444?sort=created

【APP逆向】了解加固基本原理-FDex2_1.1脱壳工具使用相关推荐

  1. 《APP逆向学习》课程介绍和什么是安卓app逆向?

    来源[小肩膀 零基础一站式安卓app逆向安全(2021版)]:aHR0cHM6Ly93d3cuYmlsaWJpbGkuY29tL3ZpZGVvL0JWMUFWNDExSjd6aw== 1.课程介绍 安 ...

  2. 云栖大会——阿里聚安全亮出创新技术 颠覆APP传统安全加固

    2016年10月17日 17:32  2175 10月13日,杭州 · 云栖大会如期召开,亮点之一就是将会有众多"黑科技"汇聚,其中由阿里聚安全带来的"全量混淆" ...

  3. 知物由学 | 干货!一文了解安卓APP逆向分析与保护机制

    "知物由学"是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道."知物 ...

  4. APP逆向之易班(第一篇)

    原本是不想写的,因为这个APP的这个版本其实很简单,后来想了下觉得还行记录一下吧.主要是记录每一次逆向能加深其中学到的知识点内容.也算是给自己一个交代,无论以后还是菜鸡也好还是成了大牛也罢,至少这一刻 ...

  5. App逆向案例 X嘟牛 - Frida监听 WT-JS工具还原(一)

    App逆向案例 X嘟牛 - Frida监听 & WT-JS工具还原(一) 提示:文章仅供参考,禁止用于非法途径: 文章目录 App逆向案例 X嘟牛 - Frida监听 & WT-JS工 ...

  6. 逆向工程--苹果移动端app逆向分析技术(一)

    0x01 基础准备 关于iphone移动端app逆向程序相关初级基础大家可以自己提前学习.本 文主要给大家分享关于脱壳加密app程序的技术.学习之前大家先搭建系 统环境,准备相应的工具,参考链接教程自 ...

  7. 【爱加密】Android App应用安全加固详细步骤

    原文地址:点击打开链接 随着各种牌子手机的不断推出,各种Android手机应用,即Android App也是满天飞.但是,在这个山寨.黑客遍布的世界,如何保证Android App的安全是广大Andr ...

  8. 搜狗微信APP逆向(一)java层

    在该app可以搜索关键词,选择微信后面的赛选进行排序: 发现如下加密参数: 未发现加固加壳方式: 我们直接搜索定位: package com.sogou.utils; 我们先hook下这个a方法看下传 ...

  9. 精品连载丨安卓 App 逆向课程之五 frida 注入 Okhttp 抓包下篇

    本篇内容是「肉丝姐教你安卓逆向之 frida 注入 Okhttp 抓包系列的第三篇,建议配合前两篇一起阅读,效果更佳. 精品连载丨安卓 App 逆向课程之三 frida 注入 Okhttp 抓包上篇 ...

最新文章

  1. 华硕WL-500W无线路由器使用感受
  2. C#进行Visio二次开发之电气线路停电分析逻辑
  3. CentOS6.5下RabbitMQ安装
  4. java分割句子_关于Java的一些句子
  5. mysql优化和索引_mysql优化和索引
  6. python读取excel写入mysql_python读取excel写入mysql
  7. Ubuntu14.04下安装Samba
  8. Linux编程学习--开篇
  9. postgress无法远程连接问题解决方案
  10. 王者荣耀游戏服务器架构的演进读后感
  11. 突破网吧及机房管理限制的方法(转)
  12. 【科研记录】如何判断(你自己的)研究工作的价值
  13. 数据研究之综合评分(一) 权重-评分-指标
  14. 了不起的女性开发者:90后误选专业入对行,酷女孩霸榜开源NO.1
  15. 2022年第二届中国高校大数据挑战赛A题探究
  16. 在技术面前,请保持一颗谦卑的心
  17. 融云CEO韩迎:如何基于云通讯构建企业竞争力
  18. 软件设计师真题知识点(本人刷题笔记)
  19. 【论文译文】Few-Shot Unsupervised Image-to-Image Translation(FUNIT)
  20. TortoiseGit配置ppk的密钥

热门文章

  1. ShardingSphere简单分库分表实现(根据int分库,根据时间分表)
  2. 基于3G手机的移动云计算和云存储
  3. 寒武纪加速平台(MLU200系列) 摸鱼指南(四)--- 边缘端实例程序分析
  4. 【青松资讯】2018年第四季度DDoS攻击报告
  5. 自动化_超前和滞后补偿
  6. 中国大学豪华宿舍图鉴!看看传说中别人的宿舍~
  7. 让chatGPT 作为 面试官 / 辩手 / 演说家 / 哲学家 / SQL终端的 Prompt 命令
  8. SSH远程连接云服务器出错
  9. A Game of Thrones(29)
  10. 日语学习(谐音快速记忆)