【APP逆向】了解加固基本原理-FDex2_1.1脱壳工具使用
目录
- 一、加固后的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
方法并传入了两个参数udid
和valueOf
由上面代码可查看到:
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"}));
}
分析上述代码可知是将传入的两个参数(udid
和valueOf
)与"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脱壳工具使用相关推荐
- 《APP逆向学习》课程介绍和什么是安卓app逆向?
来源[小肩膀 零基础一站式安卓app逆向安全(2021版)]:aHR0cHM6Ly93d3cuYmlsaWJpbGkuY29tL3ZpZGVvL0JWMUFWNDExSjd6aw== 1.课程介绍 安 ...
- 云栖大会——阿里聚安全亮出创新技术 颠覆APP传统安全加固
2016年10月17日 17:32 2175 10月13日,杭州 · 云栖大会如期召开,亮点之一就是将会有众多"黑科技"汇聚,其中由阿里聚安全带来的"全量混淆" ...
- 知物由学 | 干货!一文了解安卓APP逆向分析与保护机制
"知物由学"是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道."知物 ...
- APP逆向之易班(第一篇)
原本是不想写的,因为这个APP的这个版本其实很简单,后来想了下觉得还行记录一下吧.主要是记录每一次逆向能加深其中学到的知识点内容.也算是给自己一个交代,无论以后还是菜鸡也好还是成了大牛也罢,至少这一刻 ...
- App逆向案例 X嘟牛 - Frida监听 WT-JS工具还原(一)
App逆向案例 X嘟牛 - Frida监听 & WT-JS工具还原(一) 提示:文章仅供参考,禁止用于非法途径: 文章目录 App逆向案例 X嘟牛 - Frida监听 & WT-JS工 ...
- 逆向工程--苹果移动端app逆向分析技术(一)
0x01 基础准备 关于iphone移动端app逆向程序相关初级基础大家可以自己提前学习.本 文主要给大家分享关于脱壳加密app程序的技术.学习之前大家先搭建系 统环境,准备相应的工具,参考链接教程自 ...
- 【爱加密】Android App应用安全加固详细步骤
原文地址:点击打开链接 随着各种牌子手机的不断推出,各种Android手机应用,即Android App也是满天飞.但是,在这个山寨.黑客遍布的世界,如何保证Android App的安全是广大Andr ...
- 搜狗微信APP逆向(一)java层
在该app可以搜索关键词,选择微信后面的赛选进行排序: 发现如下加密参数: 未发现加固加壳方式: 我们直接搜索定位: package com.sogou.utils; 我们先hook下这个a方法看下传 ...
- 精品连载丨安卓 App 逆向课程之五 frida 注入 Okhttp 抓包下篇
本篇内容是「肉丝姐教你安卓逆向之 frida 注入 Okhttp 抓包系列的第三篇,建议配合前两篇一起阅读,效果更佳. 精品连载丨安卓 App 逆向课程之三 frida 注入 Okhttp 抓包上篇 ...
最新文章
- 华硕WL-500W无线路由器使用感受
- C#进行Visio二次开发之电气线路停电分析逻辑
- CentOS6.5下RabbitMQ安装
- java分割句子_关于Java的一些句子
- mysql优化和索引_mysql优化和索引
- python读取excel写入mysql_python读取excel写入mysql
- Ubuntu14.04下安装Samba
- Linux编程学习--开篇
- postgress无法远程连接问题解决方案
- 王者荣耀游戏服务器架构的演进读后感
- 突破网吧及机房管理限制的方法(转)
- 【科研记录】如何判断(你自己的)研究工作的价值
- 数据研究之综合评分(一) 权重-评分-指标
- 了不起的女性开发者:90后误选专业入对行,酷女孩霸榜开源NO.1
- 2022年第二届中国高校大数据挑战赛A题探究
- 在技术面前,请保持一颗谦卑的心
- 融云CEO韩迎:如何基于云通讯构建企业竞争力
- 软件设计师真题知识点(本人刷题笔记)
- 【论文译文】Few-Shot Unsupervised Image-to-Image Translation(FUNIT)
- TortoiseGit配置ppk的密钥