题目在官方网站还可以下载得到,这里比赛后总结一下WP(虽然比赛的时候并没有做上)
题目源码:
from flag import flag
def getMagic():
magic = []
with open("magic.txt") as f:
while True:
line = f.readline()
if (line):
line = int(line, 16)
magic.append(line)
# print bin(line)[2:]
else:
break
return magic
def playMagic(magic, key):
cipher = 0
for i in range(len(magic)):
cipher = cipher << 1
t = magic[i] & key
c = 0
while t:
c = (t & 1) ^ c
t = t >> 1
cipher = cipher ^ c
return cipher
def main():
key = flag[5:-1]
assert len(key) == 32
key = key.encode("hex")
key = int(key, 16)
magic = getMagic()
cipher = playMagic(magic, key)
cipher = hex(cipher)[2:-1]
with open("cipher.txt", "w") as f:
f.write(cipher + "\n")
if __name__ == "__main__":
main()
magic文件预览:
cipher:
ae9d5ce2d396bdd5b30a20fa252e3dc53549f4499d5066ef2d005ce5696f976e
题目分析:
magic可以看做是一个256个由256个0/1组成的二进制数字串(magic文件里是长度64位的16进制数字串)
key也是一串32长度的字符串,本质上就是32*8 bits的0/1数字串
题目的意思就是:magic每次取一行,选取key为1位置的对应位置,这些位共同进行异或的结果放在cipher的第一位(本质上相当于求1的个数然后mod 2),然后cipher每次都左移一次,共进行了256次,所以magic是256行,cipher是256bits
解题思路:
把magic看成是256*256的0/1组成的矩阵;我们的key是256行1列的0/1矩阵;而最后的cipher同样是一个256行1列的0/1矩阵
所以就有矩阵运算: magic*key (mod 2)= cipher
求出magic的逆矩阵magic^-1即可通过key = cipher*(magic^-1) (mod2) 求解
解题脚本:
解题脚本使用sage写的,因为python里面的numpy求逆矩阵的时候始终得不到精确结果(可能有但我不会用),直接在sage里运行就成了:
def getMagic():
magic = []
with open("E:\CTF-Quals\SUCTF\magic\magic.txt","r") as f:
while True:
line = f.readline()
if (line):
line = int(line, 16)
magic.append(line)
else:
break
return magic
magic = getMagic()
magicbin = []
for i in magic:
magicbin.append(bin(i)[2:].zfill(256))
tmp1 = []
magicarray = []
for i in magicbin:
for cnt in i:
tmp1.append(int(cnt))
magicarray.append(tmp1)
tmp1 = []
magic = matrix(magicarray)
I = magic.inverse()
#print I
cipher = int("ae9d5ce2d396bdd5b30a20fa252e3dc53549f4499d5066ef2d005ce5696f976e",16)
cipherVector = ""
cipherVector = bin(cipher)[2:].zfill(256)
cipherMatrix = []
for i in cipherVector:
tmp = []
tmp.append(int(i))
cipherMatrix.append(tmp)
#print cipherMatrix
cipherMatrix = matrix(cipherMatrix)
flagMatrix = (I*cipherMatrix)%2
#print flagMatrix
flagbin = ""
for i in flagMatrix:
flagbin+=str(i[0])
flag = ""
for i in range(0,len(flagbin),8):
flag += chr(int(flagbin[i:i+8],2))
flag = "SUCTF{" + flag + "}"
print flag
结果如下:
其实通过这道题基本上就只到Hill Cipher到底是个什么东西了。-!-
(懒狗一只,继续努力!)