首页
社区
课程
招聘
看雪 2022 KCTF 秋季赛 第三题 水患猖獗
发表于: 2022-11-21 06:01 9907

看雪 2022 KCTF 秋季赛 第三题 水患猖獗

2022-11-21 06:01
9907

惊闻被 hzqmwne 大哥 cue 了一下,不甚惶恐。要不是拜读了您之前的 wp,这第三题应该是没我的(

先来碎碎念:第一次关注 KCTF + 第一次认真调试安卓,居然碰上这种硬茬子 orz

在开赛前看到 app 分类 + 名字 vmp,就是很慌的。到手 apk,jadx 一开没啥看头,核心逻辑都在 native 的 libcrackme.so 里。虽然有 Java_armvmp_cn_crackme_hello 这个符号,但是似乎完全不能逆向,然后就开始了为期两天的各种奇妙却没用的操作,包括但不限于:

周末回家里拿出 root 过的旧手机,又发现:

当时的进展:

直到周日下午,在搜索安卓反调试的资料的时候,居然搜到一篇春季赛的 wp,一看出题人也是 ArmVMP。好家伙,这不得把 wp源码翻烂?尤其是作者的文章,其实已经解释了我好不容易才发现的事 & 一直在猜的坑,比如说 svc 实现的 read write 等。

这篇 wp了解到了frida inline hook,适配一下,可以打印 read write 的参数,对比春季赛源码确认了校验都是在子进程。此外还可以把 PTRACE_CONT hook 成 PTRACE_DETTACH 等等,不过父进程会检查 /proc/self/status 的 TracerPid 得是子进程。当时看到两个进程的 Tracer 都是 0,只是觉得有些奇怪。想 hook open,把 pid 存进文件,竞争了才发现原来 frida hook 也会影响子进程。

至于我 hook pthread_create 的事儿,是因为子进程处理消息也是用 pthread_create 起的,我给他也干掉了。就改成按照地址做了判断:

但是好像没有啥效果,迷惑了半天才发现,js 的运算符优先级,==& 居然要优先...然后就没有再管 ptrace 和 Tracer 了,因为只需要调试子进程,子进程不检查 Tracer。

gdb attach 子进程,刚好前面 inline hook 找到了 read write 的地址。
对 serial 之类的下 watchpoint 看了一会儿,放弃了,决定直接进行内存 diff:serial 的地址是容易得到的,在子进程断在 write 结果的时候,dump serial 所在的整个段。

试各种 name serial 的组合,对比找到所有内存不同的地方,然后就可以发现一些有用或者没用的:

变化中的“低 16 位”似乎能和 hzqmwne 春季赛的 wp 对上。于是提取 fbca8 的值,测试全 0 的输入,和只有一个 FF 在不同位置的输入,模仿一下算法,通过

答案:42A4ECA067F54074C3EB2F177ACB06FE1379055CD4FB2211C3BD874FAD9E101D

吐槽:感觉比起春季赛,反调试保护似乎并没有太多变化。算法大概是增强了,但是只有 name 做了非线性的运算,一通处理算出来的结果和 serial 用稀奇古怪的方法做一些线性比较,导致最后的解法也基本没有变,感觉几乎是原题了。搜 wp 搜晚了,再摆摆烂,分数就只有一半了5555

 
 
 
 
if (func.toInt32() & 0xfff == 0xaa5) {
    ... // 只干掉它
}
if (func.toInt32() & 0xfff == 0xaa5) {
    ... // 只干掉它
}
 
 
data = [0x000025a0, 0x000024dc, 0x0000244c, 0x000024e4, 0x00002556, 0x0000243a, 0x000025a4, 0x0000253c, 0x0000249e, 0x0000244e, 0x000025c6, 0x000025f6, 0x00002530, 0x0000248e, 0x00002618, 0x00002428, 0x000025fe, 0x00002532, 0x0000261a, 0x0000256c, 0x0000247c, 0x0000256c, 0x0000247c, 0x0000242e, 0x000025e0, 0x00002602, 0x0000249e, 0x000024aa, 0x00002516, 0x00002586, 0x000024ca, 0x000024e8, 0x00002604, 0x000025ea]
print(bytes((0x2525-x+0xff) // 2 for x in data).hex().upper())
data = [0x000025a0, 0x000024dc, 0x0000244c, 0x000024e4, 0x00002556, 0x0000243a, 0x000025a4, 0x0000253c, 0x0000249e, 0x0000244e, 0x000025c6, 0x000025f6, 0x00002530, 0x0000248e, 0x00002618, 0x00002428, 0x000025fe, 0x00002532, 0x0000261a, 0x0000256c, 0x0000247c, 0x0000256c, 0x0000247c, 0x0000242e, 0x000025e0, 0x00002602, 0x0000249e, 0x000024aa, 0x00002516, 0x00002586, 0x000024ca, 0x000024e8, 0x00002604, 0x000025ea]
print(bytes((0x2525-x+0xff) // 2 for x in data).hex().upper())
 
1
2
3
if (func.toInt32() & 0xfff == 0xaa5) {
    ... // 只干掉它
}
1
2
data = [0x000025a0, 0x000024dc, 0x0000244c, 0x000024e4, 0x00002556, 0x0000243a, 0x000025a4, 0x0000253c, 0x0000249e, 0x0000244e, 0x000025c6, 0x000025f6, 0x00002530, 0x0000248e, 0x00002618, 0x00002428, 0x000025fe, 0x00002532, 0x0000261a, 0x0000256c, 0x0000247c, 0x0000256c, 0x0000247c, 0x0000242e, 0x000025e0, 0x00002602, 0x0000249e, 0x000024aa, 0x00002516, 0x00002586, 0x000024ca, 0x000024e8, 0x00002604, 0x000025ea]
print(bytes((0x2525-x+0xff) // 2 for x in data).hex().upper())
  • 摆弄前几个月换掉的小米前主力机,想 root 才发现之前没绑定不给解锁
  • 捣鼓模拟器,发现模拟器都是 x86 的,就算打了补丁装上 apk 也跑不起,又不乐意装 Android Studio 用里面 qemu 的 arm
  • IDA 翻翻 Ghidra 看看,除了一堆没有引用的字符串,啥也看不出

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-11-21 06:05 被tkmk编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//