将整数转换为字符串会使注入的父进程崩溃 [Delphi]

Converting Integer to String crashes Injected Parent Process [Delphi]

我的应用程序是一个 x64 Windows 控制台应用程序,需要将自身注入另一个 运行 进程。从命令行执行时,输入要注入的进程的 PID 作为命令行参数。

在父进程下线程 运行 的上下文中,我可以使用字符串变量,但我很难弄清楚如何将整数转换为字符串Delphi。我尝试从 Integer 转换为 String 的所有内容都会导致父进程崩溃。我知道标准 Delphi RTL 命令不会起作用,我需要使用 WINAPI 函数。

这是我尝试过的一些命令的列表:

一个。 IntToStr(int) 使父进程崩溃;

b。 itoa(src, dst, radix) 使父进程崩溃;

c。 strcpy(dst, src) 使父进程崩溃;

我已经包含了一段在 Delphi RAD Studio RIO 10.3.2 中编译的工作代码片段。请务必将目标平台设置为 Windows-64 位。按原样,该程序只是简单地注入一个进程并显示一个 MessageBox。我已经包含并注释掉了使父进程崩溃的命令。

在此示例程序中,我尝试显示使用 GetCurrentProcessId() 确定的 运行 进程的 PID,其中 returns PID 作为整数。挑战在于尝试将变量 'x' 转换为字符串变量 's'。我还尝试使用 itoa() 将 'x' 转换为 PAnsiChar 变量,但失败了。

我预计我的问题可能是我没有加载正确的 Windows 库,或者我没有定义我尝试使用的 WINAPI 函数。

任何帮助将不胜感激,因为我被困住了,在我克服这个障碍之前无法前进。

program Inject;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Variants,
  System.Classes,
  Winapi.Windows,
  Winapi.Messages,
  ShellAPI,
  System.Win.crtl,
  shlobj;

var
  ClassName: string;
  ProcessHandle: Thandle;
  Active : Integer;
  PID : integer;
  Module, NewModule: Pointer;
  Size: SIZE_T;
  BytesWritten: SIZE_T;
  TID: DWORD;

procedure Main;
var
  x : Integer;
  s : string;
  p : PAnsiChar;
begin
  LoadLibrary('kernel32.dll');
  LoadLibrary('user32.dll');
  LoadLibrary('msvcrt.dll');
  LoadLibrary('win32.dll');

  x := GetCurrentProcessId;

  { This command crashes the parent process }
  // s := IntToStr(x);

  { This command crashes the parent process }
  // itoa(x, p, 10);

  { This command crashes the parent process }
  strcpy(P, PAnsiChar(IntToStr(x)));

  { A standard Message Box works }
  MessageBox(0, 'This Message Box produced by Thread running under Parent Process', 'Process ID', 0);

  { This Message Box crashes the parent process }
  // MessageBox(0, PWideChar(IntToStr(x)), 'Process ID', 0);

  ExitThread(0);
end;

begin
try
   if (ParamCount() > 0) then
   begin
      PID := StrToInt(ParamStr(1));
      ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
      Module := Pointer(GetModuleHandle(nil));
      Size := PImageOptionalHeader64(Pointer(integer(Module) + PImageDosHeader(Module)._lfanew + SizeOf(dword) + SizeOf(TImageFileHeader))).SizeOfImage;
      VirtualFreeEx(ProcessHandle, Module, 0, MEM_RELEASE);
      NewModule := VirtualAllocEx(ProcessHandle, Module, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
      WriteProcessMemory(ProcessHandle, NewModule, Module, Size, BytesWritten);
      CreateRemoteThread(ProcessHandle, nil, 0, @Main, Module, 0, TID);
      WaitForSingleObject(ProcessHandle, 1000);
  end
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

在您的 Main() 过程中,当调用 itoa()strcpy() 时,您的 p 变量是一个 未初始化的指针 ,它不指向任何有效的内存。您需要分配内存来写入,例如:

procedure Main;
var
  x : Integer;
  str : array[0..12] of AnsiChar;
begin
  LoadLibrary('kernel32.dll');
  LoadLibrary('user32.dll');
  LoadLibrary('msvcrt.dll');
  LoadLibrary('win32.dll');

  x := GetCurrentProcessId;
  itoa(x, str, 10);

  MessageBoxA(0, str, 'Process ID', 0);
  ExitThread(0);
end;

strcpy() 的情况下,您还有一个额外的问题,即 IntToStr() in Delphi 2009+ returns a UnicodeString,而不是 AnsiString,所以你对 PAnsiChar 的类型转换无论如何都是错误的。

或者,查看 user32.dll 中的 Win32 wsprintfA() 函数:

procedure Main;
var
  x : Integer;
  str : array[0..12] of AnsiChar;
begin
  LoadLibrary('kernel32.dll');
  LoadLibrary('user32.dll');
  LoadLibrary('msvcrt.dll');
  LoadLibrary('win32.dll');

  x := GetCurrentProcessId;
  wsprintfA(str, '%d', x);

  MessageBoxA(0, str, 'Process ID', 0);
  ExitThread(0);
end;