2021NCTF-RE

NCTF-RE

签到

送IDA又送flag

欢迎来到NCTF-逆向工程(Reverse Engineering)
这里可能有你需要的工具:
ida pro 7.6 :

链接:https://pan.baidu.com/s/1bV2HjBBX0bwwtzORqhErOg

提取码:o49x

Shadowbringer

c++64位程序,ida载入

std::string::string(v4, "U>F2UsQXN`5sXMELT=:7M_2<X]^1ThaWF0=KM?9IUhAsTM5:T==_Ns&<Vhb!", &v6);
  std::allocator<char>::~allocator(&v6);
  std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Welcome.Please input your flag:\n");
  std::operator>><char>(refptr__ZSt3cin, (std::string *)input);
  std::string::string((std::string *)v8, (const std::string *)input);// strcpy
  base64encode1((std::string *)v7, (std::string *)v8);// 换表的base64
  std::string::operator=((std::string *)input, (const std::string *)v7);// 赋值 第一层密文
  std::string::~string((std::string *)v7);
  std::string::~string((std::string *)v8);
  std::string::string((std::string *)v10, (const std::string *)input);// 复制一个对象v10
  base64encode2((std::string *)v9, (std::string *)v10); // base64换表 两次 不同的表
  std::string::operator=((std::string *)input, (const std::string *)v9);
  std::string::~string((std::string *)v9);
  std::string::~string((std::string *)v10);
  if ( (unsigned __int8)std::operator==<char>(input, v4) )
    std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Right.");
  else
    std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Wrong.");
  std::string::~string((std::string *)v4);

主要用到了c++ string类来进行处理,结合动调,大致经过了两次base64变表加密,在和v4进行比较。
第一组表,
’#$%&’,27h,’()*+,-.s0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[h]’+’^_`ab’

第二组表
’ba`_^]h[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210s.-,+*)(’,27h,’&’’+’%$#'

两次加密的代码大致相同,主要通过表的长度和每次处理的二进制长度判断为base64.

std::bitset<8ull>::to_string(v13, v14);     // 转为2进制
for ( j = 0; j < (unsigned __int64)std::string::size((std::string *)&v9); j += 6 )// 6个二进制一组
v7 = (char *)std::string::operator[](&hisoralce, v6);//表索引

while ( (std::string::size(a1) & 3) != 0 )
  {
    std::operator+<char>(v19, a1, '!');
    std::string::operator=(a1, (const std::string *)v19);
    std::string::~string((std::string *)v19);
  }
//不为4的倍数就不断+!

了解流程后写解密脚本即可

import base64
table1='#$%&'+'\x27'+'()*+,-.s0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[h]'+'^_`ab'
table2='ba`_^]h[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210s.-,+*)('+'\x27'+'&%$#'
base='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
enc='U>F2UsQXN`5sXMELT=:7M_2<X]^1ThaWF0=KM?9IUhAsTM5:T==_Ns&<Vhb!'
#enc='FsJ7M?b<U->2M>U:'#123456789测试
def newbase(enc,table):
    m=''
    for i in range(len(enc)):
        if enc[i] in table:
            m+=base[table.index(enc[i])]
        else:
            m+='='
    print(base64.b64decode(m))
    return base64.b64decode(m)
c1=newbase(enc,table2).decode()
newbase(c1,table1)
#NCTF{H0m3_r1d1n9_h0m3_dy1n9_h0p3}

鲨鲨的秘密

32位程序,ida载入

 IpAdress = malloc(0x20u);
  VirtualProtect(IpAdress, 0x20u, 0x40u, &flOldProtect);
  dword_404E48 = (int)IpAdress;
  *(_BYTE *)IpAdress = 0xC3;                    // ret的机器码
  ((void (*)(void))IpAdress)

刚载入就有种莫名其妙的熟悉感,和西湖论剑的一道逆向题思路差不多,又是体力活。
是一种修改代码的操作数并单语句执行的SMC,通过一个数组来确定赋值代码长度的大小,和选定相应的操作数和修改的位置。

