DDCTF2020官方Write Up——MISC 篇

  • A+
所属分类:逆向工程

目录

 0x01 :一起来拼图

 0x02:decryp

   出题人现身说法,带来官方解读

01

一起来拼图

团队昵称:混吃等死 

一血用时:55分钟


出题人

DDCTF2020官方Write Up——MISC 篇

吴琼

滴滴出行专家工程师

出题人视角

原图被随机打散为6400块,选手通过使用图像识别算法,与原图进行比对,确定拼图碎片的位置,将拼图碎片拼回后,即可看到FLAG。另外一血混吃等死队思路清奇稳中带皮 ,所以再多放出一个猛追湾无人机侦查大队的WP,供同学们参考

-----选手Write Up-----

为了抢一血,和队友手撸出来的。在6400张图片里找含有flag的图片。一人找到17张图同名替换正好得到20张含有flag的图。

DDCTF2020官方Write Up——MISC 篇

用ps拼:

DDCTF2020官方Write Up——MISC 篇

团队昵称:猛追湾无人机侦查大队


对原图片,从左到右从上到下,用 dhash 算法进行相似对匹配,遍历文件夹里面的图片,相似度最高的就拼上去


对拼图排序,大概半个小时可以计算出来


import cv2

import numpy as np

import os

from match import d_score

import pickle

path = 'picture'

dirs = os.listdir(path)

sort_imgs=[]

original_img_len=2160

imgs=[]

match_list=[]

original_img=cv2.imread("demo.jpg")



print(original_img.shape)



for file in dirs:

    img=cv2.imread('picture/'+file)

    imgs.append(img)



print("ok")

leng = 27

high = 51



current_len=0

current_high=0

imgg=img = np.zeros((27,51,3), np.uint8)

for kkk in range(len(imgs)):

    match_list.clear()

    for i in range(len(imgs)):

        img = imgs[i]

        img2=original_img[current_len:current_len+leng,current_high:current_high+high]

        rate=d_score(img,img2)

        match_list.append(rate)



    current_len = current_len + leng

    if (current_len == original_img_len):

        current_len = 0

        current_high = current_high + 51



    max=0

    max_id=0

    for i in range(len(match_list)):

        if (match_list[i]>=max):

            max=match_list[i]

            max_id=i

    print(dirs[max_id],max,len(match_list))

    sort_imgs.append(dirs[max_id])

    del imgs[max_id]

    del dirs[max_id]


print(sort_imgs)

obj=open("list","wb")

pickle.dump(sort_imgs,obj)

import cv2

import numpy as np

from PIL import Image

from io import BytesIO

import matplotlib


matplotlib.use('TkAgg')

import matplotlib.pyplot as plt


def aHash(img):

    # 均值哈希算法

    # 缩放为8*8

    img = cv2.resize(img, (88))

    # 转换为灰度图

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # s为像素和初值为0,hash_str为hash值初值为''

    s = 0

    hash_str = ''

    # 遍历累加求像素和

    for i in range(8):

        for j in range(8):

            s = s + gray[i, j]

    # 求平均灰度

    avg = s / 64

    # 灰度大于平均值为1相反为0生成图片的hash值

    for i in range(8):

        for j in range(8):

            if gray[i, j] > avg:

                hash_str = hash_str + '1'

            else:

                hash_str = hash_str + '0'

    return hash_str

def dHash(img):

    # 差值哈希算法

    # 缩放8*8

    img = cv2.resize(img, (98))

    # 转换灰度图

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    hash_str = ''

    # 每行前一个像素大于后一个像素为1,相反为0,生成哈希

    for i in range(8):

        for j in range(8):

            if gray[i, j] > gray[i, j + 1]:

                hash_str = hash_str + '1'

            else:

                hash_str = hash_str + '0'

    return hash_str

def pHash(img):

    # 感知哈希算法

    # 缩放32*32

    img = cv2.resize(img, (3232))  # , interpolation=cv2.INTER_CUBIC



    # 转换为灰度图

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 将灰度图转为浮点型,再进行dct变换

    dct = cv2.dct(np.float32(gray))

    # opencv实现的掩码操作

    dct_roi = dct[0:80:8]



    hash = []

    avreage = np.mean(dct_roi)

    for i in range(dct_roi.shape[0]):

        for j in range(dct_roi.shape[1]):

            if dct_roi[i, j] > avreage:

                hash.append(1)

            else:

                hash.append(0)

    return hash


