记一次爱加密反调试分析及绕过思路

2020-05-20 13:44:18 Author: bbs.pediy.com
觉得文章还不错?,点我收藏



该应用 native 层反调较为简单,网上针对此类技术文章也很丰富,其中最多也最基础的应该是针对 ptrace 调试标志位检测来完成反调试
p.s. 若通过刷机修改了 ptrace 标志位的大神们可以忽略了
ptrace 会在调试进程与被调试进程间构建父子关系,此时被调试进程的一切行为诸如指令执行、信号捕获等均可以被父进程监视
并且同时会在 /proc/[pid]/status(pid 为被调试进程号)文件内将 TracerPid 字段置为调试进程的 pid

该应用反调试的点存在于 dlopen 加载 libexec.so 时 .init 段的某个函数中,考虑到这种反调试方案依然具有一定代表性,所以还是做了如下总结记录
首先 ida 挂起该应用,开始调试,发现仅仅在加载 libexec.so 后进程就崩溃退出了,所以需要在 linker 中的 _dl__ZN6soinfo13call_functionEPKcPFvvE 函数下断点
该函数负责调用被加载 so 的 .init 段函数,如下图所示,v3(v7) 是 .init 段函数调用语句

p.s. 该函数内部包含众所周知的特征字符串 "[ Calling %s @ %p for \"%s\" ]"
p.p.s. 该函数所处于 [dlopen] 流程调用栈如下所示(1+5 — Android 7.1.1)

_dl_android_dlopen_ext
|
_dl__ZL10dlopen_extPKciPK17android_dlextinfoPv
|
_dl__Z9do_dlopenPKciPK17android_dlextinfoPv
|
_dl__ZN6soinfo17call_constructorsEv
|
_dl__ZN6soinfo13call_functionEPKcPFvvE

在这个位置下断点,大概断点重复至40次时(发现第40次就会挂掉),发现一函数较为可疑,如图所示,

首先 dump 下来 libexec.so 解密后的内存(libexec.so 会在加载后将自己的指令所在内存解密)

使用 ida 分析之,该函数如下图

直接给出结论,红框内函数通过构造 "/proc/%d/status" 字符串并检测 TracerPid 字段来进行调试检测,并且检测到调试器后将 r0 寄存器置为1,后续 BNE 跳转会调用 exit 退出进程
最后测试发现,可以采用简便的方法直接在 libc.so 的 _exit 导出函数上下断点来快速发现其退出流程来定位反调试函数

尝试直接把 r0 寄存器置为0,强行续命,但后续加载 libart.so 时出现 sigsegv 信号且无法绕过,依然导致程序退出。。。
猜测可能还有其他检测机制,实在懒得寻找了,最后使用刷过 ptrace 调试标志位的机器挂载调试无任何异常
关于如何刷机绕过 ptrace 请参见 倔强石头 的文章 ([原创]记一次安卓内核源码编译刷机过程(修改反调试标志位))




觉得文章还不错?,点我收藏



如果文章侵犯到您的版权,请联系我:buaq.net[#]pm.me