Всем привет. Многие знают об этой замечательной игре — LIMBO! Вы даже наверняка покупали ее в Стиме, или качали с торрентов…
Я тоже ее купил когда-то (что и вам советую!), и прошел). Но, как всегда, мне было этого мало, и я, из спортивного интереса, решил изучить ее защиту. Так и появился кейген к игре LIMBO.

В этой статье я расскажу и покажу вам, как я это делал.

Прежде, чем начинать, помните: все действия вы выполняете на свой страх и риск. Уважайте работу геймдевелоперов.


Этап первый: Поверхностный осмотр пациента

Полный инсталлятор игры можно скачать здесь. Установив игру, первым делом, как обычно, выясняем, на чем написан главный исполняемый файл. Я воспользуюсь для этого ExeInfo PE.



Видим: Visual Studio 2008. IDA Pro прекрасно с ней справляется, поэтому туда и отправим. Я буду пользоваться связкой IDA Pro + HexRays, т.е. с декомпилятором — для ускорения работы.

Этап второй: что мы ищем?

Первым делом, дадим Иде проанализировать limbo.exe — главный исполняемый файл игры.

Далее, нужно определить, что именно мы, собственно, хотим найти здесь. Запустим игру:



Видим волшебную надпись "UNLOCK FULL GAME". На нее и нажмем. Далее нас ожидает нежданчик (по крайней мере, я, когда первый раз выбирал этот пункт меню, я ожидал увидеть поле ввода на графическом движке игры, или типа того, а оказалось все гораздо проще...):



Да, да! Именно обычное окошко! Нам же легче. Попробуем что-нибудь ввести, и нажать Unlock. Как-то так:



Ну что ж, поищем по тексту в IDA, чтобы затем от него отталкиваться, и найти место проверки. И тут меня ожидал облом…
По тексту сообщения в окне ошибки Ида мне ничего не нашла! То же самое сказал мне и поиск по содержимому через Total Commander. Возможно, сообщение зашифровано. Можно попробовать найти вызов окна отталкиваясь от вызова MessageBoxA/W. Но, я пошел другим путем, который, почему-то, мало где в статьях описывают.

Этап третий: Нажми меня

Мы поступим следующим образом. Откроем любой удобный Вам редактор ресурсов, затащим в него ехе-шник, найдем окошко диалога ввода ключа, а в нем — кнопку Unlock. Сказано — сделано:



На скрине я выделил ID нашей кнопки. По нему мы и будем искать, где именно обрабатывается нажатие. Откроем Иду, нажмем Alt+I (Search -> immediate value...), введем число 203 (без 0x, т.к. десятичное), и посмотрим, что найдется. А нашлось вот это:



Видите те строчки, которые Ида пометила как ; nIDDlgItem? С них и начнем. Двойным кликом переходим на первый из таких результатов:



Зеленой стрелкой я обозначил место, на которое указала Ида, а чуть ниже (привычка: прокручивать выше/ниже искомого места) — стрелкой обозначено место вызова одной интересной API-функции: GetDlgItemTextA. Судя по названию по MSDN, эта функция получает текст указанного элемента окна в буфер.

Почему я сразу не искал по ID поля ввода? Можно, конечно и так было сделать. Но, мало ли какие действия происходят после нажатия кнопки, еще до вычитывания текста из поля.

Итак, проследим, куда уходит полученный серийник. Прокручиваем листинг, чтобы видеть место вызова API-функции целиком:



Мой "намыленный" взгляд подсказывает мне, что полученный буфер (Ида обозначила его как var_134) передается прямиком в следующую за вызовом GetDlgItemTextA функцию, которая возвращает в al нулевое, либо ненулевое значение (похоже на результат проверки ключа). Давайте проверим догадку…

Этап четыре: Декомпиляция

Заходим в функцию. Видим там прыжок на еще один адрес — переходим по нему. Видим нормальный код, поэтому смело жмем там F5 (вызываем HexRays Decompiler).