挖出汇编代码,结合动调分析语句还原算法。

mov     ds:dword_403474, 0FFFFFFFFh            // mov output ,0xffffffff
mov     ecx, ds:dword_403464                         // mov ecx,index(0) 
mov     dl, byte ptr ds:VirtualProtect[ecx]        // mov dl,input[0]
mov     byte ptr ds:dword_403470, dl             // mov temp,dl
movzx   eax, byte ptr ds:dword_403470         //  mov eax, temp  输入传给eax
xor     eax, ds:dword_403474                          //  xor   eax,output 取反类似
mov     byte ptr ds:dword_403470, al            //   mov temp , al  保存取反的值
movzx   ecx, byte ptr ds:dword_403470        //   mov ecx,temp 
and     ecx, 0FFh                                             //   and  ecx,0xff
mov     byte ptr ds:dword_403470, cl            //   mov temp,cl
mov     edx, ds:dword_403474                      //    mov edx,output 
shr     edx,   8                                                 //    shr   edx,8
mov     ds:dword_403474, edx                      //    mov output,edx
movzx   eax, byte ptr ds:dword_403470       //    mov eax,temp
mov     ecx, ds:dword_403474                         //    mov ecx,output
xor     ecx, dword ptr ds:byte_403058[eax*4]     //  xor ecx, sbox[4*eax]   //174841BC  xor sbox[4*0x9e] 结果保存到output
mov     ds:dword_403474, ecx                              
mov     edx, ds:dword_403464                            ....
mov     al, [edx+403005h]		
mov     byte ptr ds:dword_403470, al		
movzx   ecx, byte ptr ds:dword_403470		
xor     ecx, ds:dword_403474		
mov     byte ptr ds:dword_403470, cl	
mov     edx, ds:dword_403474
shr     edx, 8
mov     ds:dword_403474, edx
movzx   eax, byte ptr ds:dword_403470
mov     ecx, ds:dword_403474
xor     ecx, dword ptr ds:byte_403058[eax*4]     //xor ecx,sbox[4*eax]  //eax 0xdd
mov     ds:dword_403474, ecx		            //mov output,ecx
mov     edx, ds:dword_403474                            //mov edx,output
xor     edx, 0FFFFFFFFh		           //xor     edx, 0FFFFFFFFh
mov     ds:dword_403474, edx                          //mov    output edx

python代码如下

input='a'*40
output=0xffffffff
for index in range(0,40,2):
        tmp=(ord(input[index])^output)&0xff
        output=output>>8
        output=output^somebox[tmp]
        #print("%x %x"%(tmp,output))
        tmp = (ord(input[index+1]) ^ output) & 0xff
        output = output >> 8
        output = output ^ somebox[tmp]
        output=output^0xffffffff
        print("%x %x" % (tmp, output))

可知是两个字节为一组进行的处理,z3解因为涉及下标问题不好下手,z3所得中间方程REF的参数不能转换为其他类型的变量,所以直接爆破。

somebox=[0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]
enc=[0xC0F6605E, 0x00B16E0A, 0x3319A2D2, 0x57CAB7B7, 0x9A646D9C, 0xBDD82726, 0xD838FB91, 0x8DE10BB3, 0x176B0DAD, 0x685FDEEF, 0x2C1FF7B1, 0x6C444296, 0xA15CFE90, 0x20CD8721, 0x62967CE8, 0x2C1641FD, 0x572D0F9A, 0xAE52DC2C, 0x50497DCF, 0xFF6ABF4A]
s=''
enc=[0xC0F6605E, 0x00B16E0A, 0x3319A2D2, 0x57CAB7B7, 0x9A646D9C, 0xBDD82726, 0xD838FB91, 0x8DE10BB3, 0x176B0DAD, 0x685FDEEF, 0x2C1FF7B1, 0x6C444296, 0xA15CFE90, 0x20CD8721, 0x62967CE8, 0x2C1641FD, 0x572D0F9A, 0xAE52DC2C, 0x50497DCF, 0xFF6ABF4A]
for i  in range(20):
    for  m in range(32,128):
        for n in range(32,128):
            output = 0xffffffff
            tmp=(m^output)&0xff
            output=output>>8
            output=output^somebox[tmp]
            #print("%x %x"%(tmp,output))
            tmp = (n ^ output) & 0xff
            output = output >> 8
            output = output ^ somebox[tmp]
            output=output^0xffffffff
            if output==enc[i]:
                s+=chr(m)+chr(n)

