Delphi XE2 x64 and TRY ... EXCEPT

If in a x64 application (Borland Delphi XE2) occurs exception in code in a block “try … except”, then instead of execution the code inside “except … end” block shows message like “This code requires valid serial number to run. Program will be terminated.” and application closes.
An error occurs in an non-encrypted part of the code, i.e. not inside code blocks of like “VMProtectBeginUltra … VMProtectEnd;”.
The serial do not loaded before. It is DEMO mode of application.

What to do? How to work with “try … except … end”?


Если в x64 приложении внутри блока try … except происходит исключение, то вместо выполнения кода внутри блока except … end, появляется сообщение вида “This code requires valid serial number to run. Program will be terminated.” и приложение закрывается.
Ошибка происходит в незашищенном участке кода, т.е. не внутри блоков кода вида VMProtectBeginUltra … VMProtectEnd;
Серийный номер не загружался перед этим. Это ДЕМО режим работы приложения.

Что делать? Как работать блоками “try … except … end”?

У вас скорее всего проблема в другом:

try
  VMProtectBeginVirtualizationLockByKey('');
  ...
  VMProtectEnd();
  try
    ...
  except
    ...
  end 
finally
  ...
end;

Обратите внимание, что блоки try/finally могут быть неявными (например когда компилятор уничтожает локальные String). Поэтому когда вы обрабатываете маркер, то туда же попадает и код между fynally/end, а после except/end управление попадает как раз на начало finally в результате чего показывается сообщение об отсутствии серийного номера.

Что делать? Как работать блоками “try … except … end”?

В данном случае уносить маркер в отдельную функцию.

Перефразирую вопрос.

Есть код вида:

try
  VMProtectBeginVirtualizationLockByKey('');
  ...
  VMProtectEnd();
finally
  ...
end;

try
  try
     ...
     [код где происходит ошибка]
     ...
   except
     ...
   end;
finally
end;

В 32-х разрядном приложении, после наложении защиты VMProtect, все отрабатывает как и должно.
В х64 приложении, после наложении защиты VMProtect, после ошибки в коде появляется сообщение:

This code requires valid serial number to run.
Program will be terminated.

и приложение закрывается совсем.

Перефразирую свой ответ - в код маркера попадает часть функции, которая выполняется после except/end (скорее всего это неявный finally, который вставляет компилятор):

var S: String;
begin
try
  // ваш код здесь и и вам не нужно вызывать деструктор S, потому что, компилятор делает это сам в собственном finally блоке
finally
  S.Free();
end;
end;

Вот пример:

procedure TForm1.Button1Click(Sender: TObject);
var sList : TStringList;
begin
  VMProtectBeginUltraLockByKey('Test.Protect');
  VMProtectEnd;

  try
    sList[0] := 'Test string'; // тут будет AccessViolation
  finally
    ShowMessage('finally for s[0]');
  end;
end;

Почему появляется сообщение “This code requires valid serial number to run. Program will be terminated.” ?
Как сделать, чтобы было сообщение “finally for s[0]” ?

В дизассемблере весь код смотрели?

Это примитивный тест. Весь код:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses VMProtectSDK;

procedure TForm1.Button1Click(Sender: TObject);
var sList : TStringList;
begin
  VMProtectBeginUltraLockByKey('Test.Protect');
  VMProtectEnd;

  try
    sList[0] := 'Test string';
  finally
    ShowMessage('finally for s[0]');
  end;
end;

end.

И собственно проект:

program Project1;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  VMProtectSDK in '..\..\..\Borland Studio Projects\Project\Common.VCL.VMProtect\VMProtectSDK.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Зачем тут дизассемблер?

Зачем тут дизассемблер?

Затем что у вас FINALLY попал в маркер!

Вот тут не понятно. Маркеры это же VMProtectBeginUltraLockByKey … VMProtectEnd;

Или что понимается под маркерами? Где это описано?

Присылайте простейший пример (оригинальный EXE+MAP+VMP файлы), на котором можно воспроизвести вашу проблему.

Мы вывели зашищенные блоки кода в отдельные процедуры и проблемы более нет.