鹏城杯2023初赛 Reverse WriteUp

一. 安全编程

  • rust逆向,直接动调

  • 定位关键函数sub_7FD043E88C70

  • 下断点跟进

  • 观察控制台

  • guess number
    plz input 1-10 number

  • 这时我们随便输入一个数,往下跟进

  • .text:00007F14B3684E9B
    .text:00007F14B3684E9B loc_7F14B3684E9B:
    .text:00007F14B3684E9B cmp     [rsp+0D8h+var_88], eax
    .text:00007F14B3684E9F jnz     loc_7F14B3684F63
    
  • 将输入的数与程序随机生成的数进行比较,从而跳转

  • .text:00007F14B3684EA5 inc     [rsp+0D8h+var_84]
    .text:00007F14B3684EA9 lea     rax, [rsp+0D8h+var_84]
    .text:00007F14B3684EAE mov     [rsp+0D8h+var_A0], rax
    .text:00007F14B3684EB3 lea     rax, sub_7F14B36D13F0
    .text:00007F14B3684EBA mov     [rsp+0D8h+var_98], rax
    .text:00007F14B3684EBF lea     rax, unk_7F14B36E6F08
    .text:00007F14B3684EC6 mov     [rsp+0D8h+var_C0], rax
    .text:00007F14B3684ECB mov     [rsp+0D8h+var_B8], 2
    .text:00007F14B3684ED4 mov     [rsp+0D8h+var_D0], 0
    .text:00007F14B3684EDD lea     rax, [rsp+0D8h+var_A0]
    .text:00007F14B3684EE2 mov     [rsp+0D8h+var_B0], rax
    .text:00007F14B3684EE7 mov     [rsp+0D8h+var_A8], 1
    .text:00007F14B3684EF0 mov     rdi, r14
    .text:00007F14B3684EF3 call    r13 ; sub_7F14B369D660
    .text:00007F14B3684EF6 cmp     [rsp+0D8h+var_84], 64h ; 'd'
    .text:00007F14B3684EFB jz      loc_7F14B368500E
    
  • 如果比较结果相同就跳到上述分支,注意到inc这一关键计数

  • 再看cmp [rsp+0D8h+var_84], 64h ; 'd',这一比较再次决定跳转

  • shift+E查看数据发现关键字符串:恭喜你获得flag,就在下面这段中

  • .text:00007F14B368500E
    .text:00007F14B368500E loc_7F14B368500E:
    .text:00007F14B368500E lea     rax, unk_7F14B36E6F28
    .text:00007F14B3685015 mov     [rsp+0D8h+var_C0], rax
    .text:00007F14B368501A mov     [rsp+0D8h+var_B8], 1
    .text:00007F14B3685023 mov     [rsp+0D8h+var_D0], 0
    .text:00007F14B368502C mov     [rsp+0D8h+var_B0], rbx
    .text:00007F14B3685031 mov     [rsp+0D8h+var_A8], 0
    .text:00007F14B368503A lea     rdi, [rsp+0D8h+var_D0]
    .text:00007F14B368503F call    cs:qword_7F14B36E9FA8
    .text:00007F14B3685045 lea     rdi, [rsp+0D8h+var_D0]
    .text:00007F14B368504A call    cs:qword_7F14B36E9C18
    .text:00007F14B3685050 lea     rdi, [rsp+0D8h+var_D0]
    .text:00007F14B3685055 mov     esi, 1
    .text:00007F14B368505A call    cs:qword_7F14B36E9E80
    .text:00007F14B3685060 lea     rdx, unk_7F14B36D2080
    .text:00007F14B3685067 lea     rdi, [rsp+0D8h+var_A0]
    .text:00007F14B368506C mov     ecx, 0Dh
    .text:00007F14B3685071 mov     rsi, rax
    .text:00007F14B3685074 call    cs:qword_7F14B36E9D50
    .text:00007F14B368507A cmp     dword ptr [rsp+0D8h+var_A0], 0
    .text:00007F14B368507F jnz     loc_7F14B3685275
    
  • 那我们就明白了,直接将64hpatch为01h,这样只需要一次正确即可找到flag

  • 接着动调结束,让程序执行完,就会发现程序生成一个img.png,即为flag

  • flag{d846b8394630f42e02fef698a4e3df1b}