def calculate(image1, image2):

    # 灰度直方图算法

    # 计算单通道的直方图的相似值

    hist1 = cv2.calcHist([image1], [0], None, [256], [0.0255.0])

    hist2 = cv2.calcHist([image2], [0], None, [256], [0.0255.0])

    # 计算直方图的重合度

    degree = 0

    for i in range(len(hist1)):

        if hist1[i] != hist2[i]:

            degree = degree + 

                     (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))

        else:

            degree = degree + 1

    degree = degree / len(hist1)

    return degree


def classify_hist_with_split(image1, image2, size=(256256)):

    # RGB每个通道的直方图相似度

    # 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值

    image1 = cv2.resize(image1, size)

    image2 = cv2.resize(image2, size)

    sub_image1 = cv2.split(image1)

    sub_image2 = cv2.split(image2)

    sub_data = 0

    for im1, im2 in zip(sub_image1, sub_image2):

        sub_data += calculate(im1, im2)

    sub_data = sub_data / 3

    return sub_data


def cmpHash(hash1, hash2):

    # Hash值对比

    # 算法中1和0顺序组合起来的即是图片的指纹hash。顺序不固定,但是比较的时候必须是相同的顺序。

    # 对比两幅图的指纹,计算汉明距离,即两个64位的hash值有多少是不一样的,不同的位数越小,图片越相似

    # 汉明距离:一组二进制数据变成另一组数据所需要的步骤,可以衡量两图的差异,汉明距离越小,则相似度越高。汉明距离为0,即两张图片完全一样

    n = 0

    # hash长度不同则返回-1代表传参出错

    if len(hash1) != len(hash2):

        return -1

    # 遍历判断

    for i in range(len(hash1)):

        # 不相等则n计数+1,n最终为相似度

        if hash1[i] != hash2[i]:

            n = n + 1

    return n


def getImageByUrl(url):

    # 根据图片url 获取图片对象

    html = requests.get(url, verify=False)

    image = Image.open(BytesIO(html.content))

    return image


def PILImageToCV():

    # PIL Image转换成OpenCV格式

    path = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"

    img = Image.open(path)

    plt.subplot(121)

    plt.imshow(img)

    print(isinstance(img, np.ndarray))

    img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

    print(isinstance(img, np.ndarray))

    plt.subplot(122)

    plt.imshow(img)

    plt.show()


def CVImageToPIL():

    # OpenCV图片转换为PIL image

    path = "/Users/waldenz/Documents/Work/doc/TestImages/t3.png"

    img = cv2.imread(path)

    # cv2.imshow("OpenCV",img)

    plt.subplot(121)

    plt.imshow(img)



    img2 = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

    plt.subplot(122)

    plt.imshow(img2)

    plt.show()


def bytes_to_cvimage(filebytes):

    # 图片字节流转换为cv image

    image = Image.open(filebytes)

    img = cv2.cvtColor(np.asarray(image), cv2.COLOR_RGB2BGR)

    return img



def hammingDist(s1, s2):

    assert len(s1) == len(s2)

    return sum([ch1 != ch2 for ch1, ch2 in zip(s1, s2)])



def d_score(img1,img2):

    dhash_str1 = dHash(img1)

    dhash_str2 = dHash(img2)

    d_scores = 1 - hammingDist(dhash_str1, dhash_str2) * 1. / (32 * 32 / 4)

    return d_scores



def runAllImageSimilaryFun(img1, img2):

    n4 = classify_hist_with_split(img1, img2)

    print('三直方图算法相似度:', n4)

2. 按照排序的结果将图片拼接起来

DDCTF2020官方Write Up——MISC 篇

最后 flag 就出来了


02

Decrypt

团队昵称:Decrypt

一血用时:2小时30分


出题人视角

本题密码学,本意是考察差分攻击方法。

解题方法一:

本题秘钥有5个参数,key=[k0,k1,k2,k3,k4], 因rol7(b^k4)^k3 = rol7(b)^rol7(k4)^k3=rol7(b)^k34, 那么可以去掉一个参数,key=[k0,k1,k2,k34]


将 y=ror7(sbox0[sbox1[sbox0[x^k0]^k1]^k2]^k34) 转化为5步

