TGCTF re 后四题复现

exchange

这一部分经过动调后发现是将输入的每两个字节转为hex,再转为四字节字符串,每四字节的中间两位交换

跟进,上图可以看到v4 = 8

所以根据判断,只执行这一部分

美化

跟进

这俩函数算一个,都是keyinit

跟进

int64 __fastcall sub_7FF6AE812BD0(__int64 key, __int16 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 round; // [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]
​
  v2 = &v8;
  for ( i = 122i64; i; --i )
  {
    *(_DWORD *)v2 = -858993460;
    v2 += 4;
  }
  sub_7FF6AE8113CA((__int64)&unk_7FF6AE8260A6);
  for ( j = 0; j < 56; ++j )                            //PC1置换
  {
    v11 = PC1_Table[j];
    v12 = v11 & 7;
    v16 = (bytebit[v11 & 7] & *(unsigned __int8 *)(key + (v11 >> 3))) != 0;
    v14[j] = v16;
  }                                                     
  for ( round = 0; round < 16; ++round )         //16轮的密钥扩展
  {
    if ( a2 == 1 )
      v12 = 2 * (15 - round);
    else
      v12 = 2 * round;
    v13 = v12 + 1;
    v15[v12 + 1] = 0;
    v15[v12] = 0;                                   //前半位移
    for ( j = 0; j < 28; ++j )
    {
      v11 = totrot[round] + j;
      if ( v11 >= 28 )
        v4 = v14[v11 - 28];
      else
        v4 = v14[v11];
      v14[j + 80] = v4;
    }
    for ( j = 28; j < 56; ++j )
    {
      v11 = totrot[round] + j;
      if ( v11 >= 56 )
        v5 = v14[v11 - 28];
      else
        v5 = v14[v11];
      v14[j + 80] = v5;
    }                                               //后半位移
    for ( j = 0; j < 24; ++j )
    {
      if ( v14[pc2[j] + 80] )
        v15[v12] |= bigbyte[j];
      if ( v14[pc2[j + 24] + 80] )
        v15[v13] |= bigbyte[j];
    }
  }                                                 //pc2置换
  sub_7FF6AE811B80(v15);
  return sub_7FF6AE81135C((__int64)v7, (__int64)&unk_7FF6AE81CE80);
}

上面是对key的初始化,每一步已经用注释标出来

再跟进encrypt函数,可以看见交换特征

接着是加密函数

_DWORD *__fastcall sub_7FF6AE812510(unsigned int *a1, _DWORD *a2)
{
  _DWORD *result; // rax
  int v3; // [rsp+24h] [rbp+4h]
  int v4; // [rsp+24h] [rbp+4h]
  unsigned 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]
  unsigned 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]
  _DWORD *v41; // [rsp+1A8h] [rbp+188h]
​
  sub_7FF6AE8113CA(byte_7FF6AE8260A6);
  v18 = a1[1];
  v5 = (v18 ^ (*a1 >> 4)) & 0xF0F0F0F;
  v19 = v5 ^ v18;
  v29 = (16 * v5) ^ *a1;
  v6 = (unsigned __int16)(v19 ^ HIWORD(v29));
  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));          //E盒扩展
  for ( i = 0; i < 8; ++i )
  {
    v10 = *a2 ^ ((v23 >> 4) | (v23 << 28));
    v41 = a2 + 1;
    v3 = dword_7FF6AE820100[HIBYTE(v10) & 0x3F] | dword_7FF6AE820300[HIWORD(v10) & 0x3F] | dword_7FF6AE820500[(v10 >> 8) & 0x3F] | dword_7FF6AE820700[v10 & 0x3F];
    v11 = *v41++ ^ v23;
    v33 ^= dword_7FF6AE820200[HIBYTE(v11) & 0x3F] | dword_7FF6AE820400[HIWORD(v11) & 0x3F] | dword_7FF6AE820600[(v11 >> 8) & 0x3F] | dword_7FF6AE820800[v11 & 0x3F] | v3;
    v12 = *v41++ ^ ((v33 >> 4) | (v33 << 28));
    v4 = dword_7FF6AE820100[HIBYTE(v12) & 0x3F] | dword_7FF6AE820300[HIWORD(v12) & 0x3F] | dword_7FF6AE820500[(v12 >> 8) & 0x3F] | dword_7FF6AE820700[v12 & 0x3F];
    v13 = *v41 ^ v33;
    a2 = v41 + 1;
    v23 ^= dword_7FF6AE820200[HIBYTE(v13) & 0x3F] | dword_7FF6AE820400[HIWORD(v13) & 0x3F] | dword_7FF6AE820600[(v13 >> 8) & 0x3F] | dword_7FF6AE820800[v13 & 0x3F] | v4;
  }                                                         //S盒置换
  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 ^ HIWORD(v27));
  v37 = v17 ^ v36;
  v28 = (v17 << 16) ^ v27;
  *a1 = (16 * ((v37 ^ (v28 >> 4)) & 0xF0F0F0F)) ^ v28;
  result = a1 + 1;
  a1[1] = (v37 ^ (v28 >> 4)) & 0xF0F0F0F ^ v37;                 //P盒置换
  return result;    
}

