Featured image of post Geek-week2-reReverse的wp及对TEA家族的学习

Geek-week2-reReverse的wp及对TEA家族的学习

TEA,XTEA,XXTEA,c语言代码,汇编代码区别

  • 前言:本文只对这三个加密进行表层的了解,不进行原理上的剖析

  • TEA

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    void tea_encrypt(uint32_t v[2], uint32_t k[4]) {
        uint32_t v0 = v[0], v1 = v[1], sum = 0;
        uint32_t delta = 0x9e3779b9;
    
        for (int i = 0; i < 32; i++) {
            sum += delta;
            v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
            v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
        }
        v[0] = v0; v[1] = v1;
    }
    
  • XTEA

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    void xtea_encrypt(uint32_t v[2], uint32_t k[4]) {
        uint32_t v0 = v[0], v1 = v[1], sum = 0;
        uint32_t delta = 0x9e3779b9;
    
        for (int i = 0; i < 32; i++) {
            v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
            sum += delta;
            v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]);
        }
        v[0] = v0; v[1] = v1;
    }
    
  • XXTEA

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    #define MX ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (k[(p & 3) ^ e] ^ z))
    
    void xxtea_encrypt(uint32_t *v, int n, uint32_t k[4]) {
        uint32_t y, z, sum = 0;
        uint32_t delta = 0x9e3779b9;
        int p, rounds = 6 + 52 / n;
    
        z = v[n - 1];
        do {
            sum += delta;
            uint32_t e = (sum >> 2) & 3;
    
            for (p = 0; p < n - 1; p++) {
                y = v[p + 1];
                z = v[p] += MX;
            }
            y = v[0];
            z = v[n - 1] += MX;
        } while (--rounds);
    }
    
  • TEA的x86-64汇编实现

      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
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    
    ; TEA加密函数 - x86-64汇编
    ; 参数: RDI=v[2], RSI=k[4]
    tea_encrypt:
        push    rbx
        push    r12
        push    r13
        push    r14
    
        ; 加载数据
        mov     eax, [rdi]          ; v0
        mov     ebx, [rdi+4]        ; v1
        mov     r12d, [rsi]         ; k[0]
        mov     r13d, [rsi+4]       ; k[1]
        mov     r14d, [rsi+8]       ; k[2]
        mov     r15d, [rsi+12]      ; k[3]
    
        xor     ecx, ecx            ; sum = 0
        mov     edx, 0x9e3779b9     ; delta
    
        mov     r8d, 32             ; 循环计数器
    
    .tea_loop:
        ; sum += delta
        add     ecx, edx
    
        ; v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1])
        mov     r9d, ebx            ; v1
        shl     r9d, 4
        add     r9d, r12d           ; (v1 << 4) + k[0]
    
        mov     r10d, ebx           ; v1
        add     r10d, ecx           ; v1 + sum
    
        mov     r11d, ebx           ; v1
        shr     r11d, 5
        add     r11d, r13d          ; (v1 >> 5) + k[1]
    
        xor     r9d, r10d
        xor     r9d, r11d
        add     eax, r9d            ; 更新v0
    
        ; v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3])
        mov     r9d, eax            ; v0
        shl     r9d, 4
        add     r9d, r14d           ; (v0 << 4) + k[2]
    
        mov     r10d, eax           ; v0
        add     r10d, ecx           ; v0 + sum
    
        mov     r11d, eax           ; v0
        shr     r11d, 5
        add     r11d, r15d          ; (v0 >> 5) + k[3]
    
        xor     r9d, r10d
        xor     r9d, r11d
        add     ebx, r9d            ; 更新v1
    
        dec     r8d
        jnz     .tea_loop
    
        ; 存储结果
        mov     [rdi], eax
        mov     [rdi+4], ebx
    
        pop     r14
        pop     r13
        pop     r12
        pop     rbx
        ret
    
    ; TEA解密函数
    tea_decrypt:
        push    rbx
        push    r12
        push    r13
        push    r14
    
        ; 加载数据
        mov     eax, [rdi]          ; v0
        mov     ebx, [rdi+4]        ; v1
        mov     r12d, [rsi]         ; k[0]
        mov     r13d, [rsi+4]       ; k[1]
        mov     r14d, [rsi+8]       ; k[2]
        mov     r15d, [rsi+12]      ; k[3]
    
        mov     ecx, 0xC6EF3720     ; sum = delta * 32
        mov     edx, 0x9e3779b9     ; delta
    
        mov     r8d, 32             ; 循环计数器
    
    .tea_decrypt_loop:
        ; v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3])
        mov     r9d, eax            ; v0
        shl     r9d, 4
        add     r9d, r14d           ; (v0 << 4) + k[2]
    
        mov     r10d, eax           ; v0
        add     r10d, ecx           ; v0 + sum
    
        mov     r11d, eax           ; v0
        shr     r11d, 5
        add     r11d, r15d          ; (v0 >> 5) + k[3]
    
        xor     r9d, r10d
        xor     r9d, r11d
        sub     ebx, r9d            ; 更新v1
    
        ; sum -= delta
        sub     ecx, edx
    
        ; v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1])
        mov     r9d, ebx            ; v1
        shl     r9d, 4
        add     r9d, r12d           ; (v1 << 4) + k[0]
    
        mov     r10d, ebx           ; v1
        add     r10d, ecx           ; v1 + sum
    
        mov     r11d, ebx           ; v1
        shr     r11d, 5
        add     r11d, r13d          ; (v1 >> 5) + k[1]
    
        xor     r9d, r10d
        xor     r9d, r11d
        sub     eax, r9d            ; 更新v0
    
        dec     r8d
        jnz     .tea_decrypt_loop
    
        ; 存储结果
        mov     [rdi], eax
        mov     [rdi+4], ebx
    
        pop     r14
        pop     r13
        pop     r12
        pop     rbx
        ret
    
  • XTEA的x86-64汇编实现

     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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    
    ; XTEA加密函数 - x86-64汇编
    ; 参数: RDI=v[2], RSI=k[4]
    xtea_encrypt:
        push    rbx
        push    r12
        push    r13
    
        ; 加载数据
        mov     eax, [rdi]          ; v0
        mov     ebx, [rdi+4]        ; v1
        mov     r12, rsi            ; k指针
    
        xor     ecx, ecx            ; sum = 0
        mov     edx, 0x9e3779b9     ; delta
    
        mov     r8d, 32             ; 循环计数器
    
    .xtea_loop:
        ; v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3])
        mov     r9d, ebx            ; v1
        mov     r10d, ebx
        shl     r9d, 4
        shr     r10d, 5
        xor     r9d, r10d
        add     r9d, ebx            ; ((v1 << 4) ^ (v1 >> 5)) + v1
    
        ; 计算 sum + k[sum & 3]
        mov     r10d, ecx           ; sum
        and     r10d, 3             ; sum & 3
        mov     r11d, [r12 + r10*4] ; k[sum & 3]
        add     r11d, ecx           ; sum + k[sum & 3]
    
        xor     r9d, r11d
        add     eax, r9d            ; 更新v0
    
        ; sum += delta
        add     ecx, edx
    
        ; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3])
        mov     r9d, eax            ; v0
        mov     r10d, eax
        shl     r9d, 4
        shr     r10d, 5
        xor     r9d, r10d
        add     r9d, eax            ; ((v0 << 4) ^ (v0 >> 5)) + v0
    
        ; 计算 sum + k[(sum >> 11) & 3]
        mov     r10d, ecx           ; sum
        shr     r10d, 11
        and     r10d, 3             ; (sum >> 11) & 3
        mov     r11d, [r12 + r10*4] ; k[(sum >> 11) & 3]
        add     r11d, ecx           ; sum + k[(sum >> 11) & 3]
    
        xor     r9d, r11d
        add     ebx, r9d            ; 更新v1
    
        dec     r8d
        jnz     .xtea_loop
    
        ; 存储结果
        mov     [rdi], eax
        mov     [rdi+4], ebx
    
        pop     r13
        pop     r12
        pop     rbx
        ret
    
  • XXXTEA的x86-64汇编实现

      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
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    
    ; XXTEA加密函数 - x86-64汇编
    ; 参数: RDI=v[], ESI=n, RDX=k[4]
    xxtea_encrypt:
        push    rbx
        push    r12
        push    r13
        push    r14
        push    r15
        push    rbp
        mov     rbp, rsp
    
        ; 保存参数
        mov     r12, rdi            ; v[]
        mov     r13d, esi           ; n
        mov     r14, rdx            ; k[4]
    
        ; 计算轮数: rounds = 6 + 52/n
        mov     eax, 52
        cdq
        idiv    r13d
        add     eax, 6
        mov     r15d, eax           ; rounds
    
        ; 加载z = v[n-1]
        mov     ecx, r13d
        dec     ecx
        mov     eax, [r12 + rcx*4]  ; z = v[n-1]
        mov     [rbp-8], eax        ; 保存z在栈上
    
        mov     edx, 0x9e3779b9     ; delta
        xor     ebx, ebx            ; sum = 0
    
    .round_loop:
        add     ebx, edx            ; sum += delta
        mov     eax, ebx
        shr     eax, 2
        and     eax, 3              ; e = (sum >> 2) & 3
    
        xor     ecx, ecx            ; p = 0
    
    .block_loop:
        ; 计算y = v[p+1]
        mov     edi, ecx
        inc     edi
        cmp     edi, r13d
        jl      .not_wrap
        xor     edi, edi            ; 如果p+1 == n,则y = v[0]
    .not_wrap:
        mov     edi, [r12 + rdi*4]  ; y = v[p+1]
    
        ; 计算MX
        ; MX = ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (k[(p & 3) ^ e] ^ z))
    
        ; 第一部分: (z >> 5 ^ y << 2)
        mov     esi, [rbp-8]        ; z
        mov     r8d, esi
        shr     r8d, 5              ; z >> 5
        mov     r9d, edi            ; y
        shl     r9d, 2              ; y << 2
        xor     r8d, r9d            ; z >> 5 ^ y << 2
    
        ; 第二部分: (y >> 3 ^ z << 4)
        mov     r9d, edi            ; y
        shr     r9d, 3              ; y >> 3
        mov     r10d, esi           ; z
        shl     r10d, 4             ; z << 4
        xor     r9d, r10d           ; y >> 3 ^ z << 4
    
        ; 第三部分: 相加
        add     r8d, r9d            ; (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)
    
        ; 第四部分: (sum ^ y)
        mov     r9d, ebx            ; sum
        xor     r9d, edi            ; sum ^ y
    
        ; 第五部分: k[(p & 3) ^ e] ^ z
        mov     r10d, ecx           ; p
        and     r10d, 3             ; p & 3
        xor     r10d, eax           ; (p & 3) ^ e
        mov     r11d, [r14 + r10*4] ; k[(p & 3) ^ e]
        xor     r11d, esi           ; k[(p & 3) ^ e] ^ z
    
        ; 第六部分: 相加
        add     r9d, r11d           ; (sum ^ y) + (k[(p & 3) ^ e] ^ z)
    
        ; 第七部分: 最终异或
        xor     r8d, r9d            ; MX结果
    
        ; 更新v[p]和z
        add     [r12 + rcx*4], r8d  ; v[p] += MX
        mov     eax, [r12 + rcx*4]  ; z = v[p]
        mov     [rbp-8], eax
    
        ; 循环控制
        inc     ecx
        cmp     ecx, r13d
        jl      .block_loop
    
        ; 外层循环控制
        dec     r15d
        jnz     .round_loop
    
        pop     rbp
        pop     r15
        pop     r14
        pop     r13
        pop     r12
        pop     rbx
        ret
    

