Babushka

In script babushka.py, there are 250 functions with random generated names, half of them are not called. To seperate them we generate a list of all the random generated names in file func_names, scan again to find thoses actually contribute to the final result, we only pay attention to those function listed in file valid_funcs.

for f in `cat func_names`;do c=$(grep $f babushka.py |wc -l);if [ $c -gt 1 ];then echo $f:$c;fi;done > valid_funcs

check_key takes input string as key and pads it to reach length of 128, return a list of boolean value, combiner takes the list as parameter, return true if particular positions in the list is True.

Run combiner only with key UMASS, we get a list of 23 False from check_key.

    key = input("Oi, babushka, what's the key? ")
    combiner = types.FunctionType(types.CodeType(*pickle.loads(b'\x80\x04\x95\xcc\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x00K\x00K\x04K\x03KCC@d\x01}\x01|\x00D\x00]\x0c}\x02|\x01o\x12|\x02}\x01q\x08d\x02}\x03|\x00D\x00]\x0c}\x02|\x03|\x02O\x00}\x03q\x1e|\x01s4|\x03r8d\x02p>|\x00d\x03\x19\x00S\x00\x94(N\x88\x89K\x00t\x94)(\x8c\nOUVCHXMRZO\x94\x8c\nGDOZHYKENT\x94\x8c\nTZCLOUEGVM\x94\x8c\nMMBJDKSFLR\x94t\x94\x8c\x0e<OwOwhatsthis>\x94\x8c\x0cany_combiner\x94J\xa2\xee\x81\x02C\x0e\x00\x01\x04\x01\x08\x01\n\x01\x04\x01\x08\x01\n\x01\x94))e.')), globals())

    res = check_key(key)
    print(res)

Create a list of 23 True, change one position to False every time. As long as res[0] is True, the result is Yes!.

    res = [True] * 23
    for i in range(len(res)):
        res[i] = False
        if combiner(res):
            print("Yes!")
        else:
            print("No!")
        res[i] = True
python3 babushka.py <<< UMASS
Oi, babushka, what's the key? No!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!
Yes!

Insert debug code print(inspect.stack()[0].function, b) into each function before return, we are able to observe how return of each function affect the final result. Play around with different conditions, it seems if the 14th place of list returned by DSIIPABGWUFNMMMZAGWI function is True, the result is Yes!.

BHXFVDRTGGNFTXBCOMOJ [False, False, False, False]
BFUQBRFEKUSFTVYAIUBC [False, False, False, False, False, False, False, False]                                                                                       LXNQKJIZEUZPFAQFDWIY [False, False, False, False, False, False, False, False, False, False, False, False]
DSIIPABGWUFNMMMZAGWI [False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False]
GXMDJYHXMQHQTWTTLDEF [False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False]
AVMDIBYGKPJHLWZSFMZK [False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False]                                                                                                                                            
QHNSNERTVUQZQIOVLXHU [True, False, False, False]
...
check_key: [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True]
Yes!

The 14th value is controlled by bytecode in function DSIIPABGWUFNMMMZAGWI. Disassemble bytecode (code0) in function DSIIPABGWUFNMMMZAGWI with Python module dis, we get another piece of bytecode(code1), disassemble code1 we get bytecodes (code2) without any further call to randomly named function. Every return appends a True or False to the list, so return of code1 might give us what we what.

import types,pickle,dis
code = types.CodeType(*pickle.loads(b'\x80\x04\x95\x11\x13\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x00K...\x01\x14\x01\x16\x018\x01\x06\x01\x1a\x01\x0c\x01\x94))e.'))
dis.disco(code)

Now take a look into the dissambled code1, to make it return True we need to make the key meet all the requirements here.

42069667           0 LOAD_CONST               1 (True)
                   2 STORE_FAST               1 (OVXPEYYWSK)

