# 闲题杂记

Contents

[toc]

## gkctf2021 6-25 补档

### XOR

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  from Crypto.Util.number import * from hashlib import md5 a = getPrime(512) b = getPrime(512) c = getPrime(512) d = getPrime(512) d1 = int(bin(d)[2:][::-1] , 2) n1 = a*b x1 = a^b n2 = c*d x2 = c^d1 flag = md5(str(a+b+c+d).encode()).hexdigest() print("n1 =",n1) print("x1 =",x1) print("n2 =",n2) print("x2 =",x2) 

a = 111

b = 100

a*a = 1 1000 1

b*b = 010000

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38   # 初始化第1位的已知数：0 def getab(n,x,lenth): a_list=[0] b_list=[0] # 这里判断512位应该就够了阿。。。。 mask = 0 for i in range(lenth): # 取第n位 mask = 2**(i+1)-1 xi = (x>>i) & 1 nextA_list=[] nextB_list=[] for ai in range(2): for bi in range(2): for j in range(len(a_list)): if (ai^bi == xi): nlow = n & mask axbLow = (((ai<

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55  def get_cd(n,x,lenth): p_low = [0] q_high = [0] q_low = [0] p_high = [0] # maskn = 2 maskn = 0 for i in range(lenth//2): maskn = 2**(i+1)-1 xi = (x >> i )&1 n_lowbits = (n & maskn) # 高位判断从lenth-1处开始 High_index = lenth-1 -i XHi = (x >> (High_index))&1 n_highbits = (n)>> (High_index) *2 nextP_l = [] nextQ_l = [] nextP_h =[] nextQ_h =[] for j in range(len(p_low)): for pl in range(2): for ql in range(2): for ph in range(2): for qh in range(2): if pl ^ qh == xi and ql ^ ph == XHi: PlxQl = (((pl<>(High_index)*2 if PlxQl == n_lowbits : # if n_highbits-PhxQh >= 0 and n_highbits-PhxQh <=((2<= 0 and n_highbits-PhxQh <=((2<

## n1ctf2021

### vss

• 难点在随机数预测上面

 1 2 3 4 5 6 7 8 9   qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=12, border=4, ) qr.add_data(FLAG) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") 

RGB = 0xffffff 是白色

RGB = 0 是黑色

  1 2 3 4 5 6 7 8 9 10   if pixel: ... else: share1.putpixel((2*x, 2*y), color0) share1.putpixel((2*x, 2*y+1), color0) ... share2.putpixel((2*x, 2*y), color1) share2.putpixel((2*x, 2*y+1), color1) ... 

exp

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35  from PIL import Image from randcrack import RandCrack import random share = Image.open('./share2.png') width = share.size[0]//2 res = Image.new('L', (width, width)) bits = '' # pixel为1填充0 # pixel为0填充1 # 01分别对应的是黑色的填充和白色的背景像素 # 官p取最后一段连续白色 for idx in range(width*width-624*32, width*width): i, j = idx//width, idx % width if share.getpixel((2*j, 2*i)) == 255: bits += '0' else: bits += '1' # 判断像素后 rc = RandCrack() for i in range(len(bits), 0, -32): rc.submit(int(bits[i-32:i], 2)) flipped_coins = [int(bit) for bit in bin(rc.predict_getrandbits(width*width-624*32))[2:].zfill(width*width-624*32)] + list(map(int, bits)) data = [] for idx in range(width*width): i, j = idx//width, idx % width if share.getpixel((2*j, 2*i)) == 255: data.append(0 if flipped_coins[idx] else 255) else: data.append(255 if flipped_coins[idx] else 0) res.putdata(data) res.save('ans.png') 

## CISCN 2021 oddaes

### Differential Fault Analysis（DFA）

Differential fault analysis (DFA) is a type of active side-channel attack in the field of cryptography, specifically cryptanalysis. The principle is to induce faults—unexpected environmental conditions—into cryptographic implementations, to reveal their internal states.

For example, a smartcard containing an embedded processor might be subjected to high temperature, unsupported supply voltage or current, excessively high overclocking, strong electric or magnetic fields, or even ionizing radiation to influence the operation of the processor. The processor may begin to output incorrect results due to physical data corruption, which may help a cryptanalyst deduce the instructions that the processor is running, or what its internal data state is.

For DES and Triple DES, about 200 single-flipped bits are necessary to obtain a secret key.DFA was also applied successfully to the AES cipher.