Результат декомпиляции
bool __cdecl sub_48D410(int a1)
{
  int v1; // esi@7
  char *v2; // ebp@7
  unsigned int v3; // edi@7
  int v4; // ST28_4@9
  int v5; // edx@9
  int v6; // eax@12
  bool result; // al@12
  char v8; // [sp+4h] [bp-44h]@8
  char v9; // [sp+Ch] [bp-3Ch]@12
  char v10; // [sp+1Ch] [bp-2Ch]@7
  char v11; // [sp+3Ch] [bp-Ch]@12

  if ( strlen((const char *)a1) != 37
    || *(_BYTE *)(a1 + 5) != 45
    || *(_BYTE *)(a1 + 11) != 45
    || *(_BYTE *)(a1 + 17) != 45
    || *(_BYTE *)(a1 + 23) != 45
    || *(_BYTE *)(a1 + 30) != 45 )
  {
    result = 0;
  }
  else
  {
    v1 = 0;
    v2 = &v10;
    v3 = 0;
    do
    {
      v8 = *(_BYTE *)(v3 + a1);
      if ( v8 != 45 )
      {
        v4 = (char)sub_412EBD(v8);
        v1 += v4 << 5 * (3 - v5);
        if ( v5 == 3 )
        {
          v2 += sprintf(v2, "%05lx", v1);
          v1 = 0;
        }
      }
      ++v3;
    }
    while ( v3 < 0x25 );
    v6 = sub_40C48C(&v10, 32);
    sprintf(&v9, "%08x", v6);
    result = strcmp(&v9, &v11) == 0;
  }
  return result;
}


Теперь можно попытаться привести этот код к более адекватному.

Первым делом, замечаем, что входной параметр имеет тип int, что не совсем правда. Обозначим его как "char *". Для этого становимся на имя функции и жмем там клавишу Y (Set item type). Исправляем тип и имя входного параметра (я обозвал его как key).

Далее… Видим строчку:

  if ( strlen(key) != 37 || key[5] != 45 || key[11] != 45 || key[17] != 45 || key[23] != 45 || key[30] != 45 )

Т.к. наш входной параметр — строка, давайте в тех местах, где символы ключа сверяются с числами, исправим на сравнение с символами. Для этого на каждом из таких чисел нажмем R (Char). Уже лучше:

  if ( strlen(key) != 37 || key[5] != '-' || key[11] != '-' || key[17] != '-' || key[23] != '-' || key[30] != '-' )

Теперь цикл:

Цикл №1
    v1 = 0;
    v2 = &v10;
    v3 = 0;
    do
    {
      v8 = key[v3];
      if ( v8 != 45 )
      {
        v4 = (char)sub_412EBD(v8);
        v1 += v4 << 5 * (3 - v5);
        if ( v5 == 3 )
        {
          v2 += sprintf(v2, "%05lx", v1);
          v1 = 0;
        }
      }
      ++v3;
    }
    while ( v3 < 0x25 );


Для наглядности дадим v3 имя i, т.к. похоже, что она используется как итератор. Переименовываем нажатием на имени клавиши N (Name).

Замечаем, что в цикле происходит взятие каждого символа из ключа, и передача его в пока неизвестную нам функцию. Предлагаю выяснить, что это за функция. Двойным щелчком переходим в нее. Видим там вызов еще одной функции, переходим туда. И, вот оно — обработка одиночного символа! (Здесь есть куча работы для клавиши R, но я лишь покажу сразу результат обработки).

Функция convert_char
char __cdecl convert_char(char C)
{
  char _C; // al@1

  _C = C;
  if ( C < '0' )
    return -1;
  if ( C <= '9' )
    return C - '0';
  if ( C < 'A' )
    return -1;
  if ( C <= 'Z' )
  {
    if ( C != 'I' && C != 'L' && C != 'O' && C != 'U' )
    {
      if ( C >= 'U' )
        _C = C - 1;
      if ( _C >= 'O' )
        --_C;
      if ( _C >= 'L' )
        --_C;
      if ( _C >= 'I' )
        --_C;
      return _C - '7';
    }
    return -1;
  }
  if ( C < 'a' || C > 'z' || C == 'i' || C == 'l' || C == 'o' || C == 'u' )
    return -1;
  if ( C >= 'u' )
    _C = C - 1;
  if ( _C >= 'o' )
    --_C;
  if ( _C >= 'l' )
    --_C;
  if ( _C >= 'i' )
    --_C;
  return _C - 'W';
}


Прекрасно! Теперь возвращаемся назад клавишей Esc до основной функции. Замечаем, что IDA сама переопределила для нас тип результата возвращаемого функцией обработки символа. Именуем дальше, обозначаем типы, и получаем следующий код цикла:

Цикл №2
    sum = 0;
    x5buf = v10;
    i = 0;
    do
    {
      C = key[i];
      if ( C != '-' )
      {
        new_c = j_convert_char(C);
        sum += new_c << 5 * (3 - itr);
        if ( itr == 3 )
        {
          x5buf += sprintf(x5buf, "%05lx", sum);
          sum = 0;
        }
      }
      ++i;
    }
    while ( i < 0x25 );


