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编辑
,原因: