前两天有别的比赛,没怎么打这场,第二天晚上才 开始重点做。第三天晚上九点疯狂上分,攒了三天的flag倾泻而出,得分趋势变成了竖线。队友们TQL~

image-20201226235702989

image-20201227000038023

reverse

签到

ida直接找到flag

zzzz3333333

38*38的矩阵,正则提取系数,然后matlab解。

提取系数:

code = '''int __cdecl sub_401500(char *a1)
{
  int result; // eax

  if ( 48 * a1[7]
     + 64 * a1[5]
     + 4 * a1[4]
     + 59 * a1[1]
     + 85 * *a1
     + 76 * a1[2]
     + 65 * a1[3]
     + 50 * a1[6]
     + 11 * a1[8]
     + 66 * a1[9] != 44858 )
    return 0;
  if ( 96 * a1[7]
     + 6 * a1[6]
     + 97 * a1[4]
     + 71 * a1[1]
     + 87 * *a1
     + 26 * a1[2]
     + 80 * a1[3]
     + 100 * a1[5]
     + 20 * a1[8]
     + 46 * a1[9] != 54177 )
    return 0;
  if ( 82 * a1[8]
     + 29 * a1[7]
     + 54 * a1[4]
     + 22 * a1[1]
     + 27 * *a1
     + 92 * a1[2]
     + 9 * a1[3]
     + 35 * a1[5]
     + 36 * a1[6]
     + 90 * a1[9] != 40412 )
    return 0;
  if ( 60 * a1[7]
     + 31 * a1[5]
     + 47 * *a1
     + 32 * a1[1]
     + 55 * a1[2]
     + 17 * a1[3]
     + 70 * a1[4]
     + 10 * a1[6]
     + 34 * a1[8]
     + 25 * a1[9] != 32362 )
    return 0;
  if ( 53 * a1[7]
     + 89 * a1[6]
     + 13 * a1[4]
     + 72 * a1[3]
     + 49 * a1[1]
     + 18 * *a1
     + 61 * a1[2]
     + 3 * a1[5]
     + 67 * a1[8]
     + 15 * a1[9] != 37176 )
    return 0;
  if ( 78 * a1[8]
     + 38 * a1[5]
     + 69 * a1[2]
     + 77 * *a1
     + 16 * a1[1]
     + 99 * a1[3]
     + 33 * a1[4]
     + 8 * a1[6]
     + 5 * a1[7]
     + 91 * a1[9] != 42742 )
    return 0;
  if ( 62 * a1[8]
     + 52 * a1[7]
     + 58 * a1[2]
     + 45 * a1[1]
     + 40 * *a1
     + 51 * a1[3]
     + 24 * a1[4]
     + 95 * a1[5]
     + 19 * a1[6]
     + 94 * a1[9] != 47553 )
    return 0;
  if ( 28 * a1[8]
     + 63 * a1[7]
     + 12 * a1[6]
     + 57 * a1[4]
     + 30 * a1[3]
     + 42 * a1[2]
     + a1[1]
     + 88 * *a1
     + 83 * a1[5]
     + 73 * a1[9] != 41059 )
    return 0;
  if ( 41 * a1[8]
     + 93 * a1[6]
     + 68 * a1[5]
     + 98 * a1[2]
     + 75 * a1[1]
     + 39 * *a1
     + 86 * a1[3]
     + 14 * a1[4]
     + 23 * a1[7]
     + 7 * a1[9] != 43919 )
    return 0;
  if ( 56 * a1[8] + 74 * a1[5] + 43 * a1[4] + 84 * a1[3] + 44 * a1[2] + 37 * *a1 + 81 * a1[1] + 2 * a1[6] + 21 * a1[9] != 35933 )
    return 0;
  if ( 36 * a1[16]
     + 98 * a1[14]
     + 79 * a1[10]
     + 97 * a1[11]
     + 33 * a1[12]
     + 60 * a1[15]
     + 24 * a1[17]
     + 78 * a1[18]
     + 72 * a1[19] != 47783 )
    return 0;
  if ( 74 * a1[17]
     + 39 * a1[16]
     + 51 * a1[15]
     + 8 * a1[14]
     + 77 * a1[13]
     + 69 * a1[12]
     + 16 * a1[11]
     + 73 * a1[10]
     + 64 * a1[18]
     + 28 * a1[19] != 44266 )
    return 0;
  if ( 47 * a1[18]
     + 52 * a1[17]
     + 53 * a1[16]
     + 99 * a1[15]
     + a1[14]
     + 38 * a1[13]
     + 67 * a1[12]
     + 45 * a1[11]
     + 61 * a1[10]
     + 66 * a1[19] != 44988 )
    return 0;
  if ( 5 * a1[17]
     + 4 * a1[13]
     + 89 * a1[12]
     + 31 * a1[10]
     + 11 * a1[11]
     + 93 * a1[14]
     + 3 * a1[15]
     + 84 * a1[16]
     + 65 * a1[18]
     + 100 * a1[19] != 46698 )
    return 0;
  if ( 82 * a1[16]
     + 62 * a1[13]
     + 58 * a1[12]
     + 42 * a1[11]
     + 86 * a1[10]
     + 85 * a1[14]
     + 27 * a1[15]
     + 43 * a1[17]
     + 15 * a1[18]
     + 26 * a1[19] != 45689 )
    return 0;
  if ( 22 * a1[16]
     + 34 * a1[13]
     + 2 * a1[12]
     + 23 * a1[11]
     + 46 * a1[10]
     + 29 * a1[14]
     + 48 * a1[15]
     + 35 * a1[17]
     + 19 * a1[18]
     + 70 * a1[19] != 27224 )
    return 0;
  if ( 96 * a1[18]
     + 81 * a1[17]
     + 92 * a1[15]
     + 54 * a1[14]
     + 94 * a1[11]
     + 57 * a1[10]
     + 55 * a1[12]
     + 80 * a1[13]
     + 71 * a1[16]
     + 25 * a1[19] != 58395 )
    return 0;
  if ( 13 * a1[17]
     + 75 * a1[13]
     + 21 * a1[11]
     + 59 * a1[10]
     + 56 * a1[12]
     + 50 * a1[14]
     + 41 * a1[15]
     + 44 * a1[16]
     + 40 * a1[18]
     + 49 * a1[19] != 40625 )
    return 0;
  if ( 12 * a1[16]
     + 91 * a1[14]
     + 88 * a1[13]
     + 87 * a1[12]
     + 68 * a1[10]
     + 7 * a1[11]
     + 83 * a1[15]
     + 20 * a1[17]
     + 32 * a1[18]
     + 37 * a1[19] != 45008 )
    return 0;
  if ( 10 * a1[17]
     + 18 * a1[16]
     + 9 * a1[15]
     + 6 * a1[14]
     + 76 * a1[10]
     + 14 * a1[11]
     + 17 * a1[12]
     + 90 * a1[13]
     + 63 * a1[18]
     + 30 * a1[19] != 32400 )
    return 0;
  if ( 83 * a1[26]
     + 45 * a1[25]
     + 4 * a1[24]
     + 48 * a1[22]
     + 38 * a1[20]
     + 22 * a1[21]
     + 7 * a1[23]
     + 62 * a1[27]
     + 25 * a1[28]
     + 85 * a1[29] != 37450 )
    return 0;
  if ( 14 * a1[28]
     + 86 * a1[26]
     + 93 * a1[25]
     + 42 * a1[24]
     + 94 * a1[21]
     + 70 * a1[20]
     + 58 * a1[22]
     + 40 * a1[23]
     + 76 * a1[27]
     + 11 * a1[29] != 48740 )
    return 0;
  if ( 72 * a1[28]
     + 46 * a1[26]
     + 92 * a1[25]
     + 98 * a1[24]
     + 55 * a1[23]
     + 80 * a1[20]
     + 32 * a1[21]
     + 12 * a1[22]
     + 84 * a1[27]
     + 27 * a1[29] != 53599 )
    return 0;
  if ( 53 * a1[27]
     + 49 * a1[23]
     + 99 * a1[22]
     + 41 * a1[20]
     + 20 * a1[21]
     + 87 * a1[25]
     + 81 * a1[26]
     + 71 * a1[28]
     + 73 * a1[29] != 52140 )
    return 0;
  if ( 68 * a1[28]
     + 61 * a1[21]
     + 28 * a1[20]
     + 91 * a1[22]
     + 31 * a1[23]
     + 67 * a1[24]
     + 15 * a1[25]
     + 44 * a1[26]
     + 6 * a1[27]
     + 64 * a1[29] != 44449 )
    return 0;
  if ( 9 * a1[27]
     + 60 * a1[25]
     + 96 * a1[23]
     + 17 * a1[20]
     + 10 * a1[21]
     + 29 * a1[22]
     + 5 * a1[24]
     + 100 * a1[26]
     + 21 * a1[28]
     + 69 * a1[29] != 35276 )
    return 0;
  if ( 59 * a1[26]
     + 66 * a1[25]
     + 23 * a1[22]
     + 8 * a1[20] 
     + 24 * a1[21]
     + 16 * a1[23]
     + 56 * a1[24]
     + 90 * a1[27]
     + 36 * a1[28]
     + 39 * a1[29] != 35577 )
    return 0;
  if ( 35 * a1[25]
     + 65 * a1[23]
     + 63 * a1[22]
     + 75 * a1[20]
     + 88 * a1[21]
     + 33 * a1[24]
     + 82 * a1[26]
     + 18 * a1[27]
     + a1[28]
     + 37 * a1[29] != 42004 )
    return 0;
  if ( 54 * a1[28]
     + 57 * a1[27]
     + 43 * a1[24]
     + 74 * a1[21]
     + 19 * a1[20]
     + 51 * a1[22]
     + 13 * a1[23]
     + 79 * a1[25]
     + 3 * a1[26]
     + 26 * a1[29] != 35802 )
    return 0;
  if ( 34 * a1[28]
     + 50 * a1[27]
     + 78 * a1[26]
     + 52 * a1[25]
     + 77 * a1[24]
     + 95 * a1[23]
     + 30 * a1[22]
     + 89 * a1[20]
     + 2 * a1[21]
     + 97 * a1[29] != 54527 )
    return 0;
  if ( 46 * a1[36] + 73 * a1[34] + 15 * a1[30] + 16 * a1[31] + 41 * a1[32] + 94 * a1[33] + 28 * a1[35] + 45 * a1[37] != 34469 )
    return 0;
  if ( 82 * a1[36] + 10 * a1[32] + 48 * a1[31] + 65 * a1[30] + 6 * a1[33] + 30 * a1[34] + 27 * a1[35] + 32 * a1[37] != 31558 )
    return 0;
  if ( 62 * a1[36] + 39 * a1[35] + 36 * a1[33] + 97 * a1[31] + 52 * a1[30] + 70 * a1[32] + 13 * a1[34] + 66 * a1[37] != 41820 )
    return 0;
  if ( 44 * a1[34] + 42 * a1[33] + 78 * a1[32] + 83 * a1[31] + 96 * a1[30] + 4 * a1[35] + 9 * a1[36] + 51 * a1[37] != 38668 )
    return 0;
  if ( 79 * a1[36] + 37 * a1[33] + 92 * a1[30] + 18 * a1[31] + 86 * a1[32] + 7 * a1[34] + 95 * a1[37] != 45530 )
    return 0;
  if ( 71 * a1[36] + 43 * a1[35] + 57 * a1[34] + 49 * a1[33] + 88 * a1[32] + 61 * a1[30] + 24 * a1[31] + 91 * a1[37] != 51396 )
    return 0;
  if ( 34 * a1[36] + 75 * a1[35] + 35 * a1[32] + 23 * a1[30] + 3 * a1[31] + 53 * a1[33] + 14 * a1[34] + 47 * a1[37] != 28874 )
    return 0;
  if ( 22 * a1[36] + 84 * a1[35] + 26 * a1[34] + 90 * a1[33] + 99 * a1[30] + 98 * a1[31] + 25 * a1[32] + a1[37] != 38231 )
    return 0;
}'''
code = code.replace('*a1', 'a1[0]')

