[羊城杯 2021]BabySmc

运行就是输入flag

不知道怎么跳过去的

这个应该就是smc加密的函数了

运行完这个函数才能继续往下

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbx
  __int64 v4; // r12
  __int64 v5; // r13
  unsigned __int64 v6; // rax
  char v7; // sp
  char v8; // cl
  __int64 v9; // rcx
  __int64 v11; // rax
  __int64 v12; // rcx
  unsigned __int128 v13; // rax
  char v14; // r9
  char v15; // r10
  char v16; // r8
  const char *v17; // rsi
  char *v18; // rdi
  bool v19; // cf
  unsigned __int8 v20; // dl
  int v21; // eax
  const char *v22; // rcx
  __int64 v23; // rcx
  unsigned __int64 v24; // rcx
  __int128 v26[2]; // [rsp+0h] [rbp-1C8h] BYREF
  _QWORD v27[2]; // [rsp+20h] [rbp-1A8h]
  __int128 v28; // [rsp+30h] [rbp-198h]
  char v29; // [rsp+40h] [rbp-188h] BYREF
  char v30; // [rsp+41h] [rbp-187h]
  char v31[254]; // [rsp+42h] [rbp-186h] BYREF
  __int128 v32[4]; // [rsp+140h] [rbp-88h]
  __m128i v33; // [rsp+180h] [rbp-48h] BYREF
  __int64 v34; // [rsp+1B0h] [rbp-18h]

  sub_7FF6D1BE1EB0(0i64, 0i64, envp);
  memset(&v33, 0, 48);
  sub_7FF6D1BE1D40("Input Your Flag : ");
  sub_7FF6D1BE1DC0("%46s", v33.m128i_i8);
  lpAddress = &loc_7FF6D1BE1085;
  qword_7FF6D1C0AD88 = (__int64)&loc_7FF6D1BE1D00;
  smcdecode();
  v6 = 256i64;
  do
  {
    *(__int128 *)((char *)&v28 + v6) = 0i64;
    *(_OWORD *)&v27[v6 / 8] = 0i64;
    v26[v6 / 0x10 + 1] = 0i64;
    v26[v6 / 0x10] = 0i64;
    v6 -= 64i64;
  }
  while ( v6 );
  v32[0] = xmmword_7FF6D1BFE340;
  v32[1] = xmmword_7FF6D1BFE350;
  v32[2] = xmmword_7FF6D1BFE360;
  v32[3] = xmmword_7FF6D1BFE370;
  v8 = v7 + 0x80;
  v9 = v8 & 0xF;
  if ( !_BitScanForward((unsigned int *)&v11, (unsigned int)_mm_movemask_epi8(_mm_cmpeq_epi8((__m128i)0i64, v33)) >> v9) )
    v11 = sub_7FF6D1BE2340(v9, &v33.m128i_i8[v9]);
  v12 = v11;
  v13 = 0xAAAAAAAAAAAAAAABui64 * (unsigned __int128)(unsigned __int64)v11;
  if ( *((_QWORD *)&v13 + 1) >> 1 )
  {
    if ( *((_QWORD *)&v13 + 1) >> 5 )
    {
      *(_QWORD *)&v28 = v3;
      v27[1] = v4;
      v27[0] = v5;
      v29 = *((_BYTE *)v32 + (v33.m128i_i8[0] >> 2)) ^ 0xA6;
      v30 = *((_BYTE *)v32 + ((v33.m128i_i8[1] >> 4) | (16 * (v33.m128i_i8[0] & 3)))) ^ 0xA3;
      v31[0] = *((_BYTE *)v32 + ((v33.m128i_i8[2] >> 6) | (4 * (v33.m128i_i8[1] & 0xF)))) ^ 0xA9;
      v31[1] = *((_BYTE *)v32 + (v33.m128i_i8[2] & 0x3F)) ^ 0xAC;
      v31[2] = *((_BYTE *)v32 + (v33.m128i_i8[3] >> 2)) ^ 0xA6;
      v31[3] = *((_BYTE *)v32 + ((v33.m128i_i8[4] >> 4) | (16 * (v33.m128i_i8[3] & 3)))) ^ 0xA3;
      v31[4] = *((_BYTE *)v32 + ((v33.m128i_i8[5] >> 6) | (4 * (v33.m128i_i8[4] & 0xF)))) ^ 0xA9;
      v31[5] = *((_BYTE *)v32 + (v33.m128i_i8[5] & 0x3F)) ^ 0xAC;
      v31[6] = *((_BYTE *)v32 + (v33.m128i_i8[6] >> 2)) ^ 0xA6;
      v31[7] = *((_BYTE *)v32 + ((v33.m128i_i8[7] >> 4) | (16 * (v33.m128i_i8[6] & 3)))) ^ 0xA3;
      v31[8] = *((_BYTE *)v32 + ((v33.m128i_i8[8] >> 6) | (4 * (v33.m128i_i8[7] & 0xF)))) ^ 0xA9;
      v31[9] = *((_BYTE *)v32 + (v33.m128i_i8[8] & 0x3F)) ^ 0xAC;
      v31[10] = *((_BYTE *)v32 + (v33.m128i_i8[9] >> 2)) ^ 0xA6;
      v31[11] = *((_BYTE *)v32 + ((v33.m128i_i8[10] >> 4) | (16 * (v33.m128i_i8[9] & 3)))) ^ 0xA3;
      v31[12] = *((_BYTE *)v32 + ((v33.m128i_i8[11] >> 6) | (4 * (v33.m128i_i8[10] & 0xF)))) ^ 0xA9;
      v31[13] = *((_BYTE *)v32 + (v33.m128i_i8[11] & 0x3F)) ^ 0xAC;
      v31[14] = *((_BYTE *)v32 + (v33.m128i_i8[12] >> 2)) ^ 0xA6;
      v31[15] = *((_BYTE *)v32 + ((v33.m128i_i8[13] >> 4) | (16 * (v33.m128i_i8[12] & 3)))) ^ 0xA3;
      JUMPOUT(0x7FF6D1BE143Di64);
    }
    JUMPOUT(0x7FF6D1BE1B22i64);
  }
  if ( v12 == 1 )
  {
    strcpy(v31, "14");
    v14 = *((_BYTE *)v32 + (unsigned __int8)(16 * (v33.m128i_i8[0] & 3))) ^ 0xA3;
    v29 = *((_BYTE *)v32 + (v33.m128i_i8[0] >> 2)) ^ 0xA6;
    v30 = v14;
  }
  else if ( v12 == 2 )
  {
    v15 = *((_BYTE *)v32 + 4 * (v33.m128i_i8[1] & 0xFu)) ^ 0xA9;
    v16 = *((_BYTE *)v32 + ((v33.m128i_i8[1] >> 4) | (16 * (v33.m128i_i8[0] & 3)))) ^ 0xA3;
    v29 = *((_BYTE *)v32 + (v33.m128i_i8[0] >> 2)) ^ 0xA6;
    v30 = v16;
    v31[0] = v15;
    strcpy(&v31[1], "4");
  }
  else
  {
    v29 = 0;
  }
  v17 = "H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<4";
  v18 = &v29;
  while ( 1 )
  {
    v19 = (unsigned __int8)*v18 < (unsigned int)*v17;
    if ( *v18 != *v17 )
      break;
    if ( !*v18 )
      goto LABEL_20;
    v20 = v18[1];
    v19 = v20 < (unsigned int)v17[1];
    if ( v20 != v17[1] )
      break;
    v18 += 2;
    v17 += 2;
    if ( !v20 )
    {
LABEL_20:
      v21 = 0;
      goto LABEL_22;
    }
  }
  v21 = v19 ? -1 : 1;
