180712 安卓-入门

安卓逆向

反编译

Apk结构

  • classes.dex
    java层的主要代码,即主程序
  • META-INF
    签名和证书相关文件
  • lib
    native层的动态链接库文件(.so)目录,按照CPU架构作为子目录存放不同的so
  • assets
    打包的静态文件,通常存放需要读取的图片、加密代码等等
  • res
    资源目录
  • AndroidManifest.xml
    配置文件,默认状态为编译后的二进制文件
  • resources.arsc
    资源配置文件,默认状态为编译后的二进制文件

常用工具

  • apktool
  • AndroidKiller/APKIDE/JadX
  • Jeb/dex2jar + jd-gui
apktool

其中最基本的工具是apktool,是大多数反编译工具的基石
它可以将整个apk解包,把dex、AndroidManifeset等编译过的文件解析成可读格式(dex->smali文件,其他转换成可读文本)
也可以将修改过的包编译回apk,只需要自行签名即可再次安装

再次签名需要使用re-sign.jar,提供相关证书,比较麻烦

AndroidKiller/ApkIDE

而对于比赛这类重打包时对签名证书无所谓的时候通常使用AndroidKiller/ApkIDE之类的傻瓜工具一键重打包

这种套件工具还可以一键解包,快速搜索内容等等,在理解步骤的基础上使用这些工具可以更快速方便地完成需求

dex2jar + jd-gui

apktool解包以后得到各个类的smali文件,是dex的解包版,接近汇编代码,可读性较差,但进行修改必须在其之上

由于java编译得到的是字节码,而dex只是jar字节码的压缩版本,因此反编译几乎可以得到完全一致的java代码
这个过程可由dex2jar + jd-gui完成,前者可将dex转为jar包,后者则将jar包转成可读的java文件格式

jd-gui具有一定的语法高亮和快捷查找功能,但是对于整体代码较弱

jeb

jeb是一个强力的反编译工具
它可以一键将smali转回java,并附带交叉引用功能。虽然对于代理、监听、反射等特殊执行代码,交叉引用常常无法发挥作用,但是普通的类和方法都可以直接通过交叉引用来查找调用

另外它还具有smali级别的动态调试功能,并可随时转回java代码来对照查看,是相当方便的工具

但是–有时套件会因为某一个工具的BUG而导致错误,进而整个反编译都失败,这就是一键的缺点了
在无法定位错误/BUG的情况下,将其手动解包,通过dex2jar来反编译是最好的方法
因此几个工具和使用方法都需要掌握,灵活使用

实验-hxb_re2.apk

smali与Davlik

Davlik

Davlik是安卓的核心部件–虚拟机,类似jvm但又跟jvm有一些不同
基本原理是相似的,通过编译字节码执行机器码来达到跨平台的目的
但Davlik是基于寄存器的,它的可执行文件格式为dex,字节码是smali语法
安卓SDK中有一个工具将java字节码转成Davlik字节码,目的是在移动端去除冗余信息以缩小体积

smali

由于smali同样是基于寄存器的结构,相对java字节码而言要更接近x86汇编,因此理解起来相对要容易一些

基本操作同样是add, sub, cmp+两个寄存器等等,在有反编译的情况下通读和修改一般问题不大

另外由于apk格式较松散,没有指定各个smali文件的大小,因此patch起来相对x86patch时的空间有限要方便许多

动态调试

jeb提供了smali粒度的动态调试
Ctrl+B下断点以后即可选择进程attach

虽然经常会出各种Bug崩进程,但是正常运行的时候还是挺强大的
可以查看各种变量的值,但目前流出的破解版不可修改变量

实验-App02.apk
(动态调试、Patch-log)

静态分析技巧

androidmanifest.xml

该文件携带了apk的配置信息,包括暴露的各个组件,各自的实现类等等
其中最常见的就是MainActivity组件
有时对于一些不具有界面的恶意软件、后台程序等,会故意不启动界面,此时可能不具有MainActivity或者它不是最先启动的Activity

这个时候就需要关注各个Activity的属性了
android.intent.action.MAIN表示应用最先启动的Activity,因此如果某个Activity具备这个属性则需要优先关注它

另外application属性中有一个android:debuggable=”true”是需要填上的,否则真机运行时可能导致release版本应用无法调试(debug版本应用默认是true的)
而模拟器则不用管,因为模拟器的有一个系统属性ro.debuggable置了1,这个属性的优先级高于各个应用的属性,因此所有应用都是可调试的

apktool.yml

这个文件是apktool解包时生成的,里面包含一些配置信息
其中需要关注的是一个minSdkVersion,如果真机的Sdk过低(而应用的编写者设置的版本过高)可能导致无法安装,但实际上一般CM是不需要高版本的Sdk的,因此可以通过将它直接删去后再重打包来解决,并不影响进程运行

MainActivity的各个方法


如图所示,一般包括多个包,其中android包内的类大多为java库,com包才是用户自己写的

onClick

对于CrackMe类型的题目,大多数情况下关注onClick方法即可
有时它会被放在子类的方法中,需要自行寻找

由于CM类型大多数情况为一个文本输入框+确认按钮,因此关注确认按钮绑定的函数能够比较快速地定位关键check

init和onCreate

和onCreate两个函数也需要注意
前者是类创建时的初始化函数,后者是Activity创建时系统调用的初始化函数
onCreate中通常会有一些诸如findViewByIdsetContentView的函数,是用来设置activity中各项控件属性的,对应的name可通过id在/res/valus/public.xml,然后通过name和type可以在对应的xml文件中找到具体属性

BuildConfig和R

BuildConfig和R这两类大多数情况下不用关注,为编译时自行添加的资源类

–实验 combo.apk
解法:patch、资源溯源

native层与so

众所周知Android系统的底层是Linux,而Java层的代码都是由Davlik这个虚拟机来执行的,但在必要的情况下程序也是可以通过一些方法来在Linux中执行一些代码,也就是原生的native层

这个方法就是加载so,linux中的动态链接库

反编译so

so文件通常存放在apk包中的lib文件夹下,通过在java层执行loadlibrary函数来加载

将其直接解压出来,使用IDA可以直接反编译

native方法

形如Java_com_example_packagename_MainActivity_check这样的就是库中被jvm调用的函数,简单的题目可以直接去找它

实验-APP02(so静态分析)

JNI_ONLOAD

这个函数是Dalvik虚拟机加载库时的初始化函数,有时里面会执行一些解密数据的操作,或是动态注册native函数

JniEnv*

Jni的若干原生方法都定义在JNI.h中
实际操作时列成一个函数表,通过JNIENV指针+偏移的方法来调用

通常见到类似a1+658的方法调用时一般就是JNI方法
识别函数的方法有两种:
1. 通过JNI.h查看偏移对应的函数名
2. 将a1的类型改为JNIENV*,IDA可以自己识别出对应的函数名

动态调试

在架构对应的基础上,通过adb将对应的server发送至android内
adb push xxx /data/local/tmp/ida_server

然后进行端口转发
adb forward tcp:23946 tcp:23946

接着在ida中选择Remote Android Debugger、Process Options将ip填上localhost即可

实验-FlagApp

安卓加壳与脱壳

加壳

加固思路经过若干年演变目前已分为三代
1. 加密隐藏真实dex,运行时动态加载
2. dex被分散隐藏,并且class仅当被加载时才会还原,且加载完就继续隐藏
3. 编译为未知语言解释执行

脱壳

动态调试so、抓取dex和Dumpdex可破解第一代加固

DexHunter可破解第二代加固

第三代加固就只能硬怼,分析虚拟机的各个字节码含义

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值