import re

l = []
right = []
r = re.finditer(r'if.+?;', code, re.S)
for line in r:
    tmp = [0] * 38
    rr = re.finditer(r'(\d+?) \* a1\[(\d+?)\]', line.group())
    for i in rr:
        a, b = int(i.group(1)), int(i.group(2))
        tmp[b] = a
    _rr = re.search(r'\+ a1\[(\d+?)\]', line.group())
    if _rr:
        a, b = 1, int(_rr.group(1))
        tmp[b] = a
    l.append(tmp)

    rrr = re.search(r'!\= (\d+)', line.group())
    right.append(int(rrr.group(1)))


for i in l:
    print(str(i)[1:-1] + ';')

print()

print(str(right).replace(',', ';'))

matlab部分截图:

image-20201227000606741

能用matlab解的最好不要用z3。z3基本靠爆破,matlab解线性方程是直接调用数学公式,不是一个时间复杂度哦。

奇怪的exe

pyinstaller打包的python程序,用pyinstxtractor.py解包,uncomlyle6提取python代码。

源码:

# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: 3.py
# Compiled at: 2020-12-24 10:52:17
# Size of source mod 2**32: 14 bytes
import base64
from binascii import *
c = [35, 101, 131, 114, 38]
enc = [122, 17, 205, 28, 104, 106, 80, 219, 39, 81, 98, 87, 214, 75, 112, 100, 63, 244, 32, 99, 110, 3, 187, 8, 114, 17, 9, 176, 22, 22, 87, 84, 206, 20, 104, 19, 49, 244, 39, 23]
print('please input your flag:')
key = input()
a = base64.b64encode(key.swapcase().encode('utf-8'))
print(a)
print(hexlify(a))
f = 1
s = []
for x in range(3):
    for i in range(len(a)):
        if (i + x) % 3 == 0:
            s.append(a[i])
print(s)
for i in range(len(s)):
    print(enc[i] ^ c[(i % 5)], s[i] )
    if enc[i] != s[i] ^ c[(i % 5)]:
        f = 0
        break

if f == 1:
    print('RIGHT')
else:
    print('WRONG')
# okay decompiling 3.pyc

难度不大,我就不解释了,直接放解题脚本:

c = [ 35, 101, 131, 114, 38]
enc = [122, 17, 205, 28, 104, 106, 80, 219, 39, 81, 98, 87, 214, 75, 112, 100, 63, 244, 32, 99, 110, 3, 187, 8, 114, 17, 9, 176, 22, 22, 87, 84, 206, 20, 104, 19, 49, 244, 39, 23]
for i in range(len(enc)):
    enc[i] ^= c[i%5]
print(enc)
new = [0] * len(enc)
o = 0

for x in range(3):
    for i in range(len(enc)):
        if (i + x) % 3 == 0:
            new[i] = enc[o]
            print(enc[o],end=' ')
            o+=1
    print()
print(new)
b = b''
import struct
for i in range(len(new)):
    b += struct.pack('B', new[i])
print(b)
import base64
r = base64.b64decode(b)
print(r.swapcase())

swapcase()大小写互换有点意思哦。我和炜昊都倒在这里。

ez_code

python字节码。

