VNCTF 2022 cm cm1 RE復現

FW_ltlly發表於2022-02-15

cm1 安卓逆向

JEB

直接跟進主函式找到

image-20220215222341145

image-20220215222351191

ASSERT裡面拿到ooo檔案 直接指令碼解密

k = "vn2022"
with open('ooo', 'rb') as f:
    c = f.read()
with open('123', 'wb') as wwww:
    for i in range(len(c)):
        wwww.write(((c[i] ^ ord(k[i % 1024 % len(k)]))).to_bytes(1, byteorder="little"))  # 他一次read是1024!

新dex再反編譯

image-20220215222459808

典型xxtea


#include <stdint.h>
#include <stdio.h>
using namespace std;
#define DELTA 0x9E3779B9
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))
void xxtea(uint32_t* v, int n, uint32_t* key)
{
    uint32_t y, z;
    int sum;
    unsigned p, rounds, e;
    // encrypt
    if (n > 1) {
        rounds = 6 + (52 / n);
        sum = 0;
        z = v[n - 1];
        do {
            sum += DELTA;
            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);
    }
    // decrypt
    else if (n < -1) {
        n = -n;
        rounds = 6 + (52 / n);
        sum = rounds * DELTA;
        y = v[0];
        do {
            e = (sum >> 2) & 3;
            for (p = n - 1; p > 0; p--) {
                z = v[p - 1];
                y = v[p] -= MX;
            }
            z = v[n - 1];
            y = v[0] -= MX;
            sum -= DELTA;
        } while (--rounds);
    }
}