二. bad_pe

  • DIE查壳,没啥问题

  • 拖进IDA看看

  • __int64 start()
    {unsigned __int64 v0; // raxHMODULE ModuleHandleA; // raxchar *v2; // rdxint v3; // ecxchar *v4; // r10__int64 v5; // r11char *v6; // r8char *v7; // rdxchar i; // r9char *v9; // rcxvoid (*v10)(void); // r9unsigned __int64 v11; // raxchar v13[14]; // [rsp+2Ah] [rbp-Eh] BYREFv0 = __rdtsc();dword_418004 = HIDWORD(v0);ModuleHandleA = GetModuleHandleA(0i64);strcpy(v13, ".ATOM");v2 = (char *)ModuleHandleA + *((int *)ModuleHandleA + 15);v3 = *((unsigned __int16 *)v2 + 3);if ( (_WORD)v3 ){v4 = v2 + 264;v5 = (__int64)&v2[40 * (v3 - 1) + 304];while ( *v4 != 46 ){
    LABEL_18:v4 += 40;if ( v4 == (char *)v5 )return 0i64;}v6 = v13;v7 = v4;for ( i = 65; ; i = v6[1] ){++v7;++v6;if ( *v7 != i )break;if ( !i )goto LABEL_10;}if ( *v7 || i )goto LABEL_18;
    LABEL_10:v9 = (char *)ModuleHandleA + *((unsigned int *)v4 + 3);if ( *((_DWORD *)v4 + 2) )//0xdd12{v7 = 0i64;do(v7++)[(_QWORD)v9] ^= 0x23u;while ( *((_DWORD *)v4 + 2) > (unsigned int)v7 );}else if ( !v9 ){return 0i64;}v10 = (void (*)(void))sub_414140(v9, v7, v6);v11 = __rdtsc();dword_418000 = HIDWORD(v11);if ( (unsigned int)(HIDWORD(v11) - dword_418004) <= 1 )v10();}return 0i64;
    }
    
  • 想动调解密,但发现PE文件格式魔改掉了

  • 放进010看看,发现一堆0x23

  • 写脚本去除:

  • arr = 0x23
    with open('C:\\Users\\lenovo\\Desktop\\bad_pe.exe', 'rb') as f:b = f.read()
    b = bytearray(b)
    for i in range(len(b)):b[i]^=0x23
    with open('C:\\Users\\lenovo\\Desktop\\COD_de1', 'wb') as f:f.write(b)
    
  • 发现在2e00处开始是一个新的PE文件,dump出来

  • data = open('C:\\Users\\lenovo\\Desktop\\COD_de1', 'rb').read()[0x2e00: 0x2e00 + 0xdd12]
    data = bytes(i for i in data)
    open('C:\\Users\\lenovo\\Desktop\\COD_de2', 'wb').write(data)
    
  • 将新文件拖入IDA,成功找到main函数

  • int __cdecl main(int argc, const char **argv, const char **envp)
    {__int128 *v3; // rdiint v4; // edxunsigned int v5; // eaxsigned __int64 v6; // rdivoid *v7; // rspvoid *v8; // rspchar *v9; // raxchar *v10; // rdxchar v11; // r8char v13[8]; // [rsp+30h] [rbp-B0h] BYREF__int64 v14; // [rsp+38h] [rbp-A8h] BYREF__int128 v15[2]; // [rsp+40h] [rbp-A0h] BYREF__int16 v16[8]; // [rsp+60h] [rbp-80h] BYREFchar v17[112]; // [rsp+70h] [rbp-70h] BYREF_main(argc, argv, envp);v3 = v15;v15[0] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405130);v14 = 0x2179336B336874i64;v15[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405140);qmemcpy(v16, ".~c", 3);do{v4 = *(_DWORD *)v3;v3 = (__int128 *)((char *)v3 + 4);v5 = ~v4 & (v4 - 16843009) & 0x80808080;}while ( !v5 );if ( (~v4 & (v4 - 16843009) & 0x8080) == 0 )v5 >>= 16;if ( (~v4 & (v4 - 16843009) & 0x8080) == 0 )v3 = (__int128 *)((char *)v3 + 2);v6 = (char *)v3 - __CFADD__((_BYTE)v5, (_BYTE)v5) - 3 - (char *)v15;v7 = alloca(v6);v8 = alloca(v6);printf("please input your flag:");putchar(10);scanf("%s", v17);rc4_crypt((unsigned int)v17, v6, (unsigned int)&v14, 7, (__int64)v13);if ( v6 ){if ( v13[0] != -67 ){
    LABEL_14:printf("wrong!");return 0;}v9 = v13;v10 = (char *)v15 + 1;while ( &v13[(unsigned int)(v6 - 1)] != v9 ){v11 = v9[1];++v10;++v9;if ( v11 != *(v10 - 1) )goto LABEL_14;}}printf("successful!!");return 0;
    }
    
  • 注意到RC4加密函数

  • char *__fastcall rc4_crypt(__int64 a1, __int64 a2, __int64 a3, int a4, __int64 a5)
    {__int64 v5; // r12int v6; // r10d__int128 *v7; // r11int v8; // eaxchar v9; // blchar *result; // rax__int64 v11; // rbx__int64 v12; // r11__int64 v13; // rdichar v14; // alchar v15; // r10__int128 v16[18]; // [rsp+0h] [rbp-128h] BYREFLOBYTE(v5) = 0;v6 = 0;v16[0] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405030);v7 = v16;v16[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405040);v16[2] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405050);v16[3] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405060);v16[4] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405070);v16[5] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405080);v16[6] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405090);v16[7] = (__int128)_mm_load_si128((const __m128i *)&xmmword_4050A0);v16[8] = (__int128)_mm_load_si128((const __m128i *)&xmmword_4050B0);v16[9] = (__int128)_mm_load_si128((const __m128i *)&xmmword_4050C0);v16[10] = (__int128)_mm_load_si128((const __m128i *)&xmmword_4050D0);v16[11] = (__int128)_mm_load_si128((const __m128i *)&xmmword_4050E0);v16[12] = (__int128)_mm_load_si128((const __m128i *)&xmmword_4050F0);v16[13] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405100);v16[14] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405110);v16[15] = (__int128)_mm_load_si128((const __m128i *)&xmmword_405120);do{v8 = v6;v9 = *(_BYTE *)v7;++v6;v7 = (__int128 *)((char *)v7 + 1);v5 = (unsigned __int8)(v5 + v9 + *(_BYTE *)(a3 + v8 % a4));result = (char *)v16 + v5;*((_BYTE *)v7 - 1) = *((_BYTE *)v16 + v5);*((_BYTE *)v16 + v5) = v9;}while ( v6 != 256 );if ( (int)a2 > 0 ){v11 = (unsigned int)(a2 - 1);v12 = 0i64;LOBYTE(v13) = 0;LOBYTE(a2) = 0;while ( 1 ){v14 = *((_BYTE *)v16 + (unsigned __int8)(a2 + 1));a2 = (unsigned __int8)(a2 + 1);v15 = *((_BYTE *)v16 + (unsigned __int8)(v14 + v13));v13 = (unsigned __int8)(v14 + v13);*((_BYTE *)v16 + a2) = v15;*((_BYTE *)v16 + v13) = v14;*(_BYTE *)(a5 + v12) = *(_BYTE *)(a1 + v12) ^ *((_BYTE *)v16 + (unsigned __int8)(*((_BYTE *)v16 + a2) + v14));result = (char *)(v12 + 1);if ( v12 == v11 )break;++v12;}}return result;
    }
    
  • 找到keyv14 = '!y3k3ht';,再动调找密文

  • 0xBD, 0xF0, 0x4C, 0xD9, 0xD0, 0x29, 0xF2, 0x46, 0x08, 0xCC, 
    0xC8, 0x9F, 0xBE, 0x4B, 0xEF, 0x67, 0x46, 0x04, 0xE6, 0x32, 
    0xF3, 0xF6, 0xAA, 0xF0, 0xD1, 0xD8, 0xEC, 0x75, 0x49, 0x2F, 
    0xCC, 0x26, 0x2E, 0x7E, 0x63
    
  • 套脚本解密即可

  • def KSA(key):key_length = len(key)S = list(range(256))j = 0for i in range(256):j = (j + S[i] + key[i % key_length]) % 256S[i], S[j] = S[j], S[i]return Sdef PRGA(S):i = 0j = 0while True:i = (i + 1) % 256j = (j + S[i]) % 256S[i], S[j] = S[j], S[i]K = S[(S[i] + S[j]) % 256]yield Kdef RC4(key):S = KSA(key)keystream = PRGA(S)return keystreamif __name__ == '__main__':key = 'th3k3y!'plaintext = [0xBD, 0xF0, 0x4C, 0xD9, 0xD0, 0x29, 0xF2, 0x46,0x08, 0xCC, 0xC8, 0x9F, 0xBE, 0x4B, 0xEF, 0x67, 0x46, 0x04, 0xE6, 0x32, 0xF3, 0xF6, 0xAA, 0xF0, 0xD1, 0xD8, 0xEC, 0x75, 0x49, 0x2F, 0xCC, 0x26, 0x2E, 0x7E, 0x63]key = key.encode()keystream = RC4(key)ciphertext = []for b in plaintext:ciphertext.append(chr(b ^ next(keystream)))print("".join(ciphertext))
    
  • flag{th3_p3fi15_1s_v3ry_nicccccc!}

