Выполнение EXE из memoryStream в Delphi2010

  • Автор темы Luben111
  • Обновлено
  • 09, Dec 2010
  • #1
Здравствуйте, Мне мучить такая проблема - не могу запустить EXE файлы из MemoryStream в Delphi2010, но в D7 все работает прекрасно (посмотрите на файл Unit1.zip). Буду очень благодарен если помогите исправить файл Unit1.zip чтобы он работал с Delphi2010 (сейчас файл работает только с Delphi 7). Unit1.zip содержит очень полезные рутины (100% работающие на Д7) и сама идея запускать EXE из ресурсов очень заманчивая.

Luben111


Рег
27 Nov, 2010

Тем
82

Постов
207

Баллов
657
  • 09, Dec 2010
  • #2
Для shellexecute все файлы надо существовать на диске.

Красота запускать файлы из MemoryStream в том что EXE может быть в ресурсы. Дам пример - если программа нуждается из какие то DLL, если они не присутствуют программа глючить.

Теперь представьте что после запуска програма проверяет для DLL, если они не присутствуют инсталирует DLL и потом запускает основная EXE
 

Luben111


Рег
27 Nov, 2010

Тем
82

Постов
207

Баллов
657
  • 09, Dec 2010
  • #3
Проблема решена - после замены PChar на Pbyte (Д2010 использует WideChar) программа проработала. Так если хотите запускать EXE из ресурсов без надобности сохранит файл на диске - смотрите атачмент
 

Luben111


Рег
27 Nov, 2010

Тем
82

Постов
207

Баллов
657
  • 09, Dec 2010
  • #4
К сожалению запуск EXE внутри файла выглядит для некоторых антивирусных программ как DelfInject.gen вирус так что я не рекомендую использование метода и возвращаюсь на ShellExecute
 

Luben111


Рег
27 Nov, 2010

Тем
82

Постов
207

Баллов
657
  • 08, Aug 2012
  • #5
решение проблемы рабочий код для windows 7 x64 тока что попробавал на delphi 7; (не ругается антивирусом (каспер) ) вызываете процедуру ExecuteFromMem(szFilePath, szParams: string; pFile: Pointer)WORD; szFilePath - путь к любому exe файлу (можно указать application.exename) szParams - пустой pFile: Pointer - указатель на поток в котором находится exe файл Tmemorystream.memory;
unit Unit2;

interface

uses Windows;

function ExecuteFromMem(szFilePath, szParams: string; pFile: Pointer)



WORD;

implementation

function NtUnmapViewOfSection(ProcessHandle



WORD; BaseAddress



ointer)



WORD; stdcall; external 'ntdll';

type
PImageBaseRelocation = ^TImageBaseRelocation;
TImageBaseRelocation = packed record
VirtualAddress: DWORD;
SizeOfBlock: DWORD;
end;

procedure PerformBaseRelocation(f_module: Pointer; INH



ImageNtHeaders; f_delta: Cardinal); stdcall;
var
l_i: Cardinal;
l_codebase: Pointer;
l_relocation: PImageBaseRelocation;
l_dest: Pointer;
l_relInfo: ^Word;
l_patchAddrHL: ^DWord;
l_type, l_offset: integer;
begin
l_codebase := f_module;
if INH^.OptionalHeader.DataDirectory[5].Size > 0 then
begin
l_relocation := PImageBaseRelocation(Cardinal(l_codebase) + INH^.OptionalHeader.DataDirectory[5].VirtualAddress);
while l_relocation.VirtualAddress > 0 do
begin
l_dest := Pointer((Cardinal(l_codebase) + l_relocation.VirtualAddress));
l_relInfo := Pointer(Cardinal(l_relocation) + 8);
for l_i := 0 to (trunc(((l_relocation.SizeOfBlock - 8) / 2)) - 1) do
begin
l_type := (l_relInfo^ shr 12);
l_offset := l_relInfo^ and $FFF;
if l_type = 3 then
begin
l_patchAddrHL := Pointer(Cardinal(l_dest) + Cardinal(l_offset));
l_patchAddrHL^ := l_patchAddrHL^ + f_delta;
end;
inc(l_relInfo);
end;
l_relocation := Pointer(cardinal(l_relocation) + l_relocation.SizeOfBlock);
end;
end;
end;

function AlignImage(pImage



ointer)



ointer;
var
IDH: PImageDosHeader;
INH: PImageNtHeaders;
ISH: PImageSectionHeader;
i: WORD;
begin
IDH := pImage;
INH := Pointer(Integer(pImage) + IDH^._lfanew);
GetMem(Result, INH^.OptionalHeader.SizeOfImage);
ZeroMemory(Result, INH^.OptionalHeader.SizeOfImage);
CopyMemory(Result, pImage, INH^.OptionalHeader.SizeOfHeaders);
for i := 0 to INH^.FileHeader.NumberOfSections - 1 do
begin
ISH := Pointer(Integer(pImage) + IDH^._lfanew + 248 + i * 40);
CopyMemory(Pointer(DWORD(Result) + ISH^.VirtualAddress), Pointer(DWORD(pImage) + ISH^.PointerToRawData), ISH^.SizeOfRawData);
end;
end;

function Get4ByteAlignedContext(var Base: PContext): PContext;
begin
Base := VirtualAlloc(nil, SizeOf(TContext) + 4, MEM_COMMIT, PAGE_READWRITE);
Result := Base;
if Base <> nil then
while ((DWORD(Result) mod 4) <> 0) do
Result := Pointer(DWORD(Result) + 1);
end;

function ExecuteFromMem(szFilePath, szParams:string; pFile



ointer)