分析大概是这样的,只是分析的草稿,注释可能有小疏漏哦。

  3           0 LOAD_GLOBAL              0 (print)
              2 LOAD_CONST               1 ('please input your flag:')
              4 CALL_FUNCTION            1
              6 POP_TOP

  4           8 LOAD_GLOBAL              1 (input)
             10 CALL_FUNCTION            0
             12 STORE_FAST               0 (flag)

  5          14 LOAD_GLOBAL              2 (len)
             16 LOAD_FAST                0 (flag)
             18 CALL_FUNCTION            1
             20 LOAD_CONST               2 (36)
             22 COMPARE_OP               3 (!=)                     # len = 36
             24 POP_JUMP_IF_FALSE       30

  6          26 LOAD_CONST               3 (0)
             28 RETURN_VALUE

  7     >>   30 BUILD_LIST               0
             32 STORE_FAST               1 (a)

  8          34 LOAD_CONST               3 (0)
             36 STORE_FAST               2 (t)                      # t = 0

 12          38 LOAD_FAST                0 (flag)
             40 GET_ITER
        >>   42 FOR_ITER                58 (to 102)
             44 STORE_FAST               3 (i)

 13          46 LOAD_FAST                2 (t)
             48 LOAD_CONST               4 (1)
             50 BINARY_AND
             52 LOAD_CONST               4 (1)
             54 COMPARE_OP               2 (==)                     # t & 1 == 1    奇数则跳
             56 POP_JUMP_IF_FALSE       78

 14          58 LOAD_FAST                1 (a)          
             60 LOAD_METHOD              3 (append)
             62 LOAD_GLOBAL              4 (ord)
             64 LOAD_FAST                3 (i)
             66 CALL_FUNCTION            1
             68 LOAD_CONST               5 (128)                    # 偶数则a.append(ord(i)+128)
             70 BINARY_ADD
             72 CALL_METHOD              1
             74 POP_TOP
             76 JUMP_FORWARD            14 (to 92)

 16     >>   78 LOAD_FAST                1 (a)
             80 LOAD_METHOD              3 (append)
             82 LOAD_GLOBAL              4 (ord)
             84 LOAD_FAST                3 (i)
             86 CALL_FUNCTION            1
             88 CALL_METHOD              1                          # 奇数则a.append(ord(i))
             90 POP_TOP

 17     >>   92 LOAD_FAST                2 (t)
             94 LOAD_CONST               4 (1)
             96 INPLACE_ADD
             98 STORE_FAST               2 (t)                      # t+1
            100 JUMP_ABSOLUTE           42                          # 跳回循环开始

 21     >>  102 LOAD_FAST                1 (a)
            104 LOAD_CONST               3 (0)
            106 BINARY_SUBSCR
            108 LOAD_CONST               6 (5)
            110 BINARY_RSHIFT
            112 STORE_FAST               4 (b)                      # a[0] >> 5

 22         114 LOAD_GLOBAL              5 (range)
            116 LOAD_GLOBAL              2 (len)
            118 LOAD_FAST                1 (a)
            120 CALL_FUNCTION            1
            122 CALL_FUNCTION            1
            124 GET_ITER
        >>  126 FOR_ITER                82 (to 210)
            128 STORE_FAST               3 (i)

 23         130 LOAD_FAST                3 (i)
            132 LOAD_GLOBAL              2 (len)
            134 LOAD_FAST                1 (a)
            136 CALL_FUNCTION            1
            138 LOAD_CONST               4 (1)
            140 BINARY_SUBTRACT                                     # len(a) - 1
            142 COMPARE_OP               2 (==)
            144 POP_JUMP_IF_FALSE      172                          # 循环体在172,而146是循环后运行的

 24         146 LOAD_FAST                1 (a)
            148 LOAD_FAST                3 (i)
            150 BINARY_SUBSCR
            152 LOAD_CONST               7 (8)
            154 BINARY_MULTIPLY                                     # a[i] * 8
            156 LOAD_CONST               8 (255)
            158 BINARY_AND                                          # (a[i] * 8) & 0xff
            160 LOAD_FAST                4 (b)
            162 BINARY_OR
            164 LOAD_FAST                1 (a)
            166 LOAD_FAST                3 (i)
            168 STORE_SUBSCR                                        # a[i] = (a[0] >> 5) | ((a[i] << 3) & 0xff)
            170 JUMP_ABSOLUTE          126

 26     >>  172 LOAD_FAST                1 (a)
            174 LOAD_FAST                3 (i)
            176 BINARY_SUBSCR
            178 LOAD_CONST               7 (8)
            180 BINARY_MULTIPLY                                     
            182 LOAD_CONST               8 (255)    
            184 BINARY_AND                                          # (a[i] * 8) & 0xff
            186 LOAD_FAST                1 (a)
            188 LOAD_FAST                3 (i)
            190 LOAD_CONST               4 (1)
            192 BINARY_ADD
            194 BINARY_SUBSCR
            196 LOAD_CONST               6 (5)
            198 BINARY_RSHIFT                                       # a[i+1] >> 5
            200 BINARY_OR
            202 LOAD_FAST                1 (a)
            204 LOAD_FAST                3 (i)
            206 STORE_SUBSCR                                        # a[i] = (a[i+1] >> 5) | ((a[i] << 3) & 0xff)
            208 JUMP_ABSOLUTE          126

 28     >>  210 BUILD_LIST               0
            212 STORE_FAST               5 (num)

 32         214 LOAD_GLOBAL              5 (range)
            216 LOAD_CONST               9 (2)
            218 LOAD_CONST              10 (129)
            220 CALL_FUNCTION            2
            222 GET_ITER
        >>  224 FOR_ITER                60 (to 286)
            226 STORE_FAST               3 (i)                      # for i in range(2, 129)

 33         228 LOAD_CONST              11 (False)
            230 STORE_FAST               2 (t)

 34         232 LOAD_GLOBAL              5 (range)
            234 LOAD_CONST               9 (2)
            236 LOAD_FAST                3 (i)
            238 CALL_FUNCTION            2
            240 GET_ITER
        >>  242 FOR_ITER                26 (to 270)
            244 STORE_FAST               6 (j)

 35         246 LOAD_FAST                3 (i)
            248 LOAD_FAST                6 (j)
            250 BINARY_MODULO
            252 LOAD_CONST               3 (0)
            254 COMPARE_OP               2 (==)                     # i % j == 0
            256 POP_JUMP_IF_FALSE      242

 36         258 LOAD_CONST              12 (True)
            260 STORE_FAST               2 (t)                      # t = True

 37         262 POP_TOP
            264 EXTENDED_ARG             1
            266 JUMP_ABSOLUTE          270
            268 JUMP_ABSOLUTE          242

 38     >>  270 LOAD_FAST                2 (t)
            272 POP_JUMP_IF_TRUE       224                          # not t

 39         274 LOAD_FAST                5 (num)
            276 LOAD_METHOD              3 (append)
            278 LOAD_FAST                3 (i)                      # num.append(i)
            280 CALL_METHOD              1
            282 POP_TOP
            284 JUMP_ABSOLUTE          224

 40     >>  286 LOAD_CONST               3 (0)
            288 BUILD_LIST               1
            290 LOAD_GLOBAL              2 (len)
            292 LOAD_FAST                1 (a)
            294 CALL_FUNCTION            1
            296 BINARY_MULTIPLY
            298 STORE_FAST               7 (c)

 41         300 LOAD_GLOBAL              5 (range)
            302 LOAD_GLOBAL              2 (len)
            304 LOAD_FAST                1 (a)
            306 CALL_FUNCTION            1
            308 CALL_FUNCTION            1
            310 GET_ITER
        >>  312 FOR_ITER                78 (to 392)
            314 STORE_FAST               3 (i)                     # for i in range(len(a))

 42         316 LOAD_FAST                1 (a)
            318 LOAD_FAST                3 (i)
            320 BINARY_SUBSCR
            322 LOAD_CONST              13 (4)
            324 BINARY_RSHIFT                           # a[i] >> 4
            326 LOAD_FAST                5 (num)
            328 LOAD_FAST                3 (i)
            330 LOAD_CONST              14 (31)
            332 BINARY_MODULO
            334 BINARY_SUBSCR                           # num[i % 31]
            336 LOAD_CONST              15 (15)
            338 BINARY_AND                              # num[i % 31] & 0xf                   
            340 BINARY_XOR
            342 STORE_FAST               8 (x1)         # x1 = (a[i] >> 4) ^ (num[i % 31] & 0xf)

 43         344 LOAD_FAST                1 (a)
            346 LOAD_FAST                3 (i)
            348 BINARY_SUBSCR
            350 LOAD_CONST              15 (15)
            352 BINARY_AND                              # a[i] & 0xf
            354 LOAD_FAST                5 (num)
            356 LOAD_FAST                3 (i)
            358 LOAD_CONST              14 (31)
            360 BINARY_MODULO
            362 BINARY_SUBSCR                           # num[i % 31]
            364 LOAD_CONST              13 (4)
            366 BINARY_RSHIFT                           # num[i % 31] >> 4
            368 BINARY_XOR
            370 STORE_FAST               9 (x2)         # x2 = (a[i] & 0xf) ^ (num[i % 31] >> 4)

 44         372 LOAD_FAST                9 (x2)
            374 LOAD_CONST              16 (16)
            376 BINARY_MULTIPLY                         # 16 * x2
            378 LOAD_FAST                8 (x1)
            380 BINARY_ADD                              # 16 * x2 + x1
            382 LOAD_FAST                7 (c)
            384 LOAD_FAST                3 (i)
            386 STORE_SUBSCR                            # c[i] = 16 * x2 + x1
            388 EXTENDED_ARG             1
            390 JUMP_ABSOLUTE          312

 47     >>  392 LOAD_CONST              17 (227)        # 密文
            394 LOAD_CONST              18 (169)
            396 LOAD_CONST              17 (227)
            398 LOAD_CONST              19 (45)
            400 LOAD_CONST              20 (234)
            402 LOAD_CONST              21 (39)
            404 LOAD_CONST              22 (98)
            406 LOAD_CONST              23 (190)
            408 LOAD_CONST              24 (197)
            410 LOAD_CONST              25 (7)
            412 LOAD_CONST              26 (229)
            414 LOAD_CONST              27 (137)
            416 LOAD_CONST              24 (197)
            418 LOAD_CONST              28 (132)
            420 LOAD_CONST              29 (119)
            422 LOAD_CONST              30 (142)
            424 LOAD_CONST              31 (97)
            426 LOAD_CONST              32 (167)
            428 LOAD_CONST              33 (59)
            430 LOAD_CONST              34 (96)
            432 LOAD_CONST              35 (166)
            434 LOAD_CONST              36 (94)
            436 LOAD_CONST              37 (136)
            438 LOAD_CONST              17 (227)
            440 LOAD_CONST              38 (131)
            442 LOAD_CONST              39 (202)
            444 LOAD_CONST              37 (136)
            446 LOAD_CONST              40 (250)
            448 LOAD_CONST              41 (21)
            450 LOAD_CONST              42 (99)
            452 LOAD_CONST              43 (20)
            454 LOAD_CONST              44 (173)
            456 LOAD_CONST              45 (121)
            458 LOAD_CONST              46 (41)
            460 LOAD_CONST              47 (125)
            462 LOAD_CONST              48 (165)
            464 BUILD_LIST              36
            466 STORE_FAST              10 (d)

 48         468 LOAD_CONST               4 (1)
            470 STORE_FAST              11 (e)

 49         472 LOAD_GLOBAL              5 (range)
            474 LOAD_GLOBAL              2 (len)
            476 LOAD_FAST               10 (d)
            478 CALL_FUNCTION            1
            480 CALL_FUNCTION            1
            482 GET_ITER
        >>  484 FOR_ITER                34 (to 520)
            486 STORE_FAST               3 (i)

 50         488 LOAD_FAST               10 (d)
            490 LOAD_FAST                3 (i)
            492 BINARY_SUBSCR
            494 LOAD_FAST                7 (c)
            496 LOAD_FAST                3 (i)
            498 BINARY_SUBSCR
            500 COMPARE_OP               3 (!=)
            502 EXTENDED_ARG             1
            504 POP_JUMP_IF_FALSE      484

 51         506 LOAD_CONST               3 (0)
            508 STORE_FAST              11 (e)

 52         510 POP_TOP
            512 EXTENDED_ARG             2
            514 JUMP_ABSOLUTE          520
            516 EXTENDED_ARG             1
            518 JUMP_ABSOLUTE          484

 53     >>  520 LOAD_FAST               11 (e)
            522 LOAD_CONST               4 (1)
            524 COMPARE_OP               2 (==)
            526 EXTENDED_ARG             2
            528 POP_JUMP_IF_FALSE      540

 54         530 LOAD_GLOBAL              0 (print)
            532 LOAD_CONST              49 ('YOU ARE RIGHT')
            534 CALL_FUNCTION            1
            536 POP_TOP
            538 JUMP_FORWARD             8 (to 548)

 56     >>  540 LOAD_GLOBAL              0 (print)
            542 LOAD_CONST              50 ('WRONG')
            544 CALL_FUNCTION            1
            546 POP_TOP
        >>  548 LOAD_CONST               0 (None)
            550 RETURN_VALUE