LABEL_22:
  v22 = "No.\r\n";
  if ( !v21 )
    v22 = "Yes.\r\n";
  sub_7FF6D1BE1D40(v22);
  sub_7FF6D1BE6B38("pause");
  v23 = v34;
  v34 = 0i64;
  v24 = (unsigned __int64)v26 ^ v23;
  if ( v24 == _security_cookie )
    return 0;
  else
    return sub_7FF6D1BE1D40(v24);
}

还是有两处问题,继续调试

走完了,那俩处还是有问题

所以应该是需要手动修复

SMC相关知识:

VirtualProtect()
在 Windows 程序中使用了VirtualProtect()函数来改变虚拟内存区域的属性。
#include <Memoryapi.h>
BOOL VirtualProtect(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
VirtualProtect()函数有4个参数,
lpAddress是要改变属性的内存起始地址,
dwSize是要改变属性的内存区域大小,
flAllocationType是内存新的属性类型,
lpflOldProtect内存原始属性类型保存地址。而flAllocationType部分值如下表。在 SMC 中常用的是 0x40。

mprotect()
在 Linux 程序中使用mprotect()函数来改变虚拟内存区域的属性。
#include <sys/mman.h>
int mprotect(void *addr, size_t len, int prot);
mprotect()系统调用修改起始位置为addr,长度为length字节的虚拟内存区域中分页上的保护。
addr取值必须为分页大小的整数倍,
length会被向上舍入到系统分页大小的下一个整数倍。
prot参数是一个位掩码。
 

刚刚动调是没有问题的,只是那俩处要 force 成代码

不能让IDA自己根据RIP生成代码,不然整个main函数结构就被拆分了,然后从选取从main函数头到第一个retn的代码段,因为IDA这时已经识别不了main函数块的结束部分了,然后选中Force强迫分析,并且不重新定义已存在的代码段,因为其它不用自修改的代码段都是正确的,所以不用全  undefined 再重定义

应该也可以静态修复

 *v0 = __ROR1__(*v0, 3) ^ 0x5A;

python循环左右移动

def ROR(i,index):	#循环右移
    tmp = bin(i)[2:].rjust(8,"0") #去掉0b,用rjust()在左侧补0,确保其8位
    for _ in range(index):
        tmp = tmp[-1] + tmp[:-1] #每次将字符串 tmp 的最后一位移到最前面,其余部分依次后移
    return int(tmp, 2) #经过右移操作的二进制字符串转换为整数
    
def ROL(i,index):	#循环左移
    tmp = bin(i)[2:].rjust(8, "0")
    for _ in range(index):
        tmp = tmp[1:] + tmp[0] #每次将字符串 tmp 的第一位移到最后,其余部分依次前移
    return int(tmp, 2)

写个内嵌脚本

def ROR(i,index):
    tmp = bin(i)[2:].rjust(8,"0")
    for _ in range(index):
        tmp = tmp[-1] + tmp[:-1]
    return int(tmp, 2)
    
addr1=0x140001085
addr2=0x140001d00
for i in range(addr2-addr1):
    patch_byte(addr1+i,ROR(get_wide_byte(addr1+i),3)^90)
print('successful')

 然后也是从开头到 retn force分析,都得到:

int __cdecl main(int argc, const char **argv, const char **envp)
{
 
  sub_7FF6D1BE1EB0(0i64, 0i64, envp);
  v96 = 0i64;
  v97 = 0i64;
  v98 = 0i64;
  sub_7FF6D1BE1D40("Input Your Flag : ");
  sub_7FF6D1BE1DC0((int)"%46s", &v96);
  lpAddress = &loc_7FF6D1BE1085;
  qword_7FF6D1C0AD88 = (__int64)&loc_7FF6D1BE1D00;
  smcdecode();
  v3 = 16i64;
  do
  {
    v93[v3 + 3] = 0i64;
    v93[v3 + 2] = 0i64;
    v93[v3 + 1] = 0i64;
    v93[v3] = 0i64;
    v3 -= 4i64;
  }
  while ( v3 * 16 );
  v95[0] = xmmword_7FF6D1BFE340;
  v95[1] = xmmword_7FF6D1BFE350;
  v95[2] = xmmword_7FF6D1BFE360;
  v95[3] = xmmword_7FF6D1BFE370;
  v5 = v4 + 0x80;
  v6 = v5 & 0xF;
  if ( !_BitScanForward((unsigned int *)&v8, (unsigned int)_mm_movemask_epi8(_mm_cmpeq_epi8((__m128i)0i64, v96)) >> v6) )
    v8 = sub_7FF6D1BE2340(v6, &v96.m128i_i8[v6]);
  v9 = v8;
  v10 = 0xAAAAAAAAAAAAAAABui64 * (unsigned __int128)(unsigned __int64)v8;
  v11 = *((_QWORD *)&v10 + 1) >> 1;
  if ( *((_QWORD *)&v10 + 1) >> 1 )
  {
    LODWORD(v12) = 0;
    LODWORD(v10) = 1;
    v14 = 0;
    v15 = 0;
    v16 = *((_QWORD *)&v10 + 1) >> 5;
    if ( *((_QWORD *)&v10 + 1) >> 5 )
    {
      do
      {
        v17 = v14;
        v18 = v15;
        v19 = v96.m128i_i8[v14 + 1];
        v20 = 16 * (v96.m128i_i8[v14] & 3);
        v21 = v96.m128i_i8[v14 + 2];
        v94[v15] = *((_BYTE *)v95 + (v96.m128i_i8[v14] >> 2)) ^ 0xA6;
        v94[v15 + 1] = *((_BYTE *)v95 + ((v19 >> 4) | v20)) ^ 0xA3;
        v94[v15 + 2] = *((_BYTE *)v95 + ((v21 >> 6) | (4 * (v19 & 0xF)))) ^ 0xA9;
        v22 = v96.m128i_i8[v14 + 3] & 3;
        v23 = v96.m128i_i8[v14 + 3] >> 2;
        v94[v15 + 3] = *((_BYTE *)v95 + (v21 & 0x3F)) ^ 0xAC;
        v24 = v96.m128i_i8[v14 + 4];
        v94[v15 + 4] = *((_BYTE *)v95 + v23) ^ 0xA6;
        LODWORD(v23) = v24;
        v25 = v96.m128i_i8[v14 + 5] & 0x3F;
        v26 = (v96.m128i_i8[v14 + 5] >> 6) | (4 * (v24 & 0xF));
        v94[v15 + 5] = *((_BYTE *)v95 + (((int)v23 >> 4) | (16 * v22))) ^ 0xA3;
        LODWORD(v23) = v96.m128i_i8[v14 + 6];
        v94[v15 + 6] = *((_BYTE *)v95 + v26) ^ 0xA9;
        v94[v15 + 7] = *((_BYTE *)v95 + v25) ^ 0xAC;
        LODWORD(v26) = v96.m128i_i8[v14 + 7];
        v94[v15 + 8] = *((_BYTE *)v95 + ((int)v23 >> 2)) ^ 0xA6;
        v27 = v26;
        v28 = v96.m128i_i8[v14 + 8] & 0x3F;
        v29 = (int)((v96.m128i_i8[v14 + 8] >> 6) | (4 * (v26 & 0xF)));
        v94[v15 + 9] = *((_BYTE *)v95 + (int)((v27 >> 4) | (16 * (v23 & 3)))) ^ 0xA3;
        v94[v15 + 10] = *((_BYTE *)v95 + v29) ^ 0xA9;
        v30 = v96.m128i_i8[v14 + 9] & 3;
        v31 = v96.m128i_i8[v14 + 9] >> 2;
        v94[v15 + 11] = *((_BYTE *)v95 + v28) ^ 0xAC;
        LODWORD(v29) = v96.m128i_i8[v14 + 10];
        v94[v15 + 12] = *((_BYTE *)v95 + v31) ^ 0xA6;
        LODWORD(v31) = v29;
        v32 = v96.m128i_i8[v14 + 11] & 0x3F;
        v33 = (int)((v96.m128i_i8[v14 + 11] >> 6) | (4 * (v29 & 0xF)));
        v94[v15 + 13] = *((_BYTE *)v95 + (((int)v31 >> 4) | (16 * v30))) ^ 0xA3;
        LODWORD(v31) = v96.m128i_i8[v14 + 12];
        v94[v15 + 14] = *((_BYTE *)v95 + v33) ^ 0xA9;
        v94[v15 + 15] = *((_BYTE *)v95 + v32) ^ 0xAC;
        LODWORD(v33) = v96.m128i_i8[v14 + 13];
        v94[v15 + 16] = *((_BYTE *)v95 + ((int)v31 >> 2)) ^ 0xA6;
        v34 = v33;
        v35 = v96.m128i_i8[v14 + 14] & 0x3F;
        v36 = (int)((v96.m128i_i8[v14 + 14] >> 6) | (4 * (v33 & 0xF)));
        v94[v15 + 17] = *((_BYTE *)v95 + (int)((v34 >> 4) | (16 * (v31 & 3)))) ^ 0xA3;
        v94[v15 + 18] = *((_BYTE *)v95 + v36) ^ 0xA9;
        v37 = v96.m128i_i8[v14 + 15] & 3;
        v38 = v96.m128i_i8[v14 + 15] >> 2;
        v94[v15 + 19] = *((_BYTE *)v95 + v35) ^ 0xAC;
        LODWORD(v36) = *((char *)&v97 + v14);
        v94[v15 + 20] = *((_BYTE *)v95 + v38) ^ 0xA6;
        LODWORD(v38) = v36;
        v39 = *((_BYTE *)&v97 + v14 + 1) & 0x3F;
        v40 = (int)((*((char *)&v97 + v14 + 1) >> 6) | (4 * (v36 & 0xF)));
        v94[v15 + 21] = *((_BYTE *)v95 + (((int)v38 >> 4) | (16 * v37))) ^ 0xA3;
        LODWORD(v38) = *((char *)&v97 + v14 + 2);
        v94[v15 + 22] = *((_BYTE *)v95 + v40) ^ 0xA9;
        v94[v15 + 23] = *((_BYTE *)v95 + v39) ^ 0xAC;
        LODWORD(v40) = *((char *)&v97 + v14 + 3);
        v94[v15 + 24] = *((_BYTE *)v95 + ((int)v38 >> 2)) ^ 0xA6;
        v41 = v40;
        v42 = *((_BYTE *)&v97 + v14 + 4) & 0x3F;
        v43 = (int)((*((char *)&v97 + v14 + 4) >> 6) | (4 * (v40 & 0xF)));
        v94[v15 + 25] = *((_BYTE *)v95 + (int)((v41 >> 4) | (16 * (v38 & 3)))) ^ 0xA3;
        v94[v15 + 26] = *((_BYTE *)v95 + v43) ^ 0xA9;
        v44 = *((_BYTE *)&v97 + v14 + 5) & 3;
        v45 = *((char *)&v97 + v14 + 5) >> 2;
        v94[v15 + 27] = *((_BYTE *)v95 + v42) ^ 0xAC;
        LODWORD(v43) = *((char *)&v97 + v14 + 6);
        v94[v15 + 28] = *((_BYTE *)v95 + v45) ^ 0xA6;
        LODWORD(v45) = v43;
        v46 = *((_BYTE *)&v97 + v14 + 7) & 0x3F;
        v47 = (int)((*((char *)&v97 + v14 + 7) >> 6) | (4 * (v43 & 0xF)));
        v94[v15 + 29] = *((_BYTE *)v95 + (((int)v45 >> 4) | (16 * v44))) ^ 0xA3;
        LODWORD(v45) = *((char *)&v97 + v14 + 8);
        v94[v15 + 30] = *((_BYTE *)v95 + v47) ^ 0xA9;
        v94[v15 + 31] = *((_BYTE *)v95 + v46) ^ 0xAC;
        LODWORD(v47) = *((char *)&v97 + v14 + 9);
        v94[v15 + 32] = *((_BYTE *)v95 + ((int)v45 >> 2)) ^ 0xA6;
        v48 = v47;
        v49 = *((_BYTE *)&v97 + v14 + 10) & 0x3F;
        v50 = (int)((*((char *)&v97 + v14 + 10) >> 6) | (4 * (v47 & 0xF)));
        v94[v15 + 33] = *((_BYTE *)v95 + (int)((v48 >> 4) | (16 * (v45 & 3)))) ^ 0xA3;
        v94[v15 + 34] = *((_BYTE *)v95 + v50) ^ 0xA9;
        v51 = *((_BYTE *)&v97 + v14 + 11) & 3;
        v52 = *((char *)&v97 + v14 + 11) >> 2;
        v94[v15 + 35] = *((_BYTE *)v95 + v49) ^ 0xAC;
        LODWORD(v50) = *((char *)&v97 + v14 + 12);
        v94[v15 + 36] = *((_BYTE *)v95 + v52) ^ 0xA6;
        LODWORD(v52) = v50;
        v53 = *((_BYTE *)&v97 + v14 + 13) & 0x3F;
        v54 = (int)((*((char *)&v97 + v14 + 13) >> 6) | (4 * (v50 & 0xF)));
        v94[v15 + 37] = *((_BYTE *)v95 + (((int)v52 >> 4) | (16 * v51))) ^ 0xA3;
        LODWORD(v52) = *((char *)&v97 + v14 + 14);
        v94[v15 + 38] = *((_BYTE *)v95 + v54) ^ 0xA9;
        v94[v15 + 39] = *((_BYTE *)v95 + v53) ^ 0xAC;
        LODWORD(v54) = *((char *)&v97 + v14 + 15);
        v94[v15 + 40] = *((_BYTE *)v95 + ((int)v52 >> 2)) ^ 0xA6;
        v55 = v54;
        v56 = *((_BYTE *)&v98 + v14) & 0x3F;
        v57 = (int)((*((char *)&v98 + v14) >> 6) | (4 * (v54 & 0xF)));
        v94[v15 + 41] = *((_BYTE *)v95 + (int)((v55 >> 4) | (16 * (v52 & 3)))) ^ 0xA3;
        v94[v15 + 42] = *((_BYTE *)v95 + v57) ^ 0xA9;
        v58 = *((_BYTE *)&v98 + v14 + 1) & 3;
        v59 = *((char *)&v98 + v14 + 1) >> 2;
        v94[v15 + 43] = *((_BYTE *)v95 + v56) ^ 0xAC;
        LODWORD(v57) = *((char *)&v98 + v14 + 2);
        v94[v15 + 44] = *((_BYTE *)v95 + v59) ^ 0xA6;
        LODWORD(v59) = v57;
        v60 = *((_BYTE *)&v98 + v14 + 3) & 0x3F;
        v61 = (int)((*((char *)&v98 + v14 + 3) >> 6) | (4 * (v57 & 0xF)));
        v94[v15 + 45] = *((_BYTE *)v95 + (((int)v59 >> 4) | (16 * v58))) ^ 0xA3;
        LODWORD(v59) = *((char *)&v98 + v14 + 4);
        v94[v15 + 46] = *((_BYTE *)v95 + v61) ^ 0xA9;
        v94[v15 + 47] = *((_BYTE *)v95 + v60) ^ 0xAC;
        LODWORD(v61) = *((char *)&v98 + v14 + 5);
        v94[v15 + 48] = *((_BYTE *)v95 + ((int)v59 >> 2)) ^ 0xA6;
        v62 = v61;
        v63 = *((_BYTE *)&v98 + v14 + 6) & 0x3F;
        v64 = (int)((*((char *)&v98 + v14 + 6) >> 6) | (4 * (v61 & 0xF)));
        v94[v15 + 49] = *((_BYTE *)v95 + (int)((v62 >> 4) | (16 * (v59 & 3)))) ^ 0xA3;
        v94[v15 + 50] = *((_BYTE *)v95 + v64) ^ 0xA9;
        v65 = *((_BYTE *)&v98 + v14 + 7) & 3;
        v66 = *((char *)&v98 + v14 + 7) >> 2;
        v94[v15 + 51] = *((_BYTE *)v95 + v63) ^ 0xAC;
        LODWORD(v64) = *((char *)&v98 + v14 + 8);
        v94[v15 + 52] = *((_BYTE *)v95 + v66) ^ 0xA6;
        LODWORD(v63) = *((char *)&v98 + v14 + 9);
        v94[v15 + 53] = *((_BYTE *)v95 + (((int)v64 >> 4) | (16 * v65))) ^ 0xA3;
        v67 = v63;
        v12 = (unsigned int)(v12 + 1);
        v14 += 48;
        v15 += 64;
        LOBYTE(v66) = *((_BYTE *)v95 + (v63 & 0x3F));
        LODWORD(v63) = *((char *)&v98 + v17 + 10);
        v94[v18 + 55] = v66 ^ 0xAC;
        LODWORD(v66) = *((char *)&v98 + v17 + 11);
        v94[v18 + 54] = *((_BYTE *)v95 + (int)((v67 >> 6) | (4 * (v64 & 0xF)))) ^ 0xA9;
        v94[v18 + 56] = *((_BYTE *)v95 + ((int)v63 >> 2)) ^ 0xA6;
        LODWORD(v64) = (int)v66 >> 4;
        v68 = *((_BYTE *)&v98 + v17 + 12) & 0x3F;
        v69 = (int)((*((char *)&v98 + v17 + 12) >> 6) | (4 * (v66 & 0xF)));
        v94[v18 + 57] = *((_BYTE *)v95 + (int)(v64 | (16 * (v63 & 3)))) ^ 0xA3;
        LOBYTE(v63) = *((_BYTE *)v95 + v69);
        v70 = *((char *)&v98 + v17 + 13) >> 2;
        LODWORD(v64) = *((_BYTE *)&v98 + v17 + 13) & 3;
        v94[v18 + 58] = v63 ^ 0xA9;
        v94[v18 + 59] = *((_BYTE *)v95 + v68) ^ 0xAC;
        LOBYTE(v68) = *((_BYTE *)v95 + v70);
        LODWORD(v70) = *((char *)&v98 + v17 + 14);
        LODWORD(v63) = v70 & 0xF;
        LODWORD(v64) = ((int)v70 >> 4) | (16 * v64);
        LODWORD(v70) = *((char *)&v98 + v17 + 15);
        v94[v18 + 60] = v68 ^ 0xA6;
        LOBYTE(v68) = *((_BYTE *)v95 + (int)v64) ^ 0xA3;
        LOBYTE(v64) = *((_BYTE *)v95 + (((int)v70 >> 6) | (4 * (int)v63))) ^ 0xA9;
        LOBYTE(v63) = *((_BYTE *)v95 + (v70 & 0x3F)) ^ 0xAC;
        v94[v18 + 61] = v68;
        v94[v18 + 62] = v64;
        v94[v18 + 63] = v63;
      }
      while ( v12 < v16 );
      v13 = 16 * v12 + 1;
    }
    v71 = (unsigned int)(v13 - 1);
    for ( i = 3 * (int)v71; v71 < v11; v94[v73 + 3] = v74 )
    {
      v73 = 4 * (int)v71;
      v71 = (unsigned int)(v71 + 1);
      v74 = v96.m128i_i8[i + 1];
      v75 = 16 * (v96.m128i_i8[i] & 3);
      v94[v73] = *((_BYTE *)v95 + (v96.m128i_i8[i] >> 2)) ^ 0xA6;
      v76 = v96.m128i_i8[i + 2];
      i += 3i64;
      v94[v73 + 1] = *((_BYTE *)v95 + ((v74 >> 4) | v75)) ^ 0xA3;
      LOBYTE(v75) = *((_BYTE *)v95 + ((v76 >> 6) | (4 * (v74 & 0xF)))) ^ 0xA9;
      LOBYTE(v74) = *((_BYTE *)v95 + (v76 & 0x3F)) ^ 0xAC;
      v94[v73 + 2] = v75;
    }
  }
  v77 = v9 - 3 * v11;
  if ( v77 == 1 )
  {
    v78 = v96.m128i_i8[3 * v11];
    v94[4 * v11 + 2] = 49;
    v94[4 * v11 + 3] = 52;
    v79 = *((_BYTE *)v95 + (unsigned __int8)(16 * (v78 & 3))) ^ 0xA3;
    v94[4 * v11] = *((_BYTE *)v95 + (v78 >> 2)) ^ 0xA6;
    v94[4 * v11 + 1] = v79;
    v94[4 * v11 + 4] = 0;
  }
  else if ( v77 == 2 )
  {
    v80 = v96.m128i_i8[3 * v11 + 1];
    v81 = v96.m128i_i8[3 * v11];
    v82 = *((_BYTE *)v95 + 4 * (v80 & 0xFu)) ^ 0xA9;
    v83 = *((_BYTE *)v95 + ((v80 >> 4) | (16 * (v81 & 3)))) ^ 0xA3;
    v94[4 * v11] = *((_BYTE *)v95 + (v81 >> 2)) ^ 0xA6;
    v94[4 * v11 + 1] = v83;
    v94[4 * v11 + 2] = v82;
    v94[4 * v11 + 3] = 52;
    v94[4 * v11 + 4] = 0;
  }
  else
  {
    v94[4 * v11] = 0;
  }
  v84 = "H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<4";
  v85 = v94;
  while ( 1 )
  {
    v86 = (unsigned __int8)*v85 < (unsigned int)*v84;
    if ( *v85 != *v84 )
      break;
    if ( !*v85 )
      goto LABEL_21;
    v87 = v85[1];
    v86 = v87 < (unsigned int)v84[1];
    if ( v87 != v84[1] )
      break;
    v85 += 2;
    v84 += 2;
    if ( !v87 )
    {
LABEL_21:
      v88 = 0;
      goto LABEL_23;
    }
  }
  v88 = v86 ? -1 : 1;
LABEL_23:
  v89 = "No.\r\n";
  if ( !v88 )
    v89 = "Yes.\r\n";
  sub_7FF6D1BE1D40(v89);
  sub_7FF6D1BE6B38("pause");
  v90 = v99;
  v99 = 0i64;
  v91 = (unsigned __int64)v93 ^ v90;
  if ( v91 == _security_cookie )
    return 0;
  else
    return sub_7FF6D1BE1D40(v91);
}

太长了,嗯要学会挑重点

然后倒着往上看:

确实看着好像base加密

但确实看上去就知道肯定是魔改的了

还要注意密文每四位对应了一个数异或,不是直接解密

key1="H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<"#4
list1=[]
list2=[0xA6,0XA3,0XA9,0XAC]
flag=""
for i in range(len(key1)):
	list1.append(ord(key1[i])^list2[i%4])
print(list1)
#[238, 157, 198, 253, 200, 149, 200, 221, 234, 209, 210, 232, 238, 149, 198, 200, 206, 199, 196, 156, 194, 238, 204, 204, 235, 225, 198, 147, 202, 241, 206, 192, 238, 215, 238, 252, 233, 199, 198, 206, 226, 207, 194, 194, 195, 201, 196, 235, 239, 223, 206, 196, 226, 193, 149]

base解一下,不对,发现有些数大了

嗯,再去看看是不是密码表变了

然后就可以进行base解密了

要注意:'='操作替换成'4',注意这里的'4'是后面加的,不在字符异或范围,所以要抽出来异或后再加进去

key1="H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<"#4
list1=[]
list2=[0xA6,0XA3,0XA9,0XAC]
flag=""
for i in range(len(key1)):
    list1.append(ord(key1[i])^list2[i%4])
print(list1)
for a in list1:
    flag+=chr(a)
flag+='4'

list2=[0xE4, 0xC4, 0xE7, 0xC7, 0xE6, 0xC6, 0xE1, 0xC1, 0xE0, 0xC0,
  0xE3, 0xC3, 0xE2, 0xC2, 0xED, 0xCD, 0xEC, 0xCC, 0xEF, 0xCF,
  0xEE, 0xCE, 0xE9, 0xC9, 0xE8, 0xC8, 0xEB, 0xCB, 0xEA, 0xCA,
  0xF5, 0xD5, 0xF4, 0xD4, 0xF7, 0xD7, 0xF6, 0xD6, 0xF1, 0xD1,
  0xF0, 0xD0, 0xF3, 0xD3, 0xF2, 0xD2, 0xFD, 0xDD, 0xFC, 0xDC,
  0xFF, 0xDF, 0x95, 0x9C, 0x9D, 0x92, 0x93, 0x90, 0x91, 0x96,
  0x97, 0x94, 0x8A, 0x8E]
letters=""
for i in list2:
    letters+=chr(i)
def decryption(inputString):
    # 对前面不是“=”的字节取索引,然后转换为2进制
    asciiList = ['{:0>6}'.format(str(bin(letters.index(i))).replace('0b', ''))
                      for i in inputString if i != '4']
    outputString = ''
    #补齐“=”的个数
    equalNumber = inputString.count('4')
    while asciiList:
        tempList = asciiList[:4]
        #转换成2进制字符串
        tempString = ''.join(tempList)
        # 对没有8位2进制的字符串补够8位2进制
        if len(tempString) % 8 != 0:
            tempString = tempString[0:-1*equalNumber*2]
        # 4个6字节的二进制  转换  为三个8字节的二进制
        tempStringList = [tempString[x:x+8] for x in [0, 8, 16]]
        # 二进制转为10进制
        tempStringList = [int(x, 2) for x in tempStringList if x]
        #连接成字符串
        outputString += ''.join([chr(x) for x in tempStringList])
        asciiList = asciiList[4:]
    #print(output_str)
    return outputString
print(decryption(flag))
#SangFor{XSAYT0u5DQhaxveIR50X1U13M-pZK5A0}

一样,还可以正向爆破

嗯,我自己对着写了一遍,大致了解这个思路,但我写的还是有点问题

最后补’4‘的操作还须多想一下

table=[0xE4, 0xC4, 0xE7, 0xC7, 0xE6, 0xC6, 0xE1, 0xC1, 0xE0, 0xC0, 
  0xE3, 0xC3, 0xE2, 0xC2, 0xED, 0xCD, 0xEC, 0xCC, 0xEF, 0xCF, 
  0xEE, 0xCE, 0xE9, 0xC9, 0xE8, 0xC8, 0xEB, 0xCB, 0xEA, 0xCA, 
  0xF5, 0xD5, 0xF4, 0xD4, 0xF7, 0xD7, 0xF6, 0xD6, 0xF1, 0xD1, 
  0xF0, 0xD0, 0xF3, 0xD3, 0xF2, 0xD2, 0xFD, 0xDD, 0xFC, 0xDC, 
  0xFF, 0xDF, 0x95, 0x9C, 0x9D, 0x92, 0x93, 0x90, 0x91, 0x96, 
  0x97, 0x94, 0x8A, 0x8E]
key1="H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<4"
str_len=int(len(key1)/4-1)	#最后一组4是补上去的,所以要特殊对待,这里str_len是13,/会得出小数,所以用int转换成整型。
flag=""
print(str_len)
for sub in range(str_len):		#最外层循环是截取要比较的4位字符,放在最外面就才可以以4个为一组来比较。
	for a in range(32,127):
		for b in range(32,127):		#完全的base64加密3*8变4*6的拆分
			for c in range(32,127):
				q=table[a >> 2] ^ 0xA6
				w=table[((a & 0x3) << 4) | (b >> 4) ] ^ 0xA3
				e=table[((b & 0xf) << 2) | (c >> 6) ] ^ 0xA9
				r=table[ c & 0x3f ] ^ 0xAC
				tempstr=chr(q)+chr(w)+chr(e)+chr(r)		
				if tempstr==key1[sub*4:(sub+1)*4]:
					flag+=chr(a)
					flag+=chr(b)
					flag+=chr(c)

for i in range(32,127):		#对待最后一组有补数的,因为只有一个补数,所以是2个明文的2*8对应3*6,剩下一个补位。
	for j in range(32,127):
		k=table[i >> 2] ^ 0xA6
		l=table[((i & 0x3) << 4) | (j >> 4)] ^ 0xA3
		m=table[(j & 0xf) <<2 ] ^ 0xA9			#从第三个开始的就不用写了,因为是0,不影响
		tempstr=chr(k)+chr(l)+chr(m)+'4'
		if tempstr=='Db<4':
			flag+=chr(i)
			flag+=chr(j)		
print(flag)	

说是还可以下标对应

import base64
key1="H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<"#4
list1=[]
list2=[0xA6,0XA3,0XA9,0XAC]
flag=""
for i in range(len(key1)):
	list1.append(ord(key1[i])^list2[i%4])
print(list1)

list2=[0xE4, 0xC4, 0xE7, 0xC7, 0xE6, 0xC6, 0xE1, 0xC1, 0xE0, 0xC0,
  0xE3, 0xC3, 0xE2, 0xC2, 0xED, 0xCD, 0xEC, 0xCC, 0xEF, 0xCF,
  0xEE, 0xCE, 0xE9, 0xC9, 0xE8, 0xC8, 0xEB, 0xCB, 0xEA, 0xCA,
  0xF5, 0xD5, 0xF4, 0xD4, 0xF7, 0xD7, 0xF6, 0xD6, 0xF1, 0xD1,
  0xF0, 0xD0, 0xF3, 0xD3, 0xF2, 0xD2, 0xFD, 0xDD, 0xFC, 0xDC,
  0xFF, 0xDF, 0x95, 0x9C, 0x9D, 0x92, 0x93, 0x90, 0x91, 0x96,
  0x97, 0x94, 0x8A, 0x8E]

table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
secret=""
for i in list1:
	k=list2.index(i)
	secret+=table[k]
secret+='='
flag=base64.b64decode(secret)
print(secret)
print(flag)
# U2FuZ0ZvcntYU0FZVDB1NURRaGF4dmVJUjUwWDFVMTNNLXBaSzVBMH0=
# b'SangFor{XSAYT0u5DQhaxveIR50X1U13M-pZK5A0}'
import base64
key1="H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<"#4
list1=[]
list2=[0xA6,0XA3,0XA9,0XAC]
origin=""
for i in range(len(key1)):
    list1.append(ord(key1[i])^list2[i%4])
#print(list1)
for a in list1:
    origin+=chr(a)
origin+='='
s='äÄçÇæÆáÁàÀãÃâÂíÍìÌïÏîÎéÉèÈëËêÊõÕôÔ÷×öÖñÑðÐóÓòÒýÝüÜÿß'#换表字符
str='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
biao=str.maketrans(s,str)
print(base64.b64decode(origin.translate(biao)))

感谢2021年9月广州羊城杯,REVERSE的RE-BabySmc_羊城杯babysmc-CSDN博客

大佬写的很好!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/665683.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

迅狐跨境电商系统源码:技术栈与多端集成

随着全球化贸易的不断深入&#xff0c;跨境电商系统源码成为了连接不同国家和地区消费者与商家的重要桥梁。本文将探讨跨境电商系统源码的技术栈以及如何通过多端集成来提升用户体验。 技术栈概览 跨境电商系统源码的技术栈是构建高效、稳定平台的基础。以下是构建跨境电商系…

一份不知道哪里来的第十五届国赛模拟题

这是一个不知道来源的模拟题目&#xff0c;没有完全完成&#xff0c;只作代码记录&#xff0c;不作分析和展示&#xff0c;极其冗长&#xff0c;但里面有长按短按双击的复合&#xff0c;可以看看。 目录 题目代码底层驱动主程序核心代码关键&#xff1a;双击单击长按复合代码 …

七年之痒!一个 PHP 程序员职业生涯的自述

大家好&#xff0c;我是码农先森。 今年刚好是我毕业的第七个年头&#xff0c;在婚姻感情当中都有一种「七年之痒」的说法&#xff0c;这次我把这个词「七年之痒」用一次在我的职业生涯复盘上。七年前我从告别校园&#xff0c;踏入互联网编程行业&#xff0c;七年后我依旧在编…

FreeRtos进阶——中断的内部逻辑

中断与非中断API的区别 BaseType_t xQueueSendToBack(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait); BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWok…

SpringBoot源码(自动装配、内嵌Tomcat)

文章目录 依赖管理pom依赖管理Web依赖自定义starter 一、WebMvcAutoConfiguration1.1 Filter1.2 Interceptor 二、源码解析2.1 SpringApplication2.1.1 构造方法1、填充webApplicationType2、自动装配Initializers3、自动装配Listeners 2.1.2 run(args) 2.2 SpringApplicationR…

实用软件分享---超级轻量级的强力卸载软件工具UninstallView_1.51

专栏介绍:本专栏主要分享一些实用的软件(Po Jie版); 声明1:软件不保证时效性;只能保证在写本文时,该软件是可用的;不保证后续时间该软件能一直正常运行;不保证没有bug;如果软件不可用了,我知道后会第一时间在题目上注明(已失效)。介意者请勿订阅。 声明2:本专栏的…

【OrangePi AIpro】从开箱到第一个AI应用开发

第一章 OrangePi AIpro介绍和开发环境搭建 1.1 OrangePi AIpro介绍 OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB/64GB/…

CANOE制造dll文件,以及应用dll文件

1、使用canoe自带的capl dll 2、然后使用Visual Studio 2022 打开项目 3、项目打开后修改下项目属性 4、修改capldll.cpp文件 4.1 添加的内容 void CAPLEXPORT far CAPLPASCAL appSum(long i, long j, long* s){*s i j;} {"sum", (CAPL_FARCALL)appSum, "…

FinalShell无法连接Linux

Linux使用Vmware会创建一个网络&#xff0c;让两个子网处于一个网关&#xff0c;这样就能在windows中连接Linux&#xff0c;只有在这种情况下才能FinalShell才能连接Linux

Redis 和 Mysql 如何保证两者数据一致性

文章目录 概述解决方案消息队列异步重试 基于 RocketMQ 的可靠性消息通信&#xff0c;来实现最终一致Canal 组件&#xff0c;监控 Mysql 中 binlog 的日志&#xff0c;把更新后的数据同步到 Redis 里面延时双删弱一致性和强一致性Canal详解 概述 在分布式系统中&#xff0c;保…

2024中国军民两用智能装备与通信技术产业展览会带你走进轻元素量子材料世界

在科技创新的浪潮中&#xff0c;北京怀柔科学城迎来了一场革命性的突破——世界首个轻元素量子材料平台正式启动运行。这一里程碑事件不仅彰显了中国在量子科学研究上的领先地位&#xff0c;也为全球科技界带来了一股新风潮。由北京大学领衔打造的这一平台&#xff0c;专注于轻…

[论文笔记]MemGPT: Towards LLMs as Operating Systems

引言 今天介绍一篇论文MemGPT: Towards LLMs as Operating Systems。翻过过来就是把LLM看成操作系统。 大语言模型已经在人工智能领域引起了革命性的变革&#xff0c;但受到有限上下文窗口的限制&#xff0c;在扩展对话和文档分析等任务中的效用受到了阻碍。为了能够利用超出…

免费生物蛋白质的类chatgpt工具助手copilot:小分子、蛋白的折叠、对接

参考: https://310.ai/copilot 可以通过自然语言通话晚上蛋白质的相关处理:生成序列、折叠等 应该是agent技术调用不同工具实现 从UniProt数据库中搜索和加载蛋白质。使用ESM Fold方法折叠蛋白质。使用310.ai基础模型设计新蛋白质。使用TM-Align方法比较蛋白质。利用Protei…

谁是镰刀谁是韭菜?程序交易与手动交易的博弈,靠技术还是靠运气

备受争议的话题&#xff0c;很多人认为程序化交易是在破坏市场的平衡&#xff0c;大量的程序交易订单可能会造成市场价格的异常波动&#xff0c;尤其是在高频交易未被监管时&#xff0c;程序化交易者占尽优势&#xff0c;来回收割。 而支持程序交易的人认为&#xff0c;市场是…

Java八股文:程序员的“面试经”还是技术壁垒?

Java八股文&#xff1a;程序员的“面试经”还是技术壁垒&#xff1f; “八股文”&#xff0c;在中国古代科举考试中&#xff0c;指的是一种程式化的文章写作格式&#xff0c;内容空洞&#xff0c;缺乏创新。而如今&#xff0c;这个词语被赋予了新的含义&#xff0c;用来形容技术…

python基础(习题、资料)

免费提取资料&#xff1a; 练习、资料免费提取。持续更新迅雷云盘https://pan.xunlei.com/s/VNz6kH1EXQtK8j-wwwz_c0k8A1?pwdrj2x# 本文为Python的进阶知识合辑&#xff0c;包括列表&#xff08;List&#xff09;、元组&#xff08;Tuple&#xff09;、字典&#xff08;Dic…

微信密码忘记了怎么找回?自助找回2个方法揭晓!

在微信的世界里&#xff0c;密码就像是我们通往个人世界的“钥匙”&#xff0c;一旦丢失&#xff0c;就仿佛被锁在了自己的门外。微信密码忘记了怎么找回&#xff1f;别担心&#xff0c;微信提供了多种自助找回密码的方法&#xff0c;让我们一起来揭秘这些找回密码的秘诀吧&…

在全志H616核桃派开发板上配置SSH远程终端方法详解

熟悉指令用户可以对已经联网的核桃派进行局域网SSH远程终端控制&#xff0c;方便使用自己的PC对核桃派远程进行各种指令操作。 普通用户&#xff08;默认&#xff09; 账号&#xff1a;pi ; 密码&#xff1a;pi管理员账户 账号&#xff1a;root ; 密码&#xff1a;root 在这之…

【MySQL访问】

文章目录 一、C远程连接到MySQLmysql_init()函数mysql_real_connect&#xff08;&#xff09;函数实战案例 二、处理查询select的细节mysql_store_result()函数获取结果行和列获取select结果获取行内容获取列属性 三、MySQL图形化界面连接 关于动态链接&#xff0c;请看这篇文章…

【C语言】基于C语言实现的贪吃蛇游戏

【C语言】基于C语言实现的贪吃蛇游戏 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C语言学习之路 文章目录 【C语言】基于C语言实现的贪吃蛇游戏前言一.最终实现效果一.Win32 API介绍1.1Win32 API1.2控制台程序1.3控制台屏幕上的坐标COORD…