Если вы заметили, то тут есть одна интересная бага декомпилера. Видим, что переменная, обозначенная у меня как itr, совершенно не инкрементируется. Чтобы выяснить, что на самом деле происходит, жмем ПКМ -> Copy to assembly, и смотрим, где же используется наша itr. Выясняем: она инкрементируется прямо в этом цикле (чего и стоило ожидать), а до цикла — обнуляется. Учтем это при написании кейгена.

Теперь вторая часть функции проверки ключа… У нас осталась одна неисследованная функция, которая, кстати, очень похожа на функцию подсчета CRC32. Результат обработки (пусть и на скорую руку, но читаемый):

crc32
int __cdecl calc_crc32(char *my_key, int len)
{
  int i; // ebp@1
  unsigned int _xor; // ecx@1
  char *_my_key; // edi@2
  char C; // al@3
  signed int mask; // edx@3
  int B; // esi@3
  bool bit; // al@4
  int crc32; // eax@10
  signed int _len; // edx@10

  i = len;
  _xor = 0xFFFFFFFF;
  if ( len )
  {
    _my_key = my_key;
    do
    {
      C = *_my_key;
      --i;
      ++_my_key;
      mask = 1;
      B = (unsigned __int8)C;
      do
      {
        bit = (_xor & 0x80000000) == 0x80000000;
        _xor *= 2;
        if ( B & mask )
          bit = bit == 0;
        if ( bit )
          _xor ^= 0x4C11DB7u;
        mask *= 2;
      }
      while ( (_BYTE)mask );
    }
    while ( i );
  }
  crc32 = _xor & 1;
  _len = 0x1F;
  do
  {
    _xor >>= 1;
    crc32 = _xor & 1 | 2 * crc32;
    --_len;
  }
  while ( _len );
  return ~crc32;
}


Оставшийся кусок (преобразованный):
    crc32 = j_calc_crc32(my_key, 32);
    sprintf(crc32_, "%08x", crc32);
    result = strcmp(crc32_, &my_key[32]) == 0;


Этап пять: написание кейгена

Задача: определить, что именно происходило с ключом, чтобы написать обратную функцию. Писать я буду, вопреки здравому смыслу и выдаче HexRays, на Delphi, а Вы можете писать на том языке, который проще именно Вам.

Путем отладки выясняем произошедшее:
  1. Игре нужен ключ в 32 символа без дефисов (37 — с дефисами).
  2. Берется по четыре символа из ключа (не учитываются дефисы). Каждый из них пропускается через функцию convert_char и суммируется по формуле: sum += new_c << 5 * (3 — itr);
  3. Каждая такая сумма преобразовывается в lower-case хекс-строку (5 символов) и доклеивается до имеющейся (итого 40 символов);
  4. Берется CRC32 от первых 32 символов получившейся строки и сравнивается с оставшимися восемью символами полученной в предыдущем пункте строки;
  5. Если строки не совпали — наш ключ неправильный.


Обратное мышление:
  1. Написать функцию, преобразующую 40-символьный хэш обратно в ключ;
  2. Сгенерировать 32-символьный хэш;
  3. Посчитать от него 8-символьный CRC32;
  4. Склеить строки, полученные на этапах (2) и (3);
  5. Передать в функцию (1) — получим искомый ключ.


Мысли о преобразующей функции:
  1. Т.к. входной хэш был получен из восьми 5-символьных хэш-кусков, будем обрабатывать его так же, по "пятеркам";
  2. Каждая "пятерка" была получена из четырех символов ключа;
  3. Т.к. при каждом вычислении "пятерки", она сдвигалась на 5 бит влево, получается, что на каждый символ ключа приходится 5 бит;
  4. Внимательное рассмотрение кода функции convert_char приводит нас к такой мысли, что набор символов ключа ограничивается лишь символами набора "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
  5. Итого: 32 символа хэша генерятся из "пятерок". 32 % 5 = 24 целых символа и 2 в остатке — т.е. два символа нам придется просто догенерить.

Итоговый вариант функции, генерирующей хэш (Delphi)
function GenHash(len: byte): string;
var
  i, k: byte;
  sum: integer;
begin
  Randomize;
  Result := '';
  sum := 0;
  k := 0;

  for i := 1 to len do
  begin
    sum := sum + (Random(Length(alphabet)) shl ((3 - k) * 5));
    Inc(k);

    if k = 4 then
    begin
      Result := Result + AnsiLowerCase(Int2Hex(sum, 5));
      sum := 0;
      k := 0;
    end;
  end;

  Result := Result + 'a0'; // Решил не баловаться, а оставить два случайных хекс символа
