hctf2017 level2

Author Avatar
Xzhah 12月 04, 2017
  • 在其它设备中阅读本文章

这是我接触ctf以来见过最喜欢的题,无论是思路还是各方面,杭电大佬真厉害

* 思路

其实这是一个类似解释器的东西,然后他用以下数据实现操作
1.png
比如开头,是把b号寄存器的地内容赋给1号寄存器
我们可以查看一下他所有的寄存器都放了啥
2.png
做下去我们会发现其实3号寄存器就是ecx,5号寄存器就是esp。。。等等

* 加密思路

0 0000->51->19 不停+19mod32 第二阶段 归0
1 0000->input的地址(case4 把地址赋给一个值)
2 0000
3 0000->case12 自加1
4 0000->case1过后得到a也就是input[19]
d_word4040 0000 经过case40置1
ebp-4ac 当前ip
v59得到当前ip
b input
9得到input 地址变为input+19
a得到input[19]
5得到4也就是input[19]的值后地址自加4,类似栈顶指针
v53经过case36比较寄存器3号和32的大小后,返回1

第二阶段
8号寄存器得到5号的值
8号左移32个int
2号得到8号
a得到2
0得到a
将0号寄存器高三位内容赋给自己本身再右移五位
4号得到0号的值
进入循环
a号得到2号寄存器的值
0号得到a号的值
0号取低五位赋给自己然后左移三位赋给自己
5号得到0号的值,然后五号指针后移四位(入栈)
8号得到5号的值
8号指针左移128位,也就是32个int,也就是取之前压入的第二个值
2号得到8号的值
a得到2
0得到a
0将高三位赋给自己右移五位赋值给自己
出栈 a得到5号寄存器的值 5号指针左移一个int
a号+0号的值赋给a
5号得到a的值然后指针右移一个int 入栈
3号寄存器自加然后判断是否小于31,若是则返回1给v53
循环判断v53为0则跳出循环

第三阶段
a得到2的值(也就是按19mod32规律取出的最后一个数)
0号得到a号的值
0号取低五位然后左移三位
4号加0号的值赋给0号
入栈 5号得到0号的值后指针右移一个int
3号寄存器清0
4号得到d号的值(deadbeef)

进入循环
8号得到5号的值
也就是加密处理后的第一个值
8号左移32个int,指向加密处理的第一个值
2号得到8号寄存器的值
a号得到2号
0号得到a号
5号得到0号的值并右移一个int 入栈
0得到4号 (deadbeef)
0号为0号内容+3号 也就是第一次应该为0xde
出栈 a得到5号寄存器的值 5号左移一个int
a号与0号异或的值给a号
入栈 5号得到a的值然后右移一个int
4号寄存器右移8位再与上2^24-1(
2^8-1 与上 4号寄存器的值然后左移24位
4号寄存器得到以上两个结果的和(循环右移八位)
3号寄存器加上1
判断三号寄存器是否小于32 若是返回1给v53
如果>=32则跳出循环

第四阶段
3号4号寄存器清0
1号寄存器得到c号寄存器的值 (0xd5 0xa5 0xcb 0xf9)
进入循环
9号寄存器得到1号寄存器的值
九号寄存器地址加三号寄存器的值赋给9号
a号得到9号的值
0号得到a号的值
入栈 0号赋值给5号 并且5号右移一个int
8号寄存器得到5号寄存器的值
8号左移33位,也就是得到之前0号a号异或第一个
a号得到8号的值
出栈 0号得到5号的值
入栈 5号得到0号的值
判断 a号0号是否不相等 是为1 给7号寄存器
4号或7号的内容给4号
3号自加
判断3号是否小于32
如果大于等于32就跳出循环

最后 如果4号寄存器为0则成功

* 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
getit=[]
encry=[0]*32
debf=[0xde,0xad,0xbe,0xef]
flag=[0]*32
realflag=[0]*32
enc=[213, 165, 203, 249, 9, 185, 207, 253, 237, 189, 195, 33, 225, 177, 199, 245, 221, 181, 219, 9, 249, 97, 223, 13, 253, 205, 195, 1, 241, 193, 215, 77]
for i in range(32):
getit.append((i+1)*51%32)
for i in range(32):
encry[i]=enc[i]^(debf[i%4]+i)
for i in range(31):
flag[i]+=(encry[i]&0xf8)>>3
flag[i+1]+=(encry[i]&0x7)<<5
flag[31]+=(encry[31]&0xf8)>>3
flag[0]+=(encry[31]&0x7)<<5
for i in range(32):
realflag[getit[i]]=flag[i]
print("".join(chr(c) for c in realflag))

* flag

3.png 4.png

* 感受

真的非常敬佩杭电的大佬,首先每个题目动态编译出不同flag就能看出他们在反作弊方面做出的努力。
然后就是re的题都很有质量,但就是有点难,感觉bin狗活不下去了
最后,希望杭电大佬都能找到女朋友 : )