手写其逻辑:

flag = input()

if len(flag) != 36:
    exit()

t = 0
a = []
for i in flag:
    if t & 1 == 1:
        a.append(ord(i)+128)
    else:
        a.append(ord(i))
    t += 1

a[len(a)-1] = ((a[len(a)-1] << 3) & 0xff) | (a[0] >> 5)
for i in range(len(a)-1):
    a[i] = ((a[i] << 3) & 0xff) | (a[i+1] >> 5)

num = []
for i in range(2, 129):
    t = False
    for j in range(2, i):
        if i % j == 0:
            t = True
    if not t:
        num.append(i)

c = [0] * len(flag)
for i in range(len(a)):
    x1 = (a[i] >> 4) ^ (num[i % 31] & 0xf)
    x2 = (a[i] & 0xf) ^ (num[i % 31] >> 4)
    c[i] = (x2 << 4) + x1

d=[227, 169, 227, 45, 234, 39, 98, 190, 197, 7, 229, 137, 197, 132, 119, 142, 97, 167, 59, 96, 166, 94, 136, 227, 131, 202, 136, 250, 21, 99, 20, 173, 121, 41, 125, 165]
for i in range(len(d)):
    if d[i] != c[i]:
        print('WRONG')
        exit()
print('YOU ARE RIGHT')

逆向主要是两段,第一段就是简单的左移3右移5。

第二段简单分析下见下图,就是a[i]交换高低4bit后与num[i%31]异或。

0cf3d7ca7bcb0a467b731a657c63f6246b60af1d

逆向脚本:

num=[]
for i in range(2,129):
    t=False
    for j in range(2,i):
        if i%j==0:
            t=True
    if not t:
        num.append(i)
print(len(num))

c=d=[227, 169, 227, 45, 234, 39, 98, 190, 197, 7, 229, 137, 197, 132, 119, 142, 97, 167, 59, 96, 166, 94, 136, 227, 131, 202, 136, 250, 21, 99, 20, 173, 121, 41, 125, 165]
print(c)
a = []
for i in range(len(c)):
    tmp = d[i] ^ num[i % 31]
    tmp = (tmp >> 4) + ((tmp & 0xf) << 4)
    a.append(tmp)

s = ''
for i in range(len(a)):
    s += bin(a[i])[2:].zfill(8)
print(s)
s = s[-3:] + s[:-3]
print(s)
flag = []
for i in range(len(a)):
    tmp = int(s[i*8: i*8+8], 2)
    if i % 2 == 0:
        flag.append(tmp)
    else:
        flag.append(tmp-128)
print(flag)
print(''.join(list(map(chr, flag))))

time

这题很有意思哦。

输入flag前会验证时间,必须在特定的年月日时分秒才能继续。但是还不能简单地patch掉这些验证。因为会把这些参数计算出一个int后传入验证flag的函数,并参与flag验证的逻辑。所以需要计算出这个int,然后patch掉时间验证之后,进入flag验证函数前,手动修改传入的这个参数 55*7*903274960*9*2018*32 = 0xec48d400

image-20201227010317187