42069668           4 LOAD_FAST                1 (OVXPEYYWSK)
                   6 JUMP_IF_FALSE_OR_POP   198
                   8 LOAD_GLOBAL              0 (ord)
                  10 LOAD_FAST                0 (QFBKDVBLQX)
                  12 LOAD_CONST               2 (12)
                  14 BINARY_SUBSCR
                  16 CALL_FUNCTION            1
                  18 LOAD_CONST               3 (128)
                  20 BINARY_AND
                  22 LOAD_CONST               4 (7)
                  24 BINARY_RSHIFT
                  26 LOAD_CONST               5 (0)
                  28 COMPARE_OP               2 (==)
                  30 JUMP_IF_FALSE_OR_POP   198
                  32 LOAD_GLOBAL              0 (ord)
                  34 LOAD_FAST                0 (QFBKDVBLQX)
                  36 LOAD_CONST               2 (12)
                  38 BINARY_SUBSCR
                  40 CALL_FUNCTION            1
                  42 LOAD_CONST               6 (64)
                  44 BINARY_AND
                  46 LOAD_CONST               7 (6)
                  48 BINARY_RSHIFT
                  50 LOAD_CONST               8 (1)
                  52 COMPARE_OP               2 (==)
                  54 JUMP_IF_FALSE_OR_POP   198
                  56 LOAD_GLOBAL              0 (ord)
                  58 LOAD_FAST                0 (QFBKDVBLQX)
                  60 LOAD_CONST               2 (12)
                  62 BINARY_SUBSCR
                  64 CALL_FUNCTION            1
                  66 LOAD_CONST               9 (32)
                  68 BINARY_AND
                  70 LOAD_CONST              10 (5)
                  72 BINARY_RSHIFT
                  74 LOAD_CONST               8 (1)
                  76 COMPARE_OP               2 (==)
                  78 JUMP_IF_FALSE_OR_POP   198
                  80 LOAD_GLOBAL              0 (ord)
                  82 LOAD_FAST                0 (QFBKDVBLQX)
                  84 LOAD_CONST               2 (12)
                  86 BINARY_SUBSCR
                  88 CALL_FUNCTION            1
                  90 LOAD_CONST              11 (16)
                  92 BINARY_AND
                  94 LOAD_CONST              12 (4)
                  96 BINARY_RSHIFT
                  98 LOAD_CONST               5 (0)
                 100 COMPARE_OP               2 (==)
                 102 JUMP_IF_FALSE_OR_POP   198
                 104 LOAD_GLOBAL              0 (ord)
                 106 LOAD_FAST                0 (QFBKDVBLQX)
                 108 LOAD_CONST               2 (12)
                 110 BINARY_SUBSCR
                 112 CALL_FUNCTION            1
                 114 LOAD_CONST              13 (8)
                 116 BINARY_AND
                 118 LOAD_CONST              14 (3)
                 120 BINARY_RSHIFT
                 122 LOAD_CONST               8 (1)
                 124 COMPARE_OP               2 (==)
                 126 JUMP_IF_FALSE_OR_POP   198
                 128 LOAD_GLOBAL              0 (ord)
                 130 LOAD_FAST                0 (QFBKDVBLQX)
                 132 LOAD_CONST               2 (12)
                 134 BINARY_SUBSCR
                 136 CALL_FUNCTION            1
                 138 LOAD_CONST              12 (4)
                 140 BINARY_AND
                 142 LOAD_CONST              15 (2)
                 144 BINARY_RSHIFT
                 146 LOAD_CONST               5 (0)
                 148 COMPARE_OP               2 (==)
                 150 JUMP_IF_FALSE_OR_POP   198
                 152 LOAD_GLOBAL              0 (ord)
                 154 LOAD_FAST                0 (QFBKDVBLQX)
                 156 LOAD_CONST               2 (12)
                 158 BINARY_SUBSCR
                 160 CALL_FUNCTION            1
                 162 LOAD_CONST              15 (2)
                 164 BINARY_AND
                 166 LOAD_CONST               8 (1)
                 168 BINARY_RSHIFT
                 170 LOAD_CONST               5 (0)
                 172 COMPARE_OP               2 (==)
                 174 JUMP_IF_FALSE_OR_POP   198
                 176 LOAD_GLOBAL              0 (ord)
                 178 LOAD_FAST                0 (QFBKDVBLQX)
                 180 LOAD_CONST               2 (12)
                 182 BINARY_SUBSCR
                 184 CALL_FUNCTION            1
                 186 LOAD_CONST               8 (1)
                 188 BINARY_AND
                 190 LOAD_CONST               5 (0)
                 192 BINARY_RSHIFT
                 194 LOAD_CONST               8 (1)
                 196 COMPARE_OP               2 (==)
                 ...

                3976 LOAD_GLOBAL              0 (ord)
                3978 LOAD_FAST                0 (QFBKDVBLQX)
                3980 LOAD_CONST               7 (6)
                3982 BINARY_SUBSCR
                3984 CALL_FUNCTION            1
                3986 LOAD_CONST              19 (15)
                3988 BINARY_AND
                3990 LOAD_CONST              12 (4)
                3992 BINARY_XOR
                3994 LOAD_CONST               5 (0)
                3996 COMPARE_OP               2 (==)
             >> 3998 STORE_FAST               1 (OVXPEYYWSK)