三. babyre

  • 定位关键函数

  • __int64 sub_140011F90()
    {size_t v1; // [rsp+28h] [rbp+8h]int i; // [rsp+44h] [rbp+24h]sub_14001138E(&unk_140022066);sub_1400111A4("plz input flag:\n");sub_14001120D(&unk_14001ADD0, Buf1, 49i64);v1 = j_strlen(Buf1);if ( v1 == 48 ){for ( i = 0; i < v1 / 4; i += 3 )sub_14001107D(&Buf1[4 * i], v1 % 4);if ( !j_memcmp(Buf1, &unk_14001D000, 0x30ui64) )sub_1400111A4("success");elsesub_1400111A4("fail");return 0i64;}else{sub_1400111A4("fail");return 0i64;}
    }
    
  • 看着逻辑很简单,就只有一个加密函数

  • __int64 __fastcall sub_140011870(int *a1)
    {char *v1; // rdi__int64 i; // rcxchar v4[32]; // [rsp+0h] [rbp-20h] BYREFchar v5; // [rsp+20h] [rbp+0h] BYREFunsigned int v6; // [rsp+24h] [rbp+4h]unsigned int v7; // [rsp+44h] [rbp+24h]unsigned int v8; // [rsp+64h] [rbp+44h]int j; // [rsp+84h] [rbp+64h]int v10; // [rsp+A8h] [rbp+88h]int v11; // [rsp+ACh] [rbp+8Ch]int v12; // [rsp+B0h] [rbp+90h]int v13; // [rsp+B4h] [rbp+94h]int v14; // [rsp+D8h] [rbp+B8h]int v15; // [rsp+DCh] [rbp+BCh]int v16; // [rsp+E0h] [rbp+C0h]int v17; // [rsp+E4h] [rbp+C4h]int v18; // [rsp+108h] [rbp+E8h]int v19; // [rsp+10Ch] [rbp+ECh]int v20; // [rsp+110h] [rbp+F0h]int v21; // [rsp+114h] [rbp+F4h]int k; // [rsp+134h] [rbp+114h]unsigned int v23; // [rsp+204h] [rbp+1E4h]unsigned int v24; // [rsp+208h] [rbp+1E8h]unsigned int v25; // [rsp+20Ch] [rbp+1ECh]v1 = &v5;for ( i = 78i64; i; --i ){*(_DWORD *)v1 = -858993460;v1 += 4;}sub_14001138E(&unk_140022066);v6 = *a1;v7 = a1[1];v8 = a1[2];srand(0xDEADC0DE);for ( j = 0; j < 32; ++j ){v10 = (unsigned __int8)v6;v11 = BYTE1(v6);v12 = BYTE2(v6);v13 = HIBYTE(v6);v14 = (unsigned __int8)v7;v15 = BYTE1(v7);v16 = BYTE2(v7);v17 = HIBYTE(v7);v18 = (unsigned __int8)v8;v19 = BYTE1(v8);v20 = BYTE2(v8);v21 = HIBYTE(v8);for ( k = 0; k < 4; ++k ){//相当于23*x+66*(&v10 + k) = (unsigned __int8)(23 * *((_BYTE *)&v10 + 4 * k) + 66);*(&v14 + k) = (unsigned __int8)(23 * *((_BYTE *)&v14 + 4 * k) + 66);*(&v18 + k) = (unsigned __int8)(23 * *((_BYTE *)&v18 + 4 * k) + 66);}//对应汇编代码:.text:00007FF6825219F6 movsxd  rax, [rbp+200h+var_EC]
    //.text:00007FF6825219FD imul    eax, [rbp+rax*4+200h+var_178], 17h
    //.text:00007FF682521A05 add     eax, 42h ; 'B'
    //.text:00007FF682521A08 and     eax, 0FFh
    //.text:00007FF682521A0D movsxd  rcx, [rbp+200h+var_EC]
    //.text:00007FF682521A14 mov     [rbp+rcx*4+200h+var_178], eaxv6 = (v13 << 24) | (v12 << 16) | (v11 << 8) | v10;//合并v7 = (v17 << 24) | (v16 << 16) | (v15 << 8) | v14;v8 = (v21 << 24) | (v20 << 16) | (v19 << 8) | v18;v23 = v7 >> 7;//类似于teav24 = rand() + v23;v25 = (v7 >> 15) ^ (v7 << 10) | 3;v6 += v24 + (rand() ^ v25);v23 = v8 >> 7;v24 = rand() + v23;v25 = (v8 >> 15) ^ (v8 << 10) | 3;v7 += v24 + (rand() ^ v25);v23 = v6 >> 7;v24 = rand() + v23;v25 = (v6 >> 15) ^ (v6 << 10) | 3;v8 += v24 + (rand() ^ v25);}*a1 = v6;a1[1] = v7;a1[2] = v8;return sub_14001132A(v4, &unk_14001ACC8);
    }
    
  • 关键是将这个算法逆了

  • 其中有很多rand,seed种子是固定的0xDEADC0DE所以每次rand生成的值我们都知道

  • //注:一些定义
    typedef unsigned char   uint8;
    #define _BYTE  uint8
    #define _WORD  uint16
    #define LOBYTE(w)           ((BYTE)(((DWORD_PTR)(w)) & 0xff))
    #define HIBYTE(w)           ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff))
    #define BYTEn(x, n)   (*((_BYTE*)&(x)+n))
    #define WORDn(x, n)   (*((_WORD*)&(x)+n))
    #define BYTE0(x)   BYTEn(x,  0)         // byte 0 (counting from 0)  添加此宏定义
    #define BYTE1(x)   BYTEn(x,  1)         // byte 1 (counting from 0)
    #define BYTE2(x)   BYTEn(x,  2)
    #define BYTE3(x)   BYTEn(x,  3)
    #define BYTE4(x)   BYTEn(x,  4)
    typedef unsigned long DWORD_PTR;
  • 注意:逆的时候记得求一下逆元:

  • print(inverse(23,256))  #167
    
  • 先把加密函数模拟出来,然后就更方便的编写解密函数

  • 注意unsigned,和IDA提取保持一只即可

  • #include <stdio.h>
    #include <stdlib.h>
    unsigned int my_rand[32][6]={0};
    void encrypt(char* data,int* data2)
    {int my_rand[6]={0};srand(0xDEADC0DE);for(int i=0;i<32;i++){for(int j=0;j<12;j++){data[j]=data[j]*23+66;}for(int z=0;z<3;z++){data2[z]=(data[4*z+3]<<24)|(data[4*z+2]<<16)|(data[4*z+1]<<8)|data[4*z];}for(int k=0;k<6;k++){my_rand[k]=rand();}int v23=data2[1]>>7;int v24=my_rand[0]+v23;int v25=(data2[1]>>15)^(data2[1]<<10)|3;data2[0]+=v24+(my_rand[1]^v25);v23=data2[2]>>7;v24=my_rand[2]+v23;v25=(data2[2]>>15)^(data2[2]<<10)|3;data2[1]+=v24+(my_rand[3]^v25);v23=data2[0]>>7;v24=my_rand[4]+v23;v25=(data2[0]>>15)^(data2[0]<<10)|3;data2[2]+=v24+(my_rand[5]^v25);}for(int z=0;z<3;z++){data[4*z]=(char)(data2[z]&0xff);data[4*z+1]=(char)((data2[z]>>8)&0xff);data[4*z+2]=(char)((data2[z]>>16)&0xff);data[4*z+3]=(char)((data2[z]>>24)&0xff);}
    }
    void decrypt(unsigned char* data,unsigned int* data2)
    {srand(0xDEADC0DE);for(int i=0;i<32;i++){for(int j=0;j<6;j++){my_rand[i][j]=rand();}}for(int i=31;i>=0;i--){unsigned int v23=data2[0]>>7;unsigned int v24=my_rand[i][4]+v23;unsigned int v25=(data2[0]>>15)^(data2[0]<<10)|3;data2[2]-=v24+(my_rand[i][5]^v25);v23=data2[2]>>7;v24=my_rand[i][2]+v23;v25=(data2[2]>>15)^(data2[2]<<10)|3;data2[1]-=v24+(my_rand[i][3]^v25);v23=data2[1]>>7;v24=my_rand[i][0]+v23;v25=(data2[1]>>15)^(data2[1]<<10)|3;data2[0]-=v24+(my_rand[i][1]^v25);for(int z=0;z<3;z++){data[4*z]=(unsigned char)(data2[z]&0xff);data[4*z+1]=(unsigned char)((data2[z]>>8)&0xff);data[4*z+2]=(unsigned char)((data2[z]>>16)&0xff);data[4*z+3]=(unsigned char)((data2[z]>>24)&0xff);}for(int j=0;j<12;j++){data[j]=167*(data[j]-66 & 0xff);}for(int z=0;z<3;z++){data2[z]=(data[4*z+3]<<24)|(data[4*z+2]<<16)|(data[4*z+1]<<8)|data[4*z];}}
    }int main() {unsigned char data[] ={0x48, 0x4D, 0x3B, 0xA0, 0x27, 0x31, 0x28, 0x54,0x6D, 0xF1, 0x21, 0x35, 0x18, 0x73, 0x6A, 0x4C,0x71, 0x3B, 0xBD, 0x98, 0xB6, 0x5A, 0x77, 0x2D,0x0B, 0x2B, 0xCB, 0x9B, 0xE4, 0x8A, 0x4C, 0xA9,0x5C, 0x4F, 0x1B, 0xF1, 0x98, 0x3D, 0x30, 0x59,0x3F, 0x14, 0xFC, 0x7A, 0xF4, 0x64, 0x02, 0x2B};unsigned int data2[]={0xA03B4D48, 0x54283127, 0x3521F16D, 0x4C6A7318, 0x98BD3B71, 0x2D775AB6, 0x9BCB2B0B, 0xA94C8AE4, 0xF11B4F5C, 0x59303D98, 0x7AFC143F, 0x2B0264F4};decrypt((unsigned char*)data,(unsigned int*)data2);decrypt((unsigned char*)data+12,(unsigned int*)data2+3);decrypt((unsigned char*)data+24,(unsigned int*)data2+6);decrypt((unsigned char*)data+36,(unsigned int*)data2+9);puts(data);return 0;
    }
  • 这里脚本我用了两个数组,好像一个就可以hhh

  • 运行得到:flag{1CpOVOIeB1d2FcYUvnN1k5PbfMzMNzUzUgV6mB7hXF}

  • 评价:个人脚本能力依托答辩www

