简单写下Android应用(APK)的逆向脱壳过程—【蘇小沐】
App和Apk的区别,App是应用程序(Application)的缩写,包含Apk;而Apk是Android应用程序包(Android Application Package)的缩写,类似Symbian Sis或Sisx的文件格式,通过将APK文件直接传到Android模拟器或Android手机中执行即可安装;是Android操作系统使用的一种应用程序包文件格式。
一个完整的Apk文件包含有被编译的代码文件(.dex 文件)、文件资源(resources)、 assets、证书(certificates)、和清单文件(manifest file)。
META-INF目录是Android 签名认证的目录,主要包含CERT.RSA、CERT.SF、MANIFEST.MF这三个文件。
Android机制要求会对每一个Apk文件都进行签名,在安装Apk文件的时候,Android系统通过对比该Apk签名信息程序的完整性,来判断程序是否有被恶意修改、添加、删除等操作,从而决定是否可以安装,该方法在一定的程度上是安全的,能保证自己的APK没有被其他人恶意的修改。
MANIFEST.MF文件Apk的摘要文件。程序遍历Apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个用SHA1生成摘要信息,再用Base64进行编码。
CERT.SF文件对摘要的签名文件。对前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用开发者的私钥进行签名。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息(即,MANIFEST.MF文件)进行对比,如果相符,则表明内容没有被异常修改。
系统在对程序进行验证的时候,用开发者公钥对不正确的签名文件进行解密,得到的结果和摘要文件(MANIFEST.MF)对应不起来,所以不能通过检验,不能成功安装文件。
CERT.RSA文件中保存了公钥、所采用的加密算法等信息;系统对签名文件进行解密,所需要的公钥就是从这个文件里取出来的。
classes.dex - dx编译后的文件格式,class.dex本来是java编译出来的.classes文件,再次通过dx编译后的格式。要还原出Android源码,首先从这个文件下手,用特殊工具把.dex文件还原成.jar,再利用查看jar格式文件的工具,即可查看源代码。
res目录是Android 程序使用的资源文件都存在这个目录下,如图片文件等。
resources.arsc,是编译好的二进制格式的资源信息,应用程序的语言文件。Apk文件在打包时,strings.xml中的字符串被加密存储为resource.arsc文件保存到Apk程序包中,当Apk被成功反编译后这个文件也被解密出来,可以透过这软件用AndroidResEdit等工具来进行编译。
官网下的豌豆荚应用市场,链接https://www.wandoujia.com/apps/7833706。
图2-1 下载页面
在司法鉴定中,需要严格记录,以便随时可以回溯所有的操作,记录唯一性,下面对该多开Apk记录信息。
名称 | 信息 |
---|---|
名称 | com.xzj.multiapps_2.1.0_21000.apk |
包名 | com.xzj.multiapps |
版本 | 2.1.0 |
APK入口 | com.xzj.multiapps |
文件大小 | 18362493字节 |
MD5 | a32d967182a8502d20003335478428f7 |
SHA-256 | cfe6e598278706502b1a97587e2a051002c9c91bd8501ef25238d82bf8663050 |
模拟器安装Apk,打开如下。
软件界面
在Android诞生的那天起,Apk始终以zip作为文件格式。这样我们用解压软件直接解压Apk文件,就可以直接看到Apk的目录结构,下图是直接解压后的应用目录。
其中,AndroidManifest.xml是非常重要的一个文件,它是Android的清单文件,该文件中存放了Apk的大量配置信息,它记录着软件的一些基本信息,包括软件的包名、版本号、包名、应用权限、组件配置等。
文件是被加密存储进了Apk文件中的,直接解压出来的AndroidManifest.xml并不能直接看到其中的内容;我们需要使用gadx-gui等特定的工具来打开Apk,可以看到AndroidManifest.xml记载的程序各种信息。
gadx-gui工具打开Apk,可以看到AndroidManifest.xml记载的程序版本号、包名、应用请求权限等信息。
很多Android应用和游戏中会存在一些恶意收集用户隐私的行为,Google对Android的"权限等级"分为"normal"、“dangerous”、“signature”、“signature|system”(或signatureOrSystem)四大类。
jadx-gui打开Apk,可以看到AndroidManifest.xml 标签内使用里面有很多的声明,"android.permission.xxx"的就是应用程序申请的具体权限要求,在权限列表中,我们可以看到,应用申请了哪些请求,下面将该Apk所要申请的(部分)权限列表如下。
许可名称 | 实现功能 |
---|---|
android.permission.INTERNET | 连接网络(2G或3G) |
android.permission.ACCESS_WIFI_STATE | 读取WiFi的连接状态 |
android.permission.WRITE_EXTERNAL_STORAGE | 写外部存储器(如:SD卡) |
android.permission.ACCESS_FINE_LOCATION | 通过GPS芯片接收卫星的定位信息(高精度) |
android.permission.ACCESS_COARSE_LOCATION | 通过WiFi、基站获取设备的经纬度信息(粗略定位) |
android.permission.CHANGE_WIFI_STATE | 改变WiFi的连接状态 |
android.permission.ACCESS_NETWORK_STATE | 读取当前的网络信息状态,判断是否有效 |
android.permission.CHANGE_NETWORK_STATE | 改变网络状态 |
android.permission.READ_PHONE_STATE | 读取手机状态 |
android.permission.CAMERA | 访问照相机设备 |
android.permission.FLASHLIGHT | 访问闪光灯 |
android.permission.ACCESS_GPS | 获取GPS |
android.permission.READ_EXTERNAL_STORAGE | 允许应用程序从外部存储读取 |
android.permission.REQUEST_INSTALL_PACKAGES | 允许应用程序请求安装软件包 |
android.permission.READ_LOGS | 读取系统底层日志 |
android.permission.RECEIVE_MMS | 接收彩信 |
android.permission.RECEIVE_SMS | 接收短信 |
android.permission.RECEIVE_WAP_PUSH | 接收WAP_PUSH信息 |
android.permission.SEND_SMS | 发送短信 |
android.permission.READ_SMS | 读取短信内容 |
android.permission.WRITE_SMS | 写短信 |
android.permission.PROCESS_OUTGOING_CALLS | 监视,修改或放弃播出电话 |
android.permission.CALL_PHONE | 打电话 |
android.permission.READ_CALL_LOG | 读取通话记录 |
android.permission.WRITE_CALL_LOG | 写入通话记录 |
android.permission.READ_SOCIAL_STREAM | 读取用户的社交信息流 |
android.permission.READ_PROFILE | 访问用户个人资料 |
android.permission.WRITE_PROFILE | 写入用户个人资料 |
android.permission.READ_USER_DICTIONARY | 读取用户词典 |
android.permission.WRITE_USER_DICTIONARY | 向用户词典中写入新词 |
android.permission.AUTHENTICATE_ACCOUNTS | 通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息 |
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS | 允许程序访问额外的程序提供者指令 |
android.permission.CHANGE_WIFI_MULTICAST_STATE | 改变WiFi多播状态 |
android.permission.MOUNT_UNMOUNT_FILESYSTEMS | 挂载、反挂载外部文件系统 |
android.permission.BATTERY_STATS | 获取电池电量统计信息 |
android.permission.BODY_SENSORS | 允许传感器 |
android.permission.DISABLE_KEYGUARD | 禁用键盘锁 |
android.permission.EXPAND_STATUS_BAR | 允许程序扩展或收缩状态栏 |
android.permission.GET_ACCOUNTS | 访问GMail账户列表 |
android.permission.MANAGE_ACCOUNTS | 管理AccountManager中的账户列表 |
android.permission.CHANGE_CONFIGURATION | 允许当前应用改变配置,如定位 |
android.permission.WRITE_SETTINGS | 读写系统设置项 |
android.permission.GET_TASKS | 获取当前或最近运行的应用 |
android.permission.KILL_BACKGROUND_PROCESSES | 结束后台程序 |
android.permission.REORDER_TASKS | 重新排序系统Z轴运行中的任务 |
android.permission.RECORD_AUDIO | 录制声音通过手机或耳机的麦克 |
android.permission.BLUETOOTH | 连接配对过的蓝牙设备 |
android.permission.BLUETOOTH_ADMIN | 发现和配对新的蓝牙设备 |
android.permission.NFC | 执行NFC操作,用于移动支持 |
android.permission.MODIFY_AUDIO_SETTINGS | 修改声音设置信息 |
android.permission.VIBRATE | 允许震动 |
android.permission.USE_FINGERPRINT | 允许程序使用指纹设备 |
android.permission.CLEAR_APP_CACHE | 清除应用缓存 |
android.permission.GET_PACKAGE_SIZE | 获取应用的文件大小 |
android.permission.WRITE_SYNC_SETTINGS | 写入Google在线同步设置 |
android.permission.READ_SYNC_SETTINGS | 读取同步设置,读取Google在线同步设置 |
android.permission.READ_SYNC_STATS | 读取同步状态,获得Google在线同步状态 |
android.permission.SUBSCRIBED_FEEDS_READ | 访问订阅信息的数据库 |
android.permission.SUBSCRIBED_FEEDS_WRITE | 写入或修改订阅内容的数据库 |
android.permission.WRITE_CALENDAR | 允许程序写入用户的日程信息 |
android.permission.READ_CALENDAR | 允许程序读取用户的日程信息 |
android.permission.READ_CONTACTS | 允许应用访问联系人通讯录信息 |
android.permission.WRITE_CONTACTS | 允许应用写入联系人通讯录信息 |
android.permission.RESTART_PACKAGES | 结束任务通过restartPackage(String)方法,该方式将在外来放弃 |
android.permission.SET_TIME | 设置系统时间 |
android.permission.SET_TIME_ZONE | 设置系统时区 |
android.permission.SET_WALLPAPER | 设置桌面壁纸 |
android.permission.SET_WALLPAPER_HINTS | 设置壁纸建议 |
android.permission.USE_SIP | 允许程序使用SIP视频服务 |
android.permission.WAKE_LOCK | 允许程序在手机屏幕关闭后后台进程仍然运行 |
android.permission.SYSTEM_ALERT_WINDOW | 显示系统窗口 |
android.permission.SYSTEM_OVERLAY_WINDOW | 关闭系统窗口 |
android.permission.RECEIVE_BOOT_COMPLETED | 允许开机自启 |
android.permission.INSTALL_PACKAGES | 允许程序安装应用 |
android.permission.DELETE_PACKAGES | 允许程序删除应用 |
android.permission.CLEAR_APP_USER_DATA | 清除应用的用户数据 |
android.permission.WRITE_MEDIA_STORAGE | 写入媒体权限 |
android.permission.DEVICE_POWER | 允许访问底层电源管理 |
android.permission.BIND_APPWIDGET | 允许一个程序告诉appWidget服务需要访问小插件的数据库 |
android.permission.ACCOUNT_MANAGER | 获取账户验证信息,主要为GMail账户信息,只有系统级进程才能访问的权限 |
android.permission.READ_OWNER_DATA | 允许程序读取所有者数据 |
android.permission.WRITE_OWNER_DATA | 允许程序写入但不读取所有者数据 |
android.permission.ACCESS_WIMAX_STATE | 建立或中断 WiMAX 网络连接 |
android.permission.ACCESS_DOWNLOAD_MANAGER | 允许程序以管理员下载 |
android.permission.CHANGE_WIMAX_STATE | 更改 WiMAX 状态 |
由于Android应用程序的代码都存储在dex文件中,在前面jadx-gui工具打开APK时,看到有qihoo.util,其使用某数字公司的壳进行了软件加固,导致我们无法直接查看.dex文件;我们要想得到dex文件,首先对该Apk进行脱壳操作,然后提取解密后的dex进行功能分析。( jadx-gui查看已加壳)
如果不清楚的话程序是否加壳,加了什么壳,我们可以借助Apktool Box等工具查壳,打开Apktool Box工具,将该Apk文件拖进去,点击查壳按钮,我们可以看到程序加了那种壳,如图显示该软件使用了360加固。
下面我们进行脱壳,首先打开模拟器安装好Apk文件,连接好模拟器后,进行脱壳操作,工具使用的是夜神模拟器,脱壳工具是drizzleDumper。
首先,启动模拟器安装需要脱壳的应用程序,ADB命令连接模拟器,输入命令:“adb connect 127.0.0.1:62001”。
接着adb 命令push drizzleDumper到模拟器的/data/local/tmp目录下,输入命令:“adb push drizzleDumper /data/local/tmp”。
然后输入命令"adb shell chmod 0777 /data/local/tmp/drizzleDumper"、“adb shell”。
输入命令:“adb shell”
输入命令:“cd/data/local/tmp”
输入命令:“./drizzleDumper com.xzj.multiapps” 。
这时候,回到模拟器,打开要脱壳的App,后就开始自动脱壳操作,如图所示为脱壳完成。
最后输入命令:"exit"退出该模式。
我们回到模拟器的/data/local/tmp文件夹目录下,现在可以看到多了一个"XXX.dex"的文件(有的软件脱壳后存在多个.dex文件),说明已经反编译成功,脱壳出来了。
现在我们就可以用jadx-gui分析解密的com.xzj.multiapps_dumped_35.dex文件了。
逆向是一个漫长的过程,以上只简单的对当前主流脱壳方法进行了脱壳分析,在网络的发展中,各种高级加壳、花壳、混淆技术等越来越高级,进阶Apk脱壳技术通过dump内存中处于解密状态的dex,进行修复分析,普通的逆向将难以应对。
公众号回复关键词【APK逆向】自动获取资源合集,如链接失效请留言,便于及时更新。
【声明:欢迎转发收藏,喜欢记得点点赞!转载引用请注明出处,著作所有权归作者 [蘇小沐] 所有】
【注:本文的软件资源等收集于官网或互联网共享,如有侵权请联系删除,谢谢!】
记录 |
---|
开始编辑:2019年 12月 25日 |
最后编辑:2019年 12月 25日 |