鹏城杯2023初赛 re WP
一. 安全编程
-
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; // rax HMODULE ModuleHandleA; // rax char *v2; // rdx int v3; // ecx char *v4; // r10 __int64 v5; // r11 char *v6; // r8 char *v7; // rdx char i; // r9 char *v9; // rcx void (*v10)(void); // r9 unsigned __int64 v11; // rax char v13[14]; // [rsp+2Ah] [rbp-Eh] BYREF v0 = __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; // rdi int v4; // edx unsigned int v5; // eax signed __int64 v6; // rdi void *v7; // rsp void *v8; // rsp char *v9; // rax char *v10; // rdx char v11; // r8 char 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] BYREF char 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; // r12 int v6; // r10d __int128 *v7; // r11 int v8; // eax char v9; // bl char *result; // rax __int64 v11; // rbx __int64 v12; // r11 __int64 v13; // rdi char v14; // al char v15; // r10 __int128 v16[18]; // [rsp+0h] [rbp-128h] BYREF LOBYTE(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; }
-
找到key
v14 = '!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 = 0 for i in range(256): j = (j + S[i] + key[i % key_length]) % 256 S[i], S[j] = S[j], S[i] return S def PRGA(S): i = 0 j = 0 while True: i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] K = S[(S[i] + S[j]) % 256] yield K def RC4(key): S = KSA(key) keystream = PRGA(S) return keystream if __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"); else sub_1400111A4("fail"); return 0i64; } else { sub_1400111A4("fail"); return 0i64; } }
-
看着逻辑很简单,就只有一个加密函数
-
__int64 __fastcall sub_140011870(int *a1) { char *v1; // rdi __int64 i; // rcx char v4[32]; // [rsp+0h] [rbp-20h] BYREF char v5; // [rsp+20h] [rbp+0h] BYREF unsigned 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], eax v6 = (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;//类似于tea v24 = 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] BYREF char v3[1024]; // [rsp+30h] [rbp-410h] BYREF unsigned __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!fail byte_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; // eax int 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)); else return (*(&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)); else return (*(&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))); else return *(&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] BYREF char v2[1024]; // [rsp+30h] [rbp-410h] BYREF unsigned __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; // eax int 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 + size def 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; // rbp unsigned __int64 v8; // r10 __int64 v9; // r8 unsigned __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; // r9 v2 = 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); else m_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 = 0x43217856 for i in range(32): sum1.value += delta v0.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.value def decrypt(v, k): v0 = c_uint32(v[0]) v1 = c_uint32(v[1]) delta = 0x43217856 sum1 = 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 -= delta return 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!}