这题应该是用了一些C语言没有的函数,伪代码有点奇怪,但没有特别的c++的特征(其实是有点的。不知道怎么编译的。识别不出来这些奇怪的库函数,只能动调慢慢推测。

输入flag后,创建一个flag备份,记作buffer,并通过下面逻辑,将传入的与时间有关的int进行转换,生成0~4的字节,并拼接到buffer的首部。

image-20201227010525135

从int中分出4个byte, &0x7f后如果满足上述逻辑,就添加到buffer的头部。可能添加0~3个字节,这取决于时间参数。对于通过验证的唯一参数0xec48d400,会添加3个字节。

创建一个table,长62,值为0-9a-zA-Z

image-20201227011123392

从buffer(3个时间参数导出的字节+flag)中找到每个字符在table0-9a-zA-Z中首次出现的索引:

image-20201227011411306

然后主要的逻辑在sub_401541。

image-20201227011500106

这次是从flag中找到每个字符在table0-9a-zA-Z中首次出现的索引,然后与上一步的table_from_find_first_index_by_buffer[i]模62相加。

什么意思呢?

一个数组是3个时间参数相关字节+flag,一个”数组“是flag,这两个数组对于元素模62相加,然后作为索引取table0-9a-zA-Z的字符。

所以其实就是个错位相加。

动调到这个函数,拿到这3个时间参数相关字节0x0d, 0x0c, 0x38。然后错位计算。

解密脚本:

import string
from z3 import *

time = 55*7*903274960*9*2018*32
print(hex(time&0xffffffff))

cipher = 'P6GvwFypZN1BbFn5tVgoWeK81LkeQ6uvuiovDgO'
print(len(cipher))
table = string.digits + string.ascii_lowercase + string.ascii_uppercase
print(table)

a = (table.find(cipher[0]) - 0x0d + 62) % 62
b = (table.find(cipher[1]) - 0x0c + 62) % 62
c = (table.find(cipher[2]) - 0x38 + 62) % 62
index = [a, b, c]
print(index)
for i in range(3, len(cipher)):
    tmp = (table.find(cipher[i]) - index[i-3] + 62) % 62
    index.append(tmp)
for i in index[:-3]:
    print(table[i],end='')
print()

baby_encrypt

把flag主体按-分割拆成3部分,分别进入函数验证

image-20201227012124185

三个main都是md5,逐渐魔改递进。

main是原版md5,然后把md5走一些古典算法,然后比较密文。

从密文可以逆回md5。然后可以查彩虹表。

main1算法:

int __cdecl main1(char *part1)
{
  int v1; // eax
  int v2; // eax
  unsigned int k; // eax
  int v5[16]; // [esp+10h] [ebp-D8h]
  char Src[8]; // [esp+50h] [ebp-98h] BYREF
  int md5_ctx[2]; // [esp+58h] [ebp-90h] BYREF
  int ctx_state; // [esp+60h] [ebp-88h] BYREF
  char md5_digest[16]; // [esp+B0h] [ebp-38h] BYREF
  const char *v10; // [esp+C0h] [ebp-28h]
  int tmp; // [esp+C4h] [ebp-24h]
  int low; // [esp+C8h] [ebp-20h]
  int high; // [esp+CCh] [ebp-1Ch]
  int v14; // [esp+D0h] [ebp-18h]
  unsigned int v15; // [esp+D4h] [ebp-14h]
  int j; // [esp+D8h] [ebp-10h]
  int i; // [esp+DCh] [ebp-Ch]

  md5_init(md5_ctx);
  v1 = strlen(part1);
  MD5Update((int)md5_ctx, part1, v1);
  v14 = 0;                                      // 以下是MD5Final
  v15 = ((unsigned int)md5_ctx[0] >> 3) & 0x3F;
  if ( v15 > 0x37 )
    v2 = 120 - v15;
  else
    v2 = 56 - v15;
  v14 = v2;
  MD5Encode((int)Src, (int)md5_ctx, 8u);
  MD5Update((int)md5_ctx, &padding, v14);
  MD5Update((int)md5_ctx, Src, 8);
  MD5Encode((int)md5_digest, (int)&ctx_state, 0x10u);// 以上是MD5Final
  for ( i = 0; i <= 15; ++i )
  {
    high = (unsigned __int8)md5_digest[i] >> 4;
    low = md5_digest[i] & 0xF;
    md5_digest[i] = 16 * low + (high ^ low);
    *((_BYTE *)&v5[8] + 2 * i) = (unsigned __int8)md5_digest[i] >> 4;//  = low, 0~15
    *((_BYTE *)&v5[8] + 2 * i + 1) = md5_digest[i] & 0xF;//  = high ^ low
  }
  for ( i = 0; i <= 31; i += 8 )
  {
    for ( j = 0; j <= 3; ++j )
    {
      tmp = *((char *)&v5[8] + i + j);
      *((_BYTE *)&v5[8] + j + i) = *((_BYTE *)&v5[8] + i + 7 - j);
      *((_BYTE *)&v5[8] + i + 7 - j) = tmp;
    }                                           // 07,16,25,34互换
  }
  for ( k = 0; k < 8; ++k )                     // memset(v5, 0, 8)
    v5[k] = 0;
  for ( i = 0; i <= 31; ++i )
  {
    if ( *((char *)&v5[8] + i) > 9 || *((char *)&v5[8] + i) < 0 )// num2char
    {
      if ( *((char *)&v5[8] + i) > 9 && *((char *)&v5[8] + i) <= 15 )
        *((_BYTE *)v5 + i) = *((_BYTE *)&v5[8] + i) + 87;
    }
    else
    {
      *((_BYTE *)v5 + i) = *((_BYTE *)&v5[8] + i) + 48;
    }
  }
  v10 = "e0c1942932d5845b5128552378fb20bf";
  for ( i = 0; i <= 31; ++i )
  {
    if ( *((_BYTE *)v5 + i) != v10[i] )
      return 0;
  }
  return 1;
}

逆向脚本:

a = 'e0c1942932d5845b5128552378fb20bf'
a = [ord(i) for i in a]
#print(a)
for i in range(0, 32, 8):
    for j in range(4):
        a[i+j], a[i+7-j] = a[i+7-j], a[i+j]
#print(a)
a = [int(str(chr(i)), 16) for i in a]
#print(a)
for i in range(16):
    t1 = a[i*2]
    t2 = a[i*2+1]
    t1, t2 = t1 ^ t2, t1
    a[i*2], a[i*2+1] = t1, t2
hash1 = ''
for i in a:
    hash1 += str(hex(i)[2:])
print(hash1)

# md5 = b9d4d1e0ebc485121305a8414f204bf8
# plain = R2e

main2算法(只比main1多了一步)

int __cdecl main2(char *Str)
{
  int v1; // eax
  int v2; // eax
  unsigned int k; // eax
  unsigned int m; // eax
  int v6[16]; // [esp+14h] [ebp-E4h]
  char Src[8]; // [esp+54h] [ebp-A4h] BYREF
  int md5_ctx[2]; // [esp+5Ch] [ebp-9Ch] BYREF
  int v9; // [esp+64h] [ebp-94h] BYREF
  char digest[16]; // [esp+B4h] [ebp-44h] BYREF
  const char *v11; // [esp+C4h] [ebp-34h]
  int v12; // [esp+C8h] [ebp-30h]
  int v13; // [esp+CCh] [ebp-2Ch]
  int v14; // [esp+D0h] [ebp-28h]
  unsigned int v15; // [esp+D4h] [ebp-24h]
  int *ctx_state; // [esp+D8h] [ebp-20h]
  int len; // [esp+DCh] [ebp-1Ch]
  unsigned int v18; // [esp+E0h] [ebp-18h]
  int l; // [esp+E4h] [ebp-14h]
  int j; // [esp+E8h] [ebp-10h]
  int i; // [esp+ECh] [ebp-Ch]

  md5_init(md5_ctx);
  v1 = strlen(Str);
  MD5Update((int)md5_ctx, Str, v1);
  len = 0;
  v18 = ((unsigned int)md5_ctx[0] >> 3) & 0x3F;
  if ( v18 > 0x37 )
    v2 = 0x78 - v18;
  else
    v2 = 0x38 - v18;
  len = v2;
  MD5Encode((int)Src, (int)md5_ctx, 8u);
  MD5Update((int)md5_ctx, &padding, len);
  MD5Update((int)md5_ctx, Src, 8);
  ctx_state = &v9;                              // 比main1多了这块
  for ( i = 0; i <= 3; ++i )
  {
    for ( j = 0; j <= 2; ++j )
    {
      v15 = (unsigned int)ctx_state[i] >> 28;
      ctx_state[i] = 16 * ctx_state[i] + v15;   // << 4 | >> 28
    }                                           // <<12 | >> 20
    ctx_state[i] ^= 0xA3DFA1DB;
  }
  MD5Encode((int)digest, (int)ctx_state, 0x10u);
  for ( k = 0; k < 8; ++k )
    v6[k + 8] = 0;
  for ( i = 0; i <= 15; ++i )
  {
    v14 = (unsigned __int8)digest[i] >> 4;
    v13 = digest[i] & 0xF;
    *((_BYTE *)&v6[8] + 2 * i) = v13;
    *((_BYTE *)&v6[8] + 2 * i + 1) = v14 ^ v13;
  }
  for ( i = 0; i <= 31; i += 8 )
  {
    for ( l = 0; l <= 3; ++l )
    {
      v12 = *((char *)&v6[8] + i + l);
      *((_BYTE *)&v6[8] + l + i) = *((_BYTE *)&v6[8] + i + 7 - l);
      *((_BYTE *)&v6[8] + i + 7 - l) = v12;
    }
  }
  for ( m = 0; m < 8; ++m )
    v6[m] = 0;
  for ( i = 0; i <= 31; ++i )
  {
    if ( *((char *)&v6[8] + i) > 9 || *((char *)&v6[8] + i) < 0 )
    {
      if ( *((char *)&v6[8] + i) > 9 && *((char *)&v6[8] + i) <= 15 )
        *((_BYTE *)v6 + i) = *((_BYTE *)&v6[8] + i) + 87;
    }
    else
    {
      *((_BYTE *)v6 + i) = *((_BYTE *)&v6[8] + i) + 48;
    }
  }
  v11 = "d039a1b9c6daa1b450b044aeb2696a44";
  for ( i = 0; i <= 31; ++i )
  {
    if ( *((_BYTE *)v6 + i) != v11[i] )
      return 0;
  }
  return 1;
}

逆向脚本(注意MD5Encode的大小端转换哦)

b = 'd039a1b9c6daa1b450b044aeb2696a44'
b = [ord(i) for i in b]
print(b)
for i in range(0, 32, 8):
    for j in range(4):
        b[i+j], b[i+7-j] = b[i+7-j], b[i+j]
print(b)
b = [int(str(chr(i)), 16) for i in b]
print(b)
for i in range(16):
    t1 = b[i*2]
    t2 = b[i*2+1]
    t1, t2 = t1 ^ t2, t1
    b[i*2], b[i*2+1] = t1, t2
b_data = []
for i in range(16):
    tmp = (b[i*2]<<4) + b[i*2+1]
    b_data.append(tmp)
print(b_data)
for i in range(4):
    tmp = b_data[i*4] + (b_data[i*4+1]<<8) + (b_data[i*4+2]<<16) + (b_data[i*4+3]<<24)
    tmp ^= 0xA3DFA1DB
    #print(bin(tmp)[2:].zfill(32))
    tmp = ((tmp<<20)&0xffffffff) + (tmp>>12)
    #print(bin(tmp)[2:].zfill(32))
    #print()
    b_data[i*4] = tmp&0xff
    b_data[i*4+1] = (tmp>>8)&0xff
    b_data[i*4+2] = (tmp>>16)&0xff
    b_data[i*4+3] = (tmp>>24)&0xff
print(b_data)
b_md5 = ''
for i in b_data:
    b_md5 += hex(i)[2:].zfill(2)
print(b_md5)

# md5 = 6137270f515af002fa365f596612f3bd
# plain = 1S

main3算法:

int __cdecl main3(char *part3)
{
  int v1; // eax
  int v2; // eax
  unsigned int l; // eax
  int result; // eax
  int Buffer; // [esp+18h] [ebp-120h] BYREF
  int f_part3[20]; // [esp+20h] [ebp-118h] BYREF
  char Src[8]; // [esp+70h] [ebp-C8h] BYREF
  int ctx[2]; // [esp+78h] [ebp-C0h] BYREF
  _BYTE v9[80]; // [esp+80h] [ebp-B8h] BYREF
  char digest[16]; // [esp+D0h] [ebp-68h] BYREF
  char _part3[16]; // [esp+E0h] [ebp-58h] BYREF
  const char *cipher; // [esp+F0h] [ebp-48h]
  int v13; // [esp+F4h] [ebp-44h]
  size_t v14; // [esp+F8h] [ebp-40h]
  FILE *fFLAG; // [esp+FCh] [ebp-3Ch]
  FILE *fdata; // [esp+100h] [ebp-38h]
  int v17; // [esp+104h] [ebp-34h]
  int v18; // [esp+108h] [ebp-30h]
  int v19; // [esp+10Ch] [ebp-2Ch]
  int v20; // [esp+110h] [ebp-28h]
  _BYTE *v21; // [esp+114h] [ebp-24h]
  int padlen; // [esp+118h] [ebp-20h]
  unsigned int v23; // [esp+11Ch] [ebp-1Ch]
  int k; // [esp+120h] [ebp-18h]
  char part3_b3; // [esp+126h] [ebp-12h]
  char part3_b1; // [esp+127h] [ebp-11h]
  int j; // [esp+128h] [ebp-10h]
  int i; // [esp+12Ch] [ebp-Ch]

  strcpy(_part3, part3);
  md5_init(ctx);
  v1 = strlen(part3);
  MD5Update((int)ctx, part3, v1);
  padlen = 0;
  v23 = ((unsigned int)ctx[0] >> 3) & 0x3F;
  if ( v23 > 0x37 )
    v2 = 120 - v23;
  else
    v2 = 56 - v23;
  padlen = v2;
  MD5Encode((int)Src, (int)ctx, 8u);
  MD5Update((int)ctx, &padding, padlen);
  MD5Update((int)ctx, Src, 8);
  v21 = v9;
  for ( i = 0; i <= 3; ++i )
  {
    for ( j = 0; j <= 2; ++j )
    {
      v20 = *(_DWORD *)&v21[4 * i] >> 28;
      *(_DWORD *)&v21[4 * i] = 16 * *(_DWORD *)&v21[4 * i] + v20;
    }
    *(_DWORD *)&v21[4 * i] ^= 0xA3DFA1DB;
  }
  MD5Encode((int)digest, (int)v9, 0x10u);
  for ( i = 0; i <= 15; ++i )
  {
    v19 = (unsigned __int8)digest[i] >> 4;
    v18 = digest[i] & 0xF;
    *((_BYTE *)&f_part3[12] + 2 * i) = v18;
    *((_BYTE *)&f_part3[12] + 2 * i + 1) = v19 ^ v18;
  }
  part3_b1 = _part3[1] & 0x7F;                  // 差异
  part3_b3 = _part3[3] & 0x7F;
  for ( i = 0; i <= 31; ++i )
  {
    if ( i != 1 )
      part3_b1 ^= *((_BYTE *)&f_part3[12] + i);
    if ( i )
      part3_b3 ^= *((_BYTE *)&f_part3[12] + i);
  }                                             // 上 差异
  for ( i = 0; i <= 31; i += 8 )
  {
    for ( k = 0; k <= 3; ++k )
    {
      v17 = *((char *)&f_part3[12] + i + k);
      *((_BYTE *)&f_part3[12] + k + i) = *((_BYTE *)&f_part3[12] + i + 7 - k);
      *((_BYTE *)&f_part3[12] + i + 7 - k) = v17;
    }
  }
  for ( l = 0; l < 8; ++l )
    f_part3[l + 4] = 0;
  for ( i = 0; i <= 31; ++i )
  {
    if ( *((char *)&f_part3[12] + i) > 9 || *((char *)&f_part3[12] + i) < 0 )
    {
      if ( *((char *)&f_part3[12] + i) > 9 && *((char *)&f_part3[12] + i) <= 15 )
        *((_BYTE *)&f_part3[4] + i) = *((_BYTE *)&f_part3[12] + i) + 87;
    }
    else
    {
      *((_BYTE *)&f_part3[4] + i) = *((_BYTE *)&f_part3[12] + i) + 48;
    }
  }
  fdata = fopen("data", "rb");
  fFLAG = fopen("FLAG", "w+b");
  if ( fdata && fFLAG )
  {
    f_part3[2] = 0;
    f_part3[3] = 0;
    v14 = 0;
    v13 = 0;
    i = 0;
    while ( 1 )
    {
      v14 = fread(f_part3, 1u, 1u, fdata);
      if ( !v14 )
        break;
      if ( (i & 1) == 0 )                       // 偶
        Buffer = f_part3[0] ^ part3_b1;
      if ( i % 2 == 1 )                         // 奇
        Buffer = f_part3[0] ^ part3_b3;
      ++i;
      fwrite(&Buffer, 1u, 1u, fFLAG);
    }
    fclose(fdata);
    fclose(fFLAG);
    cipher = "46f627c53e41fc2a2182ba286295bc35";
    for ( i = 0; i <= 31; ++i )
    {
      if ( *((_BYTE *)&f_part3[4] + i) != cipher[i] )
        return 0;
    }
    result = 1;
  }
  else
  {
    puts("error!");
    result = 0;
  }
  return result;
}

main3是在main2基础上改的。

hint中有提示jpg。答案就是,第三段的md5查表查不出来,长度是13,爆破也不太容易。但是第三段flag就在jpg里面写着(data是jpg的密文)

那data的密钥是啥呢?来看下逻辑。

image-20201227013420150

首先flag的第三部分&0x7f后,分奇偶分别与md5计算后但是验证前的中间值循环异或。

好的,中间值我们可以逆向得到,但是这个输入值拿不到啊。这里不是突破点。

那再来看下,从data读入密文,异或后,buffer是解密的明文。

image-20201227013726366

buffer是输出,f_part3[0]是从data文件中读入的一个字节,part3_b1是密钥。

如果是jpg,那么文件头是固定(ffd8ffe0)的,所以buffer已知一定的字节。然后是f_part3[0],这是异或和的密文,就在data里,也已知。所以我们可求密钥。

解密脚本:

b = '46f627c53e41fc2a2182ba286295bc35'
b = [ord(i) for i in b]
print(b)
for i in range(0, 32, 8):
    for j in range(4):
        b[i+j], b[i+7-j] = b[i+7-j], b[i+j]
print(b)
b = [int(str(chr(i)), 16) for i in b]
print(b)


part3_b1 = 0xbd ^ 0xff
part3_b3 = 0x8b ^ 0xd8
print(part3_b1, part3_b3)
with open('data', 'rb')as f:
    b = f.read()
b = list(b)
for i in range(len(b)):
    if i % 2 == 0:
        b[i] ^= part3_b1
    else:
        b[i] ^= part3_b3
bb = b''
import struct
for i in b:
    bb += struct.pack('B', i)
with open(r'data.jpg', 'wb')as f:
    f.write(bb)

data

crypto

RSA签到

n = 807862607863494903203347547751222668477246136996519972166847
c = 6525071913169990474785757170304035615411828876052879070297
e = 65537

from Crypto.Util.number import *
from gmpy2 import *

P31 = 1034526559407993507734818408829
P30 = 780900790334269659443297956843
phi = (P31-1) * (P30-1)
d = inverse(e, phi)
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))

