SUCTF2019-MT
首先要知道位运算的优先级,由高到低:<<,&,^
考点
- MT19937
题目代码
1 | from Crypto.Random import random |
朴素的方法
第一次接触MT19937,最直观的想法就是把convert逆回去
第一四组位运算
与第一个位运算相同,第四个位运算也可以逆回来
1
2
3
4
5
6
7def forth_cal_re(c, x):
y = len(bin(c)[2:])-x
c = bin(c)[2:]
part1 = c[0:x].zfill(x)
part2 = bin(int(c[x:], 2) ^ int(c[:y], 2))[2:].zfill(y)
output = int(part1+part2, 2)
return output合并一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18def first_cal_re(c, x):
y = len(bin(c)[2:].zfill(31))-2*x
if y <= 0:
y = len(bin(c)[2:].zfill(31)) - x
c = bin(c)[2:].zfill(31)
# 高x位完全相同
part1 = c[0:x].zfill(x)
part2 = bin(int(c[x:], 2) ^ int(c[:y], 2))[2:].zfill(y)
output = int(part1 + part2, 2)
return output
c = bin(c)[2:].zfill(31)
# 高x位完全相同
high13 = c[0:x].zfill(x)
# 中间的几位
mid5 = bin(int(c[x:x+y], 2) ^ int(high13[:y], 2))[2:].zfill(y)
low13 = bin(int(c[x+y:], 2) ^ int((high13+mid5)[y:], 2))[2:].zfill(x) # 注意填充
output = int(high13+mid5+low13, 2)
return output第二三组位运算
如法炮制,总之也是可以逆回去的
实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def second_cal_re(c, x, y):
y = bin(y)[2:].zfill(32)
c = bin(c)[2:].zfill(32)
output = [0 for _ in range(len(c))]
# 低x位保持不变
for i in range(len(y)-x, len(y)):
output[i] = int(c[i])
# 13-21位 = (低x位)&(y[13:21])^c[13:21]
for i in range(len(y)-2*x, len(y)-x):
output[i] = output[i+x] & int(y[i]) ^ int(c[i])
# 4-12位 = (13-21位)&(y[4:12])^c[4:12]
for i in range(len(y)-3*x, len(y)-2*x):
output[i] = output[i+x] & int(y[i]) ^ int(c[i])
# 高4位 = (8-12位)&(y[0:3])^c[0:3]
for i in range(0, 5):
output[i] = output[i+x] & int(y[i]) ^ int(c[i])
output = "".join(map(lambda _: str(_), output))
output = int(output, 2)
return output
但在实际跑的时候,存在一些bug。比如1234转数字是9位,而abcd是8位
最后看着flag把脚本改出来了,如下
1 | #!/usr/bin/env python |
尚师傅的方法
简单来说,有类位运算是可以移回来的,也就是
1 | for i in range(xxx): |
循环固定的次数就能够恢复初试的状态
不清楚是为啥,但经常在比赛中遇到
通用的方法
其实这里的convert作为MT19937中extract_number的一部分,逆向convert是有固定套路的,也就是用位运算精简上面朴素的方法
不带mask的右移
1 | m = m ^ m >> 18 |
1 | def inverse_right(res, shift, bits=32): |
带mask的左移
1 | m = m ^ m << 17 & 2245263360 |
1 | def inverse_left_values(res, shift, mask, bits=32): |
细想还挺简单的
最后附上官方wp