- 去年西湖论剑没打,今年要打了,补下之前的题。
一. BabyRe
-
main函数中只有一句
-
int __cdecl main(int argc, const char **argv, const char **envp) { __CheckForDebuggerJustMyCode(&unk_4090A2); GetLastError(); return 0; }
-
查看字符串,并交叉引用
-
找到几个函数:
-
int sub_401000() { __CheckForDebuggerJustMyCode(&unk_4090A2); sub_401170(&unk_4085C6); return atexit(sub_405770); }
-
int sub_401050() { __CheckForDebuggerJustMyCode(&unk_4090A2); sub_401230(&unk_4085C4); return atexit(sub_4057B0); }
-
int sub_4010A0() { __CheckForDebuggerJustMyCode(&unk_4090A2); sub_4012B0(&unk_4085C5); return atexit(sub_4057F0); }
-
发现了atexit函数,这个函数为登记函数,是在正常程序退出时调用的函数,⼀个进程可以登记若⼲个(具体⾃⼰验证⼀下)个函数,这些函数由exit⾃动调⽤,这些函数被称为终⽌处理函数, atexit函数可以登记这些函数。 exit调⽤终⽌处理函数的顺序和atexit登记的顺序相反
-
再通过打断点动调,即可找到函数调用顺序
-
401170 401230 4012B0 main atexit 4014E0 atexit 4015C0 atexit 401670
-
分别分析函数作用如下:
-
void *__thiscall sub_401170(void *this)//输入函数 { char v2; // [esp+0h] [ebp-E4h] size_t i; // [esp+D0h] [ebp-14h] __CheckForDebuggerJustMyCode(&unk_4090A2); sub_4025A0("Input:", v2); sub_402620("%99s", (char)Str); for ( i = 0; i < strlen(Str); ++i ) { if ( Str[i] < 48 || Str[i] > 57 ) ExitProcess(0); } return this; }
-
void *__thiscall sub_401230(void *this)//按位取反,得到01234567的table { int i; // [esp+D0h] [ebp-14h] __CheckForDebuggerJustMyCode(&unk_4090A2); for ( i = 0; i < 8; ++i ) byte_408104[i] = ~byte_408104[i]; return this; }
-
int __thiscall sub_4012B0(void *this)//遍历输入表进行hook { int i; // [esp+DCh] [ebp-9Ch] char *v3; // [esp+E8h] [ebp-90h] char *v4; // [esp+F4h] [ebp-84h] const CHAR *lpModuleName; // [esp+10Ch] [ebp-6Ch] _DWORD *v6; // [esp+118h] [ebp-60h] DWORD flOldProtect[9]; // [esp+124h] [ebp-54h] BYREF int v8; // [esp+148h] [ebp-30h] HMODULE v9; // [esp+154h] [ebp-24h] HMODULE ModuleHandleA; // [esp+160h] [ebp-18h] void *v11; // [esp+16Ch] [ebp-Ch] v11 = this; __CheckForDebuggerJustMyCode(&unk_4090A2); ModuleHandleA = GetModuleHandleA(0); v9 = ModuleHandleA; v8 = (int)ModuleHandleA + *((_DWORD *)ModuleHandleA + 15) + 4; flOldProtect[6] = v8 + 20; flOldProtect[3] = v8 + 116; v6 = (_DWORD *)((char *)ModuleHandleA + *(_DWORD *)(v8 + 124)); while ( v6[3] ) { lpModuleName = (char *)ModuleHandleA + v6[3]; if ( GetModuleHandleA(lpModuleName) || LoadLibraryA(lpModuleName) ) { v4 = (char *)ModuleHandleA + *v6; v3 = (char *)ModuleHandleA + v6[4]; for ( i = 0; *(_DWORD *)&v4[4 * i]; ++i ) { if ( *(int *)&v4[4 * i] >= 0 && !strcmp((const char *)ModuleHandleA + *(_DWORD *)&v4[4 * i] + 2, "GetLastError") ) { dword_4085C0 = *(_DWORD *)&v3[4 * i]; VirtualProtect(&v3[4 * i], 4u, 4u, flOldProtect); *(_DWORD *)&v3[4 * i] = sub_4019D0;//将GetLastError函数改为4019D0 break; } } v6 += 5; } else { v6 += 5; } } return (int)v11; }
-
int sub_401670() { int result; // eax __CheckForDebuggerJustMyCode(&unk_4090A2); sub_401720(&Str, (int)&unk_4081C0);//base8加密 result = memcmp(&unk_4081D0, a16230465152334, 0x60u);//赋值 if ( result ) ExitProcess(0); return result; }
-
int sub_4015C0() { int result; // eax __CheckForDebuggerJustMyCode(&unk_4090A2); sub_401CC0((int)&unk_4081C0, 112, 0, Buffer);//sha-1 result = memcmp(Buffer, a67339fc92b4875, 0x28u); if ( result ) ExitProcess(0); return result; }
-
int __cdecl sub_4014E0()//检验 { char v1; // [esp+0h] [ebp-E8h] __CheckForDebuggerJustMyCode(&unk_4090A2); memcpy(&unk_4084C0, &unk_4081C0, 0x70u);//赋值,前16位未知,后面96位已知 sub_401B60(&unk_4083C0, &unk_408182, 6);//RC4_init,6位密钥为输入的后六位 sub_401A40(&unk_4083C0, &unk_4084C0, 112);//RC4 if ( memcmp(&unk_4084C0, &unk_408090, 0x70u) )//比较函数 ExitProcess(0); return sub_4025A0("Good, flag is DASCTF{your input}", v1); }
-
void *__cdecl sub_401CC0(int a1, __int64 a2, char *Buffer)//换了常数的SHA-1加密 { void *result; // eax int v4; // [esp+Ch] [ebp-4D4h] int v5; // [esp+10h] [ebp-4D0h] int v6; // [esp+14h] [ebp-4CCh] int v7; // [esp+18h] [ebp-4C8h] int v8; // [esp+1A0h] [ebp-340h] int v9; // [esp+1ACh] [ebp-334h] int v10; // [esp+1B8h] [ebp-328h] int v11; // [esp+1C4h] [ebp-31Ch] int v12; // [esp+1D0h] [ebp-310h] int v13; // [esp+1DCh] [ebp-304h] int v14; // [esp+1E4h] [ebp-2FCh] int v15; // [esp+1E8h] [ebp-2F8h] int v16[2]; // [esp+1ECh] [ebp-2F4h] int v17; // [esp+1F4h] [ebp-2ECh] int v18; // [esp+200h] [ebp-2E0h] int v19[2]; // [esp+204h] [ebp-2DCh] int v20; // [esp+20Ch] [ebp-2D4h] int v21[167]; // [esp+218h] [ebp-2C8h] int i; // [esp+4B4h] [ebp-2Ch] size_t Size; // [esp+4C0h] [ebp-20h] unsigned int v24; // [esp+4CCh] [ebp-14h] unsigned int v25; // [esp+4D8h] [ebp-8h] __CheckForDebuggerJustMyCode(&unk_4090A2); v12 = 271733878; v11 = -1984242434; v10 = -271733879; v9 = 1732588033; v8 = 253635900; for ( i = 0; i < 20; ++i ) v21[i + 85] = dword_408148[0]; for ( i = 20; i < 40; ++i ) v21[i + 85] = dword_408148[1]; for ( i = 40; i < 60; ++i ) v21[i + 85] = dword_408148[2]; for ( i = 60; i < 80; ++i ) v21[i + 85] = dword_408148[3]; if ( a2 % 64 <= 56 ) v4 = 64 - a2 % 64; else v4 = 128 - a2 % 64; Size = v4 + a2; result = malloc(v4 + a2); v25 = (unsigned int)result; if ( result ) { for ( i = 0; i < a2; ++i ) *(_BYTE *)(v25 + i + 3 - 2 * (i % 4)) = *(_BYTE *)(i + a1); *(_BYTE *)(v25 + i + 3 - 2 * (i % 4)) = 0x80; ++i; while ( i < (int)Size ) { *(_BYTE *)(v25 + i + 3 - 2 * (i % 4)) = 0; ++i; } *(_DWORD *)(Size + v25 - 4) = 8 * a2; *(_DWORD *)(Size + v25 - 8) = a2 >> 29; v24 = Size + v25; while ( v25 < v24 ) { for ( i = 0; i < 16; ++i ) v21[i + 3] = *(_DWORD *)(v25 + 4 * i); for ( i = 16; i < 80; ++i ) { dword_4081BC = *(&v14 + i) ^ v16[i] ^ v19[i] ^ v21[i]; v21[i + 3] = (2 * dword_4081BC) | (dword_4081BC >> 31) & 1; } v20 = v12; v18 = v11; v17 = v10; v15 = v9; v13 = v8; for ( i = 0; i < 80; ++i ) { dword_4081BC = v20; if ( i >= 40 ) { if ( i >= 60 ) v5 = v15 ^ v17 ^ v18; else v5 = v15 & v17 | v15 & v18 | v17 & v18; v6 = v5; } else { if ( i >= 20 ) v7 = v15 ^ v17 ^ v18; else v7 = v15 & ~v18 | v17 & v18; v6 = v7; } v21[0] = v21[i + 85] + v21[i + 3] + v13 + v6 + ((32 * dword_4081BC) | (dword_4081BC >> 27) & 0x1F); v13 = v15; v15 = v17; dword_4081BC = v18; v17 = (v18 << 30) | (v18 >> 2) & 0x3FFFFFFF; v18 = v20; v20 = v21[0]; } v12 += v20; v11 += v18; v10 += v17; v9 += v15; v8 += v13; v25 += 64; } free((void *)(v25 - Size)); return (void *)sub_4026A0(Buffer, "%08x%08x%08x%08x%08x", v12); } return result; }
-
六位密钥,可以先进行爆破
-
c=[0x3F, 0x95, 0xBB, 0xF2, 0x57, 0xF1, 0x7A, 0x5A, 0x22, 0x61, 0x51, 0x43, 0xA2, 0xFA, 0x9B, 0x6F, 0x44, 0x63, 0xC0, 0x08, 0x12, 0x65, 0x5C, 0x8A, 0x8C, 0x4C, 0xED, 0x5E, 0xCA, 0x76, 0xB9, 0x85, 0xAF, 0x05, 0x38, 0xED, 0x42, 0x3E, 0x42, 0xDF, 0x5D, 0xBE, 0x05, 0x8B, 0x35, 0x6D, 0xF3, 0x1C, 0xCF, 0xF8, 0x6A, 0x73, 0x25, 0xE4, 0xB7, 0xB9, 0x36, 0xFB, 0x02, 0x11, 0xA0, 0xF0, 0x57, 0xAB, 0x21, 0xC6, 0xC7, 0x46, 0x99, 0xBD, 0x1E, 0x61, 0x5E, 0xEE, 0x55, 0x18, 0xEE, 0x03, 0x29, 0x84, 0x7F, 0x94, 0x5F, 0xB4, 0x6A, 0x29, 0xD8, 0x6C, 0xE4, 0xC0, 0x9D, 0x6B, 0xCC, 0xD5, 0x94, 0x5C, 0xDD, 0xCC, 0xD5, 0x3D, 0xC0, 0xEF, 0x0C, 0x29, 0xE5, 0xB0, 0x93, 0xF1, 0xB3, 0xDE, 0xB0, 0x70] x=[0]*16+[0x31, 0x36, 0x32, 0x33, 0x30, 0x34, 0x36, 0x35, 0x31, 0x35, 0x32, 0x33, 0x33, 0x34, 0x36, 0x32, 0x31, 0x34, 0x34, 0x33, 0x31, 0x34, 0x37, 0x31, 0x31, 0x35, 0x30, 0x33, 0x31, 0x30, 0x37, 0x30, 0x31, 0x35, 0x30, 0x33, 0x32, 0x30, 0x37, 0x31, 0x31, 0x36, 0x30, 0x33, 0x32, 0x30, 0x36, 0x33, 0x31, 0x34, 0x30, 0x33, 0x33, 0x34, 0x36, 0x36, 0x31, 0x35, 0x34, 0x33, 0x34, 0x34, 0x36, 0x31, 0x31, 0x34, 0x34, 0x33, 0x34, 0x30, 0x36, 0x36, 0x31, 0x34, 0x32, 0x33, 0x30, 0x34, 0x36, 0x36, 0x31, 0x35, 0x36, 0x33, 0x34, 0x34, 0x36, 0x36, 0x31, 0x35, 0x34, 0x33, 0x30, 0x34, 0x36, 0x34] a1=[0]*256 v5=[0]*256 for i1 in range(48,58): for i2 in range(48, 58): for i3 in range(48, 58): for i4 in range(48, 58): for i5 in range(48, 58): for i6 in range(48, 58): key=[i1,i2,i3,i4,i5,i6] v6=0 for i in range(256): a1[i]=i v5[i]=key[i%6] for i in range(256): v6=(v5[i]+v6+a1[i])%256 v4=a1[i] a1[i]=a1[v6] a1[v6]=v4 flag=1 v6=0 v7=0 for i in range(112): v7=(v7+1)%256 v6=(v6+a1[v7])%256 v4=a1[v7] a1[v7]=a1[v6] a1[v6]=v4 if i<16: continue else: if c[i]^a1[(a1[v6]+a1[v7])%256]!=x[i]: flag=0 break if flag==1: print(i1,i2,i3,i4,i5,i6) exit(0)
-
然后直接对密文先进行RC4解密,再进行base8解密即可
-
def base8decode(c): flag='' for i in c: flag+=bin(int(chr(i)))[2:].rjust(3,'0') return [int(flag[i:i+8],2) for i in range(0,len(flag),8)] key=[56 ,48 ,55 ,51 ,57, 49] v6=0 a1=[0]*256 v5=[0]*256 for i in range(256): a1[i]=i v5[i]=key[i%6] for i in range(256): v6=(v5[i]+v6+a1[i])%256 a1[i],a1[v6]=a1[v6],a1[i] v6=0 v7=0 for i in range(112): v7=(v7+1)%256 v6=(v6+a1[v7])%256 a1[v7],a1[v6]=a1[v6],a1[v7] c[i]^=a1[(a1[v6]+a1[v7])%256] flag=bytes(base8decode(c)+key) print(flag)
-
DASCTF{561516915572239428449843076691286116796614807391}
二. Dual personality
-
本题打开就是一片红,发现是依据Window的WoW机制进行实现的天堂之门,那么本题主要思路就是一段一段dump分析即可
-
main第一段:
-
.text:004013A0 .text:004013A0 ; int __cdecl main(int argc, const char **argv, const char **envp) .text:004013A0 _main: ; CODE XREF: invoke_main(void)+2E↓p .text:004013A0 55 push ebp .text:004013A1 8B EC mov ebp, esp .text:004013A3 81 EC 34 01 00 00 sub esp, 134h .text:004013A9 53 push ebx .text:004013AA 56 push esi .text:004013AB 57 push edi .text:004013AC 8D 7D 8C lea edi, [ebp-74h] .text:004013AF B9 1D 00 00 00 mov ecx, 1Dh .text:004013B4 B8 CC CC CC CC mov eax, 0CCCCCCCCh .text:004013B9 F3 AB rep stosd .text:004013BB A1 24 70 40 00 mov eax, ___security_cookie .text:004013C0 33 C5 xor eax, ebp .text:004013C2 89 45 FC mov [ebp-4], eax .text:004013C5 E8 36 FC FF FF call sub_401000 .text:004013C5 .text:004013CA 68 60 70 40 00 push offset unk_407060 .text:004013CF 68 70 51 40 00 push offset a99s ; "%99s" .text:004013D4 E8 47 02 00 00 call sub_401620 .text:004013D4 .text:004013D9 83 C4 08 add esp, 8 .text:004013DC 68 D0 11 40 00 push offset dword_4011D0 .text:004013E1 6A 07 push 7 .text:004013E3 E8 38 FD FF FF call sub_401120 .text:004013E3 .text:004013E8 83 C4 08 add esp, 8 .text:004013EB 85 C0 test eax, eax .text:004013ED 74 05 jz short loc_4013F4 .text:004013ED .text:004013EF A1 58 70 40 00 mov eax, dword_407058 .text:004013EF
-
主要分析401120函数
-
两个参数,一个是长度,一个是地址
-
int __cdecl sub_401120(size_t Size, int a2) { char *v2; // ebx char *retaddr; // [esp+D0h] [ebp+4h] dword_407050 = VirtualAlloc(0, Size + 6, 0x3000u, 0x40u); dword_407000 = (int)dword_407050; memcpy(dword_407050, retaddr, Size); v2 = (char *)dword_407050 + Size; *v2 = -23; *(_DWORD *)(v2 + 1) = &retaddr[Size] - v2 - 5; v2[5] = -52; *retaddr = -22; *(_DWORD *)(retaddr + 1) = a2; *(_WORD *)(retaddr + 5) = 51; return 0; }
-
该函数首先创建新空间,将未修改前的指令拷贝至新申请的内存中,将调用函数的后长度个字修改为0xEA地址0x33 ,还有一个跳转回原地址的指令
-
修改后的指令实现一个远跳,同时修改cs与ip的地址,并切换成64位模式
-
下面将对应地址数据进行dump
-
seg000:0000000000000000 sub_0 proc near seg000:0000000000000000 65 48 8B 04 25 60 00 00 00 mov rax, qword ptr gs:loc_5F+1 seg000:0000000000000009 8A 40 02 mov al, [rax+2] seg000:000000000000000C 88 04 25 5C 70 40 00 mov ds:40705Ch, al seg000:0000000000000013 84 C0 test al, al seg000:0000000000000015 75 0E jnz short loc_25 seg000:0000000000000015 seg000:0000000000000017 41 BC AE 66 F9 5D mov r12d, 5DF966AEh seg000:000000000000001D 44 89 24 25 58 70 40 00 mov ds:407058h, r12d seg000:000000000000001D seg000:0000000000000025 seg000:0000000000000025 loc_25: ; CODE XREF: sub_0+15↑j seg000:0000000000000025 44 B8 00 70 40 00 mov eax, 407000h seg000:000000000000002B 48 FF 28 jmp qword ptr [rax] seg000:000000000000002B seg000:000000000000002B sub_0 endp
-
其中很明显的使用了Beingdebugged反调试技巧
-
并将407058的值进行修改
-
最终跳回407000中所存的地址处(就是原地址)
-
继续向下分析主函数
-
.text:004013F4 loc_4013F4: ; CODE XREF: .text:004013ED↑j .text:004013F4 2D 11 41 52 21 sub eax, 21524111h .text:004013F9 A3 58 70 40 00 mov dword_407058, eax .text:004013FE C7 45 F4 60 70 40 00 mov dword ptr [ebp-0Ch], offset unk_407060 .text:00401405 C7 45 E8 00 00 00 00 mov dword ptr [ebp-18h], 0 .text:0040140C EB 09 jmp short loc_401417 .text:0040140C .text:0040140E ; --------------------------------------------------------------------------- .text:0040140E .text:0040140E loc_40140E: ; CODE XREF: .text:0040144A↓j .text:0040140E 8B 45 E8 mov eax, [ebp-18h] .text:00401411 83 C0 01 add eax, 1 .text:00401414 89 45 E8 mov [ebp-18h], eax .text:00401414 .text:00401417 .text:00401417 loc_401417: ; CODE XREF: .text:0040140C↑j .text:00401417 83 7D E8 08 cmp dword ptr [ebp-18h], 8 .text:0040141B 7D 2F jge short loc_40144C .text:0040141B .text:0040141D 8B 45 E8 mov eax, [ebp-18h] .text:00401420 8B 4D F4 mov ecx, [ebp-0Ch] .text:00401423 8B 14 81 mov edx, [ecx+eax*4] .text:00401426 03 15 58 70 40 00 add edx, dword_407058 .text:0040142C 8B 45 E8 mov eax, [ebp-18h] .text:0040142F 8B 4D F4 mov ecx, [ebp-0Ch] .text:00401432 89 14 81 mov [ecx+eax*4], edx .text:00401435 8B 45 E8 mov eax, [ebp-18h] .text:00401438 8B 4D F4 mov ecx, [ebp-0Ch] .text:0040143B 8B 15 58 70 40 00 mov edx, dword_407058 .text:00401441 33 14 81 xor edx, [ecx+eax*4] .text:00401444 89 15 58 70 40 00 mov dword_407058, edx .text:0040144A EB C2 jmp short loc_40140E .text:0040144A
-
很明显的一段加密,循环
-
第一次加密后继续跳转
-
.text:0040144C loc_40144C: ; CODE XREF: .text:0040141B↑j .text:0040144C 6A 00 push 0 .text:0040144E 8D 05 60 70 40 00 lea eax, unk_407060 .text:00401454 50 push eax .text:00401455 FF 1D 0C 70 40 00 call fword ptr byte_40700C
-
这里的call实现第二次向64位的切换,
-
.data:0040700C byte_40700C db 0, 12h, 40h, 0, 33h, 0
-
将401200处数据dump下来
-
dump脚本如下:
-
static main(void) { auto fp, begin, end, dexbyte; fp = fopen("D:\dump1", "wb"); begin = 0x401200; end = 0x401288; for ( dexbyte = begin; dexbyte < end; dexbyte ++ ) fputc(Byte(dexbyte), fp); }
-
void sub_0() { _QWORD *v0; // [rsp+10h] [rbp+10h] if ( MEMORY[0x40705C] ) { *v0 = __ROL8__(*v0, 32); v0[1] = __ROL8__(v0[1], 32); v0[2] = __ROL8__(v0[2], 32); v0[3] = __ROL8__(v0[3], 32); JUMPOUT(0x7Ci64); } *v0 = __ROL8__(*v0, 12); v0[1] = __ROL8__(v0[1], 34); v0[2] = __ROL8__(v0[2], 56); v0[3] = __ROL8__(v0[3], 14); JUMPOUT(0x77i64); }
-
如果调试中,则错误加密,否则正确加密
-
结束后
.text:0040127C mov ebx, 0 .text:00401281 dec eax .text:00401282 xor eax, eax .text:00401284 dec eax .text:00401285 mov esp, ebp .text:00401287 pop ebp .text:00401288 retf 8
-
重新切换到32位模式(retf跳回原位置)
-
继续分析main
-
text:0040145B push offset dword_401290 .text:00401460 push 7 .text:00401462 call sub_401120 .text:00401462 .text:00401467 add esp, 8 .text:0040146A test eax, eax .text:0040146C jnz short near ptr loc_40146F+4 .text:0040146C .text:0040146E dec eax
-
又是一个401120函数,第三次切换成64位模式
-
继续dump分析
-
__int64 sub_0() { MEMORY[0x407000] = 4199621; MEMORY[0x407014] &= MEMORY[0x407018]; MEMORY[0x407018] |= MEMORY[0x40701C]; MEMORY[0x40701C] ^= MEMORY[0x407020]; MEMORY[0x407020] = ~MEMORY[0x407020]; return MEMORY[0x407050](); }
-
这里直接返回未修改前保存的指令,并未切换为32位
-
导致下面的指令无法被IDA32分析,故继续dump
-
seg000:0000000000000000 sub_0 proc near ; CODE XREF: sub_0+4C↓j seg000:0000000000000000 48 8B 04 25 C8 70 40 00 mov rax, ds:4070C8h seg000:0000000000000008 48 83 F8 20 cmp rax, 20h ; ' ' seg000:000000000000000C 74 40 jz short loc_4E seg000:000000000000000C seg000:000000000000000E 48 33 D2 xor rdx, rdx seg000:0000000000000011 48 B9 04 00 00 00 00 00 00 00 mov rcx, 4 seg000:000000000000001B 48 F7 F1 div rcx seg000:000000000000001E 48 8D 1C 25 14 70 40 00 lea rbx, ds:407014h seg000:0000000000000026 8A 14 93 mov dl, [rbx+rdx*4] seg000:0000000000000029 48 8B 04 25 C8 70 40 00 mov rax, ds:4070C8h seg000:0000000000000031 48 8D 1C 25 60 70 40 00 lea rbx, ds:407060h seg000:0000000000000039 8A 0C 03 mov cl, [rbx+rax] seg000:000000000000003C 32 CA xor cl, dl seg000:000000000000003E 88 0C 03 mov [rbx+rax], cl seg000:0000000000000041 48 FF C0 inc rax seg000:0000000000000044 48 89 04 25 C8 70 40 00 mov ds:4070C8h, rax seg000:000000000000004C EB B2 jmp short sub_0 seg000:000000000000004C seg000:000000000000004E ; --------------------------------------------------------------------------- seg000:000000000000004E seg000:000000000000004E loc_4E: ; CODE XREF: sub_0+C↑j seg000:000000000000004E 44 B8 00 70 40 00 mov eax, 407000h seg000:0000000000000054 48 FF 28 jmp qword ptr [rax] seg000:0000000000000054 seg000:0000000000000057 ; --------------------------------------------------------------------------- seg000:0000000000000057 33 C0 xor eax, eax seg000:0000000000000059 89 45 BC mov [rbp-44h], eax seg000:000000000000005C 89 45 C0 mov [rbp-40h], eax seg000:000000000000005F 89 45 C4 mov [rbp-3Ch], eax seg000:0000000000000062 89 45 C8 mov [rbp-38h], eax seg000:0000000000000065 89 45 CC mov [rbp-34h], eax seg000:0000000000000068 89 45 D0 mov [rbp-30h], eax seg000:000000000000006B 89 45 D4 mov [rbp-2Ch], eax seg000:000000000000006E 89 45 D8 mov [rbp-28h], eax seg000:0000000000000071 88 45 DC mov [rbp-24h], al seg000:0000000000000074 C6 45 90 AA mov byte ptr [rbp-70h], 0AAh seg000:0000000000000078 C6 45 91 4F mov byte ptr [rbp-6Fh], 4Fh ; 'O' seg000:000000000000007C C6 45 92 0F mov byte ptr [rbp-6Eh], 0Fh seg000:0000000000000080 C6 45 93 E2 mov byte ptr [rbp-6Dh], 0E2h seg000:0000000000000084 C6 45 94 E4 mov byte ptr [rbp-6Ch], 0E4h seg000:0000000000000088 C6 45 95 41 mov byte ptr [rbp-6Bh], 41h ; 'A' seg000:000000000000008C C6 45 96 99 mov byte ptr [rbp-6Ah], 99h seg000:0000000000000090 C6 45 97 54 mov byte ptr [rbp-69h], 54h ; 'T' seg000:0000000000000094 C6 45 98 2C mov byte ptr [rbp-68h], 2Ch ; ',' seg000:0000000000000098 C6 45 99 2B mov byte ptr [rbp-67h], 2Bh ; '+' seg000:000000000000009C C6 45 9A 84 mov byte ptr [rbp-66h], 84h seg000:00000000000000A0 C6 45 9B 7E mov byte ptr [rbp-65h], 7Eh ; '~' seg000:00000000000000A4 C6 45 9C BC mov byte ptr [rbp-64h], 0BCh seg000:00000000000000A8 C6 45 9D 8F mov byte ptr [rbp-63h], 8Fh seg000:00000000000000AC C6 45 9E 8B mov byte ptr [rbp-62h], 8Bh seg000:00000000000000B0 C6 45 9F 78 mov byte ptr [rbp-61h], 78h ; 'x' seg000:00000000000000B4 C6 45 A0 D3 mov byte ptr [rbp-60h], 0D3h seg000:00000000000000B8 C6 45 A1 73 mov byte ptr [rbp-5Fh], 73h ; 's' seg000:00000000000000BC C6 45 A2 88 mov byte ptr [rbp-5Eh], 88h seg000:00000000000000C0 C6 45 A3 5E mov byte ptr [rbp-5Dh], 5Eh ; '^' seg000:00000000000000C4 C6 45 A4 AE mov byte ptr [rbp-5Ch], 0AEh seg000:00000000000000C8 C6 45 A5 47 mov byte ptr [rbp-5Bh], 47h ; 'G' seg000:00000000000000CC C6 45 A6 85 mov byte ptr [rbp-5Ah], 85h seg000:00000000000000D0 C6 45 A7 70 mov byte ptr [rbp-59h], 70h ; 'p' seg000:00000000000000D4 C6 45 A8 31 mov byte ptr [rbp-58h], 31h ; '1' seg000:00000000000000D8 C6 45 A9 B3 mov byte ptr [rbp-57h], 0B3h seg000:00000000000000DC C6 45 AA 09 mov byte ptr [rbp-56h], 9 seg000:00000000000000E0 C6 45 AB CE mov byte ptr [rbp-55h], 0CEh seg000:00000000000000E4 C6 45 AC 13 mov byte ptr [rbp-54h], 13h seg000:00000000000000E8 C6 45 AD F5 mov byte ptr [rbp-53h], 0F5h seg000:00000000000000EC C6 45 AE 0D mov byte ptr [rbp-52h], 0Dh seg000:00000000000000F0 C6 45 AF CA mov byte ptr [rbp-51h], 0CAh seg000:00000000000000F4 33 C0 xor eax, eax seg000:00000000000000F6 88 45 B0 mov [rbp-50h], al seg000:00000000000000F9 6A 20 push 20h ; ' ' seg000:00000000000000FB 8D 45 90 lea eax, [rbp-70h] seg000:00000000000000FE 50 push rax seg000:00000000000000FF 68 60 70 40 00 push 407060h seg000:0000000000000104 E8 AD 2C 00 00 call near ptr 2DB6h seg000:0000000000000104 seg000:0000000000000109 83 C4 0C add esp, 0Ch seg000:000000000000010C 85 C0 test eax, eax seg000:000000000000010E 75 28 jnz short loc_138 seg000:000000000000010E seg000:0000000000000110 8B F4 mov esi, esp seg000:0000000000000112 68 78 51 40 00 push 405178h seg000:0000000000000117 FF 15 F8 50 40 00 call qword ptr cs:405215h seg000:0000000000000117 seg000:000000000000011D 83 C4 04 add esp, 4 seg000:0000000000000120 3B F4 cmp esi, esp seg000:0000000000000122 E8 9B 02 00 00 call near ptr 3C2h seg000:0000000000000122 seg000:0000000000000127 8B F4 mov esi, esp seg000:0000000000000129 6A 00 push 0 seg000:000000000000012B FF 15 F0 50 40 00 call qword ptr cs:405221h seg000:000000000000012B seg000:0000000000000131 3B F4 cmp esi, esp seg000:0000000000000133 E8 8A 02 00 00 call near ptr 3C2h seg000:0000000000000133 seg000:0000000000000138 seg000:0000000000000138 loc_138: ; CODE XREF: sub_0+10E↑j seg000:0000000000000138 8B F4 mov esi, esp seg000:000000000000013A 68 9C 51 40 00 push 40519Ch seg000:000000000000013F FF 15 F8 50 40 00 call qword ptr cs:40523Dh seg000:000000000000013F seg000:0000000000000145 83 C4 04 add esp, 4 seg000:0000000000000148 3B F4 cmp esi, esp seg000:000000000000014A E8 73 02 00 00 call near ptr 3C2h seg000:000000000000014A seg000:000000000000014F 33 C0 xor eax, eax seg000:0000000000000151 52 push rdx seg000:0000000000000152 8B CD mov ecx, ebp seg000:0000000000000154 50 push rax seg000:0000000000000155 8D 15 F0 15 40 00 lea edx, cs:40174Bh seg000:000000000000015B E8 02 02 00 00 call near ptr 362h seg000:000000000000015B seg000:0000000000000160 58 pop rax seg000:0000000000000161 5A pop rdx seg000:0000000000000162 5F pop rdi seg000:0000000000000163 5E pop rsi seg000:0000000000000164 5B pop rbx seg000:0000000000000165 8B 4D FC mov ecx, [rbp-4] seg000:0000000000000168 33 CD xor ecx, ebp seg000:000000000000016A E8 C3 02 00 00 call near ptr 432h seg000:000000000000016A seg000:000000000000016F 81 C4 34 01 00 00 add esp, 134h seg000:0000000000000175 3B EC cmp ebp, esp seg000:0000000000000177 E8 46 02 00 00 call near ptr 3C2h seg000:0000000000000177 seg000:000000000000017C 8B E5 mov esp, ebp seg000:000000000000017E 5D pop rbp seg000:000000000000017E seg000:000000000000017E sub_0 endp ; sp-analysis failed
-
主要操作即为 : ^key[i%4]
-
再回到主函数,后面就没有天堂之门了
-
按顺序写一下解密函数
-
int main() { DWORD key[] = { 4 ,119 ,130 ,-182 }; DWORD delta = 0x5df966ae; unsigned char flag[]={0xAA, 0x4F, 0x0F, 0xE2, 0xE4, 0x41, 0x99, 0x54, 0x2C, 0x2B, 0x84, 0x7E, 0xBC, 0x8F, 0x8B, 0x78, 0xD3, 0x73, 0x88, 0x5E, 0xAE, 0x47, 0x85, 0x70, 0x31, 0xB3, 0x09, 0xCE, 0x13, 0xF5, 0x0D, 0xCA}; DWORD* pDwordFlag = (DWORD*)flag; unsigned long long* pQwordFlag = (unsigned long long*)flag; for (int i = 0; i < 32; i++) { flag[i] ^= key[i % 4]; } pQwordFlag = (unsigned long long*)flag; *(pQwordFlag + 0) = (*(pQwordFlag + 0) >> 12) | (*(pQwordFlag + 0) << (64 - 12)); *(pQwordFlag + 1) = (*(pQwordFlag + 1) >> 34) | (*(pQwordFlag + 1) << (64 - 34)); *(pQwordFlag + 2) = (*(pQwordFlag + 2) >> 56) | (*(pQwordFlag + 2) << (64 - 56)); *(pQwordFlag + 3) = (*(pQwordFlag + 3) >> 14) | (*(pQwordFlag + 3) << (64 - 14)); delta = 0x5df966ae; delta += 0xdeadbeef; //0x3CA7259D for (int i = 0; i < 8; i++) { DWORD tmp = pDwordFlag[i] ^ delta; pDwordFlag[i] -= delta; delta = tmp; } printf("flag:DASCTF{%s}", flag); return 0; }
-
DASCTF{6cc1e44811647d38a15017e389b3f704}