42069715        4000 LOAD_FAST                1 (OVXPEYYWSK)
                4002 EXTENDED_ARG            15
                4004 JUMP_IF_FALSE_OR_POP  4020
                4006 LOAD_GLOBAL              0 (ord)
                4008 LOAD_FAST                0 (QFBKDVBLQX)
                4010 LOAD_CONST              61 (27)
                4012 BINARY_SUBSCR
                4014 CALL_FUNCTION            1
                4016 LOAD_CONST              51 (95)
                4018 COMPARE_OP               2 (==)
             >> 4020 STORE_FAST               1 (OVXPEYYWSK)

42069716        4022 LOAD_FAST                1 (OVXPEYYWSK)
                4024 BUILD_LIST               1
                4026 STORE_FAST               1 (OVXPEYYWSK)

42069717        4028 LOAD_GLOBAL              2 (types)
                4030 LOAD_METHOD              3 (FunctionType)
                4032 LOAD_GLOBAL              2 (types)
                4034 LOAD_ATTR                4 (CodeType)
                4036 LOAD_GLOBAL              5 (pickle)
                4038 LOAD_METHOD              6 (loads)
                4040 LOAD_CONST              62 (b'\x80\x04\x95\x11\x13\x00\x00...\x01\x0c\x01\x94))e.')
                4042 CALL_METHOD              1
                4044 CALL_FUNCTION_EX         0
                4046 LOAD_GLOBAL              7 (globals)
                4048 CALL_FUNCTION            0
                4050 CALL_METHOD              2
                4052 STORE_FAST               3 (RWNMTPXTXX)

42069718        4054 LOAD_FAST                3 (RWNMTPXTXX)
                4056 LOAD_FAST                0 (QFBKDVBLQX)
                4058 CALL_FUNCTION            1
                4060 LOAD_FAST                1 (OVXPEYYWSK)
                4062 BINARY_ADD
                4064 STORE_FAST               1 (OVXPEYYWSK)

42069719        4066 LOAD_FAST                1 (OVXPEYYWSK)
                4068 RETURN_VALUE

Translate them block by block, here is the positional values of the key according to the opcodes.

s = [0]*128
s[:5] = 'UMASS'
s[5] = 123
s[6] = 112|4
s[7] = 96|8
s[8] = 51
s[9] = 80|15
s[10] = ((1<<6)&64)|((1<<5)&32)|((1<<4)&16)|((1<<1)&2)|((1<<0)&1)
s[11] = ((1<<6)&64)|((1<<5)&32)|((1<<4)&16)
s[12] = ((1<<6)&64)|((1<<5)&32)|((1<<3)&8)|((1<<0)&1)
s[13] = ((1<<5)&32)|((1<<4)&16)|((1<<0)&1)
s[14] = 49
s[15] = ((1<<6)&64)|((1<<5)&32)|((1<<0)&1)
s[16] = ((1<<6)&64)|((1<<5)&32)|((1<<2)&4)|((1<<1)&2)|((1<<0)&1)
s[17] = ((1<<5)&32)|((1<<4)&16)|((1<<1)&2)|((1<<0)&1)
s[18] = 80|15
s[19] = 98
s[20] = 112|9
s[21] = 116
s[22] = 48|3
s[23] = ((1<<6)&64)|((1<<5)&32)|((1<<1)&2)|((1<<0)&1)
s[24] = 48
s[25] = 100
s[26] = 51
s[27] = 95
s[28] = ((1<<6)&64)|((1<<5)&32)|((1<<1)&2)|((1<<0)&1)
s[29] = 112|4
s[30] = 96|6
s[31] = 116
s[32] = 96|9
s[33] = 109
s[34] = 51
s[35] = 95
s[36] = 104
s[37] = 97
s[38] = ((1<<6)&64)|((1<<5)&32)|((1<<1)&2)|((1<<0)&1)
s[39] = 96|11
s[40] = ((1<<6)&64)|((1<<5)&32)|((1<<4)&16)|((1<<3)&8)|((1<<2)&4)|((1<<0)&1)
print(''.join(s[:5])+''.join(map(chr, s[5:])))

Run the script and feed the output to babushka we get a yes!, which means this the flag.

$ python3 key.py|python3 babushka.py
Yes!
TOP