DES的加密流程画了一个图,助于理解

最后网上脚本是有但是改了太多,这道题连E表和P表都没有

只能用wp的脚本,或者patch调用没删的dec函数

解出333936147332632923d96353321d3345636826d26314621d3349330463126348

写个脚本

得出flag

conforand

这题需要看函数,函数框里寥寥几个函数,rc4,rand

再交叉引用rand,发现再init函数里,并不是用来加密输入的

由此猜想可能有对称性

patch byte,换成output

经过调试发现每次加密结果都不一样,应该是每次的Sbox不同

通过随机加密key生成的随机的Sbox对输入加密,应该爆破种子,动调行不通。。

看了liv的wp,方法实在学不会。。

只能老老实实用D810去部分混淆,写脚本

手搓脚本

#include<stdio.h>
​
\#include<string.h>
​
\#include<stdlib.h>
​
\#include<stdint.h>
​
\#include<math.h>
​
​
​
int initsbox(unsigned char s[], unsigned char key[], unsigned int randnum) {
​
  int i, j;
​
  char k[256] = {0};
​
  unsigned char tmp;
​
​
​
  for (i = 0; i < 257; i++) {
​
•    s[i] = i;
​
•    k[i] = key[i % 9] ^ randnum; 
​
  }
​
​
​
  for (i = 0; i < 257; i++) {
​
•    j = (j + s[i] + k[i]) % 257;
​
•    tmp = s[i];
​
•    s[i] = s[j];
​
•    s[j] = tmp;
​
  }
​
​
​
  return 0;
​
}
​
​
​
int main() {
​
  for (unsigned int randnum = 0; randnum < 300; randnum++) {
​
•    unsigned char sbox[256];
​
•    unsigned char key[] = "JustDoIt!";
​
•    
​
•    // for (int i = 0; i < 9; i++)
​
•    // {
​
•    //   key[i]^=randnum;
​
•    // }
​
•    
​
•    initsbox(sbox, key, randnum);
​
•    unsigned int Data[] = {
​
•      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
​
•    };
​
•    unsigned long k = 0;
​
•    unsigned char tmp;
​
•    int i = 0, j = 0, t = 0;
​
•    for (k = 0; k < sizeof(Data) / sizeof(Data[0]); k++) {
​
•      i = (i + 1) % 257;
​
•      j = (j + sbox[i]) % 257;
​
•      sbox[i] = sbox[j];
​
•      sbox[j] = sbox[i];
​
•      t = (sbox[i] + sbox[j]) % 257;
​
•      Data[k] ^= sbox[t]; 
​
•    }
​
​
​
•    for (int i = 0; i < sizeof(Data) / sizeof(Data[0]); i++) {
​
•      printf("%c", (unsigned char)Data[i]); 
​
•    }
​
•    putchar('\n'); 
​
  }
​
​
​
  return 0;
​
}

终于出了

RandomSystem

函数分析

开头这两个函数可以静态分析

  puts("Welcome to HZNUCTF!!!\n", v4);
  puts("Enter something: \n", v5);
  sub_9E1037("%64s", v29);
  BinaryToHex(v29, v28);
  ReverseAndCut(v28[0], v28[1], &v23);
​

也可以查看TLS回调函数,初始化线程本地存储

输入的内容为str的二进制

动调得seed

得Str

得key

去除花指令 注释每个加密过程,去除步骤见### 花指令去除