四. StateMachine

  • 看到init函数里面的src和四个看着像密钥的东西,其实可以先猜一下是tea,但是没有delta(十分逆向七分猜(bushi))

  • __int64 __fastcall main(int a1, char **a2, char **a3)
    {puts("Welcome! Drill Down.");sub_21D8("Welcome! Drill Down.", a2);sub_2407();putchar(10);return 0LL;
    }unsigned __int64 sub_21D8()  //init
    {int i; // [rsp+4h] [rbp-43Ch]__int64 src[4]; // [rsp+10h] [rbp-430h] BYREFchar v3[1024]; // [rsp+30h] [rbp-410h] BYREFunsigned __int64 v4; // [rsp+438h] [rbp-8h]v4 = __readfsqword(0x28u);for ( i = 0; i <= 9; ++i )byte_5104[8 * i] = 1;byte_5154 = 1;byte_5558 = 1;byte_5621 = 1;qmemcpy(v3, &unk_3020, 0x157uLL);memset(&v3[343], 0, 681);qmemcpy(&unk_5158, v3, 0x400uLL);memset(&byte_5559[40], 0, 0x2CuLL);byte_5559[40] = 119;byte_5559[41] = 105;byte_5559[42] = 110;byte_5559[43] = 33;byte_5559[44] = 102;byte_5559[45] = 97;byte_5559[46] = 105;byte_5559[47] = 108;  //win!failbyte_5559[24] = 17;byte_5559[28] = 34;byte_5559[32] = -120;byte_5559[36] = -1;src[0] = 0x3A84F4140FB6B1B8LL;src[1] = 0xB485900290CE01CBLL;src[2] = 0x2D7458B7EA807F7CLL;src[3] = 0LL;memcpy(&byte_5559[88], src, 0x18uLL);return v4 - __readfsqword(0x28u);
    }int sub_2407()
    {int i; // [rsp+8h] [rbp-8h]int j; // [rsp+Ch] [rbp-4h]for ( i = 0; i <= 9; ++i )pthread_create(&qword_5080[i], 0LL, start_routine, (char *)&unk_5020 + 4 * i);//根据地址,确定thread[0-9]pthread_create(&th, 0LL, sub_1C41, 0LL);//th=thread[10]pthread_create(&qword_50D8, 0LL, sub_1EFF, 0LL);//50D8=thread[11]pthread_create(&qword_50E0, 0LL, sub_1F91, 0LL);//50E0=thread[12]for ( j = 0; j <= 9; ++j )pthread_join(qword_5080[j], 0LL);pthread_join(th, 0LL);pthread_join(qword_50D8, 0LL);return pthread_join(qword_50E0, 0LL);
    }
    
  • void __fastcall __noreturn start_routine(int *a1)
    {int v1; // eaxint i; // [rsp+18h] [rbp-18h]int v3; // [rsp+1Ch] [rbp-14h]int v4; // [rsp+20h] [rbp-10h]int v5; // [rsp+24h] [rbp-Ch]int v6; // [rsp+28h] [rbp-8h]int v7; // [rsp+2Ch] [rbp-4h]v3 = *a1;for ( i = 1; i <= (int)&unk_F423F; ++i ){*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329);while ( !byte_5154[1316 * i - 1316] );while ( !byte_5558[1316 * i - 1316] );v4 = sub_1249((unsigned int)(i - 1), *((unsigned int *)&unk_5150 + 329 * i - 329));if ( v4 != 29 || v3 ){if ( v4 == 31 )break;if ( v3 == (unsigned int)sub_1321((unsigned int)(i - 1),(unsigned int)(*((_DWORD *)&unk_5150 + 329 * i - 329) + 5)) ){if ( (v4 & 0x18) != 0 ){if ( (v4 & 0x18) == 8 ){v6 = sub_13F9((unsigned int)(i - 1), (unsigned int)(*((_DWORD *)&unk_5150 + 329 * i - 329) + 9));switch ( v4 & 7 ){case 0:*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = v6 + *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329);break;case 1:*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329) - v6;break;case 2:*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = v6;break;case 3:*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329) << v6;break;case 4:*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329) >> v6;break;default:break;}}else if ( v4 == 16 ){v5 = sub_1321((unsigned int)(i - 1), (unsigned int)(*((_DWORD *)&unk_5150 + 329 * i - 329) + 9));do{while ( !byte_5104[1316 * i - 1316 + 8 * v5] );}while ( !byte_5621[1316 * i - 1316] );*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = (unsigned __int8)byte_5559[1316 * i- 1316+ *((unsigned int *)&unk_5100+ 329 * i+ 2 * v5- 329)];}}else{v7 = sub_1321((unsigned int)(i - 1), (unsigned int)(*((_DWORD *)&unk_5150 + 329 * i - 329) + 9));while ( !byte_5104[1316 * i - 1316 + 8 * v7] );v1 = v4 & 7;if ( v1 == 3 ){*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v7 - 329) ^ *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329);}else if ( (v4 & 7u) <= 3 ){if ( v1 == 2 ){*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v7 - 329);}else if ( (v4 & 7) != 0 ){*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329)- *((_DWORD *)&unk_5100 + 329 * i + 2 * v7 - 329);}else{*((_DWORD *)&unk_5100 + 329 * i + 2 * v3) = *((_DWORD *)&unk_5100 + 329 * i + 2 * v3 - 329)+ *((_DWORD *)&unk_5100 + 329 * i + 2 * v7 - 329);}}}}}else{*((_DWORD *)&unk_5100 + 329 * i) = getchar();}byte_5104[1316 * i + 8 * v3] = 1;}pthread_exit(0LL);
    }
    
  • void __fastcall __noreturn sub_1C41(void *a1)
    {int i; // [rsp+4h] [rbp-Ch]int v2; // [rsp+8h] [rbp-8h]int v3; // [rsp+Ch] [rbp-4h]for ( i = 1; i <= &unk_1869F; ++i ){*(&unk_5150 + 329 * i) = *(&unk_5150 + 329 * i - 329);while ( !byte_5558[1316 * i - 1316] );v2 = sub_1249((i - 1), *(&unk_5150 + 329 * i - 329));if ( (v2 & 0x18) != 0 && (v2 & 0x18) != 16 ){if ( (v2 & 0x18) == 24 ){*(&unk_5150 + 329 * i) = *(&unk_5150 + 329 * i - 329) + 5;if ( v2 == 28 ){while ( !*(&byte_5104 + 1316 * i - 1316) );putchar(*(&unk_5100 + 329 * i - 329));}if ( v2 == 31 )break;}else if ( (v2 & 0x18) == 8 ){*(&unk_5150 + 329 * i) = *(&unk_5150 + 329 * i - 329) + 25;if ( v2 == 15 ){v3 = sub_1321((i - 1), (*(&unk_5150 + 329 * i - 329) + 5));while ( !*(&byte_5104 + 1316 * i + 8 * v3 - 1316) );if ( *(&unk_5100 + 329 * i + 2 * v3 - 329) )*(&unk_5150 + 329 * i) = sub_13F9((i - 1), (*(&unk_5150 + 329 * i - 329) + 9));}}}else{*(&unk_5150 + 329 * i) = *(&unk_5150 + 329 * i - 329) + 13;}byte_5154[1316 * i] = 1;}pthread_exit(0LL);
    }
  • void __fastcall __noreturn sub_1EFF(void *a1)
    {int i; // [rsp+Ch] [rbp-4h]for ( i = 1; i <= &unk_1869F; ++i ){memcpy(&unk_5100 + 1316 * i + 88, &unk_5100 + 1316 * i - 1228, 0x400uLL);byte_5558[1316 * i] = 1;}pthread_exit(0LL);
    }
    
  • void __fastcall __noreturn sub_1F91(void *a1)
    {int i; // [rsp+0h] [rbp-10h]int v2; // [rsp+4h] [rbp-Ch]int v3; // [rsp+8h] [rbp-8h]int v4; // [rsp+Ch] [rbp-4h]for ( i = 1; i <= &unk_1869F; ++i ){memcpy(&unk_5100 + 1316 * i + 1113, &unk_5100 + 1316 * i - 203, 0xC8uLL);while ( !byte_5154[1316 * i - 1316] );while ( !byte_5558[1316 * i - 1316] );v2 = sub_1249(i - 1, *(&unk_5150 + 329 * i - 329));if ( v2 == 17 ){v3 = sub_1321((i - 1), (*(&unk_5150 + 329 * i - 329) + 5));v4 = sub_1321((i - 1), (*(&unk_5150 + 329 * i - 329) + 9));do{while ( !byte_5104[1316 * i - 1316 + 8 * v3] );}while ( !byte_5104[1316 * i - 1316 + 8 * v4] );byte_5559[1316 * i + *(&unk_5100 + 329 * i + 2 * v4 - 329)] = *(&unk_5100 + 329 * i + 2 * v3 - 329);}else if ( v2 == 31 ){break;}byte_5621[1316 * i] = 1;}pthread_exit(0LL);
    }
    
  • __int64 __fastcall sub_1249(int a1, unsigned int a2)
    {unsigned int v3; // [rsp+Ch] [rbp-Ch]unsigned int v4; // [rsp+10h] [rbp-8h]v3 = a2 >> 3;v4 = a2 & 7;if ( v4 > 3 )return (*(&unk_5158 + 1316 * a1 + v3) >> v4) | ((((1 << ((a2 & 7) - 3)) - 1) & *(&unk_5158 + 1316 * a1 + v3 + 1)) << (8 - v4));elsereturn (*(&unk_5158 + 1316 * a1 + v3) >> v4) & 0x1F;
    }
    
  • __int64 __fastcall sub_1321(int a1, unsigned int a2)
    {unsigned int v3; // [rsp+Ch] [rbp-Ch]unsigned int v4; // [rsp+10h] [rbp-8h]v3 = a2 >> 3;v4 = a2 & 7;if ( v4 > 4 )return (*(&unk_5158 + 1316 * a1 + v3) >> v4) | ((((1 << ((a2 & 7) - 4)) - 1) & *(&unk_5158 + 1316 * a1 + v3 + 1)) << (8 - v4));elsereturn (*(&unk_5158 + 1316 * a1 + v3) >> v4) & 0xF;
    }
    
  • __int64 __fastcall sub_13F9(int a1, unsigned int a2)
    {unsigned int v3; // [rsp+Ch] [rbp-Ch]v3 = a2 >> 3;if ( (a2 & 7) != 0 )return (*(&unk_5158 + 1316 * a1 + v3) >> (a2 & 7)) | (*(&unk_5158 + 1316 * a1 + v3 + 1) << (8 - (a2 & 7))) | ((((1 << (a2 & 7)) - 1) & *(&unk_5158 + 1316 * a1 + v3 + 2)) << (16 - (a2 & 7)));elsereturn *(&unk_5158 + 1316 * a1 + v3) | (*(&unk_5158 + 1316 * a1 + v3 + 1) << 8);
    }
    
  • 翻译一下:

  • int __cdecl main(int argc, const char **argv, const char **envp)
    {puts("Welcome! Drill Down.");init_vm();run_vm();putchar(10);return 0;
    }void __fastcall init_vm()
    {int i; // [rsp+4h] [rbp-43Ch]__int64 src[4]; // [rsp+10h] [rbp-430h] BYREFchar v2[1024]; // [rsp+30h] [rbp-410h] BYREFunsigned __int64 v3; // [rsp+438h] [rbp-8h]v3 = __readfsqword(0x28u);for ( i = 0; i <= 9; ++i )vm_ins[0].reg[i].ready = 1;vm_ins[0].pc_ready = 1;vm_ins[0].code_ready = 1;vm_ins[0].memory_ready = 1;qmemcpy(v2, byte_3020, 343uLL);v2[343] = 0;memset(&v2[344], 0, 680uLL);qmemcpy(vm_ins[0].code, v2, sizeof(vm_ins[0].code));memset(&vm_ins[0].memory[40], 0, 44uLL);qmemcpy(&vm_ins[0].memory[40], "win!fail", 8);vm_ins[0].memory[24] = 0x11;vm_ins[0].memory[28] = 0x22;vm_ins[0].memory[32] = 0x88;vm_ins[0].memory[36] = 0xFF;src[0] = 0x3A84F4140FB6B1B8LL;src[1] = 0xB485900290CE01CBLL;src[2] = 0x2D7458B7EA807F7CLL;src[3] = 0LL;memcpy(&vm_ins[0].memory[88], src, 0x18uLL);
    }void __fastcall run_vm()
    {int i; // [rsp+8h] [rbp-8h]int j; // [rsp+Ch] [rbp-4h]for ( i = 0; i <= 9; ++i )pthread_create(&threads[i], 0LL, (void *(*)(void *))start_routine, &dword_5020[i]);pthread_create(&threads[10], 0LL, (void *(*)(void *))prepare_pc, 0LL);pthread_create(&threads[11], 0LL, (void *(*)(void *))prepare_code, 0LL);pthread_create(&threads[12], 0LL, (void *(*)(void *))prepare_memory, 0LL);for ( j = 0; j <= 9; ++j )pthread_join(threads[j], 0LL);pthread_join(threads[10], 0LL);pthread_join(threads[11], 0LL);pthread_join(threads[12], 0LL);
    }void __fastcall start_routine(unsigned int *arg)
    {int v1; // eaxint i; // [rsp+18h] [rbp-18h]unsigned int reg_index; // [rsp+1Ch] [rbp-14h]unsigned int opcode; // [rsp+20h] [rbp-10h]unsigned int v5; // [rsp+24h] [rbp-Ch]unsigned int imm; // [rsp+28h] [rbp-8h]unsigned int v7; // [rsp+2Ch] [rbp-4h]reg_index = *arg;for ( i = 1; i <= 999999; ++i ){vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[reg_index].value;while ( !vm_ins[i - 1].pc_ready );while ( !vm_ins[i - 1].code_ready );opcode = fetch_opcode(i - 1, vm_ins[i - 1].pc);if ( opcode != 29 || reg_index ){if ( opcode == 31 )break;if ( reg_index == fetch_reg_index(i - 1, vm_ins[i - 1].pc + 5) ){if ( (opcode & 0x18) != 0 ){if ( (opcode & 0x18) == 8 ){imm = fetch_imm16(i - 1, vm_ins[i - 1].pc + 9);switch ( opcode & 7 ){case 0u:vm_ins[i].reg[reg_index].value = imm + vm_ins[i - 1].reg[reg_index].value;break;case 1u:vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[reg_index].value - imm;break;case 2u:vm_ins[i].reg[reg_index].value = imm;break;case 3u:vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[reg_index].value << imm;break;case 4u:vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[reg_index].value >> imm;break;default:break;}}else if ( opcode == 16 ){v5 = fetch_reg_index(i - 1, vm_ins[i - 1].pc + 9);do{while ( !vm_ins[i - 1].reg[v5].ready );}while ( !vm_ins[i - 1].memory_ready );vm_ins[i].reg[reg_index].value = (unsigned __int8)vm_ins[i - 1].memory[vm_ins[i - 1].reg[v5].value];}}else{v7 = fetch_reg_index(i - 1, vm_ins[i - 1].pc + 9);while ( !vm_ins[i - 1].reg[v7].ready );v1 = opcode & 7;if ( v1 == 3 ){vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[v7].value ^ vm_ins[i - 1].reg[reg_index].value;}else if ( (opcode & 7) <= 3 ){if ( v1 == 2 ){vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[v7].value;}else if ( (opcode & 7) != 0 ){vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[reg_index].value - vm_ins[i - 1].reg[v7].value;}else{vm_ins[i].reg[reg_index].value = vm_ins[i - 1].reg[reg_index].value + vm_ins[i - 1].reg[v7].value;}}}}}else{vm_ins[i].reg[0].value = getchar();}vm_ins[i].reg[reg_index].ready = 1;}pthread_exit(0LL);
    }void __fastcall __noreturn prepare_pc(void *arg)
    {int i; // [rsp+4h] [rbp-Ch]unsigned int v2; // [rsp+8h] [rbp-8h]unsigned int v3; // [rsp+Ch] [rbp-4h]for ( i = 1; i <= 99999; ++i ){vm_ins[i].pc = vm_ins[i - 1].pc;while ( !vm_ins[i - 1].code_ready );v2 = fetch_opcode(i - 1, vm_ins[i - 1].pc);if ( (v2 & 0x18) != 0 && (v2 & 0x18) != 0x10 ){if ( (v2 & 0x18) == 0x18 ){vm_ins[i].pc = vm_ins[i - 1].pc + 5;if ( v2 == 28 ){while ( !vm_ins[i - 1].reg[0].ready );putchar((char)vm_ins[i - 1].reg[0].value);}if ( v2 == 31 )break;}else if ( (v2 & 0x18) == 8 ){vm_ins[i].pc = vm_ins[i - 1].pc + 25;if ( v2 == 15 ){v3 = fetch_reg_index(i - 1, vm_ins[i - 1].pc + 5);while ( !vm_ins[i - 1].reg[v3].ready );if ( vm_ins[i - 1].reg[v3].value )vm_ins[i].pc = fetch_imm16(i - 1, vm_ins[i - 1].pc + 9);}}}else{vm_ins[i].pc = vm_ins[i - 1].pc + 13;}vm_ins[i].pc_ready = 1;}pthread_exit(0LL);
    }void __fastcall __noreturn prepare_code(void *arg)
    {int i; // [rsp+Ch] [rbp-4h]for ( i = 1; i <= 99999; ++i ){memcpy(vm_ins[i].code, vm_ins[i - 1].code, sizeof(vm_ins[i].code));vm_ins[i].code_ready = 1;}pthread_exit(0LL);
    }void __fastcall __noreturn prepare_memory(void *arg)
    {int i; // [rsp+0h] [rbp-10h]unsigned int v2; // [rsp+4h] [rbp-Ch]unsigned int v3; // [rsp+8h] [rbp-8h]unsigned int v4; // [rsp+Ch] [rbp-4h]for ( i = 1; i <= 99999; ++i ){memcpy(vm_ins[i].memory, vm_ins[i - 1].memory, sizeof(vm_ins[i].memory));while ( !vm_ins[i - 1].pc_ready );while ( !vm_ins[i - 1].code_ready );v2 = fetch_opcode(i - 1, vm_ins[i - 1].pc);if ( v2 == 17 ){v3 = fetch_reg_index(i - 1, vm_ins[i - 1].pc + 5);v4 = fetch_reg_index(i - 1, vm_ins[i - 1].pc + 9);do{while ( !vm_ins[i - 1].reg[v3].ready );}while ( !vm_ins[i - 1].reg[v4].ready );vm_ins[i].memory[vm_ins[i - 1].reg[v4].value] = vm_ins[i - 1].reg[v3].value;}else if ( v2 == 31 ){break;}vm_ins[i].memory_ready = 1;}pthread_exit(0LL);
    }
    
  • 开了很多并行独立程序,实现了一个类似于实际 CPU 执行的 vm,在计算机使用者的角度不用考虑 CPU 的具体设计,只要知道指令是顺序执行的就行。

  • 下面进行提取执行的指令:

  • codes = open('./vm', 'rb').read()[0x3020: 0x3020 + 0x157]
    codes = ''.join(bin(i)[2: ].rjust(8, '0')[:: -1] for i in codes)def fetch_imm(codes, pc, size):assert pc + size <= len(codes)value = int(codes[pc: pc + size][:: -1], 2)return value, pc + sizedef fetch_opcode(codes, pc):return fetch_imm(codes, pc, 5)def fetch_reg_index(codes, pc):return fetch_imm(codes, pc, 4)def fetch_imm16(codes, pc):return fetch_imm(codes, pc, 16)regs = ['rax', 'rbp', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15']print('.intel_syntax noprefix')
    pc = 0
    while pc < len(codes):print('_0x%04x: ' % pc, end='')opcode, pc = fetch_opcode(codes, pc)if opcode == 15:dreg, pc = fetch_reg_index(codes, pc)imm, pc = fetch_imm16(codes, pc)print('cmp %s, 0\n  jnz _0x%04x' % (regs[dreg], imm))elif opcode == 17:dreg, pc = fetch_reg_index(codes, pc)sreg, pc = fetch_reg_index(codes, pc)print('mov [%s + 0x2000], %s' % (regs[sreg], regs[dreg]))elif opcode == 28:print('call m_putchar')elif opcode == 29:print('call m_getchar')elif opcode == 31:print('ret')elif opcode == 16:dreg, pc = fetch_reg_index(codes, pc)sreg, pc = fetch_reg_index(codes, pc)print('mov %s, [%s + 0x2000]' % (regs[dreg], regs[sreg]))elif opcode & 0x18 == 8:dreg, pc = fetch_reg_index(codes, pc)imm, pc = fetch_imm16(codes, pc)op = ['add', 'sub', 'mov', 'shl', 'shr'][opcode & 7]print('%s %s, 0x%x' % (op, regs[dreg], imm))elif opcode & 0x18 == 0:dreg, pc = fetch_reg_index(codes, pc)sreg, pc = fetch_reg_index(codes, pc)op = ['add', 'sub', 'mov', 'xor'][opcode & 7]print('%s %s, %s' % (op, regs[dreg], regs[sreg]))else:assert False, hex(opcode)
  • 运行,得到指令存在main.s中,gcc -c ./main.s -o main.o,编译好用IDA分析。

  • 得到:

  • __int64 __fastcall 0x0000(__int64 a1, __int64 a2)
    {__int64 v2; // rbp__int64 v3; // r8__int64 v4; // rax__int64 v5; // r8__int64 v6; // r8__int64 v7; // rbpunsigned __int64 v8; // r10__int64 v9; // r8unsigned __int64 v10; // r11__int64 v11; // rbp__int64 v12; // rax__int64 v13; // r13__int64 v14; // rax__int64 v15; // rax__int64 v16; // r14__int64 v17; // rax__int64 v18; // rax__int64 v19; // r13__int64 v20; // rax__int64 v21; // rax__int64 v22; // r14__int64 v23; // rax__int64 v24; // rbp__int64 v25; // r8__int64 v26; // r9__int64 v27; // rdx__int64 v28; // rcx__int64 v29; // r8__int64 v30; // r9__int64 v31; // rdx__int64 v32; // rcx__int64 v33; // r8__int64 v34; // r9__int64 v35; // rdx__int64 v36; // rcx__int64 v37; // r8__int64 v38; // r9v2 = 24i64;v3 = 0i64;do{v4 = m_getchar(a1, a2, v3);*(_QWORD *)(v5 + 0x2000) = v4;--v2;v3 = v5 + 1;}while ( v2 );do{v6 = 4i64;v7 = 8i64 * MEMORY[0x2030];v8 = 0i64;do{v8 = *(_QWORD *)(v7 + 0x2000) ^ (v8 << 8);++v7;--v6;}while ( v6 );v9 = 4i64;v10 = 0i64;do{v10 = *(_QWORD *)(v7 + 0x2000) ^ (v10 << 8);++v7;--v9;}while ( v9 );v11 = 32i64;do{v9 += 1126266966i64;v12 = 4i64;v13 = 0i64;do{v14 = v12 + 23;v13 = *(_QWORD *)(v14 + 0x2000) ^ (v13 << 8);v12 = v14 - 24;}while ( v12 );v15 = 4i64;v16 = 0i64;do{v17 = v15 + 27;v16 = *(_QWORD *)(v17 + 0x2000) ^ (v16 << 8);v15 = v17 - 28;}while ( v15 );v8 += (v16 + (v10 >> 5)) ^ (v10 + v9) ^ (v13 + 16 * v10);v18 = 4i64;v19 = 0i64;do{v20 = v18 + 31;v19 = *(_QWORD *)(v20 + 0x2000) ^ (v19 << 8);v18 = v20 - 32;}while ( v18 );v21 = 4i64;v22 = 0i64;do{v23 = v21 + 35;v22 = *(_QWORD *)(v23 + 0x2000) ^ (v22 << 8);v21 = v23 - 36;}while ( v21 );v10 += (v22 + (v8 >> 5)) ^ (v8 + v9) ^ (v19 + 16 * v8);--v11;}while ( v11 );v24 = 8i64 * MEMORY[0x2030] + 64;v25 = 8i64 * MEMORY[0x2030] + 68;v26 = 4i64;do{--v26;*(_QWORD *)(v24 + 0x2000) = v8;*(_QWORD *)(v25 + 0x2000) = v10;++v24;++v25;v8 >>= 8;v10 >>= 8;}while ( v26 );++MEMORY[0x2030];}while ( MEMORY[0x2030] != 3i64 );if ( MEMORY[0x2058] != MEMORY[0x2040] )m_putchar(a1, a2, 88i64, 24i64);elsem_putchar(a1, a2, 89i64, 23i64);m_putchar(v28, v27, v29, v30);m_putchar(v32, v31, v33, v34);return m_putchar(v36, v35, v37, v38);
    }
    
  • 就是tea加密,套脚本解密即可

  • from ctypes import *def encrypt(v, k):v0 = c_uint32(v[0])v1 = c_uint32(v[1])sum1 = c_uint32(0)delta = 0x43217856for i in range(32):sum1.value += deltav0.value += ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])v1.value += ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])return v0.value, v1.valuedef decrypt(v, k):v0 = c_uint32(v[0])v1 = c_uint32(v[1])delta = 0x43217856sum1 = c_uint32(delta*32)for i in range(32):v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3])v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1])sum1.value -= deltareturn long_to_bytes(v0.value)+long_to_bytes(v1.value)if __name__ == '__main__':a=[0x0FB6B1B8, 0x3A84F414]a1=[0x90CE01CB,0xB4859002]a2=[0xEA807F7C,0x2D7458B7]k=[17,34,0x88,0xFF]res= decrypt(a, k)+decrypt(a1,k)+decrypt(a2,k)print("解密后数据:", res)
  • 得到flag:flag{FSM_A_M4j0r_In_CO!}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/583576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

