[Qiangwang Mimesis 2022] Reverse question reappears

I was so anxious, the analysis of unlambda in the game was almost done. The result was abbreviated and exploded. windows_call vaguely felt that it was related to aes, but in the end, I ran to unlambda and didn’t make it to the finals.

If I could AK Re, I wouldn't have so many problems, I'm dying, I'm dying

comeongo

Pure dynamic adjustment questions, the encoding in check1 finds that the offset is a base58 table, and it is the base58 converted from 1-8 bits of name+passwd. In check2, it is found that 9-12 bits are base64, and there is an offset of +-12 or no offset, output it as plaintext misc; move to byte_compare, you can find that 13-14 bits of passwd are vG, there is a place in front There is a rax, which is related to bits 13-16. The ciphertext is an unk array, and then the difference between the last two bits in runtime_other is found to be 63 and 31. Since it is a plaintext flag, it can be done directly as a misc question. After verifying the md5, it will do.

I was thinking about grabbing the second blood in the morning, but I made it all the way to 4:30 in the afternoon, I laughed

unlambda

I touched more than half of the game, and the idea was basically correct. As a result, the stack used in the later replacement was useless and sent it.

Read some blog s first

https://zhuanlan.zhihu.com/p/30510749

https://zhuanlan.zhihu.com/p/57972301

Then you can probably figure it out.

l = lambda _ : (_ (lambda _ : lambda __: lambda ___ : (_ (___)) (__ (___))))(lambda _ : lambda __: _) stands for the iota combinator, l(l) is I, l(l(l(l))) is K, and l(l(l(l(l(l)))) is S.

I = lambda _ : arr[_(lambda _ : _ + 1)(0)] is taking out the flag of the corresponding bit

So now we use the regular first to do the first replacement

l = lambda _: (_(lambda _: lambda __: lambda ___: (_(___))(__(___))))(lambda _: lambda __: _)

id = lambda _: _(lambda _: _ + 1)(0)

stack = []
cnt = 0
flag = False
find_id = []

for i in range(len(checker)):
    if checker[i] == 'I':
        flag = True

    elif flag:
        if checker[i] == '(':
            stack.append(i)
            cnt += 1

        elif checker[i] == ')':
            st = stack.pop()
            cnt -= 1

            if cnt == 0:
                flag = False
                find_id.append(checker[st + 1: i])

for i in find_id:
    checker = checker.replace('I(' + i + ')', 'arr[' + str(id(eval(i))) + ']')

checker = checker.replace('l(l(l(l(l))))', 'S')
checker = checker.replace('l(l(l(l)))', 'K')
checker = checker.replace('l(l)', 'I')


print(checker)


Taking checker_0 as an example here, it can be found that after replacement, it will become

S(S(K(S(K(S))(K)))(S))(K(K))(arr[4])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[0])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[42])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[28])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[20])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[39])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[56])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[30])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[27])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[2])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[52])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[62])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[48])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[58])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[60])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[6])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[23])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[19])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[12])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[43])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[57])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[44])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[53])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[55])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[51])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[25])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[26])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[29])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[17])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[38])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[40])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[32])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[37])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[18])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[11])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[3])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[50])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[21])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[8])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[33])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[16])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[47])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[22])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[9])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[59])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[41])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[5])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[34])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[10])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[61])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[45])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[15])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[1])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[7])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[35])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[54])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[24])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[46])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[36])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[14])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[31])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[13])(K(I))(S(S(K(S(K(S))(K)))(S))(K(K))(arr[49])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[63])(K)(K(I)))(K(I))))(K(I)))))))))(K(I))))(K(I)))(K(I)))))(K(I))))))(K(I))))(K(I)))))(K(I)))))(K(I))))(K(I)))))(K(I))))(K(I))))))(K(I)))(K(I))))(K(I)))(K(I))))(K(I)))(K(I)))(K(I))))(K(I))))))(K(I))))(K(I))))(K(I)))(K(I)))(K(I)))(K(I)))(K(I)))(K(I)))(K(I))

In this way, you will find that there are a large number of repeated components. You can find K(I)=False by checking on the wiki, then you can find it by simplifying it a step further.

