unit DhaeMarker;
{ Dhaedalida RabbitStart / RabbitEnd virtualization markers for Delphi / Object Pascal
  and Free Pascal. Covers BOTH x86-64 (PE32+) and 32-bit x86 (PE32).

  Each marker emits the 8 magic bytes of sdk/dhae_marker_sig.h verbatim into
  code, so the Dhaedalida GUI detects a caller exactly like the C binding. The
  DB values below MUST equal DHAE_SIG_RABBITSTART / DHAE_SIG_RABBITEND there.

      x64:  48 B8 <magic> C3      movabs rax, magic ; ret
      x86:  EB 08 <magic> C3      jmp short $+10 ; <data> ; ret

  On 32-bit there is no 64-bit immediate to hide the magic in, so it is emitted
  as inline DATA and jumped over - the EB 08 branch lands exactly on the C3.

  Usage - bracket the routine you want protected:

      uses DhaeMarker;
      function ValidateLicense(const Key: string): Boolean;
      begin
        RabbitStart;
        // ... sensitive code ...
        RabbitEnd;
        Result := True;
      end;

  Targets: Delphi XE2+ (Win32 or Win64) or FPC (-Px86_64 -Twin64 / -Pi386
  -Twin32). Raw DB bytes keep the magic within the first bytes of the routine
  regardless of any compiler-inserted prologue, so detection's 16-byte window is
  satisfied either way. Both markers take no parameters, so a bare RET is the
  correct epilogue under register (Delphi's default), stdcall and cdecl alike. }

interface

procedure RabbitStart;
procedure RabbitEnd;
procedure BearStart;
procedure BearEnd;

implementation

{$IFDEF FPC}{$ASMMODE INTEL}{$ENDIF}

{$IFDEF CPUX64}

procedure RabbitStart; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $48, $B8, $01, $54, $76, $DE, $C0, $E5, $1A, $D1   // movabs rax, 0D11AE5C0DE765401h
  DB $C3                                                 // ret
end;

procedure RabbitEnd; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $48, $B8, $02, $54, $76, $DE, $C0, $E5, $1A, $D1   // movabs rax, 0D11AE5C0DE765402h
  DB $C3
end;

procedure BearStart; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $48, $B8, $05, $54, $76, $DE, $C0, $E5, $1A, $D1   // movabs rax, 0D11AE5C0DE765405h
  DB $C3
end;

procedure BearEnd; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $48, $B8, $06, $54, $76, $DE, $C0, $E5, $1A, $D1   // movabs rax, 0D11AE5C0DE765406h
  DB $C3
end;

{$ELSE}

procedure RabbitStart; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $EB, $08                                            // jmp short $+10 -> the RET below
  DB $01, $54, $76, $DE, $C0, $E5, $1A, $D1              // DHAE_SIG_RABBITSTART, little-endian
  DB $C3                                                 // ret
end;

procedure RabbitEnd; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $EB, $08
  DB $02, $54, $76, $DE, $C0, $E5, $1A, $D1              // DHAE_SIG_RABBITEND, little-endian
  DB $C3
end;

procedure BearStart; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $EB, $08                                            // jmp short $+10 -> the RET below
  DB $05, $54, $76, $DE, $C0, $E5, $1A, $D1              // DHAE_SIG_BEARSTART, little-endian
  DB $C3                                                 // ret
end;

procedure BearEnd; assembler; {$IFDEF FPC}nostackframe;{$ENDIF}
asm
  DB $EB, $08
  DB $06, $54, $76, $DE, $C0, $E5, $1A, $D1              // DHAE_SIG_BEAREND, little-endian
  DB $C3
end;

{$ENDIF}

end.