print(s)
#NCTF{rLdE57TG0iHA39qUnFZp6LeJyYEBcxMNL7}

狗狗的秘密

挺不错的,解完想暴打出题人。
32位程序,ida载入获得假flag一枚

不过main之前有个TlsCallback函数,直接下个断点,动态分析。

 if ( !v9 && !IsDebuggerPresent() )
    {
      off_825014 = (int (__cdecl *)(_DWORD))sub_823000;
      v8 = (unsigned int *)((char *)sub_823000 + 256);
      for ( i = 0; i < 24; ++i )
        v8 += 2;
      for ( j = 0; j < 24; ++j )
      {
        v8 -= 2;
        sub_8211F0(v8);
      }
    }

反调试,off_825014在主函数出现过,但是个假逻辑,所以这部分内容是SMC修改技术。

unsigned int __cdecl sub_8211F0(unsigned int *a1)
{
  unsigned int result; // eax
  int i; // [esp+0h] [ebp-Ch]
  unsigned int v3; // [esp+4h] [ebp-8h]
  unsigned int v4; // [esp+8h] [ebp-4h]

  v4 = *a1;
  v3 = a1[1];
  for ( i = 0; i < 64; ++i )
  {
    v3 -= (dword_825004[(*(_DWORD *)delta >> 11) & 3] + *(_DWORD *)delta) ^ (v4 + ((v4 >> 5) ^ (16 * v4)));
    *(_DWORD *)delta += dword_825000;
    v4 -= (dword_825004[delta[0] & 3] + *(_DWORD *)delta) ^ (v3 + ((v3 >> 5) ^ (16 * v3)));
  }
  *a1 = v4;
  result = v3;
  a1[1] = v3;
  return result;
}

直接改eip绕过这个反调试即可,同时修改代码用的xTea,不过delta的值有个小坑,main函数中有个创建线程的函数,将delta赋值为0xDA76C600,patch进行修改,后面下个断F9。

线程的执行顺序不是太清楚,不过TLSCALLBACK在main之前执行,而delta在main函数中被改掉,为什么会应用到smc中呢,有待解决。

修复函数后拿到真正处理逻辑。