S(S(K(S(K(S))(K)))(S))(K(K))(arr[4])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[0])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[42])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[28])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[20])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[39])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[56])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[30])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[27])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[2])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[52])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[62])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[48])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[58])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[60])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[6])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[23])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[19])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[12])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[43])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[57])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[44])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[53])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[55])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[51])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[25])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[26])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[29])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[17])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[38])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[40])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[32])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[37])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[18])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[11])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[3])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[50])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[21])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[8])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[33])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[16])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[47])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[22])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[9])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[59])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[41])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[5])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[34])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[10])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[61])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[45])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[15])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[1])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[7])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[35])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[54])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[24])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[46])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[36])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[14])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[31])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[13])(False)(S(S(K(S(K(S))(K)))(S))(K(K))(arr[49])(S(S(K(S(K(S))(K)))(S))(K(K))(arr[63])(K)(False))(False)))(False))))))))(False)))(False))(False))))(False)))))(False)))(False))))(False))))(False)))(False))))(False)))(False)))))(False))(False)))(False))(False)))(False))(False))(False)))(False)))))(False)))(False)))(False))(False))(False))(False))(False))(False))(False)

There are still a lot of S(S(K(S(K(S))(K)))(S))(K(K)), after staring with big eyes, I found that there is a (K) after arr[63] , the rest are all (False). Check on the wiki and you will find that K=True. If you look at the Boolean expression of the wiki and recursively simplify the above formula, you can find that it is equivalent to an if-then-else structure. then we replace it with if

if(arr[4])(if(arr[0])(if(arr[42])(if(arr[28])(if(arr[20])(if(arr[39])(if(arr[56])(if(arr[30])(False)(if(arr[27])(if(arr[2])(False)(if(arr[52])(if(arr[62])(False)(if(arr[48])(False)(if(arr[58])(False)(if(arr[60])(if(arr[6])(False)(if(arr[23])(if(arr[19])(if(arr[12])(if(arr[43])(False)(if(arr[57])(if(arr[44])(if(arr[53])(False)(if(arr[55])(if(arr[51])(if(arr[25])(False)(if(arr[26])(False)(if(arr[29])(False)(if(arr[17])(if(arr[38])(False)(if(arr[40])(if(arr[32])(False)(if(arr[37])(False)(if(arr[18])(if(arr[11])(False)(if(arr[3])(if(arr[50])(False)(if(arr[21])(False)(if(arr[8])(if(arr[33])(False)(if(arr[16])(False)(if(arr[47])(if(arr[22])(False)(if(arr[9])(if(arr[59])(False)(if(arr[41])(False)(if(arr[5])(False)(if(arr[34])(if(arr[10])(False)(if(arr[61])(False)(if(arr[45])(if(arr[15])(if(arr[1])(False)(if(arr[7])(if(arr[35])(False)(if(arr[54])(False)(if(arr[24])(False)(if(arr[46])(False)(if(arr[36])(False)(if(arr[14])(False)(if(arr[31])(if(arr[13])(False)(if(arr[49])(if(arr[63])(True)(False))(False)))(False))))))))(False)))(False))(False))))(False)))))(False)))(False))))(False))))(False)))(False))))(False)))(False)))))(False))(False)))(False))(False)))(False))(False))(False)))(False)))))(False)))(False)))(False))(False))(False))(False))(False))(False))(False)

The logic is more obvious now. This will judge whether arr[i] is T or F layer by layer, and finally constrain checker[i] = 1, which means that we need to make it all true. In the if-then-else structure represented by if, if it is followed by (False), it is itself true, otherwise it is false (can be understood as: if(a)(b)(c) := if a then c else b.

After getting 6 checker s, you can get the flag as:

flag{JelL0_wy_De@r_l@mBdA_ExprESzl0n_wITh_iOt@!}

If you don't use stack simulation in the game, add some regular replacement, maybe you can make it 😭

windows_call

This time there is really a shadow on aes, I will write slowly later

Posted by melefire on Tue, 08 Nov 2022 19:41:26 +0530