end;


Далее считаем CRC32 от хэша:
var
  key, hash, crc32: string;

begin
  hash := GenHash(24);
  crc32 := Crc32b(hash); // нашел первый попавшийся модуль, реализующий данный хэш-алгоритм

Код функции-преобразователя:
Функция-преобразователь хэша в код
function Hash2Code(const Hash: string): string;
var
  s: string;
  five: integer;
begin
  Result := '';
  s := Hash;

  while Length(s) > 0 do
  begin
    five := Hex2Int(Copy(s, 1, 5));
    Delete(s, 1, 5);

    Result := Result + alphabet[(five and $F8000 shr 15) + 1] +
                       alphabet[(five and $07C00 shr 10) + 1] +
                       alphabet[(five and $003E0 shr 05) + 1] +
                       alphabet[(five and $0001F shr 00) + 1];
  end;
end;



Ну и, наконец, результирующее получение лицензионного ключа:

  key := Hash2Code(hash + crc32);
  lic_code := Format('%s-%s-%s-%s-%s-%s', [Copy(key, 1, 5),
                                              Copy(key, 6, 5),
                                              Copy(key, 11, 5),
                                              Copy(key, 16, 5),
                                              Copy(key, 21, 6),
                                              Copy(key, 27, 6)
                                              ]);

Проверяем, и… Ввод сгенеренного ключа активировал игру, пункт активации исчез!

Итоги

Главное при написании кейгена — уметь обратно думать. Т.е. уметь написать такой алгоритм, который будет обратным тому, который вы имеете. Это непростая задача, но, и она решаема в большинстве случаев.

P.S.

Возможно, статья получилась слишком сумбурной, не знаю. Главная идея, которую я хотел донести: кейген — не такая и сложная штука, если есть мозги, и желание вместе с усидчивостью.

P.P.S.

В следующей статье я опишу, как я писал кейген к другой игре — Unepic.