int __cdecl sub_823000(const char *a1)
{
  signed int v2; // [esp+0h] [ebp-98h]
  unsigned int v3; // [esp+10h] [ebp-88h]
  signed int v4; // [esp+1Ch] [ebp-7Ch]
  int v5; // [esp+2Ch] [ebp-6Ch]
  int v6; // [esp+2Ch] [ebp-6Ch]
  char v7; // [esp+32h] [ebp-66h]
  signed int Size; // [esp+34h] [ebp-64h]
  unsigned int v9; // [esp+38h] [ebp-60h]
  int k; // [esp+38h] [ebp-60h]
  unsigned __int8 *v11; // [esp+3Ch] [ebp-5Ch]
  int i; // [esp+40h] [ebp-58h]
  signed int j; // [esp+40h] [ebp-58h]
  signed int m; // [esp+40h] [ebp-58h]
  signed int n; // [esp+40h] [ebp-58h]
  signed int ii; // [esp+40h] [ebp-58h]
  char v17[62]; // [esp+44h] [ebp-54h]
  int v18; // [esp+82h] [ebp-16h]
  int v19; // [esp+86h] [ebp-12h]
  int v20; // [esp+8Ah] [ebp-Eh]
  int v21; // [esp+8Eh] [ebp-Ah]
  __int16 v22; // [esp+92h] [ebp-6h]

  v3 = strlen(a1);
  Size = 146 * v3 / 0x64 + 1;
  v4 = 0;
  v11 = (unsigned __int8 *)malloc(Size);
  v17[0] = 82;
  v17[1] = -61;
  v17[2] = 26;
  v17[3] = -32;
  v17[4] = 22;
  v17[5] = 93;
  v17[6] = 94;
  v17[7] = -30;
  v17[8] = 103;
  v17[9] = 31;
  v17[10] = 31;
  v17[11] = 6;
  v17[12] = 6;
  v17[13] = 31;
  v17[14] = 23;
  v17[15] = 6;
  v17[16] = 15;
  v17[17] = -7;
  v17[18] = 6;
  v17[19] = 103;
  v17[20] = 88;
  v17[21] = -78;
  v17[22] = -30;
  v17[23] = -116;
  v17[24] = 15;
  v17[25] = 42;
  v17[26] = 6;
  v17[27] = -119;
  v17[28] = -49;
  v17[29] = 42;
  v17[30] = 6;
  v17[31] = 31;
  v17[32] = -104;
  v17[33] = 26;
  v17[34] = 62;
  v17[35] = 23;
  v17[36] = 103;
  v17[37] = 31;
  v17[38] = -9;
  v17[39] = 58;
  v17[40] = 68;
  v17[41] = -61;
  v17[42] = 22;
  v17[43] = 51;
  v17[44] = 105;
  v17[45] = 26;
  v17[46] = 117;
  v17[47] = 22;
  v17[48] = 62;
  v17[49] = 23;
  v17[50] = -43;
  v17[51] = 105;
  v17[52] = 122;
  v17[53] = 27;
  v17[54] = 68;
  v17[55] = 68;
  v17[56] = 62;
  v17[57] = 103;
  v17[58] = -9;
  v17[59] = -119;
  v17[60] = 103;
  v17[61] = -61;
  v18 = 0;
  v19 = 0;
  v20 = 0;
  v21 = 0;
  v22 = 0;
  memset(v11, 0, Size);
  v9 = 0;
  for ( i = 0; i < 256; ++i )
  {
    v7 = byte_825018[i];
    byte_825018[i] = byte_825018[(i + *((unsigned __int8 *)&delta + i % 4)) % 256];// delta变为0了
    byte_825018[(i + *((unsigned __int8 *)&delta + i % 4)) % 256] = v7;
  }
  while ( v9 < strlen(a1) )
  {
    v5 = a1[v9];
    for ( j = 146 * v3 / 0x64; ; --j )
    {
      v6 = v5 + (v11[j] << 8);
      v11[j] = v6 % 47;
      v5 = v6 / 47;
      if ( j < v4 )
        v4 = j;
      if ( !v5 && j <= v4 )
        break;
    }
    ++v9;
  }
  for ( k = 0; !v11[k]; ++k )
    ;
  for ( m = 0; m < Size; ++m )
    v11[m] = byte_825118[v11[k++]];             // 单表替换
  while ( m < Size )
    v11[m++] = 0;
  v2 = strlen((const char *)v11);
  for ( n = 0; n < v2; ++n )
    v11[n] ^= byte_825018[v11[n]];              // 异或处理
  for ( ii = 0; ii < v2; ++ii )
  {
    if ( v11[ii] != (unsigned __int8)v17[ii] )
    {
      printf("Wrong!\n", v2);
      exit(0);
    }
  }
  printf("Right!\n", v2);
  return 0;
}

delta的值是0,需要注意一下,接着就是写脚本逆向,z3不好直接求解,加密流程是先将输入转为47进制下每位的值存在数组v11中,找到第一个非0值的下标k,接着进行单表替换和异或。

又是一个z3直接出,却被ban了的题,类型转换有点坑

