[SWPU2019]EasiestRe
双进程保护
父进程
用于调试运行子进程,遇到int3指令进行处理
int __usercall sub_978BC0@<eax>(int a1@<xmm0>)
{
ProcessInformation.hProcess = 0;
ProcessInformation.hThread = 0;
ProcessInformation.dwProcessId = 0;
ProcessInformation.dwThreadId = 0;
sub_971EFB((int)&StartupInfo, 0, 68);
v94 = -112;
v95 = -125;
v96 = 125;
v97 = -8;
v98 = 24;
v99 = 125;
v100 = 17;
v64 = -112;
v65 = 15;
v66 = -74;
v67 = 85;
v68 = -9;
v69 = -117;
v70 = 69;
v71 = 8;
v72 = -117;
v73 = 4;
v74 = -112;
v75 = 15;
v76 = -81;
v77 = 69;
v78 = -4;
v79 = 51;
v80 = -46;
v81 = -9;
v82 = 117;
v83 = -8;
v84 = 15;
v85 = -74;
v86 = 77;
v87 = -9;
v88 = -117;
v89 = 69;
v90 = 12;
v91 = -119;
v92 = 20;
v93 = -120;
sub_971EFB((int)Buffer, 0, 50);
NumberOfBytesWritten = 0;
i = 0;
v57 = 1;
v1 = IsDebuggerPresent();
if ( sub_973481(v3, v2, &v47 == &v47, v1, a1) )
{
j_main(v47, v48, v49); //调试情况下
}
else
{
GetStartupInfoA(&StartupInfo);
sub_973481(v7, v6, &v47 == &v47, v5, a1);
v8 = GetModuleFileNameA(0, &Filename, 0x104u);
sub_973481(v10, v9, &v47 == &v47, v8, a1);
v11 = CreateProcessA(&Filename, 0, 0, 0, 0, 3u, 0, 0, &StartupInfo, &ProcessInformation);
v52 = sub_973481(v13, v12, &v47 == &v47, v11, a1) != 0;
LOBYTE(v4) = v52;
v104 = v52;
if ( v52 )
{
v54 = 1;
lpBaseAddress = 0;
while ( v54 )
{
dwContinueStatus = 65538;
v14 = WaitForDebugEvent(&DebugEvent, 0xFFFFFFFF);
sub_973481(v16, v15, &v47 == &v47, v14, a1);
v51 = DebugEvent.dwDebugEventCode - 1;
switch ( DebugEvent.dwDebugEventCode )
{
case 1u:
v50 = DebugEvent.u.Exception.ExceptionRecord.ExceptionCode;
if ( DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == -2147483645 )//异常0x80000003
{
v57 = 1;
dwContinueStatus = 65538;
lpBaseAddress = DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress;
v17 = ReadProcessMemory(
ProcessInformation.hProcess,
DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,
Buffer,
0x23u,
&NumberOfBytesRead);
sub_973481(v19, v18, &v47 == &v47, v17, a1);
if ( NumberOfBytesRead )
{
for ( i = 1; i < 35 && (unsigned __int8)Buffer[i] == 144; ++i ) //计算int3与nop的长度
;
}
if ( i == 1 )
v57 = 0;
if ( v57 )
{
v49 = (const char **)(i - 4);
switch ( i ) //根据长度处理
{
case 4:
Context.ContextFlags = 65543;
v29 = OpenThread(0x1FFFFFu, 0, DebugEvent.dwThreadId);
v32 = (void *)sub_973481(v31, v30, &v47 == &v47, (int)v29, a1);
hThread = v32;
v33 = GetThreadContext(v32, &Context);
if ( !sub_973481(v35, v34, &v47 == &v47, v33, a1) )
goto LABEL_32;
++Context.Eip;
v36 = SetThreadContext(hThread, &Context);
if ( sub_973481(v38, v37, &v47 == &v47, v36, a1) )
{
dwContinueStatus = 65538;
v39 = CloseHandle(hThread);
sub_973481(v41, v40, &v47 == &v47, v39, a1);
}
break;
case 5:
LABEL_32:
dwContinueStatus = 0x80010001;
break;
case 7: //和下面30都是补缺的机器码
v20 = WriteProcessMemory(
ProcessInformation.hProcess,
(LPVOID)lpBaseAddress,
&v94,
7u,
&NumberOfBytesWritten);
sub_973481(v22, v21, &v47 == &v47, v20, a1);
if ( NumberOfBytesWritten == 7 )
{
v23 = ReadProcessMemory(
ProcessInformation.hProcess,
lpBaseAddress,
Buffer,
7u,
&NumberOfBytesRead);
sub_973481(v25, v24, &v47 == &v47, v23, a1);
dwContinueStatus = 65538;
}
break;
case 30:
v26 = WriteProcessMemory(
ProcessInformation.hProcess,
(LPVOID)lpBaseAddress,
&v64,
0x1Eu,
&NumberOfBytesWritten);
sub_973481(v28, v27, &v47 == &v47, v26, a1);
if ( NumberOfBytesWritten == 30 )
dwContinueStatus = 65538;
break;
default:
goto LABEL_35;
}
}
else
{
dwContinueStatus = 0x80010001;
}
}
break;
case 2u:
dwContinueStatus = 65538;
break;
case 3u:
dwContinueStatus = 65538;
break;
case 4u:
dwContinueStatus = 65538;
v54 = 0;
break;
case 5u:
dwContinueStatus = 65538;
v54 = 0;
break;
case 6u:
dwContinueStatus = 65538;
break;
default:
break;
}
LABEL_35:
v42 = ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, dwContinueStatus);
sub_973481(v44, v43, &v47 == &v47, v42, a1);
}
}
}
v45 = v4;
sub_973616((int)&savedregs, (int)&dword_9791A0);
return sub_973481((unsigned int)&savedregs ^ v105, v45, 1, 0, a1);
}
子进程
根据父进程的代码对缺失的机器码进行修改后
看加密部分
v28 = 0x1234;
v20 = 0;
v21 = 0;
v22 = 0;
v23 = 0;
v24 = 0;
v25 = 0;
v26 = 0;
v27 = 0;
v18 = 0;
v19 = 0;
v17 = len(a1);
sub_97460B(v7, xmm0_4_0, a2, (int)&v20);
for ( i = 0; ; ++i )
{
v9 = v17;
if ( i >= v17 )
break;
if ( i )
a1[i] ^= *(_BYTE *)(a3 + 4 * i - 4);
else
*a1 ^= v28;
v13 = 1;
sub_971EFB((int)&v18, 0, 8);
__debugbreak();
for ( j = 0; j < 8; ++j )
{
if ( v13 & (char)a1[i] )
{
*((_BYTE *)&v18 + j) = 1;
}
else
{
if ( (unsigned int)j >= 8 )
sub_9726CB(ebx0, edi0, a4);
*((_BYTE *)&v18 + j) = 0;
}
v13 *= 2;
}
for ( k = 0; k < 8; ++k )
*(_DWORD *)(a3 + 4 * i) += *(&v20 + 7 - k) * *((unsigned __int8 *)&v18 + k);
v8 = i + 1;
}
其中sub_97460B经过填充后
背包加密,sub_97460B是公钥的生成函数,给了私钥,iv
看check部分
可找到密文
#for i in range(1,10000): #这里计算的是inv
#if 41*i%491==1:
#print(i)
# break
iv=0x1234
inv=12
c=[0x3d1,0x2f0,0x52,0x475,0x1d2,0x2f0,0x224,0x51c,0x4e6,0x29f,0x2ee,0x39b,0x3f9,0x32b,0x2f2,0x5b5,0x24c,0x45a,0x34c,0x56d,0xa,0x4e6,0x476,0x2d9]
key=[2,3,7,14,30,57,120,251]
flag=[]
for i in range(24):
t=c[i]*inv%491
p=""
for i in range(8):
if key[7-i]>t:
p+="0"
else:
p+="1"
t-=key[7-i]
flag.append(int(p[::-1],2))
print(chr((flag[0]^0x1234)&0xff),end="")
for i in range(1,len(flag)):
print(chr((flag[i]^c[i-1])&0xff),end="")