2024网鼎杯-青龙组-RE方向全部题解
想成为安卓高手 发表于 湖北 CTF 707浏览 · 2024-10-29 12:04

附件见最后

Reverse01

Flag: wdflag{8f1e0766197e1bc6d346fe66d346fe66}
把flag分为四段,进行不同的加密来比较密文
前两段

part1 = [0x70, 0xcc, 0x62, 0xca, 0x60, 0x6e, 0x6c, 0x6c]
flag1 = ""
for i in range(len(part1)):
    flag1 += chr(part1[i]//2)
print(flag1)

part2 = [0x69,0x56,0x45,0x17,0x7D,0x0D,0x11,0x52]
key = b"XorrLord"
flag2 = ""

for i in range(8):
    flag2 += chr(part2[i] ^ key[i])
print(flag2)

第三段,换表base64


第四段aes加密

reverse02

reverse02
Flag: wdflag{20cd6d3d-6de7-4894-b288-e27a5a68eb91}


找到check


再交叉引用check函数


接下来看so文件,
看到box,CK等,是魔改的sm4,在网上找到脚本,再修改魔改的部分
他的box盒经过xor7之后就得到原本的没魔改的box盒
修改了
static const uint32_t TBL_FIX_PARAMS[32] = {

0x00070E12, 0x1C232A36, 0x383F464A, 0x545B626E, 0x70777E82, 0x8C939AA6, 0xA8AFB6BA, 0xC4CBD2DE, 
0xE0E7EEF2, 0xFC030A16, 0x181F262A, 0x343B424E, 0x50575E62, 0x6C737A86, 0x888F969A, 0xA4ABB2BE, 
0xC0C7CED2, 0xDCE3EAF6, 0xF8FF060A, 0x141B222E, 0x30373E42, 0x4C535A66, 0x686F767A, 0x848B929E, 
0xA0A7AEB2, 0xBCC3CAD6, 0xD8DFE6EA, 0xF4FB020E, 0x10171E22, 0x2C333A46, 0x484F565A, 0x646B727E

};这一部分和ulKeyList[i + 4] = ulKeyList[i] ^ func_key(ulKeyList[i + 1] ^ ulKeyList[i + 2] ^ ulKeyList[i + 3] ^ TBL_FIX_PARAMS[i]^7)这一部分,再输入他修改过后的key解出就是flag
sm4.h

// sm4.h文件//
#include "stdlib.h"
#include "string.h"
#ifndef UDP_SM4_LED_DEMO1_SM4_H
#define UDP_SM4_LED_DEMO1_SM4_H
typedef   signed           char int8_t;
typedef   signed short     int int16_t;
typedef   signed           int int32_t;
typedef unsigned           char uint8_t;
typedef unsigned short     int uint16_t;
typedef unsigned           int uint32_t;
void four_uCh2uLong(uint8_t *in, uint32_t *out);        //4字节无符号数组转无符号long型
void uLong2four_uCh(uint32_t in, uint8_t *out);         //无符号long型转4字节无符号数组
uint32_t move(uint32_t data, uint8_t length);           //循环左移
void print_hex(uint8_t *data, uint32_t len);            //无符号字符数组转16进制打印
extern uint8_t key[] ;       //定义16字节的密钥
/******************************定义系统参数FK的取值****************************************/
static const uint32_t TBL_SYS_PARAMS[4] = {
        0xa3b1bac6,
        0x56aa3350,
        0x677d9197,
        0xb27022dc
};

/******************************定义固定参数CK的取值****************************************/
static const uint32_t TBL_FIX_PARAMS[32] = {

    0x00070E12, 0x1C232A36, 0x383F464A, 0x545B626E, 0x70777E82, 0x8C939AA6, 0xA8AFB6BA, 0xC4CBD2DE, 
    0xE0E7EEF2, 0xFC030A16, 0x181F262A, 0x343B424E, 0x50575E62, 0x6C737A86, 0x888F969A, 0xA4ABB2BE, 
    0xC0C7CED2, 0xDCE3EAF6, 0xF8FF060A, 0x141B222E, 0x30373E42, 0x4C535A66, 0x686F767A, 0x848B929E, 
    0xA0A7AEB2, 0xBCC3CAD6, 0xD8DFE6EA, 0xF4FB020E, 0x10171E22, 0x2C333A46, 0x484F565A, 0x646B727E
};

/******************************SBox参数列表****************************************/
static const uint8_t TBL_SBOX[256] = {

        0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
        0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
        0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
        0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
        0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
        0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
        0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
        0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,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,0x0d,0x53,0x4e,0x6f,
        0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
        0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
        0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
        0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
        0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48
};

#include <stdio.h>

//4字节无符号数组转无符号long型
void four_uCh2uLong(uint8_t *in, uint32_t *out)
{
    int i = 0;
    *out = 0;
    for (i = 0; i < 4; i++)
        *out = ((uint32_t)in[i] << (24 - i * 8)) ^ *out;
}

//无符号long型转4字节无符号数组
void uLong2four_uCh(uint32_t in, uint8_t *out)
{
    int i = 0;
    //从32位unsigned long的高位开始取
    for (i = 0; i < 4; i++)
        *(out + i) = (uint32_t)(in >> (24 - i * 8));
}

//循环左移
uint32_t move(uint32_t data, uint8_t length)
{
    uint32_t result = 0;
    result = (data << length) ^ (data >> (32 - length));

    return result;
}

//无符号字符数组转16进制打印
void print_hex(uint8_t *data, uint32_t len)
{
    uint32_t i = 0;
    char alTmp[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
    for (i = 0; i < len; i++)
    {
        printf("%c", alTmp[data[i] / 16]);
        printf("%c", alTmp[data[i] % 16]);
        putchar(' ');
    }
    putchar('\n');
}
uint8_t key[16] = {   65, 49, 49, 50, 50, 51, 53, 55, 0x34, 0x36, 0x38, 0x39, 0x39, 0x30, 0x30, 0x5a };       //定义16字节的密钥

#ifdef CBC_MODE
uint8_t IV[16] = {0};       //初始话向量IV
#endif

//秘钥处理函数,先使用Sbox进行非线性变化,再将线性变换L置换为L'
uint32_t func_key(uint32_t input)
{
    int i = 0;
    uint32_t ulTmp = 0;
    uint8_t ucIndexList[4] = { 0 };
    uint8_t ucSboxValueList[4] = { 0 };
    uLong2four_uCh(input, ucIndexList);
    for (i = 0; i < 4; i++)
    {
        ucSboxValueList[i] = TBL_SBOX[ucIndexList[i]];
    }
    four_uCh2uLong(ucSboxValueList, &ulTmp);
    ulTmp = ulTmp ^ move(ulTmp, 13) ^ move(ulTmp, 23);

    return ulTmp;
}

//加解密数据处理函数,先使用Sbox进行非线性变化,再进行线性变换L
uint32_t func_data(uint32_t input)
{
    int i = 0;
    uint32_t ulTmp = 0;
    uint8_t ucIndexList[4] = { 0 };
    uint8_t ucSboxValueList[4] = { 0 };
    uLong2four_uCh(input, ucIndexList);
    for (i = 0; i < 4; i++)
    {
        ucSboxValueList[i] = TBL_SBOX[ucIndexList[i]];
    }
    four_uCh2uLong(ucSboxValueList, &ulTmp);
    ulTmp = ulTmp ^ move(ulTmp, 2) ^ move(ulTmp, 10) ^ move(ulTmp, 18) ^ move(ulTmp, 24);

    return ulTmp;
}

//加密函数(可以加密任意长度数据,16字节为一次循环,不足部分补0凑齐16字节的整数倍)
//len:数据长度(任意长度数据) key:密钥(16字节) input:输入的原始数据 output:加密后输出数据
void  encode_fun(uint32_t len,uint8_t *key, uint8_t *input, uint32_t * output_len, uint8_t *output)
{
    int i = 0,j=0;
    uint32_t nSrcLen = 0;

#ifdef CBC_MODE
    uint8_t  IV_new[16] = {0};
    for(i=0; i<16; i++)
    {
        IV_new[i] = IV[i];
    }
#endif

    if(len%16)         //将不足16字节补0凑齐16的整数倍
    {
        nSrcLen = len+(16-len%16);
    }
    else
    {
        nSrcLen = len;
    }
    * output_len = nSrcLen;

    uint8_t *p = (uint8_t *)malloc(nSrcLen);      //定义一个缓存区,
    memset(p, 0, nSrcLen);
    memcpy(p, input, nSrcLen);                    //将输入数据存放在p缓存区

    uint32_t ulKeyTmpList[4] = { 0 };   //存储密钥的u32数据
    uint32_t ulKeyList[36] = { 0 };     //用于密钥扩展算法与系统参数FK运算后的结果存储
    uint32_t ulDataList[36] = { 0 };    //用于存放加密数据

    /***************************开始生成子秘钥********************************************/
    four_uCh2uLong(key, &(ulKeyTmpList[0]));
    four_uCh2uLong(key + 4, &(ulKeyTmpList[1]));
    four_uCh2uLong(key + 8, &(ulKeyTmpList[2]));
    four_uCh2uLong(key + 12, &(ulKeyTmpList[3]));

    ulKeyList[0] = ulKeyTmpList[0] ^ TBL_SYS_PARAMS[0];
    ulKeyList[1] = ulKeyTmpList[1] ^ TBL_SYS_PARAMS[1];
    ulKeyList[2] = ulKeyTmpList[2] ^ TBL_SYS_PARAMS[2];
    ulKeyList[3] = ulKeyTmpList[3] ^ TBL_SYS_PARAMS[3];

    for (i = 0; i < 32; i++)             //32次循环迭代运算
    {
        //5-36为32个子秘钥
        ulKeyList[i + 4] = ulKeyList[i] ^ func_key(ulKeyList[i + 1] ^ ulKeyList[i + 2] ^ ulKeyList[i + 3] ^ TBL_FIX_PARAMS[i]^7);
    }

    for (j = 0; j < len / 16 + ((len % 16) ? 1:0); j++)  //进行循环加密,并将加密后数据保存(可以看出此处是以16字节为一次加密,进行循环,即若16字节则进行一次,17字节补0至32字节后进行加密两次,以此类推)
    {
#ifdef CBC_MODE
        for(i = 0; i < 16; i++)
        {
            *(p + 16 * j+ i) = *(p + 16 * j + i) ^ IV_new[i];
        }
#endif

        /*开始处理加密数据*/
        four_uCh2uLong(p + 16 * j, &(ulDataList[0]));
        four_uCh2uLong(p + 16 * j + 4, &(ulDataList[1]));
        four_uCh2uLong(p + 16 * j + 8, &(ulDataList[2]));
        four_uCh2uLong(p + 16 * j + 12, &(ulDataList[3]));
        //加密
        for (i = 0; i < 32; i++)
        {
            ulDataList[i + 4] = ulDataList[i] ^ func_data(ulDataList[i + 1] ^ ulDataList[i + 2] ^ ulDataList[i + 3] ^ ulKeyList[i + 4]);
        }
        /*将加密后数据输出*/
        uLong2four_uCh(ulDataList[35], output + 16 * j);
        uLong2four_uCh(ulDataList[34], output + 16 * j + 4);
        uLong2four_uCh(ulDataList[33], output + 16 * j + 8);
        uLong2four_uCh(ulDataList[32], output + 16 * j + 12);

#ifdef CBC_MODE
        for(i = 0; i < 16; i++)
        {
            IV_new[i] = *(output + 16 * j + i) ;
        }
#endif
    }

    free(p);

}

//解密函数(与加密函数基本一致,只是秘钥使用的顺序不同,即把钥匙反着用就是解密)
//len:数据长度 key:密钥 input:输入的加密后数据 output:输出的解密后数据
void decode_fun(uint32_t len,uint8_t *key, uint8_t *input, uint8_t *output)
{
    int i = 0,j=0;
    uint32_t ulKeyTmpList[4] = { 0 };//存储密钥的u32数据
    uint32_t ulKeyList[36] = { 0 };  //用于密钥扩展算法与系统参数FK运算后的结果存储
    uint32_t ulDataList[36] = { 0 }; //用于存放加密数据

#ifdef CBC_MODE
    uint8_t  IV_new[16] = {0};
    for(i=0; i<16; i++)
    {
        IV_new[i] = IV[i];
    }
#endif

    /*开始生成子秘钥*/
    four_uCh2uLong(key, &(ulKeyTmpList[0]));
    four_uCh2uLong(key + 4, &(ulKeyTmpList[1]));
    four_uCh2uLong(key + 8, &(ulKeyTmpList[2]));
    four_uCh2uLong(key + 12, &(ulKeyTmpList[3]));

    ulKeyList[0] = ulKeyTmpList[0] ^ TBL_SYS_PARAMS[0];
    ulKeyList[1] = ulKeyTmpList[1] ^ TBL_SYS_PARAMS[1];
    ulKeyList[2] = ulKeyTmpList[2] ^ TBL_SYS_PARAMS[2];
    ulKeyList[3] = ulKeyTmpList[3] ^ TBL_SYS_PARAMS[3];

    for (i = 0; i < 32; i++)             //32次循环迭代运算
    {
        //5-36为32个子秘钥
        ulKeyList[i + 4] = ulKeyList[i] ^ func_key(ulKeyList[i + 1] ^ ulKeyList[i + 2] ^ ulKeyList[i + 3] ^ TBL_FIX_PARAMS[i]^7);
    }
    /*生成32轮32位长子秘钥结束*/

    for (j = 0; j < len / 16; j++)  //进行循环加密,并将加密后数据保存
    {

        /*开始处理解密数据*/
        four_uCh2uLong(input + 16 * j, &(ulDataList[0]));
        four_uCh2uLong(input + 16 * j + 4, &(ulDataList[1]));
        four_uCh2uLong(input + 16 * j + 8, &(ulDataList[2]));
        four_uCh2uLong(input + 16 * j + 12, &(ulDataList[3]));

        //解密
        for (i = 0; i < 32; i++)
        {
            ulDataList[i + 4] = ulDataList[i] ^ func_data(ulDataList[i + 1] ^ ulDataList[i + 2] ^ ulDataList[i + 3] ^ ulKeyList[35 - i]);//与加密唯一不同的就是轮密钥的使用顺序
        }

        /*将解密后数据输出*/
        uLong2four_uCh(ulDataList[35], output + 16 * j);
        uLong2four_uCh(ulDataList[34], output + 16 * j + 4);
        uLong2four_uCh(ulDataList[33], output + 16 * j + 8);
        uLong2four_uCh(ulDataList[32], output + 16 * j + 12);

#ifdef CBC_MODE
        for(i = 0; i < 16; i++)
        {
            *(output + 16 * j + i) = *(output + 16 * j + i) ^ IV_new[i];
        }

        for(i = 0; i < 16; i++)
        {
            IV_new[i] = *(input + 16 * j + i) ;
        }
#endif

    }
}
#endif //UDP_SM4_LED_DEMO1_SM4_H

sm4.c

#include "stdlib.h"
#include "sm4.h"
#include <stdio.h>

int main(void)
{
    uint8_t buffer[]={0x06, 0x80, 0x8A, 0x6F, 0x3B, 0xA8, 0xDD, 0xD4, 0x10, 0x4A, 0x3C, 0xAC, 0xF7, 0x74, 0x9A, 0x4C, 0xC6, 0x41, 0xD5, 0xDC, 0xCA, 0x2F, 0xF0, 0xBF, 0xFB, 0xD6, 0x76, 0x7B, 0xED, 0x67, 0xD0, 0xA7, 0xB3, 0xD9, 0x26, 0x81, 0x23, 0xFE, 0xEB, 0xF5, 0x45, 0x09, 0x97, 0x62, 0xC0, 0x85, 0x8B, 0xF0};//原始输入数据(测试用);
    uint8_t i,len;
    uint32_t encode_len;
    uint8_t encode_Result[50] = { 0 };    //定义加密输出缓存区
    uint8_t decode_Result[50] = { 0 };    //定义解密输出缓存区
    //数据加密

    buffer[sizeof(buffer)] = 0;
    // encode_fun(sizeof(buffer),key, buffer, &encode_len, encode_Result);
    // printf("加密后数据是:\n");
    // printf("%d\n", strlen(encode_Result));
    // for (i = 0; i < encode_len ; i++)
    // printf("%02x ", *(encode_Result + i));
    // printf("\n");
    // /*注意:此处解密函数的输入数据长度应为扩展后的数据长度,即必为16的倍数*/
    decode_fun(48, key, buffer, decode_Result);      //数据解密
    printf("\n");
    for (i = 0; i < strlen(decode_Result); i++)
        printf("%02x ", *(decode_Result + i));
   // printf("%d\n", strlen(decode_Result));
}

得到32 30 63 64 36 64 33 64 2d 36 64 65 37 2d 34 38 39 34 2d 62 32 38 38 2d 65 32 37 61 35 61 36 38 65 62 39 31

附件:
0 条评论
某人
表情
可输入 255
目录