Script for Extra Protection

Hello,

Okay i decided to write a script to better virtualize the Entry Point. But it doesn’t seem to work because P.ExtAddresses.Count is always zero is this an error? or did i do something wrong? BTW i never coded in Delphi so it could be
my fault :slight_smile:.

procedure OnBeforeCompilation;
var A, I:Integer;
    Address:Int64;
    EA:TExtAddresses;
    P:TVMProcedure;
    NewP:TVMProcedure;
    Instruction:TIntelRecord;
begin
     for I := 0 to VMProtector.Count - 1 do
     begin
          P := VMProtector.Procedures[I];
          if P.Name = 'EntryPoint' then
          begin
             P.IncludedInCompilation := True;
             P.CompilationType := ctUltra;
             P.CompilationOptions := [coCheckCRC, coEncryptRegs, coEncryptValues];
             EA := P.ExtAddresses;
             Writeln(Format('Protecting %d additional procedures', [EA.Count]));
             for A := 0 to EA.Count - 1 do
             begin
                  Address := EA[A];
                  Writeln(Format('Adding address %x for protection', [Address]));
                  
                  NewP := VMProtector.AddByAddress(Address, ctUltra, True);
                  NewP.CompilationType := ctUltra;
                  NewP.CompilationOptions := [coCheckCRC, coEncryptRegs, coEncryptValues];
             end;
          end;
     end;
end;

Do you want to add the EntryPoint`s calls into the list for protection?

Yes is that possible?

Try this script:

procedure OnBeforeCompilation;
var I,J:Integer;
    NewProcedure,EntryPointProcedure:TVMProcedure;
    CurRecord:TIntelRecord;
    FirstOperand:TOperand;
begin
  with VMProtector do
   begin
    I:=IndexOfAddress(InputFile.EntryPoint);
    if I>-1 then
     begin
      EntryPointProcedure:=Procedures[I];
      for J:=0 to EntryPointProcedure.Count-1 do
       begin
        CurRecord:=EntryPointProcedure[J];
        if CurRecord.CommandType=cmCall then
         begin
          FirstOperand:=CurRecord.Operands[0];
          if FirstOperand.OperandType=[otValue] then
           begin
            NewProcedure:=AddByAddress(FirstOperand.Value,ctUltra,True);
            if NewProcedure<>nil then
             NewProcedure.CompilationOptions:=[coCheckCRC,coEncryptRegs,coEncryptValues];
           end;
         end; 
       end;
     end;  
   end;
end;

P.S. TVMProcedure.ExtAddresses - it`s a user defined external addresses (not is calls).

Ah thank you very much I tried doing it that way with TIntelRecord but docs do not say there is OperandType and Operands so i thought it was not possible that way.

BTW: Scripting part of VMProtect is a very powerful and great feature if used correctly. Maybe put that information on main site :sunglasses:. i didn’t know how good it is until recently when I started reading the docs.

The description of TIntelRecord.Operands (TOperand, TOperandSize, TOperandType, etc.) will be added to the help file in next versions.

This is a nice script, indeed :smiley:
But during trying, this error occurs:

[Error] 10002C250: Minimal size of procedure for compilation is 5 bytes

Reason: the called subroutine is just:
000000010002C250 33C0 xor eax, eax
000000010002C252 C3 ret

Is there a way to check whether a subroutine is too small to be added with AddByAddress in the script, so this error does not occur - or there a way to silently skip these subroutines w/o terminating the protection process?

Thanks in advance,
Henrik

henrik

Is there a way to check whether a subroutine is too small to be added with AddByAddress in the script, so this error does not occur - or there a way to silently skip these subroutines w/o terminating the protection process?

The check of length can be made by script:

procedure OnBeforeCompilation;
var I,J,K,R:Integer;
    NewProcedure,EntryPointProcedure:TVMProcedure;
    CurRecord:TIntelRecord;
    FirstOperand:TOperand;
    ProcLength:Longint;
begin
  with VMProtector do
   begin
    I:=IndexOfAddress(InputFile.EntryPoint);
    if I>-1 then
     begin
      EntryPointProcedure:=Procedures[I];
      for J:=0 to EntryPointProcedure.Count-1 do
       begin
        CurRecord:=EntryPointProcedure[J];
        // need only CALL instruction
        if CurRecord.CommandType=cmCall then
         begin
          FirstOperand:=CurRecord.Operands[0];
          // the first operand must be value 
          if FirstOperand.OperandType=[otValue] then
           begin
            NewProcedure:=AddByAddress(FirstOperand.Value,ctUltra,True);
            // new procedure is added
            if NewProcedure<>nil then
             begin
              ProcLength:=0;
              K:=NewProcedure.IndexOfAddress(NewProcedure.Address);
              // need start index of procedure entry 
              if K>-1 then
               for R:=K to NewProcedure.Count-1 do
                begin
                 CurRecord:=NewProcedure[K];
                 if CurRecord.Address<>NewProcedure.Address+ProcLength then
                  break;
                 ProcLength:=ProcLength+CurRecord.DumpLength;
                 // optimization  
                 if ProcLength>=5 then
                  break;
                end;
              // the check of length 
              if ProcLength<5 then
               NewProcedure.Free
              else 
               NewProcedure.CompilationOptions:=[coCheckCRC,coEncryptRegs,coEncryptValues]
             end;  
           end;
         end; 
       end;
     end;  
   end;
end;

Wow :open_mouth:

Henrik