#reverse #swift #ast

一道基础的 swift AST 题目。

Swift AST 和 LLVM AST 差不多,照着写一下可以得到:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func check(_ encoded: String, _ keyValue: String) -> Bool {
    var b = Array(encoded.utf8)
    var k = Array(keyValue.utf8)
    var r0, r1, r2, r3: UInt8
    for i in 0...(b.count-4) {
        (r0, r1, r2, r3) = (b[i], b[i+1], b[i+2], b[i+3])
        b[i+0]=r2^((k[0]+(r0>>4))&0xff)
        b[i+1]=r3^((k[1]+(r1>>2))&0xff)
        b[i+2]=r0^k[2]
        b[i+3]=r1^k[3]
        (k[0], k[1], k[2], k[3]) = (k[1], k[2], k[3], k[0])
    }


    return b == [88, 35, 88, 225, 7, 201, 57, 94, 77, 56, 75, 168, 72, 218, 64, 91, 16, 101, 32, 207, 73, 130, 74, 128, 76, 201, 16, 248, 41, 205, 103, 84, 91, 99, 79, 202, 22, 131, 63, 255, 20, 16]
}
if CommandLine.arguments.count >= 2 {
    let data = CommandLine.arguments[1]
    let key = "345y"
    let result = check(data, key)
    print(result)
}

观察计算,发现它是对称的,观察计算的算法:

1
2
3
4
5
6
7
8
    for i in 0...(b.count-4) {
        (r0, r1, r2, r3) = (b[i], b[i+1], b[i+2], b[i+3])
        b[i+0]=r2^((k[0]+(r0>>4))&0xff)
        b[i+1]=r3^((k[1]+(r1>>2))&0xff)
        b[i+2]=r0^k[2]
        b[i+3]=r1^k[3]
        (k[0], k[1], k[2], k[3]) = (k[1], k[2], k[3], k[0])
    }

首先,b[i+2]b[i+3] 的计算过程是可逆的,我们可以从后往前推出 r0r1

有了 r0r1 之后,r2r3 就能相应地计算出来了,因为它的过程也是可逆的。

我们可以从后向前推出data。脚本为

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func recheck(_ keyValue: String) {
    var b: [UInt8]=[88, 35, 88, 225, 7, 201, 57, 94, 77, 56, 75, 168, 72, 218, 64, 91, 16, 101, 32, 207, 73, 130, 74, 128, 76, 201, 16, 248, 41, 205, 103, 84, 91, 99, 79, 202, 22, 131, 63, 255, 20, 16]
    var k = Array(keyValue.utf8)
    var r0, r1, r2, r3: UInt8
    for _ in 0...38 {
        (k[0], k[1], k[2], k[3]) = (k[1], k[2], k[3], k[0])
    }
    for i in stride(from: 38, to: -1, by: -1) {
        (k[3], k[2], k[1], k[0]) = (k[2], k[1], k[0], k[3])


        r0 = b[i + 2] ^ k[2]
        r1 = b[i + 3] ^ k[3]
        r2 = b[i + 0] ^ ((k[0] + (r0 >> 4)) & 0xff);
        r3 = b[i + 1] ^ ((k[1] + (r1 >> 2)) & 0xff);


        (b[i], b[i+1], b[i+2], b[i+3]) = (r0, r1, r2, r3)
    }
    let string = String(decoding: b, as: UTF8.self)
        print(string)
}


let key = "345y"
recheck(key)

得到 flag{30831242-56db-45b4-96fd-1f47e60da99d}

感觉应该可以在某些地方处理,通过编译器得到源码,或者直接翻译成二进制也好。可以尝试做一下。 #todo