-
-
看雪 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 看看,除了一堆没有引用的字符串,啥也看不出
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!