观察差异

  • tea特征,较多左移,右移,异或操作,32/64这种轮数,key一般比较整128bit,有魔数delta,一般为0x9E3779B9
  • tea和xtea,xxtea这俩的一大明显差别是后二者多了&操作,也就使得汇编多了and指令
  • xtea和xxtea的差别是xxtea调用的寄存器比较多,操作复杂

例题

极客大挑战2025week2,reReverse

这题主要难点在于汇编中那一段爆红的汇编代码。

出题人:利用信号机制倒置了执行流,可以使用gdb的忽略信号机制调试。(这玩意挺有意思的,先鸽着有时间写个文章学一学)

所以这题要不就像无机盐大手子一样直接看汇编盯帧,要不然就用idapython,讲执行流倒置回来。

由于本人脚本编写能力有限,所以先使用盯帧法。于是就有了上面的关于tea,xtea,xxtea加密的识别

 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
27
.text:0000000000400C80     loc_400C80:                             ; CODE XREF: .text:000000000040094A↑j
.text:0000000000400C80                     mov     dword ptr [rsp+0Ch], 0C0FFh
.text:0000000000400C88                     mov     [rsp+2Ch], r14d
.text:0000000000400C8D                     mov     r10d, [rsp+64h]
.text:0000000000400C92                     mov     r11d, [rsp+60h]
.text:0000000000400C97                     mov     dword ptr [rsp+10h], 0DEADh
.text:0000000000400C9F                     mov     ebp, [rsp+5Ch]
.text:0000000000400CA3                     mov     ebx, [rsp+58h]
.text:0000000000400CA7                     mov     r8d, [rsp+54h]
.text:0000000000400CAC                     mov     dword ptr [rsp+14h], 0BEEFh
.text:0000000000400CB4                     mov     edx, [rsp+50h]
.text:0000000000400CB8                     mov     dword ptr [rsp+18h], 5A7Dh
.text:0000000000400CC0                     mov     ecx, [rsp+4Ch]
.text:0000000000400CC4                     mov     dword ptr [rsp+1Ch], 0C0FFh
.text:0000000000400CCC                     mov     esi, [rsp+48h]
.text:0000000000400CD0                     mov     dword ptr [rsp+20h], 0DEADh
.text:0000000000400CD8                     mov     r15d, 0C0FFh
.text:0000000000400CDE                     mov     edi, [rsp+44h]
.text:0000000000400CE2                     mov     dword ptr [rsp+24h], 0BEEFh
.text:0000000000400CEA                     mov     eax, 9E3779B9h
.text:0000000000400CEF                     mov     r9d, [rsp+40h]
.text:0000000000400CF4                     mov     dword ptr [rsp+28h], 5A7Dh
.text:0000000000400CFC                     mov     r14d, 5A7Dh
.text:0000000000400D02                     jnz     short loc_400D53 ; Jump if Not Zero (ZF=0)
.text:0000000000400D04                     cmp     rdx, 28h ; '('  ; Compare Two Operands
.text:0000000000400D08                     jz      loc_4008B7      ; Jump if Zero (ZF=1)
.text:0000000000400D0E