__int64 sub_9E2370()
{
  int v0; // edx
  int v1; // eax
  __int64 v3; // [esp-8h] [ebp-78Ch]
  char v4; // [esp+0h] [ebp-784h]
  char v5; // [esp+0h] [ebp-784h]
  char v6; // [esp+0h] [ebp-784h]
  char v7; // [esp+0h] [ebp-784h]
  char v8; // [esp+0h] [ebp-784h]
  int m; // [esp+250h] [ebp-534h]
  int k; // [esp+25Ch] [ebp-528h]
  unsigned int v11; // [esp+268h] [ebp-51Ch]
  int j; // [esp+274h] [ebp-510h]
  char v13; // [esp+283h] [ebp-501h]
  int i; // [esp+298h] [ebp-4ECh]
  int key[34]; // [esp+2A4h] [ebp-4E0h] BYREF
  char Str[20]; // [esp+32Ch] [ebp-458h] BYREF
  int v17[66]; // [esp+340h] [ebp-444h] BYREF
  int v18[66]; // [esp+448h] [ebp-33Ch] BYREF
  int sqr[66]; // [esp+550h] [ebp-234h] BYREF
  int Destination[24]; // [esp+658h] [ebp-12Ch] BYREF
  char input; // [esp+6B8h] [ebp-CCh] BYREF
  char Source[76]; // [esp+6C0h] [ebp-C4h] BYREF
  int v23; // [esp+70Ch] [ebp-78h] BYREF
  int v24; // [esp+710h] [ebp-74h]
  int v25; // [esp+714h] [ebp-70h]
  int v26; // [esp+718h] [ebp-6Ch]
  char v27; // [esp+71Ch] [ebp-68h]
  int v28[4]; // [esp+728h] [ebp-5Ch] BYREF
  char v29[72]; // [esp+738h] [ebp-4Ch] BYREF
  int savedregs; // [esp+784h] [ebp+0h] BYREF
​
  sub_9E137A(&unk_9EE0A9);
  v23 = 0;
  v24 = 0;
  v25 = 0;
  v26 = 0;
  v27 = 0;
  j_memset(sqr, 0, 256u);
  j_memset(v18, 0, 256u);
  strcpy(Str, "KeYkEy!!");
  v17[0] = 0x178;
  v17[1] = 0x164;
  v17[2] = 0xA9;
  v17[3] = 0x1F5;
  v17[4] = 0x115;
  v17[5] = 0x149;
  v17[6] = 0x8B;
  v17[7] = 342;
  v17[8] = 380;
  v17[9] = 0x16D;
  v17[10] = 162;
  v17[11] = 258;
  v17[12] = 381;
  v17[13] = 339;
  v17[14] = 347;
  v17[15] = 307;
  v17[16] = 263;
  v17[17] = 359;
  v17[18] = 162;
  v17[19] = 484;
  v17[20] = 310;
  v17[21] = 333;
  v17[22] = 346;
  v17[23] = 339;
  v17[24] = 150;
  v17[25] = 194;
  v17[26] = 175;
  v17[27] = 344;
  v17[28] = 158;
  v17[29] = 250;
  v17[30] = 128;
  v17[31] = 175;
  v17[32] = 158;
  v17[33] = 173;
  v17[34] = 152;
  v17[35] = 379;
  v17[36] = 158;
  v17[37] = 292;
  v17[38] = 130;
  v17[39] = 365;
  v17[40] = 197;
  v17[41] = 20;
  v17[42] = 197;
  v17[43] = 161;
  v17[44] = 198;
  v17[45] = 10;
  v17[46] = 207;
  v17[47] = 244;
  v17[48] = 202;
  v17[49] = 14;
  v17[50] = 204;
  v17[51] = 176;
  v17[52] = 193;
  v17[53] = 255;
  v17[54] = 35;
  v17[55] = 7;
  v17[56] = 158;
  v17[57] = 181;
  v17[58] = 145;
  v17[59] = 353;
  v17[60] = 153;
  v17[61] = 357;
  v17[62] = 0xF6;
  v17[63] = 0x97;
  puts("Welcome to HZNUCTF!!!\n", v4);
  puts("Enter something: \n", v5);
  sub_9E1037("%64s", (char)v29);
  sub_9E1339(v29, v28);
  sub_9E128F(v28[0], v28[1], &v23);
  if ( (char)v23 == '5'
    && SBYTE1(v23) == '2'
    && SBYTE2(v23) == '6'
    && SHIBYTE(v23) == '5'
    && (char)v24 == '5'
    && SBYTE1(v24) == '6'
    && SBYTE2(v24) == '6'
    && SHIBYTE(v24) == '5'
    && (char)v25 == '5'
    && SBYTE1(v25) == '2'
    && SBYTE2(v25) == '6'
    && SHIBYTE(v25) == '5'
    && (char)v26 == '5'
    && SBYTE1(v26) == '3'
    && SBYTE2(v26) == '6'
    && SHIBYTE(v26) == '5' )
  {
    puts("good_job!!!\n", v6);
    puts("So, Plz input the flag:\n", v7);
    sub_9E1037("%73s", (char)&input);
    strncpy_s((char *)Destination, 65u, Source, 64u);
    sub_9E127B();
    srand(Seed);
    sub_9E127B();
    j_memset(key, 0, 128u);
    for ( i = 0; i < 32; ++i )
    {
      do
      {
        rand();
        v1 = sub_9E127B() % 32;
        v13 = 1;
        for ( j = 0; j < i; ++j )
        {
          if ( key[j] == v1 )
          {
            v13 = 0;
            break;
          }
        }
      }
      while ( !v13 );
      key[i] = v1;
    }                                           // 生成32个随机数
    sub_9E105F((char *)Destination, key);       // 32次用key对半置换矩阵
                                                // 
    copy(sqr, Destination);
    sub_9E1334((char *)&v23, (int)Str);         // 合并生成str   ReVeReSe
    sub_9E12DA((int *)asc_9EC368, sqr, v18);    // 矩阵相乘
    v11 = 0;
    for ( k = 0; k < 8; ++k )
    {
      for ( m = 0; m < 8; ++m )
      {
        v18[8 * k + m] ^= Str[v11 % j_strlen(Str)];// 8
                                                // 用str加密
        ++v11;
      }
    }
    if ( sqr_cmp(v18, v17) == 1 )
      puts("Congratulation!!!\n", v8);
  }
  else
  {
    puts("wrong_wrong!!!\n", v6);
  }
  sub_9E120D(&savedregs, &dword_9E2D48, 0, v0);
  return v3;
}