### analysis and implement

https://eprint.iacr.org/2009/575.pdf

Abstract. In this paper we present a differential fault attack that can be applied to the AES using a single fault. We demonstrate that when a single random byte fault is induced at the input of the eighth round, the AES key can be deduced using a two stage algorithm.

Conclusion

these attacks can be conducted without any knowledge of the plaintext being enciphered, as an attacker would just need to know the plaintexts were the same

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47   def encrypt_block(self, plaintext): """ Encrypts a single block of 16 byte long plaintext. """ assert len(plaintext) == 16 plain_state = bytes2matrix(plaintext) add_round_key(plain_state, self._key_matrices[0]) for i in range(1, self.n_rounds): sub_bytes(plain_state) shift_rows(plain_state) mix_columns(plain_state) add_round_key(plain_state, self._key_matrices[i]) sub_bytes(plain_state) shift_rows(plain_state) add_round_key(plain_state, self._key_matrices[-1]) return matrix2bytes(plain_state) def encrypt_block_(self, plaintext,bytee): """ Encrypts a single block of 16 byte long plaintext. """ assert len(plaintext) == 16 plain_state = bytes2matrix(plaintext) add_round_key(plain_state, self._key_matrices[0]) for i in range(1, self.n_rounds): # 故意在第八轮中手动加入了差错。。。。 if i==8: plain_state[0][0] ^= bytee sub_bytes(plain_state) shift_rows(plain_state) mix_columns(plain_state) add_round_key(plain_state, self._key_matrices[i]) sub_bytes(plain_state) shift_rows(plain_state) add_round_key(plain_state, self._key_matrices[-1]) keym = self._key_matrices[-1] return matrix2bytes(plain_state),keym[0]+keym[1]+keym[2]+keym[3] 

https://github.com/Daeinar/dfa-aes

csv的文件结构和txt基本一样

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23  from aes import AES import os,hashlib,random from tqdm import tqdm # ----------------------------------- f = open('keys-0.csv','r') plain = os.urandom(16) m1 = '973f5ae78bc933a8fc7f7ab98d53d16f' m2 = '628aab012199cdab83cc1aa72204ea98' s = random.randint(0,255) for i in tqdm(range(4266)): key = f.readline().replace('\n','') cipher,k = AES(bytes.fromhex(key)).encrypt_block_(plain,s) piece1 = [k[0],k[1],k[4],k[7],k[10],k[11],k[13],k[14]] m11 = hashlib.md5(bytes(piece1)).hexdigest() piece2 = [k[2],k[3],k[5],k[6],k[8],k[9],k[12],k[15]] m22 = hashlib.md5(bytes(piece2)).hexdigest() if m11 == m1 and m22 == m2: print(key) print("CISCN{"+hashlib.md5(bytes.fromhex(key)).hexdigest()+"}") break 

## 癫疯极客2021补档 7-31

### learnSM4

SM4采用和aes完全不同的结构

  1 2 3 4 5 6 7 8 9 10 11 12 13  def _crypthack(num, mk, rou,index): x_keys = list(_byte_unpack(num, byte_n=16)) round_keys = _round_keys(mk) leak = 0 for i in _range(32): reg = _round_f(x_keys[i:i+4], round_keys[i]) x_keys.append(reg) # use x0123 get x4 reg = _byte_unpack(reg) if i == rou: leak = reg[index] return _byte_pack(x_keys[-4:][::-1], byte_n=16),leak 

