midnightctf2023 reverse

Open Source Software

sat solve

from z3 import *

key = [16, 0, 8, 20, 14, 12, 18, 2, 22, 10, 6, 4]
N = 24
flag = [BitVec('flag%d' % i, 32) for i in range(N)]
g7k = [0 for _ in range(6)]
h8m = [0 for _ in range(6)]
j9n = [0 for _ in range(12)]
q1s, r8w, s9r = 1, 1, 1

solver = Solver()

for a2z in range(0, N):
    solver.add(flag[a2z] < 256)
    solver.add(flag[a2z] >= 0)

for a2z in range(0, N, 4):
    if a2z < 12:
        j9n[key[a2z + 3] // 2] = (((((((((flag[key[a2z + 3]]) ^ (flag[key[a2z + 3] + 1])) & 0xff)) << 4) | (((((flag[key[a2z + 3]]) ^ (flag[key[a2z + 3] + 1])) & 0xff)) >> 4))) << 1) | ((((((((flag[key[a2z + 3]]) ^ (flag[key[a2z + 3] + 1])) & 0xff)) << 4) | (((((flag[key[a2z + 3]]) ^ (flag[key[a2z + 3] + 1])) & 0xff)) >> 4))) >> 7))
        g7k[a2z // 4] = (((((flag[a2z * 2 + 2]) << 4) ^ (((((((flag[a2z * 2]) ^ (flag[a2z * 2 + 2])) & 0xff)) << 4) | (((((flag[a2z * 2]) ^ (flag[a2z * 2 + 2])) & 0xff)) >> 4))))) ^ ((((flag[a2z * 2 + 6]) << 4) ^ (((((((flag[a2z * 2 + 4]) ^ (flag[a2z * 2 + 6])) & 0xff)) << 4) | (((((flag[a2z * 2 + 4]) ^ (flag[a2z * 2 + 6])) & 0xff)) >> 4))))))
        if (a2z < 4):
            h8m[a2z // 4] = (((((((((((((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[a2z + 4])) % 1257) & 0xff)) << 4) | ((((((((((((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) << 1) | (((((flag[a2z]) ^ (flag[a2z + 4])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) << 1) | (((((flag[a2z + 8]) ^ (flag[a2z + 12])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[a2z + 4])) % 1257) & 0xff)) >> 4))
        g7k[(a2z // 4) + 3] = (((((flag[a2z * 2 + 3]) << 4) ^ (((((((flag[a2z * 2 + 1]) ^ (flag[a2z * 2 + 3])) & 0xff)) << 4) | (((((flag[a2z * 2 + 1]) ^ (flag[a2z * 2 + 3])) & 0xff)) >> 4))))) ^ ((((flag[a2z * 2 + 7]) << 4) ^ (((((((flag[a2z * 2 + 5]) ^ (flag[a2z * 2 + 7])) & 0xff)) << 4) | (((((flag[a2z * 2 + 5]) ^ (flag[a2z * 2 + 7])) & 0xff)) >> 4))))));
        j9n[key[a2z + 1] // 2] = (((((((((flag[key[a2z + 1]]) ^ (flag[key[a2z + 1] + 1])) & 0xff)) << 4) | (((((flag[key[a2z + 1]]) ^ (flag[key[a2z + 1] + 1])) & 0xff)) >> 4))) << 1) | ((((((((flag[key[a2z + 1]]) ^ (flag[key[a2z + 1] + 1])) & 0xff)) << 4) | (((((flag[key[a2z + 1]]) ^ (flag[key[a2z + 1] + 1])) & 0xff)) >> 4))) >> 7))
        j9n[key[a2z + 2] // 2] = (((((((((flag[key[a2z + 2]]) ^ (flag[key[a2z + 2] + 1])) & 0xff)) << 4) | (((((flag[key[a2z + 2]]) ^ (flag[key[a2z + 2] + 1])) & 0xff)) >> 4))) << 1) | ((((((((flag[key[a2z + 2]]) ^ (flag[key[a2z + 2] + 1])) & 0xff)) << 4) | (((((flag[key[a2z + 2]]) ^ (flag[key[a2z + 2] + 1])) & 0xff)) >> 4))) >> 7))
        if (a2z == 4):
            h8m[1] = (((((((((((((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[20])) % 1257) & 0xff)) << 4) | ((((((((((((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[16]) ^ (flag[20])) & 0xff)) << 1) | (((((flag[16]) ^ (flag[20])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[1]) ^ (flag[5])) & 0xff)) << 1) | (((((flag[1]) ^ (flag[5])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[20])) % 1257) & 0xff)) >> 4))
        j9n[key[a2z] // 2] = (((((((((flag[key[a2z]]) ^ (flag[key[a2z] + 1])) & 0xff)) << 4) | (((((flag[key[a2z]]) ^ (flag[key[a2z] + 1])) & 0xff)) >> 4))) << 1) | ((((((((flag[key[a2z]]) ^ (flag[key[a2z] + 1])) & 0xff)) << 4) | (((((flag[key[a2z]]) ^ (flag[key[a2z] + 1])) & 0xff)) >> 4))) >> 7))
    else:
        if a2z < 16:
            h8m[a2z // 6] = (((((((((((((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[a2z + 1])) % 1257) & 0xff)) << 4) | ((((((((((((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) << 1) | (((((flag[a2z - 3]) ^ (flag[a2z + 1])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) << 1) | (((((flag[a2z + 5]) ^ (flag[a2z * 2 - 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[a2z + 1])) % 1257) & 0xff)) >> 4))
            h8m[3] = (((((((((((((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[6])) % 1257) & 0xff)) << 4) | ((((((((((((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[2]) ^ (flag[6])) & 0xff)) << 1) | (((((flag[2]) ^ (flag[6])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[10]) ^ (flag[14])) & 0xff)) << 1) | (((((flag[10]) ^ (flag[14])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[6])) % 1257) & 0xff)) >> 4))
        # if (((g7k[0]) << 3) ^ ((g7k[0]) >> 5)) == (0x202):
        #     s9r += 1
        # if (((g7k[1]) << 3) ^ ((g7k[1]) >> 5)) == (0x1aa2):
        #     s9r += 1
        # if (((g7k[2]) << 3) ^ ((g7k[2]) >> 5)) == (0x5a5):
        #     s9r += 1

s9r = 10

h8m[4] = (((((((((((((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[s9r * 2 + q1s + r8w])) % 1257) & 0xff)) << 4) | ((((((((((((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) << 1) | (((((flag[s9r * 2 - q1s - r8w]) ^ (flag[s9r * 2 + q1s + r8w])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) << 1) | (((((flag[q1s * 3]) ^ (flag[r8w * 7])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[s9r * 2 + q1s + r8w])) % 1257) & 0xff)) >> 4))
h8m[5] = (((((((((((((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[s9r + 5])) % 1257) & 0xff)) << 4) | ((((((((((((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) << 1) | (((((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) << 4) | ((((((((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) << 1) | (((((flag[s9r + q1s]) ^ (flag[s9r + 5])) & 0xff)) >> 7))) & 0x55) | (((((((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) << 1) | (((((flag[s9r * 2 - r8w]) ^ (flag[s9r * 2 + 3])) & 0xff)) >> 7))) & 0xaa) >> 1)) >> 4))) >> 7))) * (flag[s9r + 5])) % 1257) & 0xff)) >> 4))

solver.add(((((((((((h8m[0]) << 4) | ((h8m[0]) >> 4))) << 1) | (((((h8m[0]) << 4) | ((h8m[0]) >> 4))) >> 7))) * (q1s)) % 1257) & 0xff) == (0x5B))
q1s += 1
solver.add(((((((((((h8m[1]) << 4) | ((h8m[1]) >> 4))) << 1) | (((((h8m[1]) << 4) | ((h8m[1]) >> 4))) >> 7))) * (q1s)) % 1257) & 0xff) == (13))
q1s += 1
solver.add(((((((((((h8m[2]) << 4) | ((h8m[2]) >> 4))) << 1) | (((((h8m[2]) << 4) | ((h8m[2]) >> 4))) >> 7))) * (q1s)) % 1257) & 0xff) == (0x5D))
q1s += 1
solver.add(((((((((((h8m[3]) << 4) | ((h8m[3]) >> 4))) << 1) | (((((h8m[3]) << 4) | ((h8m[3]) >> 4))) >> 7))) * (q1s)) % 1257) & 0xff) == (0o244))
q1s += 1
solver.add(((((((((((h8m[4]) << 4) | ((h8m[4]) >> 4))) << 1) | (((((h8m[4]) << 4) | ((h8m[4]) >> 4))) >> 7))) * (q1s)) % 1257) & 0xff) == (52))
q1s += 1
solver.add(((((((((((h8m[5]) << 4) | ((h8m[5]) >> 4))) << 1) | (((((h8m[5]) << 4) | ((h8m[5]) >> 4))) >> 7))) * (q1s)) % 1257) & 0xff) == (0xDC))
q1s += 1

solver.add(((((((j9n[0]) << 4) | ((j9n[0]) >> 4))) << 1) | (((((j9n[0]) << 4) | ((j9n[0]) >> 4))) >> 7)) == (0x1010))
solver.add(((((((j9n[1]) << 4) | ((j9n[1]) >> 4))) << 1) | (((((j9n[1]) << 4) | ((j9n[1]) >> 4))) >> 7)) == (0o24050))
solver.add(((((((j9n[2]) << 4) | ((j9n[2]) >> 4))) << 1) | (((((j9n[2]) << 4) | ((j9n[2]) >> 4))) >> 7)) == (0o34070))
solver.add(((((((j9n[3]) << 4) | ((j9n[3]) >> 4))) << 1) | (((((j9n[3]) << 4) | ((j9n[3]) >> 4))) >> 7)) == (28784))
solver.add(((((((j9n[4]) << 4) | ((j9n[4]) >> 4))) << 1) | (((((j9n[4]) << 4) | ((j9n[4]) >> 4))) >> 7)) == (0x12d2d))
solver.add(((((((j9n[5]) << 4) | ((j9n[5]) >> 4))) << 1) | (((((j9n[5]) << 4) | ((j9n[5]) >> 4))) >> 7)) == (0x10d0d))
solver.add(((((((j9n[6]) << 4) | ((j9n[6]) >> 4))) << 1) | (((((j9n[6]) << 4) | ((j9n[6]) >> 4))) >> 7)) == (0o42104))
solver.add(((((((j9n[7]) << 4) | ((j9n[7]) >> 4))) << 1) | (((((j9n[7]) << 4) | ((j9n[7]) >> 4))) >> 7)) == (0o12024))
solver.add(((((((j9n[8]) << 4) | ((j9n[8]) >> 4))) << 1) | (((((j9n[8]) << 4) | ((j9n[8]) >> 4))) >> 7)) == (0xc4c4))
solver.add(((((((j9n[9]) << 4) | ((j9n[9]) >> 4))) << 1) | (((((j9n[9]) << 4) | ((j9n[9]) >> 4))) >> 7)) == (0o156334))
solver.add(((((((j9n[10]) << 4) | ((j9n[10]) >> 4))) << 1) | (((((j9n[10]) << 4) | ((j9n[10]) >> 4))) >> 7)) == (0x16161))
solver.add(((((((j9n[11]) << 4) | ((j9n[11]) >> 4))) << 1) | (((((j9n[11]) << 4) | ((j9n[11]) >> 4))) >> 7)) == (0o270561))
solver.add((((((((((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) << 1) | ((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) >> 7))) << 4) | (((((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) << 1) | ((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) >> 7))) >> 4))) << 1) | ((((((((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) << 1) | ((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) >> 7))) << 4) | (((((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) << 1) | ((((((((flag[20]) ^ (flag[23])) & 0xff)) << 4) | (((((flag[20]) ^ (flag[23])) & 0xff)) >> 4))) >> 7))) >> 4))) >> 7)) == (4112))
solver.add((((((((((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) << 1) | ((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) >> 7))) << 4) | (((((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) << 1) | ((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) >> 7))) >> 4))) << 1) | ((((((((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) << 1) | ((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) >> 7))) << 4) | (((((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) << 1) | ((((((((flag[14]) ^ (flag[0])) & 0xff)) << 4) | (((((flag[14]) ^ (flag[0])) & 0xff)) >> 4))) >> 7))) >> 4))) >> 7)) == (90465))

# ext3
solver.add((((g7k[3]) << 3) ^ ((g7k[3]) >> 5)) == (0o3417))
solver.add((((g7k[4]) << 3) ^ ((g7k[4]) >> 5)) == (0x3787))
solver.add((((g7k[5]) << 3) ^ ((g7k[5]) >> 5)) == (0o30421))

s1d = 0
for a2z in range(N):
    s1d = (s1d * 251) ^ flag[a2z]
solver.add(s1d == 0x4E6F76D0)

print(solver.check())
mod = solver.model()
print(bytes([int(mod[i].as_long()) for i in flag]))

expectations

用longjmp和setjmp做的异常处理
由于前八字节一定是“midnight”
可以直接在下图位置下断点, 手工尝试cur_chr的值
在这里插入图片描述

pressure

递归嵌套的程序,每次check两字节, 因为flag不长所以是苦力的手工做的
不过队友写了ptrace的dump脚本

Seccomp、BPF与容器安全

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stddef.h>

#include <sys/ptrace.h>
#include <sys/reg.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
/*
struct seccomp_data {
  int nr ;                    // 系统调用号(依赖于体系架构) 
  __u32 arch ;                // 架构(如AUDIT_ARCH_X86_64) 
  __u64 instruction_pointer ; // CPU指令指针 
  __u64 args [6];             // 系统调用参数,最多有6个参数 
};
*/
static void process_signals(pid_t child);
static int wait_for_write(pid_t child);
static void write_file(pid_t child, int *cnt);

/* ./a.out  ./pressure "flag{123}"  */
int main(int argc, char **argv)
{
    pid_t pid;
    int status;

    if ((pid = fork()) == 0) { //child
        struct sock_filter filter[] = {
        	// BPF_STMT有两个参数,操作码(code)和值(k)
        	// BPF_LD: 建一个 BPF 加载操作 ;BPF_W:操作数大小是一个字,
        	// BPF_ABS: 使用绝对偏移,即使用指令中的值作为数据区的偏移量,该值是体系结构字段与数据区域的偏移量 。
        	// offsetof()生成数据区域中期望字段的偏移量。
            BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)),  
            // BPF_JUMP 中有四个参数:操作码、值(k)、为真跳转(jt)和为假跳转(jf)
            // 它将指令中的值(即第二个参数__NR_write)与累加器中的值(BPF_K)进行比较,判断是否相等
            // 如果系统调用是write,则执行下一条指令(jf=0,代表如果测试为假,则跳过0条指令,也就是继续执行下一条指令)
            // 否则跳过下一条指令(jt=1,代表测试为真跳过一条指令)。
            BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 0, 1), 
            BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRACE),  //尝试通知ptrace(), 使之有机会获得控制权
            BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_execve, 0, 1),
            BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRACE),
            BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), //允许执行
        };
        struct sock_fprog prog = {
            .len = (unsigned short) (sizeof(filter)/sizeof(filter[0])),  /* BPF指令的数量 */
            .filter = filter, /*指向BPF数组的指针 */
        };
        ptrace(PTRACE_TRACEME, 0, 0, 0);
        /* To avoid the need for CAP_SYS_ADMIN */
        // 当设置了 no_new_privs 标志后,execve 会保证不会赋予运行进程新的权限, 
        // suid、sgid 权限会失效并且文件特殊权限也会失效,这意味着 execve 运行的新程序不会拥有比原进程更高的权限。
        /* With arg2 set to SECCOMP_MODE_FILTER (since Linux 3.5),
         * he system calls allowed are defined by a pointer to a
         * Berkeley Packet Filter passed in arg3.
		**/
        if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
            perror("prctl(PR_SET_NO_NEW_PRIVS)");
            return 1;
        }
        //Set the secure computing (seccomp) mode for the calling thread, to limit the available system calls.
        if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) == -1) {
            perror("when setting seccomp filter");
            return 1;
        }
        kill(getpid(), SIGSTOP); //This line of code sends a signal to the current process to suspend it.
        return execvp(argv[1], argv + 1);  // 传入程序名 和它的参数
    } else {
        waitpid(pid, &status, 0); //等待接受子进程的traceme信号  参数为0:也就是阻塞版本的等待,也就是说该waitpid在子进程没有退出情况下就不会返回
        ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESECCOMP);
        process_signals(pid);
        return 0;
    }
}

static void process_signals(pid_t child)
{
    int cnt = 0;

    while(1) {

        /* Wait for open syscall start */
        if (wait_for_write(child) != 0) break;  

        
        write_file(child, &cnt);  // call when  syscall is write 
    }

    exit(cnt);
}
static int cve_cnt = 0;
static int wait_for_write(pid_t child)
{
    int status;

    while (1) {
        ptrace(PTRACE_CONT, child, 0, 0);
        waitpid(child, &status, 0);
        printf("[waitpid status: 0x%08x]\n", status);
        /* Is it our filter for the open syscall? */
        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)) &&
            ptrace(PTRACE_PEEKUSER, child,
                   sizeof(long)*ORIG_RAX, 0) == __NR_write)
            return 0;
        
        if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8)) &&
            ptrace(PTRACE_PEEKUSER, child,
                   sizeof(long)*ORIG_RAX, 0) == __NR_execve)
            {
                cve_cnt++;
                if(cve_cnt == 2)
                    return 1;
            }
        if (WIFEXITED(status)) //若此值为非0 表明子进程正常结束。
            return 1;
    }
}

static void write_file(pid_t child, int *cnt)
{
    char *child_addr;
    long child_size;

    int fd = (int) ptrace(PTRACE_PEEKUSER, child, sizeof(long)*RDI, 0);
    child_addr = (char *) ptrace(PTRACE_PEEKUSER, child, sizeof(long)*RSI, 0);
    child_size = (long) ptrace(PTRACE_PEEKUSER, child, sizeof(long)*RDX, 0);

    if (fd < 3) return;
    (*cnt)++;
    printf("Write to fd %d, addr %p, size %ld to %d.elf\n", fd, child_addr, child_size, *cnt);
    char memfile_name[256];
    sprintf(memfile_name, "/proc/%d/mem", child);
    int memfile_fd = open(memfile_name, O_RDONLY);
    lseek(memfile_fd, (off_t) child_addr, SEEK_SET);
    char *buf = (char *)malloc(child_size);
    read(memfile_fd, buf, child_size);
    close(memfile_fd);
    printf("%d\n", buf[0]);
    sprintf(memfile_name, "%d.elf", *cnt);
    int file_fd = open(memfile_name, O_WRONLY | O_CREAT, 0644);
    write(file_fd, buf, child_size);
    close(file_fd);
    free(buf);
}

import os, time

def dump_file(name, dep):
    print(f'begin ' + f'chroot ./ ./trace {name} ' + 'f' * 64)
    ret = os.system(f'chroot ./ ./trace {name} ' + 'f' * 64)
    print(f'end {name}, {ret}')
    time.sleep(0.1)
    if os.path.exists(f'./1.elf'):
        assert os.path.exists(f'./2.elf')
        # assert not os.path.exists(f'./3.elf'), name
        os.rename(f'./1.elf', f'./{dep}1.elf')
        os.rename(f'./2.elf', f'./{dep}2.elf')
        return True
    else:
        # assert not os.path.exists(f'./2.elf')
        # assert not os.path.exists(f'./3.elf')
        if os.popen(f'chroot ./ {name} ' + 'f' * 64).read().strip() != 'failure':
            print(f'[++++] success {name}')
        return False

def dump_tree(name, dep):
    if dump_file(name, dep):
        dump_tree(f'./{dep}1.elf', dep + '1')
        dump_tree(f'./{dep}2.elf', dep + '2')
    else:
        print(f'{name} is leave')

dump_tree('./pressure', 'dumps')

dump下来的逻辑很简单, 不多说了 flag: u_b34t_th3_c10ck

unreal

吐了这题, 当时把它当misc在做, 后面才知道它可以是个可执行文件
https://blog.cmpxchg8b.com/2012/09/fun-with-constrained-programming.html
用这个工具dump一下asm的指令就行 : https://github.com/Pusty/rarvm-debugger

>>> bytes([0x0000003A ^ 0x00000057, 0x0000001F ^ 0x00000076, 0x000000B8 ^ 0x000000DC, 0x00000029 ^ 0x00000047, 0x00000086 ^ 0x000000EF, 0x00000071 ^ 0x00000016, 0x0000004E ^ 0x00000026, 0x000000F0 ^ 0x00000084, 0x00000092 ^ 0x000000E9, 0x000000C5 ^ 0x000000B7, 0x0000009A ^ 0x000000FB, 0x000000D7 ^ 0x000000A5, 0x000000E4 ^ 0x000000B2, 0x00000065 ^ 0x00000028, 0x00000037 ^ 0x00000068, 0x000000F2 ^ 0x0000009B, 0x00000011 ^ 0x00000062, 0x0000008A ^ 0x000000D5, 0x0000005D ^ 0x0000002E, 0x0000006E ^ 0x0000001A, 0x000000B1 ^ 0x000000D8, 0x000000C8 ^ 0x000000A4, 0x00000043 ^ 0x0000002F, 0x000000A9 ^ 0x000000F6, 0x00000025 ^ 0x0000004A, 0x0000004B ^ 0x0000003E, 0x0000000F ^ 0x0000007B, 0x00000072 ^ 0x0000002D, 0x00000066 ^ 0x00000012, 0x0000009C ^ 0x000000F4, 0x00000083 ^ 0x000000E6, 0x00000021 ^ 0x00000053, 0x000000BD ^ 0x000000D8, 0x000000EF ^ 0x00000092])
b'midnight{rarVM_is_still_out_there}'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值