A = x ^ k0

B = sbox0(A)^k1

C = sbox1(B)^k2

D = sbox0(C)^k34

E = ror7(D)


可以用题目中提示中的两个结果对进行分析         

2684 encrypts to 2568

3599 encrypts to 3185


建立差分矩阵链条,[x1^x2,A1^A2,B1^B2,C1^C2,D1^D2,E1^E2] , 现在我们已知两个输入(x1=2684,x2=3599),和两个输出

(E1=2568,E2=3185), 其原理是找到其中最有可能的差分链,从而求解秘钥


A1^A2 = (k0 ^ x1) ^ (k0 ^ x2) = x1^x2    

 (注:两个相同的值异或可以抵消)

      =  2684 ^ 3599 = 1139


B1^B2 = sbox0(A1)^k1 ^ sbox0(A2)^k1 = sbox0(A1)^sbox0(A2)


建立sbox0的差分表

for A1 in xrange(MAX_VALUE):

    for A2 in xrange(x1,MAX_VALUE):

        B1^B2 = cipher.sbox0[A1]^cipher.sbox0[A2]

        print A1,A2,A1^A2,B1^B2


由于A1^A2 = 1139, 计算B1^B2最大的概率, 结果为2891 

awk '{if($3==1139) print $4}' sbox0|sort | uniq -c | sort -nr | more


同理,C1^C2 = sbox1(B1)^sbox1(B2), 当B1^B2为2891时,计算C1^C2的最大概率为1915

D1^D2 = sbox0(C1)^sbox0(C2) , 复用sbox0差分表, D1^D2 最大概率为3251


E1^E2 = ror7(D1)^ror7(D2)=ror7(D1^D2)=ror7(3251)= 1657


计算 E1^E2 = 2568^3185 = 1657 与前推算相同,说明选择的差分链路正确


即 [x1^x2,A1^A2,B1^B2,C1^C2,D1^D2,E1^E2] = [1139,1139,2891,1915,3251,1657]


看sbox0差分表,A1,A2,A1^A2,B1^B2,

当确定A1^A2=1139,B1^B2=2891时,则A1,A2的可能选择的值就不多了,

列举如下

A = [138,1273,183,1220,516,1655,925,2030,943,2012,981,1958,2188,3327]

同理,所有B的可能性为

B = [29,2902,173,3046,239,2980,1285,3662,1397,3646,1571,3432,1621,3358]

C = [2,1913,318,1605,518,1405,918,1261,982,1197,2150,3869,2441,3826]

D = [比较多,有2048个]


A = x^k0, 则k0 = A^x 的可能性为: 

k0 = [2806, 3717, 2763, 3768, 2168, 3083, 2529, 3474, 2515, 3488, 2473, 3546, 752, 1667]

k1 = sbox0(A)^B

k2 = sbox1(B)^C

k34 = sbox0(C)^D


然后从给定的明密文对中随便找几个验证下k是否正确,就可以求解出正确的密文 key = [3488,2863,726,1886]


解题方法二:

在同学们提交的writeup中, ddmmhm队的解法较好,get到了本题的思路是差分攻击+暴力破解,通过cipherdiff设计,把算法复杂度降到4096^2。

补充了下推导过程如下:

y = ror7(sbox0[sbox1[sbox0[x^k0]^k1]^k2] ^k3)



y1^y2 = ror7(sbox0[sbox1[sbox0[x1^k0]^k1]^k2] ^k3) ^ ror7(sbox0[sbox1[sbox0[x2^k0]^k1]^k2] ^k3)

      = ror7(sbox0[sbox1[sbox0[x1^k0]^k1]^k2] ^ sbox0[sbox1[sbox0[x2^k0]^k1]^k2])



rol7(y1^y2) = sbox0[sbox1[sbox0[x1^k0]^k1]^k2] ^ sbox0[sbox1[sbox0[x2^k0]^k1]^k2]



令 Mx = sbox1[sbox0[x1^k0]^k1]  => rol7(y1^y2) = sbox0[Mx1] ^ sbox0[Mx2]

令  My = sbox0(Mx) => Mx  = rsbox0(My)

则 My1^ My2 = sbox0(Mx1) ^ sbox0(Mx2) = rol7(y1^y2)