Комментарии (76)


  1. Ivan_83
    17.04.2015 04:26
    +4

    Было бы не так весело будь там асимметричное крипто. Впрочем вводить такое руками тоже не весело.


    1. DrMefistO Автор
      17.04.2015 09:42

      Я понимаю. Поэтому для статьи я выбирал наиболее простой вариант, чтобы на нем можно было обучить.


  1. robert_ayrapetyan
    17.04.2015 05:43
    +13

    Самая интересная и крутая защита, которую приходилось отламывать:

    Прога под дос, переходит в защищенный режим, делает кучу телодвижений с таблицами дескрипторов, попутно распаковываясь, затем читает определенные сектора HDD через порты. Время: две недели почти круглосуточно, т.к. фактически приходилось эмулировать все действо в Win SoftICE. Назначение софта: некая оболочка для работы с швейным оборудованием.


    1. DrMefistO Автор
      17.04.2015 09:43
      +4

      У меня тоже есть свой опыт «самой крутой» ненавесной защиты. Но описать ее кейгенинг в статье просто нереально, т.к. будет множество отсылок на «набитую руку» и «намыленный взгляд».


      1. vmchaz
        17.04.2015 13:59
        +4

        Читать про такое всегда интересно.
        Нестандартные приёмы работы с ОС (а порой и оборудованием) и их обход — это читается как детектив.
        Так что пишите!


    1. vmchaz
      17.04.2015 13:54

      В каком году это было?
      Возможно ли было заэмулировать всё это дело в Bochs, к примеру? (там есть встроенный отладчик)


      1. robert_ayrapetyan
        17.04.2015 18:31

        Более 10 лет назад, про Bochs тогда еще не слышал… Сомневаюсь что получилось бы проще.


  1. kelevra
    17.04.2015 06:42
    +5

    такое и защитой-то язык не поворачивается назвать. уж очень громкое название статьи :)


    1. Scratch
      17.04.2015 09:26
      -26

      Мне тоже непонятно, почему автор решил открыть тут филиал кряклаба для самых маленьких. Таких статей базилион на профильных сайтах. Но если пипл хавает, то пусть будет.


      1. DrMefistO Автор
        17.04.2015 09:40
        +14

        Не так уж и много статей по кейгенингу. Их раз-два и обчелся.


        1. Scratch
          17.04.2015 09:50
          -1

          Давайте я поясню почему я к вам придираюсь. Мне кажется, что на хабр следует писать статьи, в которых описывается что то новое и эксклюзивное. Вот ВМПрот, например, еще публично никто не разобрал, это было бы интересно. А такие вот новичковые статьи про патчинг, кейгены из CRC32, которых реально сотни, я считаю не совсем тут к месту.


          1. DrMefistO Автор
            17.04.2015 09:52
            +7

            Дайте мне в личку хоть одну статью про "кейгены из CRC32". Тогда я с вами соглашусь.

            И почему новая статья о процессе кейгенинга известного продукта не является «новой и эксклюзивной»?


            1. Scratch
              17.04.2015 10:01
              -4

              exelab.ru/art/?action=list&f=8 Выбирайте на свой вкус. Куча статей о кейгенах к реальным известным продуктам. Продуктов много, а статей об интересных защитах единицы


              1. DrMefistO Автор
                17.04.2015 10:08
                +3

                Читал я эти статьи. Не все из них простые для понимания и не ко всем из них уже можно достать ломаемый софт. Затем, я решил воспользоваться новыми (с 2005 года — даты последней статьи) представившимися возможностями в плане софта: IDA Pro (именно статья, в которой используется IDA Pro), HexRays, возможность втиснуть скриншоты. На exelab все статьи чисто текстовые.


                1. Oldster
                  17.04.2015 12:25
                  +1

                  Спасибо за статью, всегда читаю такие с интересом.
                  На exelab-е есть возможность выкладывать статьи в файлах, например *.doc.

                  PS: покопался там в архивах и увидел свою статью… ностальгия по былым временам.


          1. DrMefistO Автор
            17.04.2015 09:56
            +2

            VMProtect публично никто не хочет разбирать лишь потому, чтобы софт, защищенный им, можно было ломать, не опасаясь выхода новой версии протектора. Собственно, так со многими навесными защитами и происходит, если они достаточно тяжелые для снятия.


            1. REU
              17.04.2015 11:31
              +2

              У нас больше всего не расскрывают эти знания лишь потому что на этом можно рубить бабло. )


              1. DrMefistO Автор
                17.04.2015 11:33

                Именно!) Ведь опытный крякер в первую очередь думает о возможном заработке на своем умении, а потом уже о релизах для команды.


            1. Dim0FF
              17.04.2015 22:47
              +1

              А вот вы могли бы на пальцах объяснить, что такого делает VMProtect, что его настолько сложно взломать?
              Ну то есть в программе всё равно где-то должна быть проверка вроде if (key.IsValid()), где можно всегда возвращать условный true.
              Очевидно, что это не так, но в чём сложности и как именно запутывают не осознаю.


              1. JKornev
                22.04.2015 17:13

                На самом деле VMProtect не такой уж и крутой протектор, его фишкой является возможность обфускации кода или интерпритация на собственных виртуальных машинах, такое сложно исследовать и патчить, так как условный переход может быть размазан на десяток ветвлений и т.п.


          1. cher11
            17.04.2015 10:00
            +20

            И много в последнее время на Хабре нового и эксклюзивного? Внезапно — для меня этим оказались две статьи DrMefistO.
            Почему вы отсылаете людей на всякие непонятные профильные ресурсы, если все отлично (и в тему) расписано тут?


            1. MennyCalavera
              17.04.2015 10:48
              -2

              Туториалы по взлому — тема скользкая. Наверняка рано или поздно этот пост увидит и создатель игры (кто-нибудь ему/им ссылку-то точно скинет на Гугл Транслейт). И тогда это приобретет неприятный оттенок. Можно исследовать что угодно, но не стояло выкладывать алгоритм генерации на Хабр — это мерзко. Статья могла остаться интересной и без него.

              А по поводу самой защиты — соглашусь с тем, кто сказал, что её тут и нет вовсе. Разработчики достаточно наивно подошли к этому вопросу. С верой в лучшее, так сказать.


              1. DrMefistO Автор
                17.04.2015 10:50
                +5

                Вы правы. Поэтому некоторые моменты я сознательно опускал, чтобы прям целиком не выкладывать работающий код.

                Но, в свое оправдание, я могу сказать, что авторам писал еще давным давно, с той целью, чтобы они улучшили алгоритм. Плюс, ажиотаж к игре прошел.


              1. NeuroTechnic
                23.04.2015 09:04

                Пфф, есть мнение, что наличие кряка на продажах не особо отражается. Для массового софта.
                К тому же rip этого лимбо на любом торрент-трекере можно найти и даже кейгеном пользоваться не придется.


        1. k_d
          17.04.2015 10:46
          +2

          Для этого существуют crackme и keygenme. Можно найти уровень защиты на свой вкус, не затронув ничьих интересов.


          1. DrMefistO Автор
            17.04.2015 10:51
            +2

            Верно. Но, порой хочется реальных «боевых» условий, т.е. пощупать именно софт из живой природы, а не специально для этого написанный.


    1. DrMefistO Автор
      17.04.2015 09:36
      +1

      В моем понимании лицензионная защита — это то, каким образом сделана лицензионная система в программе.


      1. dvserg
        17.04.2015 10:00
        +1

        А где традиционное… «Вся приведенная в статье информация предназначена исключительно для образовательных целей. Все ваши действия вы производите на свой страх и риск. Автор не несет ответственности ни за какие последствия Ваших действий»?


        1. DrMefistO Автор
          17.04.2015 10:09

          Обновил)


  1. megaDRONe
    17.04.2015 09:18
    +21

    Покупайте хорошие инди игр, не ломайте их. Маленькие независимые разработчики игр, все же, в первую очередь думают, как игру сделать, а не защиту похитрее написать. Говорю от лица инди гейм девелоперов. :)

    Вот статья про взлом защиты какого-нибудь энтерпрайз софта была бы намного интереснее и циничнее имхо.


    1. DrMefistO Автор
      17.04.2015 09:38

      Я полностью с вами согласен! Но, опять же, цель не в том, чтобы обидеть разрабов (им я писал, но ответа не получил), а чтобы кто-то не сделал это с плохой целью (например, барыженье ключами).


      1. dvserg
        17.04.2015 10:08

        Можете сразу от интересного к полезному перейти — предложить разработчикам методы улучшения защиты ))


        1. DrMefistO Автор
          17.04.2015 10:10
          +1

          Ответа на мое письмо, отправленное разрабам еще 12.04.13, я не получил. Значит улучшать защиту они не хотят. Да и смысла нету уже: все кто хотели, купили и сыграли.


          1. megaDRONe
            17.04.2015 10:22
            +3

            Я думаю, что они и без вас прекрасно понимают, что их игру легко сломать и не пытались это решить, в надежде, что найдутся люди, которые принципиально купят, даже если кряк будет лежать по соседней ссылке.
            В любом случае, статься достаточно интересная, хоть и косвенно поощряет не самые порядочные пути в жизни.


            1. DrMefistO Автор
              17.04.2015 10:24
              +8

              =) Я всегда считал и буду считать: "If you like it, you will buy it!"


  1. siemdi
    17.04.2015 10:09
    +12

    Выше в комментариях я встретил упоминание что это не защита и т.д.
    Так вот что я хочу сказать, если Вы прочитали просто много статей про обход защиты и Вам кажется что это слишком просто, то попробуйте на примере автора обойти своими ручками ходить одну защиту, даже самую простую.
    Автору спасибо, т.к. эта тема очень специфическая и очень интересная.


    1. REU
      17.04.2015 11:30

      А если человек делает вывод не по прочитаным статьям, а по реальному опыту, тогда что?


      1. siemdi
        17.04.2015 12:13

        Если кому — то просто, то не стоит заходить в топик. darked
        REU Предполагается что Вы родились сразу со «скилом» Взлома?)


        1. REU
          17.04.2015 12:45
          +2

          Когда я начинал у меня не было интернета и статей ) а были диски с варезом и в каком-то из них было пару хтмл о отладке и патчинге винрара выдраных с какого-то сайта, пропатчил по ней винрар, немного понял суть, пропатчил вторую, третью,… программу. Потом появился кое какой интернет и желание кейгенить, решил попробовать на простеньком кейгенми, алгорит понимал, но как обратить нет, создал тему на кряклабе (одна с первых :) ) мне там объяснили (да, тогда еще там помагали новичкам :) ) я снова понял суть, и снова много практики во время которой постигаешь новые приемы и техники, всё. )


          1. DrMefistO Автор
            17.04.2015 13:43

            А я начинал вообще с перевода консольных игр на русский язык. Отсюда появилась тяга к реверсу.
            Дальше: статьи кряклаба, крякмисы… Писал много статей по патчингу популярных программ.

            А затем я понял, что патчи — не тот уровень уже. Надо бы и кейгены научиться делать. Так я и написал свой первый кейген.)
            Столько воды утекло.

            Потом, списавшись с одним челом по поводу ArtMoney (о которой я тоже как-нибудь напишу), я решил попробовать вступить в одну реверс-команду. Так я и стал участником той тимы, которая чуть ниже в комментах засветилась на скрине)


  1. darked
    17.04.2015 11:58
    +5

    Поддерживаю всех поддерживающих автора ) Спасибо за статью. Если кому — то просто, то не стоит заходить в топик.
    Интересен не сам взлом как таковой — а как логическая задача. Интересно почитать ход мыслей, посмотреть примеры пользование инструментарием.


  1. Spin7ion
    17.04.2015 12:17

    Скажите, а возможно ли модифицировать функцию sub_48D410 чтобы она возвращала всегда корректность ключа, так ли создаются таблетки?
    Статья очень интересная, спасибо.


    1. DrMefistO Автор
      17.04.2015 12:19

      Именно так и создаются патчи/патченые ехе-шники.


    1. vmchaz
      17.04.2015 13:49
      +1

      Да, можно, и так делают самые простые патчи.
      У этого способа есть один минус — меняется исполняемый код. Т.е. из другого места можно просканировать собственный код и понять, правили его или нет.
      К примеру, если где-то в дальше игре есть код, который вычисляет MD5 участка кода с защитой, и полученным числом расшифровывает какие-нибудь ресурсы, которые используются ближе к концу игры, то это может вызвать некоторое недовольство воспользовавшихся патчем (а обычно просто проверяют — запустилось или нет). Кстати, такое поведение вполне может стимулировать продажи игры.

      Кстати, ещё можно вызывать функцию CheckSerial() с заведомо неправильным номером и, если она вернула True, считать код пропатченным и действовать соответственно.


      1. DrMefistO Автор
        17.04.2015 13:53
        +1

        Именно поэтому кейген всегда лучше! Но он и усилий больших требует, понятное дело.


      1. Yuuri
        17.04.2015 14:14
        +1

        если где-то в дальше игре есть код, который вычисляет MD5 участка кода с защитой...

        … и подселяет неубиваемого скорпиона :)


        1. vmchaz
          17.04.2015 14:19
          +1

          Это по аналогии с неубиваемым Шреддером?
          К счастью, я про него только слышал — у меня, насколько я помню, все Шреддеры убивались.


  1. MrAnonymous
    17.04.2015 13:01
    +14

    А я сделал реверсинг картинке :)

    image

    Restorator 2007 — D:\TPORT\unepic_ko\limbo\limbo.exe


    Я прав?


    1. DrMefistO Автор
      17.04.2015 13:39

      Вы правы!) Просто не хотел папку палить) Ибо это цель следующей статьи) Да и имя тимы светится)
      Неудачно получилось))


    1. DrMefistO Автор
      17.04.2015 13:47
      +1

      Только не _ko, а kg)


  1. spiiin
    17.04.2015 15:09

    Простенькая защита.
    Не знал, что код можно так легко декомпилировать обратно в си, просто асмовый код читал сразу.


    1. REU
      17.04.2015 15:50
      +3

      Для того что бы «можно так легко декомпилировать обратно в си» нужно одать несколько килобаксов.


  1. AndreyDmitriev
    17.04.2015 16:20
    +1

    первым делом, как обычно, выясняем, на чем написан главный исполняемый файл.
    Видим: Visual Studio 2008.


    Это ещё как бы ни о чём не говорит. Вот вам, для разнообразия, крякми, который Exeinfo PE распознаётся как «Microsoft Visual C++ 9.0 — Visual Studio 2008», но написан не на VS:

    CrackMeLV.7z

    Кстати, сможете отреверсить пароль, который приведёт к результату, отличному от Access Denied? Ну или как минимум модифицировать исполняемый файл, так, чтобы в ответ на любой пароль получить доступ (это сильно проще)?

    image

    Вирусов там нет, деструктивных действий код не выполняет, все рантайм библиотеки приложены, исходники естественно вышлю по запросу. Пароль существует и однозначно реверсится из кода.


    1. DrMefistO Автор
      17.04.2015 16:22
      +4

      Это челендж?)


      1. AndreyDmitriev
        17.04.2015 16:30

        Челендж — если будет угодно.
        Я знаю, как бы я стал ломать эту штуку (но у меня подход предвзятый, поскольку сам её и написал), но любопытно, как вы подойдёте к снаряду (если есть время недолгими весенними вечерами). Там есть пара забавных мест. Зубодробительных алгоритмов для проверки пароля и обфускаций там не заложено, а изюминка — именно в использованном, скажем так, несколько нетрадиционном, средстве разработки.


    1. DrMefistO Автор
      17.04.2015 16:27

      Программы идентификаторы подсказывают, чем скомпилирована программа, в первую очередь.


    1. REU
      17.04.2015 17:10

      Что-то оно не похоже на крякми…


      1. DrMefistO Автор
        17.04.2015 17:11

        Ну, тут либо крякать, либо кейгенить. Вполне можно.


        1. REU
          17.04.2015 17:16

          Я к тому что внутри много чего лишнего


          1. k_d
            17.04.2015 17:19
            +1

            Потому что на LabView


            1. DrMefistO Автор
              17.04.2015 17:21

              Об этом, и о многом другом я хотел написать позже)


          1. AndreyDmitriev
            17.04.2015 17:34

            Это так. Рантайм там весьма увесистый. Собственно в коде лишнего почти нет, хотя я немного «разнёс» места, где производится нажатие и собственно сравнение. Но чтобы туда добраться, придётся продраться через дебри рантайма, да.


            1. REU
              17.04.2015 17:54
              +2

              Ну ок, посмотрим.


      1. AndreyDmitriev
        17.04.2015 17:24

        Чем же не похоже? Мне казалось, крякми примерно так и выглядят — ну разве что поле «Password» — его кто «Key», кто «Serial» называет. А в остальном — есть исходный код, он скомпилирован в исполняемый файл. Все библиотеки, что там в архиве — они к среде исполнения относятся (их там два рантайма). По идее их надо было инсталляторами разворачивать, но я их бросил в ту же директорию для удобства.
        Если крякми с вашей точки зрения по-другому должен выглядеть — напишите как.
        Бывает ещё кейгенми — там обычно два поля, связанных алгоритмом и требуется написать программку, воспроизводящую зашитый туда алгоритм.


  1. Gol
    17.04.2015 21:05

    Я правильно понимаю, если игрушку защитить чем-то таким — написать кряк или ещё как-то поломать вообще не получится?


    1. robert_ayrapetyan
      17.04.2015 21:29

      отсутвующий код или часть приложения никогда ни при каких условиях не покидает доверенные сервера

      Как минимум, если это правда, приложение без доступа в инет вообще будет неработоспособно (очень сомнительная защита).

      В студенческие годы пытался создать нечто подобное, но с реализацией в аппаратном устройстве со спец. FPGA процем, идея была в том что без этого спец. устройства код, даже сграбленый, будет тормозить на настольном ПК, но дальше теорий все это не ушло.

      Если наврали — то как минимум одному человеку придется таки купить, ну а потом собрать «полную локальную версию» — дело техники )


      1. Gol
        17.04.2015 21:51

        Ну, я так понял что защита для сетевых игрушек, которые без инета и так не работают нормально


        1. robert_ayrapetyan
          17.04.2015 22:31

          Как правило, в сетевых игрушках и так легко вычислить\забанить левых пользователей не особо изощряясь, поэтому польза от такой навороченной защиты сомнительна. Неизвестно, есть ли у них вообще поддержка js и пр. В примере на сайте у них «Сапер» и Notepad++ на сях, и метки именно в код в VS встроены, похоже они ориентированы на защиту «локального» десктопного софта.

          Но вообще все это попытки продать то, что умерло 10 лет назад, под новым соусом…


          1. Gol
            17.04.2015 23:08

            Про js не знаю, на сайте вроде ничего нету про такое. Про игрушки знаю только что тренировались на Doom 3 и на TTD, вроде норм работает.

            А что 10 лет назад умерло, если не секрет?


            1. robert_ayrapetyan
              17.04.2015 23:35

              Ну весь этот рынок навесных защит, armadillo, execryptor и т.п. Вообще в первую очередь «умер» рынок десктопного софта, все ушло в веб и на моб. платформы…


              1. Gol
                17.04.2015 23:37

                А, понял, спасиб


              1. REU
                18.04.2015 00:19

                Вы назвали 2 прота, которые сами уже умерли и не поддерживаются )


  1. Stiver
    17.04.2015 23:39

    Выше правильно заметили про ассиметричную криптографию. Смотрел как-то софт, а там обычная RSA, простенько и со вкусом. Повезло, что 256-битная оказалась, удалось разложить. А начиная самое позднее с 1024 можно тушить свет.


    1. foxmuldercp
      18.04.2015 01:06

      Эм, это имеется в виду однонавправленное шифрование серийника в наборе процедур которые скажут «серийник валиден, работай на здоровье»?


      1. Stiver
        18.04.2015 12:38

        Примерно так. Серийник (с дополнительными данными по вкусу, типа имени клиента) шифруется приватным ключем, а программа пытается расшифровать публичным.


        1. xRay
          22.04.2015 21:24

          По типу защиты примененной в FL Studio от Image Line?