1. Теперь за форумную активность начисляются биткоины и другие криптоденьги. Подробнее.
    Скрыть объявление
  2. Появилась архивная версия форума arhiv.xaker.name, где собраны темы с 2007 по 2012 год.
    Скрыть объявление

Самомодификация как средство защиты своих программ - Часть 2

Тема в разделе "Статьи, руководства, видео", создана пользователем Dr. MefistO, 1 фев 2012.

  1. Dr. MefistO
    Dr. MefistO Крывіч Глобальный модератор
    Симпатии:
    125
    [​IMG]

    Привет всем!

    Надеюсь, вы успешно прочитали и осилили предыдущую статью о самомодификации?!) Если да, пойдем дальше, и займемся простеньким шифрованием кода какой-нибудь процедуры. Ну а если нет - не бойтесь задавать вопросы - постараюсь ответить)

    Инструментарий:
    • Delphi 7 Lite (для написания приложений) + KOL;
    • Olly Debugger v2 (для анализа кода);
    • Hex Workshop - для модификации процедуры на побайтовом уровне.

    Часть II: защита исполняемого кода от декомпиляторов

    Итак, приступим.
    Допустим, нам надо защитить код процедуры WriteValues из предыдущей статьи, чтобы реверсер не мог увидеть ее исходного кода (а вдруг у нас там процедура проверки ключа).
    Код:
    procedure WriteValues;
    var
      i: Byte;
    begin
      for i:=1 to 10 do
      Writeln(i);
    end;
    Для начала, выберем алгоритм шифрования. Пускай это будет обычный XOR с любым байтом (я выбрал $AB). Предположим, что мы уже зашифровали процедуру. Как мы будем ее расшифровывать?

    Приблизительный алгоритм:
    1. Получить зашифрованный байт процедуры;
    2. Поксорить его с $AB (т.к. операция обратимая, т.е. как шифруем, так и расшифровываем);
    3. Записать на место прежнего байта.

    Напишем код расшифровки. Для этого нам нужно определить - сколько байт мы будем расшифровывать. Для этого глянем на картинку из предыдущей статьи, и посчитаем количество байт в дампе памяти (от первого до последнего байта процедуры):
    [​IMG]

    Получилось 53 байта, или $35 в хексе. Изменим соответствующим образом VirtualProtect:
    Код:
      VirtualProtect(
      Pointer(base), //передаем указатель на модифицируемый байт
      53,             //количество изменяемых байт исправлено на 53
      PAGE_EXECUTE_READWRITE,  //режим чтения-записи в память
      OldPageProtection        //в эту переменную мы сохраняем старый режим
      );
    Расшифровывать мы будем с первого байта, поэтому offset будет равен нулю:
    Код:
    offset:=0;
    Действия будут выполняться в цикле от первого до последнего байта, поэтому объявим переменную для счетчика:
    Код:
    i: Byte;
    Теперь вместо:
    Код:
    base^:=101;
    нам нужно написать сам цикл. Он будет выглядеть следующим образом:
    Код:
      for i:=1 to 53 do
      begin
      base^:=base^ xor $AB; //считываем байт процедуры и ксорим его с $AB
      inc(base);           //переходим к следующему байту
      end;
    Вот и вся процедура расшифровки. Скомпилируем ехешник и засунем в Olly Debugger, перейдем к адресу нашей процедуры, который мы получаем всегда из сообщения:
    Код:
    MsgOK(Int2Hex(Cardinal(@WriteValues),8));
    На первой строчке процедуры щелкните правой кнопкой мыши, и выберите Follow in Dump->Selection. Мы окажемся на том байте дампа памяти, с которого начинается процедура. Необходимо посчитать длину процедуры. Я выделил прямоугольниками байты процедуры:
    [​IMG]

    Выделите их, и нажмите правой кнопкой мыши, а затем: Edit->Binary Copy.
    Запустим хекс-редактор, и вставим туда эти байты. Теперь шифрование.

    Вставьте из буфера обмена в новый файл эти байты (File->New). Жмем меню Tools->Operations->XOR...

    Выставляем настройки так, как на скрине:
    [​IMG]

    И жмем ОК. Копируем новые байты, и вставляем их вместо предыдущих в Oly Debugger: Edit->Binary Paste. Опять жмем правой кнопкой мыши на измененных байтах в дампе, и выбираем меню: Edit->Copy to Executable, а в новом окошке жмем правой кнопкой и пункт меню Save File. Жмем Yes, заменяем исходный файл.

    Анализ выполненного

    Переоткрываем наш измененный файл в Olly Debugger, переходим на адрес процедуры. Видим, что там непонятный набор байт. Попробуем запустить файл на исполнение, и... О ЧУДО! Эта штука работает)

    Привожу исходный код всего проекта:
    Код:
    program test1;
    
    {$APPTYPE CONSOLE}
    
    uses
      KOL, windows;
    
    procedure WriteValues;
    var
      i: Byte;
    begin
      for i:=1 to 10 do
      Writeln(i);
    end;
    
    var
      OldPageProtection: Cardinal;
      base: PByte;
      offset: byte;
      i: byte;
    begin
      MsgOK(Int2Hex(Cardinal(@WriteValues),8));
      WriteValues;     //первый раз выводим для просмотра результата
    
      offset:=0; //Смещение изменяемого байта относительно начала процедуры
    
      base := PByte(Cardinal(@WriteValues) + offset); //Позиция изменяемого байта
      VirtualProtect(
      Pointer(base), //передаем указатель на модифицируемый байт
      53,             //количество изменяемых байт
      PAGE_EXECUTE_READWRITE,  //режим чтения-записи в память
      OldPageProtection        //в эту переменную мы сохраняем старый режим
      );
    
      for i:=1 to 53 do
      begin
      base^:=base^ xor $AB; //считываем байт процедуры и ксорим его с $AB
      inc(base);           //переходим к следующему байту
      end;
    
      VirtualProtect(Pointer(base),53,OldPageProtection,OldPageProtection);
    
      WriteValues;    //смотрим изменения
    
      Readln;
    end.
    Исходник проекта из статьи

    ----------------------------------------------------------------​

    Автор: Владимир Мефисто
     
    1 фев 2012
    3 пользователям это понравилось.

Поделиться этой страницей

Загрузка...