Mx1^Mx2  = rsbox0(My1) ^ rsbox0(My2) = rsbox0(My1) ^ rsbox0(rol7(y1^y2) ^ My1)


脚本如下:

NUM_BITS = 12

BLOCK_SIZE_BITS = 48

BLOCK_SIZE = BLOCK_SIZE_BITS / 8

MAX_VALUE = (2 << (NUM_BITS - 1))

BIT_MASK = MAX_VALUE - 1



def ror7(b):

    return ((((b) & BIT_MASK) >> 7) | (((b) << (NUM_BITS - 7)) & BIT_MASK))

def rol7(b):

    return ((((b) << 7) & BIT_MASK) | (((b) & BIT_MASK) >> (NUM_BITS - 7)))


k = [(1943307), (8002489), (39482361), (39412168), (20802160), (11211001), (138073), (1897934), (21692845), (17663036), (1396415), (1042240), (16701214), (0326), (3642896), (1590993), (633361), (1655990), (18942759), (17991793), (873258), (15912209), (15592214), (5192269), (16543808), (13941260), (609790), (17982503), (18423884), (1079567), (11353421), (1862300)]

_rand_start = 0

def my_rand():

    global _rand_start

    if _rand_start == 0:

        _rand_start = 123459876

    hi = _rand_start / 127773

    lo = _rand_start % 127773

    x = 16807 * lo - 2836 * hi

    if x < 0:

        x += 0x7fffffff

    _rand_start = (x % (0x7fffffff + 1))

    return _rand_start

def generate_boxes(seed):

    global _rand_start

    _rand_start = seed

    sbox = range(MAX_VALUE)

    rsbox = range(MAX_VALUE)

    for i in range(MAX_VALUE):

        r = my_rand() % MAX_VALUE

        temp = sbox[i]

        sbox[i] = sbox[r]

        sbox[r] = temp

    for i in range(MAX_VALUE):

        rsbox[sbox[i]] = i

    return sbox, rsbox

sbox0, rsbox0 = generate_boxes(106)

sbox1, rsbox1 = generate_boxes(81)

SECRET_KEY = [3488286300]


# k5 = rol(k4) ^ k3

def extract(n):

    global SECRET_KEY

    for i in range(4):

        SECRET_KEY[i] = n % (2 ** 12)

        n /= (2 ** 12)

def encrypt_bits(b, SECRET_KEY):

    t = sbox0[(b & BIT_MASK) ^ SECRET_KEY[0]] ^ SECRET_KEY[1]

    boxed = sbox0[sbox1[ t ] ^ SECRET_KEY[2]]

    return ror7(boxed ^ SECRET_KEY[3] ) & BIT_MASK


def decrypt_bits(b):

    unboxed = rol7((b & BIT_MASK)) ^ SECRET_KEY[3]

    t = rsbox1[  rsbox0[unboxed] ^ SECRET_KEY[2]  ] ^ SECRET_KEY[1]

    return (rsbox0[  t  ] ^ SECRET_KEY[0])


pair = [(1943307), (8002489), (39482361), (39412168), (20802160), (11211001), (138073), (1897934), (21692845), (17663036), (1396415), (1042240), (16701214), (0326), (3642896), (1590993), (633361), (1655990), (18942759), (17991793), (873258), (15912209), (15592214), (5192269), (16543808), (13941260), (609790), (17982503), (18423884), (1079567), (26842568), (11353421), (1862300), (35993185)]


def fun1(diff, box):

    res = {}

    for i in range(2 ** 12):

        res[box[i] ^ box[i ^ diff]] = i

    return res

cipherdiff = []

for i in pair[1:]:

    cipherdiff.append(fun1(rol7(pair[0][1] ^ i[1]), rsbox0))

import multiprocessing

def run(start):

    print(start)

    for key0 in range(start, start+256):

        for key1 in range(2 ** 12):

            mid = [sbox1[sbox0[(i[0]) ^ key0] ^ key1] for i in pair]

            for i in range(1, len(mid)):

                if not mid[0] ^ mid[i] in cipherdiff[i - 1]:

                    break

            else:

                print (key0, key1)

def run1(start):

    print(start)

    for key2 in range(start, start+256):

        for key3 in range(2 ** 12):

            SECRET_KEY = [34882863, key2, key3]

            for i in pair:

                if encrypt_bits(i[0], SECRET_KEY) != i[1]:

                    break

            else:

                print (key2, key3)

                return


