freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Android Native层逆向探索
2022-05-31 10:33:30
所属地 天津

1.    概述

众所周知,Android是分层架构的。顶层应用层,Android会随系统一起打包一些核心应用(日历、短信、电话等),均是使用java语言编写;Java框架层也就是我们所说的Framework,里面主要为一些ActivityManagerService、PackageManageService等等,我们所编写的android代码能够正常的识别和动作都要依赖这一层的支持,由java语言实现;而Native层为一些本地服务和链接库,例如我们需要一个复杂的运算如果使用java去编写效率会很低,该层一般用c++开发,因语言的差异此时要与上层编写的java代码互通,就需要使用android中的jni机制;Android底层是在linux内核基础上做一些裁剪和定制,并运行了一个Dalvik/Art虚拟机,所有的应用都需要运行在虚拟机上。当程序代码趋向底层时对其的破译、逆向分析难度也就会增大从而安全性和隐蔽性也就有了良好的保障,而黑客也正是利用这一点对其开发的程序加上了一层保护伞。

近期,暗影实验室发现了一款app,此类恶意程序启动后,隐藏启动图标,防止用户主动查杀,而其真正目的是在后台窃取用户隐私。经过对该app的挖掘分析,发现其将自身的敏感且关键的信息写到了本地层,该篇文章即通过此示例讲述了Native层的逆向以及对ARM汇编代码的解析,最后提取出我们所需要的关键信息。

2.    样本信息

恶意程序基本信息如下表:

应用名称

样本md5

包名

相片

762B9874707BA9305914F4528D08CD2C

com.swift.a45

表2-1 样本基本信息

恶意程序安装信息如下图:

1653963327_62957a3f09273423a80af.png!small?1653963328682

表2-2 样本安装信息


恶意程序签名信息如下表:

所有者

CN=8y9u43,OU=ht97uig,O=tiug543,L=yf54543,ST=uyfh543,C=86

发布者

CN=8y9u43,OU=ht97uig,O=tiug543,L=yf54543,ST=uyfh543,C=86

序列号

6BDF7DA9

证书MD5

8C63C8499087821D567D2EE16B8C57C3

证书SHA1

53760FC838C5C4DD7FCD825FBDAAA49A0B42EC0D

表2-3 样本签名信息

3.     Native层逆向逻辑分析流程

1653963459_62957ac3bfc620b616fec.png!small?1653963461192

4.    代码分析

4.1 启动项与加载项

该程序采用传统的启动方式,即MainActivity的onCreate方法,随后通过Intent跳转到后台服务执行恶意操作。

1653963479_62957ad7c3d1964405c7f.png!small?1653963481220

图4-1-1 启动项

启动服务-关键信息切入点:

1653963499_62957aeb99c59a84ab258.png!small?1653963501102

图4-1-2 加载项

4.2 NativeMethod

该应用为了提高隐蔽性已将个人数据隐藏至本地层,在启动服务后加载指定函数,调用本地方法,从本地拿取所需的关键数据。

1653963531_62957b0b26a4fc4ee1ca3.png!small?1653963532563

图4-2-1 接入本地方法

1653963555_62957b23715e00963943a.png!small?1653963556872

图4-2-2加载so与本地方法

4.3 通过Jni完成函数的调用

JNI作为与本地数据传递的桥梁,通过其可以实现Java代码里调用C、C++等语言的代码,如下为加载到本地层的关键函数信息

1653963571_62957b3310e28b7b4eee9.png!small?1653963572797

图4-3-1 JNI函数调用模块

此时需注意通过JNI调用本地方法的书写方式:

  1. 格式 = Java_包名_类名_需要调用的方法名
  1. Java必须大写
  1. 对于包名,包名里的.要改成_,_要改成_1。

如包名为scut.carson_ho.ndk_demo,则需要改成scut_carson_1ho_ndk_1demo

4.4 解析ARM指令

找到调用的函数后,我们可以将其转换成汇编伪指令,进一步解读其含义,此时应注意code位数与指令模式以便进行偏移的计算。

4.4.1 ARM关键函数信息

邮箱信息指令逻辑

1653963596_62957b4c9e180d6315b09.png!small?1653963598124

图4-4-1-1 arm-邮箱账号函数块

密码信息指令逻辑

1653963613_62957b5d7fca173fb4e02.png!small?1653963614972

图4-4-1-2 arm-邮箱密码函数块

号码信息指令逻辑

1653963630_62957b6ed64efc05be8aa.png!small?1653963632311

图4-4-1-3 arm-手机号信息

众所周知,25端口为SMTP协议主要用于发送邮件,也被很多木马程序所利用。

1653963650_62957b826444d3f177004.png!small?1653963651832

图4-4-1-4 arm-端口号及主机信息

4.4.2 ARM指令解析

因结构与计算方式大同小异,仅以上述邮箱和密码为例

1653963674_62957b9a7932b4ee33055.png!small?1653963675968

图4-4-2-1 邮箱信息

1653963693_62957bad7548f173375b9.png!small?1653963694904

图4-4-2-2 加密数据信息