因为涉及到表索引和本身异或不好逆向还原,所以想着先爆破v11数组。

enc=[0x52, 0xC3, 0x1A, 0xE0, 0x16, 0x5D, 0x5E, 0xE2, 0x67, 0x1F, 0x1F, 0x06, 0x06, 0x1F, 0x17, 0x06, 0x0F, 0xF9, 0x06, 0x67, 0x58, 0xB2, 0xE2, 0x8C, 0x0F, 0x2A, 0x06, 0x89, 0xCF, 0x2A, 0x06, 0x1F, 0x98, 0x1A, 0x3E, 0x17, 0x67, 0x1F, 0xF7, 0x3A, 0x44, 0xC3, 0x16, 0x33, 0x69, 0x1A, 0x75, 0x16, 0x3E, 0x17, 0xD5, 0x69, 0x7A, 0x1B, 0x44, 0x44, 0x3E, 0x67, 0xF7, 0x89, 0x67, 0xC3]
c=[]
for i in range(61):
    temp=[]
    for j in range(47):
        tmp=tb2[j]
        tmp=tmp^table[tmp]
        if tmp==enc[i]:
            temp.append(j)
    if len(temp)==1:
        c.append(temp[0])
    else:
        c.append(temp)
c.insert(0,0)

#[0, 2, 0, [33, 45], 44, 30, 40, 8, 23, [7, 11, 22], [34, 37], [34, 37], [19, 20, 43], [19, 20, 43], [34, 37], 24, [19, 20, 43], [4, 31], 29, [19, 20, 43], [7, 11, 22], 13, 5, 23, 41, [4, 31], 35, [19, 20, 43], 9, 14, 35, [19, 20, 43], [34, 37], 3, [33, 45], 10, 24, [7, 11, 22], [34, 37], 38, 1, 25, 0, 30, 6, 42, [33, 45], 36, 30, 10, 24, 21, 42, 26, 28, 25, 25, 10, [7, 11, 22], 38, 9, [7, 11, 22]]

v11第一位是0,根据加密的最后一位是0xc3,或者多次测试都可知,不过这解有点多,下面就是对c进行排列组合,之后47进制转,long_to_bytes下即可,不过这…tmd,dfs不太会写,直接硬爆破了,大概跑了半小时,直接整emo了。

跑起来才意识到从高位开始爆破会比较快,高位对转字符的影响较大,傻了

完整如下

from Crypto.Util.number import *


def dododo(c):
    sum = 0
    for i in range(62):
        sum += c[i] * pow(47, 61 - i)
    m=long_to_bytes(sum)
    try:
        flag=m.decode()
        print(flag)
        exit(0)
    except:
        pass