for i in range(16):

    # multiprocessing.Process(target=run, args=(i * 256,)).start()

    multiprocessing.Process(target=run1, args=(i * 256,)).start()


-----选手Write Up-----

很容易看出,bits_list_to_string和string_to_bits_list互为逆运算,将每3bytes和非负整数相互转换,核心加密函数为encrypt_bits,是GF(212)上的可逆函数。

具体的加密过程可以表示如下:

DDCTF2020官方Write Up——MISC 篇

对于给定密钥,输入和输出一一对应。而我们有一组明文和密文对照,可以以此爆破密钥,时间复杂度为40965≈1018;考虑中间相遇攻击,时间复杂度为40963≈1011。进一步观察,对于解密第一步操作rol7(b ^ k4) ^ k3 = rol7(b) ^ rol7(k4) ^ k3,而rol7(k4) ^ k3仍属于GF(212),因此可以将时间复杂度降至40962≈107,该时间代价较小,可以利用普通电脑破解。经测试,使用32核cpu服务器不到10分钟可以使用python得出结果。

注:若不进行最后一步化简,将产生多解,虽然也能正确解密,但对算法的理解不够深入。

解题步骤:

1、使用string_to_bits_list将明文和密文分别转换成数组;

2、爆破密钥,分别将前两步加密结果和后两步解密结果存储至不同集合(本代码中使用字典和bits_list_to_string方便存储);

3、求两个集合交集,计算相应密钥并解密。

解题脚本:

NUM_BITS = 12

BLOCK_SIZE_BITS = 48

BLOCK_SIZE = BLOCK_SIZE_BITS // 8

MAX_VALUE = (2 << (NUM_BITS - 1))

BIT_MASK = MAX_VALUE - 1



class Cipher(object):

    def __init__(self, k0, k1, k2, k3, k4):

        self.k0 = k0

        self.k1 = k1

        self.k2 = k2

        self.k3 = k3

        self.k4 = k4



        self._rand_start = 0

        self.sbox0, self.rsbox0 = self.generate_boxes(106)

        self.sbox1, self.rsbox1 = self.generate_boxes(81)


    def my_srand(self, seed):

        self._rand_start = seed


    def my_rand(self):

        if self._rand_start == 0:

            self._rand_start = 123459876

        hi = self._rand_start // 127773

        lo = self._rand_start % 127773

        x = 16807 * lo - 2836 * hi

        if x < 0:

            x += 0x7fffffff

        self._rand_start = (x % (0x7fffffff + 1))

        return self._rand_start



    def generate_boxes(self, seed):

        self.my_srand(seed)

        sbox = list(range(MAX_VALUE))

        rsbox = list(range(MAX_VALUE))


        for i in range(MAX_VALUE):

            r = self.my_rand() % MAX_VALUE

            temp = sbox[i]

            sbox[i] = sbox[r]

            sbox[r] = temp


        for i in range(MAX_VALUE):

            rsbox[sbox[i]] = i


        return sbox, rsbox


    def ror7(self, b):

        return ((((b) & BIT_MASK) >> 7) | (((b) << (NUM_BITS - 7)) & BIT_MASK))


    def rol7(self, b):

        return ((((b) << 7) & BIT_MASK) | (((b) & BIT_MASK) >> (NUM_BITS - 7)))



    def pad_string(self, s):

        num_blocks = len(s) // BLOCK_SIZE

        num_remainder = len(s) % BLOCK_SIZE



        pad = (BLOCK_SIZE - num_remainder) % BLOCK_SIZE

        s += bytes([pad]*(BLOCK_SIZE - num_remainder))

        return s


    def unpad_string(self, s):

        pad = s[-1] & 0xff

        if pad == 0 or pad > BLOCK_SIZE:

            pad = BLOCK_SIZE

        return s[:-pad]


    def string_to_bits_list(self, s):

        input_chars = s

        num_blocks = len(s) // BLOCK_SIZE



        bits_list = []

        for i in range(num_blocks):

            block = 0

            for j in range(BLOCK_SIZE):

                block = block << 8

                block = block | input_chars[i * BLOCK_SIZE + j]

            for j in range(BLOCK_SIZE_BITS, 0, -NUM_BITS):

                bits_list.append((block >> (j - NUM_BITS)) & BIT_MASK)

        return bits_list



    def bits_list_to_string(self, input_bits):

        num_input_bits_per_block = BLOCK_SIZE_BITS // NUM_BITS;

        output_chars = []

        for i in range(0, len(input_bits), num_input_bits_per_block):

            block = 0

            for j in range(num_input_bits_per_block):

                block = block << NUM_BITS

                block = block | (input_bits[i+j])

            for j in range(BLOCK_SIZE, 0-1):

                output_chars.append((block >> ((j-1) * 8)) & 0xff)

        return bytes(output_chars)



    def encrypt_bits(self, b):

        boxed = self.sbox0[self.sbox1[self.sbox0[(b & BIT_MASK) ^ self.k0] ^ self.k1] ^ self.k2] ^ self.k3

        return (self.ror7(boxed) ^ self.k4) & BIT_MASK;



    def decrypt_bits(self, b):

        unboxed = self.rol7((b & BIT_MASK) ^ self.k4) ^ self.k3

        return (self.rsbox0[self.rsbox1[self.rsbox0[unboxed] ^ self.k2] ^ self.k1] ^ self.k0);



    def encrypt(self, s):

        pad_s = self.pad_string(s)

        bits = self.string_to_bits_list(pad_s)

        return self.bits_list_to_string([(self.encrypt_bits(b)) for b in bits])



    def decrypt(self, s):

        bits = self.string_to_bits_list(s)

        dec = [self.decrypt_bits(b) for b in bits]

        return self.unpad_string(self.bits_list_to_string(dec))