逆向第一步,解密数v18

#include<stdio.h>
int main(){
unsigned int v17[64];
unsigned int res[8][8];
unsigned char str[] = "ReVeReSe";
  v17[0] = 376;
  v17[1] = 356;
  v17[2] = 169;
  v17[3] = 501;
  v17[4] = 277;
  v17[5] = 329;
  v17[6] = 139;
  v17[7] = 342;
  v17[8] = 380;
  v17[9] = 365;
  v17[10] = 162;
  v17[11] = 258;
  v17[12] = 381;
  v17[13] = 339;
  v17[14] = 347;
  v17[15] = 307;
  v17[16] = 263;
  v17[17] = 359;
  v17[18] = 162;
  v17[19] = 484;
  v17[20] = 310;
  v17[21] = 333;
  v17[22] = 346;
  v17[23] = 339;
  v17[24] = 150;
  v17[25] = 194;
  v17[26] = 175;
  v17[27] = 344;
  v17[28] = 158;
  v17[29] = 250;
  v17[30] = 128;
  v17[31] = 175;
  v17[32] = 158;
  v17[33] = 173;
  v17[34] = 152;
  v17[35] = 379;
  v17[36] = 158;
  v17[37] = 292;
  v17[38] = 130;
  v17[39] = 365;
  v17[40] = 197;
  v17[41] = 20;
  v17[42] = 197;
  v17[43] = 161;
  v17[44] = 198;
  v17[45] = 10;
  v17[46] = 207;
  v17[47] = 244;
  v17[48] = 202;
  v17[49] = 14;
  v17[50] = 204;
  v17[51] = 176;
  v17[52] = 193;
  v17[53] = 255;
  v17[54] = 35;
  v17[55] = 7;
  v17[56] = 158;
  v17[57] = 181;
  v17[58] = 145;
  v17[59] = 353;
  v17[60] = 153;
  v17[61] = 357;
  v17[62] = 246;
  v17[63] = 151;
  int matrix[8][8] = {
    {1, 1, 0, 1, 0, 0, 1, 0},
    {0, 1, 1, 0, 0, 1, 0, 1},
    {0, 0, 1, 1, 0, 1, 1, 0},
    {0, 0, 0, 1, 0, 1, 0, 1},
    {0, 1, 0, 0, 1, 0, 1, 0},
    {0, 0, 0, 0, 0, 1, 0, 1},
    {0, 0, 0, 0, 0, 0, 1, 1},
    {0, 1, 1, 0, 0, 0, 0, 1}
};                                       //矩阵1
  int k = 0;
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            res[i][k%8] = v17[i*8+j];
            k++;
        }
    }
    int cnt = 0;
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            res[i][j]^=str[cnt%8];
            ++cnt;