拓扑排序笔记

这段代码通过拓扑排序对有向无环图进行排序。它创建了一个图结构&#xff0c;其中包含节点、邻接表和入度数组。然后&#xff0c;通过输入添加了一些边&#xff0c;创建了图的结构。接着&#xff0c;使用拓扑排序算法对图进行排序&#xff0c;并将排序后的结果打印输出。 首先…

C++如何获取随机浮点数

在C中&#xff0c;可以使用标准库中的<random>头文件来生成随机浮点数。以下是一个简单的例子&#xff1a; #include <iostream> #include <random>int main() {// 创建一个随机数生成器对象std::random_device rd;std::mt19937 gen(rd());// 创建一个均匀分…

使用FFmpeg进行录屏

不用下载那些录屏软件&#xff0c;安装了FFmpeg的话&#xff0c;直接实现 使用FFmpeg进行屏幕录制可以通过以下步骤实现&#xff1a; 安装FFmpeg&#xff1a;首先需要在您的系统上安装FFmpeg。可以通过包管理器&#xff08;如apt、yum等&#xff09;或从官方网站下载并编译安装…

openGauss学习笔记-176 openGauss 数据库运维-实例主备切换

文章目录 openGauss学习笔记-176 openGauss 数据库运维-实例主备切换176.1 操作场景176.2 操作步骤176.3 示例176.4 错误排查176.5 异常处理 openGauss学习笔记-176 openGauss 数据库运维-实例主备切换 176.1 操作场景 openGauss在运行过程中&#xff0c;数据库管理员可能需要…

