段落引用 本文思路和主要代码来源,感谢大佬们提供的NB思路,关于seccomp等不再赘述,直接传送至各位前辈大佬的文章即可: [原创]基于seccomp+sigaction的Android通用svc hook方案 [原创]SVC的TraceHook沙箱的实现&无痕Hook实现思路 [原创]分享一个Android通用svc跟踪以及hook方案——Frida-Seccomp
段落引用 本文思路和主要代码来源,感谢大佬们提供的NB思路,关于seccomp等不再赘述,直接传送至各位前辈大佬的文章即可:
[原创]基于seccomp+sigaction的Android通用svc hook方案 [原创]SVC的TraceHook沙箱的实现&无痕Hook实现思路 [原创]分享一个Android通用svc跟踪以及hook方案——Frida-Seccomp
一切都因WMCTF2023一道Android 游戏题BabyAnti-2而起,预期解为拦截mincore调用(int mincore(void *start, size_t length, unsigned char *vec);监测指定大小的页面是否处于物理内存中。一般用于内存扫描的检查,一旦扫描行为发生,有些并不在物理内存的页面被调入。vec 是一个字节数组,用于存储结果。每个字节对应 addr 和 length 指定的内存区域中的一个页面。如果相应的页面驻留在内存中,那么相应的字节的最低位会被设置为 1,否则会被设置为 0。),当时非预期了题目,即直接CheatEngine附加游戏题,扫描内存时游戏虽然会监测到并弹窗,但是游戏正常运行,直接能修改分数并且拿到flag。后来想着除了通过内存搜索mincore的svc调用指令外还有什么其他别的办法快速的拦截svc调用,就看到了看雪上面的三篇文章
经过实验发现,
Ptrace-seccomp方案原理简单,因为要fork子进程来监控父进程,实操较为复杂且容易出现各种问题。本人手太拙,在用这种方案对小demo是成功的,但是对游戏父进程进行ptrace时会出现问题。
Frida-seccomp方案,上手十分迅速,但是由于异常处理是Frida来做的,而且利用Frida的Process.setExceptionHandler来自己设置异常回调。这就会导致在进行大量系统调用的APP上使用该方案时产生极大的时间损耗,游戏运行极慢,但是可以成功拦截mincore调用并修改参数。
Sigaction-seccomp方案中作者给出了主要思路,即通过sigaction注册信号处理handler,这个注册过程和信号处理是发生在APP内部而不是Frida,所以会快很多。一开始采用自己编译so注入到APP,成功拦截mincore调用并修改参数。为了更方便一点,参考Frida-seccomp方案的思路,直接使用Frida的CModule,无需自己编译so并注入,经实验可以成功拦截mincore调用并修改参数。
关于后两种方案速度的差异可以看,左侧为Frida-seccomp,右侧Sigaction-seccomp172K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2F1L8%4c8A6L8$3&6Q4x3X3g2K6L8#2)9J5c8X3W2E0j5h3N6W2i4K6u0r3K9s2c8@1M7s2y4Q4x3U0f1K6b7g2)9J5y4e0u0r3i4K6t1#2x3V1k6H3M7X3!0V1i4K6u0V1k6X3W2D9k6i4y4Q4x3X3c8K6k6h3y4#2M7X3g2Q4x3X3g2K6x3#2)9J5k6i4g2K6i4K6u0V1N6$3g2K6N6q4)9J5k6o6u0Q4x3X3g2S2L8h3q4*7L8$3&6S2N6%4y4Q4x3X3g2U0L8$3#2Q4x3U0f1J5c8U0y4V1z5h3b7#2z5o6q4T1i4K6u0V1x3h3y4T1k6g2)9J5k6o6b7@1z5h3g2Q4x3X3b7&6y4K6t1K6i4K6u0V1k6U0t1I4y4U0t1$3y4U0u0S2j5e0M7$3i4K6t1#2x3V1j5H3z5h3f1#2x3h3k6V1x3W2)9J5k6o6g2U0y4U0c8Q4x3X3b7@1x3r3x3$3i4K6u0V1j5h3y4T1y4q4)9J5k6o6t1K6x3U0l9$3j5X3q4S2x3o6j5&6k6W2)9J5y4e0u0r3x3U0l9J5y4o6l9I4x3U0b7J5x3e0t1&6i4K6u0W2k6$3W2X3i4K6y4r3N6r3q4T1L8r3g2Q4x3@1c8T1L8r3!0U0K9#2)9J5y4X3q4E0M7q4)9K6b7X3W2V1i4K6y4p5z5h3u0V1z5h3f1H3z5h3u0Q4x3X3b7^5x3K6g2V1i4K6u0V1y4o6l9#2y4q4)9J5k6o6W2V1z5o6g2Q4x3X3b7@1j5X3f1#2y4U0u0W2j5X3t1K6j5e0y4Q4x3U0k6S2L8i4m8Q4x3@1u0@1i4K6y4p5z5h3u0V1z5h3f1H3z5h3u0Q4x3X3b7^5x3K6g2V1i4K6u0V1y4o6l9#2y4q4)9J5k6o6W2V1z5o6g2Q4x3X3b7@1j5X3f1#2y4U0u0W2j5X3t1K6j5e0x3`.
8b4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6x3e0r3g2S2N6X3g2K6c8#2)9J5c8V1k6J5K9h3c8S2i4K6u0V1f1$3W2Y4j5h3y4@1K9h3!0F1i4K6u0V1f1$3g2U0j5$3!0E0M7l9`.`.
直接将js注入即可实现对openat的监控,需要在logcat过滤native查看结果
在实战时根据自己需求修改CModule中的define,其中target_nr 是目标系统调用号。
define
target_nr
在拦截到系统调用后会再次进行系统调用,防止再次被拦截,就需要一个寄存器来放一个标识符SECMAGIC ,避免循环拦截系统调用从而crash。SECMAGIC_POS 即为对应系统调用所不需要的第一个寄存器,比如openat需要三个参数,那么SECMAGIC_POS 填3即可,因为寄存器从x0开始,args[3]即为第四个寄存器。
SECMAGIC
crash
SECMAGIC_POS
openat
x0
args[3]
然后就是在sig_handler 中写劫持逻辑。如果想拦截更多的系统调用,就需要重写seccomp filter 。
sig_handler
seccomp filter
除此之外调用栈等信息,可以参考[原创]分享一个Android通用svc跟踪以及hook方案——Frida-Seccomp 阿碧大佬的思路自己添加。
同理也可以实现对mincore的拦截
再次感谢上述大佬提供的代码和思路,本文意在抛砖引玉,如有侵权联系本人删除。
[培训]科锐逆向工程师培训第53期2025年7月8日开班!