强网拟态国际精英防御赛 复盘 baby_re 异常 + 魔改AES
md,这道题不难的,就是被放出来的比较完,没细看
一、分析程序
首先发现该程序存在tls回调函数
可以看到,程序设置的VEH异常和顶层接管异常,后面的除0操作用于触发异常
其中VEH异常修改了s_box盒
观察main函数逻辑,由于该程序是c++编写的,逻辑有点奇怪,但不影响分析,中间这一串即为密钥
根据特征可发现这是一个AES加密,其有三处魔改点
1、s_box盒
这在tls回调函数中已经体现了
2、addRoundKey 轮密钥加
黑盒测试可以发现,作者对论密钥加的结果进行了转置
3、storeStateArray
在第一轮加密结束后,原AES加密会对得到的密文进行转置,而该程序没有此操作
这里有个坑,我们不能去修改storeStateArray 函数,而是需要手动把密文转置!!!
二、程序流程
密文被分开成两部分,第一部分密文进行AES加密操作的key值题目已经给出,第二部分密文进行AES加密的key值是第一部分加密后的密文异或第一部分的key的结果
最后两组密文连接起来和题目中的cip相比较
三、exp
#include <stdint.h> #include <stdio.h> #include <string.h> typedef struct { uint32_t eK[44], dK[44]; // encKey, decKey int Nr; // 10 rounds }AesKey; #define BLOCKSIZE 16 //AES-128分组长度为16字节 // uint8_t y[4] -> uint32_t x #define LOAD32H(x, y) \ do { (x) = ((uint32_t)((y)[0] & 0xff)<<24) | ((uint32_t)((y)[1] & 0xff)<<16) | \ ((uint32_t)((y)[2] & 0xff)<<8) | ((uint32_t)((y)[3] & 0xff));} while(0) // uint32_t x -> uint8_t y[4] #define STORE32H(x, y) \ do { (y)[0] = (uint8_t)(((x)>>24) & 0xff); (y)[1] = (uint8_t)(((x)>>16) & 0xff); \ (y)[2] = (uint8_t)(((x)>>8) & 0xff); (y)[3] = (uint8_t)((x) & 0xff); } while(0) // 从uint32_t x中提取从低位开始的第n个字节 #define BYTE(x, n) (((x) >> (8 * (n))) & 0xff) /* used for keyExpansion */ // 字节替换然后循环左移1位 #define MIX(x) (((S[BYTE(x, 2)] << 24) & 0xff000000) ^ ((S[BYTE(x, 1)] << 16) & 0xff0000) ^ \ ((S[BYTE(x, 0)] << 8) & 0xff00) ^ (S[BYTE(x, 3)] & 0xff)) // uint32_t x循环左移n位 #define ROF32(x, n) (((x) << (n)) | ((x) >> (32-(n)))) // uint32_t x循环右移n位 #define ROR32(x, n) (((x) >> (n)) | ((x) << (32-(n)))) /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ // AES-128轮常量 static const uint32_t rcon[10] = { 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL }; // S盒 unsigned char S[256] = { 0x00000077, 0x00000068, 0x00000063, 0x0000006F, 0x000000E6, 0x0000007F, 0x0000007B, 0x000000D1, 0x00000024, 0x00000015, 0x00000073, 0x0000003F, 0x000000EA, 0x000000C3, 0x000000BF, 0x00000062, 0x000000DE, 0x00000096, 0x000000DD, 0x00000069, 0x000000EE, 0x0000004D, 0x00000053, 0x000000E4, 0x000000B9, 0x000000C0, 0x000000B6, 0x000000BB, 0x00000088, 0x000000B0, 0x00000066, 0x000000D4, 0x000000A3, 0x000000E9, 0x00000087, 0x00000032, 0x00000022, 0x0000002B, 0x000000E3, 0x000000D8, 0x00000020, 0x000000B1, 0x000000F1, 0x000000E5, 0x00000065, 0x000000CC, 0x00000025, 0x00000001, 0x00000010, 0x000000D3, 0x00000037, 0x000000D7, 0x0000000C, 0x00000082, 0x00000011, 0x0000008E, 0x00000013, 0x00000006, 0x00000094, 0x000000F6, 0x000000FF, 0x00000033, 0x000000A6, 0x00000061, 0x0000001D, 0x00000097, 0x00000038, 0x0000000E, 0x0000000F, 0x0000007A, 0x0000004E, 0x000000B4, 0x00000046, 0x0000002F, 0x000000C2, 0x000000A7, 0x0000003D, 0x000000F7, 0x0000003B, 0x00000090, 0x00000047, 0x000000C5, 0x00000014, 0x000000F9, 0x00000034, 0x000000E8, 0x000000A5, 0x0000004F, 0x0000007E, 0x000000DF, 0x000000AA, 0x0000002D, 0x0000005E, 0x00000058, 0x0000004C, 0x000000DB, 0x000000C4, 0x000000FB, 0x000000BE, 0x000000EF, 0x00000057, 0x00000059, 0x00000027, 0x00000091, 0x00000051, 0x000000ED, 0x00000016, 0x0000006B, 0x00000044, 0x00000028, 0x0000008B, 0x000000BC, 0x00000045, 0x000000B7, 0x00000054, 0x0000009B, 0x00000086, 0x00000089, 0x0000002C, 0x000000E1, 0x000000A8, 0x000000A2, 0x000000CE, 0x00000035, 0x00000004, 0x000000EB, 0x000000E7, 0x000000C6, 0x000000D9, 0x00000018, 0x00000007, 0x000000F8, 0x0000004B, 0x00000083, 0x00000050, 0x00000003, 0x000000D0, 0x000000B3, 0x0000006A, 0x00000029, 0x00000070, 0x00000049, 0x0000000D, 0x00000067, 0x00000074, 0x00000095, 0x0000005B, 0x000000C8, 0x00000036, 0x0000003E, 0x00000084, 0x0000009C, 0x00000052, 0x000000FA, 0x000000AC, 0x00000000, 0x000000CA, 0x0000004A, 0x0000001F, 0x000000CF, 0x000000F4, 0x00000026, 0x0000002E, 0x0000001E, 0x0000005D, 0x00000012, 0x00000030, 0x00000048, 0x000000D6, 0x000000C7, 0x000000B8, 0x00000076, 0x00000085, 0x00000081, 0x000000F0, 0x0000006D, 0x000000F3, 0x000000DC, 0x00000023, 0x00000079, 0x00000099, 0x000000C1, 0x0000005A, 0x000000BD, 0x00000078, 0x00000042, 0x000000E0, 0x000000FE, 0x00000071, 0x0000006E, 0x000000BA, 0x0000001C, 0x000000AE, 0x0000006C, 0x00000031, 0x0000003A, 0x00000008, 0x000000B2, 0x000000A0, 0x000000D2, 0x000000FC, 0x000000C9, 0x00000060, 0x0000000B, 0x0000005F, 0x000000A9, 0x0000009F, 0x0000009E, 0x00000064, 0x0000002A, 0x000000A1, 0x00000072, 0x0000005C, 0x00000017, 0x000000E2, 0x0000001A, 0x00000075, 0x00000021, 0x00000043, 0x000000AD, 0x00000092, 0x000000D5, 0x00000009, 0x0000008A, 0x000000F5, 0x000000EC, 0x0000008C, 0x00000005, 0x0000007D, 0x000000CD, 0x0000009A, 0x00000080, 0x0000008F, 0x0000000A, 0x00000093, 0x000000FD, 0x000000DA, 0x00000041, 0x0000003C, 0x000000CB, 0x00000098, 0x000000B5, 0x0000009D, 0x00000019, 0x000000AB, 0x000000F2, 0x00000056, 0x0000007C, 0x00000055, 0x0000008D, 0x00000039, 0x0000001B, 0x000000A4, 0x00000040, 0x000000AF, 0x00000002 }; //逆S盒 unsigned char inv_S[256] = { 0x9B, 0x2F, 0xFF, 0x87, 0x7C, 0xE3, 0x39, 0x82, 0xC4, 0xDE, 0xE9, 0xCB, 0x34, 0x8E, 0x43, 0x44, 0x30, 0x36, 0xA5, 0x38, 0x52, 0x09, 0x6A, 0xD5, 0x81, 0xF3, 0xD7, 0xFB, 0xBF, 0x40, 0xA3, 0x9E, 0x28, 0xD9, 0x24, 0xB2, 0x08, 0x2E, 0xA1, 0x66, 0x6D, 0x8B, 0xD1, 0x25, 0x76, 0x5B, 0xA2, 0x49, 0xA6, 0xC2, 0x23, 0x3D, 0x54, 0x7B, 0x94, 0x32, 0x42, 0xFA, 0xC3, 0x4E, 0xEE, 0x4C, 0x95, 0x0B, 0xFD, 0xED, 0xB9, 0xDA, 0x6C, 0x70, 0x48, 0x50, 0xA7, 0x8D, 0x9D, 0x84, 0x5E, 0x15, 0x46, 0x57, 0x86, 0x68, 0x98, 0x16, 0x72, 0xF8, 0xF6, 0x64, 0x5D, 0x65, 0xB6, 0x92, 0xD4, 0xA4, 0x5C, 0xCC, 0xCA, 0x3F, 0x0F, 0x02, 0xD0, 0x2C, 0x1E, 0x8F, 0x01, 0x13, 0x8A, 0x6B, 0xC1, 0xAF, 0xBD, 0x03, 0x8C, 0xBC, 0xD3, 0x0A, 0x90, 0xD8, 0xAB, 0x00, 0xB8, 0xB3, 0x45, 0x06, 0xF7, 0xE4, 0x58, 0x05, 0xE7, 0xAD, 0x35, 0x85, 0x96, 0xAC, 0x74, 0x22, 0x1C, 0x75, 0xDF, 0x6E, 0xE2, 0xF9, 0x37, 0xE8, 0x4F, 0x67, 0xDC, 0xEA, 0x3A, 0x91, 0x11, 0x41, 0xF0, 0xB4, 0xE6, 0x73, 0x97, 0xF2, 0xCF, 0xCE, 0xC6, 0xD2, 0x79, 0x20, 0xFC, 0x56, 0x3E, 0x4B, 0x78, 0xCD, 0x5A, 0xF4, 0x9A, 0xDB, 0xC0, 0xFE, 0x1D, 0x29, 0xC5, 0x89, 0x47, 0xF1, 0x1A, 0x71, 0xAA, 0x18, 0xBE, 0x1B, 0x6F, 0xB7, 0x62, 0x0E, 0x19, 0xB5, 0x4A, 0x0D, 0x60, 0x51, 0x7F, 0xA9, 0x93, 0xC9, 0x9C, 0xEF, 0x2D, 0xE5, 0x7A, 0x9F, 0x88, 0x07, 0xC7, 0x31, 0x1F, 0xDD, 0xA8, 0x33, 0x27, 0x80, 0xEC, 0x5F, 0xB1, 0x12, 0x10, 0x59, 0xBA, 0x77, 0xD6, 0x26, 0x17, 0x2B, 0x04, 0x7E, 0x55, 0x21, 0x0C, 0x7D, 0xE1, 0x69, 0x14, 0x63, 0xAE, 0x2A, 0xF5, 0xB0, 0xA0, 0xE0, 0x3B, 0x4D, 0x83, 0x53, 0x99, 0x61, 0xC8, 0xEB, 0xBB, 0x3C }; /* copy in[16] to state[4][4] */ int loadStateArray(uint8_t(*state)[4], const uint8_t* in) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { state[j][i] = *in++; } } return 0; } /* copy state[4][4] to out[16] */ int storeStateArray(uint8_t(*state)[4], uint8_t* out) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { *out++ = state[i][j]; } } return 0; } //秘钥扩展 int keyExpansion(const uint8_t* key, uint32_t keyLen, AesKey* aesKey) { if (NULL == key || NULL == aesKey) { printf("keyExpansion param is NULL\n"); return -1; } if (keyLen != 16) { printf("keyExpansion keyLen = %d, Not support.\n", keyLen); return -1; } uint32_t* w = aesKey->eK; //加密秘钥 uint32_t* v = aesKey->dK; //解密秘钥 /* keyLen is 16 Bytes, generate uint32_t W[44]. */ /* W[0-3] */ for (int i = 0; i < 4; ++i) { LOAD32H(w[i], key + 4 * i); } /* W[4-43] */ for (int i = 0; i < 10; ++i) { w[4] = w[0] ^ MIX(w[3]) ^ rcon[i]; w[5] = w[1] ^ w[4]; w[6] = w[2] ^ w[5]; w[7] = w[3] ^ w[6]; w += 4; } // uint32_t* ww = aesKey->eK; // for(int i = 0;i<=43;i++){ // if (i % 15 == 0){ // printf("\n"); // } // printf("0x%x ",ww[i] ); // } w = aesKey->eK + 44 - 4; //解密秘钥矩阵为加密秘钥矩阵的倒序,方便使用,把ek的11个矩阵倒序排列分配给dk作为解密秘钥 //即dk[0-3]=ek[41-44], dk[4-7]=ek[37-40]... dk[41-44]=ek[0-3] for (int j = 0; j < 11; ++j) { for (int i = 0; i < 4; ++i) { v[i] = w[i]; } w -= 4; v += 4; } return 0; } // 轮秘钥加 int addRoundKey(uint8_t(*state)[4], const uint32_t* key) { uint8_t k[4][4]; /* i: row, j: col */ for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { k[i][j] = (uint8_t)BYTE(key[j], 3 - i); /* 把 uint32 key[4] 先转换为矩阵 uint8 k[4][4] */ state[i][j] ^= k[i][j]; } } return 0; } //字节替换 int subBytes(uint8_t(*state)[4]) { /* i: row, j: col */ for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { state[i][j] = S[state[i][j]]; //直接使用原始字节作为S盒数据下标 } } return 0; } //逆字节替换 int invSubBytes(uint8_t(*state)[4]) { /* i: row, j: col */ for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { state[i][j] = inv_S[state[i][j]]; } } return 0; } //行移位 int shiftRows(uint8_t(*state)[4]) { uint32_t block[4] = { 0 }; /* i: row */ for (int i = 0; i < 4; ++i) { //便于行循环移位,先把一行4字节拼成uint_32结构,移位后再转成独立的4个字节uint8_t LOAD32H(block[i], state[i]); block[i] = ROF32(block[i], 8 * i); STORE32H(block[i], state[i]); } return 0; } //逆行移位 int invShiftRows(uint8_t(*state)[4]) { uint32_t block[4] = { 0 }; /* i: row */ for (int i = 0; i < 4; ++i) { LOAD32H(block[i], state[i]); block[i] = ROR32(block[i], 8 * i); STORE32H(block[i], state[i]); } return 0; } /* Galois Field (256) Multiplication of two Bytes */ // 两字节的伽罗华域乘法运算 uint8_t GMul(uint8_t u, uint8_t v) { uint8_t p = 0; for (int i = 0; i < 8; ++i) { if (u & 0x01) { // p ^= v; } int flag = (v & 0x80); v <<= 1; if (flag) { v ^= 0x1B; /* x^8 + x^4 + x^3 + x + 1 */ } u >>= 1; } return p; } // 列混合 int mixColumns(uint8_t(*state)[4]) { uint8_t tmp[4][4]; uint8_t M[4][4] = { {0x02, 0x03, 0x01, 0x01}, {0x01, 0x02, 0x03, 0x01}, {0x01, 0x01, 0x02, 0x03}, {0x03, 0x01, 0x01, 0x02} }; /* copy state[4][4] to tmp[4][4] */ for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { tmp[i][j] = state[i][j]; } } for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { //伽罗华域加法和乘法 // printf("0x%x = 0x%x ^ 0x%x ^ 0x%x ^ 0x%x\n",state[j][0],GMul(M[i][0], tmp[0][j]), GMul(M[i][1], tmp[1][j]),GMul(M[i][2], tmp[2][j]),GMul(M[i][3], tmp[3][j])); // getchar(); state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j]) ^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]); //魔改: // state[j][i] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j]) // ^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]); } } return 0; } // 逆列混合 int invMixColumns(uint8_t(*state)[4]) { uint8_t tmp[4][4]; uint8_t M[4][4] = { {0x0E, 0x0B, 0x0D, 0x09}, {0x09, 0x0E, 0x0B, 0x0D}, {0x0D, 0x09, 0x0E, 0x0B}, {0x0B, 0x0D, 0x09, 0x0E} }; //使用列混合矩阵的逆矩阵 /* copy state[4][4] to tmp[4][4] */ for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { tmp[i][j] = state[i][j]; } } for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j]) ^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]); } } return 0; } // AES-128加密接口,输入key应为16字节长度,输入长度应该是16字节整倍数, // 这样输出长度与输入长度相同,函数调用外部为输出数据分配内存 int aesEncrypt(const uint8_t* key, uint32_t keyLen, const uint8_t* pt, uint8_t* ct, uint32_t len) { AesKey aesKey; uint8_t* pos = ct; const uint32_t* rk = aesKey.eK; //解密秘钥指针 uint8_t out[BLOCKSIZE] = { 0 }; uint8_t actualKey[16] = { 0 }; uint8_t state[4][4] = { 0 }; if (NULL == key || NULL == pt || NULL == ct) { printf("param err.\n"); return -1; } if (keyLen > 16) { printf("keyLen must be 16.\n"); return -1; } if (len % BLOCKSIZE) { printf("inLen is invalid.\n"); return -1; } memcpy(actualKey, key, keyLen); keyExpansion(actualKey, 16, &aesKey); // 秘钥扩展 // 使用ECB模式循环加密多个分组长度的数据 for (int i = 0; i < len; i += BLOCKSIZE) { // 把16字节的明文转换为4x4状态矩阵来进行处理 loadStateArray(state, pt); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // unsigned char t[4][4] = { {0x30,0x31,0x32,0x33},{0x34,0x35,0x36,0x37},{0x38,0x39,0x3a,0x3b},{0x3c,0x3d,0x3e,0x3f} }; unsigned char t[4][4] = {0}; memcpy(t,state,16); for(int i = 0;i<=3;i++){ for(int j = 0;j<=3;j++){ state[i][j] = t[j][i]; } } // 轮秘钥加 addRoundKey(state, rk); // printf("轮秘钥加 => \n"); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // getchar(); for (int j = 1; j < 10; ++j) { rk += 4; subBytes(state); // 字节替换 // printf("字节替换1 => \n"); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // printf("\n"); // getchar(); shiftRows(state); // 行移位 // printf("行移位2 => \n"); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // printf("\n"); // getchar(); mixColumns(state); // 列混合 // printf("列混合3 => \n"); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // printf("\n"); // getchar(); addRoundKey(state, rk); // 轮秘钥加 // printf("轮秘钥加4 => \n"); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // printf("\n"); // getchar(); } subBytes(state); // 字节替换 // printf("字节替换1 => \n"); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // printf("\n"); // getchar(); shiftRows(state); // 行移位 // 此处不进行列混合 addRoundKey(state, rk + 4); // 轮秘钥加 // printf("轮秘钥加4 => \n"); // for(int i = 0;i<=3;i++){ // for(int j = 0;j<=3;j++){ // printf("%x ",state[i][j]); // } // printf("\n"); // } // printf("\n"); // getchar(); // 把4x4状态矩阵转换为uint8_t一维数组输出保存 storeStateArray(state, pos); // printf("storeStateArray 转换二维矩阵为一维矩阵同时行列变换\n"); // for(int i = 0;i<=15;i++){ // printf("%x ",pos[i]); // } // printf("\n"); // getchar(); pos += BLOCKSIZE; // 加密数据内存指针移动到下一个分组 pt += BLOCKSIZE; // 明文数据指针移动到下一个分组 rk = aesKey.eK; // 恢复rk指针到秘钥初始位置 } return 0; } // AES128解密, 参数要求同加密 int aesDecrypt(const uint8_t* key, uint32_t keyLen, const uint8_t* ct, uint8_t* pt, uint32_t len) { AesKey aesKey; uint8_t* pos = pt; const uint32_t* rk = aesKey.dK; //解密秘钥指针 uint8_t out[BLOCKSIZE] = { 0 }; uint8_t actualKey[16] = { 0 }; uint8_t state[4][4] = { 0 }; if (NULL == key || NULL == ct || NULL == pt) { printf("param err.\n"); return -1; } if (keyLen > 16) { printf("keyLen must be 16.\n"); return -1; } if (len % BLOCKSIZE) { printf("inLen is invalid.\n"); return -1; } memcpy(actualKey, key, keyLen); keyExpansion(actualKey, 16, &aesKey); //秘钥扩展,同加密 for (int i = 0; i < len; i += BLOCKSIZE) { // 把16字节的密文转换为4x4状态矩阵来进行处理 loadStateArray(state, ct); // 轮秘钥加,同加密 addRoundKey(state, rk); for (int j = 1; j < 10; ++j) { rk += 4; invShiftRows(state); // 逆行移位 invSubBytes(state); // 逆字节替换,这两步顺序可以颠倒 addRoundKey(state, rk); // 轮秘钥加,同加密 invMixColumns(state); // 逆列混合 } invSubBytes(state); // 逆字节替换 invShiftRows(state); // 逆行移位 // 此处没有逆列混合 addRoundKey(state, rk + 4); // 轮秘钥加,同加密 storeStateArray(state, pos); // 保存明文数据 pos += BLOCKSIZE; // 输出数据内存指针移位分组长度 ct += BLOCKSIZE; // 输入数据内存指针移位分组长度 rk = aesKey.dK; // 恢复rk指针到秘钥初始位置 } return 0; } void printHex(const uint8_t* ptr, int len, const char* tag) { printf("%s\ndata[%d]: ", tag, len); for (int i = 0; i < len; ++i) { printf("%.2X ", *ptr++); } printf("\n"); } int main() { // case 1 const uint8_t key[16] = { 0x17, 0x93, 0x38, 0xc, 0x11, 0xa7, 0xf7, 0x54, 0xf7, 0x89, 0xc8, 0x20, 0xd4, 0x1a, 0xfa, 0x25 }; unsigned char cip[32] = { 0x0000004E, 0x00000054, 0x000000D6, 0x00000026, 0x000000C7, 0x00000097, 0x00000097, 0x0000008B, 0x00000006, 0x000000E5, 0x00000009, 0x0000009E, 0x000000BE, 0x00000057, 0x00000008, 0x0000004E, 0x00000028, 0x0000002A, 0x0000008A, 0x0000007F, 0x00000088, 0x000000C9, 0x000000F7, 0x000000EB, 0x000000E2, 0x000000BA, 0x000000F4, 0x0000005E, 0x000000E1, 0x00000040, 0x000000C0, 0x0000005A }; unsigned char cip1[] = {0x0000004e,0x000000c7,0x00000006,0x000000be,0x00000054,0x00000097,0x000000e5,0x00000057,0x000000d6,0x00000097,0x00000009,0x00000008,0x00000026,0x0000008b,0x0000009e,0x0000004e}; // unsigned char cip1[] = {0xFA ,0x94, 0xCC, 0x40, 0x67, 0x0A, 0x80, 0x55, 0xC3, 0x1A, 0x92,0xBF, 0x1B, 0x54,0xD1, 0x29}; // unsigned char cip1[] = {0xFA,0x67,0xC3,0x1B,0x94,0x0A,0x1A,0x54,0xCC,0x80,0x92,0xD1,0x40,0x55,0xBF,0x29}; unsigned char cip2[] = {0x00000028,0x00000088,0x000000E2,0x000000E1,0x0000002A,0x000000C9,0x000000BA,0x00000040,0x0000008A,0x000000F7,0x000000F4,0x000000C0,0x0000007F,0x000000EB,0x0000005E,0x0000005A}; uint8_t plain[16] = { 0 }; // 外部申请输出数据内存,用于解密后的数据 aesDecrypt(key, 16, cip1, plain, 16); // 解密 uint8_t key2[16] = {0 }; for(int i = 0;i<=15;i++){ key2[i] = key[i] ^cip[i] ; } printHex(plain, 16, "after decryption:"); // 打印解密后的明文数据 aesDecrypt((const unsigned char *)key2, 16, cip2, plain, 16); // 解密 printHex(plain, 16, "after decryption:"); // 打印解密后的明文数据 return 0; } //代码链接:https://blog.csdn.net/gq1870554301/article/details/118737728
__EOF__

本文作者:_TLSN
本文链接:https://www.cnblogs.com/lordtianqiyi/articles/16890556.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/lordtianqiyi/articles/16890556.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现