ZJCTF2021-crackPYC

ZJCTF2021

re-crackPYC

打开题目所给crackPYC.txt文件

1           0 LOAD_CONST               0 (<code object keyinit at 0x0000028C1CC11D20, file "crackPYC.py", line 1>)
              2 LOAD_CONST               1 ('keyinit')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (keyinit)

  8           8 LOAD_NAME                1 (__name__)
             10 LOAD_CONST               2 ('__main__')
             12 COMPARE_OP               2 (==)
             14 POP_JUMP_IF_FALSE      250

  9          16 LOAD_NAME                2 (print)
             18 LOAD_CONST               3 ('Can you crack pyc?')
             20 CALL_FUNCTION            1
             22 POP_TOP

 10          24 LOAD_NAME                3 (input)
             26 LOAD_CONST               4 ('Plz give me your flag:')
             28 CALL_FUNCTION            1
             30 STORE_NAME               4 (str)     #将输入的字符存入str内

 11          32 LOAD_CONST               5 (108)
             34 LOAD_CONST               6 (17)
             36 LOAD_CONST               7 (42)
             38 LOAD_CONST               8 (226)
             40 LOAD_CONST               9 (158)
             42 LOAD_CONST              10 (180)
             44 LOAD_CONST              11 (96)
             46 LOAD_CONST              12 (115)
             48 LOAD_CONST              13 (64)
             50 LOAD_CONST              14 (24)
             52 LOAD_CONST              15 (38)
             54 LOAD_CONST              16 (236)
             56 LOAD_CONST              17 (179)
             58 LOAD_CONST              18 (173)
             60 LOAD_CONST              19 (34)
             62 LOAD_CONST              20 (22)
             64 LOAD_CONST              21 (81)
             66 LOAD_CONST              22 (113)
             68 LOAD_CONST              15 (38)
             70 LOAD_CONST              23 (215)
             72 LOAD_CONST              24 (165)
             74 LOAD_CONST              25 (135)
             76 LOAD_CONST              26 (68)
             78 LOAD_CONST              27 (7)

 12          80 LOAD_CONST              28 (119)
             82 LOAD_CONST              29 (97)
             84 LOAD_CONST              30 (45)
             86 LOAD_CONST              31 (254)
             88 LOAD_CONST              32 (250)
             90 LOAD_CONST              33 (172)
             92 LOAD_CONST              34 (43)
             94 LOAD_CONST              35 (62)
             96 BUILD_LIST              32           #建立容量为32的列表
             98 STORE_NAME               5 (text)    #以上32个数据为text数组的数值

 13         100 LOAD_NAME                6 (len)     
            102 LOAD_NAME                4 (str)     
            104 CALL_FUNCTION            1
            106 LOAD_CONST              36 (32)
            108 COMPARE_OP               3 (!=)
            110 POP_JUMP_IF_TRUE       140           #判断str即输入字符串的长度是否为32,不是则跳转到140
            112 LOAD_NAME                4 (str)     
            114 LOAD_CONST              37 (0)
            116 LOAD_CONST              27 (7)
            118 BUILD_SLICE              2
            120 BINARY_SUBSCR
            122 LOAD_CONST              38 ('DASCTF{')
            124 COMPARE_OP               3 (!=)
            126 POP_JUMP_IF_TRUE       140           #判断str字符串的前七位是否为'DASCTF{',不是则跳转到140
            128 LOAD_NAME                4 (str)
            130 LOAD_CONST              39 (31)
            132 BINARY_SUBSCR
            134 LOAD_CONST              40 ('}')
            136 COMPARE_OP               3 (!=)
            138 POP_JUMP_IF_FALSE      154           #判断str字符串的最后一位也就是31位是否为'}',不是则跳转到154
            									 #因为如果不跳转继续执行的话就会执行到输入字符串符合的一段代码使程序												    #退出

 14     >>  140 LOAD_NAME                2 (print)    
            142 LOAD_CONST              41 ('Bye bye~~')
            144 CALL_FUNCTION            1
            146 POP_TOP

 15         148 LOAD_NAME                7 (exit)
            150 CALL_FUNCTION            0
            152 POP_TOP                              #退出程序

 16     >>  154 LOAD_NAME                8 (list)    
            156 LOAD_NAME                4 (str)
            158 CALL_FUNCTION            1
            160 STORE_NAME               9 (st)      #创建列表st

 17         162 BUILD_LIST               0
            164 STORE_NAME              10 (key)

 18         166 LOAD_NAME                0 (keyinit)
            168 LOAD_NAME               10 (key)
            170 CALL_FUNCTION            1
            172 POP_TOP

 19         174 SETUP_LOOP              48 (to 224)
            176 LOAD_NAME               11 (range)
            178 LOAD_CONST              36 (32)
            180 CALL_FUNCTION            1
            182 GET_ITER
        >>  184 FOR_ITER                36 (to 222)
            186 STORE_NAME              12 (i)         #相当于for i in range(0,32)

 20         188 LOAD_NAME               13 (ord)
            190 LOAD_NAME                4 (str)
            192 LOAD_NAME               12 (i)
            194 BINARY_SUBSCR
            196 CALL_FUNCTION            1
            198 LOAD_NAME               10 (key)        
            200 LOAD_NAME               12 (i)
            202 LOAD_NAME                6 (len)
            204 LOAD_NAME               10 (key)
            206 CALL_FUNCTION            1            
            208 BINARY_MODULO                          #key元素少于str元素,所以要把i和key的长度取余避免越界
            210 BINARY_SUBSCR
            212 BINARY_XOR
            214 LOAD_NAME                9 (st)
            216 LOAD_NAME               12 (i)
            218 STORE_SUBSCR                           #此处代码将str和key中的元素进行异或处理后存入st
            220 JUMP_ABSOLUTE          184             #相当于st[i] = ord(str[i]) ^ key[i % len(key)]
        >>  222 POP_BLOCK                            

 21     >>  224 LOAD_NAME                9 (st)        
            226 LOAD_NAME                5 (text)
            228 COMPARE_OP               2 (==)
            230 POP_JUMP_IF_FALSE      242             #对比st数组和text数组,不相等则跳转到地址242处
 
 22         232 LOAD_NAME                2 (print)
            234 LOAD_CONST              42 ('Congratulations and you are good at PYC!')
            236 CALL_FUNCTION            1
            238 POP_TOP
            240 JUMP_FORWARD             8 (to 250)

 24     >>  242 LOAD_NAME                2 (print)
            244 LOAD_CONST              43 ('Sorry,plz learn more about pyc.')
            246 CALL_FUNCTION            1
            248 POP_TOP
        >>  250 LOAD_CONST              44 (None)
            252 RETURN_VALUE

