ddctf 2018 android writeup

 空余时间刷了下ddctf,ak 了 android,不难,整理发一下 writeup。

文件链接:https://github.com/LeadroyaL/attachment_repo/tree/master/didictf_2018

一、LeveL1

Java 层什么都没有,直接看 native;native 里包含了一些数学计算。

有 init_array ,但里面主要是一些线程相关操作的初始化,没有JNI_OnLoad。

上来先算了32次平方,不知道想干嘛,调用2次 GetTicks ,不知道想干嘛。之后把输入转为 std::string 类型,进入 check  函数。

首先检测长度是否为36,以及与 const-data 进行 xor。

这个地方校验第0~10、第11~20、第21~30、第30~40是否一模一样。

最后的检测是

这里v3最后被返回了,要求是前者能够整除后者,而且会有除数和商的大小比较,只有除数大于上时候才有可能返回1。

往上翻,发现输入仅与除数有关。

被除数是由两个字符串算出来的,怎么算出来的我也看不大懂,好像是重新组合成一个字符串,拼接字符什么样的,应该可以直接 dump。

【后来看某位老哥写的 writeup,发现是通过2个字符串取 index 得到的】

https://blog.csdn.net/dydxdz/article/details/80037937

先创建 map<char,int> ,第 i 个 char对应的数字是 i/2 ,刚好得到每个 char 对应 [0,10) 的数字;再查询 str2里每个 char 所对应的下标,将这个下标加上 '0' ,拼起来,得到新的十进制的字符串。

综上,拿到数字 5889412424631952987 ,将它分解了, 5889412424631952987=1499419583*3927794789 ,输入就是偏大的数字, 1499419583 ,再 xor 一下常量就行了。

最后 flag 是 d5axivcw6ggfswpxg80estgc58h7yghqogbm 。

二、LeveL2

看起来使用的是 Robust 的热更新框架,没有做太特殊的处理,在 assets 里存放了 GeekTan.BMP ,其实是个 zip 包,里面放着 Robust 的 patch 文件。

有简单的方法,也有复杂的方法,复杂的就是肉眼去看,把代码运行一遍即可,是个约瑟夫问题,也可以直接求解,跟我以前出的用栈写约瑟夫很像。

简单的方法嘛,直接上 xposed

三、LeveL3

Java 层什么都没有,直接看 native。

init_array 应该是初始化一些东西,没有过多操作。

没有JNI_OnLoad。

直接看 JNI 的方法,进入之后先将输入转化为 std::string ,再使用 str2ll 转为int64。

长得比较丑,看起来是做 divmod(int64, int64) ,循环终止的条件是 i==int64(input) ,最后检测余数是否和预期相等。

debug 一下,大概就是左移1bit,mod 一下,左移1bit,mod 一下这样,写段 python 爆破即可。

不知道这题想干嘛。。。

四、LeveL4

这次只有 java 层,没有 native 层,看起来使用了公开的第三方库 spongycastle,所以丢到网站上 deguard 一下,得到一个非常优美的结果~

官方说是10位以内的数字,所以是暗示爆破,而且 ECC 么,除了爆破也没有办法。

使用的是 ECC 加密算法,使用secp256k1曲线,先拿到 G 点,与输入进行椭圆域上的相乘,得到新的点,去校验计算出来的点是否是预先规定好的那个点,是的话就 return true 。

这个没什么操作,就是按照描述去爆破,一开始懒得写 java 代码,直接在手机上爆破的(原谅我脑残),发现速度简直慢到炸,手机烫了一晚上也没跑多少数据。

然后想着优化,但发现这个 API 似乎很不好用, G+G+G  和 G*3 不相等,以及各种神奇的表现,可能是我不大会用 API 吧,按理说加法比乘法好做很多,每次加一比每次乘法应该要快,但优化时候老是算出来的不一样,就懒得优化了。

最后在 PC 上写个爆破脚本,早上起来就看到了 flag,DDCTF{54135710}。

五、LeveL5

这题就是反调试的大集合,乱七八糟的方式什么都有,Java 层没有东西,直接看 native。

init_array 没有特殊操作,是 C++的初始化。

JNI_OnLoad里动态注册了 JNI 函数,没有额外操作。

直接看了哈,最原始的长这样

将输入操作一下,xor 一下,返回的是 strncmp 的结果,这不是送分题么?直接上去调试,断下来,发现答案并不对。。。有几个反调试的函数,把 xor_key  给修改了。

sub_3c54是第一个函数,先做一些不知道什么的操作,再检测 tracerPid那行的 strlen ,可以绕过,然后去从sha256_table里取一些值,不知道想干嘛。内层还有一堆不知道在干嘛的函数,估计藏了一些反调试,而且会对 global 的值进行一些操作,乱七八糟的。

反正每次都会被测到反调试,于是懒得搞了,我认输,ok?

patch 一下 binary 文件,因为是简单的 xor,所以只要能拿到xor_key 即可,在最后一句他是strncmp,如果把它 patch 为memcpy的话,在正常运行过程中,就可以将算出来的密文保存下来。之后想办法 dump 内存,就能拿到密文,与输入进行 xor ,就拿到了 key。

经过一番努力,终于 patch 成功了。。。如上图的最后一个 memcpy。

先运行,让它算一遍,再 attach,断在最开始,就能拿到明密文对了。

最后算出来是DDCTF{GoodJob,Congratulations!!}。


=============================================================
随着访客的增多,LeadroyaL在本站流量的开支越来越多了,曾经1元能用1个月,现在1元只能用3天。如果觉得本文帮到了你,希望能够为服务器的流量稍微打赏一点,谢谢!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code