$X_4=repT(X_1\oplus X_2\oplus X_3\oplus roundKey)$

 1 2 3 4  def _round_f(byte4_array, rk): x0, x1, x2, x3 = byte4_array print(x0, x1, x2, x3) return x0 ^ _rep_t(x1 ^ x2 ^ x3 ^ rk) 

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68  import z3 S_BOX = { 0X00: 0XD6, 0X01: 0X90, 0X02: 0XE9, 0X03: 0XFE, 0X04: 0XCC, 0X05: 0XE1, 0X06: 0X3D, 0X07: 0XB7, 0X08: 0X16, 0X09: 0XB6, 0X0A: 0X14, 0X0B: 0XC2, 0X0C: 0X28, 0X0D: 0XFB, 0X0E: 0X2C, 0X0F: 0X05, 0X10: 0X2B, 0X11: 0X67, 0X12: 0X9A, 0X13: 0X76, 0X14: 0X2A, 0X15: 0XBE, 0X16: 0X04, 0X17: 0XC3, 0X18: 0XAA, 0X19: 0X44, 0X1A: 0X13, 0X1B: 0X26, 0X1C: 0X49, 0X1D: 0X86, 0X1E: 0X06, 0X1F: 0X99, 0X20: 0X9C, 0X21: 0X42, 0X22: 0X50, 0X23: 0XF4, 0X24: 0X91, 0X25: 0XEF, 0X26: 0X98, 0X27: 0X7A, 0X28: 0X33, 0X29: 0X54, 0X2A: 0X0B, 0X2B: 0X43, 0X2C: 0XED, 0X2D: 0XCF, 0X2E: 0XAC, 0X2F: 0X62, 0X30: 0XE4, 0X31: 0XB3, 0X32: 0X1C, 0X33: 0XA9, 0X34: 0XC9, 0X35: 0X08, 0X36: 0XE8, 0X37: 0X95, 0X38: 0X80, 0X39: 0XDF, 0X3A: 0X94, 0X3B: 0XFA, 0X3C: 0X75, 0X3D: 0X8F, 0X3E: 0X3F, 0X3F: 0XA6, 0X40: 0X47, 0X41: 0X07, 0X42: 0XA7, 0X43: 0XFC, 0X44: 0XF3, 0X45: 0X73, 0X46: 0X17, 0X47: 0XBA, 0X48: 0X83, 0X49: 0X59, 0X4A: 0X3C, 0X4B: 0X19, 0X4C: 0XE6, 0X4D: 0X85, 0X4E: 0X4F, 0X4F: 0XA8, 0X50: 0X68, 0X51: 0X6B, 0X52: 0X81, 0X53: 0XB2, 0X54: 0X71, 0X55: 0X64, 0X56: 0XDA, 0X57: 0X8B, 0X58: 0XF8, 0X59: 0XEB, 0X5A: 0X0F, 0X5B: 0X4B, 0X5C: 0X70, 0X5D: 0X56, 0X5E: 0X9D, 0X5F: 0X35, 0X60: 0X1E, 0X61: 0X24, 0X62: 0X0E, 0X63: 0X5E, 0X64: 0X63, 0X65: 0X58, 0X66: 0XD1, 0X67: 0XA2, 0X68: 0X25, 0X69: 0X22, 0X6A: 0X7C, 0X6B: 0X3B, 0X6C: 0X01, 0X6D: 0X21, 0X6E: 0X78, 0X6F: 0X87, 0X70: 0XD4, 0X71: 0X00, 0X72: 0X46, 0X73: 0X57, 0X74: 0X9F, 0X75: 0XD3, 0X76: 0X27, 0X77: 0X52, 0X78: 0X4C, 0X79: 0X36, 0X7A: 0X02, 0X7B: 0XE7, 0X7C: 0XA0, 0X7D: 0XC4, 0X7E: 0XC8, 0X7F: 0X9E, 0X80: 0XEA, 0X81: 0XBF, 0X82: 0X8A, 0X83: 0XD2, 0X84: 0X40, 0X85: 0XC7, 0X86: 0X38, 0X87: 0XB5, 0X88: 0XA3, 0X89: 0XF7, 0X8A: 0XF2, 0X8B: 0XCE, 0X8C: 0XF9, 0X8D: 0X61, 0X8E: 0X15, 0X8F: 0XA1, 0X90: 0XE0, 0X91: 0XAE, 0X92: 0X5D, 0X93: 0XA4, 0X94: 0X9B, 0X95: 0X34, 0X96: 0X1A, 0X97: 0X55, 0X98: 0XAD, 0X99: 0X93, 0X9A: 0X32, 0X9B: 0X30, 0X9C: 0XF5, 0X9D: 0X8C, 0X9E: 0XB1, 0X9F: 0XE3, 0XA0: 0X1D, 0XA1: 0XF6, 0XA2: 0XE2, 0XA3: 0X2E, 0XA4: 0X82, 0XA5: 0X66, 0XA6: 0XCA, 0XA7: 0X60, 0XA8: 0XC0, 0XA9: 0X29, 0XAA: 0X23, 0XAB: 0XAB, 0XAC: 0X0D, 0XAD: 0X53, 0XAE: 0X4E, 0XAF: 0X6F, 0XB0: 0XD5, 0XB1: 0XDB, 0XB2: 0X37, 0XB3: 0X45, 0XB4: 0XDE, 0XB5: 0XFD, 0XB6: 0X8E, 0XB7: 0X2F, 0XB8: 0X03, 0XB9: 0XFF, 0XBA: 0X6A, 0XBB: 0X72, 0XBC: 0X6D, 0XBD: 0X6C, 0XBE: 0X5B, 0XBF: 0X51, 0XC0: 0X8D, 0XC1: 0X1B, 0XC2: 0XAF, 0XC3: 0X92, 0XC4: 0XBB, 0XC5: 0XDD, 0XC6: 0XBC, 0XC7: 0X7F, 0XC8: 0X11, 0XC9: 0XD9, 0XCA: 0X5C, 0XCB: 0X41, 0XCC: 0X1F, 0XCD: 0X10, 0XCE: 0X5A, 0XCF: 0XD8, 0XD0: 0X0A, 0XD1: 0XC1, 0XD2: 0X31, 0XD3: 0X88, 0XD4: 0XA5, 0XD5: 0XCD, 0XD6: 0X7B, 0XD7: 0XBD, 0XD8: 0X2D, 0XD9: 0X74, 0XDA: 0XD0, 0XDB: 0X12, 0XDC: 0XB8, 0XDD: 0XE5, 0XDE: 0XB4, 0XDF: 0XB0, 0XE0: 0X89, 0XE1: 0X69, 0XE2: 0X97, 0XE3: 0X4A, 0XE4: 0X0C, 0XE5: 0X96, 0XE6: 0X77, 0XE7: 0X7E, 0XE8: 0X65, 0XE9: 0XB9, 0XEA: 0XF1, 0XEB: 0X09, 0XEC: 0XC5, 0XED: 0X6E, 0XEE: 0XC6, 0XEF: 0X84, 0XF0: 0X18, 0XF1: 0XF0, 0XF2: 0X7D, 0XF3: 0XEC, 0XF4: 0X3A, 0XF5: 0XDC, 0XF6: 0X4D, 0XF7: 0X20, 0XF8: 0X79, 0XF9: 0XEE, 0XFA: 0X5F, 0XFB: 0X3E, 0XFC: 0XD7, 0XFD: 0XCB, 0XFE: 0X39, 0XFF: 0X48 } def getnum(arr): HEX = '' for i in arr: HEX += hex(i)[2:] return int(HEX,16) # 用z3逆T变换中的r(x) def f(B): B1 = (((B << 2 ) & 0b1100000000000000000000000000000000) >>32) ^ (B << 2) & 0xffffffff B2 = (((B << 10) & 0b111111111100000000000000000000000000000000) >> 32) ^ (B<<10) & 0xffffffff B3 = (((B << 18) & 0b11111111111111111100000000000000000000000000000000) >> 32) ^ (B<<18) & 0xffffffff B4 = (((B << 24) & 0b11111111111111111111111100000000000000000000000000000000) >> 32) ^ (B<<24) & 0xffffffff return B ^ B1 ^ B2 ^ B3 ^ B4 S = z3.Solver() x = z3.BitVec('x',64) # 四次获取的x4 S.add((getnum([173,171,64,87])^1)- f(x)==0) if S.check(): print(S.model()) # [x = 2810370552] print(hex(2810370552)[2:]) # 0x842586b9 key = '0' arr = [0xa7,0x82,0xd9,0xf8] for i in arr: key += hex(findS(i))[2:] print(int(key,16)) 

### crtrsa

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23  from gmpy2 import * from Crypto.Util.number import * from tqdm import tqdm from rich.progress import track from rich.traceback import install install() # ----------------------------------- N = 6006128121276172470274143101473619963750725942458450119252491144009018469845917986523007748831362674341219814935241703026024431390531323127620970750816983 e = 2953544268002866703872076551930953722572317122777861299293407053391808199220655289235983088986372630141821049118015752017412642148934113723174855236142887 c=4082777468662493175049853412968913980472986215497247773911290709560282223053863513029985115855416847643274608394467813391117463817805000754191093158289399 a=2 A=powmod(a,e,N) for dp in tqdm(range(1,2**20)): if gcd(powmod(A,dp,N)-a,N)!=1 and gcd(powmod(A,dp,N)-a,N)!=N: p=gcd(pow(A,dp,N)-a,N) q=N//p phi=(p-1)*(q-1) d=invert(e,phi) m=pow(c,d,N) print(long_to_bytes(m)) break