1. 程式人生 > 實用技巧 >[SWPU2019]EasiestRe

[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="")