0xGame 2023【WEEK1】Crypto全解
What's CBC?
题目信息
from Crypto.Util.number import *
from secret import flag,key
def bytes_xor(a,b):
a,b=bytes_to_long(a),bytes_to_long(b)
return long_to_bytes(a^b)
def pad(text):
if len(text)%8:
return text
else:
pad = 8-(len(text)%8)
text += pad.to_bytes(1,'big')*pad
return text
def Encrypt_CBC(text,iv,key):
result = b''
text = pad(text)
block=[text[_*8:(_+1)*8] for _ in range(len(text)//8)]
for i in block:
tmp = bytes_xor(iv,i)
iv = encrypt(tmp,key)
result += iv
return result
def encrypt(text,key):
result = b''
for i in text:
result += ((i^key)).to_bytes(1,'big')
return result
iv = b'11111111'
enc = (Encrypt_CBC(flag,iv,key))
print(f'enc = {enc}')
#enc = b"\x8e\xc6\xf9\xdf\xd3\xdb\xc5\x8e8q\x10f>7.5\x81\xcc\xae\x8d\x82\x8f\x92\xd9o'D6h8.d\xd6\x9a\xfc\xdb\xd3\xd1\x97\x96Q\x1d{\\TV\x10\x11"
简单的一个CBC加密,先生成一个iv,然后每次加密都先用明文与iv异或后再加密,并将上一块的密文作为下一块的iv继续加密下一块。这里的加密比较简单就是个1字节的异或。
这里先用第1块爆破一下key得到143再解密
enc = b"\x8e\xc6\xf9\xdf\xd3\xdb\xc5\x8e8q\x10f>7.5\x81\xcc\xae\x8d\x82\x8f\x92\xd9o'D6h8.d\xd6\x9a\xfc\xdb\xd3\xd1\x97\x96Q\x1d{\\TV\x10\x11"
from pwn import xor
v = xor(enc[:8], b'1')
for i in range(256):
print(i, xor(v,bytes([i])))
key = 143
for i in range(8, len(enc),8):
print(xor(enc[i-8:i], xor(bytes([key]),enc[i:i+8])))
#0xGame{098f6bcd4621d373cade4e832627b4f6}
密码,觅码,先有*再密
题目信息
from secret import flag #从中导入秘密的flag,这是我们要破解的信息
from Crypto.Util.number import bytes_to_long #从函数库导入一些编码函数
from base64 import b64encode
#hint:也许下列函数库会对你有些帮助,但是要怎么用呢……
from base64 import b64decode
from gmpy2 import iroot
from Crypto.Util.number import long_to_bytes
flag = flag.encode()
lent = len(flag)
flag = [flag[i*(lent//4):(i+1)*(lent//4)] for i in range(4)]#将flag切割成四份
c1 = bytes_to_long(flag[0])
c2 = ''.join([str(bin(i))[2:] for i in flag[1]])
c3 = b64encode(flag[2])
c4 = flag[3].hex()
print(f'c1?= {pow(c1,5)}\nc2 = {c2}\nc3 = {c3}\nc4 = {c4}')
'''
c1?= 2607076237872456265701394408859286660368327415582106508683648834772020887801353062171214554351749058553609022833985773083200356284531601339221590756213276590896143894954053902973407638214851164171968630602313844022016135428560081844499356672695981757804756591891049233334352061975924028218309004551
c2 = 10010000100001101110100010100111101000111110010010111010100001101110010010111111101000011110011010000001101011111110011010011000101011111110010110100110100000101110010010111101100101011110011110111100
c3 = b'lueggeeahO+8jOmCo+S5iOW8gOWni+aIkQ=='
c4 = e4bbace79a8443727970746fe68c91e68898e590a72121217d
'''
#全是乱码,那咋办嘛?
本题是对一些python库函数的测试。
分了4段进行加密,part1是转整后再5次幂,part2是转二进制,part3是base64,part4是16进制,最后合起来是乱码bytes转str用utf-8(默认值)
from Crypto.Util.number import bytes_to_long
from base64 import b64encode
from base64 import b64decode
from gmpy2 import iroot
from Crypto.Util.number import long_to_bytes
c1 = 2607076237872456265701394408859286660368327415582106508683648834772020887801353062171214554351749058553609022833985773083200356284531601339221590756213276590896143894954053902973407638214851164171968630602313844022016135428560081844499356672695981757804756591891049233334352061975924028218309004551
c2 = '10010000100001101110100010100111101000111110010010111010100001101110010010111111101000011110011010000001101011111110011010011000101011111110010110100110100000101110010010111101100101011110011110111100'
c3 = b'lueggeeahO+8jOmCo+S5iOW8gOWni+aIkQ=='
c4 = 'e4bbace79a8443727970746fe68c91e68898e590a72121217d'
part1 = long_to_bytes(iroot(c1,5)[0])
print(part1)
part2 = int(c2, 2).to_bytes((len(c2) + 7) // 8, 'big')
print(part2)
part3 = b64decode(c3)
print(part3)
part4 = bytes.fromhex(c4)
print(part4)
m = part1+part2+part3+part4
print(m.decode())
#b'0xGame{ \xe6\x81\xad\xe5\x96\x9c\xe4\xbd\xa0,\xe5\xb7\xb2\xe7\xbb\x8f\xe7'
#b'\x90\x86\xe8\xa7\xa3\xe4\xba\x86\xe4\xbf\xa1\xe6\x81\xaf\xe6\x98\xaf\xe5\xa6\x82\xe4\xbd\x95\xe7\xbc'
#b'\x96\xe7\xa0\x81\xe7\x9a\x84\xef\xbc\x8c\xe9\x82\xa3\xe4\xb9\x88\xe5\xbc\x80\xe5\xa7\x8b\xe6\x88\x91'
#b'\xe4\xbb\xac\xe7\x9a\x84Crypto\xe6\x8c\x91\xe6\x88\x98\xe5\x90\xa7!!!}'
#0xGame{ 恭喜你,已经理解了信息是如何编码的,那么开始我们的Crypto挑战吧!!!}
Take my bag!
题目信息
from Crypto.Util.number import *
from secret import flag
def encrypt(m):
m = str(bin(m))[2:][::-1]
enc = 0
for i in range(len(m)):
enc += init[i] * int(m[i]) % n
return enc
w = getPrime(64)
n = getPrime(512)
init = [w*pow(3, i) % n for i in range(512)]
c = encrypt(bytes_to_long(flag))
print(f'w={w}')
print(f'n={n}')
print(f'c={c}')
'''
w=16221818045491479713
n=9702074289348763131102174377899883904548584105641045150269763589431293826913348632496775173099776917930517270317586740686008539085898910110442820776001061
c=4795969289572314590787467990865205548430190921556722879891721107719262822789483863742356553249935437004378475661668768893462652103739250038700528111
'''
先生成一个逐渐增加的序列,每一项都大于前面项的和。分解与每一位(0/1)相乘,取和。解密的方法就是从大到小,够减的话就1减掉,不够减就是0
exp
w=16221818045491479713
n=9702074289348763131102174377899883904548584105641045150269763589431293826913348632496775173099776917930517270317586740686008539085898910110442820776001061
c=4795969289572314590787467990865205548430190921556722879891721107719262822789483863742356553249935437004378475661668768893462652103739250038700528111
init = [w*pow(3, i) % n for i in range(512)]
m = ''
for v in init[::-1]:
if c>=v:
m+='1'
c-=v
else:
m+='0'
flag = ''
for i in range(0, len(m), 8):
flag += chr(int(m[i:i+8],2))
print(flag)
#0xGame{Welc0me_2_Crypt0_G@me!#$&%}
BabyRSA
题目信息
from Crypto.Util.number import *
from random import getrandbits
from secret import flag
def getN():
N = 1
for i in range(16):
tmp = getPrime(32)
N *= tmp
return N
mask = getrandbits(256)
e = 65537
n = getN()
m = bytes_to_long(flag)
c = pow(m*mask,e,n)
print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')
print(f'mask = {mask}')
'''
n = 93099494899964317992000886585964221136368777219322402558083737546844067074234332564205970300159140111778084916162471993849233358306940868232157447540597
e = 65537
c = 54352122428332145724828674757308827564883974087400720449151348825082737474080849774814293027988784740602148317713402758353653028988960687525211635107801
mask = 54257528450885974256117108479579183871895740052660152544049844968621224899247
'''
可以先分解n然后求phi,比较麻烦。这里直接用sage里的euler_phi求(因为n由小素数组成)
sage跑
from Crypto.Util.number import long_to_bytes
n = 93099494899964317992000886585964221136368777219322402558083737546844067074234332564205970300159140111778084916162471993849233358306940868232157447540597
e = 65537
c = 54352122428332145724828674757308827564883974087400720449151348825082737474080849774814293027988784740602148317713402758353653028988960687525211635107801
mask = 54257528450885974256117108479579183871895740052660152544049844968621224899247
mm = pow(c, inverse_mod(e, euler_phi(n)), n)
m = int(mm) // mask
print(m)
#334526535497992378634036751902245187892235112866317344720327978830278781
print(long_to_bytes(int(m)//mask))
#0xGame{Magic_M@th_Make_Crypt0}
猜谜
题目信息
from secret import flag,key
from Crypto.Util.number import *
def dec(text):
text = text.decode()
code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
unpad = 0
tmp = ''
if (text[-1] == '=') & (text[-2:] != '=='):
text = text[:-1]
unpad = -1
if text[-2:] == '==':
text = text[:-2]
unpad = -2
for i in text:
tmp += str(bin(code.index(i)))[2:].zfill(3)
tmp = tmp[:unpad]
result = long_to_bytes(int(tmp,2))
return result
def enc(text):
code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
text = ''.join([str(bin(i))[2:].zfill(8) for i in text])
length = len(text)
pad = b''
if length%3 == 1:
text += '00'
pad = b'=='
elif length%3 == 2:
text += '0'
pad = b'='
result = [code[int(text[3*i:3*(i+1)],2)] for i in range(0,len(text)//3)]
return ''.join(result).encode()+pad
def encrypt(flag):
result = b''
for i in range(len(flag)):
result += (key[i%7]^(flag[i]+i)).to_bytes(1,'big')
return result
c = enc(encrypt(flag))
print(f'c = {c}')
flag先通过encrypt再enc,encrypt里与key异或,由于flag头部已知,可以直接求出key.
code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
c = 'IPxYIYPYXPAn3nXX3IXA3YIAPn3xAYnYnPIIPAYYIA3nxxInXAYnIPAIxnXYYYIXIIPAXn3XYXIYAA3AXnx'
m = ''.join([bin(code.index(i))[2:].zfill(3) for i in c])
v = bytes([int(m[i:i+8],2) for i in range(0, len(m),8)])
flag = b'0xGame{'
key = xor(v[:7], bytes([i+flag[i] for i in range(7)]))
v2 = xor(v, key)
m = bytes([v-i for i,v in enumerate(v2)])
#0xGame{Kn0wn_pl@intext_Att@ck!}
Vigenere
题目信息
密文:0dGmqk{79ap4i0522g0a67m6i196he52357q60f} 古老而神秘的加密方式?
手算key即可