So自加密解密(找不到JNI_Onload 跟 init_array)

Shelldemo.apk
里 libdemo.so
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
看到 getString 这个函数
下面是一堆DCD 行
说明这个函数 被加密了

那么如何得到它真实的 函数样子了?
我们得知 在运行的时候 so被加载的时候 是要先被解密 然后加载进内存的

我们就想到 在
libdvm.so 系统so 里的 loadnative(是关键字不全)这个函数里 这个函数里 有去加载 apk的 so的 JNI_Onload
这里去下断点
来试试
在这里插入图片描述
这位置按 Tab 快捷键 到下断点

在这里插入图片描述

运行起来 结果 这里 并没有断下来
而apk 已经跑起来了

这是为什么呢?
其实我们在静态分析 libdemo.so 时 搜索 JNI_Onload 函数 并没有搜索出来 这是为什么呢?
这是因为 这个so ELF格式被破坏掉了 但是破坏的有点巧妙
是操作系统不会 理会的地方 但是反编译 又需要那个地方的东西
所以造成了这种局面
操作系统 可以正常加载这个 so
IDA反编译器 不能

那么怎么办呢?
init_array 介绍
init_array段是在so加载的时候 执行的 执行顺序要优于 JNI_OnLoad 所以这里是最早被执行的函数

那么我们就猜测 加密(部分加密)的so 是在init_array 里面 解密的

正常来说 在IDA中打开要分析的so 按 ctrl+s 打开segment表 是可以找到 init_array段的
然后这里找不到 是因为这个 so被破坏了(应该是故意破坏的制造难度)

那么怎么办呢?
linker是SO加载中的一个 链接器
我们可以 在Module里 找 linker (system/bin/linker) 下的
init_array 在这下断点 即可

然而动态调试的时候 在Module里 找到linker 然后里面却没有发现
到 init_array ; 这说明IDA 并没有 翻译出来
那么我们手动去翻译下
怎么翻译呢?

思路是这样的:
在Module里 能显示出来 linker的 基址 跟 大小的
如果我们能知道 init_array在 linker里的 偏移大小
那么我们就能通过 基址 + 偏移 = 内存真实地址
这样定位到 真实位置去

好 那我们 就去分析 init_array在 linker里的 偏移大小
先弄出来 linker
linker是 位于 手机的 system/bin 目录下的
可以通过cmd指令
adb pull /system/bin/linker 导出到电脑上来
还可以 通过 android killer 的 文件工具 导出来
导出来后
到 IDA中分析

这里直接 搜 init_array 还是搜不出来 IDA还是没能正确翻译
下面先记住 这么操作的先 至于为什么 得了解 linker里的 源码才能得到答案 这里先不去研究这个先

打开Strings窗口 快捷键是 shift+F12
搜索关键字 call
在这里插入图片描述
红色 标记处 双击进去
再按 ctrl+x
在这里插入图片描述
双击 红色位置 进去
在这里插入图片描述

这里的 BLX R4 位置处 就是 init_array 函数
这里的 0000284C 就是 init_array 的偏移 (在linker里的偏移)
好了 静态分析 偏移位置 结束

到动态调试里 去定位 init_array 位置
先找到 linker的基址

在这里插入图片描述
Base 基址是 40030000
上面静态分析得到 偏移是 0000284C
基址+偏移 =内存地址
40030000+0000284C = 4003284C
动态调试里 按 快捷键 G 输入 4003284C
在这里插入图片描述
定位到这 这本应该是 个函数 然后IDA翻译成了数据
翻译错误 那么我们手动纠正下
选中这里 按 快捷键 C 手动反编译
则成为这样

在这里插入图片描述

这时我们再对比下 静态分析的 时候的 样子 证实下
完全一样 说明 找对了

动态调试里按 F9 运行
然后 开 monitor(DDMS) 赋予 此进程 8700端口

然后再开个 cmd
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
开启jdb连接 运行

这时IDA里 弹出来的窗口 点 取消即可
此事就 断下来了 在 BLX R4
按 F7 单步跟踪进入 看看里面干了啥

在这里插入图片描述
init_getString 这个函数 猜测 应该是 解密函数
我们到 静态分析 libdemo.so 里去看看 这个函数 大概是干啥的!

在这里插入图片描述

没错 就是在这里 解密的
大概意思就是 获取到这个lib 的地址 然后 对一部分 字节进行 取反 改写字节

那么我们就等 这个 函数解密 完后
在要返回(这个时候 已经解密完了)的时候 下个断点 再去内存中 提取 解密完了的 so
在这里插入图片描述

这里下个 断点 按F9运行 到这 解密完成
现在来 提取解密后的 so

先到 Module 里搜 libdemo.so 关键字
得到 Base 跟 Size

在这里插入图片描述
记录下来
/data/app-lib/com.example.shelldemo-1/libdemo.so
基址 61366000
大小 00005000

然后 File->Script Command 打开脚本执行脚本在这里插入图片描述
这时 很快就dump就出来了 并没有出现 弹出 running

这时把dump解密出来的 so 跟 原本的so 对比下看

在这里插入图片描述
红色位置 其实也是 翻译错了 不要以为是什么 指令
可以通过 右键 undifne 取消定义 更清楚的看

OK
至此结束

总结下:
如果 找不到 JNI_Onload 或者是 JNI_Onload 也被加密了
那么就到 init_array 里去分析
一般来讲 这种情况是 被加密了 然后加载的时候 在 init_array里 解密出来的

难点是 找到 init_array 的定位

发布了116 篇原创文章 · 获赞 1 · 访问量 5600
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览