这个小赛只作了8个crypto简单部分,后边5个都不会

pokecomms

密码签到,给了堆字符,细看就两种,每行8组 CHU! 开头,显然是替换成01。然后出来就是flag,这个flag有1364个字符。是我见过最长的。

CHU! PIKA CHU! PIKA CHU! PIKA CHU! PIKA
 CHU! PIKA CHU! CHU! PIKA PIKA CHU! PIKA
 CHU! PIKA CHU! CHU! CHU! PIKA CHU! CHU!
 CHU! PIKA CHU! CHU! CHU! CHU! PIKA PIKA
 CHU! PIKA CHU! PIKA CHU! PIKA CHU! CHU!
 CHU! PIKA CHU! CHU! CHU! PIKA PIKA CHU!

CBC-MAC 1

题目很长得慢慢读,在一个10次的循环里有两个功能,1是输入数据进行加密,返回密文的最后一块。2是输入明文和预测的密文,如果正确就能得到flag(不能是输入过的,废话)

import socket
import threading
from _thread import *
from Crypto import Random
from Crypto.Cipher import AESfrom binascii import hexlify, unhexlifyHOST = '0.0.0.0'  # Standard loopback interface address (localhost)
PORT = 60001        # Port to listen on (non-privileged ports are > 1023)
FLAG = open('flag.txt', 'r').read().strip()
MENU = "\nWhat would you like to do?\n\t(1) MAC Query\n\t(2) Forgery\n\t(3) Exit\n\nChoice: "
INITIAL = "Team Rocket told me CBC-MAC with arbitrary-length messages is safe from forgery. If you manage to forge a message you haven't queried using my oracle, I'll give you something in return.\n"BS = 16 # Block Size
MAX_QUERIES = 10def cbc_mac(msg, key):iv = b'\x00'*BScipher = AES.new(key, AES.MODE_CBC, iv=iv)t = cipher.encrypt(msg)[-16:]return hexlify(t)def threading(conn):conn.sendall(INITIAL.encode())key = Random.get_random_bytes(16)queries = []while len(queries) < MAX_QUERIES:conn.sendall(MENU.encode())try:choice = conn.recv(1024).decode().strip()except ConnectionResetError as cre:return# MAC QUERYif choice == '1':conn.sendall(b'msg (hex): ')msg = conn.recv(1024).strip()try:msg = unhexlify(msg)if (len(msg) + BS) % BS != 0:conn.sendall(f'Invalid msg length. Must be a multiple of BS={BS}\n'.encode())else:queries.append(msg)t = cbc_mac(msg, key)conn.sendall(f'CBC-MAC(msg): {t.decode()}\n'.encode())except Exception as e:conn.sendall(b'Invalid msg format. Must be in hexadecimal\n')# FORGERY (impossible as I'm told)elif choice == '2':conn.sendall(b'msg (hex): ')msg = conn.recv(1024).strip()conn.sendall(b'tag (hex): ')tag = conn.recv(1024).strip()try:msg = unhexlify(msg)if (len(msg) + BS) % BS != 0:conn.sendall(f'Invalid msg length. Must be a multiple of BS={BS} bytes\n'.encode())elif len(tag) != BS*2:conn.sendall(f'Invalid tag length. Must be {BS} bytes\n'.encode())elif msg in queries:conn.sendall(f'cheater\n'.encode())else:t_ret = cbc_mac(msg, key)if t_ret == tag:conn.sendall(f'If you reach this point, I guess we need to find a better MAC (and not trust TR). {FLAG}\n'.encode())else:conn.sendall(str(t_ret == tag).encode() + b'\n')except Exception as e:conn.sendall(b'Invalid msg format. Must be in hexadecimal\n')else:if choice == '3': # EXITconn.sendall(b'bye\n')else: # INVALID CHOICEconn.sendall(b'invalid menu choice\n')breakif len(queries) > MAX_QUERIES:conn.sendall(f'too many queries: {len(queries)}\n'.encode())conn.close()if __name__ == "__main__":with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)s.bind((HOST, PORT))s.listen()while True:conn, addr = s.accept()print(f'new connection: {addr}')start_new_thread(threading, (conn, ))s.close()

核心部分是cbc_mac函数,采用AES_CBC加密,IV是b'0'*16

AES是第1个被玩坏的加密算法,不管是ECB还是CBC都有固定的漏洞。CBC加入的前反馈用的是上一块的密文,比如如果明文是两块AB,返回的密文也是两块CD,这里的B=ENC(A),D=ENC(B^C) ,所以这个题如果输入A能得到B,输入AB得到CD,于是可以预测输入B^C可以得到D

┌──(kali㉿kali)-[~]
└─$ nc 0.cloud.chals.io 12769
Team Rocket told me CBC-MAC with arbitrary-length messages is safe from forgery. If you manage to forge a message you haven't queried using my oracle, I'll give you something in return.

What would you like to do?
        (1) MAC Query
        (2) Forgery
        (3) Exit

Choice: 1
msg (hex): 00000000000000000000000000000000
CBC-MAC(msg): aa4103b3e49bf200f9e3ded28d1287c4

