\*CTF-2022-someRE
*CTF-2022
题目本身逻辑不难,主要偏向于基础能力的考察,时间在看汇编和调试的过程中慢慢溜走。还有就是淦RE时不要中途去玩儿别的方向,坚持才是胜利,一遍调试不行那就来N遍,当然合理的搜索和工具的使用往往会加速分析。🤔🤔🤔
Simple File System
tip:debug
签到题,虽然名字听起来有点吓人。
生成文件进行的操作。
1 | I implemented a very simple file system and buried my flag in it. |
主要关注plantflag
操作,只有当sub_1E16("flag", v17, 1)
才会写入加密后的flag,其余都是写入随机数。
读写都以4k为单位,并且写入的数据长度为0x20,v4是从第一个数据块中取出的4Byte数据0xDEEDBEEF
,之后将处理后的flag写入文件。
可以通过调试模拟生成文件的过程拿到v4,定位flag写的位置。通过010观察
image.flag
文件,4k一块,每块开头处便是写入的0x20Byte数据,直接遍历所有解根据flag的格式判断即可。
1 | f=open(r'G:\game\X-CTF\RE\文件系统\image.flag','rb').read() |
解密时异或的的key写成了ED ED,没有直接静态干掉,之后结合调试发现抄错了key。
NaCl
tip:Feistel/Xtea
r15模拟esp,自己维护的堆栈,所以IDA反编译的代码就比较乱,不过加密的逻辑块不是很多,调试加读汇编即可。=.= 硬逆
大🔥出题时间差不多,差一点点就摸到血了😭😭😭。
Xtea的delta和轮数被魔改了比较坑,并且在之前还进行了Feistel
结构的加密。首先秘钥扩展,得到长为44的int数组,不过秘钥是固定的可以直接dump生成的扩展秘钥。
贴一下当时跟踪时记录的数据处理信息。
1 | def rol(n,m): |
exp
魔改Xtea
1 |
|
RE-Feistel
1 | tb=[0x04050607, 0x00010203, 0x0C0D0E0F, 0x08090A0B, 0xCD3FE81B, 0xD7C45477, 0x9F3E9236, 0x0107F187, 0xF993CB81, 0xBF74166C, 0xDA198427, 0x1A05ABFF, 0x9307E5E4, 0xCB8B0E45, 0x306DF7F5, 0xAD300197, 0xAA86B056, 0x449263BA, 0x3FA4401B, 0x1E41F917, 0xC6CB1E7D, 0x18EB0D7A, 0xD4EC4800, 0xB486F92B, 0x8737F9F3, 0x765E3D25, 0xDB3D3537, 0xEE44552B, 0x11D0C94C, 0x9B605BCB, 0x903B98B3, 0x24C2EEA3, 0x896E10A2, 0x2247F0C0, 0xB84E5CAA, 0x8D2C04F0, 0x3BC7842C, 0x1A50D606, 0x49A1917C, 0x7E1CB50C, 0xFC27B826, 0x5FDDDFBC, 0xDE0FC404,0x0B2B30907] |
出题人: 很抱歉所有玩家通过对原始汇编代码的动态调试和静态分析解决了这个挑战。因为我的隐藏逻辑代码很短。太糟了。
预期: 首先,转储段SFI和SFI_data。然后,您通过脚本代码修改二进制文件。您需要恢复堆栈、寄存器和指令调用、ret 等。
这,确实自动化逆向工具和ipython的运用还不到位,暂时不会写。😔😔😔
jump
tip:setjmp/longjmp
硬逆
逆出流程的时候有点晚了,没看懂逻辑,肝不动了。。。
无符号,控制流不清晰,逻辑比较乱的,看一下数据段的信息准备动调。
密文是34位,并且第一个函数就是输入。
1 | input="01234567abcdefghijklmnopqrstuvwxyz" //测试输入的长度有问题 结合下文分析应为32位 |
之后进入进入sub_46a4c0
函数,a1明显是一个结构体,可以通过调试信息定义一下。
原本猜测为虚拟机,但后来发现这是保存上下文的操作,结合调试信息定义结构体存放数据,若了解
setjmp/longjmp
直接改参数为jmpbuf结构体即可。
直接按照setjmp函数的参数进行修复,大致如下。
1 | //env 结构体是全局变量 |
那么sub_401D45
函数则是longjmp
。
在函数sub_402689中实现加密操作。
其中longjmp与外层函数的交互,依次将处理后输入字符循环左移。
内存中如下
1 | var=0//2 '01234567abcdefghijklmnopqrstuvwxyz'3 |
生成了一系列的tmp_str
数组,接着进入sub_401F62
函数进行处理。
该函数是对str_arr中的字符串组进行升序的快速排序,=.= 当时没认出来。第一个字符从小到大。
之后又按照类似操作循环取字符,每次取str_arr[i][0x21]。
内层通过jmp_buf
变量env来保持上下文。
循环0x22次获取enc,最后longjmp(env,0x23)
调到check函数的比对处,相等则返回并输出,加密算法和测试数据如下。
1 | testinput='01234567abcdefghijklmnopqrstuvwxyz' |
exp
1 | import copy |
这次的测试输入和算法识别上失误有点大,去符号猜的函数有点偏差,C的基础确实薄弱了点,没识别setjmp和longjmp。
符号恢复
可以使用Finger - 符号恢复-github来恢复库函数符号,真脚本小子的福利,基本上常用库函数都被复原了,分析直接上高速。
恢复了一些库函数的符号,增加了程序的可读性,同时调试时也可以快速判断一些处理。
end
唯有自信和坚持,才能得到自己想要的结果。👏👏👏