IT-Блог о программировании и операционных системах

Защита Delphi-программ от взлома. Часть IV - Защита от декомпилятора DeDe (Delphi Decompiler).

И снова здравствуй, уважаемый читатель! В прошлых частях я рассказывал о:
  1. Защита Delphi-программ от взлома. Часть I – Инструментальная
  2. Защита Delphi-программ от взлома. Часть II – Защитно-обзорная
  3. Защита Delphi-программ от взлома. Часть III – Навесная
Я продолжаю публиковать заметки о защите программного обеспечения на Delphi и сегодня мы рассмотрим такой известный декомпилятор, как DeDe ну и конечно попробуем от него защищаться :) Поехали?

Тестовый проект

Для начала, накидайте на Делфи простой тестовый проект с защитой (можно не извращаться, это просто для тестов). Вот как выглядит моя защита:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text :=  fGeneratePass;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if Edit2.Text = fGeneratePass then
  ShowMessage('Good Boy!');
end;

function TForm1.fGeneratePass: String;
var
  pPCName: array [0..MAX_COMPUTERNAME_LENGTH+1] of Char;
  cPassLen: Cardinal;
  i,j:integer;
  Password:string;
begin
  ZeroMemory(@pPCName, SizeOf(pPCName));
  cPassLen := MAX_COMPUTERNAME_LENGTH+1;
  GetComputerName(@pPCName,cPassLen);
  for i := 0 to High(pPCName) - 1 do
    for j := 0 to Length(Self.Caption) - 1 do
      Password := Password + IntToStr(Ord(pPCName[i]) xor Ord(Self.Caption[j]));
  result := Password;
end;





Интерфейс программы тоже минимальный:





11





Кнопка Generate генерирует серийник на основе имени машины и заголовка программы, а кнопка Check Key соответственно, проверяет его.






Внимание!





Так, как сделал проверку я, никогда не следует делать. Это просто тестовый пример для DeDe! А вот о том, как следует, читайте в моих следующих заметках.






Вроде бы всё просто. Компилируем. И тут… Тут стоит остановиться и сказать, что сама DeDe разделяется на так называемую старую версию, которая от DaFixer и новую, которая от BitMaker. Ни одна из них, даже с учётом последних версий точно не понимают компилятора Delphi версии 21.00





Delphi2010





(Delphi 2010). Может быть они не понимали его ещё с версии 2009 – точно не знаю, проверьте если интересно. По крайней мере, компилятор Delphi 15.0 (Delphi 7) они понимают прекрасно.





Delphi 7





Что значит “понимают” и не “понимают”? Мы поймём, как только начнём исследовать программу, скомпилированную разными компиляторами в DeDe. Не будем терять времени и загрузим в новую версию DeDe программу скомпилированную в Delphi 7. Переходим на вкладку “Процедуры” и видим, в моём случае два события класса TForm1! Это как раз те два OnClick, которые я написал в тестовом примере. Вот посмотрите:





DeDe 





Как видите, по информационному окну информации предоставляется просто предостаточно! И имя метода и событие, и вызывающий объект, и даже заголовок кнопки. Прибавить к тому, самое главное – RVA-адрес, с которого собственно и начинается наша процедура сравнения и получаем собственно всю необходимую информацию для успешного реверсинга нашей программки. По двойному клику на событие откроется так-же и дизассемблированный код процедуры. Он конечно может быть сколько угодно глубоким, но факт остаётся фактом – информация есть, и она представлена в лучшем виде.





Если мы загрузим в DeDe программу скомпилированную в Delphi 2010, то кроме имён классов вы ничего не увидите. Те, кто сидит на Delphi 2010 сейчас обрадуются, но им всё-же не стоит забывать, что кроме DeDe, существуют и другие инструменты, которым на версию компилятора глубоко фиолетово – уж поверьте…





А что, если я не хочу отходить от использования Delphi 7? Ничего не поделаешь. Придётся. Даже если заменить компилятор 7 Delphi на 10 всё равно ничего вы этим не добьётесь, так как связано это с внутренним устройством среды Delphi 2010. Во первых в разных библиотеках, разные адреса функций (DCCxx.dll), а во вторых стоит ли надеяться, что библиотеки эти одинаковы в плане своей архитектуры? Но это не говорит о том, единственным способом защиты от DeDe является переход на молодые версии, можно прекрасно защищаться и на Delphi 7! И вот как!

Защищаемся



Основным способом защиты от DeDe является динамическое присваивание событиям указателей методов. Давайте рассмотрим как это происходит:



// Форма
//##########################################################
public
  { Public declarations }
  function fGeneratePass:String;
  procedure pGetPassToEdit(Sender:TObject);
  procedure pCheckPass(Sender:TObject);
  ...

// Методы
  procedure TForm1.pGetPassToEdit(Sender:TObject);
  begin
    Form1.Edit1.Text :=  Form1.fGeneratePass;
  end;

  procedure TForm1.pCheckPass(Sender:TObject);
  begin
    if Form1.Edit2.Text = Form1.fGeneratePass then
    ShowMessage('Good Boy!');
  end;