Disassembly of <code object keyinit at 0x0000028C1CC11D20, file "crackPYC.py", line 1>:
  2           0 LOAD_CONST               1 (0)
              2 STORE_FAST               1 (num)

  3           4 SETUP_LOOP              42 (to 48)
              6 LOAD_GLOBAL              0 (range)
              8 LOAD_CONST               2 (8)   
             10 CALL_FUNCTION            1
             12 GET_ITER
        >>   14 FOR_ITER                30 (to 46)
             16 STORE_FAST               2 (i)         #相当于for i in range(0,8)
												  #从这里我们可以知道key的长度为8
  4          18 LOAD_FAST                1 (num)
             20 LOAD_CONST               3 (7508399208111569251)
             22 BINARY_SUBTRACT
             24 LOAD_CONST               4 (4294967295)
             26 BINARY_MODULO
             28 STORE_FAST               1 (num)

  5          30 LOAD_FAST                0 (key)
             32 LOAD_METHOD              1 (append)
             34 LOAD_FAST                1 (num)
             36 LOAD_CONST               5 (24)
             38 BINARY_RSHIFT                         #不理解这一句的意思
             40 CALL_METHOD              1            #但这一段代码就是给key赋值
             42 POP_TOP
             44 JUMP_ABSOLUTE           14
        >>   46 POP_BLOCK
        >>   48 LOAD_CONST               0 (None)
       
             50 RETURN_VALUE
        
        
        
        
        
        
        

这段代码的总体意思就是将输入的str字符串与key数组进行异或加密后存入st数组并于text数组进行对比我们可以从代码中得之text数组的元素值也可以知道str的前七位必为’DASCTF{’,最后一位必为’}’,而key数组只有8位,所以对str的加密是8位8位的进行的又因为异或具有自反性,所以可以据’DASCTF{‘字符串与text前7个元素做异或处理得出前7位,再将’}'与text最后一位进行异或 #处理得出第8位,就可以得到key的整个数组(其实主要是没看懂key数组是如何读出数据的…orz)

根据以上思路编写脚本

flag = ""
key = [0, 0, 0, 0, 0, 0, 0, 0]
text = [108, 17, 42, 226, 158, 180, 96, 115, 64, 24, 38, 236, 179, 173, 34, 22, 81, 113, 38, 215, 165, 135, 68, 7, 119, 97, 45, 254, 250, 172, 43, 62]
key[0] = ord('D') ^ text[0]
key[1] = ord('A') ^ text[1]
key[2] = ord('S') ^ text[2]
key[3] = ord('C') ^ text[3]
key[4] = ord('T') ^ text[4]
key[5] = ord('F') ^ text[5]
key[6] = ord('{') ^ text[6]
key[7] = ord('}') ^ text[31]
for i in range(32):
     flag += chr(text[i] ^ key[i % 8])
print flag

get flag

DASCTF{0hH_My_9Uy!_vou_D_1T_0^0}

PS:后面才知道应该这样解出key,我的方法也算是歪门邪道,看看就好…orz

key = []
for i in range(8):
    num = (num - 7508399208111569251) % 4294967295
    key.append((num >> 24))

猜你喜欢

转载自blog.csdn.net/weixin_50783572/article/details/120961773