巅峰极客wp

7.31,今天打两场,一场巅峰极客,一场CryptoCTF,人麻了。巅峰极客一共三题密码,SM4那题听说差分,直接摸了,所以我就写了剩下两题,以下是wp。

MedicalImage

拿到题目源码,分析一下,题目缺少​,根据提示可以知道,是logistics混沌模型,百度找一下,让参数取最大的4就可以了,直接return 4*x*(1-x)。

后面encrypt的部分,先循环了200次​,把它们混沌了,然后是一个交换点的过程,这个过程是需要倒序逆向的 (正序没出,有师傅知道原因,告诉我为什么)。p0 c0做为config没有给我们,一共16组可以爆破,然后就是真正的加密部分的循环。

加密部分关键是 c0 = k ^ ((k + p0) % 256) ^ c0 。k这里可以直接得到然后异或回去,c0的话,取上一个点的值异或,然后再减k就可以了。这一部分的逆向需要顺序进行,否则p0是未知的。

from PIL import Image
from decimal import *
import numpy as np
import random

getcontext().prec = 20

def f1(x): assert (x >= 0) assert (x <= 1) return 4 * x * (1 - x)

def f2(x): assert (x >= 0) assert (x <= 1) return 4 * x * (1 - x)

def f3(x): assert (x >= 0) assert (x <= 1) return 4 * x * (1 - x)

im = Image.open(‘flag_enc.bmp’) size = im.size pic = np.array(im) im.close() r1 = Decimal(‘0.478706063089473894123’) r2 = Decimal(‘0.613494245341234672318’) r3 = Decimal(‘0.946365754637812381837’) w, h = size for i in range(200): r1 = f1(r1) r2 = f2(r2) r3 = f3(r3) const = 10 ** 14 p = [100, 101, 102, 103] c = [200, 201, 202, 203] R1, R2, R3 = r1, r2, r3 l1 = [] l2 = [] for i in range(w * h): l1.append(r1) l2.append(r2) r1 = f1(r1) r2 = f2(r2)

def decrypt(p0, c0, r1=R1, r2=R2, r3=R3): for x in range(w): for y in range(h): k = int(round(const * r3)) % 256 k = bin(k)[2:].ljust(8, ‘0’) k = int(k[p0 % 8:] + k[:p0 % 8], 2) r3 = f3(r3) pic[y, x] = ((pic[y, x] ^ c0 ^ k) - k) % 256 p0 = pic[y, x] c0 = k ^ ((k + p0) % 256) ^ c0 t = w * h - 1 for x in range(w - 1, -1, -1): for y in range(h - 1, -1, -1): x1 = int(round(const * l1[t])) % w y1 = int(round(const * l2[t])) % h tmp = pic[y, x] pic[y, x] = pic[y1, x1] pic[y1, x1] = tmp t -= 1 return pic, size

enc_img = ‘flag.bmp’ count = 0 for p0 in p: for c0 in c: pic, size = decrypt(p0, c0) im = Image.new(‘P’, size, ‘white’) pixels = im.load() for i in range(im.size[0]): for j in range(im.size[1]): pixels[i, j] = (int(pic[j][i])) count += 1 im.save(str(count) + enc_img)

crtrsa

这题一开始拿到,以为和MRCTF那题差不多,翻了那题的paper,怎么搞都搞不出来。再回到式子本身,才知道怎么做。

先对CRT化简

对(p-1)和(q-1)取模可以知道,dp、dq就是正常的dp、dq。

注意到dp被限制在1<<20之内,所以可以爆破。于是我们有

所以由费马小定理我们可以知道

于是只需要把等式左边的值,和n GCD就可以得到p,进而得到flag,不过爆破还是要跑一小会的。

import gmpy2 as gp
from Crypto.Util.number import *
e = 2953544268002866703872076551930953722572317122777861299293407053391808199220655289235983088986372630141821049118015752017412642148934113723174855236142887
n = 6006128121276172470274143101473619963750725942458450119252491144009018469845917986523007748831362674341219814935241703026024431390531323127620970750816983
c = 4082777468662493175049853412968913980472986215497247773911290709560282223053863513029985115855416847643274608394467813391117463817805000754191093158289399

for i in range(1,1<<20): dp=i t=pow(2,e*dp-1,n)-1 if gp.gcd(t,n)!=1: print(gp.gcd(t,n))

p=88483113499234291234797595363172914275282163218450540253170700235627922981203 q=n//p phi=(p-1)*(q-1) d=gp.invert(e,phi) print(long_to_bytes(pow(c,d,n)))

SM4

这题过几天复现(咕咕咕咕咕