将整数转换为字符串会导致注入的父进程崩溃[Delphi] [英] Converting Integer to String crashes Injected Parent Process [Delphi]

查看:122
本文介绍了将整数转换为字符串会导致注入的父进程崩溃[Delphi]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My application is an x64 Windows console app that needs to inject itself into another running process. When executed from the command line, you enter the PID of the process you want to inject into as a command line parameter.

在父级下运行的线程的上下文中过程中,我可以使用String变量,但是在尝试弄清楚如何在Delphi中将Integer转换为String时遇到了困难。我尝试从Integer转换为String的所有操作都会使父进程崩溃。我知道标准的Delphi RTL命令无法使用,并且需要使用WINAPI函数。

Within the context of a thread running under a parent process, I'm able to work with String variables, but I'm having difficulty trying to figure out how to convert an Integer to a String in Delphi. Everything I've tried to convert from Integer to String has the effect of crashing the parent process. I understand that standard Delphi RTL commands are not going to work, and that I need to use WINAPI functions.

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

Here is a list of some of the commands I've tried:

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

a. IntToStr(int) crashes parent process;

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

b. itoa(src, dst, radix) crashes parent process;

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

c. strcpy(dst, src) crashes parent process;

我提供了一个有效的代码段,该代码段在Delphi RAD Studio RIO 10.3.2中进行了编译。确保将目标平台设置为Windows 64位。照原样,该程序只是注入到进程中并显示MessageBox。我已经包含并注释了使父进程崩溃的命令。

I've included a working snippet of code that compiles in Delphi RAD Studio RIO 10.3.2. Be sure to set the Target Platform as a Windows-64-bit. As-is, the program simply injects into a process and displays a MessageBox. I've included and commented out the commands that crash the parent process.

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

In this sample program, I'm attempting to display the PID of the running process which was determined using GetCurrentProcessId(), which returns the PID as an Integer. The challenge is trying to convert the variable 'x' to a string variable 's'. I've also tried converting 'x' into a PAnsiChar variable using itoa(), which fails.

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

I anticipate that my issue is likely that I'm not loading the correct Windows library, or that I'm not defining the WINAPI function that I'm trying to use.

任何帮助将不胜感激,因为我遇到了麻烦,

Any assistance would be greatly appreciated, as I'm stuck and can't move forward until I get past this hurdle.

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 变量是未初始化的指针,它没有指向任何有效的内存。您需要分配要写入的内存,例如:

In your Main() procedure, when calling itoa() or strcpy(), your p variable is an uninitialized pointer, it doesn't point to any valid memory. You need to allocate memory to write to, eg:

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(),您还有另外一个问题,就是在Delphi 2009+中, IntToStr()返回 UnicodeString ,而不是 AnsiString ,所以您对 PAnsiChar 的打字还是错误的。

In the case of strcpy(), you have the additional problem that IntToStr() in Delphi 2009+ returns a UnicodeString, not an AnsiString, so your typecast to PAnsiChar is wrong anyway.

在Win32 wsprintfA( ) user32.dll 中的功能:

Alternatively, look at the Win32 wsprintfA() function in user32.dll:

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;

这篇关于将整数转换为字符串会导致注入的父进程崩溃[Delphi]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