linux卸载小皮面板phpstudy教程

千万不要直接删文件夹! 千万不要直接删文件夹! 千万不要直接删文件夹! 我就是按照网上搜索的教程,直接删了,然后 系统就不停的崩溃 生成这种文件: -rw------- 1 root root 223M Dec 28 22:36 core.31544 -rw------- 1 root root 223M Dec 28 18:04…

基于elemen二次封装弹窗组件

效果&#xff1a; 一、自定义内容类型弹窗 <!-- title&#xff1a;对话框的标题confirmLoading&#xff1a;当前是否处于提交中titleCenter&#xff1a;对话框标题居中方式footerCenter&#xff1a;底部按钮的对其方式visible&#xff1a;是否显示弹窗width&#xff1a;设置…

【机器学习】Boosting算法-AdaBoost算法

一、AdaBoost理论 随机森林与AdaBoost算法的比较 AdaBoost算法 AdaBoost模型训练误差分析 从广义加法模型推导出AdaBoost训练算法&#xff0c;从而给出AdaBoost算法在理论上的解释 各种AdaBoost算法对比 标准AdaBoost算法只能用于二分类问题&#xff0c;它的改进型可以用于多分…

泽攸科技PECVD设备助力开发新型石墨烯生物传感器

近日&#xff0c;松山湖材料实验室许智团队与清华大学符汪洋合作在纳米领域头部期刊《Small》上发表了一项引人注目的研究成果&#xff0c;题为“Ultrasensitive biochemical sensing platform enabled by directly grown graphene on insulator”&#xff08;硅晶圆上直接生长…

