绿城杯总结

前言

上午上课,中午开始看的题目

说实话,这次的比赛有把我捞到,哎

总结经验,吸取教训吧

easy_re

常规题,不多bb。

main函数有个花指令,去一下

image.png

反编译看main函数

image.png

观察算法特征,是RC4,但是有个细节变异 多了个异或0x37

key也有,密文动调得到

编写exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
key = 'tallmewhy'

text = [0xF5, 0x8C, 0x8D, 0xE4, 0x9F, 0xA5, 0x28, 0x65, 0x30, 0xF4,
0xEB, 0xD3, 0x24, 0xA9, 0x91, 0x1A, 0x6F, 0xD4, 0x6A, 0xD7,
0x0B, 0x8D, 0xE8, 0xB8, 0x83, 0x4A, 0x5A, 0x6E, 0xBE, 0xCB,
0xF4, 0x4B, 0x99, 0xD6, 0xE6, 0x54, 0x7A, 0x4F, 0x50, 0x14,
0xE5, 0xEC]
v2 = 0x100
enc_key = []
for i in range(0x100):
enc_key.append(i)
v1 = 0
for j in range(0x100):
v1 = (enc_key[j] + v1 + ord(key[j % len(key)])) % 0x100
v4 = enc_key[j]
enc_key[j] = enc_key[v1]
enc_key[v1] = v4 ^ 0x37

v0 = 0
v1 = 0
for i in enc_key:
print(hex(i), ',', end='')
for i in range(len(text)):
v0 = (v0 + 1) % 0x100
v1 = ((enc_key[v0] & 0xFF) + v1) % 0x100
v3 = enc_key[v0]
enc_key[v0] = enc_key[v1]
enc_key[v1] = v3
text[i] = text[i] ^ enc_key[(enc_key[v0] + enc_key[v1]) % 0x100]

print()
print(''.join(chr(text[i]) for i in range(len(text))))

# flag{c5e0f5f6-f79e-5b9b-988f-28f046117802}

抛石机

这题是真的吃了浮点转换和运算的亏了,他的判断逻辑还是比较好把握的

1

这里是判断输入的格式,必须得是flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx},字符x的内容可变

contx的内容,8个字节为一组,然后存入4个全局变量中

2

然后是check函数,内容如下:

2

其实就是两个2元一次方程,一共得4个解。

不是等式方程(有个范围值,但很小),有师傅索性直接等于0,然后求解方程。

其实用范围约束来爆破得到的结果其实也一样,这个就不管了,不是我总结这题的重点

check函数开头有两个判断,可以用来判断一个2元1次方程的两个解应该分别是哪个变量

求解方程脚本——z3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from z3 import *

x = Real('x')
# y = Real('y')
z = Real('z')
# l = Real('l')

set_option(precision=20) # 设置小数位数
# 精度不够的话可能后面转16进制表示形式的时候会有差别
s = Solver()

v4 = 149.2 * x + x * (-27.6) * x - 129.0
# v3 = 149.2 * y + y * (-27.6) * y - 129.0
v2 = z * -39.6 * z + 59.2 * z + 37.8
# v1 = l * -39.6 * l + 59.2 * l + 37.8

s.add(v4 == 0)

# s.add(v3 == 0)

s.add(v2 == 0)

# s.add(v1 == 0)

print(s.check())
while s.check() == sat: # 求多个解
m = s.model()
print(m)
s.add(Or(x != m[x]), z != m[z])

#sat
#[x = 1.08063237896641294938?, z = -0.48267319186340060660?]
#[z = 1.97762268681289555610?, x = 4.32516472248286241293?]

由输出结果加上前面的分析可以判断:

  • x == 1.08063237896641294938
  • y == 4.32516472248286241293
  • z == -0.48267319186340060660
  • l == 1.97762268681289555610

转16进制形式exp——struct

坑点都在注释里写上了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import struct


def d2hex(f):
return hex(struct.unpack('<Q', struct.pack('<d', f))[0]) # double 转 qword(hex)


def hex2d(f):
return struct.unpack('<d', struct.pack('<Q', f))[0] # qword 转 double


print(d2hex(1.0806323789))
print(d2hex(4.3251647224))
print(d2hex(-0.4826731918))
print(d2hex(1.9776226868))

# 实际输出:
# 0x3ff14a452d65fca5
# 0x40114cf7fb22156c
# 0xbfdee41e195bf6c0
# 0x3fffa457afba236f
# 坑点之一:
# 程序中用到的只是高位4字节的值,后面的值与精度有关但不影响结果
# 所以截断一下(注意舍去和进位)
# x = 0x3ff14a45
# y = 0x40114cf8
# z = 0xbfdee41e
# l = 0x3fffa458
# 坑点之二:
# 这里是要让程序给变量赋值完后,xyzl的qword值得分别如上
# 所以flag要自行倒一下序(小端序)

# flag{454af13f-f84c-1140-1ee4-debf58a4ff3f}

无坑写法——C

其实C语言本身带的格式控制符写这种浮点数的题比python更自然一点,直接copy其他师傅的脚本了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

int main()
{

for(unsigned long long int i=0;i<0xffffffff;i++)
{
unsigned long long int tmp = i<<32;
double tmp2 = *(double*)(&tmp);
double v4 = 149.2 * tmp2 + tmp2 * (-27.6) * tmp2 - 129.0;
double v2 = tmp2 * (-39.6) * tmp2 + (59.2) * tmp2 + (37.8);
double v1 = tmp2 * (-39.6) * tmp2 + (59.2) * tmp2 + (37.8);
if( v4>-0.00003 && v4<0.00003)
{
printf("v4:%p\n",i);
}
if(v2>-0.00002 && v2<0.00002)
{
printf("v2:%p\n",i);
}
if(v1>-0.00003 && v1<0.00003)
{
printf("v1:%p\n",i);
}
}
return 0;
}

//「努力学习的大康」

babyvxworks

这题说实话是自己放弃了,vxworks好像是固件逆向,没做过,以为自己不会,没太认真看

后面看了下wp发现也就那样。。认真看应该是能做出来的

有很多花指令,有点去不干净**(tcl**,等一个大佬的去花wp,逻辑比较简单,就不分析了

exp

直接copy的ChaMd5的exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
c=[188,10,187,193,213,134,127,10,201,185,81,78,136,10,130,185,49,141,10,253,201,199,127,185,17,78,185,232,141,87]
t=30
def decrypt(c,t):
for i in range(len(c)):
for j in range(t):
c[i]-=3
c[i]=c[i]+0x100&0xff
c[i]^=0x22
# print(bytes(c))
for t in range(1024):
d=[i for i in c]
decrypt(d,t)
j=0
while j<len(d):
if d[j]<32 or d[j]>128:
break
j+=1
if j==len(d):print(bytes(d))
# print(t)

flag{helo_w0rld_W3lcome_70_R3}

Comments