crackPYC 题解

这个题目主要就是阅读 pyc 反汇编代码,这边把注释过的 pyc 反汇编代码贴出来

部分变量名为了方便阅读做了转换

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 (user_input) ; 输入数据

 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
             98 STORE_NAME               5 (text)

 13         100 LOAD_NAME                6 (len)
            102 LOAD_NAME                4 (user_input)
            104 CALL_FUNCTION            1
            106 LOAD_CONST              36 (32)
            108 COMPARE_OP               3 (!=) ; 比较长度
            110 POP_JUMP_IF_TRUE       140
            112 LOAD_NAME                4 (user_input)
            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
            128 LOAD_NAME                4 (user_input)
            130 LOAD_CONST              39 (31)
            132 BINARY_SUBSCR
            134 LOAD_CONST              40 ('}')
            136 COMPARE_OP               3 (!=)
            138 POP_JUMP_IF_FALSE      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 (user_input)
            158 CALL_FUNCTION            1
            160 STORE_NAME               9 (st) ; 将 user_input 转换成 list 存入 st

 17         162 BUILD_LIST               0
            164 STORE_NAME              10 (key)

 18         166 LOAD_NAME                0 (keyinit) ; 初始化 key
            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 循环

 20         188 LOAD_NAME               13 (ord)
            190 LOAD_NAME                4 (user_input)
            192 LOAD_NAME               12 (i) ; ord(user_input[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 ; len(key)
            208 BINARY_MODULO ; i % len(key)
            210 BINARY_SUBSCR ; key[i % len(key)]
            212 BINARY_XOR ; ord(user_input[i]) ^ key[i % len(key)]
            214 LOAD_NAME                9 (st)
            216 LOAD_NAME               12 (i)
            218 STORE_SUBSCR
            220 JUMP_ABSOLUTE          184
        >>  222 POP_BLOCK

 21     >>  224 LOAD_NAME                9 (st)
            226 LOAD_NAME                5 (text)
            228 COMPARE_OP               2 (==)
            230 POP_JUMP_IF_FALSE      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)

  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
             42 POP_TOP
             44 JUMP_ABSOLUTE           14
        >>   46 POP_BLOCK
        >>   48 LOAD_CONST               0 (None)
             50 RETURN_VALUE

可以得到 key 的生成函数 keyinit 的代码应该是这样的

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

加密过程为

data[i] ^ key[i % len(key)]

所以最后的解题代码

data =[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]

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

if __name__ == '__main__':
    key = keyinit()

    for i in range(len(data)):
        print(chr(data[i] ^ key[i % len(key)]), end="")