首页
社区
课程
招聘
[原创]tgctf2025 部分re wp
发表于: 2025-4-15 21:09 3609

[原创]tgctf2025 部分re wp

2025-4-15 21:09
3609

conforand  :

这题是本次拿的唯一一个前三血的题qwq,大概思路比较简单

先去除平坦化,发现代码还是比较多,但是仔细观察会发现都是大片的无关代码,而实际加密部分被分割在其中

流程大概是:init中执行了sub_5s5s5s,初始化随机数种子srand(time(0)),并传入密钥JustDoIt!->

main函数调用rc4 -> rc4中先调用了init_sbox ->init_sbox中利用rand混淆s盒 -> 回到rc4中调用魔改rc4加密

加密点主要是两个,一是利用随机数混淆s盒,二是rc4加密中,最后一次的swap操作做了改动

这部分代码看着很多,其实调试一下可以发现就是rc4最后一步的生成密钥流并xor

t = ((uint8_t)s1[a] + (uint8_t)s1[d]) % 257; encode[i] = s1[t] ^ plain[i];

这题得先利用前几个字节HZNUCTF{来爆破随机数,再爆破明文

#include <iostream>
using namespace std;

void decipher(int RAND, uint8_t* PLAIN) {
    ;
}

int main()
{
    uint8_t target[] = {0x83, 0x1e, 0x9c, 0x48, 0x7a, 0xfa, 0xe8, 0x88, 0x36, 0xd5, 0x0a, 0x08, 0xf6, 0xa7, 0x70, 0x0f, 0xfd, 0x67, 0xdd, 0xd4, 0x3c, 0xa7, 0xed, 0x8d, 0x51, 0x10, 0xce, 0x6a, 0x9e, 0x56, 0x57, 0x83, 0x56, 0xe7, 0x67, 0x9a, 0x67, 0x22, 0x24, 0x6e, 0xcd, 0x2f};
    uint8_t plain[43] = "HZNUCTF{";
    for (int len = 8; len < 41; len++) {
        for (int cc = 30; cc < 127; cc++) {
            plain[len] = cc & 0xff;
            //printf("%x:", plain[len]);
            char const key[] = "JustDoIt!";
            int rand = 0x30000038;
            uint8_t s0[257];
            for (int i = 0; i < 257; i++) {
                s0[i] = uint8_t(rand ^ key[i % 9]);
            }
            //for (int i = 0; i < 257; i++) printf("%x ", s0[i]);
            //printf("\n");
            uint8_t s1[257];
            for (int i = 0; i < 257; i++) {
                s1[i] = i;
            }
            s1[256] = 0;
            int j = 0;
            int k = 0;
            uint8_t tmp = 0;
            for (int i = 0; i < 257; i++) {
                j = s1[i] + s0[i] + k;
                k = j % 257;
                tmp = s1[i];
                s1[i] = s1[k];
                s1[k] = tmp;
            }
            int a = 0, d = 0, t = 0;
            uint8_t encode[43];
            for (int i = 0; i <= len; i++) {
                a = (a + 1) % 257;
                d = (d + (uint8_t)s1[a]) % 257;
                s1[a] = s1[d];
                s1[d] = s1[a];
                t = ((uint8_t)s1[a] + (uint8_t)s1[d]) % 257;
                encode[i] = s1[t] ^ plain[i];
            }
            //for (int i = 0; i < 42; i++) printf("%x ", s1[i]);
            //printf("\n");
            uint8_t v132;
            unsigned int v133;
            for (int i = 0; i <= len; i++) {
                v132 = encode[i];
                v133 = ~(~(char)v132 | (~v132 | (char)v132 | 0xFF) & ((~(char)v132 & 0xCCCF7300 | (char)v132 & 0x33308C00 | 0xA4) ^ v132 ^ 0xCCCF735B));
                encode[i] = v133;
            }
            //for (int i = 0; i <= len; i++) printf("%x ", encode[i]);
            //printf("\n");
            if (encode[len] == target[len]) {
                break;
            }
        }
    }
    printf("%41s", plain);
}

exchange  :

一个魔改的DES加密

HZNUCTF{作为密钥传入,第一次加密进行了hex->str->组内字符交换(1234->1324)

sub_7FF7489413B6作为加密函数,下面是cmp

这里分析一下知道,函数只走了上面部分,其中41429这个函数是用密钥HZNUCTF{生成了轮密钥写入v12

4105A函数通过控制参数0,1进行加密和解密密钥的生成,并写入一个全局变量,41041函数将该全局变量写入a1,密钥生成如下:

可以看到0,1控制了v12是正序生成还是倒叙生成,比较符合

生成密钥后进入41D2F进行加密操作,可以看到进行了如下三个操作

其中3500和39A0是在把uint8写入uint32的数组v8(大端序读入)以及v8拆分到v10,

因为des加解密共同同一套算法,区别只在于密钥的不同,因此我们可以直接把这个算法抄下来就行,把最后的密文作为输入

#include <iostream>
#include<string>
using namespace std;

uint32_t dword_7FF748950DB0[32];

void sub_7FF74894113B(uint32_t* a1)
{
    uint32_t* i; // [rsp+28h] [rbp+8h]
    for (i = dword_7FF748950DB0; ; ++i)
    {
        if (i >= &dword_7FF748950DB0[32])
            break;
        *i = *a1++;
    }
}
void sub_7FF748941B80(uint32_t* a1)
{
    char* v1; // rdi
    __int64 i; // rcx
    char v4[32]; // [rsp+0h] [rbp-20h] BYREF
    char v5; // [rsp+20h] [rbp+0h] BYREF
    char* v6; // [rsp+28h] [rbp+8h]
    uint32_t* v7; // [rsp+48h] [rbp+28h]
    char v8[148]; // [rsp+70h] [rbp+50h] BYREF
    int v9; // [rsp+104h] [rbp+E4h]
    uint32_t* v11; // [rsp+200h] [rbp+1E0h]

    v6 = v8;
    v9 = 0;
    while (v9 < 16)
    {
        v7 = a1;
        v11 = a1 + 1;
        *(uint32_t*)v6 = (*v7 & 0xFC0000) << 6;
        *(uint32_t*)v6 |= (*v7 & 0xFC0) << 10;
        *(uint32_t*)v6 |= (*v11 & 0xFC0000u) >> 10;
        *(uint32_t*)v6 |= (*v11 & 0xFC0u) >> 6;
        v6 += 4;
        *(uint32_t*)v6 = (*v7 & 0x3F000) << 12;
        *(uint32_t*)v6 |= (*v7 & 0x3F) << 16;
        *(uint32_t*)v6 |= (*v11 & 0x3F000u) >> 4;
        *(uint32_t*)v6 |= *v11 & 0x3F;
        v6 += 4;
        ++v9;
        a1 = v11 + 1;
    }
    sub_7FF74894113B((uint32_t*)v8);
}
void sub_7FF74894105A(__int64 a1, __int64 a2) {
    char* v2; // rdi
    __int64 i; // rcx
    char v4; // al
    char v5; // al
    char v7[32]; // [rsp+0h] [rbp-20h] BYREF
    char v8; // [rsp+20h] [rbp+0h] BYREF
    int k; // [rsp+24h] [rbp+4h]
    int j; // [rsp+44h] [rbp+24h]
    int v11; // [rsp+64h] [rbp+44h]
    int v12; // [rsp+84h] [rbp+64h]
    int v13; // [rsp+A4h] [rbp+84h]
    char v14[168]; // [rsp+C8h] [rbp+A8h]
    int v15[81]; // [rsp+170h] [rbp+150h] BYREF
    bool v16; // [rsp+2B4h] [rbp+294h]
    uint8_t byte_7FF748950970[56] = { 0x38,0x30,0x28,0x20,0x18,0x10,0x8,0x0,0x39,0x31,0x29,0x21,0x19,0x11,0x9,0x1,0x3a,0x32,0x2a,0x22,0x1a,0x12,0xa,0x2,0x3b,0x33,0x2b,0x23,0x3e,0x36,0x2e,0x26,0x1e,0x16,0xe,0x6,0x3d,0x35,0x2d,0x25,0x1d,0x15,0xd,0x5,0x3c,0x34,0x2c,0x24,0x1c,0x14,0xc,0x4,0x1b,0x13,0xb,0x3 };
    uint16_t word_7FF748950900[8] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
    uint8_t byte_7FF7489509A8[16] = { 0x201, 0x302, 0x403, 0x504, 0x605, 0x706, 0x807, 0x908, 0xa09, 0xb0a, 0xc0b, 0xd0c, 0xe0d, 0xf0e, 0x100f, 0xd10 };
    uint8_t byte_7FF7489509B8[48] = { 0xd,0x10,0xa,0x17,0x0,0x4,0x2,0x1b,0xe,0x5,0x14,0x9,0x16,0x12,0xb,0x3,0x19,0x7,0xf,0x6,0x1a,0x13,0xc,0x1,0x28,0x33,0x1e,0x24,0x2e,0x36,0x1d,0x27,0x32,0x2c,0x20,0x2f,0x2b,0x30,0x26,0x37,0x21,0x34,0x2d,0x29,0x31,0x23,0x1c,0x1f };
    uint32_t dword_7FF748950910[24] = { 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
    for (j = 0; j < 56; ++j)
    {
        v11 = byte_7FF748950970[j];
        v12 = v11 & 7;
        v16 = (word_7FF748950900[v11 & 7] & *(unsigned __int8*)(a1 + (v11 >> 3))) != 0;
        v14[j] = v16;
    }
    for (k = 0; k < 16; ++k)
    {
        if (a2 == 1)
            v12 = 2 * (15 - k);
        else
            v12 = 2 * k;
        v13 = v12 + 1;
        v15[v12 + 1] = 0;
        v15[v12] = 0;
        for (j = 0; j < 28; ++j)
        {
            v11 = byte_7FF7489509A8[k] + j;
            if (v11 >= 28)
                v4 = v14[v11 - 28];
            else
                v4 = v14[v11];
            v14[j + 80] = v4;
        }
        for (j = 28; j < 56; ++j)
        {
            v11 = byte_7FF7489509A8[k] + j;
            if (v11 >= 56)
                v5 = v14[v11 - 28];
            else
                v5 = v14[v11];
            v14[j + 80] = v5;
        }
        for (j = 0; j < 24; ++j)
        {
            if (v14[byte_7FF7489509B8[j] + 80])
                v15[v12] |= dword_7FF748950910[j];
            if (v14[byte_7FF7489509B8[j + 24] + 80])
                v15[v13] |= dword_7FF748950910[j];
        }
    }
    sub_7FF748941B80((uint32_t*)v15);
}
void sub_7FF748941041(uint32_t* a1)
{
    char* result; // rax
    uint32_t* i; // [rsp+28h] [rbp+8h]
    for (i = dword_7FF748950DB0; ; ++i)
    {
        if (i >= dword_7FF748950DB0 + 32)
            break;
        *a1++ = *i;
    }
}
void sub_7FF748941249(__int64 a1, __int64 a2)
{
    sub_7FF74894105A(a2, 0i64);
    sub_7FF748941041((uint32_t*)a1);

    sub_7FF74894105A(a2, 1i64);
    sub_7FF748941041((uint32_t*)(a1 + 128));
}

void func(uint32_t* a1, uint32_t* a2) {
    int v3; // [rsp+24h] [rbp+4h]
    int v4; // [rsp+24h] [rbp+4h]
    int v5; // [rsp+44h] [rbp+24h]
    int v6; // [rsp+44h] [rbp+24h]
    int v7; // [rsp+44h] [rbp+24h]
    int v8; // [rsp+44h] [rbp+24h]
    unsigned int v9; // [rsp+44h] [rbp+24h]
    unsigned int v10; // [rsp+44h] [rbp+24h]
    unsigned int v11; // [rsp+44h] [rbp+24h]
    unsigned int v12; // [rsp+44h] [rbp+24h]
    unsigned int v13; // [rsp+44h] [rbp+24h]
    unsigned int v14; // [rsp+44h] [rbp+24h]
    int v15; // [rsp+44h] [rbp+24h]
    int v16; // [rsp+44h] [rbp+24h]
    int v17; // [rsp+44h] [rbp+24h]
    unsigned int v18; // [rsp+64h] [rbp+44h]
    int v19; // [rsp+64h] [rbp+44h]
    unsigned int v20; // [rsp+64h] [rbp+44h]
    unsigned int v21; // [rsp+64h] [rbp+44h]
    unsigned int v22; // [rsp+64h] [rbp+44h]
    unsigned int v23; // [rsp+64h] [rbp+44h]
    int v24; // [rsp+64h] [rbp+44h]
    int v25; // [rsp+64h] [rbp+44h]
    int v26; // [rsp+64h] [rbp+44h]
    int v27; // [rsp+64h] [rbp+44h]
    unsigned int v28; // [rsp+64h] [rbp+44h]
    int v29; // [rsp+84h] [rbp+64h]
    int v30; // [rsp+84h] [rbp+64h]
    int v31; // [rsp+84h] [rbp+64h]
    int v32; // [rsp+84h] [rbp+64h]
    unsigned int v33; // [rsp+84h] [rbp+64h]
    unsigned int v34; // [rsp+84h] [rbp+64h]
    unsigned int v35; // [rsp+84h] [rbp+64h]
    int v36; // [rsp+84h] [rbp+64h]
    int v37; // [rsp+84h] [rbp+64h]
    int i; // [rsp+A4h] [rbp+84h]
    uint32_t* v41; // [rsp+1A8h] [rbp+188h]
    uint32_t dword_7FF748950100[64] = { 0x1010400,0x0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0x0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0x0,0x10004,0x10400,0x0,0x1010004 };
    uint32_t dword_7FF748950300[64] = { 0x208,0x8020200,0x0,0x8020008,0x8000200,0x0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0x0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0x0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200 };
    uint32_t dword_7FF748950500[64] = { 0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0x0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0x0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0x0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0x0,0x40080000,0x2080100,0x40000100 };
    uint32_t dword_7FF748950700[64] = { 0x200000,0x4200002,0x4000802,0x0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0x0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0x0,0x2,0x4200802,0x0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002 };
    uint32_t dword_7FF748950200[64] = { 0x80108020,0x80008000,0x8000,0x108020,0x100000,0x20,0x80100020,0x80008020,0x80000020,0x80108020,0x80108000,0x80000000,0x80008000,0x100000,0x20,0x80100020,0x108000,0x100020,0x80008020,0x0,0x80000000,0x8000,0x108020,0x80100000,0x100020,0x80000020,0x0,0x108000,0x8020,0x80108000,0x80100000,0x8020,0x0,0x108020,0x80100020,0x100000,0x80008020,0x80100000,0x80108000,0x8000,0x80100000,0x80008000,0x20,0x80108020,0x108020,0x20,0x8000,0x80000000,0x8020,0x80108000,0x100000,0x80000020,0x100020,0x80008020,0x80000020,0x100020,0x108000,0x0,0x80008000,0x8020,0x80000000,0x80100020,0x80108020,0x108000 };
    uint32_t dword_7FF748950400[64] = { 0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0x0,0x802000,0x802000,0x802081,0x81,0x0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0x0,0x0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080 };
    uint32_t dword_7FF748950600[64] = { 0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0x0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0x0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0x0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0x0,0x20404000,0x20000000,0x400010,0x20004010 };
    uint32_t dword_7FF748950800[64] = { 0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0x0,0x0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0x0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0x0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000 };
    v18 = a1[1];
    v5 = (v18 ^ (*a1 >> 4)) & 0xF0F0F0F;
    v19 = v5 ^ v18;
    v29 = (16 * v5) ^ *a1;
    v6 = (unsigned __int16)(v19 ^ ((v29 >> 16) & 0xffff));
    v20 = v6 ^ v19;
    v30 = (v6 << 16) ^ v29;
    v7 = (v30 ^ (v20 >> 2)) & 0x33333333;
    v31 = v7 ^ v30;
    v21 = (4 * v7) ^ v20;
    v8 = (v31 ^ (v21 >> 8)) & 0xFF00FF;
    v32 = v8 ^ v31;
    v22 = (((v8 << 8) ^ v21) >> 31) | (2 * ((v8 << 8) ^ v21));
    v9 = (v22 ^ v32) & 0xAAAAAAAA;
    v23 = v9 ^ v22;
    v33 = ((v9 ^ v32) >> 31) | (2 * (v9 ^ v32));
    for (i = 0; i < 8; ++i)
    {
        v10 = *a2 ^ ((v23 >> 4) | (v23 << 28));
        v41 = a2 + 1;
        v3 = dword_7FF748950100[((v10 >> 24) & 0xff) & 0x3F] | dword_7FF748950300[((v10 >> 16) & 0xffff) & 0x3F] | dword_7FF748950500[(v10 >> 8) & 0x3F] | dword_7FF748950700[v10 & 0x3F];
        v11 = *v41++ ^ v23;
        v33 ^= dword_7FF748950200[((v11 >> 24) & 0xff) & 0x3F] | dword_7FF748950400[((v11 >> 16) & 0xffff) & 0x3F] | dword_7FF748950600[(v11 >> 8) & 0x3F] | dword_7FF748950800[v11 & 0x3F] | v3;
        v12 = *v41++ ^ ((v33 >> 4) | (v33 << 28));
        v4 = dword_7FF748950100[((v12 >> 24) & 0xff) & 0x3F] | dword_7FF748950300[((v12 >> 16) & 0xffff) & 0x3F] | dword_7FF748950500[(v12 >> 8) & 0x3F] | dword_7FF748950700[v12 & 0x3F];
        v13 = *v41 ^ v33;
        a2 = v41 + 1;
        v23 ^= dword_7FF748950200[((v13 >> 24) & 0xff) & 0x3F] | dword_7FF748950400[((v13 >> 16) & 0xffff) & 0x3F] | dword_7FF748950600[(v13 >> 8) & 0x3F] | dword_7FF748950800[v13 & 0x3F] | v4;
    }
    v24 = (v23 >> 1) | (v23 << 31);
    v14 = (v24 ^ v33) & 0xAAAAAAAA;
    v25 = v14 ^ v24;
    v34 = ((v14 ^ v33) >> 1) | ((v14 ^ v33) << 31);
    v15 = (v25 ^ (v34 >> 8)) & 0xFF00FF;
    v26 = v15 ^ v25;
    v35 = (v15 << 8) ^ v34;
    v16 = (v26 ^ (v35 >> 2)) & 0x33333333;
    v27 = v16 ^ v26;
    v36 = (4 * v16) ^ v35;
    v17 = (unsigned __int16)(v36 ^ ((v27 >> 16) & 0xffff));
    v37 = v17 ^ v36;
    v28 = (v17 << 16) ^ v27;
    *a1 = (16 * ((v37 ^ (v28 >> 4)) & 0xF0F0F0F)) ^ v28;
    a1[1] = (v37 ^ (v28 >> 4)) & 0xF0F0F0F ^ v37;
}

void sub_7FF7489412DF(__int64 a1, uint8_t* a2)
{
    uint32_t* v8 = new uint32_t[2];
    int j; // [rsp+44h] [rbp+24h]
    uint8_t* v10; // [rsp+68h] [rbp+48h]
    v10 = a2;
    for (j = 0; j < 8; ++j)
    {
        v8[0] = (v10[0] << 24) | (v10[1] << 16) | (v10[2] << 8) | (v10[3]);
        v8[1] = (v10[4] << 24) | (v10[5] << 16) | (v10[6] << 8) | (v10[7]);
        func(v8, (uint32_t*)a1);
        v10[0] = (v8[0] >> 24) & 0xff; v10[1] = (v8[0] >> 16) & 0xff;
        v10[2] = (v8[0] >> 8) & 0xff; v10[3] = (v8[0]) & 0xff;
        v10[4] = (v8[1] >> 24) & 0xff; v10[5] = (v8[1] >> 16) & 0xff;
        v10[6] = (v8[1] >> 8) & 0xff; v10[7] = (v8[1]) & 0xff;
        v10 = (uint8_t*)((__int64)v10 + 8);
    }
}
void sub_7FF7489421B0(uint8_t* a4)
{
    char v13[] = "HZNUCTF{";
    char v12[280];
    sub_7FF748941249((_int64)v12, (_int64)v13);
    sub_7FF7489412DF((_int64)v12 + 128, a4);
}
int main()
{
    unsigned char e[] = { 0x84,0x8b,0x3,0x22,0x14,0xbe,0xdf,0x75,0xb3,0xd5,0x76,0x6f,0xcd,0x2a,0x5d,0xd7,0x4d,0xb2,0x5f,0x6,0x98,0x9d,0x3e,0xa8,0xf7,0x23,0xf2,0x8b,0xf2,0x54,0x65,0x7a,0x20,0xc0,0x87,0x55,0xd6,0x3b,0x46,0x3d,0xf7,0xb2,0x7a,0x9d,0xc2,0xcf,0x1a,0xae,0x16,0xc7,0x15,0x30,0x8e,0xfd,0x8f,0x9e,0xaa,0x39,0xab,0xfe,0x95,0xa7,0x1f,0xf1 };
    sub_7FF7489421B0((uint8_t*)e);
    printf("HZNUCTF{");
    for (int i = 0; i < 64; i = i + 4) {
        string tmp;
        tmp += e[i];
        tmp += e[i + 2];
        printf("%c", std::stoi(tmp, 0, 16));
        tmp = "";
        tmp += e[i + 1];
        tmp += e[i + 3];
        printf("%c", std::stoi(tmp, 0, 16));
    }
    printf("}");
}

这里代码写了很久都没跑对。中间也是请教了liv✌。最后才改出来,输出要转换成字符,再把字符转换成十六进制数据然后才是转换成输入 :(

index  :

webassembly的题,加密流程比较清晰,不算难,只是有点费时间。打开010,发现魔术头是大写的,改成小写的。用wabt工具包把wasm转成.c文件,再用gcc编译成.o,放到ida中分析(其实这里应该用ghidra,安装插件后效果比ida好很多,插件地址为2aaK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6F1L8X3g2G2L8X3&6W2L8#2)9J5c8X3N6Z5K9h3c8J5j5g2)9J5k6s2N6S2M7$3#2Q4x3X3c8H3L8s2g2Y4K9h3&6Q4x3V1k6Q4c8f1k6Q4b7V1y4Q4z5o6W2Q4c8e0y4Q4z5o6m8Q4z5o6t1`.

个人感觉wasm类似于基于堆栈的虚拟机,可以分析这里的代码

这里是开辟栈帧和恢复栈帧,a1类似于句柄,这里是指向一个储存文件(程序)信息的结构体。a1+16是栈指针,a1+32是载入文件的基址,类似于用mmap做了个映射,然后指定基址。在init里有初始化

初始化栈缓冲区,这里的store就是个存储操作,结合这里的栈指针就是push

第一步输入了密钥,这里检验密钥是否为TGCTF404

第一个函数对密钥逐位xor 0x51,scanf上面的函数是在压参数,向v11+80输入,这里的0x1007A是映射后的地址,实际上应该是base+offset,其中0x10000的实际地址是0x40780,在init中初始化

先校验输入长度是否为32,第一个函数进行了加密输入,并将结果写入+32,下面是一个for循环,执行4次,每次加密8字节,这里函数内部的逻辑都比较简单

值得注意的是f9有一个f15,向指定内存写入404-1,f9->f8里有一个f16,读取该内存的值,进行大数运算以及模运算,其实就是线性同余算法,产生伪随机数。不过可能是反编译的问题,直接跑这段代码和使用rand的结果是不同的(也就是在这里卡了很久,没想明白是怎么生成)

对拍写解密脚本就行了

#include <iostream>
using namespace std;

uint8_t sbox1[] = { 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x1,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x4,0xc7,0x23,0xc3,0x18,0x96,0x5,0x9a,0x7,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x9,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x0,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x2,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0xc,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0xb,0xdb,0xe0,0x32,0x3a,0xa,0x49,0x6,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x8,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x3,0xf6,0xe,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0xd,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0xf,0xb0,0x54,0xbb,0x16 };
uint8_t sbox2[] = { 0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x5,0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x4,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x6,0x99,0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0xb,0x43,0xed,0xcf,0xac,0x62,0xe4,0xb3,0x1c,0xa9,0xc9,0x8,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,0x47,0x7,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0xf,0x4b,0x70,0x56,0x9d,0x35,0x1e,0x24,0xe,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x1,0x21,0x78,0x87,0xd4,0x0,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x2,0xe7,0xa0,0xc4,0xc8,0x9e,0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0xd,0x53,0x4e,0x6f,0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x3,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,0xa,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,0x89,0x69,0x97,0x4a,0xc,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x9,0xc5,0x6e,0xc6,0x84,0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48 };
uint8_t sbox3[] = "TGCTF404";
uint8_t key[9] = "TGCTF404";
uint8_t encode[] = { 0x84,0x1c,0x6b,0xf7,0x49,0x22,0xd6,0x42,0x50,0x7b,0x42,0xf4,0x46,0xa9,0x83,0x62,0xd1,0x32,0x80,0x42,0x6a,0x10,0xa3,0xf2,0xe2,0xb8,0xb,0x76,0xb0,0xdc,0x2,0x51 };
void xor_key() {
    for (int i = 0; i < 8; i++) {
        key[i] ^= 0x51;
    }
}
void encrypt1(uint8_t* a) {
    uint64_t sum = 403;
    uint64_t v22;
    int v5, v6;
    uint8_t tmp;
    srand(sum);
    for (int i = 0; i < 31; i++) {
        v22 = rand();
        v5 = 32 - i;
        v6 = 0x7FFF / v5 + 1;
        tmp = a[v22 / v6 + i];
        a[v22 / v6 + i] = a[i];
        a[i] = tmp;
    }
}
void encrypt3(uint8_t a) {
    for (int i = 0; i < 256; i++) {
        sbox2[i] = sbox2[i] ^ a;
    }
}
void encrypt2(uint8_t* a) {
    uint8_t* tmp = a;
    for (int i = 0; i < 8; i++) {
        tmp = tmp + 4 * i;
        uint8_t ktmp = sbox1[16 * (key[i] >> 4) + key[i] & 0xF];
        encrypt3(ktmp);
        for (int j = 0; j < 4; j++) {
            uint8_t stmp = sbox2[((key[i] >> 4) + j) * 16 + (key[i] & 0xF) + j];
            tmp[j] ^= stmp;
            tmp[j] ^= sbox3[j];
        }
    }
}

void decrypt(uint8_t* a) {
    uint8_t* tmp = a;
    for (int i = 0; i < 8; i++) {
        uint8_t ktmp = sbox1[16 * (key[i] >> 4) + (key[i] & 0xF)];
        encrypt3(ktmp);
        for (int j = 0; j < 4; j++) {
            uint8_t stmp = sbox2[(((key[i] >> 4) + j) * 16 + (key[i] & 0xF) + j) & 0xFF];
            tmp[j] ^= stmp;
            tmp[j] ^= sbox3[j];
        }
        tmp = tmp + 4;
    }
    srand(404);
    uint8_t randlist[50];
    for (int i = 0; i < 32; i++) {
        int sum = rand();
        randlist[i] = sum / (0x7FFF / (32 - i) + 1) + i;
    }
    for (int i = 31; i >= 0; i--) {
        uint8_t t = a[randlist[i]];
        a[randlist[i]] = a[i];
        a[i] = t;
    }
}
int main()
{
    uint8_t* a = encode;
    xor_key();
    decrypt(a);
    printf("%.32s", encode);
}



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2025-4-16 14:37 被t0rch编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 42927
活跃值: (65707)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
图片没有了,请重新上传一份
2025-4-21 17:38
0
雪    币: 11
活跃值: (470)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
Editor 图片没有了,请重新上传一份
好的好的
2025-4-21 20:55
0
游客
登录 | 注册 方可回帖
返回