[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="")
原文地址:https://www.cnblogs.com/harmonica11/p/13525663.html