这里有魔数0x9E3779B9h,基本确定是tea加密家族,顺带把key得了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
.text:0000000000400D8E                     call    _fgets          ; Call Procedure
.text:0000000000400D93                     mov     rdi, rbx
.text:0000000000400D96                     mov     esi, 64h ; 'd'
.text:0000000000400D9B                     mov     rdx, cs:stdin
.text:0000000000400DA2                     call    ___printf_chk   ; Call Procedure
.text:0000000000400DA7                     movaps  xmmword ptr [rsp+30h], xmm0 ; Move Aligned Four Packed Single-FP
.text:0000000000400DAC                     lea     rbx, [rsp+40h]  ; Load Effective Address
.text:0000000000400DB1                     xor     eax, eax        ; Logical Exclusive OR
.text:0000000000400DB3                     mov     [rsp+0A8h], rax
.text:0000000000400DBB                     mov     rax, fs:28h
.text:0000000000400DC4                     movdqa  xmm0, cs:xmmword_401090 ; Move Aligned Double Quadword
.text:0000000000400DCC                     sub     rsp, 0B8h       ; Integer Subtraction
.text:0000000000400DD3                     push    rbx
.text:0000000000400DD4                     push    rbp
.text:0000000000400DD5                     push    r12
.text:0000000000400DD7                     push    r13
.text:0000000000400DD9                     push    r14
.text:0000000000400DDB                     mov     edi, 1
.text:0000000000400DE0                     lea     rsi, unk_401074 ; Load Effective Address
.text:0000000000400DE7                     push    r15
.text:0000000000400DE9                     endbr64                 ; Terminate an Indirect Branch in 64-bit Mode
.text:0000000000400DED                  

