标题好长= =
Rev
shellcode
拿到题目
目录结构
.
├── main.bat
├── part1.exe
├── part2.bin
└── part3.exe
cat main.bat
set /p FLAG=please input your flag: start /MIN part1.exe echo checking... sleep 2 && part3
先看part1,很容易发现是Golang写的= =,ida7.6打开
我用的freeware版本,不知道我的网络还是啥,提示连接不到远程服务器,所以没法反编译成伪代码,不过不碍事,看了看汇编,大体知道这是一个HTTP Server,绑定本地端口8080,开了两条api
/hello:name
,/shell/:key
直接看part3,
int __cdecl main(int argc, const char **argv, const char **envp) { HANDLE v3; // eax void *v4; // esi int result; // eax DWORD v6; // edi void (*v7)(void); // eax void (*v8)(void); // [esp+8h] [ebp-Ch] DWORD NumberOfBytesRead; // [esp+Ch] [ebp-8h] BYREF v3 = CreateFileA("part2.bin", 0x80000000, 0, 0, 4u, 0, 0); v4 = v3; if ( v3 == (HANDLE)-1 ) { sub_401010("CreateFile Error"); result = -1; } else { v6 = GetFileSize(v3, 0); v7 = (void (*)(void))VirtualAlloc(0, v6, 0x1000u, 0x40u); v8 = v7; if ( v7 ) { NumberOfBytesRead = 0; ReadFile(v4, v7, v6, &NumberOfBytesRead, 0); v8(); result = 0; } else { sub_401010("VirtualAlloc Error"); CloseHandle(v4); result = -1; } } return result; }
加载了part2.bin的shellcode,上动态调试
int sub_1E0005() { char v1[8]; // [esp+0h] [ebp-BCh] BYREF int (__stdcall *v2)(char *, int, _DWORD, _DWORD, _DWORD); // [esp+8h] [ebp-B4h] void (__stdcall *v3)(int); // [esp+Ch] [ebp-B0h] int (__stdcall *v4)(int, int, int, int *); // [esp+10h] [ebp-ACh] int (__stdcall *v5)(_DWORD, unsigned __int8 *, int, int); // [esp+14h] [ebp-A8h] void (__stdcall *v6)(int, _DWORD, _DWORD, _DWORD, _DWORD); // [esp+18h] [ebp-A4h] int (__stdcall *v7)(int, char *, int, _DWORD, _DWORD, int, _DWORD, _DWORD); // [esp+20h] [ebp-9Ch] int (__stdcall *v8)(int, char *, char *, char *, _DWORD, _DWORD, int, _DWORD); // [esp+24h] [ebp-98h] int v9; // [esp+28h] [ebp-94h] int (*v10)(void); // [esp+2Ch] [ebp-90h] int v11; // [esp+30h] [ebp-8Ch] int v12; // [esp+34h] [ebp-88h] int v13; // [esp+38h] [ebp-84h] int v14; // [esp+3Ch] [ebp-80h] char v15[16]; // [esp+40h] [ebp-7Ch] BYREF char v16[8]; // [esp+50h] [ebp-6Ch] BYREF int v17; // [esp+58h] [ebp-64h] int v18; // [esp+5Ch] [ebp-60h] BYREF char v19[4]; // [esp+60h] [ebp-5Ch] BYREF char v20[40]; // [esp+64h] [ebp-58h] BYREF char v21[16]; // [esp+8Ch] [ebp-30h] BYREF char v22[12]; // [esp+9Ch] [ebp-20h] BYREF char v23[12]; // [esp+A8h] [ebp-14h] BYREF int v24; // [esp+B4h] [ebp-8h] char v25[4]; // [esp+B8h] [ebp-4h] BYREF ((void (__cdecl *)(char *))unk_1E0480)(v1); strcpy(v15, "Hello GuiShou"); strcpy(v19, "Tip"); v11 = v5(0, &unk_400000, 4096, 64); v10 = (int (*)(void))v5(0, &unk_400000, 4096, 64); v9 = 0x4000000; strcpy(v22, "127.0.0.1"); strcpy(v16, "8080"); strcpy(v25, "GET"); strcpy(v21, "/shell/voidrn"); strcpy(v20, "Mozilla/5.0 (Windows NT 6.1; rv:11.0)"); strcpy(v23, "HTTP/1.0"); v14 = 1; v18 = -1; v24 = 0; v12 = v2(v20, 1, 0, 0, 0); // Http new v13 = v7(v12, v22, 8080, 0, 0, 3, 0, 0); // Http init v17 = v8(v13, v25, v21, v23, 0, 0, v9, 0); // Http open v6(v17, 0, 0, 0, 0); // Http send while ( v14 && v18 ) { v14 = v4(v17, v24 + v11, 4096, &v18); // Http get resonse Text v24 += v18; // Http response Text } v3(v17); // Http free v3(v13); // Http free v3(v12); // Http free ((void (__cdecl *)(int, int, int (*)(void)))unk_1E059F)(v11, v24, v10); return v10(); }
大胆推测,调用/shell/void
,而后将响应传入((void (__cdecl *)(int, int, int (*)(void)))unk_1E059F)
这个方法
int __cdecl sub_1E059F(int a1, unsigned int a2, int a3) { char v4[47]; // [esp+40h] [ebp-90h] char v5[56]; // [esp+6Fh] [ebp-61h] BYREF char v6[25]; // [esp+A7h] [ebp-29h] BYREF unsigned int v7; // [esp+C0h] [ebp-10h] unsigned int i; // [esp+C4h] [ebp-Ch] int v9; // [esp+C8h] [ebp-8h] unsigned __int8 v10; // [esp+CFh] [ebp-1h] v4[0] = -1; v4[1] = -1; v4[2] = -1; v4[3] = -1; v4[4] = -1; v4[5] = -1; v4[6] = -1; v4[7] = -1; v4[8] = -1; v4[9] = -1; v4[10] = -1; v4[11] = -1; v4[12] = -1; v4[13] = -1; v4[14] = -1; v4[15] = -1; v4[16] = -1; v4[17] = -1; v4[18] = -1; v4[19] = -1; v4[20] = -1; v4[21] = -1; v4[22] = -1; v4[23] = -1; v4[24] = -1; v4[25] = -1; v4[26] = -1; v4[27] = -1; v4[28] = -1; v4[29] = -1; v4[30] = -1; v4[31] = -1; v4[32] = -1; v4[33] = -1; v4[34] = -1; v4[35] = -1; v4[36] = -1; v4[37] = -1; v4[38] = -1; v4[39] = -1; v4[40] = -1; v4[41] = -1; v4[42] = -1; v4[43] = 62; v4[44] = -1; v4[45] = -1; v4[46] = -1; qmemcpy(v5, "?456789:;<=", 11); v5[11] = -1; v5[12] = -1; v5[13] = -1; v5[14] = -1; v5[15] = -1; v5[16] = -1; v5[17] = -1; v5[18] = 0; v5[19] = 1; v5[20] = 2; v5[21] = 3; v5[22] = 4; v5[23] = 5; v5[24] = 6; v5[25] = 7; v5[26] = 8; v5[27] = 9; v5[28] = 10; v5[29] = 11; v5[30] = 12; v5[31] = 13; v5[32] = 14; v5[33] = 15; v5[34] = 16; v5[35] = 17; v5[36] = 18; v5[37] = 19; v5[38] = 20; v5[39] = 21; v5[40] = 22; v5[41] = 23; v5[42] = 24; v5[43] = 25; v5[44] = -1; v5[45] = -1; v5[46] = -1; v5[47] = -1; v5[48] = -1; v5[49] = -1; v5[50] = 26; v5[51] = 27; v5[52] = 28; v5[53] = 29; v5[54] = 30; v5[55] = 31; qmemcpy(v6, " !\"#$%&'()*+,-./0123", 20); v6[20] = -1; v6[21] = -1; v6[22] = -1; v6[23] = -1; v6[24] = -1; if ( (a2 & 3) != 0 ) return 0; v9 = 0; for ( i = 0; i < a2 && *(_BYTE *)(i + a1) != 61; ++i ) { if ( *(char *)(i + a1) < 43 || *(char *)(i + a1) > 122 ) return 0; v10 = v4[*(unsigned __int8 *)(i + a1)]; if ( v10 == 255 ) return 0; v7 = i & 3; if ( (i & 3) != 0 ) { switch ( v7 ) { case 1u: *(_BYTE *)(v9 + a3) |= ((int)v10 >> 4) & 3; *(_BYTE *)(++v9 + a3) = 16 * (v10 & 0xF); break; case 2u: *(_BYTE *)(v9 + a3) |= ((int)v10 >> 2) & 0xF; *(_BYTE *)(++v9 + a3) = (v10 & 3) << 6; break; case 3u: *(_BYTE *)(v9 + a3) |= v10; ++v9; break; } } else { *(_BYTE *)(v9 + a3) = 4 * v10; } } return v9; }
后半段一看,明显是base64算法
运行part1,再去康康这条api返回了什么
盲猜还是shellcode
开着part1,继续看加载的shellcode
int sub_25C0005() { int result; // eax char v1[4]; // [esp+0h] [ebp-C0h] BYREF int (__stdcall *v2)(_DWORD, char *, _DWORD, int); // [esp+4h] [ebp-BCh] void (__stdcall *v3)(char *, char *, int); // [esp+28h] [ebp-98h] char v4[35]; // [esp+2Ch] [ebp-94h] char v5[3]; // [esp+4Fh] [ebp-71h] BYREF char v6[44]; // [esp+54h] [ebp-6Ch] BYREF char v7[44]; // [esp+80h] [ebp-40h] BYREF char v8[8]; // [esp+ACh] [ebp-14h] BYREF char v9[8]; // [esp+B4h] [ebp-Ch] BYREF int i; // [esp+BCh] [ebp-4h] ((void (__cdecl *)(char *))unk_25C048A)(v1); v7[0] = 0; v7[1] = 0; v7[2] = 0; v7[3] = 0; v7[4] = 0; v7[5] = 0; v7[6] = 0; v7[7] = 0; v7[8] = 0; v7[9] = 0; v7[10] = 0; v7[11] = 0; v7[12] = 0; v7[13] = 0; v7[14] = 0; v7[15] = 0; v7[16] = 0; v7[17] = 0; v7[18] = 0; v7[19] = 0; v7[20] = 0; v7[21] = 0; v7[22] = 0; v7[23] = 0; v7[24] = 0; v7[25] = 0; v7[26] = 0; v7[27] = 0; v7[28] = 0; v7[29] = 0; v7[30] = 0; v7[31] = 0; v7[32] = 0; v7[33] = 0; v7[34] = 0; v7[35] = 0; v7[36] = 0; v7[37] = 0; v7[38] = 0; v7[39] = 0; v7[40] = 0; v7[41] = 0; v7[42] = 0; v7[43] = 0; strcpy(v9, "FLAG"); v3(v9, v7, 44); v6[0] = 0; v6[1] = 0; v6[2] = 0; v6[3] = 0; v6[4] = 0; v6[5] = 0; v6[6] = 0; v6[7] = 0; v6[8] = 0; v6[9] = 0; v6[10] = 0; v6[11] = 0; v6[12] = 0; v6[13] = 0; v6[14] = 0; v6[15] = 0; v6[16] = 0; v6[17] = 0; v6[18] = 0; v6[19] = 0; v6[20] = 0; v6[21] = 0; v6[22] = 0; v6[23] = 0; v6[24] = 0; v6[25] = 0; v6[26] = 0; v6[27] = 0; v6[28] = 0; v6[29] = 0; v6[30] = 0; v6[31] = 0; v6[32] = 0; v6[33] = 0; v6[34] = 0; v6[35] = 0; v6[36] = 0; v6[37] = 0; v6[38] = 0; v6[39] = 0; v6[40] = 0; v6[41] = 0; v6[42] = 0; v6[43] = 0; v4[0] = 100; v4[1] = 46; v4[2] = -112; v4[3] = 52; v4[4] = 65; v4[5] = -40; v4[6] = 36; v4[7] = -53; v4[8] = 82; v4[9] = 46; v4[10] = -5; v4[11] = 57; v4[12] = 62; v4[13] = -111; v4[14] = 7; v4[15] = 14; v4[16] = -106; v4[17] = -10; v4[18] = 60; v4[19] = 9; v4[20] = -100; v4[21] = 33; v4[22] = -110; v4[23] = 33; v4[24] = -78; v4[25] = -52; v4[26] = -97; v4[27] = 81; v4[28] = 72; v4[29] = 99; v4[30] = 76; v4[31] = -113; v4[32] = 114; v4[33] = 93; v4[34] = -65; qmemcpy(v5, "lQv", sizeof(v5)); ((void (__cdecl *)(char *, int, char *))unk_25C05BA)(v7, 38, v6); for ( i = 0; i < 38; ++i ) { result = (unsigned __int8)v6[i]; if ( result != (unsigned __int8)v4[i] ) return result; } strcpy(v8, "Correct"); return v2(0, v8, 0, 64); }
看到末尾v6与v4对比,往上康康((void (__cdecl *)(char *, int, char *))unk_25C05BA)
int __cdecl sub_25C05BA(int a1, int a2, int a3) { int result; // eax char v4[256]; // [esp+0h] [ebp-124h] int v5; // [esp+100h] [ebp-24h] int v6; // [esp+104h] [ebp-20h] char v7[12]; // [esp+108h] [ebp-1Ch] BYREF int j; // [esp+114h] [ebp-10h] int v9; // [esp+118h] [ebp-Ch] int i; // [esp+11Ch] [ebp-8h] char v11; // [esp+123h] [ebp-1h] strcpy(v7, "golangc2"); v6 = 8; for ( i = 0; i < 256; ++i ) v4[i] = i; v9 = 0; for ( i = 0; i < 256; ++i ) { v9 = ((unsigned __int8)v4[i] + v9 + v7[i % v6]) % 256; v11 = v4[i]; v4[i] = v4[v9]; v4[v9] = v11; } v9 = 0; i = 0; for ( j = 0; ; ++j ) { result = j; if ( j >= a2 ) break; i = (i + 1) % 256; v9 = (v9 + (unsigned __int8)v4[i]) % 256; v11 = v4[i]; v4[i] = v4[v9]; v4[v9] = v11; v5 = ((unsigned __int8)v4[v9] + (unsigned __int8)v4[i]) % 256; v11 = v4[v5]; *(_BYTE *)(j + a3) = v11 ^ *(_BYTE *)(j + a1); } return result; }
一眼看穿是RC4,key拿到手golangc2
那么直接去拿密文就行了,这里直接运行到调用RC4前,以防动态运行时它再加点料,然后dump下来解密完事
replace
lua题,32位,试了下bindiff,根本识别不出来 = =
那就dump下luac,unluac跑出脚本来
local L0_1, L1_1, L2_1, L3_1, L4_1, L5_1, L6_1, L7_1, L8_1, L9_1, L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1 L0_1 = require L1_1 = "enclib" L0_1 = L0_1(L1_1) enclib = L0_1 function L0_1(A0_2) local L1_2, L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2 L1_2 = string L1_2 = L1_2.len L2_2 = A0_2 L1_2 = L1_2(L2_2) L2_2 = {} L3_2 = {} L4_2 = 0 L5_2 = 255 L6_2 = 1 for L7_2 = L4_2, L5_2, L6_2 do L2_2[L7_2] = L7_2 end L4_2 = 1 L5_2 = L1_2 L6_2 = 1 for L7_2 = L4_2, L5_2, L6_2 do L8_2 = L7_2 - 1 L9_2 = string L9_2 = L9_2.byte L10_2 = A0_2 L11_2 = L7_2 L12_2 = L7_2 L9_2 = L9_2(L10_2, L11_2, L12_2) L3_2[L8_2] = L9_2 end L4_2 = 0 L5_2 = 0 L6_2 = 255 L7_2 = 1 for L8_2 = L5_2, L6_2, L7_2 do L9_2 = L2_2[L8_2] L9_2 = L4_2 + L9_2 L10_2 = L8_2 % L1_2 L10_2 = L3_2[L10_2] L9_2 = L9_2 + L10_2 L4_2 = L9_2 % 256 L9_2 = L2_2[L4_2] L10_2 = L2_2[L8_2] L2_2[L4_2] = L10_2 L2_2[L8_2] = L9_2 end return L2_2 end KSA = L0_1 function L0_1(A0_2, A1_2) local L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2 L2_2 = 0 L3_2 = 0 L4_2 = {} L5_2 = 1 L6_2 = A1_2 L7_2 = 1 for L8_2 = L5_2, L6_2, L7_2 do L9_2 = L2_2 + 1 L2_2 = L9_2 % 256 L9_2 = A0_2[L2_2] L9_2 = L3_2 + L9_2 L3_2 = L9_2 % 256 L9_2 = A0_2[L3_2] L10_2 = A0_2[L2_2] A0_2[L3_2] = L10_2 A0_2[L2_2] = L9_2 L9_2 = A0_2[L2_2] L10_2 = A0_2[L3_2] L9_2 = L9_2 + L10_2 L9_2 = L9_2 % 256 L9_2 = A0_2[L9_2] L4_2[L8_2] = L9_2 end return L4_2 end PRGA = L0_1 function L0_1(A0_2, A1_2) local L2_2, L3_2, L4_2, L5_2, L6_2, L7_2 L2_2 = string L2_2 = L2_2.len L3_2 = A1_2 L2_2 = L2_2(L3_2) L3_2 = KSA L4_2 = A0_2 L3_2 = L3_2(L4_2) L4_2 = PRGA L5_2 = L3_2 L6_2 = L2_2 L4_2 = L4_2(L5_2, L6_2) L5_2 = output L6_2 = L4_2 L7_2 = A1_2 return L5_2(L6_2, L7_2) end RC4 = L0_1 function L0_1(A0_2, A1_2) local L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2 L2_2 = string L2_2 = L2_2.len L3_2 = A1_2 L2_2 = L2_2(L3_2) L3_2 = nil L4_2 = {} L5_2 = 1 L6_2 = L2_2 L7_2 = 1 for L8_2 = L5_2, L6_2, L7_2 do L9_2 = string L9_2 = L9_2.byte L10_2 = A1_2 L11_2 = L8_2 L12_2 = L8_2 L9_2 = L9_2(L10_2, L11_2, L12_2) L3_2 = L9_2 L9_2 = string L9_2 = L9_2.char L10_2 = bxor L11_2 = A0_2[L8_2] L12_2 = L3_2 L10_2, L11_2, L12_2 = L10_2(L11_2, L12_2) L9_2 = L9_2(L10_2, L11_2, L12_2) L4_2[L8_2] = L9_2 end L5_2 = table L5_2 = L5_2.concat L6_2 = L4_2 return L5_2(L6_2) end output = L0_1 L0_1 = {} function L1_1(A0_2, A1_2) local L2_2 L2_2 = A0_2 + A1_2 if L2_2 == 2 then L2_2 = 1 if L2_2 then goto lbl_8 end end L2_2 = 0 ::lbl_8:: return L2_2 end L0_1.cond_and = L1_1 function L1_1(A0_2, A1_2) local L2_2 L2_2 = A0_2 + A1_2 if L2_2 == 1 then L2_2 = 1 if L2_2 then goto lbl_8 end end L2_2 = 0 ::lbl_8:: return L2_2 end L0_1.cond_xor = L1_1 function L1_1(A0_2, A1_2) local L2_2 L2_2 = A0_2 + A1_2 if 0 < L2_2 then L2_2 = 1 if L2_2 then goto lbl_8 end end L2_2 = 0 ::lbl_8:: return L2_2 end L0_1.cond_or = L1_1 function L1_1(A0_2, A1_2, A2_2) local L3_2, L4_2, L5_2, L6_2, L7_2 if A1_2 < A2_2 then L3_2 = A2_2 A2_2 = A1_2 A1_2 = L3_2 end L3_2 = 0 L4_2 = 1 while A1_2 ~= 0 do L5_2 = A1_2 % 2 r_a = L5_2 L5_2 = A2_2 % 2 r_b = L5_2 L5_2 = L0_1[A0_2] L6_2 = r_a L7_2 = r_b L5_2 = L5_2(L6_2, L7_2) L5_2 = L4_2 * L5_2 L3_2 = L5_2 + L3_2 L4_2 = L4_2 * 2 L5_2 = math L5_2 = L5_2.modf L6_2 = A1_2 / 2 L5_2 = L5_2(L6_2) A1_2 = L5_2 L5_2 = math L5_2 = L5_2.modf L6_2 = A2_2 / 2 L5_2 = L5_2(L6_2) A2_2 = L5_2 end return L3_2 end L0_1.base = L1_1 function L1_1(A0_2, A1_2) local L2_2, L3_2, L4_2, L5_2 L2_2 = L0_1.base L3_2 = "cond_xor" L4_2 = A0_2 L5_2 = A1_2 return L2_2(L3_2, L4_2, L5_2) end bxor = L1_1 function L1_1(A0_2, A1_2) local L2_2, L3_2, L4_2, L5_2 L2_2 = L0_1.base L3_2 = "cond_and" L4_2 = A0_2 L5_2 = A1_2 return L2_2(L3_2, L4_2, L5_2) end band = L1_1 function L1_1(A0_2, A1_2) local L2_2, L3_2, L4_2, L5_2 L2_2 = L0_1.base L3_2 = "cond_or" L4_2 = A0_2 L5_2 = A1_2 return L2_2(L3_2, L4_2, L5_2) end bor = L1_1 L1_1 = print L2_1 = "Welcome to the world of reverse\n" L1_1(L2_1) L1_1 = print L2_1 = "Now please give me the key : " L1_1(L2_1) L1_1 = "RC4KEY" L2_1 = io L2_1 = L2_1.read L3_1 = "*l" L2_1 = L2_1(L3_1) L3_1 = string L3_1 = L3_1.len L4_1 = L2_1 L3_1 = L3_1(L4_1) if L3_1 ~= 38 then L3_1 = print L4_1 = "wrong length" L3_1(L4_1) L3_1 = os L3_1 = L3_1.exit L3_1() end L3_1 = enclib L3_1 = L3_1.prepare L3_1() L3_1 = enclib L3_1 = L3_1.encrypt L4_1 = L2_1 L5_1 = string L5_1 = L5_1.len L6_1 = L2_1 L5_1, L6_1, L7_1, L8_1, L9_1, L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1 = L5_1(L6_1) L3_1 = L3_1(L4_1, L5_1, L6_1, L7_1, L8_1, L9_1, L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1) res = L3_1 L3_1 = RC4 L4_1 = L1_1 L5_1 = res L3_1 = L3_1(L4_1, L5_1) K = L3_1 L3_1 = {} t = L3_1 L3_1 = {} L4_1 = 43 L5_1 = 50 L6_1 = 118 L7_1 = 51 L8_1 = 186 L9_1 = 167 L10_1 = 106 L11_1 = 55 L12_1 = 228 L13_1 = 145 L14_1 = 160 L15_1 = 171 L16_1 = 23 L17_1 = 227 L18_1 = 82 L19_1 = 56 L20_1 = 191 L21_1 = 166 L22_1 = 65 L23_1 = 254 L24_1 = 189 L25_1 = 167 L26_1 = 236 L27_1 = 92 L28_1 = 154 L29_1 = 70 L30_1 = 19 L31_1 = 169 L32_1 = 10 L33_1 = 70 L34_1 = 222 L35_1 = 237 L36_1 = 237 L37_1 = 19 L38_1 = 249 L39_1 = 70 L40_1 = 121 L41_1 = 127 L42_1 = 189 L43_1 = 104 L44_1 = 169 L45_1 = 107 L46_1 = 43 L47_1 = 1 L48_1 = 50 L49_1 = 165 L50_1 = 234 L51_1 = 90 L52_1 = 76 L53_1 = 190 L3_1[1] = L4_1 L3_1[2] = L5_1 L3_1[3] = L6_1 L3_1[4] = L7_1 L3_1[5] = L8_1 L3_1[6] = L9_1 L3_1[7] = L10_1 L3_1[8] = L11_1 L3_1[9] = L12_1 L3_1[10] = L13_1 L3_1[11] = L14_1 L3_1[12] = L15_1 L3_1[13] = L16_1 L3_1[14] = L17_1 L3_1[15] = L18_1 L3_1[16] = L19_1 L3_1[17] = L20_1 L3_1[18] = L21_1 L3_1[19] = L22_1 L3_1[20] = L23_1 L3_1[21] = L24_1 L3_1[22] = L25_1 L3_1[23] = L26_1 L3_1[24] = L27_1 L3_1[25] = L28_1 L3_1[26] = L29_1 L3_1[27] = L30_1 L3_1[28] = L31_1 L3_1[29] = L32_1 L3_1[30] = L33_1 L3_1[31] = L34_1 L3_1[32] = L35_1 L3_1[33] = L36_1 L3_1[34] = L37_1 L3_1[35] = L38_1 L3_1[36] = L39_1 L3_1[37] = L40_1 L3_1[38] = L41_1 L3_1[39] = L42_1 L3_1[40] = L43_1 L3_1[41] = L44_1 L3_1[42] = L45_1 L3_1[43] = L46_1 L3_1[44] = L47_1 L3_1[45] = L48_1 L3_1[46] = L49_1 L3_1[47] = L50_1 L3_1[48] = L51_1 L3_1[49] = L52_1 L3_1[50] = L53_1 L4_1 = 239 L5_1 = 227 L3_1[51] = L4_1 L3_1[52] = L5_1 flag = L3_1 L3_1 = 1 L4_1 = string L4_1 = L4_1.len L5_1 = K L4_1 = L4_1(L5_1) L5_1 = 1 for L6_1 = L3_1, L4_1, L5_1 do L7_1 = table L7_1 = L7_1.insert L8_1 = t L9_1 = string L9_1 = L9_1.byte L10_1 = string L10_1 = L10_1.sub L11_1 = K L12_1 = L6_1 L13_1 = L6_1 L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1 = L10_1(L11_1, L12_1, L13_1) L9_1, L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1 = L9_1(L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1) L7_1(L8_1, L9_1, L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1) end L3_1 = 1 L4_1 = string L4_1 = L4_1.len L5_1 = K L4_1 = L4_1(L5_1) L5_1 = 1 for L6_1 = L3_1, L4_1, L5_1 do L7_1 = t L7_1 = L7_1[L6_1] L8_1 = flag L8_1 = L8_1[L6_1] if L7_1 ~= L8_1 then L7_1 = print L8_1 = "wrong" L7_1(L8_1) L7_1 = os L7_1 = L7_1.exit L7_1() end end L3_1 = print L4_1 = "correct!" L3_1(L4_1)
代码虽然不好看,但是好歹能看。
逻辑分析下来,第一层加密在enclib.encrypt
,回IDA康康
// local variable allocation has failed, the output may be wrong! int __cdecl sub_4A9110(int a1) { _DWORD *v1; // edi int v2; // eax int *v3; // ecx double v4; // xmm0_8 int v5; // ecx int v6; // esi int v7; // ebx const char *v8; // ecx unsigned int v9; // eax int v10; // edx const char *v11; // esi int v12; // ebx int v13; // edi unsigned int v14; // ecx unsigned int v15; // edx int v16; // eax unsigned int v17; // ecx int v18; // ebx int v19; // eax int *v20; // ecx int v21; // eax int v23; // [esp+4h] [ebp-1Ch] int v24; // [esp+10h] [ebp-10h] const char *v25; // [esp+14h] [ebp-Ch] int v26; // [esp+18h] [ebp-8h] double var8_4; // [esp+1Ch] [ebp-4h] OVERLAPPED BYREF v1 = (_DWORD *)a1; lua_pushnil(0); v24 = v2; if ( !v2 ) lua_pushvalue((lua_State *)4, v23); v3 = &dword_4DCDA0; if ( (unsigned int)(**(_DWORD **)(a1 + 20) + 32) < *(_DWORD *)(a1 + 12) ) v3 = (int *)(**(_DWORD **)(a1 + 20) + 32); if ( v3[2] == 3 ) { v4 = *(double *)v3; } else { if ( !luaV_tonumber_(v3, &var8_4) ) lua_pushvalue((lua_State *)3, v23); v4 = var8_4; } v5 = (int)v4 / 3; v6 = 4 * v5; v7 = (int)v4 % 3; if ( v7 ) v6 = 4 * v5 + 4; v8 = (const char *)malloc(__CFADD__(v6, 1) ? -1 : v6 + 1); v9 = v6 - 2; v25 = v8; v10 = 0; v8[v6] = 0; if ( v6 - 2 > 0 ) { v11 = v8 + 2; v12 = v24 + 2; v13 = (v9 >> 2) + 1; LODWORD(var8_4) = 4 * v13; do { v14 = *(unsigned __int8 *)(v12 - 2); v12 += 3; v15 = *(unsigned __int8 *)(v12 - 4); v11 += 4; *((_BYTE *)v11 - 6) = aAbcdefghijklmn[v14 >> 2]; v16 = (16 * (v14 & 3)) | (v15 >> 4); v17 = *(unsigned __int8 *)(v12 - 3); *((_BYTE *)v11 - 5) = aAbcdefghijklmn[v16]; *((_BYTE *)v11 - 4) = aAbcdefghijklmn[(4 * (v15 & 0xF)) | (v17 >> 6)]; *((_BYTE *)v11 - 3) = aAbcdefghijklmn[v17 & 0x3F]; --v13; } while ( v13 ); v1 = (_DWORD *)a1; v8 = v25; v26 = (int)v4 % 3; v10 = LODWORD(var8_4); v7 = v26; } v18 = v7 - 1; if ( v18 ) { if ( v18 == 1 ) v8[v10 - 1] = '='; } else { *(_WORD *)&v8[v10 - 2] = 15677; } if ( v8 ) { v19 = T_000_new_localvarliteral_((int)v1, v8); v20 = (int *)v1[3]; *v20 = v19; v20[2] = *(unsigned __int8 *)(v19 + 4) | 0x40; } else { *(_DWORD *)(v1[3] + 8) = 0; } v21 = v1[4]; v1[3] += 16; if ( *(int *)(v21 + 12) > 0 ) luaC_step(v1); return 1; }
明显的base64
顺便看下prepare
int sub_4A90D0() { int v0; // esi char *v1; // eax char v2; // dl v0 = 0; v1 = &aAbcdefghijklmn[63]; do { v2 = byte_50AA8F[++v0]; byte_50AA8F[v0] = *v1; *v1-- = v2; } while ( (int)v1 > (int)&aAbcdefghijklmn[31] ); return 1; }
逆了一下码表
看第二层,RC4,对称加密,密钥为RC4KEY
直接抄代码运行了,省的分析算法,去看有没有魔改
然而密钥是错的 = =,ida分析一下会发现,密钥变成了Good!!
function KSA(key) local key_len = string.len(key) local S = {} local key_byte = {} for i = 0, 255 do S[i] = i end for i = 1, key_len do key_byte[i-1] = string.byte(key, i, i) end local j = 0 for i = 0, 255 do j = (j + S[i] + key_byte[i % key_len]) % 256 S[i], S[j] = S[j], S[i] end return S end function PRGA(S, text_len) local i = 0 local j = 0 local K = {} for n = 1, text_len do i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] K[n] = S[(S[i] + S[j]) % 256] end return K end function RC4(key, text) local text_len = string.len(text) local S = KSA(key) local K = PRGA(S, text_len) return output(K, text) end function output(S, text) local len = string.len(text) local c = nil local res = {} for i = 1, len do c = string.byte(text, i, i) res[i] = string.char(bxor(S[i], c)) end return table.concat(res) end local bit_op = {} function bit_op.cond_and(r_a, r_b) return (r_a + r_b == 2) and 1 or 0 end function bit_op.cond_xor(r_a, r_b) return (r_a + r_b == 1) and 1 or 0 end function bit_op.cond_or(r_a, r_b) return (r_a + r_b > 0) and 1 or 0 end function bit_op.base(op_cond, a, b) -- bit operation if a < b then a, b = b, a end local res = 0 local shift = 1 while a ~= 0 do r_a = a % 2 r_b = b % 2 res = shift * bit_op[op_cond](r_a, r_b) + res shift = shift * 2 a = math.modf(a / 2) b = math.modf(b / 2) end return res end function bxor(a, b) return bit_op.base('cond_xor', a, b) end function band(a, b) return bit_op.base('cond_and', a, b) end function bor(a, b) return bit_op.base('cond_or', a, b) end local L0_1, L1_1, L2_1, L3_1, L4_1, L5_1, L6_1, L7_1, L8_1, L9_1, L10_1, L11_1, L12_1, L13_1, L14_1, L15_1, L16_1, L17_1, L18_1, L19_1, L20_1, L21_1, L22_1, L23_1, L24_1, L25_1, L26_1, L27_1, L28_1, L29_1, L30_1, L31_1, L32_1, L33_1, L34_1, L35_1, L36_1, L37_1, L38_1, L39_1, L40_1, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L48_1, L49_1, L50_1, L51_1, L52_1, L53_1 L3_1 = {} L4_1 = 43 L5_1 = 50 L6_1 = 118 L7_1 = 51 L8_1 = 186 L9_1 = 167 L10_1 = 106 L11_1 = 55 L12_1 = 228 L13_1 = 145 L14_1 = 160 L15_1 = 171 L16_1 = 23 L17_1 = 227 L18_1 = 82 L19_1 = 56 L20_1 = 191 L21_1 = 166 L22_1 = 65 L23_1 = 254 L24_1 = 189 L25_1 = 167 L26_1 = 236 L27_1 = 92 L28_1 = 154 L29_1 = 70 L30_1 = 19 L31_1 = 169 L32_1 = 10 L33_1 = 70 L34_1 = 222 L35_1 = 237 L36_1 = 237 L37_1 = 19 L38_1 = 249 L39_1 = 70 L40_1 = 121 L41_1 = 127 L42_1 = 189 L43_1 = 104 L44_1 = 169 L45_1 = 107 L46_1 = 43 L47_1 = 1 L48_1 = 50 L49_1 = 165 L50_1 = 234 L51_1 = 90 L52_1 = 76 L53_1 = 190 L3_1[1] = L4_1 L3_1[2] = L5_1 L3_1[3] = L6_1 L3_1[4] = L7_1 L3_1[5] = L8_1 L3_1[6] = L9_1 L3_1[7] = L10_1 L3_1[8] = L11_1 L3_1[9] = L12_1 L3_1[10] = L13_1 L3_1[11] = L14_1 L3_1[12] = L15_1 L3_1[13] = L16_1 L3_1[14] = L17_1 L3_1[15] = L18_1 L3_1[16] = L19_1 L3_1[17] = L20_1 L3_1[18] = L21_1 L3_1[19] = L22_1 L3_1[20] = L23_1 L3_1[21] = L24_1 L3_1[22] = L25_1 L3_1[23] = L26_1 L3_1[24] = L27_1 L3_1[25] = L28_1 L3_1[26] = L29_1 L3_1[27] = L30_1 L3_1[28] = L31_1 L3_1[29] = L32_1 L3_1[30] = L33_1 L3_1[31] = L34_1 L3_1[32] = L35_1 L3_1[33] = L36_1 L3_1[34] = L37_1 L3_1[35] = L38_1 L3_1[36] = L39_1 L3_1[37] = L40_1 L3_1[38] = L41_1 L3_1[39] = L42_1 L3_1[40] = L43_1 L3_1[41] = L44_1 L3_1[42] = L45_1 L3_1[43] = L46_1 L3_1[44] = L47_1 L3_1[45] = L48_1 L3_1[46] = L49_1 L3_1[47] = L50_1 L3_1[48] = L51_1 L3_1[49] = L52_1 L3_1[50] = L53_1 L4_1 = 239 L5_1 = 227 L3_1[51] = L4_1 L3_1[52] = L5_1 flag = L3_1 local function bin2hex(s) s=string.gsub(s,"(.)",function (x) return string.format("%02X",string.byte(x)) end) return s end local h2b = { ["0"] = 0, ["1"] = 1, ["2"] = 2, ["3"] = 3, ["4"] = 4, ["5"] = 5, ["6"] = 6, ["7"] = 7, ["8"] = 8, ["9"] = 9, ["A"] = 10, ["B"] = 11, ["C"] = 12, ["D"] = 13, ["E"] = 14, ["F"] = 15 } local function hex2bin( hexstr ) local s = string.gsub(hexstr, "(.)(.)%s", function ( h, l ) return string.char(h2b[h]*16+h2b[l]) end) return s end text = "" for i = 1, 52 do text = text .. string.char(flag[i]) end key = "Good!!" K = RC4(key, text) print (bin2hex(K))
再换码表base64解码完事
后记
后期验证了一下,用lua跑出对比密文的hex解码就行
Misc
funny_maze
nc连接,就是走迷宫,计算要走的步数,四轮,一轮比一轮多
写个寻路算法,然后直接pwntools上手
为了快点拿到flag,脚本写的我自己都不忍直视……直接手动跑了最后一次(不过算法写法还是ok的)
from pwn import * from six import b class maze: def __init__(self, maze, size, sx, sy, ex, ey): self.end = [ey, ex] self.size = size self.route_stack = [[sy, sx]] self.route_history = [[sy, sx]] self.lo = [sy, sx] self.source = maze def up(self, location): if location[1] == 0: return False else: new_location = [location[0], location[1] - 1] # if new_location in self.route_history: return False # elif self.source[new_location[0]][new_location[1]] == 1: return False else: self.route_stack.append(new_location) self.route_history.append(new_location) return True def down(self, location): if location[1] == self.size - 1: return False else: new_location = [location[0], location[1] + 1] if new_location in self.route_history: return False elif self.source[new_location[0]][new_location[1]] == 1: return False else: self.route_stack.append(new_location) self.route_history.append(new_location) return True def left(self, location): if location[0] == 0: return False else: new_location = [location[0] - 1, location[1]] if new_location in self.route_history: return False elif self.source[new_location[0]][new_location[1]] == 1: return False else: self.route_stack.append(new_location) self.route_history.append(new_location) return True def right(self, location): if location[0] == self.size - 1: return False else: new_location = [location[0] + 1, location[1]] if new_location in self.route_history: return False elif self.source[new_location[0]][new_location[1]] == 1: return False else: self.route_stack.append(new_location) self.route_history.append(new_location) return True def findpath(self): while self.route_stack[-1] != self.end: if self.up(self.lo): self.lo = self.route_stack[-1] continue if self.down(self.lo): self.lo = self.route_stack[-1] continue if self.left(self.lo): self.lo = self.route_stack[-1] continue if self.right(self.lo): self.lo = self.route_stack[-1] continue self.route_stack.pop() self.lo = self.route_stack[-1] return self.route_stack r = remote("node4.buuoj.cn", 25619) r.sendline(b"1") t2 = "Please enter your answer:" data = r.recvuntil(t2) t = "3.Introduction to this game\n" mazeStr = data[data.find(t) + len(t):-len(t2)] for _ in range(4): mazes = [] startx = starty = 0 endx = endy = 0 for j, line in enumerate(mazeStr.splitlines()): tline = [1] * len(line) for m, i in enumerate(line): if i == "#": tline[m] = 1 elif i == " ": tline[m] = 0 elif i == "S": startx = m starty = j tline[m] = 0 elif i == "E": endx = m endy = j tline[m] = 0 mazes.append(tline) lesn = len(mazes) m = maze(mazes, lesn, startx, starty, endx, endy).findpath() print(m) if _ == 3: print(len(m)) r.interactive() r.sendline(str(len(m)).encode()) tt = b"answer:" data = r.recvuntil(tt) print(data) sleep(1) t = "next level!\n" mazeStr = data[data.find(t) + len(t):-len(tt)]
发表回复