首先,通过指令地址的对应关系及指令长度可知该指令为Thumb指令,关于指令模式也可根据T标志位得知,T=0为ARM模式,T=1为Thumb模式;

若要解析ARM指令,首先要明确其指令模式,Thumb指令可以是16位也可以是32位,ARM指令为32位,而新版本的ARM已经64位了,寄存器也从R改为了X。ARM程序和Thumb程序可相互调用,相互之间的状态切换开销几乎为零。

通过分析可知,该应用为Thumb与arm指令结合使用,而关键的函数调用则为Thumb指令。

1653963717_62957bc54e5c5e938aa9c.png!small?1653963719279

图4-4-2-3 函数指令模式

PUSH {R3,LR}与POP{R3,PC}用于开辟空间,申请了多少空间,当程序执行完毕后就需要释放多少空间,堆栈平衡原理,否则会造成地址或内存混乱程序崩溃;

使用LDR指令通过寄存器的寻址,加载R1寄存器。

邮箱账号:

此时R1寄存器取址为:R1,=(a100ab104ab108a - 0xDB0)

当前PC取址:00000DAC

a100ab104ab108a取址:rodata:00001FD0

取得如上字符串后,通过Bl指令跳转到JNIEnv,进行字符串转化,将值返回到调用者。

邮箱密码:

此时R1寄存器取址为:R1, =(a164ab164ab100a - 0xDC0)

当前PC取址:00000DAC

a100ab104ab108a取址:rodata:00001FD0

当前PC取址:00000DBC

取得如上字符串后,通过Bl指令跳转到JNIEnv,进行字符串转化,将值返回到调用者。

4.5 指令计算

因PC指令用来存放当前欲执行指令的地址,ARM是冯诺依曼结构,同时采用流水线工作原理,对于三级流水线(最少也是三级),有取址、译码、执行阶段。那么当执行当前语句时,PC的值就是指向下第2条指令(以当前指令为参考系),这就是我们所说的地址重定位,即地址重定位地址=偏移地址+当前PC地址因如上指令采用的为Thumb指令,当执行到PC时实际地址需+4,ARM指令模式需+8。所以得到如下计算

邮箱账号模块指令计算流程:

R1+PC=(a100ab104ab108a - 0xDB0)+DAC+4=1FD0-0xDB0+DAC+4=1FD0

即关键信息就在地址1FD0处,值的加密信息如下图

邮箱密码模块指令计算流程:

R1+PC=(a164ab164ab100a - 0xDC0)+DBC+4=202F-0xDC0+DBC+4=202F

即关键信息就在地址202F处,值的加密信息如下图

1653963743_62957bdfbadc2071d1939.png!small?1653963745447

图4-5-1 寻址到的加密数据信息

4.6 解密

将拿到的本地数据通过拟写好的解密算法解密,该算法即是将拿到的字符串以“AB”字符分割,随后将分割出的字符逐个解析成整型进行算数运算(将所有值-51)最后再重组成新的字符串得以返回。

1653963765_62957bf54645eda53a604.png!small?1653963766775

图4-6-1 解密算法封装

解密算法如下:

1653963787_62957c0b3ef1b0b55aada.png!small?1653963788646

图4-6-2 解密算法

StringTokenizer是java中object类的一个子类,属于 java.util 包,用于分割字符串,该算法即是将拿到的字符串以“AB”字符分割。

1653963802_62957c1a5f3706480430f.png!small?1653963803787

图4-6-3 解密算法

解密后得到我们想要的本地关键数据,邮箱和密码

1653963819_62957c2b5291a67cac629.png!small?1653963820792

图4-6-4 解密结果

也可通过码表得出上述结果

1653963841_62957c416e3743df2fe9d.png!small?1653963843361


图4-6-5 通过码表匹配结果

5.    修复方法

当用户不慎安装恶意app后,处理方式有四个步骤,用户可以通过以下方法卸载:

(1)立即关闭所有网络连接(断开手机移动网络和wlan),在未删除app前,建议禁止网络连接;

(2)在手机设置的应用信息中找到应用图标,点击卸载;

(3)当恶意程序已经运行且隐藏了图标,此时应在手机正在运行的程序中,找到该应用停止并卸载,若已激活了设备管理器需找到管理器界面停止授权并卸载。

(4)如果以上方法都无法删除,备份一些重要数据到电脑,然后恢复出厂设置。如果不放心,也可选择重置手机,以此规避已经投放到手机上的恶意负载的攻击。

6.     安全建议

恒安嘉新暗影移动安全实验室在此提醒广大用户,不轻易相信陌生人,不轻易点击陌生人发送的链接,不轻易下载不安全应用,不安装非正规途径来源的APP。用户可以采用以下方式来阻止恶意软件攻击:

  • 谨慎打开未知短信的下载链接。
  • 避免点击网页中的链接或下载附件。
  • 仅从受信任的来源下载应用程序,建议去正规的应用市场或官方下载。
  • 适时升级系统,常做对手机进行扫描查杀
# 逆向分析 # native层 # 数据加密算法 # arm汇编分析 # so文件剖析
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录