window.onload=function(){ /*页面加载完成之后生成博客目录*/ BlogDirectory.createBlogDirectory("cnblogs_post_body","h2","h3",20); }

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即可

 

posted @ 2023-10-21 06:10  Kicky_Mu  阅读(113)  评论(0编辑  收藏  举报