ISCC-2022-reverse-mobile-部分wp

我太菜了,呜呜呜

在这里插入图片描述

reverse

  • GetTheTable-100
  • Poetry-100
  • Amy's Code-100
  • How_decode-150
  • Sad Code-200
  • VigenereLike-250
  • Bob's Code-300
  • Ruststr-300
  • MOBILE - A
  • MOBILE - B
  • MOBILE - C

GetTheTable-100

这个说要用正确的解密软件解密,我还想了好久,想不到有啥解密软件,直接IDA

ISCC-2022-reverse-mobile-部分wp_第1张图片

先查壳

ISCC-2022-reverse-mobile-部分wp_第2张图片

找到主函数,分析代码逻辑

// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char str12581[59]; // [rsp+20h] [rbp-60h] BYREF
  char flag[32]; // [rsp+60h] [rbp-20h] BYREF
  char str[27]; // [rsp+80h] [rbp+0h] BYREF
  int j; // [rsp+A0h] [rbp+20h]
  int index; // [rsp+A4h] [rbp+24h]
  char *encryption; // [rsp+A8h] [rbp+28h]
  _BYTE len[12]; // [rsp+B4h] [rbp+34h] OVERLAPPED
  int n; // [rsp+C4h] [rbp+44h]
  int n1; // [rsp+C8h] [rbp+48h]
  int j_1; // [rsp+CCh] [rbp+4Ch]
  int j_0; // [rsp+D0h] [rbp+50h]
  int carry; // [rsp+D4h] [rbp+54h]
  int high; // [rsp+D8h] [rbp+58h]
  int i; // [rsp+DCh] [rbp+5Ch]

  _main();
  n1 = 18;
  strcpy(str, "ERaQux2kCQGLeLwddrgMCKtL6x");    // flag最终的变化形式
  scanf("%s", flag);
  n = strlen(flag);
  if ( n <= 32 )                                // flag长度小于32
  {
    *(_QWORD *)&len[4] = 0i64;
    *(_QWORD *)len = (unsigned int)(138 * strlen(flag) / 0x64) + 1;// len=36
    strcpy(str12581, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
    encryption = (char *)malloc(*(int *)len);
    index = 0;
    memset(encryption, 0, *(int *)len);
    high = *(_DWORD *)len - 1;                  // high=35
    j = 0;
    i = 0;
    while ( i < strlen(flag) )
    {
      carry = flag[i];
      for ( j_0 = *(_DWORD *)len - 1; j_0 > high || carry; --j_0 )
      {
        carry += encryption[j_0] << 8;
        encryption[j_0] = (char)carry % 58;
        carry /= 58;
        if ( !j_0 )
          break;
      }
      ++i;
      high = j;
    }
    for ( i = 0; !encryption[i]; ++i )
      ;
    j_1 = 0;
    while ( *(int *)len > i )
    {
      if ( str[j_1] != str12581[encryption[i]] )
      {
        printf("Wrong answer!");
        system("pause");
        return 0;
      }
      ++i;
      ++j_1;
    }
    printf("Your input is the right answer!");
    system("pause");
    return 0;
  }
  else
  {
    printf("Wrong answer!");
    system("pause");
    return 0;
  }
}

主要就是这一段的加密方式,我乍一眼也没看明白,然后跑了下这个加密方式

while ( i < strlen(flag) )
    {
      carry = flag[i];
      for ( j_0 = *(_DWORD *)len - 1; j_0 > high || carry; --j_0 )
      {
        carry += encryption[j_0] << 8;
        encryption[j_0] = (char)carry % 58;
        carry /= 58;
        if ( !j_0 )
          break;
      }
      ++i;
      high = j;
    }

随便整个字符串试一下

char flag[] = "ISCC{hello_word}";
  int carry;
  int j_0,i=0,j=0,high=22,len=23,k;
  char en[24]={0};
  while(i < strlen(flag))
  {
      carry = flag[i];
      for(j_0 = 22; j_0 > high || carry ; --j_0)
      {
          //printf("carry = %d\n",carry);
          carry += en[j_0] << 8;
          en[j_0] = carry % 58;
          carry /= 58;
          if(!j_0) break;
      }
      printf("i = %d\n",i);
      for(k = 0 ; k < 23;k++)
      {
          printf("%d ",en[k]);
      }


         ++i;
      high=j;
  }

运行结果:

ISCC-2022-reverse-mobile-部分wp_第3张图片

这样就好看多了,可以看出都是从最后一位开始加密,每轮加密都会比上面的多两个数,第一个数是carry除以58的商,第二个数是carry除以58的余数,根据这个可以算出上一个carry,以及上一轮的最后一轮的第一个数。

根据这个可以写出脚本

Str = "ERaQux2kCQGLeLwddrgMCKtL6x"
Str_1 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
en = []
for i in range(len(Str)):
    en.append(Str_1.find(Str[i]))

print(en)
def f(list):
    last_list = []
    carry = 0
    for i in range(0,len(list)):
        carry *= 58
        carry += list[i]
        t = carry // 256
        last_list.append( t)
        carry -= (t * 256)
    del last_list[0]   #删除掉开始的零元素
    print(last_list)
    return carry,last_list

flag = [0] * 26
for i in range(25,-1,-1):
     flag[i],en = f(en) 
for i in flag:
    if i > 0:
        print(chr(i),end="")
print(flag)

运行结果

[13, 24, 33, 23, 52, 55, 1, 43, 11, 23, 15, 19, 37, 19, 54, 36, 36, 49, 39, 20, 11, 18, 51, 
19, 5, 55]
[3, 2, 22, 56, 36, 0, 39, 47, 22, 56, 27, 28, 27, 2, 14, 37, 17, 23, 54, 39, 27, 2, 0, 43, 43]
[0, 39, 55, 55, 24, 27, 19, 51, 56, 23, 38, 49, 28, 45, 21, 25, 38, 48, 27, 19, 47, 20, 49, 
6]
[0, 9, 3, 9, 22, 17, 56, 35, 45, 49, 44, 34, 45, 2, 7, 7, 10, 9, 9, 47, 31, 6, 57]
[0, 2, 2, 56, 55, 20, 22, 19, 51, 36, 11, 26, 52, 46, 14, 17, 28, 7, 29, 50, 11, 7]
[0, 0, 26, 55, 28, 49, 27, 41, 38, 24, 56, 3, 48, 12, 16, 48, 21, 18, 53, 25, 24]
[0, 0, 6, 6, 13, 19, 21, 13, 30, 0, 12, 40, 43, 5, 29, 10, 55, 33, 42, 53]
[0, 0, 1, 22, 14, 46, 30, 37, 2, 41, 42, 43, 38, 44, 17, 2, 1, 41, 36]
[0, 0, 0, 18, 10, 35, 0, 34, 39, 7, 37, 18, 55, 26, 20, 9, 56, 33]
[0, 0, 0, 4, 6, 54, 8, 43, 11, 33, 52, 23, 45, 10, 55, 18, 33]
[0, 0, 0, 0, 54, 7, 42, 44, 13, 2, 40, 24, 24, 16, 30, 38]
[0, 0, 0, 0, 12, 15, 20, 6, 22, 51, 47, 12, 45, 21, 50]
[0, 0, 0, 0, 2, 45, 9, 31, 20, 34, 22, 54, 5, 43]
[0, 0, 0, 0, 0, 36, 29, 46, 30, 28, 36, 53, 2]
[0, 0, 0, 0, 0, 8, 15, 47, 14, 9, 11, 57]
[0, 0, 0, 0, 0, 1, 50, 41, 3, 38, 19]
[0, 0, 0, 0, 0, 0, 24, 36, 28, 27]
[0, 0, 0, 0, 0, 0, 5, 33, 37]
[0, 0, 0, 0, 0, 0, 1, 15]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0]
[0, 0]
[0]
[]
ISCC{T5xr15ruVEyXI}[0, 0, 0, 0, 0, 0, 0, 73, 83, 67, 67, 123, 84, 53, 120, 114, 49, 53, 114, 117, 86, 69, 121, 88, 73, 125]

得到flag: ISCC{T5xr15ruVEyXI}

Poetry-100

这题0解,还是等着看别人的wp吧

ISCC-2022-reverse-mobile-部分wp_第4张图片

Amy’s Code-100

ISCC-2022-reverse-mobile-部分wp_第5张图片

还是先查看信息

ISCC-2022-reverse-mobile-部分wp_第6张图片

IDA查看字符串,直接定位到关键函数

ISCC-2022-reverse-mobile-部分wp_第7张图片

代码很简单,就一个异或和一个加法

ISCC-2022-reverse-mobile-部分wp_第8张图片

写个脚本出来就行

#include 
#include 
#include 

int main()
{
 int v9[20] = {0};
 char v6[21] = "LWHFUENGDJGEFHYDHIGJ";
 char flag[21];
 int i,j,k;
 v9[0] = 149;
  v9[1] = 169;
  v9[2] = 137;
  v9[3] = 134;
  v9[4] = 212;
  v9[5] = 188;
  v9[6] = 177;
  v9[7] = 184;
  v9[8] = 177;
  v9[9] = 197;
  v9[10] = 192;
  v9[11] = 179;
  v9[12] = 153;
  v9[13] = 142;
  v9[14] = 191;
  v9[15] = 130;
  v9[16] = 167;
  v9[17] = 191;
  v9[18] = 104;
  v9[19] = 184;
  for (i = 0 ; i < 20 ; i ++)
  {
      flag[i] = v9[i] - v6[i];
      flag[i] ^= i;
      printf("%c",flag[i]);
  }
  return 0;

}

运行结果:

ISCC-2022-reverse-mobile-部分wp_第9张图片

How_decode-150

ISCC-2022-reverse-mobile-部分wp_第10张图片

还是先查下壳

ISCC-2022-reverse-mobile-部分wp_第11张图片

查看字符串,然后定位到主函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *v3; // rsp
  int v2[32]; // [rsp+20h] [rbp-60h] BYREF
  int k[4]; // [rsp+A0h] [rbp+20h] BYREF
  char v[32]; // [rsp+B0h] [rbp+30h] BYREF
  int n; // [rsp+DCh] [rbp+5Ch]
  int (*p_v1)[]; // [rsp+E0h] [rbp+60h]
  __int64 v10; // [rsp+E8h] [rbp+68h]
  int n1; // [rsp+F4h] [rbp+74h]
  int i; // [rsp+F8h] [rbp+78h]
  int i_0; // [rsp+FCh] [rbp+7Ch]

  _main();
  n1 = 18;
  v10 = 17i64;
  v3 = alloca(80i64);
  p_v1 = (int (*)[])v2;
  v2[0] = 0x8D7FFB13;
  v2[1] = 0x8B2B6DB0;
  v2[2] = 0x66C4403F;
  v2[3] = 0x7413DD82;
  v2[4] = 0xDBF303FC;
  v2[5] = 0x417C54F3;
  v2[6] = 0x428681FC;
  v2[7] = 0xDE6B433E;
  v2[8] = 0x88CD333A;
  v2[9] = 156067879;
  v2[10] = 1935606960;
  v2[11] = 0x96FAB237;
  v2[12] = 0xF5ED4CB2;
  v2[13] = 3273616493;
  v2[14] = 2496521664;
  v2[15] = 1139822545;
  v2[16] = 3741141319;
  v2[17] = 244541121;
  k[0] = 'I';
  k[1] = 'S';
  k[2] = 'C';
  k[3] = 'C';
  scanf("%s", v);
  n = strlen(v);
  if ( n == n1 )
  {
    for ( i = 0; i < n; ++i )
      v2[i] = v[i];
    encode(v2, n, k);
    for ( i_0 = 0; i_0 < n; ++i_0 )
    {
      if ( *((_DWORD *)p_v1 + i_0) != v2[i_0] )
        goto LABEL_2;
    }
    printf("Your input is the right answer!");
    system("pause");
    return 0;
  }
  else
  {
LABEL_2:
    printf("Wrong answer!");
    system("pause");
    return 0;
  }
}

就只有一个encode函数加密,点进去看下,感觉像是xxtea加密的变种

void __cdecl encode(int *v, int n, const int *key)
{
  int *v4; // rax
  int *v5; // rax
  int y; // [rsp+8h] [rbp-18h]
  int e; // [rsp+Ch] [rbp-14h]
  int rounds; // [rsp+10h] [rbp-10h]
  int p; // [rsp+14h] [rbp-Ch]
  int sum; // [rsp+18h] [rbp-8h]
  int z; // [rsp+1Ch] [rbp-4h]

  rounds = 52 / n + 6;
  sum = 0;
  for ( z = v[n - 1]; rounds--; z = *v5 )
  {
    sum -= 0x61C88647;
    e = (sum >> 2) & 3;
    for ( p = 0; p < n - 1; ++p )
    {
      y = v[p + 1];
      v4 = &v[p];
      *v4 += ((y ^ sum) + (z ^ key[e ^ p & 3])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));
      z = *v4;
    }
    v5 = &v[n - 1];
    *v5 += ((*v ^ sum) + (z ^ key[e ^ p & 3])) ^ (((4 * *v) ^ (z >> 5)) + ((*v >> 3) ^ (16 * z)));
  }
}

网上嫖了个脚本,改了改

#include 
#include 
#include 
#define MX ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)))
#define DELTA 0x61C88647
int main()
{
  int key[5] = {73,83,67,67};
  int v2[20] = {0};
  v2[0] = 0x8D7FFB13;
  v2[1] = 0x8B2B6DB0;
  v2[2] = 0x66C4403F;
  v2[3] = 0x7413DD82;
  v2[4] = 0xDBF303FC;
  v2[5] = 0x417C54F3;
  v2[6] = 0x428681FC;
  v2[7] = 0xDE6B433E;
  v2[8] = 0x88CD333A;
  v2[9] = 0x94D6827;
  v2[10] = 0x735F04B0;
  v2[11] = 0x96FAB237;
  v2[12] = 0xF5ED4CB2;
  v2[13] = 0xC31F6C6D;
  v2[14] = 0x94CDE5C0;
  v2[15] = 0x43F04FD1;
  v2[16] = 0xDEFD4947;
  v2[17] = 0xE9366C1;
  // n = 18
  int sum = 0 , n = 18;
  int rounds = 52 / n + 6;
  int i,j,k;
  int z,y,e,p;
        sum = rounds * DELTA * (-1);
        y = v2[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p=n-1; p>0; p--)
            {
                z = v2[p-1];
                //y = v2[p] -= ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));
                y = v2[p] -= MX;
            }
            z = v2[n-1];
            //y = v2[0] -= ((v2[0] ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * v2[0]) ^ (z >> 5)) + ((v2[0] >> 3) ^ (16 * z)));
            y = v2[0] -= MX;
            sum += DELTA;
        }
        while (--rounds);

   for(i = 0 ; i < 18 ; i++)
   {
       printf("%c",v2[i],v2[i]);
   }
  return 0;

}

运行结果:

ISCC-2022-reverse-mobile-部分wp_第12张图片

Sad Code-200

ISCC-2022-reverse-mobile-部分wp_第13张图片

先看下信息

ISCC-2022-reverse-mobile-部分wp_第14张图片

定位到主函数,这个的代码也是很简洁

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  __int64 v4; // rax
  int v5; // ecx
  char Destination[60]; // [esp+D8h] [ebp-348h] BYREF
  int k; // [esp+114h] [ebp-30Ch]
  char v8; // [esp+120h] [ebp-300h]
  char v9[49]; // [esp+121h] [ebp-2FFh] BYREF
  size_t v10; // [esp+15Ch] [ebp-2C4h]
  int j; // [esp+168h] [ebp-2B8h]
  int i; // [esp+174h] [ebp-2ACh]
  char v13[56]; // [esp+180h] [ebp-2A0h] BYREF
  __int64 v14[10]; // [esp+1B8h] [ebp-268h] BYREF
  int v15; // [esp+208h] [ebp-218h]
  int v16; // [esp+20Ch] [ebp-214h]
  char Str[516]; // [esp+218h] [ebp-208h] BYREF

  v15 = 0;
  v16 = 0;
  memset(v14, 0, 72);
  memset(v13, 0, 45);
  j__printf(&byte_439F18);
  sub_413834((va_list)"%s", (char)Str);         // 输入函数到Str中
  if ( j__strlen(Str) != 32 )
    return 0;
  for ( i = 0; i < 8; ++i )
  {
    for ( j = 0; j < 4; ++j )
      v13[5 * i + j] = Str[4 * i + j];          // 四个一组存入到二维数组 v13中
  }
  v10 = 0;
  v8 = 0;
  j__memset(v9, 0, sizeof(v9));
  for ( k = 0; k < 8; ++k )
  {
    memset(Destination, 0, 50);
    sub_4130CD((int)&v13[5 * k], Destination);
    v10 = j__strlen(Destination);
    v4 = sub_413BDB(v10, Destination, v15, v16);
    v5 = k;
    LODWORD(v14[k]) = v4;
    HIDWORD(v14[v5]) = HIDWORD(v4);
  }
  if ( v14[2] + 7 * v14[1] - 4 * v14[0] - 2 * v14[3] == 0x2060BF585i64
    && 5 * v14[3] + 3 * v14[2] - v14[1] - 2 * v14[0] == 0x164D5CCD0i64
    && 2 * v14[1] + 8 * v14[3] + 10 * v14[0] - 5 * v14[2] == 0x449C83E5Ei64
    && 7 * v14[0] + 15 * v14[1] - 3 * v14[3] - 2 * v14[2] == 0x7B13C2C5Di64 )
  {
    if ( 15 * v14[4] + 35 * v14[7] - v14[5] - v14[6] == 0xF919FB032i64
      && 38 * v14[6] + v14[4] + v14[7] - 24 * v14[5] == 0x7060508FAi64
      && 38 * v14[5] + 32 * v14[4] - v14[6] - v14[7] == 0x124F561560i64
      && v14[4] + 41 * v14[6] - v14[5] - 25 * v14[7] == 0x51C97373Ei64 )
    {
      j__printf("Correct!\n");
    }
    else
    {
      j__printf("Keep trying!\n");
    }
  }
  else
  {
    j__printf("Wrong!\n");
  }
  j__system("pause");
  return 0;
}

这里有个==sub_413BDB(v10, Destination, v15, v16);==函数,其实这个就是将16进制转换为10进制而已

 for ( k = 0; k < 8; ++k )
  {
    memset(Destination, 0, 50);
    sub_4130CD((int)&v13[5 * k], Destination);
    v10 = j__strlen(Destination);
    v4 = sub_413BDB(v10, Destination, v15, v16);
    v5 = k;
    LODWORD(v14[k]) = v4;
    HIDWORD(v14[v5]) = HIDWORD(v4);
  }

转为10进制后然后返回成字符串的形式

__int64 __cdecl sub_414A20(int a1, int a2)
{
  int j; // [esp+D4h] [ebp-30h]
  int i; // [esp+E0h] [ebp-24h]
  __int64 v5; // [esp+ECh] [ebp-18h]
  int v6; // [esp+FCh] [ebp-8h]
  __int64 v8; // [esp+114h] [ebp+10h]

  v8 = 0i64;
  for ( i = 0; *(_BYTE *)(i + a2); ++i )
  {
    switch ( *(_BYTE *)(i + a2) )               // 将16进制0-A转成0到16
    {
      case 'A':
        v6 = 10;
        break;
      case 'B':
        v6 = 11;
        break;
      case 'C':
        v6 = 12;
        break;
      case 'D':
        v6 = 13;
        break;
      case 'E':
        v6 = 14;
        break;
      case 'F':
        v6 = 15;
        break;
      default:
        v6 = *(char *)(i + a2) - '0';
        break;
    }
    v5 = 1i64;
    for ( j = 0; j < a1 - 1 - i; ++j )          // 16进制转10进制
      v5 = (unsigned __int64)((double)v5 * 16.0);
    v8 += v6 * v5;
  }
  return v8;
}

一看这一堆等式,第一个想到的就是z3,写个脚本

from z3 import *
v = [Int(('v%d'% i)) for i in range(8) ]
s = Solver()
s.add(v[2] + 7 * v[1] - 4 * v[0] - 2 * v[3] == 0x2060BF585)
s.add(5 * v[3] + 3 * v[2] - v[1] - 2 * v[0] == 0x164D5CCD0)
s.add(2 * v[1] + 8 * v[3] + 10 * v[0] - 5 * v[2] == 0x449C83E5E)
s.add(7 * v[0] + 15 * v[1] - 3 * v[3] - 2 * v[2] == 0x7B13C2C5D)
s.add(15 * v[4] + 35 * v[7] - v[5] - v[6] == 0xF919FB032)
s.add(38 * v[6] + v[4] + v[7] - 24 * v[5] == 0x7060508FA)
s.add(38 * v[5] + 32 * v[4] - v[6] - v[7] == 0x124F561560)
s.add(v[4] + 41 * v[6] - v[5] - 25 * v[7] == 0x51C97373E)
s.check()
m = s.model()

print(m)
for i in range(8):
    print(int(str(m[v[i]])))
result = [0] * 8
k = 0
for i in range(8):
    result[i] = str(hex(int(str(m[v[i]])))).replace("0x","")
    #change(result[i])
    s = result[i]
    for j in range(0,8,2):
        print(chr(int(s[j:j+2],16)),end='')
print(result)

运行结果

[v3 = 1194153047,
 v5 = 1095576901,
 v7 = 1448236925,
 v4 = 1245988943,
 v0 = 1230193475,
 v2 = 1515214414,
 v6 = 1414878529,
 v1 = 2069321031]
1230193475
2069321031
1515214414
1194153047
1245988943
1095576901
1414878529
1448236925
ISCC{WUGZPVNG-TWJDHOAM-ETUUAVRW}['49534343', '7b575547', '5a50564e', '472d5457', '4a44484f', '414d2d45', '54555541', '5652577d']

最终flag:ISCC{WUGZPVNG-TWJDHOAM-ETUUAVRW}

VigenereLike-250

ISCC-2022-reverse-mobile-部分wp_第15张图片

先查壳

ISCC-2022-reverse-mobile-部分wp_第16张图片

这题找到主函数乍一眼看得我一脸懵,后面一点一点分析看了俩小时给看出来了,都是一边看一边猜的

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 v3; // rdx
  bool v4; // bl
  __int64 v5; // rax
  __int64 v6; // rdx
  __int64 v7; // rax
  __int64 v8; // rdx
  __int64 v9; // rax
  __int64 v10; // rsi
  __int64 v11; // rdx
  __int64 v12; // rax
  char v14; // [rsp+Fh] [rbp-1E1h] BYREF
  char v15[32]; // [rsp+10h] [rbp-1E0h] BYREF
  char v16[32]; // [rsp+30h] [rbp-1C0h] BYREF
  int v17[8]; // [rsp+50h] [rbp-1A0h] BYREF
  char v18[32]; // [rsp+70h] [rbp-180h] BYREF
  char v19[32]; // [rsp+90h] [rbp-160h] BYREF
  char v20[32]; // [rsp+B0h] [rbp-140h] BYREF
  char v21[32]; // [rsp+D0h] [rbp-120h] BYREF
  char v22[32]; // [rsp+F0h] [rbp-100h] BYREF
  char v23[32]; // [rsp+110h] [rbp-E0h] BYREF
  char v24[32]; // [rsp+130h] [rbp-C0h] BYREF
  char v25[136]; // [rsp+150h] [rbp-A0h] BYREF
  unsigned __int64 v26; // [rsp+1D8h] [rbp-18h]

  v26 = __readfsqword(0x28u);
  v17[0] = 1;
  v17[1] = 2;
  v17[2] = 3;
  v17[3] = 4;
  v17[4] = 5;
  v17[5] = 6;
  v17[6] = 7;
  std::allocator<char>::allocator(v16, a2, a3);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v18, "ISCCYES", v16);
  std::allocator<char>::~allocator(v16);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v19);
  std::operator<<<std::char_traits<char>>(&std::cout, "id: ");// 输入id到v19中
  std::operator>><char>(&std::cin, v19);
  std::istream::get((std::istream *)&std::cin);
  sub_4A5A((__int64)v25, (__int64)v19);         // 对v19进行变换后存入v25中
  std::allocator<char>::allocator(v16, v19, v3);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(
    v20,
    "cfe6902ba6404626f1bcabc81e72767b",
    v16);
  std::allocator<char>::~allocator(v16);
  sub_4CE4(v24, v25);                           // 对v25进行变换后存入v24中
  v4 = (unsigned int)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(v24, v20) == 0;// id = cfe6902ba6404626f1bcabc81e72767b
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
  if ( v4 )
  {
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v21);
    v5 = std::operator<<<std::char_traits<char>>(&std::cout, "Please give me the flag:");
    std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
    std::operator>><char>(&std::cin, v21);
    std::allocator<char>::allocator(v16, v21, v6);// 输入flag到v21中
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v24, "{", v16);// 取{位置的指针
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v23, v21);
    sub_2A5F(v15, v23, v24);                    // 取flag中{之前的字符串到v15中,v24感觉像个临时变量,啥东西都往里面存
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v23);
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
    std::allocator<char>::~allocator(v16);
    v7 = sub_38CA(v15);                         // v7 = ISCC
    if ( (unsigned __int8)sub_38F4(v7, "ISCC") )// 比较
    {
      std::allocator<char>::allocator(&v14, "ISCC", v8);
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v24, "}", &v14);// 取}位置的指针
      v9 = sub_391E(v15);                   //
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v23, v9);
      sub_2A5F(v16, v23, v24);
      v10 = sub_38CA(v16);                      // v10和v16还是flag
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(v21, v10);// 拷贝给v21
      sub_3704(v16);
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v23);
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
      std::allocator<char>::~allocator(&v14);
      std::allocator<char>::allocator(&v14, v10, v11);
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v23, "4", &v14);// 取4位置的指针
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v22, v19);// v19是id,将id拷贝给v22
      sub_2A5F(v16, v22, v23);                  // 取id中4之前的字符串到v16
      v12 = sub_38CA(v16);
      std::operator+<char>(v24, v21, v12);      // 将v21和v12拷贝到v24中
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(v21, v24);// 将v24中的内容拷贝到v21
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
      sub_3704(v16);
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v22);
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v23);
      std::allocator<char>::~allocator(&v14);
      sub_2914(v21, v17);                       // 加密
      sub_29C9(v24, v21, v18);                  // base加密
      if ( (unsigned int)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(
                           v24,
                           "rJFsLqVyFKZ7nl1Zgrs4C LsCGyEjHm6HPmmCrv=") )// flag内容
        std::operator<<<std::char_traits<char>>(&std::cout, "Wrong!");
      else
        std::operator<<<std::char_traits<char>>(&std::cout, "Correct!");
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
    }
    else
    {
      std::operator<<<std::char_traits<char>>(&std::cout, "head! head! head!");
    }
    sub_3704(v15);
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v21);
  }
  else
  {
    std::operator<<<std::char_traits<char>>(&std::cout, "You don't have permission to acess the file!");
  }
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v20);
  sub_3636(v25);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v19);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v18);
  return 0LL;
}

仔细分析一下,大概流程是这样的:先输入id -> 对id进行变换 -> 输入flag -> 提取出{} 中的内容 -> 取一段变换后的id,将其添加到前一步得到的字符串末尾->进行加密

这里有两个加密函数,从后往前分析

ISCC-2022-reverse-mobile-部分wp_第17张图片

先分析sub_29C9(v24, v21, v18);

// a3 = "ISCCYES"
__int64 __fastcall sub_29C9(__int64 a1, __int64 a2, __int64 a3)
{
  char v5[40]; // [rsp+20h] [rbp-40h] BYREF
  unsigned __int64 v6; // [rsp+48h] [rbp-18h]

  v6 = __readfsqword(0x28u);
  sub_27C6(v5, a2);
  sub_2569(a1, v5, a3);                         // v5为flag base加密后的结果
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v5);
  return a1;
}

sub_27C6(v5, a2);是魔改的base64加密
aAbcdefghijklmn db ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’

__int64 __fastcall sub_27C6(__int64 a1, __int64 a2)
{
  int v3; // [rsp+14h] [rbp-1Ch]
  int v4; // [rsp+18h] [rbp-18h]
  int i; // [rsp+1Ch] [rbp-14h]

  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(a1);
  v3 = 0;
  v4 = -6u;
  for ( i = 0;
        i < (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a2);
        ++i )
  {
    v3 = (v3 << 8)
       + *(char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
    for ( v4 += 8; v4 >= 0; v4 -= 6 )
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::push_back(
        a1,
        (unsigned int)aAbcdefghijklmn[(v3 >> v4) & 0x3F]);
  }
  if ( v4 >= -5 )
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::push_back(
      a1,
      (unsigned int)aAbcdefghijklmn[(v3 << 8 >> (v4 + 8)) & 0x3F]);
  while ( (std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a1) & 3) != 0 )
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::push_back(a1, 61LL);
  return a1;
}

简洁一点写是这样的,看不出来没关系,带个字符串直接给他运行一下就清楚了

v3 = 0;
v4 = -6;
a2[] = {};
for (i = 0 ; i < strlen(a2) ; i++)
{
	v3 = (v3 << 8) + a2[i]
	for (v4 += 8; v4 >=0 ; v4 -= 6)
	{
		a2 += base[(v3 >> v4) & 0x3F];
	}
	
}
if (v4 > -5)
	a2 += base[(v3 << 8 >> (v4 + 8 )) &  0x3F];
a2 += '='

每三位字符加密后得到四位字符,最后用“=”填充

ISCC-2022-reverse-mobile-部分wp_第18张图片

可以写出一个爆破脚本出来

v3 = 0
v4 = -6
i = 0
for i in range(0,len(flag_encode_2),4):
    for j1 in range(32,128):      #爆破第一位
        temp1 = ((v3 << 8) + j1) % (2**32)
        if flag_encode_2[i] == base[(temp1 >> 2) & 0x3F]:
            #if i == 20 : print("temp1 = ",temp1)
            for j2 in range(32,128):     #爆破第二位
                temp2 = ((temp1 << 8) + j2) % (2 ** 32)
                if flag_encode_2[i + 1] == base[(temp2 >> 4) &0x3F]:
                    #if i == 20 : print("temp2 = ",temp2)
                    if i <= 32:
                        for j3 in range(32,128):
                            temp3 = ((temp2 << 8) + j3) % (2 ** 32)
                            if (flag_encode_2[i + 2] == base[(temp3 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == base[temp3 & 0x3F]):
                                flag_encode_1.append(j1)
                                flag_encode_1.append(j2)
                                flag_encode_1.append(j3)
                                v3 = temp3
                                print("i=",i,"v3=",v3)
                    else:
                        temp3 =temp2
                        if (flag_encode_2[i + 2] == base[(temp3 << 8 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == ord('=')):
                            flag_encode_1.append(j1)
                            flag_encode_1.append(j2)
                            v3 = temp3
                            print("i=",i,"v3=",v3)

sub_2569(a1, v5, a3); 是做的一个替换加密

__int64 __fastcall sub_2569(__int64 a1, __int64 a2, __int64 a3)
{
  __int64 v3; // rdx
  char *v4; // rax
  char *v6; // rax
  int v7; // ebx
  char *v8; // rax
  unsigned __int64 v9; // rbx
  unsigned __int64 v10; // rax
  _BYTE *v11; // rbx
  char v14; // [rsp+23h] [rbp-4Dh] BYREF
  int i; // [rsp+24h] [rbp-4Ch]
  int v16; // [rsp+28h] [rbp-48h]
  int v17; // [rsp+2Ch] [rbp-44h]
  char v18[40]; // [rsp+30h] [rbp-40h] BYREF
  unsigned __int64 v19; // [rsp+58h] [rbp-18h]

  v19 = __readfsqword(0x28u);
  v16 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a2);// v16为flag的长度
  v17 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a3);// a3 = "ISCCYES"
  std::allocator<char>::allocator(&v14, a2, v3);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(a1, v16, 120LL, &v14);
  std::allocator<char>::~allocator(&v14);
  sub_2447(v18, a2, a3);                        // 将a3的值循环赋值给v18
  for ( i = 0; i < v16; ++i )
  {
    v4 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
    if ( isalnum(*v4)
      || *(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i) == 32 )// 如果是数字或者字母以及空格
    {
      v6 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
      v7 = sub_23D9((unsigned int)*v6);         // 返回和在unk_10280中相等的数的下标
      v8 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
                     (__int64)v18,
                     i);
      v9 = (int)(v7 + sub_23D9((unsigned int)*v8));
      v10 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(&unk_10280);
      v11 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
                       (__int64)&unk_10280,
                       v9 % v10);
    }
    else
    {
      v11 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
    }
    *(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a1, i) = *v11;
  }
  *(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a1, i) = 0;
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v18);
  return a1;
}

依旧是可以写个爆破脚本出来

def find(temp):
    if(temp in unk_10280):
        return unk_10280.index(temp)
    else:
        return -1
for i in range(len(Str)):
    for j in range(32,128):
        if (j in range(48,58)) or (j in range(65,91)) or (j in range(97,123)) or (j == ord(" ")):
            v7 = find(j)
            v8 = v18[i]
            v9 = v7 + find(v8)
            v11 = unk_10280[v9 % len(unk_10280)]
        else:
            v11 = j
        if v11 == Str[i]:
            flag_encode_2.append(j)
            print(i)
            break

unk_10280的值,直接点击跳转是看不到unk_10280的值的,需要按x查看这个数组的交叉引用,然后一个一个找到给它赋值的地方

ISCC-2022-reverse-mobile-部分wp_第19张图片

sub_2914(v21, v17) 这个就比较简单了,只是做了一个异或变换

v17 = [1,2,3,4,5,6,7]
for i in range(len(flag_encode_1)):
    flag_encode_1[i] = flag_encode_1[i] ^ v17[i % 7]
    print(chr(flag_encode_1[i]),end="")
    

然后得出总脚本

import base64
unk_10280 = [ord(i) for i in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "]
base = [ord(i) for i in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]

Str = [ord(i) for i in "rJFsLqVyFKZ7nl1Zgrs4C LsCGyEjHm6HPmmCrv="]
t = [ord(i) for i in "ISCCYES"]
v18 = []
flag = []
flag_encode_1 = []
flag_encode_2 = []
for i in range(len(Str)):
    v18.append(t[i % 7])
print("v18 = ",v18)
#解密1,爆破
def find(temp):
    if(temp in unk_10280):
        return unk_10280.index(temp)
    else:
        return -1
for i in range(len(Str)):
    for j in range(32,128):
        if (j in range(48,58)) or (j in range(65,91)) or (j in range(97,123)) or (j == ord(" ")):
            v7 = find(j)
            v8 = v18[i]
            v9 = v7 + find(v8)
            v11 = unk_10280[v9 % len(unk_10280)]
        else:
            v11 = j
        if v11 == Str[i]:
            flag_encode_2.append(j)
            print(i)
            break
print("flag_encode_2 = ",flag_encode_2)

#第二次解密
v3 = 0
v4 = -6
i = 0
for i in range(0,len(flag_encode_2),4):
    for j1 in range(32,128):      #爆破第一位
        temp1 = ((v3 << 8) + j1) % (2**32)
        if flag_encode_2[i] == base[(temp1 >> 2) & 0x3F]:
            #if i == 20 : print("temp1 = ",temp1)
            for j2 in range(32,128):     #爆破第二位
                temp2 = ((temp1 << 8) + j2) % (2 ** 32)
                if flag_encode_2[i + 1] == base[(temp2 >> 4) &0x3F]:
                    #if i == 20 : print("temp2 = ",temp2)
                    if i <= 32:
                        for j3 in range(32,128):
                            temp3 = ((temp2 << 8) + j3) % (2 ** 32)
                            if (flag_encode_2[i + 2] == base[(temp3 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == base[temp3 & 0x3F]):
                                flag_encode_1.append(j1)
                                flag_encode_1.append(j2)
                                flag_encode_1.append(j3)
                                v3 = temp3
                                print("i=",i,"v3=",v3)
                    else:
                        temp3 =temp2
                        if (flag_encode_2[i + 2] == base[(temp3 << 8 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == ord('=')):
                            flag_encode_1.append(j1)
                            flag_encode_1.append(j2)
                            v3 = temp3
                            print("i=",i,"v3=",v3)
print("flag_encode_1 = ",flag_encode_1)
v17 = [1,2,3,4,5,6,7]
for i in range(len(flag_encode_1)):
    flag_encode_1[i] = flag_encode_1[i] ^ v17[i % 7]
    print(chr(flag_encode_1[i]),end="")


运行结果:

Reverse-aSOd9FAV-1l8P2GGVTIPO

然后这段字符是加了一部分的id在里面的,但是id的加密太麻烦了,看不出来,也不知道加了几位到后面,所以只需要从后往前依次减去一位字符,然后提交看对不对

最终测试的结果是减去了四位字符,最终flag: ISCC{Reverse-aSOd9FAV-1l8P2GGV}

Bob’s Code-300

ISCC-2022-reverse-mobile-部分wp_第20张图片

这题确实挺简单的,看懂逻辑就行

ISCC-2022-reverse-mobile-部分wp_第21张图片

还是先定位到主函数,然后分析一下(其实也没啥好分析的

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  int v4; // [esp+DCh] [ebp-E98h]
  int v5; // [esp+E8h] [ebp-E8Ch]
  char Str2[1112]; // [esp+F4h] [ebp-E80h] BYREF
  char flag_encode_4[520]; // [esp+54Ch] [ebp-A28h] BYREF
  char flag_encode_3[520]; // [esp+754h] [ebp-820h] BYREF
  char flag_encode_2[520]; // [esp+95Ch] [ebp-618h] BYREF
  char flag_encode_1[520]; // [esp+B64h] [ebp-410h] BYREF
  char flag[516]; // [esp+D6Ch] [ebp-208h] BYREF

  memset(flag, 0, 512);
  memset(flag_encode_1, 0, 512);
  memset(flag_encode_2, 0, 512);
  memset(flag_encode_3, 0, 512);
  memset(flag_encode_4, 0, 512);
  memset(&Str2[592], 0, 512);
  memset(&Str2[72], 0, 512);
  j__printf(&byte_430F98);
  sub_411721((va_list)"%s", (char)flag);        // 输入flag到Str中
  strcpy(Str2, ".W1BqthGbfjhXoLGaBiU1f.2XRoFtXXG15VMBuoM1VojNpgMl4XivlghXwoF0.");
  v5 = j__strlen(flag);
  sub_4116C7((int)flag, v5, (int)flag_encode_1, 0);// base64加密
  v4 = j__strlen(flag_encode_1);
  sub_411389((int)flag_encode_1, v4, (int)flag_encode_2, 1);// 变表base64加密
  sub_411023((int)flag_encode_2, (int)flag_encode_3, 46, 0);// 在下标为0的位置加一个.
  sub_411023((int)flag_encode_3, (int)flag_encode_4, 46, 22);// 在下标为22的位置加一个.
  sub_4116E0(flag_encode_4, 2);                 // 字母表往后循环2位
  if ( !j__strcmp(flag_encode_4, Str2) )
    j__printf("flag is Correct!\n");
  else
    j__printf("flag is wrong!\n");
  j__system("pause");
  return 0;
}

写出脚本,第一次base64就是正常的base64加密,所以base1是多余的,然后要去掉0位和22位的那两个 .,我就手动去掉了

import base64

#base表
base1="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
base2 = [ord(i) for i in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"]
#将base2的表进行还原
for i in range(5,19):   
    temp = base2[i]
    base2[i] = base2[i + 26]
    base2[i+26]  = temp

print("base2=",base2)
Str2 = list("W1BqthGbfjhXoLGaBiU1f2XRoFtXXG15VMBuoM1VojNpgMl4XivlghXwoF0.") 
print("Str2=",Str2)
flag = ""   #存储flag
flag_encode_1 = []
flag_encode_2 = [0]*len(Str2)
flag_encode_3 = [0]*len(Str2)
flag_encode_4 = [0]*len(Str2)

#第一次解密,往前循环两位
for i in range(len(Str2)):
    t = ord(Str2[i])
    if( t >= 97 ) and (t <= 122):
        flag_encode_4[i]=(t - 2 - 97) % 26 + 97
    elif(t >= 65) and (t <= 90):
        flag_encode_4[i] = (t - 2 - 65) % 26 + 65
    else:
        flag_encode_4[i] = t
print("flag_encode_4 = ",flag_encode_4)

flag_encode_2 = flag_encode_4
print("flag_encode_2=",flag_encode_2)
#第四次解密    变表base
for i in range(0,len(Str2),4):   #四位四位加密
    for j1 in range(32,127):   #爆破第一位
        if base2[ (j1 & 0xFC) >> 2] == flag_encode_2[i]:  #第一位相等
            #if i==56: print(56)
            v9 = 16 * (j1 & 3)
            for j2 in range(32,127):   #爆破第二位
                if flag_encode_2[i + 1] == base2[((j2 & 0xF0) >> 4) + v9]:
                    #if i==56: print(56)
                    v10 = 4 * (j2 & 0xF)
                    if i <= 52:
                        for j3 in range(32,127):   #爆破第三位
                            if (flag_encode_2[i + 2] == base2[v10 + ((j3 & 0xC0) >> 6 ) ] and (flag_encode_2[i + 3] == base2[j3 & 0x3F])):
                                if i==56: print(56)
                                print(i)
                                flag_encode_1.append(j1)
                                flag_encode_1.append(j2)
                                flag_encode_1.append(j3)
                    else:
                        if (flag_encode_2[i+2] == base2[v10]) and (flag_encode_2[i+3] == ord(".")):
                            print(i)
                            flag_encode_1.append(j1)
                            flag_encode_1.append(j2)                          
print("flag_encode_1 = ",flag_encode_1)
for i in range(len(flag_encode_1)):
    flag+=chr(flag_encode_1[i])
print(base64.b64decode(flag))

运行结果:

base2= [65, 66, 67, 68, 69, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95]
Str2= ['W', '1', 'B', 'q', 't', 'h', 'G', 'b', 'f', 'j', 'h', 'X', 'o', 'L', 'G', 'a', 'B', 'i', 'U', '1', 'f', '2', 'X', 'R', 'o', 'F', 't', 'X', 'X', 'G', '1', '5', 'V', 'M', 'B', 'u', 'o', 'M', '1', 'V', 'o', 'j', 'N', 'p', 'g', 'M', 'l', '4', 'X', 'i', 'v', 'l', 'g', 'h', 'X', 'w', 'o', 'F', '0', '.']
flag_encode_4 =  [85, 49, 90, 111, 114, 102, 69, 122, 100, 104, 102, 86, 109, 74, 69, 121, 90, 103, 83, 49, 100, 50, 86, 80, 109, 68, 114, 86, 86, 69, 49, 53, 84, 75, 90, 115, 109, 75, 49, 84, 109, 104, 76, 110, 101, 75, 106, 52, 86, 103, 116, 106, 101, 102, 86, 117, 109, 68, 48, 46]
flag_encode_2= [85, 49, 90, 111, 114, 102, 69, 122, 100, 104, 102, 86, 109, 74, 69, 121, 90, 103, 83, 49, 100, 50, 86, 80, 109, 68, 114, 86, 86, 69, 49, 53, 84, 75, 90, 115, 109, 75, 49, 84, 109, 104, 
76, 110, 101, 75, 106, 52, 86, 103, 116, 106, 101, 102, 86, 117, 109, 68, 48, 46]
0
4
8
12
16
20
24
28
32
36
40
44
48
52
56
flag_encode_1 =  [83, 86, 78, 68, 81, 51, 116, 113, 85, 50, 49, 50, 100, 107, 53, 119, 101, 105, 48, 52, 85, 84, 77, 121, 78, 70, 82, 50, 77, 83, 48, 121, 77, 122, 66, 120, 84, 107, 73, 120, 85, 110, 48, 61]
b'ISCC{jSmvvNpz-8Q324Tv1-230qNB1R}'

最终flag:ISCC{jSmvvNpz-8Q324Tv1-230qNB1R}

Ruststr-300

MOBILE - A

代码逻辑挺简单的,分析如下

  private boolean Jformat(String arg10) {
        String v0 = "";
        String v1 = "\n";
        int v2 = arg10.lastIndexOf("_");   //取得最后一个"_"的下标
        if(v2 == -1) {
            return 0;
        }

        if(arg10.length() < 10) {  // flag长度大于10
            return 0;
        }

        int v4 = 5;
        if(!arg10.substring(0, v4).equals("ISCC{")) {
            return 0;
        }

        if(arg10.charAt(arg10.length() - 1) != 0x7D) {  // 右括号
            return 0;
        }

        ++v2;
        //从截取v2到字符串末尾调用Jlast加密,解密的结果为kit
        if(!this.Jlast(arg10.substring(v2, arg10.length() - 1))) {  // 最后一个单词为 kit
            return 0;
        }

        try {   //AES加密
            byte[] v5 = new String(Base64.encode("K@e2022%%y".getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).getBytes(StandardCharsets.UTF_8);  // 将 \n 替换
            byte[] v7 = new String(Base64.encode("I&V2022***".getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).getBytes(StandardCharsets.UTF_8);
            byte[] v10_1 = arg10.substring(v4, v2).getBytes(StandardCharsets.UTF_8);
            SecretKeySpec v2_1 = new SecretKeySpec(v5, "AES");
            IvParameterSpec v4_1 = new IvParameterSpec(v7);
            Cipher v5_1 = Cipher.getInstance("AES/CBC/PKCS7Padding");
            v5_1.init(1, ((Key)v2_1), ((AlgorithmParameterSpec)v4_1));
            if(!new String(Base64.encode(Base64.encodeToString(v5_1.doFinal(v10_1), 2).getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).equals("SS90YmE3M2hUc0lVVCs1ZkZhWW0vNGl1dVNPWkc0UVdTaXlXN29GcDRvdz0=")) {
                return 0;
            }
        }
        catch(Exception v10) {
            v10.printStackTrace();
            return 0;
        }

        return 1;
    }

    private boolean Jlast(String arg8) {
        try {
            MessageDigest v1 = MessageDigest.getInstance("MD5");
            new BASE64Encoder();
            arg8 = BASE64Encoder.encode(v1.digest(arg8.getBytes("utf-8")));
            if(arg8.length() != 24) {  // MD5加密再base64加密后长度为24
                return 0;
            }

            char[] v1_1 = new char[arg8.length()];
            int v2 = 5;
            int v3 = 0;
            int v4 = 0;
            while(v2 >= 0) {
                int v6 = 3;
                if(v3 == 0) {
                    while(v6 >= 0) {
                        v1_1[v4] = arg8.charAt(v6 * 6 + v2);
                        ++v4;
                        --v6;
                    }

                    v3 = 1;
                }
                else {
                    for(v3 = 0; v3 <= v6; ++v3) {
                        v1_1[v4] = arg8.charAt(v3 * 6 + v2);
                        ++v4;
                    }

                    v3 = 0;
                }

                --v2;
            }

            if(!String.valueOf(v1_1).equals("=emd9M4=wlKEBdOFiCJ6/GTB")) {
                return 0;
            }

从截取v2到字符串末尾调用Jlast加密,解密的结果为kit

ISCC-2022-reverse-mobile-部分wp_第22张图片

写个解密脚本

#include 
#include 
#include 

int main()
{
  char Str[] = "=emd9M4=wlKEBdOFiCJ6/GTB";
  char Str2[33];
  int v2 = 5;
  int v3 = 0;
  int v4 = 0;
  char flag[33];
  while(v2 >= 0 )
  {
      int v6 = 3;
      if(v3 == 0)
      {
          while(v6 >=0 )
          {

              flag[v6 * 6 + v2] = Str[v4++];
              --v6;
          }
          v3 = 1;
      }
      else
      {
          for(v3 = 0; v3 <= v6; ++v3)
          {
              flag[v3 * 6 + v2] = Str[v4++];

          }
          v3 = 0;
      }
      --v2;
  }
  for(int  i = 0 ; i <  strlen(Str); i++)
  {
      printf("%c",flag[i]);
  }
  return 0;
}

将得到的结果进行md5解密,得到kit

ISCC-2022-reverse-mobile-部分wp_第23张图片

然后看最后的解密条件,逆着来就行

  if(!new String(Base64.encode(Base64.encodeToString(v5_1.doFinal(v10_1), 2).getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).equals("SS90YmE3M2hUc0lVVCs1ZkZhWW0vNGl1dVNPWkc0UVdTaXlXN29GcDRvdz0=")) 

base64解密的结果
ISCC-2022-reverse-mobile-部分wp_第24张图片
直接上脚本

import base64
from Crypto.Cipher import AES

s = "SS90YmE3M2hUc0lVVCs1ZkZhWW0vNGl1dVNPWkc0UVdTaXlXN29GcDRvdz0="
s1 = base64.b64decode(s.encode('utf-8'))
s2 = base64.b64decode(s1)  #s2就是密文
print("s2=",s2)
#password = b'S0BlMjAyMiUleQ=='  #秘钥
password = base64.b64encode("K@e2022%%y".encode('utf-8'))

#iv = b'SSZWMjAyMioqKg=='  #偏移量
iv = base64.b64encode("I&V2022***".encode('utf-8'))
aes = AES.new(password,AES.MODE_CBC,iv)

text = aes.decrypt(s2)
print(text)
text1=bytes.decode(text).rstrip("\x01").\
            rstrip("\x02").rstrip("\x03").rstrip("\x04").rstrip("\x05").\
            rstrip("\x06").rstrip("\x07").rstrip("\x08").rstrip("\x09").\
            rstrip("\x0a").rstrip("\x0b").rstrip("\x0c").rstrip("\x0d").\
            rstrip("\x0e").rstrip("\x0f").rstrip("\x10")
print(text1)

最终flag:

ISCC-2022-reverse-mobile-部分wp_第25张图片

MOBILE - B

MOBILE - C

你可能感兴趣的:(#,CTF比赛实战,reverse,ISCC,2022)