https://bbs.kanxue.com/thread-284044.htm?style=1

https://blog.xmcve.com/2024/10/20/%E5%BC%BA%E7%BD%91%E6%8B%9F%E6%80%812024-Writeup/#title-11

反调试绕过: https://github.com/x64dbg/ScyllaHide/

反调试

什么超级动调大师训练题(

j__fgetc_nolockstrlen 可以确定输入位置 在 sub_7FF7CC614A9C(__int64 a1, int a2)

对输入位置下硬件断点,ponce 调试

len = strlen(flag) cmp     rdx, 38h ;

好麻烦,用输入验证到底干嘛了,有两次操作,一次加法,一次取反和与运算乱七八糟合在一起,

MBA混淆

应该是一一对应,输入进去一样的输出一样,那么遍历输入就能直接得到字典

Tea加密

shr 11

有 TEA 加密特征数

这里就是 key[(sum>>11) & 3] 的取数的地方

key = [0x0EF6FD9DB,0x0D2C273D3,0x6F97E412,0x72BFD624]

在返回的时候查看栈帧,可以看到参数的传递(硬件断点)

所以加密次数是 0x66

(原始的函数栈还是很干净的


00007FF7CC60B1A0

什么鬼,IDA 爆炸了,trace 出来看罢

在这里比较最后一位,往前溯源,得到密文(其实就是 data 段的开头,猜的话应该也是猜放在这)

0xA1, 0xE3, 0x51, 0x98, 0x86, 0x56, 0x76, 0x49, 0x6F, 0x6B, 
0x2B, 0x81, 0xCF, 0xCE, 0x12, 0x96, 0xA2, 0x70, 0x35, 0x3C, 
0x31, 0x62, 0x5C, 0xF1, 0xFA, 0x77, 0x6B, 0xAA, 0x9E, 0x6D, 
0x05, 0xBE, 0xE8, 0x24, 0xA4, 0xF8, 0xDB, 0x23, 0x3A, 0x0B, 
0x16, 0x20, 0xCC, 0x03, 0xAD, 0xB5, 0x2B, 0xA9, 0x34, 0x9F, 
0x78, 0x1D, 0x2E, 0xB9, 0xF9, 0x9E

根据前面的密码本就能复原

#include <stdint.h>
#include <stdio.h>
 
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */
 
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
    for (i = 0; i < num_rounds; i++) {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
    }
    v[0] = v0;
    v[1] = v1;
}
 
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
    for (i = 0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0] = v0;
    v[1] = v1;
}
 
int main() {
    uint8_t cipher[] = {
        0xA1, 0xE3, 0x51, 0x98, 0x86, 0x56, 0x76, 0x49, 0x6F, 0x6B, 0x2B, 0x81,
        0xCF, 0xCE, 0x12, 0x96, 0xA2, 0x70, 0x35, 0x3C, 0x31, 0x62, 0x5C, 0xF1,
        0xFA, 0x77, 0x6B, 0xAA, 0x9E, 0x6D, 0x05, 0xBE, 0xE8, 0x24, 0xA4, 0xF8,
        0xDB, 0x23, 0x3A, 0x0B, 0x16, 0x20, 0xCC, 0x03, 0xAD, 0xB5, 0x2B, 0xA9,
        0x34, 0x9F, 0x78, 0x1D, 0x2E, 0xB9, 0xF9, 0x9E};
    uint32_t key[4] = {0x0EF6FD9DB, 0x0D2C273D3, 0x6F97E412, 0x72BFD624};
 
    for (int i = 0; i * 8 < sizeof(cipher); i++) {
        decipher(0x66, (uint32_t *)(cipher + i * 8), key);
    }
 
    uint8_t ebokk[] = {0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16,
                       0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D,
                       0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
                       0x03, 0x02, 0x01, 0x00, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB,
                       0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
                       0xF1, 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9,
                       0xE8, 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
                       0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8, 0xD7,
                       0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0, 0xCF, 0xCE,
                       0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8, 0xC7, 0xC6, 0xC5,
                       0xC4, 0xC3, 0xC2, 0xC1};
 
    for (int i = 0; i < sizeof(cipher); i++) {
        int ch = 0;
        for (int j = 0; j < sizeof(ebokk); j++) {
            if (cipher[i] == ebokk[j]) {
                ch = j;
                break;
            }
        }
        printf("%c", ch + 0x21);
    }
 
    return 0;
}
flag{u_ar3_re@11y_g00d_@t_011vm_de0bf_and_anti_debugger}