[BUUCTF] REVERSE —— Сингал [Wangding Cup 2020 Blue Dragon Group]

[Wangding Cup 2020 Blue Dragon Group] сингл

приложение

шаг

  1. Регулярная проверка, 32-битная программа, без оболочки
    Вставьте описание изображения сюда
  2. Попробуйте программу локально
    Вставьте описание изображения сюда
  3. Загружается 32-битный ida. Сначала найдите основную функцию и определите стиль строки флага. Flag {……} В
    Вставьте описание изображения сюда
    соответствии со строкой подсказки точки ввода найдите соответствующую функцию и убедитесь, что длина строки составляет 15,
    Вставьте описание изображения сюда
    щелкните правой кнопкой мыши функцию и найдите вызов. Место этой функции переходит к функции vm_operad (). Посмотрите на основную функцию, чтобы знать, что параметр v4 в vm_operad вызывает функцию qmemcpy в верхней строке. Baidu говорит, что qmemcpy = memcpy в обратном направлении - это функция копирования memcpy на языке C., Копировать 0x1C8 байтов данных из unk_403040 в v4
    unk_403040 Этот адрес имеет много копий данных 0x1C8
    Вставьте описание изображения сюда
    выбран в 0x403208 , shift + e преобразуется в массив из
    Вставьте описание изображения сюда
    4 байтов, равных int, процессор interl - это память с прямым порядком байтов, в самый раз. Значение массива a1 - это шестнадцатеричное число перед тремя 00. Чтобы разобраться,
    v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1]
    обратите внимание на порядок младшего байта, когда 32 -битная программа сохраняется. Я не буду менять порядок следования. Давайте поищем обработку в памяти. Некоторые данные в то время

Затем вызовите массив и 114 введите функцию vm_operad

int __cdecl vm_operad(int *a1, int _114)
{
  int result; // eax
  char Str[200]; // [esp+13h] [ebp-E5h] BYREF
  char v4; // [esp+DBh] [ebp-1Dh]
  int v5; // [esp+DCh] [ebp-1Ch]
  int v6; // [esp+E0h] [ebp-18h]
  int v7; // [esp+E4h] [ebp-14h]
  int v8; // [esp+E8h] [ebp-10h]
  int v9; // [esp+ECh] [ebp-Ch]

  v9 = 0;
  v8 = 0;
  v7 = 0;
  v6 = 0;
  v5 = 0;
  while ( 1 )
  {
    result = v9;
    if ( v9 >= _114 )
      return result;
    switch ( a1[v9] )
    {
      case 1:
        Str[v6 + 100] = v4;
        ++v9;
        ++v6;
        ++v8;
        break;
      case 2:
        v4 = a1[v9 + 1] + Str[v8];
        v9 += 2;
        break;
      case 3:
        v4 = Str[v8] - LOBYTE(a1[v9 + 1]);
        v9 += 2;
        break;
      case 4:
        v4 = a1[v9 + 1] ^ Str[v8];
        v9 += 2;
        break;
      case 5:
        v4 = a1[v9 + 1] * Str[v8];
        v9 += 2;
        break;
      case 6:
        ++v9;
        break;
      case 7:
        if ( Str[v7 + 100] != a1[v9 + 1] )
        {
          printf("what a shame...");
          exit(0);
        }
        ++v7;
        v9 += 2;
        break;
      case 8:
        Str[v5] = v4;
        ++v9;
        ++v5;
        break;
      case 10:
        read(Str);
        ++v9;
        break;
      case 11:
        v4 = Str[v8] - 1;
        ++v9;
        break;
      case 12:
        v4 = Str[v8] + 1;
        ++v9;
        break;
      default:
        continue;
    }
  }
}

Когда значение равно 7, значение массива str будет сравниваться со следующим битом массива a1, и равенство продолжится, не дожидаясь ошибки. Число после 7 - это значение, которое необходимо сравнить с правильным вводом после шифрования, просто значение 7 находится в конце массива a1, извлеките эту строку значений

str=[]
a1=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(a1)):
          if a1[i]==7:
                    str.append(a1[i+1])

print(a1)

Вставьте описание изображения сюда
str = [34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
Тогда другие варианты case в switch - это операции с массивом str и, наконец, получение Значение в str, обратный алгоритм решения

В нем есть функция под названием LOBYTE. Когда я это сделал, я зашел в Baidu. Некоторые сказали, что это самая правая, а некоторые сказали, что это четыре цифры справа. Нет единого оператора. Я нашел wp других мастеров и сказал, что это функция ida. Игнорируйте эту функцию. rax - 64-битный регистр, eax - 32-битный регистр, ax - 16-битный регистр, al - младшие 8 бит регистра ax, а ah - старшие 8 бит регистра ax.
Вставьте описание изображения сюда

a1=[]
v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(v4)):
          if v4[i]==7:
                    a1.append(v4[i+1])
#print(a1)

a1 = [34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
a1.reverse()
v4.reverse()

v9 = 0
us = 0
v5 = 0
flag = []
for i in range(0, len(v4)):
    if i == len(v4) - 1:
        flag.append(us)

    if v4[i] == 1 and v4[i - 1] != 1:
        v5 = a1[v9]
        v9 += 1
        flag.append(us)

    if v4[i] == 2:
        if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 5):
            us = v5 - v4[i - 1]
            # print(us,v5,a[i-1])

    if v4[i] == 3:
        if (v4[i + 1] != 2 and v4[i + 1] != 4 and v4[i + 1] != 5):
            us = v5 + v4[i - 1]  # LOBYTE是al有8位,参与运算的5、33、32是全值,所以LOBYTE可省略

    if v4[i] == 4:
        if (v4[i + 1] != 3 and v4[i + 1] != 2 and v4[i + 1] != 5):
            us = v5 ^ v4[i - 1]

    if v4[i] == 5:
        if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 2):
            us = int(v5 / v4[i - 1])
    if v4[i] == 8:
        v5 = us

    if v4[i] == 11:
        us = v5 + 1

    if v4[i] == 12:
        us = v5 - 1
        # print("12:",us)

flag.reverse()
out = ''
for j in flag:
    out += chr(j)
print("flag{" + out + "}")

флаг {757515121f3d478}

рекомендация

отblog.csdn.net/mcmuyanga/article/details/114309960