一. 安全编程
-
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; }
-
找到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 = 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!}