LOADING

加载过慢请开启缓存 浏览器默认开启

2024浙江省省赛决赛 Writeup

reverse1

两个rc4加密,一个是原版另一个是被修改的版本。加密过程就是用key1先加密key,再用加密的key去加密flag。所以按照这个逻辑来逆向即可解密。rc4原版加密是对称加密,而修改版的rc4只要把减号改为加号就行。

在比赛时这题并没有写出来,脚本最后的结果一直是乱码,后面复盘时发现了一个关键的东西。当盒子是char类型时,只要盒子里的元素被当作下标时,就要把这个下标转成(unsigned char),如果不转的话在后面的下标就是一个负数。当盒子是unsigned char类型时,(box[v5] + box[v6])作为下标时要转化为(unsigned char),如果不转化的话(box[v5] + box[v6])就有可能会超过下标255。所以box[(unsigned char)(box[v5] + box[v6])]实际上就是box[(box[v5] + box[v6])%256]。

  • 所以在写题中一定要注意下标的数值是否合规。
#include <stdio.h>
#include <string.h>

char input[32] = {
    0x4E, 0x47, 0x38, 0x47, 0x62, 0x0A, 0x79, 0x6A, 0x03, 0x66, 0xC0, 0x69, 0x8D, 0x1C, 0x84, 0x0F,
    0x54, 0x4A, 0x3B, 0x08, 0xE3, 0x30, 0x4F, 0xB9, 0x6C, 0xAB, 0x36, 0x24, 0x52, 0x81, 0xCF, 0x00
};
char key[100] = "ban_debug!";
char key1[] = "keykey";
unsigned char box[256];

int getbox(unsigned char*box, char*key,int keylen) {
    char v4;
    int v6 = 0;
    int v8[256];
    memset(v8, 0, 0x400uLL);
    for (int i = 0; i <= 255; ++i)
    {
        box[i] = i;
        v8[i] = (unsigned char)key[i % keylen];
    }
    v6 = 0;
    for (int j = 0; j <= 255; ++j)
    {
       
        v6 = (v8[j] + v6 + box[j]) % 256;
        v4 = box[j];
        box[j] = box[v6];
        box[v6] = v4;
    }
    return 0;
}


int dec1(unsigned char*box, unsigned char* input,int len) {
    char v4; 
    int v5; 
    int v6; 
    int i; 

    v5 = 0;
    v6 = 0;
    for (i = 0; ; ++i)
    {
        if (len <= i)
            break;
        v5 = (v5 + 1) % 256;
        v6 = (v6 + box[v5]) % 256;
        v4 = box[v5];
        box[v5] = box[v6];
        box[v6] = v4;
        input[i] ^= box[(unsigned char)(box[v5] + box[v6])];
    }
    return 0;
}

int dec2(unsigned char* box,char* input, int len) {
    char v4;
    int v5; 
    int v6;
    int i;

    v5 = 0;
    v6 = 0;
    for (i = 0; ; ++i)
    {
        if (len <= i)
            break;
        v5 = (v5 + 1) % 256;
        v6 = (v6 + box[v5]) % 256;
        v4 = box[v5];
        box[v5] = box[v6];
        box[v6] = v4;
        input[i] += box[(unsigned char)(box[v5] + box[v6])];
    }
    return 0;
}


int main() {

    getbox(box, key1, strlen(key1));
    dec1(box, (unsigned char*)key, strlen(key));
    memset(box, 0, sizeof(box));
    getbox(box, key, strlen(key));
    dec2(box, input, 32);
    for (int i = 0; i < 31; i++) {
        printf("%c", input[i]);
    }
   
    //puts(input);
    
}

reverse2

用010editer把ABC全部修改为UPX,ida分析后就是一个base64加密函数,直接就可以看到明文和码表,直接解密就得flag