简单的密码学

task.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import libnum
import random
e=libnum.s2n(flag)
n = 2 ** 514
m = random.randint(2, n-1) | 1
c = pow(m, e, n)
print('m = ' + str(m))
print('c = ' + str(c))
# m = 45930439493588458217814199095166325056793804285450102007731089001050571514856332627851425138364361016243889773238664380678029627984235001868004334568770697
# c = 5057805883715955343508948629802682033540608675113624374337084633322875196538392521768197949724904990019045804655058020268973563802830621371118940310488041

flag是e,所以是离散对数的求解。

贴个资料:

img

直接上sympy的轮子:

from sympy.ntheory import *
from Crypto.Util.number import *
n = 2 ** 514
m = 45930439493588458217814199095166325056793804285450102007731089001050571514856332627851425138364361016243889773238664380678029627984235001868004334568770697
c = 5057805883715955343508948629802682033540608675113624374337084633322875196538392521768197949724904990019045804655058020268973563802830621371118940310488041
flag = discrete_log(n,c,m) 
print(long_to_bytes(flag))

名字不重要

给出一个pyc,一个流量包。

pyc改成python3.8.5的魔数,然后转成python代码。

# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: res.py
# Compiled at: 2020-12-26 02:08:16
# Size of source mod 2**32: 5 bytes
import hmac, hashlib, random, struct
KIDING_SIZE = 32
SIG_SIZE = 16
TOTAL_SIZE = set((c for c in range(256)))
KEY = b'af5f76f605a700ae8c0895c3e6175909'