WORD;
var
PI: TProcessInformation;
SI: TStartupInfo;
CT: PContext;
CTBase: PContext;
IDH: PImageDosHeader;
INH: PImageNtHeaders;
dwImageBase: DWORD;
pModule: Pointer;
dwNull: DWORD;
begin
if szParams <> '' then szParams := '"'+szFilePath+'" '+szParams;

Result := 0;
IDH := pFile;
if IDH^.e_magic = IMAGE_DOS_SIGNATURE then
begin
INH := Pointer(Integer(pFile) + IDH^._lfanew);
if INH^.Signature = IMAGE_NT_SIGNATURE then
begin
FillChar(SI, SizeOf(TStartupInfo), #0);
FillChar(PI, SizeOf(TProcessInformation), #0);
SI.cb := SizeOf(TStartupInfo);
if CreateProcess(PChar(szFilePath), PChar(szParams), nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, SI, PI) then
begin
CT := Get4ByteAlignedContext(CTBase);
if CT <> nil then
begin
CT.ContextFlags := CONTEXT_FULL;
if GetThreadContext(PI.hThread, CT^) then
begin
ReadProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @dwImageBase, 4, dwNull);
if dwImageBase = INH^.OptionalHeader.ImageBase then
begin
if NtUnmapViewOfSection(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase)) = 0 then
pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
else
pModule := VirtualAllocEx(PI.hProcess, nil, INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
end
else
pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if pModule <> nil then
begin
pFile := AlignImage(pFile);
if DWORD(pModule) <> INH^.OptionalHeader.ImageBase then
begin
PerformBaseRelocation(pFile, INH, (DWORD(pModule) - INH^.OptionalHeader.ImageBase));
INH^.OptionalHeader.ImageBase := DWORD(pModule);
CopyMemory(Pointer(Integer(pFile) + IDH^._lfanew), INH, 248);
end;
WriteProcessMemory(PI.hProcess, pModule, pFile, INH.OptionalHeader.SizeOfImage, dwNull);
WriteProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @pModule, 4, dwNull);
CT.Eax := DWORD(pModule) + INH^.OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, CT^);
ResumeThread(PI.hThread);
Result := PI.hThread;
end;
end;
VirtualFree(CTBase, 0, MEM_RELEASE);
end;
if Result = 0 then
TerminateProcess(PI.hProcess, 0);
end;
end;
end;
end;

end.
 

Alex4012


Рег
27 Jul, 2012

Тем
73

Постов
230

Баллов
625
  • 27, Jul 2013
  • #6
luben111, post: 726822:Проблема решена - после замены PChar на Pbyte (Д2010 использует WideChar) программа проработала. Так если хотите запускать EXE из ресурсов без надобности сохранит файл на диске - смотрите атачмент
Почему не могу скачать этот Zip? Открывается мелкая картинка в бравзере и всё! Где архив Очень надо! (желательно к этому и первый тоже, тот что в первом посте, так как тоже не открывает)
 

-gigant-x


Рег
27 Jul, 2013

Тем
75

Постов
196

Баллов
571
  • 28, Jul 2013
  • #7
alex4012, post: 726824:рабочий код для windows 7 x64 тока что попробавал на delphi 7;
(не ругается антивирусом (каспер) )
вызываете процедуру ExecuteFromMem(szFilePath, szParams: string; pFile: Pointer)



WORD;

szFilePath - путь к любому exe файлу (можно указать application.exename)
szParams - пустой
pFile: Pointer - указатель на поток в котором находится exe файл
Tmemorystream.memory;

На Delphi XE4 (Win7x64) - код НЕ компилится! Взял твой текст Unit.pas и запустил на новом проекте в режиме Win32Bit
Спотыкается на .Ebx в строках: "ReadProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @dwImageBase, 4, dwNull);"
и WriteProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @pModule, 4, dwNull);
Спотыкается на .Eax в строке: CT.Eax := DWORD(pModule) + INH^.OptionalHeader.AddressOfEntryPoint; --- Короче нужно писать чисто под Delphi XE, так как Delphi 7 уже не актуален в серьёзных современных проектах... Вопрос про отсутствие в D7 поддержки 64Bit вообще даже не встаёт... НАРОД - ПОМОГИТЕ eer: Очень нужен код адаптированный именно под Delphi XE! ac: ;( ek:
Не судите меня строго, осваиваю Delphi сам и с нуля с 15.07.2013 (сам в шоке - но наглядные примеры очень помогают!)
 

-gigant-x


Рег
27 Jul, 2013

Тем
75

Постов
196

Баллов
571
  • 29, Aug 2013
  • #8
Ну допустим сие чудо получится (или уже получилось) возникает мысль на которую никакой поиск НЕ ДАЛ внятного ответа! Народ! ( сколько не рылся по инету - гугл ли-бо не понимает что ищу, либо специально выдаёт не то или ПОЧТИ то что ищу! ) А именно "по данной теме": как снова запустить дамп процесса? Если я имею в памяти рабочую программу (из одного *.exe - без вызовов dll-ок) и всё тип-топ, я например сохраняю дамп процесса на диск!
Вопрос:
Как запустить прогу снова, но уже из созданного мной дампа? - Дамп создан правильно и всё записалось как надо. - Это вообще возможно? (теоретически и/или практически) - Если да, то как? (может где инфа есть) - А так-же как защитить прогу если подобный дамп создаст хакер?
То есть как защитить программу от снятия дампа или что-то в этом роде? Ну или хотя-бы чтоб дамп процесса был полностью НЕ пригоден... eer:
 

-gigant-x


Рег
27 Jul, 2013

Тем
75

Постов
196

Баллов
571
  • 19, Sep 2013
  • #9
Тема. Как c dll так сделать? Если программе нужна dll и она в ресурсах этой программы, подгрузить и использовать функции?
 

Prelryontorie


Рег
19 Sep, 2013

Тем
80

Постов
201

Баллов
631
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно