起因

早都想出题了,之前不是打了个 ISCC 吗?

擂台赛有某组织进行一些匪夷所思的操作,看得我也想出一道题,越难越好,越变态越好。

我们联合起来!形成🍞🧀🍞;

于是就诞生了 这道 《1+1的签到题》

出题思路

我接触逆向时间并不长,小半年不到。看的题也不多,想拿出一些新鲜的好玩的东西出题。

就想起来之前 美国普度大学 举办的 b01lers-ctf-2021 中出现的新题型(对我来说):

残缺程序逆向;

这种题难度较高,对逆向的思维和技术有较高要求。但是我水平受限,不能把精髓提炼出来。

所以降低了题目难度;题目中并没有太多的函数调用,减少了难度。加密也用的非常常见的base;一眼就能看出来。算得上签到题了。

伪随机数

基础就不讲了,百度一大堆。

建议上手试验一下,用C语言写一个随机数脚本,python写一个。都制定相同的种子。在windows下和在linux下运行结果都是不同的。

所以要严谨,该题编译为elf文件就是在暗示要在 linux 下的随机数。

base换表

一个是base58的换表,即便粗心也能因为报错反应过来。

第二层是base64的表,我定义了一个假表,在加密时并没有用到,仔细就能发现真正的表在哪里。

小插曲——数据溢出

事情是这样的,题目出了以后有师傅解出的 flag 和正确的相差一位。

在师傅提醒下发现数据溢出了,反而没有仔细看数据宽度的人能解出正确答案。我连忙改代码更新附件,数据问题大概如下:

1
2
3
4
5
C
……
int guess = 20*rand()
youarefast();
if((input ^ 0x235fffa864 ^ rand() ^ 0x67b7940f53) == guess)

int 是四字节,但是 rand() 返回的也是四字节,相乘导致数据直接溢出,舍去了一位。

第一次修正是将定义去掉,直接带入式子。但是并没有变化,因为存放返回值的还是四字节的寄存器 EAX ;

第二次修正直接采用了 强制转换,代码如下:

1
2
3
C
youarefast();
if((input ^ 0x235fffa864 ^ rand() ^ 0x67b7940f53) == (long) 20*rand())

但是这里伪代码还是没有改变,我急了、慌了。

这才想起了 师傅曾经说过,不要过度依赖 F5 ;跑去看汇编,发现此时寄存器已经变为 RAX,八字节。

小插曲完美解决。

收获

第一次出题,刺激、紧张、开心。

看到自己出的题被别人做出来,心里的石头也落下了,起码说明了我的题还是能写的。

出题过程也很辛苦,由于没有经验,出现了各种各样的 BUG ,源代码改了又改,编译删掉再编译。

好处是真不少,有贴纸,有 小钱钱。

最大的收获莫过于弥补了我一下基础漏洞。

也让我明白了想要学好逆向,就不能依赖于 F5 和 F12 。

题目以及wp

小红解开了混乱音频后发现文件夹里还有一个没有后缀名的文件。小明告诉他,那是一个藏有秘密的程序但是主函数没有写完。小红心想里面一定是小明对他的告白,于是打算找一个工具人来帮忙。你能帮助小红找到小明藏在程序中的秘密吗?

注:主函数未写完

将得到的答案加上flag{}提交。

附件:1+1=的签到题

提取码:shan