这里出现很多寄存器

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
.text:0000000000400BBC     loc_400BBC:                             ; CODE XREF: .text:0000000000400C7B↓j
.text:0000000000400BBC                     mov     r14d, [rsp+r12*4+30h]
.text:0000000000400BC1                     mov     [rsp+24h], r14d
.text:0000000000400BC6                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400BCB                     mov     [rsp+20h], r14d
.text:0000000000400BD0                     and     r13d, 3         ; Logical AND
.text:0000000000400BD4                     xor     r13d, 7         ; Logical Exclusive OR
.text:0000000000400BD8                     and     r12d, 3         ; Logical AND
.text:0000000000400BDC                     mov     r13d, r12d
.text:0000000000400BDF                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400BE4                     mov     [rsp+1Ch], r14d
.text:0000000000400BE9                     and     r13d, 3         ; Logical AND
.text:0000000000400BED                     xor     r13d, 6         ; Logical Exclusive OR
.text:0000000000400BF1                     mov     r13d, r12d
.text:0000000000400BF4                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400BF9                     mov     [rsp+18h], r14d
.text:0000000000400BFE                     and     r13d, 3         ; Logical AND
.text:0000000000400C02                     xor     r13d, 5         ; Logical Exclusive OR
.text:0000000000400C06                     mov     r13d, r12d
.text:0000000000400C09                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400C0E                     mov     [rsp+14h], r14d
.text:0000000000400C13                     and     r13d, 3         ; Logical AND
.text:0000000000400C17                     mov     r13d, r12d
.text:0000000000400C1A                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400C1F                     mov     [rsp+10h], r14d
.text:0000000000400C24                     and     r13d, 3         ; Logical AND
.text:0000000000400C28                     not     r13d            ; One's Complement Negation
.text:0000000000400C2B                     mov     r13d, r12d
.text:0000000000400C2E                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400C33                     mov     [rsp+0Ch], r14d
.text:0000000000400C38                     and     r13d, 3         ; Logical AND
.text:0000000000400C3C                     xor     r13d, 2         ; Logical Exclusive OR
.text:0000000000400C40                     mov     r13d, r12d
.text:0000000000400C43                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400C48                     mov     [rsp+2Ch], r14d
.text:0000000000400C4D                     and     r13d, 3         ; Logical AND
.text:0000000000400C51                     xor     r13d, 1         ; Logical Exclusive OR
.text:0000000000400C55                     mov     r13d, r12d
.text:0000000000400C58                     mov     r14d, [rsp+r13*4+30h]
.text:0000000000400C5D                     and     r13d, 3         ; Logical AND
.text:0000000000400C61                     mov     r13d, r12d
.text:0000000000400C64                     mov     r15d, [rsp+r13*4+30h]
.text:0000000000400C69                     and     r13d, 3         ; Logical AND
.text:0000000000400C6D                     xor     r13d, 9         ; Logical Exclusive OR
.text:0000000000400C71                     mov     r13d, r12d
.text:0000000000400C74                     shr     r12d, 2         ; Shift Logical Right
.text:0000000000400C78                     mov     r12d, eax
.text:0000000000400C7B                     jmp     loc_400BBC      ; Jump