enc=[0x52, 0xC3, 0x1A, 0xE0, 0x16, 0x5D, 0x5E, 0xE2, 0x67, 0x1F, 0x1F, 0x06, 0x06, 0x1F, 0x17, 0x06, 0x0F, 0xF9, 0x06, 0x67, 0x58, 0xB2, 0xE2, 0x8C, 0x0F, 0x2A, 0x06, 0x89, 0xCF, 0x2A, 0x06, 0x1F, 0x98, 0x1A, 0x3E, 0x17, 0x67, 0x1F, 0xF7, 0x3A, 0x44, 0xC3, 0x16, 0x33, 0x69, 0x1A, 0x75, 0x16, 0x3E, 0x17, 0xD5, 0x69, 0x7A, 0x1B, 0x44, 0x44, 0x3E, 0x67, 0xF7, 0x89, 0x67, 0xC3]
table=[0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x65, 0xA2, 0x9B, 0xF4, 0xDF, 0xAC, 0x7C, 0xA1, 0xC6, 0x16, 0xD0, 0x0F, 0xDD, 0xDC, 0x73, 0xC5, 0x6B, 0xD1, 0x96, 0x47, 0xC2, 0x26, 0x67, 0x4E, 0x41, 0x82, 0x20, 0x56, 0x9A, 0x6E, 0x33, 0x92, 0x88, 0x29, 0xB5, 0xB4, 0x71, 0xA9, 0xCE, 0xC3, 0x34, 0x50, 0x59, 0xBF, 0x2D, 0x57, 0x22, 0xA6, 0x30, 0x04, 0xB2, 0xCD, 0x36, 0xD5, 0x68, 0x4D, 0x5B, 0x45, 0x9E, 0x85, 0xCF, 0x9D, 0xCC, 0x61, 0x78, 0x32, 0x76, 0x31, 0xE3, 0x80, 0xAD, 0x39, 0x4F, 0xFA, 0x72, 0x83, 0x4C, 0x86, 0x60, 0xB7, 0xD7, 0x63, 0x0C, 0x44, 0x35, 0xB3, 0x7B, 0x19, 0xD4, 0x69, 0x08, 0x0B, 0x1F, 0x3D, 0x11, 0x79, 0xD3, 0xEE, 0x93, 0x42, 0xDE, 0x23, 0x3B, 0x5D, 0x8D, 0xA5, 0x77, 0x5F, 0x58, 0xDB, 0x97, 0xF6, 0x7A, 0x18, 0x52, 0x15, 0x74, 0x25, 0x62, 0x2C, 0x05, 0xE8, 0x0D, 0x98, 0x2A, 0x43, 0xE2, 0xEF, 0x48, 0x87, 0x49, 0x1C, 0xCA, 0x2B, 0xA7, 0x8A, 0x09, 0x81, 0xE7, 0x53, 0xAA, 0xFF, 0x6F, 0x8E, 0x91, 0xF1, 0xF0, 0xA4, 0x46, 0x3A, 0x7D, 0x54, 0xEB, 0x2F, 0xC1, 0xC0, 0x0E, 0xBD, 0xE1, 0x6C, 0x64, 0xBE, 0xE4, 0x02, 0x3C, 0x5A, 0xA8, 0x9F, 0x37, 0xAF, 0xA0, 0x13, 0xED, 0x1B, 0xEC, 0x8B, 0x3E, 0x7E, 0x27, 0x99, 0x75, 0xAB, 0xFE, 0xD9, 0x3F, 0xF3, 0xEA, 0x70, 0xF7, 0x95, 0xBA, 0x1D, 0x40, 0xB0, 0xF9, 0xE5, 0xF8, 0x06, 0xBC, 0xB6, 0x03, 0xC9, 0x10, 0x9C, 0x2E, 0x89, 0x5C, 0x7F, 0xB1, 0x1A, 0xD6, 0x90, 0xAE, 0xDA, 0xE6, 0x5E, 0xB9, 0x84, 0xE9, 0x55, 0xBB, 0xC7, 0x0A, 0xE0, 0x66, 0xF2, 0xD8, 0xCB, 0x00, 0x12, 0xB8, 0x17, 0x94, 0x6A, 0x4A, 0x01, 0x24, 0x14, 0x51, 0x07, 0x65, 0x21, 0xC8, 0x38, 0xFD, 0x8F, 0xC4, 0xF5, 0xFC]
#delta=[0,0xc6,0x76,0xda]
tb2=[0xA7, 0x1C, 0x7E, 0xAF, 0xD9, 0xC2, 0xC0, 0xBE, 0x1F, 0x45, 0x9A, 0x85, 0x26, 0xE3, 0x87, 0xC3, 0x21, 0xE0, 0x95, 0x10, 0x71, 0x70, 0x02, 0x75, 0x35, 0xA5, 0x1D, 0x0D, 0x2F, 0xEE, 0x25, 0x7B, 0xB5, 0x82, 0x66, 0x8D, 0xDB, 0x53, 0x3A, 0x29, 0xD4, 0x43, 0x99, 0x97, 0x9D, 0xE8, 0x49, 0x00]

c=[]