def func1(v):
    return bytes([v])


def sign_sign_sign(val, key):
    return hmac.new(key,
      val, digestmod=(hashlib.sha256)).digest()[:SIG_SIZE]


def chaff_chaff_chaff_b(val, key):
    messgs = {}
    messgs[val[0]] = sign_sign_sign(val, key)
    while len(messgs) < KIDING_SIZE:
        arg1 = list(TOTAL_SIZE - set(messgs.keys()))
        c = random.choice(arg1)
        if c == val:
            raise ValueError('C~h~o~s~e d~u~p~l~i~c~a~t~e~!')
        bad_sig = bytes(random.choices((list(TOTAL_SIZE)), k=SIG_SIZE))
        messgs[c] = bad_sig

    block = []
    for k, v in messgs.items():
        block.append(b'%s%s' % (func1(k), v))
    else:
        random.shuffle(block)
        return ''.join(block)


def chaff_chaff_chaff_m(val, key):
    if not isinstance(val, bytes):
        val = val.encode('utf-8')
    the_out = []
    for b in val:
        the_out.append(chaff_chaff_chaff_b(func1(b), key))
    else:
        out1 = ''.join(the_out)
        return struct.pack('>I', len(val)) + out1


def winnow_winnow_winnow_m(val, key):
    if not isinstance(val, bytes):
        val = val.encode('utf-8')
    msglen = struct.unpack('>I', val[:4])[0]
    val = val[4:]
    block_len = (SIG_SIZE + 1) * KIDING_SIZE
    expected_len = block_len * msglen
    if len(val) != expected_len:
        raise ValueError('E~x~p~e~c~t~e~d l~e~n~g~t~h %d, saw %d.' % (expected_len, len(val)))
    pieces = []
    for c in range(msglen):
        chunk = val[block_len * c:block_len * (c + 1)]
        res = winnow_winnow_winnow_b(chunk, key)
        pieces.append(res)
    else:
        return ''.join(pieces)


def winnow_winnow_winnow_b(val, key):
    while val:
        c = func1(val[0])
        sig = val[1:SIG_SIZE + 1]
        if sign_sign_sign(c, key) == sig:
            return c
        val = val[SIG_SIZE + 1:]

    raise ValueError('~N~o v~a~l~i~d s~i~g f~o~u~n~d!')


def main():
    inp = b'~T~h~i~s i~s a t~e~s~t m~e~s~s~a~g~e!'
    msg = chaff_chaff_chaff_m(inp, KEY)
    ret = winnow_winnow_winnow_m(msg, KEY)
    if inp != ret:
        print('W~r~o~n~g r~e~t: %s' % ret)


if __name__ == '__main__':
    main()
# okay decompiling just_a_name.pyc

传输模型为首先4个字节是消息长度。然后是消息,每32*17字节为一组,每组的有效信息只有1字节。对该字节求hash,取前16byte添加在有效信息这一字节后面,这是共17字节。然后随机选31字节,这是非有效的垃圾信息,重复上述步骤,共得到32*17字节,最后随机打乱32小组的相对顺序。有效信息其实只有一字节。然后后面的有效信息同理。

另一端取出一组后,共32*17字节,循环32次。利用提前约定好的key,计算32个字节的hash,共32*16字节,对比计算结果和每个小组中的第2~17个字节的签名是否相符,相符则是有效信息,其余31字节则是垃圾信息。

但我们没有key怎么办呢?统计。

由于一个字节的签名永远是相同的。所以如果一组中的签名也在其余组中出现,那么这大概率就是有效信息及其签名。

from Crypto.Util.number import *
from scapy.all import rdpcap


packets = rdpcap("message.pcap")
sport=3199
src="127.0.0.1"
f = b''
for packet in packets:
    if "TCP" in packet and packet['TCP'].payload:
        if packet["IP"].src==src and packet["TCP"].sport==sport:
            f += packet['TCP'].payload.load
f = f[4:]


packets = []
for i in range(0, len(f), 32*17):
    packets.append(f[i:i+32*17])

data = []
all_value = []
for packet in packets:
    tmp = []
    for i in range(0, 32*17, 17):
        group = packet[i:i+17]
        ch, sig = group[0], group[1:]
        all_value.append((ch, sig))
        tmp.append((ch, sig))
    data.append(tmp)

result = []
for item in data:
    for m in item:
        if all_value.count(m) > 1:
            result.append(m)
            break

print(b''.join([long_to_bytes(item[0]) for item in result]))

名字没想好

task.py

from gmpy2 import *
import gmpy2
from Crypto.Util.number import *
from sympy import *
import sympy

#part1
flag1 = b'CUMTCTF{**********'
m1 = bytes_to_long(flag1)
p1 = getPrime(1024)
q1 = getPrime(1024)
e1 = 103738
n1 = p1 * q1
gift = lcm(p1 - 1, q1 - 1)
c1 = pow(m1, e1, n1)
print('n1 = ', n1)
print('c1 = ', c1)
print('gift = ', gift)

#part2
flag2 = b'**********************'
e2 = 65537
m2 = bytes_to_long(flag2)
p2 = getPrime(1024)
q2 = sympy.nextprime(p2)
n2 = p2 * q2
phi2 = (p2 - 1) * (q2 - 1)
d2 = gmpy2.invert(e2, phi2)
c2 = pow(m2, e2, n2)
print('d = ', d2)
print('c2 = ', c2)

data:

n1 =  24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273
c1 =  7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574
gift =  12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834
d =  14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257
c2 =  23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579

一共两关。

首先观察到e明显不是素数,但是e/2是。所以rsa的公司转换成m的平方的e/2方。套公式的时候,要把e/2当成e代入,求出的是m的平方。然后开方可得m。

然后得想办法求phi。很明显题目给出了p-1和q-1的最小公倍数。由于lcm(p-1, q-1) * gcd(p-1, q-1) = (p-1)*(q-1)

简记为lcm * gcd = phi

phi和n的长度差不太多,n的长度是2048,而lcm的长度是2047,所以gcd只需要爆个位数就行。爆出phi就可以求第一段flag.

那第二关呢?

已知e, d, c。求n。

很明显p和q是相邻素数,在这前提下p约等于根号下n约等于根号下phi。

phi可以表示成(e*d-1)/k,e和d已知。所以可以爆破k。ed乘积是2063,phi必然比d要大,而d的长度是2047,所以爆破上限是2的16次方。

