TSCTF-J 2023
Misc:
- 白夜:
打开之后提示点击等待秒数,点击后开始计时。用processhack暂停进程,ce搜索秒,再次暂停,再次搜索,然后修改。
不想复制的话,ce搜一下再复制也可以
Web:
- 十年之约:
随便输入一个答案按住回车不放就行了
AB:
- abstract:宣讲彩蛋猜故事 人生得意须尽欢莫使金樽空对月
- Music:刚到学校,听音乐,所以是传邮万里。看歌词,严谨在这里铸就创新从这里萌芽
- Movie:电影名有法语e,也有7,所以就是TSCTF-J{七个法语e}
- ancient poetry:古诗 二十四桥明月夜
- Music revenge:百度搜一下和李诞有关的歌
实现你所有浪漫的幻想
REVERSE:
- the path:根据提示,这里面有五万条路,也就是说五万个函数
main里面调用第一个,然后嵌套调用,最后会出结果
判断肯定是其中的某一个。这一我们就生成pattern,然后搜索,看看谁没出现就可以了。
使用IDA FUSION,生成出55 48 89 E5 48 83 EC ? 48 89 7D ? 48 8B 45 ? 48 89 C7 E8 ? ? ? ? C9 C3 55 48 89 E5 48 83 EC ? 48
Alt+b搜索 全部导出到txt,再用python找下在哪不连续了。发现两个函数
写脚本
3.The_GoBang
一看就是c#写的,直接放到dnspy去。
找到getflag()这里,这里有校验。
Form1.flag再分析一下,发现是落子时用来记录位置的
肯定不能遍历所有落子可能。我们直接逆向这个算法。根据Hint。
左移一位之后最后是0,如果被异或了就是1,如果没被异或还是0。再根据这个判断最高位是什么,也就是是正还是负
得到结果8536368890943866260,去dnspy修改一下
再改一下button1.click,判断按键就给flag。
- The_Step
IDA打开进入Main函数
这么简单一眼假。怀疑真正的输出字符串被加密了,x64dbg跟进一下,找到真正的main函数
果然都是异或7之后输出的。然后我们用x64dbg接着跟进,找出来这些处理字符串的操作,我们分别按顺序命名1234.
从4321反着推理来写过程
- The Magic
根据Hint找到tls回调函数。也是字符串异或了保存,防止被shift+f12看出
根据这里解flag,解出来发现是
这显然是不对的。缺少了某些东西。根据hint中提到的try except异常处理,我们再回汇编查看。
这里除法除数为0就会触发异常处理,然后就去except那边了,这里显然和try里面的方式是不一样的。我们根据汇编写出逆向的代码即可。
- The_shell
查壳发现无壳
但这里其实是有一个upx壳的,猜测有没有可能把加壳信息抹掉了呢?拖进x64dbg手脱。
运行到input处 直接用scylla dump出来就行了 不用管入口点 iat auto search就可以
把scy.exe拖进ida
非常简单的加密函数
提取数据,写脚本
因为数据之间间隔了三个0,所以我们给它写成i*4
- The Art
因为有代码自修改,我们直接去x64dbg执行到printf的地方,然后再dump出来,代码自修改就没了。然后看IDA
Main函数没有主动反编译出来,我们去除一下花指令,然后再创建main函数
Ctrn+alt+f看一眼,是sm4加密
所以就看明白了。这里做了一个sm4加密,密钥是v19,v20,v21,v22。
其中22,23,24,先左移八位,然后把用户输入附加上。用户输入作为三个16进制数字,拼接之后形成key。
所以key是
A98737XX F75B8AXX FE9118XX 705ADE09
其中XX是未知字符,我们需要破解,破解之后这三个十六进制连在一起求md5就是答案了
加密之后的密文在下面也有,是
97D579F4 DFA9F2C7 5D2DAAE7 204BFFBB
而被加密的明文是这里的连续数组
找过去就看到了
其实就是中文 提问:艺术就是?
然后编写我们的脚本进行爆破,因为艺术就是爆炸
遍历所有可能密钥 结果
加密得md5:
- The Native
这是一道安卓逆向题。用jadx打开
找到入口
初始化string,然后判断长度,再比较,计算,比较。用ida打开so即可。
找到对应构造函数。读数据,然后拼接。直接提取数组
执行完这两步并没有得到正确flag,发现总是差^48,所以我们再补上
- The_devil
这是一道虚拟机逆向。先看main函数。经历了三个函数的调用之后,然后去判断是否相等。那判断条件的一个数组就是结果。直接提取出来。
接下来就是要看怎么根据结果来拿到我们的输入了。先看调用的三个函数。
第一个:给一个数组赋值为0,有012345五个元素。
第二个:
通过switch来寻址。所以我们发现其实dword_140097d0就是寄存器,0是0号,同时也控制下一次执行哪里的命令,也可以当作rip。+1为1号,+2为二号,以此类推。
所以dword_140007040就是机器码,也就是switch寻址的地方。
所以我们把名称稍作修改,就清晰一些了。
然后我们把switcharray这个数组给提取出来。大概格式像这个样子
就是到case多少,1,2大部分都是寄存器,15这种大部分都是基址
根据这个去case里面找,写出类似汇编的东西。然后再化简。注意~&|这里可以化简成异或
然后再写出反向的代码:
直接把result放进来跑,是出不来结果的。想起来一开始看到了三个函数,接着回去看。
第三个函数像这样,不知道为什么会对result再进行操作啊,并没有直接的操作,猜测可能是通过伪寄存器的那个数组索引到了。可以看到上面下面两个函数,解密switcharray,放到v123,然后加密再存好。我们直接把加密过程给nop掉,再来ida动态调试下断点。看到这样。
这个函数完全执行完就可以把switcharray给提取出来。因为第一次return ++FackEIP,所以这次从第一个255之后开始执行,然后到下一个255结束,拿出来动态调试提取的数组看一下,并根据这个再写一个类似于汇编的操作出来。
用到了索引8,-432,这是一组,然后下面是类似的相同操作,只是变成索引9,-431,那么这些位置是什么呢。8其实是第一次处理完了之后的字符串,-431是另一个字符串,得到为
char love[] = "LoveCanConquerEverything";
化简汇编
其实一大堆或非和刚才的一样,也是异或,那我们就可以写出更简单的C++代码
所以进行异或后输出。
然后我们再放到我们第一个逆向的加密算法里,进行再一次的解密
出现了flag:
TSCTF-J{You_successfully_dispelled_the_devil_within_three_days!}