​
        }
    }
    for (int i = 0; i < 8; i++)
    {   
        for (int  j = 0; j < 8; j++)
        {
            printf("%d ",res[i][j]);
        }
        putchar('\n');
        
    }    //v18
//     int inv_matrix[8][8] = {
//         1 ,-4 ,1 ,-2, 0, 5, -2, 3 ,
// 0, 3, -1, 1 ,0, -3 ,1 ,-2 ,
// 0, -2 ,1 -1, 0, 2 -1, 2 ,
// 0, 0 ,0, 1,0 ,-1, 0, 0 ,
// 0, -4, 1, -1, 1 ,4, -2, 3 ,
// 0, 1 ,0, 0, 0, 0, 0, -1, 
// 0, 1, 0 ,0, 0 ,-1, 1,-1 ,
// 0 ,-1 ,0, 0 ,0 ,1, 0 ,1 
//     };
​
    
    
}

查看asc_9EC368矩阵,256个,因为是每个元素int,32位

求逆矩阵

还原sqr

 

#include<stdio.h>
int main(){
    unsigned char key[] =
{
     27,    
    26,  
    25,     
    23,  
    28,   
    1,   
    6,  
    10,  
    20,  
    7,   
    15,  
    14,   
    31,   
    18,  
    19,   
    21,    
    9,   
    30,  
    22,  
    24,  
    8,   
    2,  
    29, 
    3,  
    12,   
    11,  
    17,   
    16,   
    0,  
    13,   
    5,  
    4,   
};
int sqr[64] = {
    102, 100 ,49, 49 ,118 ,53 ,54, 100 ,
52 ,53 ,52 ,114 ,54 ,102, 52, 97 ,
99 ,98 ,45 ,49 ,101, 97, 56, 100 ,
45,54 ,102 ,121 ,56 ,48, 55, 57 ,
53 ,97, 102, 56, 51 ,122, 102, 114 ,
98, 56, 45 ,99 ,100, 54, 99 ,100 ,
99, 50, 52 ,116, 99 ,97 ,55, 53 ,
53 ,57 ,102, 97 ,48, 57, 57, 45 ,
};
int tmp;
for (int i = 0; i <32; i++)
{
    tmp = sqr[i];
    sqr[i] = sqr[64 - key[i] - 1];
    sqr[64 - key[i] - 1] = tmp;
}
for (int i = 0; i < 64; i++)
{
    printf("%c",sqr[i]);
}
​
​
}

解出flag

花指令去除

第一个函数

去除后

第二个:

重新U P 生成函数

第三个:

 

U P生成函数

第四个:

和第三个一样

 

index

修改文件头

WASM , 基于二进制格式的可执行文件格式

用ghidra安装wasm反汇编插件,11.2版本

反汇编及美化如下

