Mas0n
to be reverse engineer🐧
翻车鱼

Android 某厂加固分析(一)

懒狗的月更文章。

在Windows / Linux中,经常能听到加壳这个词,最经典的壳当属upx,在商业产品上vmp令人闻风丧胆。

同理,android上也可以通过加壳实现软件防护。

文章已作脱敏处理(手动🐶)

In Java

Java层代码不多,从入口分析下来,能看到样本做的一些简单的处理:

  • 字符串 & 字面量混淆
  • 壳so为了兼容x86作出相依的处理

这里主要分析arch为arm64

native library

IDA开幕雷击

https://cdn.shi1011.cn/2023/03/663bcf93dabb2a126c7ca0b340f218a3.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5
SHT有问题

看下segment

https://cdn.shi1011.cn/2023/03/598d6bf01b9c53e341d1dd4fe94ba3fc.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

没找到init_array,反而看到几个奇怪的段:note.gnu.procnote.gnu.text

符号表也被混淆了

https://cdn.shi1011.cn/2023/03/17b51cdfdb5ebef3ea87b2074f807493.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

跨出第一步

在Android中,一个动态库的加载经由Java层的System.loadLibrary("native-lib")直至/system/bin/linker

看过Linker源码之后,很容易知道android中动态库经装载 (load) 、链接 (link) 、重定位 (rellocate) 后会执行init函数,而在一般情况下,init函数包含在.init_array区段中

在重定向完成后,linker会调用init函数

https://cdn.shi1011.cn/2023/03/7065863d122b2a14a178ff7e44097d27.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

一个动态库的init函数是不可能被加密的。

出师不利

IDA显示的区段中并不存在.init_array,如果尝试用其他工具来看区段,就会发现.init_array的偏移为0x2de830

https://cdn.shi1011.cn/2023/03/21fc78b02fc65f3a422dc12ac139db52.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

当IDA跳转到0x2de830 这个地址就会发现,它指向的根本不是一个合法函数。

跨过第一个障碍

样本通过混淆SHT使IDA分析出现错误,实际上IDA分析一个ELF,SHT并不是必须的,这意味着我们可以直接将SHT填充,恢复IDA的解析。

https://cdn.shi1011.cn/2023/03/a5e583e1cd7b5cf63ac25dd947d7df70.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

做完这些,下面就是IDA的主场。

进击

重新加载文件,定位至 .init_array , 这里将关键函数分别命名为 init_* , 开始分析壳so

https://cdn.shi1011.cn/2023/03/f56ea513fc9a73288859099604a107b7.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

壳的第一个函数

简单分析下开头几个函数,其实是混淆。

https://cdn.shi1011.cn/2023/03/8b8fc0e5e3e145870571ed5ccf0df29d.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

根据特征写个脚本批量patch

去除之后的效果如下

https://cdn.shi1011.cn/2023/03/e7bec742d425104fd21eb67ad6cc721f.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

终于能正常分析了。

第一个函数很简单,读取libc.so在内存中的位置,判断是否拥有执行权限并修改默认值为PROT_EXECj_PROT_EXEC

为什么?(技术所限,未知)

渐入佳境

在宇宙的尺度下,一颗原子的大小微乎其微。

同样的去除混淆之后分析:

smc恢复加密函数,这个函数初始了壳so需要调用的libc中的函数。

https://cdn.shi1011.cn/2023/03/39ba056f9bd07c158b69b0ec44a5c8db.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

具体函数表如下:

https://cdn.shi1011.cn/2023/03/dad46a9ad595edad405484f96cb3d380.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

遍历phdr,寻找type为dynamic的段,用于后面组装soinfo

https://cdn.shi1011.cn/2023/03/bfd229a2cf57dbc1afbd9545c77996bb.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

link dynamic段,恢复壳so的符号表、字符串表

https://cdn.shi1011.cn/2023/03/e5f153901c502cf90ed4dbbc304d8c1a.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

这里的child_so_header指向的是子so在壳so中的信息,当然这个信息是被打乱的。

告一段落

恢复壳so后,紧接着就是释放子so

https://cdn.shi1011.cn/2023/03/6258b53187da7a8960400f2d5a59c2af.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

释放子so的过程实际上和linker源码中的装载流程相似

https://cdn.shi1011.cn/2023/03/c07f69071f0b4318acad1460aed0af58.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

decrypt_and_build_child_soinfo解密存放在壳so中的加密数据,并将其组装进子so的soinfo中

https://cdn.shi1011.cn/2023/03/e90be8e1d38d164375288a4325daff06.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

在子so装载完成之后,壳so会调用子so的init_array,子so开始工作。

https://cdn.shi1011.cn/2023/03/e9aa804682fb0d142daca49dcb7b035c.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

至此壳so完成使命。

Refer

本文链接:https://blog.shi1011.cn/rev/android/2481
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可

Mas0n

文章作者

发表回复

textsms
account_circle
email

翻车鱼

Android 某厂加固分析(一)
懒狗的月更文章。 在Windows / Linux中,经常能听到加壳这个词,最经典的壳当属upx,在商业产品上vmp令人闻风丧胆。 同理,android上也可以通过加壳实现软件防护。 文章已作…
扫描二维码继续阅读
2023-03-13