for i in range(61):
    temp=[]
    for j in range(47):
        tmp=tb2[j]
        tmp=tmp^table[tmp]
        if tmp==enc[i]:
            temp.append(j)
    if len(temp)==1:
        c.append(temp[0])
    else:
        c.append(temp)
c.insert(0,0)
print(c)
for i in c:
    if isinstance(i,int):
        pass
    else:
        print(i)
c[3]=45
tblen=[]
l=1
index=[]
for i in range(len(c)):
    try:
        tblen.append(len(c[i]))
        l*=len(c[i])
        index.append(i)
    except:
        tblen.append(1)

print(tblen)
print(index)

sum=0
t1=[7, 11, 22]
t2=[34, 37]
t3=[19, 20, 43]
t4=[4, 31]
t5=[33, 45]


for  a1 in range(3):
    c[9]=t1[a1]
    for a2 in range(2):
        c[10]=t2[a2]
        for a3 in range(2):
            c[11]=t2[a3]
            for a4 in range(3):
                c[12]=t3[a4]
                for a5 in range(3):
                    c[13]=t3[a5]
                    for a6 in range(2):
                        c[14]=t2[a6]
                        for a7 in range(3):
                            c[16]=t3[a7]
                            for a8 in range(2):
                                c[17]=t4[a8]
                                for a9 in range(3):
                                    c[19]=t3[a9]
                                    for a10 in range(3):
                                        c[20]=t1[a10]
                                        for a11 in range(2):
                                            c[25]=t4[a11]
                                            for a12 in range(3):
                                                c[27]=t3[a12]
                                                for a13 in range(3):
                                                    c[31]=t3[a13]
                                                    for a14 in range(2):
                                                        c[32]=t2[a14]
                                                        for a15 in range(2):
                                                            c[34]=t5[a15]
                                                            for a16 in range(3):
                                                                c[37]=t1[a16]
                                                                for a17 in range(2):
                                                                    c[38]=t2[a17]
                                                                    for a18 in range(2):
                                                                        c[46]=t5[a18]
                                                                        for a19 in range(3):
                                                                            c[58]=t1[a19]
                                                                            for a20 in range(3):
                                                                                c[61]=t1[a20]
                                                                                dododo(c)

#NCTF{ADF0E239-D911-3781-7E40-A575A19E5835}

题感觉都挺好玩的,就是把z3 ban掉太不够意思了,自己的算法能力不是太给力。


总结:C++或者再复杂一点的语言还得是动调,线程的调用关系要梳理清晰还有常见算法,同时巩固了一下西湖的SMC思路。

NCTF还是差一道Android就能AK了,native层的代码看的头皮发麻,有时间要及时复现和反思,另:航哥TQQQLLL,直接给秒了

加上安洵杯,上周小比赛还是蛮多的,能学到很多东西,但还没完全复现。

另:自己搭建了一个博客,可能最新内容会在个人博客上发布
欢迎师傅们来玩儿 -------------------------- Lu1u的blog

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
\[NCTF2019\]SQLi是一个CTF比赛中的题目,涉及到SQL注入。根据引用\[1\]和引用\[2\]的内容,可以得知在该题目中,通过构造特定的SQL语句,可以绕过过滤,获取到管理员的密码,从而获得flag。具体的解题思路是通过不断尝试不同的字符,构造SQL语句进行盲注,判断是否成功绕过过滤。引用\[3\]提供了一个Python脚本的示例,可以用来自动化进行尝试。该脚本通过构造不同长度的payload,逐位尝试密码的每一位字符,直到获取到完整的密码。 #### 引用[.reference_title] - *1* [[NCTF2019]SQLi --BUUCTF --详解](https://blog.csdn.net/l2872253606/article/details/125265138)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [[NCTF2019]SQLi(Regexp注入)](https://blog.csdn.net/weixin_45669205/article/details/116137824)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [[NCTF2019]SQLi](https://blog.csdn.net/shinygod/article/details/124100832)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值