这里出现了很多and

基本确定xxtea加密,密文是硬编码的也可以直接得到,但是这个密文顺序是不确定的需要暴力枚举

exp如下

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import itertools
import time

# XXTEA核心常量(与标准脚本一致)
DELTA = 0x9E3779B9

def xxtea_dec(v, k, delta=DELTA):
    """完全对齐标准脚本的XXTEA解密函数(带32位无符号截断)"""
    n = len(v)
    if n < 2:
        return v
    r = 6 + 52 // n
    s = (r + 1) * delta & 0xffffffff
    for _ in range(r):
        s = (s - delta) & 0xffffffff
        e = (s >> 2) & 3
        for i in range(n-1, -1, -1):
            y = v[(i+1) % n]
            z = v[(i-1) % n]
            v[i] = (v[i] - (((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((s ^ y) + (k[(i&3) ^ e] ^ z)))) & 0xffffffff
    return v

def uint32_array_to_bytes(arr):
    """32位整数数组转小端序字节串(高效实现)"""
    return b"".join(x.to_bytes(4, "little") for x in arr)

def check_syc_format(s):
    """校验字符串是否符合SYC{}格式:以SYC{开头、}结尾,中间为可打印字符"""
    if len(s) < 5:  # 至少SYC{}(5个字符)
        return False
    if not s.startswith("SYC{") or not s.endswith("}"):
        return False
    # 检查中间字符是否为可打印ASCII(32-126)
    for c in s[3:-1]:
        if not 32 <= ord(c) <= 126:
            return False
    return True

# 配置参数
dk = [0xDEAD, 0xBEEF, 0x5A7D, 0xC0FF]  # 固定密钥
dm = [0x2973bd37, 0x08662435, 0x0eef6889, 0xae421991, 0xd7b702cf, 0x3b98e6e6, 0x352adccf, 0xbfc393ab, 0xb3c20088, 0x1ba99aa3]  # 10个密文块

if __name__ == "__main__":
    total_perms = 3628800  # 10!的总排列数
    start_time = time.time()
    found = False
    
    print(f"开始遍历{total_perms}种密文块排列...")
    print("="*50)
    
    # 遍历所有密文块排列(itertools.permutations生成不重复排列)
    for idx, perm in enumerate(itertools.permutations(dm)):
        # 每10000次迭代打印进度
        if idx % 10000 == 0:
            elapsed = time.time() - start_time
            speed = idx / elapsed if elapsed > 0 else 0
            remaining = (total_perms - idx) / speed if speed > 0 else 0
            print(f"进度:{idx}/{total_perms} | 耗时:{elapsed:.2f}s | 速度:{speed:.0f}次/s | 剩余:{remaining:.2f}s", end="\r")
        
        # 解密当前排列的密文块
        decrypted_v = xxtea_dec(list(perm), dk.copy())
        # 转换为字节串并去除末尾补零
        decrypted_bytes = uint32_array_to_bytes(decrypted_v).rstrip(b"\x00")
        # 解码为字符串(忽略无效字符)
        decrypted_str = decrypted_bytes.decode("utf-8", "ignore")
        
        # 校验是否符合SYC{}格式
        if check_syc_format(decrypted_str):
            print("\n" + "="*50)
            print(f"✅ 找到符合格式的明文!")
            print(f"密文块正确顺序:{[hex(x) for x in perm]}")
            print(f"解密后的明文:{decrypted_str}")
            print("="*50)
            found = True
            break
    
    if not found:
        print("\n" + "="*50)
        print("❌ 未找到符合SYC{}格式的明文(可能密文/密钥错误,或格式不符)")
    
    # 输出总耗时
    total_elapsed = time.time() - start_time
    print(f"\n总耗时:{total_elapsed:.2f}秒")

结果如下

flag

或者也可以观察出密文块的顺序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.text:00000000004008BA                 cmp     r9d, 2973BD37h
.text:00000000004008E1                 cmp     r10d, 8662435h
.text:00000000004008ED                 cmp     r11d, 0EEF6889h
.text:00000000004008F9                 cmp     ebx, 0AE421991h
.text:0000000000400902                 cmp     ebp, 0D7B702CFh
.text:000000000040090A                 cmp     r8d, 3B98E6E6h
.text:0000000000400926                 cmp     edx, 352ADCCFh
.text:000000000040092F                 cmp     ecx, 0BFC393ABh
.text:0000000000400938                 cmp     esi, 0B3C20088h
.text:0000000000400942                 cmp     edi, 1BA99AA3h

这里可以看出密文是存到寄存器里面的

现在只要知道寄存器在栈里的顺序就可以知道真正的密文顺序了

 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
27
.text:0000000000400C80 loc_400C80:                             ; CODE XREF: .text:000000000040094A↑j
.text:0000000000400C80                 mov     dword ptr [rsp+0Ch], 0C0FFh
.text:0000000000400C88                 mov     [rsp+2Ch], r14d
.text:0000000000400C8D                 mov     r10d, [rsp+64h]
.text:0000000000400C92                 mov     r11d, [rsp+60h]
.text:0000000000400C97                 mov     dword ptr [rsp+10h], 0DEADh
.text:0000000000400C9F                 mov     ebp, [rsp+5Ch]
.text:0000000000400CA3                 mov     ebx, [rsp+58h]
.text:0000000000400CA7                 mov     r8d, [rsp+54h]
.text:0000000000400CAC                 mov     dword ptr [rsp+14h], 0BEEFh
.text:0000000000400CB4                 mov     edx, [rsp+50h]
.text:0000000000400CB8                 mov     dword ptr [rsp+18h], 5A7Dh
.text:0000000000400CC0                 mov     ecx, [rsp+4Ch]
.text:0000000000400CC4                 mov     dword ptr [rsp+1Ch], 0C0FFh
.text:0000000000400CCC                 mov     esi, [rsp+48h]
.text:0000000000400CD0                 mov     dword ptr [rsp+20h], 0DEADh
.text:0000000000400CD8                 mov     r15d, 0C0FFh
.text:0000000000400CDE                 mov     edi, [rsp+44h]
.text:0000000000400CE2                 mov     dword ptr [rsp+24h], 0BEEFh
.text:0000000000400CEA                 mov     eax, 9E3779B9h
.text:0000000000400CEF                 mov     r9d, [rsp+40h]
.text:0000000000400CF4                 mov     dword ptr [rsp+28h], 5A7Dh
.text:0000000000400CFC                 mov     r14d, 5A7Dh
.text:0000000000400D02                 jnz     short loc_400D53
.text:0000000000400D04                 cmp     rdx, 28h ; '('
.text:0000000000400D08                 jz      loc_4008B7
.text:0000000000400D0E

可知

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.text:0000000000400CEA                 mov     r9d, [rsp+40h]
.text:0000000000400CDE                 mov     edi, [rsp+44h]
.text:0000000000400CD0                 mov     esi, [rsp+48h]
.text:0000000000400CC4                 mov     ecx, [rsp+4Ch]
.text:0000000000400CB4                 mov     edx, [rsp+50h]
.text:0000000000400CA7                 mov     r8d, [rsp+54h]
.text:0000000000400CA3                 mov     ebx, [rsp+58h]
.text:0000000000400C9F                 mov     ebp, [rsp+5Ch]
.text:0000000000400C92                 mov     r11d, [rsp+60h]
.text:0000000000400C8D                 mov     r10d, [rsp+64h]

根据这个就可以直接获得密文,无需遍历

SYC{sakurakouji_runasama_wa_seikai_ichi}