稍微约束下就开始爆破。对phi开根号,可以得到p的近似值tmp。然后next_prime(tmp)必然是p或者q。为啥呢?因为p<q,如果p和q都在tmp的左侧,那么p*q<tmp的平方即phi。矛盾哦。

脚本:

from gmpy2 import *
from Crypto.Util.number import *
from sympy import *

n1 = 24511956296934419790810802924028121267308277322350201914243748724443965915830044792139346496470216715543376102606906727287935669186132061565360428924230740995935556111187855700300365517739695893842582114724005232045077425187550801509268664723237890122110051088839310003135672964413501812829310021228720112275276180469100308793523051405119335989674132224715582989624204590983857159312466387546505666052162775188773736419909262619409755848412558718676873188073997893894862353873441073313610102773845304906678909624700529896455885309546409645526387707907518497436045821973310653257012148438207441605902771515486273283273
c1 = 7357116532209949285136310518084676100522798730487701269950303460540634127932201594120600757671807456790592531487713433579926404640474277692592102315472760853853767347752080563508622523821339163225554653816787201616233932746815764392729597579461985789538131853246938443458331139199802764554726447278501492140335824365867574318693890007499638038064582031311613039571335453968072426153706431456149868515230310567240569544961967582304893471240728585336273245259533905230737876248875784828430507371662455796543123714325161987112223947057481814610592300979207673818538093532100233028106442070524965861451563388404227738574
_lcm = gift = 12255978148467209895405401462014060633654138661175100957121874362221982957915022396069673248235108357771688051303453363643967834593066030782680214462115370497967778055593927850150182758869847946921291057362002616022538712593775400754634332361618945061055025544419655001567836482206750906414655010614360056137481173664901476116870144816992211793902146834987166288769615612767704010592138813256140678199511291489394523989294805910740127557682458229594376211232977501267410539674224065875285801753027816046254818608535462445306054117075379711073762930279723764342988824053970592468109679774789092077979655857748513636834
e1 = 103738 // 2

for _gcd in range(1, 10):
    try:
        phi = _lcm * _gcd
        d1 = inverse(e1, phi)
        m1 = pow(c1, d1, n1)
        m1 = iroot(m1, 2)[0]
        msg = long_to_bytes(m1)

        if b'CUMTCTF{' in msg:
            print(msg)
            break
    except:
        pass


d2 = 14519297697723031496224953772301033569165883208616356699837703756220717249229195213146695656923357394378868735444167631602696573904678412172248043414276910206086892084385988564720914312238316434518024995169814463252129242492227202678878240875905293369168263909256455159691392124769949072754243536472227070447391890140409479709945084894060833468804156778720190688101601664725009609222256314873780002770605127043596912060811904733471592387441742111474341938658516761896926403628885365926903655309306738689809023277824030268579979837642613499180913999651379232105756338399243024739524553588216117189742912479604441636257
c2 = 23574157314515030841894399693996910252287747536395985840285410194536546768646580704111053676040921830550019965767796038280932469005359270920519250763405535872475345625907947986452218739530197421244240070129909526493952916306821311836861766221812155261751444946282559677005557815746813525162411907545113665605490915464367483833005576787591204417525937745572210195816236947103271664048065491627347939268785403334419989160034526164012966888952162714736497312282011026789187871221751240709801544484784941178786820290118585681595783245449236394480319395321877182096839866054466492123200354772280398476167002177544154960579
e2 = 65537
ed = e2 * d2
print(len(bin(ed)[2:]))

for k in range(2**14, 2**15):
    if (ed - 1) % k == 0:
        phi2 = (ed - 1) // k
        tmp = iroot(phi2, 2)[0]
        p2 = next_prime(tmp)
        #print(k)
        #print(phi2 % (p2-1))
        if phi2 % (p2-1) == 0:
            q2 = phi2 // (p2-1) + 1
            n2 = p2 * q2
            m2 = pow(c2, d2, n2)
            msg = long_to_bytes(m2)
            print(msg)
            break

Merry_Christmas

task.py

from Crypto.Util.number import *
from gmpy2 import *
#from secret import flag
bit_length = 1024
p = getPrime(bit_length)
q = getPrime(bit_length)    
n = p*q
m = bytes_to_long(flag)
n= p * q
e = 65537
c = pow(m,e,n)

p1 = getPrime(bit_length)
q1 = getPrime(bit_length)
n1 = p1*q1
e1 = 979691
c1 = pow(p,e1,n1)
gift1 = pow(907*p1+q1,587,n1)
gift2 = pow(p1+q1,691,n1)

print('n={}'.format(n))
print('c={}'.format(c))
print('n1={}'.format(n1))
print('c1={}'.format(c1))
print('gift1={}'.format(gift1))
print('gift2={}'.format(gift2))

data:

n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097
c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003
n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787
c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142
gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231
gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665

之前上海市ctf的题,原地tp我之前的wp

解题脚本:

from Crypto.Util.number import *
from gmpy2 import *

n=17539423546879883396629573776616418986256902147283732214295946312835113344061142956076117932720247053739715326040027048199629442201144987405090572982720131052885163184811793669071684926986445262835990861167700118224153436202178098707759605979066475651999711718728200184335695206586643579499656822346329750835696158561669170301767928780361376643304324731146650458384564533895090608529488304659924485356518526226061081943815971670656857778229528022465452008890430046982169571771039198877713729197033434033303723925335811353531172899520232033290866272195248554656110282928669639257994965701208856346298076998993772423097
c=5560694632613114538708358450844738346732427106497566176686415566542021811907746171660858360055720615188679328728275250111979427060322426593068123630729075838980217642604281020733578019517061369665467249555496690538379316251258553434263030485822069081031041121329559075841297923650799241347196473466430248261213536319894271629049899379974582453405472218720572088937075254938460083046946717784821298765199164644879680847984441166684509290675197526982405556980540919856072198191306527746754844792294221564010770506298266272017613487725494001276623402987809305696759434595799863487759478902384039066714073292949058853003
n1=21465819616864492551767155722996412718832402997933699784091937387760830726039866762857450959675228856561597024318920734312362144261628290737563681759442171285581931041622345778933572673367607809994811354957971820829401430301563611970709279094237597394734599103937206689348004861322161582747568764567491894069565665829828570957338594421227530701263883322496237907509301547209937444268813162260988374157151529111924866290775985684107622034449136081744171954609262107449388993051611516007232903948144186151363436032658716266030263647775582015141329829060294352706551807295555026827381280240539020513044515406829846588787
c1=19585478304129650368934167685581947379018238627360258251578178648406399091655911309790559870365866290321783969820131014958701556570645863667895395615377725655139970869868226237575462206775170966585306390686724869174973947234608655786245191308423334769172394586099003865664934720651493266130413617892286830586179842568659758155132923079476873190047514962385696606866440573294836559927597496331643346032100075257329902065785369011323134807157288931237650262052445952481912276967263237183320639027956890814569212814115581834172475173790422964999583755677956698930811772293980516268488171908878145019531149798750799613142
gift1=21073862899796816496314528055339279280335681203948249072101881208021752125789533267427994742277358208178070970462447090818216561770563907183494712376741842209323406667050344266668347773728401520981152006053958337605219297650281680615939792818684114311810254344598007357629176456353064311734075462353266893546853648829947081541158912147691654438830914577857503519080776224006347318623082457516638594584206488534978134212723395494600005197454325625290580653432901204502054226866606652982669196910942405139803194404497913820850500332680877820694279428529873469583387698995104411071804749202120283361058269192420218572231
gift2=7634352822409241151514235360777296908269419654786551951076299092182838191720014827302929726661609788893676185300000003824161794580145215813570705896440007085639728197111313542046542236060921056046727832889041640187683808320443684484085665265794806366182119574554965179974119587542057100849953753232435527244682735108194058759240757296546820383552711669453408694460188770050594702462736564767783116432265746800810795602828775783509056534518928775187835786128676790426643882842096826044057116388930041087679950264956074503205229333151001519229166174531496272703271636344792947552939606533888390978361247276796123693665
e1 = 979691
e = 65537


#gift1 = pow(907*p1+q1,587,n1)
#gift2 = pow(p1+q1,691,n1)

tmp = pow(gift2, 587, n1) - pow(gift1, 691, n1)
p1 = gcd(tmp, n1)
q1 = n1 // p1
phi1 = (p1 - 1) * (q1 - 1)
d1 = inverse(e1, phi1)
p = pow(c1, d1, n1)

q = n // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
msg = long_to_bytes(m)
print(msg)
Last modification:December 27th, 2020 at 03:26 am