int main()
{
    int8_t a[] = { 68, 39, -92, 108, -82, -18, 72, -55, 74, -56, 38, 11, 60, 84, 97, -40, 87, 71, 99, -82, 120, 104, 47, -71, -58, -57, 0, 33, 42, 38, -44, -39, -60, 113, -2, 92, -75, 118, -77, 50, -121, 43, 32, -106 };
    uint32_t *v=(uint32_t *)a;
    // uint32_t v[9] = { 1,1,1,1,1,1,1,1,1 };
    // 四個32位無符號整數,即128bit的key
    uint32_t *k=(uint32_t *)"H4pPY_VNCTF!!OvO";
    // n的絕對值表示v的長度,取正表示加密,取負表示解密
    int n = 11;
    printf("Data is : %x %x %X %x %x %X %x %x %X\n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
    // xxtea(v, n, k);
    //  printf("Encrypted data is : %x %x %X %x %x %X %x %x %X\n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
    xxtea(v, -n, k);
    printf("Decrypted data is : %x %x %X %x %x %X %x %x %X\n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);

    printf("最後結果為%s", v);
    return 0;
}

cmgo! go語言與虛擬機器

ida7.6開啟 go語言直接反編譯好了

image-20220215222652384

unk_AFD8A0是opcode

main___ptr_MzVm__run函式的((void (*)(void))(v1 + 8 * v4 + 4104))();

來根據opcode執行虛擬機器

image-20220215223215516

一共20種命令

動態除錯一下 發現他每三個一組 第一個數表示操作指令 二三個數表示暫存器或者運算元

image-20220215222917599

跟進[rbx+rdi*8+1008h] 檢視opcode和函式的對映關係

image-20220215223041838

轉dq後對應一下opcode的 0-16對應函式1-17

97 98 99對應函式18 19 20

分析一下opcode和對應函式 發現不是所有函式都被使用 所以我們只用分析用到的函式(code值為0, 1, 98, 97, 2, 5, 6, 7, 8, 99, 10, 9, 12, 11, 14)

code0 nop

image-20220215223616943

code 1 mov 暫存器 運算元

image-20220215223834407

code 2 mov 暫存器 暫存器

image-20220215223922917

code5 push 暫存器 0

image-20220215224230684

code 6 pop

image-20220215224310686

code 7 add 暫存器 暫存器

code 8 sub

code 9 div

code 10 mul暫存器

code 11 xor

code 12 jmp

code 14 jne 不一樣退出

code 97scanf

image-20220215223355686

code 98 putchar

image-20220215224816503

code 99 quit

image-20220215225138261

解析指令碼


opcode = [[0, 0, 0], [0, 0, 0], [1, 0, 87], [98, 0, 0], [1, 0, 101], [98, 0, 0], [1, 0, 108], [98, 0, 0], [1, 0, 99],
          [98, 0, 0], [1, 0, 111], [98, 0, 0], [1, 0, 109], [98, 0, 0], [1, 0, 101], [98, 0, 0], [1, 0, 32], [98, 0, 0],
          [1, 0, 116], [98, 0, 0], [1, 0, 111], [98, 0, 0], [1, 0, 32], [98, 0, 0], [1, 0, 86], [98, 0, 0], [1, 0, 78],
          [98, 0, 0], [1, 0, 67], [98, 0, 0], [1, 0, 84], [98, 0, 0], [1, 0, 70], [98, 0, 0], [1, 0, 50], [98, 0, 0],
          [1, 0, 48], [98, 0, 0], [1, 0, 50], [98, 0, 0], [1, 0, 50], [98, 0, 0], [1, 0, 33], [98, 0, 0], [1, 0, 10],
          [98, 0, 0], [1, 0, 105], [98, 0, 0], [1, 0, 110], [98, 0, 0], [1, 0, 112], [98, 0, 0], [1, 0, 117],
          [98, 0, 0], [1, 0, 116], [98, 0, 0], [1, 0, 32], [98, 0, 0], [1, 0, 102], [98, 0, 0], [1, 0, 108], [98, 0, 0],
          [1, 0, 97], [98, 0, 0], [1, 0, 103], [98, 0, 0], [1, 0, 58], [98, 0, 0], [1, 0, 10], [98, 0, 0], [1, 19, 73],
          [1, 3, 0], [1, 1, 43], [1, 2, 1], [97, 0, 0], [5, 0, 0], [8, 1, 2], [14, 1, 3], [1, 0, 0], [5, 0, 0],
          [0, 0, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 6, 0], [6, 0, 0], [7, 6, 0], [2, 0, 6],
          [10, 0, 5], [2, 6, 0], [6, 0, 0], [7, 6, 0], [2, 0, 6], [10, 0, 5], [2, 6, 0], [6, 0, 0], [7, 6, 0],
          [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 7, 0], [6, 0, 0], [7, 7, 0], [2, 0, 7], [10, 0, 5],
          [2, 7, 0], [6, 0, 0], [7, 7, 0], [2, 0, 7], [10, 0, 5], [2, 7, 0], [6, 0, 0], [7, 7, 0], [0, 0, 0], [6, 0, 0],
          [1, 5, 256], [10, 0, 5], [2, 8, 0], [6, 0, 0], [7, 8, 0], [2, 0, 8], [10, 0, 5], [2, 8, 0], [6, 0, 0],
          [7, 8, 0], [2, 0, 8], [10, 0, 5], [2, 8, 0], [6, 0, 0], [7, 8, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256],
          [10, 0, 5], [2, 9, 0], [6, 0, 0], [7, 9, 0], [2, 0, 9], [10, 0, 5], [2, 9, 0], [6, 0, 0], [7, 9, 0],
          [2, 0, 9], [10, 0, 5], [2, 9, 0], [6, 0, 0], [7, 9, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5],
          [2, 10, 0], [6, 0, 0], [7, 10, 0], [2, 0, 10], [10, 0, 5], [2, 10, 0], [6, 0, 0], [7, 10, 0], [2, 0, 10],
          [10, 0, 5], [2, 10, 0], [6, 0, 0], [7, 10, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 11, 0],
          [6, 0, 0], [7, 11, 0], [2, 0, 11], [10, 0, 5], [2, 11, 0], [6, 0, 0], [7, 11, 0], [2, 0, 11], [10, 0, 5],
          [2, 11, 0], [6, 0, 0], [7, 11, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 12, 0], [6, 0, 0],
          [7, 12, 0], [2, 0, 12], [10, 0, 5], [2, 12, 0], [6, 0, 0], [7, 12, 0], [2, 0, 12], [10, 0, 5], [2, 12, 0],
          [6, 0, 0], [7, 12, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 13, 0], [6, 0, 0], [7, 13, 0],
          [2, 0, 13], [10, 0, 5], [2, 13, 0], [6, 0, 0], [7, 13, 0], [2, 0, 13], [10, 0, 5], [2, 13, 0], [6, 0, 0],
          [7, 13, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 14, 0], [6, 0, 0], [7, 14, 0], [2, 0, 14],
          [10, 0, 5], [2, 14, 0], [6, 0, 0], [7, 14, 0], [2, 0, 14], [10, 0, 5], [2, 14, 0], [6, 0, 0], [7, 14, 0],
          [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 15, 0], [6, 0, 0], [7, 15, 0], [2, 0, 15], [10, 0, 5],
          [2, 15, 0], [6, 0, 0], [7, 15, 0], [2, 0, 15], [10, 0, 5], [2, 15, 0], [6, 0, 0], [7, 15, 0], [0, 0, 0],
          [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 16, 0], [6, 0, 0], [7, 16, 0], [2, 0, 16], [10, 0, 5], [2, 16, 0],
          [6, 0, 0], [7, 16, 0], [2, 0, 16], [10, 0, 5], [2, 16, 0], [6, 0, 0], [7, 16, 0], [0, 0, 0], [5, 6, 0],
          [5, 7, 0], [5, 8, 0], [5, 9, 0], [5, 10, 0], [5, 11, 0], [5, 12, 0], [5, 13, 0], [5, 14, 0], [5, 15, 0],
          [5, 16, 0], [6, 1, 0], [6, 2, 0], [1, 20, 284], [1, 0, 340], [12, 0, 0], [1, 0, 3906065887], [1, 19, 387],
          [1, 20, 339], [14, 1, 0], [1, 0, 4125344020], [14, 2, 0], [6, 1, 0], [6, 2, 0], [1, 20, 295], [1, 0, 340],
          [12, 0, 0], [1, 0, 579781142], [1, 19, 387], [1, 20, 339], [14, 1, 0], [1, 0, 2312395361], [14, 2, 0],
          [6, 1, 0], [6, 2, 0], [1, 20, 306], [1, 0, 340], [12, 0, 0], [1, 0, 1700499305], [1, 19, 387], [1, 20, 339],
          [14, 1, 0], [1, 0, 612671610], [14, 2, 0], [6, 1, 0], [6, 2, 0], [1, 20, 317], [1, 0, 340], [12, 0, 0],
          [1, 0, 3655723000], [1, 19, 387], [1, 20, 339], [14, 1, 0], [1, 0, 977540402], [14, 2, 0], [6, 1, 0],
          [6, 2, 0], [1, 20, 328], [1, 0, 340], [12, 0, 0], [1, 0, 2443935368], [1, 19, 387], [1, 20, 339], [14, 1, 0],
          [1, 0, 1778148540], [14, 2, 0], [6, 1, 0], [1, 0, 8206181], [14, 1, 0], [1, 0, 393], [12, 0, 0], [99, 0, 0],
          [1, 3, 2654435769], [1, 4, 613452], [1, 5, 34589], [1, 6, 108471], [1, 7, 1230791], [1, 8, 0], [1, 17, 16],
          [1, 18, 32], [1, 19, 352], [1, 10, 0], [1, 11, 32], [1, 12, 1], [7, 8, 3], [2, 0, 2], [10, 0, 17], [7, 0, 4],
          [2, 14, 0], [2, 0, 2], [7, 0, 8], [2, 15, 0], [2, 0, 2], [9, 0, 18], [7, 0, 5], [2, 16, 0], [2, 0, 14],
          [11, 0, 15], [11, 0, 16], [7, 1, 0], [2, 0, 1], [10, 0, 17], [7, 0, 6], [2, 14, 0], [2, 0, 1], [7, 0, 8],
          [2, 15, 0], [2, 0, 1], [9, 0, 18], [7, 0, 7], [2, 16, 0], [2, 0, 14], [11, 0, 15], [11, 0, 16], [7, 2, 0],
          [8, 11, 12], [14, 11, 10], [12, 20, 0], [0, 0, 0], [1, 0, 110], [98, 0, 0], [1, 0, 111], [98, 0, 0],
          [12, 20, 0], [0, 0, 0], [1, 0, 121], [98, 0, 0], [1, 0, 101], [98, 0, 0], [1, 0, 115], [98, 0, 0],
          [12, 20, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
for x in opcode:
    if x[0] == 0:
        # print("nop")
        pass
    elif x[0] == 1:
        print(f"mov r{x[1]} {hex(x[2]).upper()}")
    elif x[0] == 2:
        print(f"mov r{x[1]} r{x[2]}")
    elif x[0] == 5:
        print(f"push r{x[1]}")
    elif x[0] == 6:
        print(f"pop r{x[1]}")
    elif x[0] == 7:
        print(f"add r{x[1]} r{x[2]}")
    elif x[0] == 8:
        print(f"sub r{x[1]} r{x[2]}")
    elif x[0] == 9:
        print(f"div r{x[1]} r{x[2]}")
    elif x[0] == 10:
        print(f"mul r{x[1]} r{x[2]}")
    elif x[0] == 11:
        print(f"xor r{x[1]} r{x[2]}")
    elif x[0] == 12:
        print(f"jmp r{x[1]}")
    elif x[0] == 14:
        print(f"if r{x[1]}!=r{x[2]}:quit")
    elif x[0] == 97:
        print(f"scanf r{x[1]} ")
    elif x[0] == 98:
        print(f"putchar r{x[1]} ")
    elif x[0] == 99:
        print(f"quit ")
mov r0 0X57
putchar r0 
mov r0 0X65
putchar r0 
mov r0 0X6C
putchar r0 
mov r0 0X63
putchar r0 
mov r0 0X6F
putchar r0 
mov r0 0X6D
putchar r0 
mov r0 0X65
putchar r0 
mov r0 0X20
putchar r0 
mov r0 0X74
putchar r0 
mov r0 0X6F
putchar r0 
mov r0 0X20
putchar r0 
mov r0 0X56
putchar r0 
mov r0 0X4E
putchar r0 
mov r0 0X43
putchar r0 
mov r0 0X54
putchar r0 
mov r0 0X46
putchar r0 
mov r0 0X32
putchar r0 
mov r0 0X30
putchar r0 
mov r0 0X32
putchar r0 
mov r0 0X32
putchar r0 
mov r0 0X21
putchar r0 
mov r0 0XA
putchar r0 
mov r0 0X69
putchar r0 
mov r0 0X6E
putchar r0 
mov r0 0X70
putchar r0 
mov r0 0X75
putchar r0 
mov r0 0X74
putchar r0 
mov r0 0X20
putchar r0 
mov r0 0X66
putchar r0 
mov r0 0X6C
putchar r0 
mov r0 0X61
putchar r0 
mov r0 0X67
putchar r0 
mov r0 0X3A
putchar r0 
mov r0 0XA
putchar r0 
#以上都是提示資訊 沒啥用
mov r19 0X49
mov r3 0X0
mov r1 0X2B
mov r2 0X1
scanf r0 
push r0
sub r1 r2
if r1!=r3:quit
mov r0 0X0
push r0
pop r0
mov r5 0X100 #這兩行相當於>>8 有點tea
mul r0 r5
mov r6 r0
pop r0
add r6 r0
mov r0 r6
mul r0 r5
mov r6 r0
pop r0
add r6 r0
mov r0 r6
mul r0 r5
mov r6 r0
pop r0
add r6 r0
pop r0
mov r5 0X100
mul r0 r5
mov r7 r0
pop r0
add r7 r0
mov r0 r7
mul r0 r5
mov r7 r0
pop r0
add r7 r0
mov r0 r7
mul r0 r5
mov r7 r0
pop r0
add r7 r0
pop r0
mov r5 0X100
mul r0 r5
mov r8 r0
pop r0
add r8 r0
mov r0 r8
mul r0 r5
mov r8 r0
pop r0
add r8 r0
mov r0 r8
mul r0 r5
mov r8 r0
pop r0
add r8 r0
pop r0
mov r5 0X100
mul r0 r5
mov r9 r0
pop r0
add r9 r0
mov r0 r9
mul r0 r5
mov r9 r0
pop r0
add r9 r0
mov r0 r9
mul r0 r5
mov r9 r0
pop r0
add r9 r0
pop r0
mov r5 0X100
mul r0 r5
mov r10 r0
pop r0
add r10 r0
mov r0 r10
mul r0 r5
mov r10 r0
pop r0
add r10 r0
mov r0 r10
mul r0 r5
mov r10 r0
pop r0
add r10 r0
pop r0
mov r5 0X100
mul r0 r5
mov r11 r0
pop r0
add r11 r0
mov r0 r11
mul r0 r5
mov r11 r0
pop r0
add r11 r0
mov r0 r11
mul r0 r5
mov r11 r0
pop r0
add r11 r0
pop r0
mov r5 0X100
mul r0 r5
mov r12 r0
pop r0
add r12 r0
mov r0 r12
mul r0 r5
mov r12 r0
pop r0
add r12 r0
mov r0 r12
mul r0 r5
mov r12 r0
pop r0
add r12 r0
pop r0
mov r5 0X100
mul r0 r5
mov r13 r0
pop r0
add r13 r0
mov r0 r13
mul r0 r5
mov r13 r0
pop r0
add r13 r0
mov r0 r13
mul r0 r5
mov r13 r0
pop r0
add r13 r0
pop r0
mov r5 0X100
mul r0 r5
mov r14 r0
pop r0
add r14 r0
mov r0 r14
mul r0 r5
mov r14 r0
pop r0
add r14 r0
mov r0 r14
mul r0 r5
mov r14 r0
pop r0
add r14 r0
pop r0
mov r5 0X100
mul r0 r5
mov r15 r0
pop r0
add r15 r0
mov r0 r15
mul r0 r5
mov r15 r0
pop r0
add r15 r0
mov r0 r15
mul r0 r5
mov r15 r0
pop r0
add r15 r0
pop r0
mov r5 0X100
mul r0 r5
mov r16 r0
pop r0
add r16 r0
mov r0 r16
mul r0 r5
mov r16 r0
pop r0
add r16 r0
mov r0 r16
mul r0 r5
mov r16 r0
pop r0
add r16 r0
push r6
push r7
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push r16
pop r1
pop r2
mov r20 0X11C
mov r0 0X154
jmp r0
mov r0 0XE8D1D5DF
mov r19 0X183
mov r20 0X153
if r1!=r0:quit
mov r0 0XF5E3C114
if r2!=r0:quit
pop r1
pop r2
mov r20 0X127
mov r0 0X154
jmp r0
mov r0 0X228EC216
mov r19 0X183
mov r20 0X153
if r1!=r0:quit
mov r0 0X89D45A61
if r2!=r0:quit
pop r1
pop r2
mov r20 0X132
mov r0 0X154
jmp r0
mov r0 0X655B8F69
mov r19 0X183
mov r20 0X153
if r1!=r0:quit
mov r0 0X2484A07A
if r2!=r0:quit
pop r1
pop r2
mov r20 0X13D
mov r0 0X154
jmp r0
mov r0 0XD9E5E7F8
mov r19 0X183
mov r20 0X153
if r1!=r0:quit
mov r0 0X3A441532
if r2!=r0:quit
pop r1
pop r2
mov r20 0X148
mov r0 0X154
jmp r0
mov r0 0X91AB7E88
mov r19 0X183
mov r20 0X153
if r1!=r0:quit
mov r0 0X69FC64BC
if r2!=r0:quit
pop r1
mov r0 0X7D3765
if r1!=r0:quit
mov r0 0X189
jmp r0
quit 
mov r3 0X9E3779B9 #delta 確定是tea
mov r4 0X95C4C #k0 到k3
mov r5 0X871D
mov r6 0X1A7B7
mov r7 0X12C7C7
mov r8 0X0 #sum
mov r17 0X10
mov r18 0X20
mov r19 0X160
mov r10 0X0
mov r11 0X20
mov r12 0X1
add r8 r3
mov r0 r2
mul r0 r17
add r0 r4
mov r14 r0
mov r0 r2
add r0 r8
mov r15 r0
mov r0 r2
div r0 r18
add r0 r5
mov r16 r0
mov r0 r14
xor r0 r15
xor r0 r16
add r1 r0
mov r0 r1
mul r0 r17
add r0 r6
mov r14 r0
mov r0 r1
add r0 r8
mov r15 r0
mov r0 r1
div r0 r18
add r0 r7
mov r16 r0
mov r0 r14
xor r0 r15
xor r0 r16
add r2 r0
sub r11 r12
if r11!=r10:quit
jmp r20
mov r0 0X6E
putchar r0 
mov r0 0X6F
putchar r0 
jmp r20
mov r0 0X79
putchar r0 
mov r0 0X65
putchar r0 
mov r0 0X73
putchar r0 
jmp r20

可以從0x9e3779b9看出應該是個tea類函式 位運算較少應該是個標準tea

上面的所有mul和div都是當位運算用的

解題指令碼

其中根據比較函式可以拿到正確的結果(一共11個 但是tea只加密了10個) 然後tea指令碼解密即可


#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;

int TEA_decode(uint32_t* v, uint32_t* key)
{

    uint32_t j;
    uint32_t delta = 0x9e3779b9;
    uint32_t sum = 0xC6EF3720;
    uint32_t v0 = v[0], v1 = v[1];
    uint32_t key0 = key[0], key1 = key[1], key2 = key[2], key3 = key[3];
    for (j = 0; j < 32; j++) {
        v1 -= ((v0 << 4) + key2) ^ (v0 + sum) ^ ((v0 >> 5) + key3);
        v0 -= ((v1 << 4) + key0) ^ (v1 + sum) ^ ((v1 >> 5) + key1);
        sum -= delta;
    }
    v[0] = v0;
    v[1] = v1;
}
int main()
{
    uint32_t k[4] = { 0X95C4C, 0X871D, 0X1A7B7, 0X12C7C7 };
    uint32_t enc[11] = { 0XE8D1D5DF, 0XF5E3C114, 0X228EC216, 0X89D45A61, 0X655B8F69, 0X2484A07A, 0XD9E5E7F8, 0X3A441532, 0X91AB7E88, 0X69FC64BC, 0X7D3765 };
    // TEA_encrypt(enc2,k);
    uint32_t t1[3] = { 0XE8D1D5DF, 0XF5E3C114, 0 };
    uint32_t t2[3] = { 0X228EC216, 0X89D45A61, 0 };
    uint32_t t3[3] = { 0X655B8F69, 0X2484A07A, 0 };
    uint32_t t4[3] = { 0XD9E5E7F8, 0X3A441532, 0 };
    uint32_t t5[3] = { 0X91AB7E88, 0X69FC64BC, 0 };
    uint32_t t6[2] = { 0X7D3765, 0 };
    TEA_decode(t1, k);
    TEA_decode(t2, k);
    TEA_decode(t3, k);
    TEA_decode(t4, k);
    TEA_decode(t5, k);
    // TEA_decode(t6, k);
    printf("%s%s%s%s%s%s", t1, t2, t3, t4, t5, t6);
    return 0;
}

VNCTF{ecd63ae5-8945-4ac4-b5a5-34fc3ade81e7}

相關文章