// функция генерации
  function TForm1.fGeneratePass: String;
  var
    pPCName: array [0..MAX_COMPUTERNAME_LENGTH+1] of Char;
    cPassLen: Cardinal;
    i,j:integer;
    Password:string;
  begin
    ZeroMemory(@pPCName, SizeOf(pPCName));
    cPassLen := MAX_COMPUTERNAME_LENGTH+1;
    GetComputerName(@pPCName,cPassLen);
    for i := 0 to High(pPCName) - 1 do
      for j := 0 to Length(Self.Caption) - 1 do
        Password := Password + IntToStr(Ord(pPCName[i]) xor Ord(Self.Caption[j]));
  result := Password;
  end;

// Проект
//##########################################################

program Project1;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Form1.Button1.OnClick := Form1.pGetPassToEdit; // !! присваиваем указатели на методы
Form1.Button2.OnClick := Form1.pCheckPass;  // !! --//--
Application.Run;
end.





Результатом будет служить то, что DeDe не сможет распознать обработчики событий:





DeDe_owned

13 комментариев:

  1. Не пробовали IDR (Interactive Delphi Reconstructor)? Это фриварный продукт, скачать можно с сайта http://www.shell-codes.com
    crypto

    ОтветитьУдалить
    Ответы
    1. http://wireless-hack.ucoz.ru - Универсальный софт для подбора пароля к Wi-Fi сетям
      На этом сайте вы сможете скачать программу для подбора пароля к Wi-Fi
      Скачать: http://goo.gl/RvYYLr
      Ознакомиться с видео презентацией работы программы: http://goo.gl/GxwLdF
      Скачать приватный hack софт бесплатно: http://goo.gl/oR7rQW
      Услуги по подбору паролей к Wi-Fi, Rar, Zip.: http://goo.gl/oTKnnE
      http://www.google.ru/#btnI=rutigunu&q=wireless-hack.ucoz
      Генератор ключей Steam: http://goo.gl/ah3i6E
      http://wireless-hack.ucoz.ru/soft/soft1.html

      Удалить
  2. Первый раз слышу, если честно. Попробую, спасибо.

    ОтветитьУдалить
  3. Если Касперски предоставил место для хостинга страницы программы, то она определённо заслуживает внимания :)

    ОтветитьУдалить
  4. IDR сейчас поддерживает версии до 2009 включительно. Версия 2010 тоже уже поддерживается, но соответствующий билд будет доступен чуть позже...

    ОтветитьУдалить
  5. Блин, она... она замечательна! Я пока не сильно конечно разобрался, но то, что получается - очень даже не дурно! Респект!

    ОтветитьУдалить
  6. Кстати, было бы приятно, если бы когда я например тыкаю на форму и открывалась бы не модально, но показывалась бы всё равно, то есть, когда открыта форма, невозможно работать с ClassViewer & CodeViewer. Вот такое пожелание :)

    ОтветитьУдалить
  7. Crypto, свяжитесь со мной, есть о чём поговорить. uin: 982401

    ОтветитьУдалить
  8. IDR уже официально поддерживает версию 2010

    ОтветитьУдалить
  9. 1. При 'for j:=0' вылетает ошибка 'Range check error', работает 'for j:=1'
    2. Дополнительно скрыть информацию от DeDe и других редакторов ресурсов можно путем динамического создания контролов (Edit, Button и др.).
    Пример:
    Удаляем все с Формы.
    Для Формы создаем событие FormCreate
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    Edit1:=TEdit.Create(Form1); //Создаем 'Edit1'
    Edit1.Parent:=Form1;
    Edit1.Left:=20; //Располагаем 'Edit1' на форме
    Edit1.Top:=20;
    BitBtn1:=TBitBtn.Create(Form1); //Создаем Кнопку
    BitBtn1.Parent:=Form1;
    BitBtn1.Left:=Edit1.Left;
    BitBtn1.Top:=Edit1.Top+Edit1.Height+8;
    BitBtn1.Caption:='Generate'; //Надпись на Кнопке
    BitBtn1.OnClick:=Form1.pGetPassToEdit; //Дейтвие на нажатие Кнопки
    end;
    Создавать Контролы можно в середине программы по мере надобности, тогда их вообще будет трудно отследить.

    ОтветитьУдалить
    Ответы
    1. Как правило контролы создаются динамически именно в обработчике события FormCreate, там же назначаются и их собственные обработчики событий, поэтому восстановить их с помощью IDR особого труда не составляет. Я подобные вещи проделывал не раз на нескольких известных программах, все прекрасно работает.
      crypto

      Удалить
  10. Спасибо за комментарии. По поводу того, что трудно отследить... хмм.. не согласен... Обычный брейк на функции CreateWindow & CreateWindowEx в отладчике сразу же спалят весь сакральный смысл тайной вечерии....

    ОтветитьУдалить
  11. Вообще-то, в статье говорится о защите программы от предварительного анализа в декомпиляторах DeDe и IDR, показывающих названия и подписи кнопок и полей, адреса функций их обработки, что сразу подсказывает, где проверяется пароль и куда ставить прерывание. При динамическом создании контролов, этой информации нет. Полей (кнопок) можно создать пару десятков (сотен), и определить какие из них отвечают за ввод пароля будет труднее... Да и работа с отладчиками IDA и OllyDbg, это уже другой уровень.

    ОтветитьУдалить