​
undefined4 unnamed_function_12(void)
​
{
  int len;
  undefined8 *inputflag [4];
  undefined8 *inputkey;
  int k;
  int j;
  int i;
  byte Str [32];
  undefined8 inputkey_;
  undefined local_38;
  undefined8 inputflag_;
  undefined8 local_28;
  undefined8 local_20;
  undefined8 local_18;
  undefined local_10;
  undefined4 local_4;
  
  local_4 = 0;
  local_10 = 0;
  local_18 = 0;
  local_20 = 0;
  local_28 = 0;
  inputflag_ = 0;
  local_38 = 0;
  inputkey_ = 0;
  Str[0x18] = 0;
  Str[0x19] = 0;
  Str[0x1a] = 0;
  Str[0x1b] = 0;
  Str[0x1c] = 0;
  Str[0x1d] = 0;
  Str[0x1e] = 0;
  Str[0x1f] = 0;
  Str[0x10] = 0;
  Str[0x11] = 0;
  Str[0x12] = 0;
  Str[0x13] = 0;
  Str[0x14] = 0;
  Str[0x15] = 0;
  Str[0x16] = 0;
  Str[0x17] = 0;
  Str[8] = 0;
  Str[9] = 0;
  Str[10] = 0;
  Str[0xb] = 0;
  Str[0xc] = 0;
  Str[0xd] = 0;
  Str[0xe] = 0;
  Str[0xf] = 0;
  Str[0] = 0;
  Str[1] = 0;
  Str[2] = 0;
  Str[3] = 0;
  Str[4] = 0;
  Str[5] = 0;
  Str[6] = 0;
  Str[7] = 0;
  puts(s_Welcome_to_HZNUCTF!!!_ram_000100ae,0);
  puts(s_Plz_input_the_key:_ram_00010051,0);
  inputkey = &inputkey_;
  scanf(0x10026,&inputkey);
                    /* TGCTF404 */
  len = cmp(&inputkey_,0x11020);
  if (len == 0) {
    xor0x51(&inputkey_);
    puts(s_Ok,_let's_go!!!_ram_0001007a,0);
    puts(s_Plz_input_the_flag:_ram_00010065,0);
    inputflag[0] = &inputflag_;
    scanf(0x10026,inputflag);
    len = ::len(&inputflag_);
    if (len == 0x20) {
      randomenc(&inputflag_,Str);
      for (i = 0; i < 8; i = i + 1) {
        xorenc(Str + i * 4,&inputkey_);
      }
      for (j = 0; j < 8; j = j + 1) {
        for (k = 0; k < 4; k = k + 1) {
          if ((uint)Str[k + j * 4] != *(uint *)(j * 0x10 + 0x10fa0 + k * 4)) {
            puts(s_wrong_wrong!!!_ram_00010042,0);
            return 0;
          }
        }
      }
      puts(s_Congratulation!!!_ram_0001008b,0);
    }
    else {
      puts(s_wrong_wrong!!!_ram_00010042,0);
    }
  }
  else {
    puts(s_wrong_wrong!!!_ram_0001009e,0);
  }
  return 0;
}

可以找到key是TGCTF404

主要加密函数有

xor0x51,randomenc,xorenc

跟进xorenc

void xorenc(int input,int key)

{
  int high4;
  uint low4;
  undefined4 i;
  byte local_15;
  byte local_9;
  
  high4 = (int)*(char *)(key + iRam00011200) >> 4;
  low4 = (int)*(char *)(key + iRam00011200) & 0xf;
  iRam00011200 = iRam00011200 + 1;
  xor(0x10ea0,(int)*(char *)(high4 * 0x10 + 0x10da0 + low4));
  for (i = 0; i < 4; i = i + 1) {
    *(byte *)(input + i) =
         *(byte *)(input + i) ^ *(byte *)(high4 * 0x10 + i * 0x11 + low4 + 0x10ea0);
    *(byte *)(input + i) = *(byte *)(input + i) ^ *(byte *)(i + 0x11020);
  }
  return;
}

在0x10da0和0x10ea0地址发现两个256长度的加密盒

用加密后的key每字节的高四位和第四位作为行和列的索引用来异或

再跟进randomenc

void randomenc(int input,int str)

{
  undefined4 j;
  undefined4 i;
  undefined4 k;
  
  k = 0;
  srand(404);
  random_exchange(input,0x20);
  for (i = 0; i < 8; i = i + 1) {
    for (j = 0; j < 4; j = j + 1) {
      *(undefined *)(str + i * 4 + j) = *(undefined *)(input + k);
      k = k + 1;
    }
  }
  return;
}

跟进random_exchange

void random_exchange(int param1,int param2)

{
  undefined uVar1;
  int iVar2;
  byte local_11;
  undefined4 i;
  
  if (1 < param2) {
    for (i = 0; i < param2 + -1; i = i + 1) {
      iVar2 = rand();
      iVar2 = i + iVar2 / (0x7fffffff / (param2 - i) + 1);
      uVar1 = *(undefined *)(param1 + iVar2);
      *(undefined *)(param1 + iVar2) = *(undefined *)(param1 + i);
      *(undefined *)(param1 + i) = uVar1;
    }
  }
  return;
}

用随机数生成索引进行置换

我们可以先把xorenc这个解出来

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

int main() {
    int k = 0;
    char key0[] = "TGCTF404";
    char flag[33];
    char input[] = "TGCTF404";
    int m = 0;
    srand(404);
    unsigned char box1[16][16] = {
        {0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 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},
        {0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75},
        {0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84},
        {0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF},
        {0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8},
        {0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2},
        {0xCD, 0x0C, 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, 0x0B, 0xDB},
        {0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 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, 0x08},
        {0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A},
        {0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 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, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}
    };
    int box2[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
    };
    
    int str[8][4] = {
        {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, 0x0b, 0x76},
        {0xb0, 0xdc, 0x02, 0x51}
    };

    for (int i = 0; i < 8; i++) {
        input[i] = (input[i] ^ 0x51) ;
    }
    for (int i = 0; i < 8; i++) {
        char Char = input[k++];
        int r = Char >> 4;
        int l = (Char & 0x0F);
        char tmp = box1[r][l];

        for (int j = 0; j < 256; j++) {
            box2[j] ^= tmp;
            box2[j] &= 0xFF;
        }

        for (int j = 0; j < 4; j++) {
            str[i][j] ^= box2[(r + j) * 16 + (l + j)];
            str[i][j] ^= key0[j];
        }
    }

    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 4; j++) {
            flag[m++] = str[i][j] & 0xFF;
        }
    }
    printf("%s", flag);
}

解出Z49H539c{--6}d4888bTUCf8NeFe--e9

再解randomenc,根据生成的rand数组进行倒序置换

遇到一个问题,原题是0x7fffffff写到脚本里生成不了随机数组

只有尝试到0x7fff时才可行,猜测时限制随机数位数的

#include<stdio.h>
#include<stdlib.h>
int main(){
    srand(404);
    for (int i = 0; i < 31; i++) {
    int num = i + rand() / (0x7fff / (32 - i) + 1);
    printf("%d ",num);
}
}

得出数组

1 24 28 24 16 25 22 29 29 12 17 19 31 13 18 19 30 31 27 25 24 30 29 25 28 27 29 27 30 29 30

置换脚本

#include<stdio.h>
#include<stdlib.h>
int main(){
    char tmp;
    char flag[] = "Z49H539c{--6}d4888bTUCf8NeFe--e9";
    int num[] = {1, 24, 28, 24, 16, 25, 22, 29, 29, 12 ,17 ,19 ,31, 13, 18 ,19,30, 31, 27 ,25, 24 ,30, 29 ,25 ,28,27 ,29 ,27, 30, 29 ,30 };
    for (int i = 30; i >=0; i--)
    {
        tmp = flag[i];
        flag[i] = flag[num[i]];
        flag[num[i]] = tmp;
    }
    for (int i = 0; i < 32; i++)
    {
        printf("%c",flag[i]);
    }
    

}

得出flag HZNUCTF{f898-de85-46e-9e43-b9c8}

内容概要:本文围绕微电网群的双层优化与分布式优化问,提出基于交替方向乘子法(ADMM)的分布式协同优化控制策略,并通过Matlab代码实现仿真验证。研究构建了上层为微电网间能量协调与优化调度、下层为各微电网内部源-荷-储精细化运行管理的双层优化模型。采用ADMM算法将集中式优化问分解为多个可并行求解的子问,实现了计算的分布式化与信息隐私保护,显著提升了系统的可扩展性与鲁棒性。文中系统阐述了模型构建原理、ADMM算法设计流程及其收敛性分析,并通过仿真实验验证了该方法在降低系统综合运行成本、提高可再生能源消纳能力以及维持系统稳定运行方面的有效性。; 适合人群:具备电力系统分析、优化理论基础,熟悉Matlab编程,从事微电网、分布式能源系统、智能电网等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 学习和掌握基于ADMM的分布式优化方法在微电网群协同能量管理中的具体应用;② 实现微电网群多主体参与下的经济调度与仿真分析;③ 深入理解双层优化架构的设计理念与分布式求解算法的实现机制。; 阅读建议:建议结合所提供的Matlab代码进行动手实践,重点剖析模型建立与算法实现的关键细节,可通过调整系统参数、改变运行场景等方式,深入探究ADMM算法的收敛特性及其对优化效果的影响。
内容概要:本文聚焦于风电出力不确定性的精确建模问,提出采用拉丁超立方抽样(LHS)方法生成具有统计代表性的风电场景,并结合先进的场景缩减技术以降低计算复杂度。通过Matlab编程实现了LHS在高维随机变量空间中的均匀采样,有效克服了传统蒙特卡洛方法样本收敛慢、效率低的问。在此基础上,引入基于聚类分析或概率距离度量的场景缩减算法,对初始大规模场景集进行优化合并,保留关键概率特征与出力趋势,构建出精简且具代表性的典型场景集。该方法显著提升了电力系统随机优化模型(如机组组合、储能调度、微电网能量管理)的求解效率与数值稳定性,同时确保输入场景的合理性与真实性,具备良好的可复现性与工程应用价值。; 适合人群:适用于具备一定电力系统分析基础和Matlab编程能力,从事新能源并网、随机规划、场景生成、电力市场及综合能源系统优化等方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握拉丁超立方抽样在风电不确定性建模中的理论原理与Matlab实现技巧;②学习并应用场景生成与缩减技术,提升随机优化问的建模与求解效率;③为含高比例风电的电力系统调度、风险评估与决策分析提供高质量的输入场景支撑。; 阅读建议:建议读者结合所提供的Matlab代码逐模块调试运行,深入理解抽样策略、距离计算、聚类缩减等核心算法的实现细节,并尝试将其集成到具体的优化模型中进行验证与拓展,以强化科研实践能力与创新思维。
内容概要:本文围绕基于交替方向乘子法(ADMM)的多主体综合能源系统分布式协同优化展开研究,提出了一种利用ADMM算法实现多个能源主体间高效协同优化的解决方案。该方法将集中式优化问分解为多个可并行求解的子问,各主体在保护自身数据隐私的前提下,仅通过交换少量边界信息即可完成全局协同优化,有效解决了传统集中式方法存在的通信负担重、隐私泄露风险高等问。研究涵盖了模型构建、算法设计、收敛性分析及仿真验证全过程,并以Matlab代码实现了算法原型,展示了其在提升系统运行效率、促进可再生能源消纳方面的潜力。该研究不仅提供了完整的算法实现框架,还深入探讨了ADMM在多区域电网、多微网及产消者等复杂场景下的适用性与扩展能力,为现代综合能源系统的分布式管理提供了理论依据和技术支持。; 适合人群:具备一定电力系统、优化理论及Matlab编程基础的研究生、科研人员或从事综合能源系统相关工作的工程技术人员。; 使用场景及目标:①应用于多区域电网、多微网、产消者(Prosumer)等多主体参与的综合能源系统协同调度;②实现数据隐私保护下的分布式优化,避免中心节点收集全局敏感信息;③学习ADMM算法在电力系统中的具体建模与实现方法,掌握其收敛特性与参数整定技巧。; 阅读建议:读者应结合提供的Matlab代码进行实践,重点关注ADMM算法的迭代流程、惩罚因子设定及其对收敛速度的影响,同时可通过修改系统规模与参数设置,进一步探究算法在不同场景下的适应性与性能表现。
代码转载自:https://pan.quark.cn/s/068a9379e0dc 在当前数字化时代背景下,教育行业对于信息技术的应用呈现日益广泛的趋势,其中联想作为知名的电脑生产商,其在教育领域的产品及解决方案备受瞩目。联想EDU7.6底层驱动程序是一款专门为联想教育终端所研发的驱动软件,其版本标识为7.6.0,发布时间定格在0727日。该驱动程序在教育环境中扮演着关键角色,特别是在维护设备稳定运行方面具有显著功能。本篇将详尽分析联想EDU7.6底层驱动的详细信息,及其与联想保护卡之间的紧密关联,并为采用该驱动的用户提供正确的安装流程和注意事项。 作为计算机系统不可或缺的核心构成,驱动程序的功能至关重要。它们充当操作系统与硬件设备之间的连接纽带,负责监管硬件设备的运行状况。联想EDU7.6底层驱动的推出,是基于联想教育终端EDU系列产品的性能提升和功能强化,目的在于增强教育设备在教学和学习过程中的效能及稳定性。然而,这款驱动程序存在一个显著的系统兼容性挑战,即不兼容Windows 10操作系统。这是由于底层驱动程序可能与Windows 10的内核存在不匹配,若在Windows 10环境中进行安装,有可能引发蓝屏故障。因此,技术人员和教育机构在应用时必须谨慎,防止因操作系统差异引发的问。 “联想保护卡”是联想为确保教育终端设备安全而设计的一项功能。它借助硬件层面的防护机制,保证系统配置不会被非法更改,从而保障教育资源的绝对安全。联想EDU7.6底层驱动与保护卡的协同使用,能够为教育终端创造一个更加安全可靠的操作环境。比如,能够有效阻止学生或未授权人员在使用期间对系统进行违规操作,进而保护教学软件和数据的安全。 在安装和运用联想EDU7.6底层驱动时,用户需...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值