点击上方蓝字关注我们~
import os
import random
import secrets
import string
#from secret import flag, secret_1, secret_2, flag_token
flag='TQLCTF{eee67011-f2a0-4f5f-ae48-1de28c76939x}'
# ========================================================================
class InvalidChar(Exception):
pass
class DangerousToken(Exception):
pass
valid_char = [ord(x) for x in string.digits +
string.ascii_letters + string.punctuation]
def check_valid(s: bytes):
r = list(map(lambda x: x in valid_char, s))
if False in r:
raise InvalidChar(r.index(False))
def getrandbits(token: bytes, k: int) -> int:
random.seed(token)
return random.getrandbits(k)
def bytes_xor_int(s: bytes, r: int, length: int) -> bytes:
s = int.from_bytes(s, 'little')
return (s ^ r).to_bytes(length, 'little')
def __byte_shuffle(s: int) -> int:
bits = list(bin(s)[2:].zfill(8))
random.shuffle(bits)
return int(''.join(bits), 2)
def __byte_shuffle_re(s: int) -> int:
s = bin(s)[2:].zfill(8)
idx = list(range(8))
random.shuffle(idx)
s = ''.join([s[idx.index(i)] for i in range(8)])
return int(s, 2)
def bits_shuffle(s: bytes) -> bytes:
s = bytearray(s)
for i in range(len(s)):
s[i] = __byte_shuffle(s[i])
return bytes(s)
def bits_shuffle_re(s: bytes) -> bytes:
s = bytearray(s)
for i in range(len(s)):
s[i] = __byte_shuffle_re(s[i])
return bytes(s)
def bytes_shuffle(token: bytes, s: bytes) -> bytes:
random.seed(token)
s = bytearray(s)
random.shuffle(s)
return bytes(s)
def bytes_shuffle_re(token: bytes, s: bytes) -> bytes:
random.seed(token)
idx = list(range(len(s)))
random.shuffle(idx)
r = bytearray(len(s))
for i in range(len(s)):
r[idx[i]] = s[i]
return bytes(r)
def encrypt(s: str, token=(None, None)):
if token[0] is None or token[1] is None:
token = (secrets.randbits(32).to_bytes(4, 'little'),
secrets.randbits(32).to_bytes(4, 'little'))
s: bytes = s.encode()
check_valid(s)
r = getrandbits(token[0]+secret_1, 8*len(s))
s = bytes_xor_int(s, r, len(s))
s = bits_shuffle(s)
s += token[0]
s = bytes_shuffle(token[1]+secret_2, s)
s += token[1]
s = s.hex()
return s
def decrypt(s: str):
s: bytes = bytes.fromhex(s)
s, token_1 = s[:-4], s[-4:]
s = bytes_shuffle_re(token_1+secret_2, s)
s, token_0 = s[:-4], s[-4:]
r = getrandbits(token_0+secret_1, 8*len(s))
s = bits_shuffle_re(s)
s = bytes_xor_int(s, r, len(s))
check_valid(s)
s = s.decode()
if (len(s) == len(flag)) + (token_0 == flag_token[0]) + (token_1 == flag_token[1]) >= 2:
raise DangerousToken
return s
def encrypt_flag():
flag_enc = encrypt(flag, flag_token)
print(f'flag: {flag_enc}')
def rebuild():
global secret_1, secret_2, flag_token
secret_1 = os.urandom(64)
secret_2 = os.urandom(64)
flag_token = (os.urandom(4), os.urandom(4))
def choose_mode():
print('Choose function:')
print('0: encrypt')
print('1: decrypt')
print('2: rebuild')
mode = int(input('> '))
assert 0 <= mode <= 2
return mode
if __name__ == '__main__':
print('Welcome to Nano OTP Box!')
rebuild()
encrypt_flag()
while True:
try:
mode = choose_mode()
if mode == 0:
print('Please input original message.')
msg = input('> ')
print('encrypted message:', encrypt(msg))
elif mode == 1:
print('Please input encrypted message.')
msg = input('> ')
print('original message:', decrypt(msg))
elif mode == 2:
rebuild()
encrypt_flag()
except InvalidChar as e:
print('The original message contains invalid characters: pos', e)
except DangerousToken:
print('The encrypted message contains dangerous token')
题目流程
首先以secre1与token0的拼接作为随机数种子初始化一个随机数生成器
利用上述随机数生成器 getrandbits 生成随机数r,与明文异或,小端序
然后对每一个字节进行一个bit级别的乱序(还是用的上面的随机数生成器)
将输出拼接上token0
然后以secre2与token1的拼接作为随机数种子初始化一个随机数生成器
利用上述随机数生成器对整个字符串进行一个bytes级别的乱序
最后拼接上token1,输出密文
将输入密文的后四个字节取出作为token1
以secre2与token1的拼接作为随机数种子初始化一个随机数生成器
利用上述随机数生成器对整个字符串进行一个bytes级别的乱序恢复
将输出的后四个字节取出作为token2
以secre1与token0的拼接作为随机数种子初始化一个随机数生成器
然后对每一个字节进行一个bit级别的乱序恢复
继续利用上述随机数生成器 getrandbits 生成随机数r,与step6的输出异或,小端序
对上述输出进行检查,如果有一个非法字符(定义了可见字符集为合法字符),则会报错,并输出该字符在字符串中的位置
如果明文的长度与flag的长度相等,token0与flag_token0相等,token1与flag_token1相等,三者满足二,则会报错,并返回dangerous token
通过检查,则返回解密后的明文字符串。
题目分析
解题思路
step1 获取token1对应乱序规则
step2 用token1’ 替换token1
流程与脚本编写
from Crypto.Util.number import *
from TQLOPT import *
flag_enc = encrypt(flag, flag_token)
c = long_to_bytes(int(flag_enc,16))
table_from_to={}
token1to=[]
c = list(c)
# 异或flag_enc的各个bit以得到token1所对应的乱序规则
for index in range(len(c)-4):# 最后四个字节是token1
times = 0#记录invalid次数
for i in range(8):
tempc = c.copy()
tempc[index] ^= 1 << i
tempstr = ''.join(chr(i) for i in tempc)
tempbytes = tempstr.encode('latin1')
templong = bytes_to_long(tempbytes)
temphex = hex(templong)[2:].rjust(104,'0')# 这里只是想把异或c的一个bit然转成hex而已,绕了一圈属于是
try:
decrypt(temphex)
except InvalidChar as e:# 由于是本地调试,我直接捕获异常了,如果是远程交互,可能还需要写一个正则匹配一下返回值
fr0m = str(e)
times += 1
except DangerousToken:
pass
if times == 8:# 如果八次全错,说明我们改到token0了,记录下位置
token1to.append(index)
else:
table_from_to[fr0m] = index
# 至此,我们获取到了密文中token0的位置,已经相应的token1所对应的映射关系 table_from_to
# 故技重施,加密一个45字节的msg,获取token1' 已经其对应的映射关系 table11_to_from,这里反正记是方便后面的调用
msg = 'a'*45
msg_enc = encrypt(msg)
token11 = msg_enc[-8:]
table11_to_from={}
token11to=[]
c = long_to_bytes(int(msg_enc,16))
c = list(c)
for index in range(len(c)-4):
times = 0
for i in range(8):
tempc = c.copy()
tempc[index] ^= 1 << i
tempstr = ''.join(chr(i) for i in tempc)
tempbytes = tempstr.encode('latin1')
templong = bytes_to_long(tempbytes)
temphex = hex(templong)[2:].rjust((45+8)*2,'0')
try:
decrypt(temphex)
except InvalidChar as e:
fr0m = str(e)
times += 1
except DangerousToken:
pass
if times == 8:
token11to.append(index)
else:
table11_to_from[index] = fr0m
# 现在我们按照table_from_to,把flag的顺序调回来,
c = long_to_bytes(int(flag_enc,16)).decode('latin1')
rec = []
for i in range(52-8):
rec += c[table_from_to[str(i)]]
token0 = ''.join(c[token1to[i]] for i in range(4))
from itertools import permutations
for each in list(permutations(token0,4)):
token00 = list(each)
rectmp = rec+['0'] + token00#然后加上一个字节,加上24种token0,
rec_s = ""
token00index=0
for i in range(53-4):
if i in table11_to_from.keys():
rec_s += rectmp[int(table11_to_from[i])]# 按照table11_to_from乱序,剩下四个空用token0去补
else:
rec_s += token00[token00index]
token00index += 1
tempbytes = rec_s.encode('latin1')
templong = bytes_to_long(tempbytes)
temphex = hex(templong)[2:].rjust((45+4)*2,'0')
temphex += token11#加上token1',再拿去解密
try:
Token0=0
if 'TQLCTF' in decrypt(temphex):
print(decrypt(temphex))
exit()# 运气好一步到位
except InvalidChar as e:
if str(e) == '44':
Token0 = token00#如果44出错说明token0对了,去换字节就好
break
if not Token0:# 如果我们生成随机数r多用的那个状态在加密的时候shuffle是有用的,则有可能失败,直接再来一遍好了。
print("Try again")
exit()
table = list(string.digits + string.ascii_letters + string.punctuation)
for each in table:
rectmp = rec+[each] + Token0 #故技重施2,换字节,直到最后一个异或完是可打印字符
rec_s = ""
token00index=0
for i in range(53-4):
if i in table11_to_from.keys():
rec_s += rectmp[int(table11_to_from[i])] # 按照table11_to_from乱序,剩下四个空用token0去补
else:
rec_s += Token0[token00index]
token00index += 1
tempbytes = rec_s.encode('latin1')
templong = bytes_to_long(tempbytes)
temphex = hex(templong)[2:].rjust((45+4)*2,'0')
temphex += token11 #加上token1',再拿去解密
try:
if 'TQLCTF' in decrypt(temphex):
print(decrypt(temphex))
break
except Exception as e:
pass
Signature
sk = pk.BKZ(block_size = 20)
v = hash_msg("")
e = signature(sk,v)
hardrsa
beta = 0.233
delta = 0.226
amplification = 1024
alpha = 0.9987
modulus = e
mm = 5
ss = 0
tt = 5
Xp = int(2 * N ** (alpha + beta + delta - 1))
Yp = int(N**beta)
Yq = int(2 * N ** (1 - beta) )
#下面求G basis的时候,取个三组,会快些
I = ideal(all_pol[:3])
点个在看你最好看
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...