Seatunnel MYSQL数据同步

Seatunnel MYSQL数据同步 Docker镜像 Seatunnel Docker image镜像制作-CSDN博客 数据库表 #source库 CREATE TABLE IF NOT EXISTS student(id INT UNSIGNED AUTO_INCREMENT,name VARCHAR(100) NOT NULL,age int unsigned,gender char(8) NOT NULL,PRIMARY KEY ( id ) )ENGINE…

监控易:智能告警管理,让运维无忧

监控易&#xff0c;一款卓越的运维管理工具&#xff0c;以其出色的告警中心功能帮助用户有效应对各类设备告警信息&#xff0c;保障企业IT系统的稳定运行。以下是对监控易告警中心功能的详细介绍。 一、实时告警管理&#xff0c;让设备状态尽在掌控 监控易的告警中心以列表形式…

H5移动端使用html2canvas点击按钮生成图片并下载

需求&#xff1a;点击按钮下载当前页的图片 可以用html2canvas生成canvas&#xff0c;再由canvas生成base64图片 npm install html2canvas --save import html2canvas from "html2canvas"; 遇到的问题 在保存的时候会遇到图片模糊的问题。 解决方案&#xff1a…

基于Java SSM框架实现艺诚美业美容美发管理系统项目【项目源码+论文说明】