#find the right SECRET_KEYS

SECRET_KEYS = [0,0,0,0,0]

cipher = Cipher(*SECRET_KEYS)

test_text = b"Cryptanalysis has coevolved together with cryptography"

test_text=cipher.string_to_bits_list(test_text)

ciphertext = bytes.fromhex("2371697013e9bdcb50133102f2c8c08a69b93e1878ac7939ac70498ddd5dee019f4be4ec8dd3a612c8708a1169701d5d3de3169c7b1d146146146146")

ciphertext=cipher.string_to_bits_list(ciphertext)



import tqdm



"""

rol7(b ^ k4) ^ k3 = rol7(b) ^ rol7(k4) ^ k3 = rol7(b) ^ k3k4

"""


k0_k1_dict={}

i=0

t=tqdm.tqdm(total=MAX_VALUE**2,ascii=True)

for k0 in range(MAX_VALUE):

    for k1 in range(MAX_VALUE):

        ts=[]

        for b in test_text[:12]:

            ts.append(cipher.sbox1[cipher.sbox0[b ^ k0] ^ k1])

        k0_k1_dict[cipher.bits_list_to_string(ts)]=i

        t.update()

        i+=1

t.close()



k2_k3k4_dict={}

i=0

t=tqdm.tqdm(total=MAX_VALUE**2,ascii=True)

for k2 in range(MAX_VALUE):

    for k3k4 in range(MAX_VALUE):

        ts=[]

        for b in ciphertext[:12]:

            ts.append(cipher.rsbox0[cipher.rol7(b) ^ k3k4] ^ k2)

        k2_k3k4_dict[cipher.bits_list_to_string(ts)]=i

        t.update()

        i+=1

t.close()



for key in k0_k1_dict.keys():

    if key in k2_k3k4_dict:

        i=k0_k1_dict[key]

        j=k2_k3k4_dict[key]

        k0=i//MAX_VALUE

        k1=i%MAX_VALUE

        k2=j//MAX_VALUE

        k3k4=j%MAX_VALUE

        break



message=[]

enc=bytes.fromhex("8ed251b18692697c0f57513c697f09ae4425eacd92a7982edcf9581fa8019e6dcb5753e96972fdf01dcf")

for c in cipher.string_to_bits_list(enc):

    message.append(cipher.rsbox0[cipher.rsbox1[cipher.rsbox0[cipher.rol7(c) ^ k3k4] ^ k2] ^ k1] ^ k0)

flag=cipher.unpad_string(cipher.bits_list_to_string(message)).decode()

print(flag)

FLAG值:

DDCTF{69f15862699b70d7c1084eca5f214a60}


本文始发于微信公众号(滴滴安全应急响应中心):DDCTF2020官方Write Up——MISC 篇

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: