Reverse(五)

BUUCTF

1. xor

exeinfope查看无壳64位,ida64位打开,定位到main的伪C代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int i; // [rsp+2Ch] [rbp-124h]
  char __b[264]; // [rsp+40h] [rbp-110h] BYREF

  memset(__b, 0, 0x100uLL);
  printf("Input your flag:\n");
  get_line(__b, 256LL);
  if ( strlen(__b) != 33 )
    goto LABEL_7;
  for ( i = 1; i < 33; ++i )
    __b[i] ^= __b[i - 1];
  if ( !strncmp(__b, global, 0x21uLL) )
    printf("Success");
  else
LABEL_7:
    printf("Failed");
  return 0;
}

可以看到输入的__b经过各位异或后和global对比,相同即可成功

查看global变量,正好33位,写出python逆向解密的脚本

data = ['f', 0xA, 'k', 0xC, 'w', '&', 'O', '.', '@', 0x11, 'x', 0xD, 'Z', ';', 'U', 0x11, 'p', 0x19, 'F', 0x1F, 'v',
        '"', 'M', '#', 'D', 0xE, 'g', 6, 'h', 0xF, 'G', '2', 'O']
flag = 'f'
for i in range(0, len(data)):
    if isinstance(data[i], str):
        data[i] = ord(data[i])
for i in range(1, len(data)):
    flag += chr(data[i] ^ data[i - 1])
print(flag)

得到flag{QianQiuWanDai_YiTongJiangHu}

也可以shift+E选中C unsigned char array(hex),可以直接 全部复制为十或十六进制

2. helloworld

使用ida打开apk文件时,开始要注意选择文件格式

image-20220328151036869.png

shift+F12查找跟flag相关的字符串即可

3. reverse3

无壳32位,ida打开查看字符串,看到了和base64相关的信息,初步猜想有这方面的加密解密

image-20220328153148029.png

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  size_t v3; // eax
  const char *v4; // eax
  size_t v5; // eax
  char v7; // [esp+0h] [ebp-188h]
  char v8; // [esp+0h] [ebp-188h]
  signed int j; // [esp+DCh] [ebp-ACh]
  int i; // [esp+E8h] [ebp-A0h]
  signed int v11; // [esp+E8h] [ebp-A0h]
  char Destination[108]; // [esp+F4h] [ebp-94h] BYREF
  char Str[28]; // [esp+160h] [ebp-28h] BYREF
  char v14[8]; // [esp+17Ch] [ebp-Ch] BYREF

  for ( i = 0; i < 100; ++i )
  {
    if ( i >= 0x64 )
      j____report_rangecheckfailure();
    Destination[i] = 0;
  }
  sub_41132F("please enter the flag:", v7);
  sub_411375("%20s", Str);
  v3 = j_strlen(Str);
  v4 = sub_4110BE(Str, v3, v14);
  strncpy(Destination, v4, 0x28u);
  v11 = j_strlen(Destination);
  for ( j = 0; j < v11; ++j )
    Destination[j] += j;
  v5 = j_strlen(Destination);
  if ( !strncmp(Destination, Str2, v5) )
    sub_41132F("rigth flag!\n", v8);
  else
    sub_41132F("wrong flag!\n", v8);
  return 0;
}

v4 = sub_4110BE(Str, v3, v14);中的sub_4110BE是base64加密函数,然后for循环对每一位进行了移位操作后与Str2对比,查看Str2

image-20220328155715289.png

首先脚本解密移位

data = 'e3nifIH9b_C@n@dH'
k = 0
flag = ''
for i in data:
    flag += chr(ord(i) - k)
    k += 1
print(flag)

得e2lfbDB2ZV95b3V9,再base64解密得{i_l0ve_you}

4. 不一样的flag

32位无壳,

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  _BYTE v3[29]; // [esp+17h] [ebp-35h] BYREF
  int v4; // [esp+34h] [ebp-18h]
  int v5; // [esp+38h] [ebp-14h] BYREF
  int i; // [esp+3Ch] [ebp-10h]
  _BYTE v7[12]; // [esp+40h] [ebp-Ch] BYREF

  __main();
  v3[26] = 0;
  *(_WORD *)&v3[27] = 0;
  v4 = 0;
  strcpy(v3, "*11110100001010000101111#");
  while ( 1 )
  {
    puts("you can choose one action to execute");
    puts("1 up");
    puts("2 down");
    puts("3 left");
    printf("4 right\n:");
    scanf("%d", &v5);
    if ( v5 == 2 )
    {
      ++*(_DWORD *)&v3[25];
    }
    else if ( v5 > 2 )    // 大于2的输入为3、4才可
    {
      if ( v5 == 3 )
      {
        --v4;
      }
      else
      {
        if ( v5 != 4 )
LABEL_13:
          exit(1);
        ++v4;
      }
    }
    else
    {
      if ( v5 != 1 )
        goto LABEL_13;
      --*(_DWORD *)&v3[25];
    }
    for ( i = 0; i <= 1; ++i )
    {
      if ( *(int *)&v3[4 * i + 25] < 0 || *(int *)&v3[4 * i + 25] > 4 )
        exit(1);
    }
    if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 49 )
      exit(1);
    if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 35 )
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }
  }
}

转换十进制数为char,可以看出最后要到#位置,如果到了1就会失败退出

image-20220328160934010.png

呃,貌似是走迷宫,就是这串字符*11110100001010000101111#排列成5*5

*1111
01000
01010
00010
1111#

这么走flag就是222441144222

image-20220328162107313.png

5. SimpleRev

无壳64位,ida64查看伪代码

image-20220328171205967.png

第一页没什么线索,关键在于进入了Decry的函数,这个函数里有了flag和输入的对比

unsigned __int64 Decry()
{
  char v1; // [rsp+Fh] [rbp-51h]
  int v2; // [rsp+10h] [rbp-50h]
  int v3; // [rsp+14h] [rbp-4Ch]
  int i; // [rsp+18h] [rbp-48h]
  int v5; // [rsp+1Ch] [rbp-44h]
  char src[8]; // [rsp+20h] [rbp-40h] BYREF
  __int64 v7; // [rsp+28h] [rbp-38h]
  int v8; // [rsp+30h] [rbp-30h]
  __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
  int v10; // [rsp+50h] [rbp-10h]
  unsigned __int64 v11; // [rsp+58h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  *(_QWORD *)src = 0x534C43444ELL;
  v7 = 0LL;
  v8 = 0;
  v9[0] = 0x776F646168LL;
  v9[1] = 0LL;
  v10 = 0;
  text = (char *)join(key3, v9);
  strcpy(key, key1);
  strcat(key, src);
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:");
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == 10 )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
        {
          str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
          ++v3;
        }
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
        ++v3;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v11;
}

定位到对比的是text和str2

先看text = (char *)join(key3, v9);,由key3和v9组成

image-20220328172137704.png

key3='kills',v9[0] = 0x776F646168LL;转换为char同时大端改小端,v9=hadow,合起来text='killshadow',挺对头的

再看str2,定位到包含str2的部分代码

image-20220328171459233.png

看到了97、26等貌似和大小写有关的字眼,同时关键在key字符串,定位到key

image-20220328174022769.png

key1先复制到key,key再和src组合起来,查看key1和src的值

image-20220328173627938.png

key1='ADSFK'

image-20220328173704938.png

src='SLCDN',结合大端改小端,得到key='ADSFKNDCLS',又经过28-34行转换为小写key='adsfkndcls'

下面分析如何输入生成str2,str2就是text的值

image-20220328174937604.png

str2 = 'killshadow'
key = 'adsfkndcls'
input = ''
for i in range(len(str2)):
    for j in range(26):
        if str2[i] == chr((j + 65 - 39 - ord(key[i % len(key)]) + 97) % 26 + 97):
            input += chr(j+65)
print(input)

flag{KLDQCUDFZO}

最后修改:2023 年 12 月 14 日
如果觉得我的文章对你有用,请随意赞赏