Maze
题目分析
先查看main函数,可以输入6个方向,再看一下移动1,8,64就知道是一个三维的地图,且会一直移动直到遇到1.
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+20h] [rbp-98h]
char dir[112]; // [rsp+30h] [rbp-88h] BYREF
v4 = 0;
memset(dir, 0, 100);
print((__int64)"Welcome to this sign in problem.\n", argv, envp);
print((__int64)"Give me your input:");
scanf("%s", dir);
for ( i = 0; ; ++i )
{
if ( i >= strlen(dir) )
wrong();
Sleep(0x28u);
switch ( dir[i] )
{
case 'a':
while ( 1 )
{
if ( v4 % 8 - 1 < 0 )
wrong();
if ( *((_BYTE *)off_7FF63A4B6200 + v4 - 1) )
break;
--v4;
}
break;
case 'd':
while ( 1 )
{
if ( v4 % 8 + 1 >= 8 )
wrong();
if ( *((_BYTE *)off_7FF63A4B6200 + v4 + 1) )
break;
++v4;
}
break;
case 'n':
while ( 1 )
{
if ( v4 - 64 < 0 )
wrong();
if ( *((_BYTE *)off_7FF63A4B6200 + v4 - 64) )
break;
v4 -= 64;
}
break;
case 's':
while ( 1 )
{
if ( v4 % 64 + 8 >= 64 )
wrong();
if ( *((_BYTE *)off_7FF63A4B6200 + v4 + 8) )
break;
v4 += 8;
}
break;
case 'u':
while ( 1 )
{
if ( v4 + 64 >= 512 )
wrong();
if ( *((_BYTE *)off_7FF63A4B6200 + v4 + 64) )
break;
v4 += 64;
}
break;
case 'w':
while ( 1 )
{
if ( v4 % 64 - 8 < 0 )
wrong();
if ( *((_BYTE *)off_7FF63A4B6200 + v4 - 8) )
break;
v4 -= 8;
}
break;
default:
wrong();
}
if ( v4 == 436 )
break;
}
print((__int64)"Good job, the flag is md5_32_lower(your input)");
return 0;
}
直接调试这个程序发现闪退,翻函数列表发现有TlsCallback回调函数。
这里对一个函数进行了解密。
int __fastcall TlsCallback_0(__int64 a1, int a2)
{
int result; // eax
int i; // [rsp+20h] [rbp-128h]
DWORD flOldProtect[3]; // [rsp+24h] [rbp-124h] BYREF
char v5[256]; // [rsp+30h] [rbp-118h] BYREF
v5[0] = 27;
v5[1] = -107;
v5[2] = -120;
v5[3] = -38;
v5[4] = -112;
v5[5] = -112;
v5[6] = -87;
v5[7] = -107;
v5[8] = -98;
v5[9] = -38;
v5[10] = -112;
v5[11] = -112;
v5[12] = -28;
v5[13] = -12;
v5[14] = 27;
v5[15] = -107;
v5[16] = -106;
v5[17] = -38;
v5[18] = -112;
v5[19] = -112;
v5[20] = 25;
v5[21] = -107;
v5[22] = -108;
v5[23] = -38;
v5[24] = -112;
v5[25] = -112;
v5[26] = 19;
v5[27] = -83;
v5[28] = -103;
v5[29] = -39;
v5[30] = -112;
v5[31] = -112;
v5[32] = -111;
v5[33] = -27;
v5[34] = -102;
v5[35] = 87;
v5[36] = -44;
v5[37] = -76;
v5[38] = -80;
v5[39] = -110;
v5[40] = -112;
v5[41] = -112;
v5[42] = -112;
v5[43] = 123;
v5[44] = -104;
v5[45] = 87;
v5[46] = -44;
v5[47] = -76;
v5[48] = -80;
v5[49] = -111;
v5[50] = -112;
v5[51] = -112;
v5[52] = -112;
v5[53] = 27;
v5[54] = -44;
v5[55] = -76;
v5[56] = -80;
v5[57] = 25;
v5[58] = -107;
v5[59] = 123;
v5[60] = -40;
v5[61] = -112;
v5[62] = -112;
v5[63] = 19;
v5[64] = -83;
v5[65] = 116;
v5[66] = -40;
v5[67] = -112;
v5[68] = -112;
v5[69] = -111;
v5[70] = -27;
v5[71] = -98;
v5[72] = -40;
v5[73] = 29;
v5[74] = -107;
v5[75] = 11;
v5[76] = -44;
v5[77] = -112;
v5[78] = -112;
v5[79] = -40;
v5[80] = 25;
v5[81] = -44;
v5[82] = -76;
v5[83] = -72;
v5[84] = 123;
v5[85] = -100;
v5[86] = -40;
v5[87] = 29;
v5[88] = -107;
v5[89] = 93;
v5[90] = -42;
v5[91] = -112;
v5[92] = -112;
v5[93] = -40;
v5[94] = 25;
v5[95] = -44;
v5[96] = -76;
v5[97] = -72;
v5[98] = -40;
v5[99] = 29;
v5[100] = -107;
v5[101] = 81;
v5[102] = -42;
v5[103] = -112;
v5[104] = -112;
v5[105] = -40;
v5[106] = 27;
v5[107] = -36;
v5[108] = -76;
v5[109] = -72;
v5[110] = -40;
v5[111] = 25;
v5[112] = -40;
v5[113] = 80;
result = 0;
memset(&v5[114], 0, 0x8Eui64);
if ( a2 == 1 )
{
result = VirtualProtect(sub_7FF63A4B1A60, 0x2000ui64, 0x40u, flOldProtect);
for ( i = 0; i < 114; ++i )
{
*((_BYTE *)sub_7FF63A4B1A60 + i + 182) ^= v5[i];
result = i + 1;
}
}
return result;
}
这里动调拿到解密完成后的反编译代码。
void __noreturn sub_7FF63A4B1A60()
{
HANDLE CurrentThread; // rax
HANDLE CurrentProcess; // rax
int v2; // [rsp+20h] [rbp-508h]
_QWORD *v3; // [rsp+28h] [rbp-500h]
HMODULE hModule; // [rsp+30h] [rbp-4F8h]
FARPROC ProcAddress; // [rsp+38h] [rbp-4F0h]
struct _CONTEXT Context; // [rsp+40h] [rbp-4E8h] BYREF
while ( 1 )
{
hModule = GetModuleHandleA("Ntdll");
ProcAddress = GetProcAddress(hModule, aS_0);
memset(&Context, 0, sizeof(Context));
Context.ContextFlags = 1048592;
CurrentThread = GetCurrentThread();
GetThreadContext(CurrentThread, &Context);
if ( Context.Dr0 || Context.Dr1 || Context.Dr2 || Context.Dr3 )
{
CurrentProcess = GetCurrentProcess();
((void (__fastcall *)(HANDLE, _QWORD))ProcAddress)(CurrentProcess, 0i64);
}
if ( i != i1 )
{
i1 = i;
if ( dword_7FF63A4B6440 == 1 )
v2 = 2;
else
v2 = 1;
dword_7FF63A4B6440 = v2;
if ( v2 == 1 )
v3 = &unk_7FF63A4B6000;
else
v3 = qword_7FF63A4B6240;
qword_7FF63A4B6240[-8] = v3;
}
Sleep(1u);
}
}
这里有一个反调试(检测硬件断点,检测到了就调用Ntdll库的ZwTerminateProcess函数)。
它会隔一次切换一次地图,而416这个终点的位置在map2。
另外发现原本上面的字符发生了改变,查一下交叉引用发现另一个反调试的函数
__int64 __fastcall sub_7FF63A4B1810(__int64 a1)
{
HANDLE CurrentThread; // rax
int i; // [rsp+20h] [rbp-28h]
int j; // [rsp+20h] [rbp-28h]
int k; // [rsp+20h] [rbp-28h]
HMODULE hModule; // [rsp+28h] [rbp-20h]
FARPROC ProcAddress; // [rsp+30h] [rbp-18h]
for ( i = 0; i < 5; ++i )
aNtdll[i] = (aNtdll[i] - 100) ^ 0x55;
for ( j = 0; j < 22; ++j )
ProcName[j] = (ProcName[j] - 100) ^ 0x55;
for ( k = 0; k < 18; ++k )
aS_0[k] = (aS_0[k] - 100) ^ 0x55;
hModule = GetModuleHandleA("Ntdll");
ProcAddress = GetProcAddress(hModule, ProcName);
CurrentThread = GetCurrentThread();
((void (__fastcall *)(HANDLE, __int64, _QWORD, _QWORD))ProcAddress)(CurrentThread, 17i64, 0i64, 0i64);
return a1;
}
那就是走两个切换的迷宫,据此写出脚本
exp
map1 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
map2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
def dfs(cnt, pos, path):
# 设置最大深度
if cnt > 15:
return
if pos == 436:
print(path)
if cnt % 2 == 0:
maze = map1
else:
maze = map2
# a
pos1 = pos
if maze[pos - 1] != 1:
while 1:
if pos1 % 8 == 0:
break
if maze[pos1-1] == 1:
dfs(cnt + 1, pos1, path + 'a')
pos1 -= 1
# d
pos2 = pos
if maze[pos + 1] != 1:
while 1:
if pos2 % 8 == 7:
break
if maze[pos2+1] == 1:
dfs(cnt + 1, pos2, path + 'd')
pos2 += 1
# n
pos3 = pos
if maze[pos - 64] != 1:
while 1:
if pos3 < 64:
break
if maze[pos3-64] == 1:
dfs(cnt + 1, pos3, path + 'n')
pos3 -= 64
# u
pos4 = pos
if maze[pos + 64] != 1:
while 1:
if pos4 + 64 >= 512:
break
if maze[pos4+64] == 1:
dfs(cnt + 1, pos4, path + 'u')
pos4 += 64
# s
pos5 = pos
if maze[pos + 8] != 1:
while 1:
if pos5 % 64 >= 56:
break
if maze[pos5+8] == 1:
dfs(cnt + 1, pos5, path + 's')
pos5 += 8
# w
pos6 = pos
if maze[pos - 8] != 1:
while 1:
if pos6 % 64 < 8:
break
if maze[pos6-8] == 1:
dfs(cnt + 1, pos6, path + 'w')
pos6 -= 8
dfs(0, 0, '')
得到路径sdwusanwduawus
flag:
DASCTF{1bb5fd78f2299f26ccc0630c5e7516b6}
ezcpp
题目分析
进入主函数
这里把输入转为了两个32位的数,可以猜到只接收了8个字符的输入。
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *v3; // rax
__int64 input_ur_flag; // rax
char v6[8]; // [rsp+20h] [rbp-188h] BYREF
void (__fastcall ***v7)(unsigned __int8 (__fastcall ***)(_QWORD)); // [rsp+28h] [rbp-180h]
int v8; // [rsp+30h] [rbp-178h]
_QWORD *v9; // [rsp+38h] [rbp-170h]
__int64 *v10; // [rsp+40h] [rbp-168h]
_QWORD *v11; // [rsp+48h] [rbp-160h]
struct _TEB *v12; // [rsp+50h] [rbp-158h]
struct _PEB *ProcessEnvironmentBlock; // [rsp+58h] [rbp-150h]
void *Block; // [rsp+68h] [rbp-140h]
__int64 v15; // [rsp+70h] [rbp-138h]
char Src[24]; // [rsp+78h] [rbp-130h] BYREF
__crt_locale_pointers input[17]; // [rsp+90h] [rbp-118h] BYREF
v8 = 1;
v12 = NtCurrentTeb();
memset(input, 0, 0x100ui64);
memset(v6, 0, 1ui64);
v3 = j_memcpy(v6, Src, (size_t)envp);
input_ur_flag = j_j_xor((__int64)v3);
sub_7FF628672A40(std::cout, input_ur_flag);
mbstrlen_l(std::cin, input);
input1 = SBYTE3(input[0].locinfo) | (SBYTE2(input[0].locinfo) << 8) | (SBYTE1(input[0].locinfo) << 16) | (SLOBYTE(input[0].locinfo) << 24);
input2 = SHIBYTE(input[0].locinfo) | (SBYTE6(input[0].locinfo) << 8) | (SBYTE5(input[0].locinfo) << 16) | (SBYTE4(input[0].locinfo) << 24);
v9 = operator new(8ui64);
if ( v9 )
{
memset(v9, 0, sizeof(_QWORD));
v11 = sub_7FF6286721E0(v9);
}
else
{
v11 = 0i64;
}
v7 = (void (__fastcall ***)(unsigned __int8 (__fastcall ***)(_QWORD)))v11;
v10 = (__int64 *)unknown_libname_17((__int64)v11);
v15 = *v10;
sub_7FF628671B20((__int64)v10, (__int64)sub_7FF628671A60, 0);
(**v7)((unsigned __int8 (__fastcall ***)(_QWORD))v7);
ProcessEnvironmentBlock = v12->ProcessEnvironmentBlock;
if ( ProcessEnvironmentBlock->BeingDebugged == 1 )
exit(0);
sub_7FF628671B20((__int64)v10, (__int64)call_exception, 0);
if ( ((unsigned __int8 (__fastcall *)(_QWORD))**v7)(v7) )
sub_7FF628671080("YES!!");
else
sub_7FF628671080("Failed..");
Block = v7;
j_j_free(v7);
system("pause");
return 0;
}
这里打印的信息都是从内存中读取数据再进行xor操作得到的,包括后面的获取密文也是需要xor操作。
然后进行了hook操作,调用了sub_7FF628671A60和call_exception函数。
sub_7FF628671A60函数产生了异常,但是tab键看汇编并没有找到异常处理代码,仅仅用来抛出异常,让主函数进入异常处理。
void __noreturn sub_7FF628671A60()
{
char pExceptionObject[40]; // [rsp+20h] [rbp-28h] BYREF
sub_7FF6286715D0(pExceptionObject, "Memory allocation failed");
CxxThrowException(pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__);
}
call_exception产生了除0异常。
_BOOL8 call_exception()
{
return 5 / 0 != 0;
}
观察汇编可以看到一场处理调用了sub_7FF628671BA0这个函数并将之前由输入获得的两个32位数字传入作为参数。
进入这个函数,发现又抛出了异常,并且这里还执行了qmemcpy(v2, &unk_7FF628678090, 0x130ui64);这个操作。
char sub_7FF628671BA0()
{
__int64 v0; // rax
void *v2; // [rsp+28h] [rbp-E0h]
char pExceptionObject[24]; // [rsp+60h] [rbp-A8h] BYREF
v2 = VirtualAlloc(0i64, 0x130ui64, 0x3000u, 0x40u);
if ( v2 )
{
qmemcpy(v2, &unk_7FF628678090, 0x130ui64);
sub_7FF6286715D0(pExceptionObject, "Memory allocation failed");
CxxThrowException(pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__);
}
v0 = sub_7FF628672A40(std::cerr, (__int64)"Memory allocation failed");
std::ostream::operator<<(v0, sub_7FF628672DA0);
return 1;
}
汇编找到异常处理,将unk_7FF628678090的值xor了0xDA。
这里脚本跑一下,发现最后的数据是0xcc就可以看出来是个函数。
import idc
ea_start=0x7FF628678090
for i in range(304):
tmp = idc.get_bytes(ea_start+i,1)
tmp = 0xda ^ ord(tmp)
idc.patch_byte(ea_start+i,tmp)
print("ok")
得到的函数反编译结果:是个魔改的xtea,重命名函数为xtea
再看sub_7FF628671BA0的汇编,在异常处理之后果然有调用xtea这个函数。
这里改一下汇编,再看sub_7FF628671BA0的反编译。
// positive sp value has been detected, the output may be wrong!
bool __fastcall sub_7FF628671BA0(int a1, int a2)
{
__int64 v2; // rbp
__int64 v3; // rdx
__int64 v4; // rax
__int64 v6; // rax
__int64 v7; // rax
__int64 v8; // rax
__int64 v9; // rax
_QWORD v10[3]; // [rsp-28h] [rbp-138h] BYREF
__int64 v11; // [rsp-10h] [rbp-120h]
__int64 v12; // [rsp-8h] [rbp-118h]
__int64 v13; // [rsp+0h] [rbp-110h]
unsigned __int64 (__fastcall *v14)(unsigned int, unsigned int, int); // [rsp+8h] [rbp-108h]
unsigned __int64 (__fastcall *v15)(unsigned int, unsigned int, int); // [rsp+10h] [rbp-100h]
__int64 v16; // [rsp+30h] [rbp-E0h] BYREF
__int64 v17; // [rsp+50h] [rbp-C0h] BYREF
__int64 v18; // [rsp+70h] [rbp-A0h] BYREF
_BYTE v19[75]; // [rsp+85h] [rbp-8Bh] BYREF
unsigned int v20; // [rsp+D0h] [rbp-40h]
int v21; // [rsp+F0h] [rbp-20h]
int v22; // [rsp+F8h] [rbp-18h]
v22 = a2;
v21 = a1;
v14 = (unsigned __int64 (__fastcall *)(unsigned int, unsigned int, int))VirtualAlloc(0i64, 0x130ui64, 0x3000u, 0x40u);
if ( v14 )
{
qmemcpy(v14, xtea, 0x130ui64);
v15 = 0i64;
v11 = v3;
v10[0] = v2;
*(_QWORD *)(v3 + 48) = *(_QWORD *)(v3 + 40);
for ( *(_DWORD *)(v3 + 36) = 0; *(int *)(v3 + 36) < 304; ++*(_DWORD *)(v3 + 36) )
*(_BYTE *)(*(_QWORD *)(v3 + 40) + *(int *)(v3 + 36)) ^= 0xDAu;
v11 = ((__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD))v10[2])(
*(unsigned int *)&v19[67],
v20,
(unsigned int)dword_7FF628678378);
memset(v10, 0, 1ui64);
v12 = ((__int64 (__fastcall *)(__int64 *, __int64))sub_7FF628671820)(&v16, v11);
v13 = v12;
v6 = ((__int64 (__fastcall *)(_QWORD *, __int64 *))sub_7FF628671DE0)(v10, &v18);
v7 = ((__int64 (__fastcall *)(__int64))sub_7FF628672290)(v6);
BYTE1(v10[0]) = ((__int64 (__fastcall *)(__int64, __int64))sub_7FF628672DF0)(v13, v7);
((void (__fastcall *)(__int64 *))sub_7FF628672310)(&v16);
if ( BYTE1(v10[0]) )
{
return 1;
}
else
{
memset((char *)v10 + 2, 0, sizeof(char));
v14 = (unsigned __int64 (__fastcall *)(unsigned int, unsigned int, int))((__int64 (__fastcall *)(__int64 *, __int64))sub_7FF628671820)(
&v17,
v11);
v15 = v14;
v8 = ((__int64 (__fastcall *)(char *, _BYTE *))sub_7FF628671E80)((char *)v10 + 2, v19);
v9 = ((__int64 (__fastcall *)(__int64))sub_7FF628672250)(v8);
BYTE3(v10[0]) = ((__int64 (__fastcall *)(unsigned __int64 (__fastcall *)(unsigned int, unsigned int, int), __int64))sub_7FF628672DF0)(
v15,
v9);
((void (__fastcall *)(__int64 *))sub_7FF628672310)(&v17);
return BYTE3(v10[0]) != 0;
}
}
else
{
v4 = sub_7FF628672A40(std::cerr, (__int64)"Memory allocation failed");
std::ostream::operator<<(v4, sub_7FF628672DA0);
return 1;
}
}
其中这里是调用xtea函数,前两个参数是我们之前传入的input1和input2,也就是那两个32位数。那么第三个参数是什么呢。
动态调试的过程中,这里有一处很明显的反调试,但是我们调试时并没有退出。
查看这里的汇编,产生了异常并且发生了异常处理,导致没有exit,而这里将ProcessEnvironmentBlock->BeingDebugged的值赋给了cs: dword_7FF628678378,也就是我们刚刚xtea的第三个参数。
现在,就只差密文就可以解密了,在sub_7FF628671BA0函数里面,有两处xor产生密文并将密文字符形式转为二进制形式,这两个密文分别对应ProcessEnvironmentBlock->BeingDebugged等于0和等于1的情况,也就是调试和非调试情况。这里直接解非调试情况下的明文提交不正确,8位作为flag也确实太短了,再解调试情况下的明文,将两个输入拼接起来就是flag
exp
enc = b"6?<82>967 4:1=??468$\a"
mes = ""
for i in range(len(enc)):
mes += chr(enc[i] ^ (i % 10 + 7))
print(mes)
enc = [ 0x32, 0x36, 0x35, 0x33, 0x32, 0x34, 0x36, 0x34, 0x37, 0x35,
0x33, 0x32, 0x33, 0x34, 0x32, 0x36, 0x35, 0x36, 0x35, 0x30,
0x03]
mes = ""
for i in range(len(enc)):
mes += chr(enc[i] ^ (i % 5 + 3))
print(mes)
from struct import pack
def decry(debuggerpresent, enc):
prev = (enc ^ debuggerpresent) >> 32
next = (enc ^ debuggerpresent) & 0xffffffff
key = [0x42CA4455, 0x8E0AE93B, 0xA569C4D0, debuggerpresent + 0x523A855B]
sum = 0xF3E56 * 32 & 0xffffffff
for i in range(32):
next -= (key[sum >> 11 & 3] + sum) ^ (prev + ((prev >> 5) ^ (prev << 4)))
next &= 0xffffffff
sum -= 0xF3E56
sum &= 0xffffffff
prev -= (key[sum & 3] + sum) ^ (next + ((next >> 5) ^ (16 * next)))
prev &= 0xffffffff
print(pack('>I', prev) + pack('>I', next))
decry(0, 17529248803287439874)
decry(1, 12055721120662551337)
flag
解密得到两个字符串,把他们拼接在一起,再用DASCTF{}包裹:DASCTF{G0g3tTea7up@fT3A}