What would you like to do?
        (1) MAC Query
        (2) Forgery
        (3) Exit

Choice: 1
msg (hex): 0000000000000000000000000000000000000000000000000000000000000000
CBC-MAC(msg): d34e824a19e71237a2a49a5cefcacc12

What would you like to do?
        (1) MAC Query
        (2) Forgery
        (3) Exit

Choice: 2
msg (hex): aa4103b3e49bf200f9e3ded28d1287c4
tag (hex): d34e824a19e71237a2a49a5cefcacc12
If you reach this point, I guess we need to find a better MAC (and not trust TR). UMDCTF{Th!s_M@C_Sch3M3_1s_0nly_S3cur3_f0r_f!xed_l3ngth_m3ss4g3s_78232813}

CBC-MAC 2

第2题大体与第1题相似,只是cbc_mac有变化,只是多了个padding块,值是前边块的数量,这样再输什么后边就是密文与序号异或的值了。

def cbc_mac(msg, key):iv = b'\x00'*BScipher = AES.new(key, AES.MODE_CBC, iv=iv)ct = cipher.encrypt(msg + l2b(len(msg)//BS, BS))t = ct[-16:]return hexlify(t)

这个方法,一时没想出来就睡觉去了,第二天醒来想到一个,一试结果就行了。

这个方法先输入A得到 _A = ENC(ENC(A)^1), 再输入B得到 _B = ENC(ENC(B)^1)

这时候如果输入 A+1这时候的密文应该是Enc(A)+ Enc(Enc(A)^1) 第2段的密文就是上面第1步的密文已知,但返回的并不是这个,而的后边padding的值,所以输入第3段输入为_A把前边的反馈异或掉,那么异或以后就是对序号0进行加密然后拿密文异或padding的3,函数返回的就是Enc(Enc(0)^3),在这中间把前边的加密结果异或掉了。同样拿B这样作也能得到这个结果。

from pwn import *
from Crypto.Util.number import long_to_bytes as l2bp = remote('0.cloud.chals.io', 31220)
context.log_level = 'debug'def get_mac(msg, key):iv = b'\x00'*BScipher = AES.new(key, AES.MODE_CBC, iv=iv)ct = cipher.encrypt(msg + l2b(len(msg)//BS, BS))t = ct[-16:]return hexlify(t)def get_msg(msg):p.sendlineafter(b'Choice: ', b'1')p.sendlineafter(b'msg (hex):', msg.hex().encode())p.recvuntil(b': ')return bytes.fromhex(p.recvline().strip().decode())def chk_msg(msg,tag):p.sendlineafter(b'Choice: ', b'2')p.sendlineafter(b'msg (hex):', msg.hex().encode())p.sendlineafter(b'tag (hex):', tag.hex().encode())c0 = get_msg(b'\x01'*16)   #0>c0,c0^1->c1,
c1 = get_msg(b'\x02'*16)c2 = get_msg(b'\x01'*16+ l2b(1, 16)+c0)
#c3 = get_msg(b'\x02'*16+ l2b(1, 16)+c1)
#print(c2,c3)
chk_msg(b'\x02'*16+ l2b(1, 16)+c1, c2)print(p.recvline())p.interactive()
#UMDCTF{W3lp_l00k5_l!k3_I_n33d_t0_ch4ng3_th1s_ag41n_s4d_f4ce_3m0j1_927323}

D3sys

这个题是D^3CTF的一个题的,没作出来,作到了取出数据,后边不会,但是前边跟上边两题神似,所以一起写在这。

题目是用的自己写的SM4加密,国密算法,这个基本不可破了(说明国密算法好吧)

输入数据会用json打包成串,串包含name:id, 权限admin,nonce:16字节的原意用不到的数据,时间time

这些数据会附着在用counter通过ECB方法生成的加密流上。生成1-2-3的块把明文异或上去。

因为自动打包是admin:0,要求打包所admin:1 时间time不能变,这块比较简单,因为是异或附着上去的,直接对密文与原明文异或就能得到加密流,再与新明文异或就得到密文。

关键是安会对生成后的每个块sha256取前16字节异或明文,类似CBC方式反馈。最后校验生成的标签。

有了上边这题的经验,可以找一个位置利用明文对sha256形成的密文进行拦截。

就是分别计算原明文到某一位置的标签,和修改后的明文到同一位置的标签,用两标签异或的值作明文,这样修改后的标签在中间位置就会变成原明文的标签,通过校验。

这个位置定在没用的nonce上,这个域正好一个16字节整块,通过调整name的长度可以让他对齐。然后在这里拦截。

不过由于拦截后的数据在decode('utf-8')后可能会有数据无法转换造成json解失败,所以要多次才能成功,试了大概10次,但也可能一上来就碰上。

这题到这只是拿到数据,怎么解密,还不清楚怎么弄。是dp+(p-1)*getPrime(128)的后447位,这是一个方程3个未知数,当然还有对称的q也是这样。整理下知识库,库里没有。

from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime,inverse
from gmssl.SM4 import CryptSM4,SM4_ENCRYPT,xor
from hashlib import sha256
#from secret import secret
import signal
import time
import json
import ossecret = b'flag{test}'
FLAG = b'ant' + secretbanner = br"""::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
'########::::'###::::'#######::::::'######::'########:'########:::::'#######::::'#####::::'#######:::'#######::##.... ##::'## ##::'##.... ##::::'##... ##:... ##..:: ##.....:::::'##.... ##::'##.. ##::'##.... ##:'##.... ##:##:::: ##:'##:. ##:..::::: ##:::: ##:::..::::: ##:::: ##::::::::::..::::: ##:'##:::: ##:..::::: ##:..::::: ##:##:::: ##:..:::..:::'#######::::: ##:::::::::: ##:::: ######:::::::'#######:: ##:::: ##::'#######:::'#######::##:::: ##:::::::::::...... ##:::: ##:::::::::: ##:::: ##...:::::::'##:::::::: ##:::: ##:'##:::::::::...... ##:##:::: ##::::::::::'##:::: ##:::: ##::: ##:::: ##:::: ##:::::::::: ##::::::::. ##:: ##:: ##::::::::'##:::: ##:########:::::::::::. #######:::::. ######::::: ##:::: ##:::::::::: #########::. #####::: #########:. #######::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"""MENU1 = br'''====------------------------------------------------------------------------------------------------------====|    |              +---------------------------------------------------------------------+              |   ||    |              |            [R]egister     [L]ogin     [T]ime     [E]xit             |              |   ||    |              +---------------------------------------------------------------------+              |   |====------------------------------------------------------------------------------------------------------====
'''MENU2 = br'''====------------------------------------------------------------------------------------------------------====|    |              +---------------------------------------------------------------------+              |   ||    |              |            [G]et_dp_dq     [F]lag     [T]ime     [E]xit             |              |   ||    |              +---------------------------------------------------------------------+              |   |====------------------------------------------------------------------------------------------------------====
'''def pad(msg):tmp = 16 - len(msg)%16return msg + bytes([tmp] * tmp)def get_token(id:str,nonce:str,_time:int):msg = {"id":id,"admin":0,"nonce":nonce,"time":_time}print('TOKEN:', str(json.dumps(msg)).encode())return str(json.dumps(msg)).encode()class CRT_RSA_SYSTEM:nbit = 1024blind_bit = 128unknownbit = 193def __init__(self):e = 0x10001p,q = [getPrime(self.nbit // 2) for _ in "AntCTF"[:2]]n = p * qself.pub = (n,e)dp = inverse(e,p - 1)dq = inverse(e,q - 1)self.priv = (p,q,dp,dq,e,n)self.blind()def blind(self):p,q,dp,dq,e,n = self.privrp,rq = [getPrime(self.blind_bit) for _ in "D^3CTF"[:2]]dp_ = (p-1) * rp + dpdq_ = (q-1) * rq + dqself.priv = (p,q,dp_,dq_,e,n)def get_priv_exp(self):p,q,dp,dq,e,n = self.privdp_ = dp & (2**(self.nbit//2 + self.blind_bit - self.unknownbit) - 1)dq_ = dq & (2**(self.nbit//2 + self.blind_bit - self.unknownbit) - 1)return (dp_,dq_)def encrypt(self,m):n,e = self.pubreturn pow(m,e,n)def decrypt(self,c):p,q,dp,dq,e,n = self.privmp = pow(c,dp,p)mq = pow(c,dq,q)m = crt([mp,mq],[p,q])assert pow(m,e,n) == creturn mclass SM4_CTR(CryptSM4):block_size = 16def _get_timers(self, iv, msgLen):blockSZ = self.block_sizeblocks = int((msgLen + blockSZ - 1) // blockSZ)timer = bytes_to_long(iv)timers = ivfor i in range(1, blocks):timer += 1timers += long_to_bytes(timer)return timers#先根据IV生成timers: count,count+1, count+2  将这些用crypt_ecb加密后与明文异或def encrypt_ctr(self, input_data,count = None):assert len(input_data) % self.block_size == 0if count == None:count = os.urandom(16)counters = self._get_timers(count,len(input_data))   #count, count+1, count+2blocks = xor(self.crypt_ecb(counters), input_data)ciphertext = bytes(blocks)return count + ciphertext[:len(input_data)]def decrypt_ctr(self, input_data):assert len(input_data) % self.block_size == 0pt = self.encrypt_ctr(input_data[self.block_size:], input_data[:self.block_size])return pt[self.block_size:]class D3_ENC:def __init__(self,key:bytes,authdate:bytes):self.crt_rsa = CRT_RSA_SYSTEM()self.block = SM4_CTR()self.block.set_key(key, SM4_ENCRYPT)self.authdate = bytes_to_long(authdate)def encrypt(self,msg):assert len(msg) % 16 == 0cipher = self.block.encrypt_ctr(msg)tag = self.get_tag(msg)return cipher,tagdef decrypt(self,cipher):assert len(cipher) % 16 == 0msg = self.block.decrypt_ctr(cipher)tag = self.get_tag(msg)return msg,tagdef get_tag(self,msg):auth_date = self.authdatemsg_block = [bytes_to_long(msg[i*16:(i+1)*16]) for i in range(len(msg)//16)]for mi in msg_block:auth_date = int(sha256(str(self.crt_rsa.encrypt(auth_date)).encode()).hexdigest()[:32],16) ^ mireturn int(sha256(str(self.crt_rsa.encrypt(auth_date)).encode()).hexdigest()[:32],16)class D3_SYS:def register(self):print('Welcome to D^3 CTF 2023!')username = input("[D^3] USERNAME:")if username in self.UsernameDict:print(f'[D^3] Sorry,the USERNAME {username} has been registered.')return elif len(username) >= 20:print('[D^3] Sorry,the USERNAME can\'t be longer than 20.')returnnonce = os.urandom(8).hex()token = get_token(username,nonce,int(time.time()))cipher_token,tag = self.d3block.encrypt(pad(token))self.UsernameDict[username] = tagprint('[D^3] ' + username + ', token is ' + cipher_token.hex() + '& nonce is ' + nonce)def login(self):print('Welcome to D^3 CTF 2023!')username = input("[D^3] USERNAME:")if username not in self.UsernameDict:   #用户名在注册字典中print('[D^3] Sorry,the username has never been registered.')return Falseveritag = self.UsernameDict[username]cipher_token = bytes.fromhex(input("[D^3] Token:"))try:msg,tag = self.d3block.decrypt(cipher_token)   #token可以正常解密except:print("[D^3] Something Wrong...quiting....")return Falseif tag != veritag :print('[D^3] Ouch! HACKER? Get Out! {tag} {veritag}')return Falsetry:token_dict = json.loads(msg.decode('latin-1').strip().encode('utf-8'))  #可以正常解析except:print('[D^3] Sorry,try again plz..')return FalseID = token_dict["id"]   #已注册的用户名if ID != username:print('[D^3] Change name?')return Falseelif abs(int(time.time()) - token_dict['time']) >= 1:  #时间少于1秒print('[D^3] oh...no...out....')return Falseelif token_dict['admin'] != True:print("[D^3] Logining.")return Falseelse:print("[D^3] Logining.")return Truedef time(self):print('[D^3] D^3\' clock shows '+str(int(time.time())))returndef get_dp_dq(self):return self.d3block.crt_rsa.get_priv_exp()def enc_flag(self):flag = FLAG + os.urandom(16)n,e = self.d3block.crt_rsa.pubenc_flag = pow(bytes_to_long(flag),e,n)return enc_flagdef handle(self):print(banner.decode())key = os.urandom(16)authdate = os.urandom(16)self.d3block = D3_ENC(key,authdate)print('[D^3] My initial Authdate is ' + authdate.hex())print('[D^3] My Auth pubkey is ' + str(self.d3block.crt_rsa.pub))self.UsernameDict = {}admin = None# signal.alarm(60) # in server.......while 1:print(MENU1.decode())option = input('option >')if option == 'R':self.register()elif option == 'L':admin = self.login()breakelif option == 'T':self.time()else:breakif admin != True:print("ByeBye! You are not admin.......")exit()print("Hello,Admin.Now, you have 2 chances to operate.")for __ in 'D^3 CTF'[:2]:print(MENU2.decode())option = input('option >')if option == 'F':cip = self.enc_flag()print('Encrypted Flag: ' + hex(cip))elif option == 'G':dp,dq = self.get_dp_dq()print(f'dp,dq:{[dp,dq]}')elif option == 'T':self.time()else:breakif __name__ == "__main__":d3sys = D3_SYS()d3sys.handle()

前半块先存在这

from pwn import *
from hashlib import sha256
from Crypto.Util.number import long_to_bytes,bytes_to_long #p = process(['python3', './server.py'])
p = remote('106.14.124.130', 32141)def pad(msg):tmp = 16 - len(msg)%16return msg + bytes([tmp] * tmp)def res_enc(r):return pow(r,e,n)def get_tag(auth_date, msg):msg_block = [bytes_to_long(msg[i*16:(i+1)*16]) for i in range(len(msg)//16)]print('Authdate:', auth_date)print('msg_block', msg_block)for mi in msg_block[:4]:auth_date = int(sha256(str(res_enc(auth_date)).encode()).hexdigest()[:32],16) ^ miprint(auth_date)#return int(sha256(str(crt_rsa.encrypt(auth_date)).encode()).hexdigest()[:32],16)return long_to_bytes(auth_date)  #noce blockdef register(name):p.sendlineafter(b'option >', b'R')p.sendlineafter(b"[D^3] USERNAME:", name.encode())p.recvuntil(b'token is ')token = p.recvuntil(b'& nonce is ', drop=True)noce  = p.recvline().decode().strip()return bytes.fromhex(token.decode()),noce def login(name, token):p.sendlineafter(b'option >', b'L')p.sendlineafter(b"[D^3] USERNAME:", name.encode())p.sendlineafter(b"[D^3] Token:", token.hex().encode())def get_time():p.sendlineafter(b'option >', b'T')p.recvuntil(b'[D^3] D^3\' clock shows ')return int(p.recvline().decode().strip())def get_enc():p.sendlineafter(b'option >', b'F')return p.recvline()def get_dpq():p.sendlineafter(b'option >', b'G')return p.recvline()'''
iv + ecb(timer)^input
{'id': 'A12345612345678', 'admin': 0, 'nonce': '863fd6c657125e0e', 'time': 1682729415}
'''
p.recvuntil(b'[D^3] My initial Authdate is ')
authdate = bytes_to_long(bytes.fromhex(p.recvline().decode().strip()))
p.recvuntil(b'[D^3] My Auth pubkey is ')
n,e = eval(p.recvline().decode())
print("AU,n,e:",hex(authdate),n,e)#控制name的长度,让nonce在一个独立的块,通过nonce来平衡对admin:1数据变动造成的sha256变化
#由于平衡hash值生成的字节可能会包含json无法识别的utf-8字符,爆破多次才能成功
username = 'A12345612345678'
tok,noce = register(username)
print('Tok:',tok)
print('Noce:',noce)stime = get_time()
#noce = 48:
data  = '{"id": "'+username+'", "admin": 0, "nonce": "'+ noce +'", "time": '+str(stime)+'}'
data1 = pad(data.encode())
print('ServerData:', data1)
data  = '{"id": "'+username+'", "admin": 1, "nonce": "'+ noce +'", "time": '+str(stime)+'}'
data2 = pad(data.encode())
print('ServerData:', data2)tab1 = get_tag(authdate, data1) #取得真实和变更后的到nonce块对应的hash值,将变更后的hash值异或
tab2 = get_tag(authdate, data2)twos = xor(noce, tab1, tab2)data  = ('{"id": "'+username+'", "admin": 1, "nonce": "').encode() + twos + ('", "time": '+str(stime)+'}').encode()
data3 = pad(data)
print('ServerData:', data3)
tab3 = get_tag(authdate, data3)
print(tab1,tab3)tok2 = tok[:16] + xor(tok[16:], data1, data3)login(username, tok2)#getencflag
enc = get_enc()
dpq = get_dpq()
print(n,e)
print(enc, dpq)

Bulbeuler

这题比较短,我喜欢,将flag按位加密,如果位为1输出x,m-x如果为0输出x和y ,其中x,y都是随机数,并给了g^x,g^y

FLAG = open('flag.txt', 'r').read()flag_bytes = [ord(c) for c in FLAG]
flag_bits = ''.join([f'{num:08b}' for num in flag_bytes])p = random_prime(2^256)
G = GF(p, modulus="primitive")
g = G.gen()  #2
m = p-1print(f'p: {p}')
for bit in flag_bits:x = G.random_element()if bit == '1':y = m-xelse:y = G.random_element()print(f'{g^x}, {g^y}')'''
#太长,不复制了
136107697176749185543209332858662868346120393376514992101253214901716362745, 4489243525362911779914961649702230836859635666195232403274786388182562879361
313387399053126414484766711139354034169709558997548368221163057994217005353, 4029565080773491679563658568390472992550553731340161637356414983568392824062
4287900589192154417478352219166638748006136888749131614780146977634009070841, 4954649930416350408097954464190826193086987784562686571699186431239839447950
'''

这个解密很简单,拿两个相乘当为1的时候g^x*g^y = g^(x+y) = g^(x+m-x) = g^m 由于m=p-1所以g^(p-1)=1

v = open('output.txt').readlines()p = 6596997572802685744626960256235787019476434707654191935397530271983648431547#g^x*g^y = g^(x+m-x) = g^m = g^(p-1) = 1 mod p
flag = ''
for i in range(1, len(v)):a,b = eval(v[i])if a*b%p == 1:flag +='1'else:flag +='0'print(flag)
flag = bytes([int(flag[i:i+8],2) for i in range(0, len(flag),8)])
print(flag)
#UMDCTF{I_d0nt_th1nk_bulby_!s_th3_n3xt_3ul3r_tbh}

Noisy Bits

这题对每字节进行编码,然后加入3位误码。这个估计有数学算法进行回纠,不过没见过。这里对所有情况进行遍历,23^3并不大

import randomPOLY = 0xC75
FLAG_BIN_LENGTH = 360def encode(cw):cw = (cw & 0xfff)c = cwfor i in range(1, 12+1):if cw & 1 != 0:cw = cw ^ POLYcw = cw >> 1return (cw << 12) | cflag = open('flag.txt', 'rb').read()binary_str = bin(int.from_bytes(flag))[2:].zfill(FLAG_BIN_LENGTH)blocks = [ ''.join([binary_str[12*i+j] for j in range(12)]) for i in range(FLAG_BIN_LENGTH // 12) ]
block_nos = [ int(s, 2) for s in blocks ]encoded = [ encode(cw) for cw in block_nos ]# flip some bits for fun
for i in range(len(encoded)):encoded[i] = encoded[i] ^ (1 << random.randint(0,22))encoded[i] = encoded[i] ^ (1 << random.randint(0,22))encoded[i] = encoded[i] ^ (1 << random.randint(0,22))encoded_bin = [ bin(e)[2:].zfill(23) for e in encoded ]print(' '.join(encoded_bin))

爆破式,可以发现没有一位由于误码造成误解,应该是可能通过哪些位的异或啥的纠错。

a1 = {}
for i in range(0x1000):a1[encode(i)]=ic = '01011100111010101110100 10111111010110100001100 00011010110011000110100 10000000111010101100110 10111011111000110110110 00001000110111100110000 10000010101001110010011 11001001000010101110001 10011100110010111010010 11100110111011101101010 01111111110001101001110 00000001011111001101100 10101101111000110110110 11011001100010000011101 10011100111011111010010 11001011100010101110010 11110001101000100110001 01111010100111110101100 00101001110001000000111 11101100000000001111111 11000010011010000000101 10101110001111100110000 10111111110011100000011 01101010101000001100010 01101011100000011000110 00101010010000101001101 11111011011010011110011 11100100100110001011110 10110111101011101010111 11010010000110100001010'c = [int(i,2) for i in c.split(' ')]m = []
for v in c:tmp = []for i in range(23):for j in range(23):for k in range(23):u = v^(1<<i)^(1<<j)^(1<<k)if u in a1:if a1[u] not in tmp:tmp.append(a1[u])m.append(tmp)#m = [[1364], [3396], [1077], [1094], [1974], [3632], [1683], [1401], [1526], [872], [838], [3694], [822], [3125], [1526], [370], [821], [3950], [775], [1119], [1029], [3952], [1827], [98], [1734], [1357], [1523], [1119], [1879], [3338]]for i in range(0,len(m),2):for v1 in m[i]:for v2 in m[i+1]:print(chr(v1>>4)+chr(((v1&0xf)<<4)|(v2>>8)) + chr(v2&0xff), end='')#UMDCTF{n0i5y_ch4nn3l5_ar3_n0t_@_pr0bleM_4_u}

Hidden Message

只有一段密文,猜是摩尔斯码(大小写和空格),但flag试了好久,就是flag要小写!换成下划线,最后一个叹号删除。

GO CATCH tHe bug parAS! AbRa LIKES His speED! GO catCH zubaT Or not! like paraS cutE zUBAT Is FUn! hes GREAT! GO CATch RoCk onix! onIx LOVes My new mATTE rocKS lol!

UMDCTF{m0rs3_c0d3_m34ns_h4v1ng_s0_m8ch_f8ns13s}

Reduce Thyself

题目给了n,e,c并提供解密,显然是通过给c*k^e来解题,但要求输入的是素数,所以爆破个k就行

import socket
import random
import threading
from _thread import *
from Crypto.Util.number import long_to_bytes as l2b, bytes_to_long as b2l, getPrime, isPrime, inverse
from math import gcd
from binascii import hexlify, unhexlifyHOST = '0.0.0.0'  # Standard loopback interface address (localhost)
PORT = 60003        # Port to listen on (non-privileged ports are > 1023)
FLAG = open('flag.txt', 'r').read().strip().encode()def decrypt(flag_ct, ct, d, n):pt = 'null'if isPrime(ct) and ct != flag_ct:pt = hexlify(l2b(pow(ct, d, n))).decode()return ptdef gen_params():while True:p,q = getPrime(1024), getPrime(1024)n = p*qe = 0x10001phi = (p-1)*(q-1)if gcd(phi, e) == 1:d = inverse(e, phi)breakreturn n,e,ddef threading(conn):n,e,d = gen_params()flag_ct = pow(b2l(FLAG), e, n)print(f'n: {n}\ne: {e}\nd: {d}')conn.sendall(f'n: {hex(n)}\ne: {hex(e)}\nflag_ct: {hex(flag_ct)}\n\n'.encode())while True:conn.sendall(b'Gimme ct (hex): ')try:ct = int(conn.recv(1024).strip().decode(), 16)except Exception as e:conn.sendall(b'invalid ct')breakpt = decrypt(flag_ct, ct, d, n)conn.sendall(f'result: {pt}\n\n'.encode())conn.close() if __name__ == "__main__":with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)s.bind((HOST, PORT))s.listen()while True:conn, addr = s.accept()print(f'new connection: {addr}')start_new_thread(threading, (conn, ))s.close()for i in range(500):if isPrime(c*pow(i+1, e, n)%n):print(i)
from pwn import *
from Crypto.Util.number import long_to_bytes as l2b, bytes_to_long as b2l, getPrime, isPrime, inversep = remote('0.cloud.chals.io', 33047)
context.log_level = 'debug'p.recvuntil(b"n: ")
n = int(p.recvline(),16)p.recvuntil(b"flag_ct: ")
flag_ct = int(p.recvline(),16)e = 0x10001
for i in range(1,2000):ct = flag_ct*pow(i,e,n)%nif isPrime(ct):print(i)p.sendlineafter(b'Gimme ct (hex): ', hex(ct)[2:].encode())p.recvuntil(b'result: ')m = int(p.recvline(),16)m //= i print(l2b(m))break

AES-TR

题目给出两个功能,随机出一个数0/1,可以询问,回复根据随机数返回询问的两个值AES_ECB加密的结果。这里IV会和密文一起给出,密文是counter序列1-2-3...与输入相加的结果

import socket
import random
import threading
from _thread import *
from Crypto import Random
from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes as l2b, bytes_to_long as b2l
from Crypto.Util.strxor import strxor
from binascii import hexlify, unhexlifyHOST = '0.0.0.0'  # Standard loopback interface address (localhost)
PORT = 60000        # Port to listen on (non-privileged ports are > 1023)
FLAG = open('flag.txt', 'r').read().strip()
MENU = "\nWhat would you like to do?\n\t(1) Encryption Query\n\t(2) Check Bit\n\t(3) Exit\n\nChoice: "
INITIAL = "Welcome to the best symmetric encryption scheme ever. I'll give you a flag if you can prove this scheme insecure under IND-CPA, but I know it's impossible!! >:)\n"BS = 16 # Block Size
MS = 30 # Maximum blocks per query
MAX_QUERIES = 10
NUM_BITS = 128def encrypt(m):m = unhexlify(m)iv = Random.get_random_bytes(16)key = Random.get_random_bytes(16)cipher = AES.new(key, AES.MODE_ECB)blocks = [m[i:i+BS] for i in range(0, len(m), BS)]ct = ivfor i in range(len(blocks)):ctr = l2b((b2l(iv)+i+1) % pow(2,BS*8))ctr = b'\x00'*(BS - len(ctr)) + ctr # byte padding if ctr < pow(2,BS*8 - 1)ct += cipher.encrypt(strxor(ctr, blocks[i]))assert len(ct) - len(m) == BSreturn hexlify(ct)def threading(conn):conn.sendall(INITIAL.encode())for bit in range(NUM_BITS):queries = 0b = random.randint(0,1)while queries < MAX_QUERIES:conn.sendall(MENU.encode())try:choice = conn.recv(1024).decode().strip()except ConnectionResetError as cre:return# ENCRYPTION QUERYif choice == '1':queries += 1conn.sendall(b'm0 (hex): ')m0 = conn.recv(1024).strip()conn.sendall(b'm1 (hex): ')m1 = conn.recv(1024).strip()if (len(m0) % 2 != 0) or ((len(m0) // 2) % BS != 0) or ((len(m0) // (2*BS)) > MS):conn.sendall(b'invalid m0\n')elif (len(m1) % 2 != 0) or ((len(m1) // 2) % BS != 0) or ((len(m1) // (2*BS)) > MS):conn.sendall(b'invalid m1\n')elif len(m0) != len(m1):conn.sendall(b'messages must be same length\n')else:if b == 0:ct = encrypt(m0)else:ct = encrypt(m1)conn.sendall(b'ct: ' + ct + b'\n')continue# CHECK BITelif choice == '2':conn.sendall(b'Bit (b) guess: ')b_guess = conn.recv(1024).strip().decode()if b_guess == str(b):conn.sendall(b'correct!\n')breakelse:conn.sendall(b'wrong\n')# EXITelif choice == '3':conn.sendall(b'bye homie\n')# INVALIDelse:conn.sendall(b'invalid menu choice\n')# close connection on exit, invalid choice, wrong bit guess, invalid encryption queryconn.close()returnif queries > MAX_QUERIES:conn.sendall(f'too many queries: {queries}\n'.encode())conn.close()return# Bits guessed correctlyconn.sendall(f'okay, okay, here is your flag: {FLAG}\n'.encode())conn.close()if __name__ == "__main__":with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)s.bind((HOST, PORT))s.listen()while True:conn, addr = s.accept()print(f'new connection: {addr}')start_new_thread(threading, (conn, ))s.close()

由于query会返回两个序列加密的结果,可以通过输入加密后的结果判断是选的哪一项。

如果能通过输入的值来构造出相同的密文,判断密文就可知选的是哪个

如果iv的尾两位为00,转入 0...01,10,11,00 恰 好与序列相同,那么生成的密文4段全都相同,但当iv是01时会是什么样呢,在11后会有进位,导致不仅尾两位变化,所以这里的输入扩展到5块,对应下表

IV\输入 01 10 11 00 01 10
00 01 10 11 - - -
01 - - 00 01 10 11
10 - 00 01 10 11 -
11 00 01 10 11 - -

由于IV尾数不为00会在第几个序号后回到00,当一组00-11为尾数时不会产生进位,所以通过一组不会产生进位的位置中的相同关系来确定随机选择的是哪个。标蓝的部分结果相同。

from pwn import *
from Crypto.Util.number import long_to_bytes as l2b, bytes_to_long as b2lp = remote('0.cloud.chals.io', 24524)context.log_level = 'debug'def query():p.sendlineafter(b"Choice: ", b'1')p.sendlineafter(b'm0 (hex): ', c1+c2+c3+c4+c1) #0p.sendlineafter(b'm1 (hex): ', c4*5)p.recvuntil(b'ct: ')ct = p.recvline().strip().decode()cs = [int(ct[i*32:(i+1)*32],16) for i in range(6)]if (cs[0]&3 == 0 and cs[1]==cs[2]) or (cs[0]&3 == 1 and cs[3]==cs[5]) or (cs[0]&3 == 2 and cs[2]==cs[3]) or (cs[0]&3 == 3 and cs[1]==cs[3]):return 0else:return 1def guess(b):p.sendlineafter(b"Choice: ", b'2')p.sendlineafter(b'Bit (b) guess: ', str(b).encode())c1 = b'00000000000000000000000000000001'
c2 = b'00000000000000000000000000000002'
c3 = b'00000000000000000000000000000003'
c4 = b'00000000000000000000000000000000'for i in range(128):b = query()guess(b)p.recvline()
p.recvline()
p.recvline()p.interactive()
#UMDCTF{N0t_@_v3ry_gr34t_5ch3m3_8ae61b7910099}

其它题等WP

[UMDCTF 2023] crypto 部分相关推荐

  1. [LitCTF 2023] crypto,pwn,rev

    这个比赛有巨多的题,而且基本上都很简单,队里答疯了.其实没大意思,本来不想写了,可又没啥可写,这周也就干点这个,算是放松吧. Crypto 1,HEX 略 2,梦想是红色的,略 3,原来你也玩原神 原 ...

  2. [cryptoverse CTF 2023] crypto部分

    没打,完事作作题. Warmup 1 Decode the following ciphertext: GmvfHt8Kvq16282R6ej3o4A9Pp6MsN. Remember: CyberC ...

  3. LitCTF 2023 - crypto复现

    文章目录 Hex?Hex! 梦想是红色的 原来你也玩原神 factordb P_Leak e的学问 Euler * Where is P? The same common divisor md5 ba ...

  4. DASCTF Apr.2023 Crypto 全解

    目录 [简单]sign1n [中等]ECC? [困难]babyhash [困难]babyhash_revenge [简单]sign1n from Crypto.Util.number import * ...

  5. [tjctf 2023] crypto,pwn,rev部分

    三块没有一个通关的.rev差两个,crypto.pwn都差一题 Crypto baby-rsa 给出n,e,c其中e=3,c明显小于n,这个一看就是n给大了e给小了,结果乘幂后还是比n小,直接开根号 ...

  6. Coinbase:2023 年 Crypto 市场展望

    作者:Coinbase 机构研究主管 David Duong 编译:DeFi 之道 隔夜的粥 图片来源:由无界版图AI工具生成 核心观点: 我们预计数字资产选择将根据可持续代币经济学.各自生态系统的成 ...

  7. 一览 A16z 在 2023 年重点关注的 Crypto 和 Web3 游戏想法

    原文来自:a16z 编译:DeFi 之道 隔夜的粥 注:顶级投资机构 a16z 刚刚发布了一份综合关注清单,列出了科技建设者在未来一年可能要解决的"大想法",这份清单涵盖了消费科技 ...

  8. [DASCTF Apr.2023 X SU战队2023开局之战] crypto复现

    感觉突然啥都不会了,后来拿到官方WP,也没整明白,这官方的WP没有代码只讲了些道理,复现一下也不容易. 1,easySign 这是个自制的签名题. from secret import r, t fr ...

  9. 2023 贵阳大数据安全精英赛 --- Crypto childrsa wp

    文章目录 题目 解题过程 解题代码 题目 childrsa.py from Crypto.Util.number import *flag = b'xxx' p = getPrime(512) q = ...

最新文章

  1. 设置显示Git的修改历史History快捷键Alt+H,方便多人开发的时候快速查看谁修改了代码
  2. 重磅消息:Spring 6 和Spring Boot 3
  3. 报名丨图神经网络前沿学术研讨会:清北高校vs企业,9位学者联袂分享
  4. Nginx在开发中常用的基础命令
  5. java array_Java 数组
  6. java lambda表达式详解_Lambda表达式详解
  7. 基于JavaWEB SSM SpringBoot婚纱影楼摄影预约网站设计和实现
  8. 响应式布局这件小事有哪些优点和缺点该怎么设计
  9. [HDU] 1533 Going Home
  10. Access数据库基于时间盲注的实现[www.freebuf.com]
  11. mysql高并发频繁地写_Mysql写入频繁,怎么破?
  12. 谈谈Ext JS组件之引子
  13. DDA算法和Bresenham算法
  14. 21天学通c语言中用的编译器,21天学通C语言
  15. Bootstrap横屏后竖屏
  16. oracle dbms_utility.get_time,dbms_utility如何使用?
  17. 破解水卡最省钱!超详细!--解决小白烦恼
  18. 软件测试发展前景进阶路线
  19. 计算机导航种植牙的优势,计算机导航微创种植牙修复
  20. SPI器件的菊链配置

热门文章

  1. shell的一些练习。
  2. 七种武器 ------- 鼠标
  3. 油管与脸书皆强化直播服务功能 打造更专业的直播平台
  4. Automatic Plugin -WordPress自动采集插件 v3.56.0
  5. 遇到滴滴司机以返程空驶为由额外加价,该如何有效维权?
  6. KM查询--好用的 汉语成语 查询 网站
  7. 07-项目训练_分页列表、快递录入、删除和修改
  8. 1092 最好吃的月饼 (20 分)
  9. 多个时间序列之间的DTW
  10. CSP 201812-1小明上线(c语言)