这东西没怎么研究过,不过很多人都完成了,不过这种比赛有很多应该是拿的别人的wp,所以减去些水份,赛后拿到一个wp是人c程序实现的。然后根据原代码还原一下加密流程。
首先是main
这里比较特殊,一开始的3个变量明显是加密函数,可以是程序并没有用到,只在比较长度为40以后就作了个与0x401的异或就结果了。
然后看汇编main这部分
这里是main的开头,后边这个箭头是花指令,实际上什么都没作(call指令长度是5,直接调用call $+5就等于接着执行)但 ida会在这里报错经常导致反编译出些问题。
前边3个箭头是另一种花指令吧,直接把3个函数地址压入栈中,在最后不平衡栈的情况在ret的时候会被作为返回地址执行。
main |
0x401220 |
0x4011a0 |
0x401100 |
然后再看0x401220
先把一个函数存入arg_4,这人函数是个明文加密后与密文比较的函数,跟进后发现它把这个函数放在下两个函数之后
再回来看220干了啥
他先执行了一个+=i*i的操作然后调用0x401560
它执行了 ^=i*(i+1)的操作,然后把 15af存入 4470然后就跳出结束了
220这块就结束了,然后下边 1A0
1A0,作了两个压栈分别是1E4和470(470是上一步存入的5AF)也和开始一样是通过压栈实现函数调用。
回过头来再看5AF在执行啥操作
这是个循环操作计数器用370,然后对每个值减序号: -=i
后边的1E4函数
这里执行了: *=3 操作
后边是100函数
虽然有点长,但是这块没啥特殊操作,可以直接反编译,这块是一个0空间实现两值交换的程序(编程入门会有)
然后就是290去比较了
加密过程是这样
main | ^=0x401 | 存入220,1A0,100作为后续执行函数 |
220 | +=i*i | 存入290到100之后,并调用560 |
560 | ^=i*(i+1) | 从偏移10开始的20个数 |
1A0 | 存入后续执行5AF,1E4 | |
5AF | -=i | 5AF不是个完整的函数 |
1E4 | *=3 | 1E4也不是完整的函数 |
100 | 交换 | 从偏移10开始对10对数(20个)两两交换位置 |
290 | 与密文比较 |
对照这个反过来写解密程序
c = [3279, 3264, 3324, 3288, 3363, 3345, 3528, 3453, 3498, 3627, 3708, 3675, 3753, 3786, 3930, 3930, 4017, 4173, 4245, 4476, 4989, 4851, 5166, 5148, 4659, 4743, 4596, 5976, 5217, 4650, 6018, 6135, 6417, 6477, 6672, 6891, 7056, 7398, 7650, 7890]
c1 = c[:10]+sum([[c[10+i+1],c[10+i]] for i in range(0,20,2)],[]) + c[30:]
c2 = [((v//3)+i)%(1<<32) for i,v in enumerate(c1)]
c3 = c2[:10]+[c2[10+i]^(i*(i+1)) for i in range(20)] + c2[30:]
c4 = [(v-i*i)^0x401 for i,v in enumerate(c3)]
bytes(c4)
#b'DASCTF{TWpnemRuSTRkVzVsWVhOMmJqZzNOREoy}'