基于java的SSM框架实现艺诚美业美容美发管理系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们…

node fs模块读取文件 readFile、readFileSync、fsPromises.readFile、createReadStream

文章目录 1.读取文件1.1 readFile1.2 readFileSync1.3 fsPromises.readFile&#xff1a;promise的写法1.4 fs.createReadStream 1.读取文件 readFile&#xff1a;异步读取文件readFileSync&#xff1a;同步读取文件fsPromises.readFile&#xff1a;promise的写法 需要注意的是…

为什么ChatGPT采用SSE协议而不是Websocket?

在探索ChatGPT的使用过程中&#xff0c;我们发现GPT采用了流式数据返回的方式。理论上&#xff0c;这种情况可以通过全双工通信协议实现持久化连接&#xff0c;或者依赖于基于EventStream的事件流。然而&#xff0c;ChatGPT选择了后者&#xff0c;也就是本文即将深入探讨的SSE&…

多账号统一登录,如何设计

多账号统一登录是一种常见的需求&#xff0c;特别是在大型应用或平台中。设计一个多账号统一登录系统需要考虑以下几个方面&#xff1a; 1. 用户标识&#xff1a;每个用户在系统中应有唯一的标识&#xff0c;可以是用户名、邮箱、手机号等。这些标识应该与账号信息关联&#x…

MC17XS6500 高边驱动芯片寄存器的介绍

本文主要是对 MC17XS6500 高边驱动芯片寄存器进行的介绍&#xff0c;MC17XS6500 寄存器分为输入寄存器和输出寄存器&#xff0c;对常用的几个输入和输出寄存器的功能和配置进行了介绍。本文中&#xff0c;世平集团基于 FlagChips FC7300 HV BMS 方案&#xff0c;对 MC17XS6500 …

Python 内置高阶函数练习(Leetcode500.键盘行)

Python 内置高阶函数练习&#xff08;Leetcode500.键盘行&#xff09; 【一】试题 &#xff08;1&#xff09;地址&#xff1a; 500. 键盘行 - 力扣&#xff08;LeetCode&#xff09; &#xff08;2&#xff09;题目 给你一个字符串数组 words &#xff0c;只返回可以使用在…

【算法】王晓东期末考题总结(一)

文章目录 分治动态规划贪心算法 分治 实现思路可参考&#xff1a;【算法】分治算法 之前写的Java版有思路。 二分搜索 #include <iostream> #include <vector>using namespace std;// 二分搜索函数 int binarySearch(const vector<int>& array, int t…

Flask笔记四之异常处理

本文首发于公众号&#xff1a;Hunter后端 原文链接&#xff1a;Flask笔记四之异常处理 在系统运行中&#xff0c;有时候需要处理报错异常。 异常的来源可能是系统在运行中的报错&#xff0c;比如错误的运算的有 1/0 这种等&#xff0c;还有的是访问了不存在接口&#xff0c;又…

docker 部署mysql

docker pull mysql:5.7.25 docker run \ --name mysql \ -e MYSQL_ROOT_PASSWORD123456 \ -p 3306:3306 \ -v /soft/mysql/conf:/etc/mysql \ -v /soft/mysql/data:/var/lib/mysql \-d \mysql:5.7.25安装好之后可以用命令行进入查看 docker exec -it mysql mysql -u root -p密…