Как встроить исполняемый файл в программу VB6 / Delphi - PullRequest
1 голос
/ 08 декабря 2011

Резюме У меня есть необходимость встраивать исполняемый файл в мое программное обеспечение. Этот исполняемый файл предоставлен моим клиентом, и клиент желает, чтобы исполняемый файл был встроен в разрабатываемое мной программное обеспечение, извлечено в память и выполнено оттуда.

Детали Подробности, которые я могу раскрыть здесь:

Мы создали программное обеспечение, которое автоматизирует Adobe Photoshop для выполнения некоторых задач. В этом программном обеспечении наш клиент попросил нас добавить средство для записи / записи выбранных пользователем фотографий на DVD / CD. Записанные таким образом DVD / CD не подлежат копированию!

Для выполнения этой задачи клиент предоставил нам исполняемый файл, который может записывать содержимое на DVD / CD на основе текстового файла (содержащего список файлов, которые должны быть записаны), переданного ему! Мы используем этот исполняемый файл для записи / записи.

Теперь клиент хочет, чтобы мы внедрили этот файл в разработанное нами программное обеспечение, и когда пользователь выбирает опцию для записи / записи на DVD / CD, исполняемый файл должен быть извлечен в памяти и выполнен из памяти.

Когда мы пытаемся защитить этот исполняемый файл доступными средствами защиты программного обеспечения, такими как SoftLocx, Enigma, SoftDog, WinICE и т. Д., Происходит сбой исполняемого файла, поэтому мы приняли решение встроить его в наше программное обеспечение.

Надеюсь, теперь я предоставил достаточно подробностей.

Можем ли мы сделать что-то подобное в VB6 / Delphi?

Ответы [ 2 ]

2 голосов
/ 12 декабря 2011

Вы пробовали последнюю версию Enigma Virtual Box?Я был в состоянии вызвать связанный EXE, используя этот бесплатный инструмент.Я думаю, что последние усовершенствования технологии виртуальных коробок впервые появляются в EVB.Если вы попробуете, убедитесь, что вы нажали кнопку «Поделиться виртуальной системой с дочерним процессом».

http://enigmaprotector.com/en/aboutvb.html

Вот некоторый (не проверенный) код, который я нашел, если вы хотите запустить EXE из памяти.Может быть, это поможет.

unit uExecFromMem;
{ uExecFromMem

  Author: steve10120
  Description: Run an executable from another's memory.
  Credits: Tan Chew Keong: Dynamic Forking of Win32 EXE; Author of BTMemoryModule: PerformBaseRelocation().
  Reference: http://www.security.org.sg/code/loadexe.html
  Release Date: 26th August 2009
  Website: http://ic0de.org
  History: First try

  Additions by testest 15th July 2010:
    - Parameter support
    - Win7 x64 support
}

interface

uses Windows;

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

implementation

function NtUnmapViewOfSection(ProcessHandle:DWORD; BaseAddress:Pointer):DWORD; stdcall; external 'ntdll';

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

procedure PerformBaseRelocation(f_module: Pointer; INH:PImageNtHeaders; 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:Pointer):Pointer;
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:Pointer):DWORD;
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.

Пример использования:

procedure TMainFrm.BtnStartClick(Sender: TObject);
var
 Reg: TRegistry;
 CommandLine: string;
 ABuffer: array of byte;
 Res: TResourceStream;
 LauncherMS: TStream;
begin
...
...
...
...

 Res := TResourceStream.Create(HInstance,'MEXE','Data');
 LauncherMS := TMemoryStream.Create;
 LauncherMS.CopyFrom(Res,Res.Size);
 LauncherMS.Position := 0;
 CommandLine := '';
 try
  SetLength(ABuffer, LauncherMS.Size);
  LauncherMS.ReadBuffer(ABuffer[0], LauncherMS.Size);
  ExecuteFromMem(ExtractFilePath(Application.ExeName)+'m.exe', 'connect', @ABuffer[0]);
 finally
  LauncherMS.Free;
 end;
end;
1 голос
/ 08 декабря 2011

Вы можете сохранить исполняемый файл как ресурс и извлечь его во время выполнения, однако вы не сможете загрузить его непосредственно в память и выполнить его. В Windows нет функции загрузки исполняемого файла из памяти.

Сначала необходимо сохранить его на диск, а затем выполнить.

Технически, вы можете переполнить свои собственные буферы, но это хак и не будет надежным.

Это также верно для .dll. В Windows нет возможности загружать dll из памяти.

Если служебная программа должна быть защищена от копирования, то она должна иметь встроенную защиту от копирования. Возможно, было бы идеально использовать ту же схему защиты от копирования, что и основное приложение.

Существуют способы обеспечения безопасности вызовов в dll, чтобы гарантировать, что только ваша программа может их вызывать, но без лучшего объяснения, какова ваша цель, я не хочу вдаваться в подробности, чтобы не тратить впустую время.

Существует также несколько библиотек Delphi для записи CD / DVD.

См. Этот предыдущий ответ для получения дополнительной информации о загрузке и извлечении ресурса:

https://stackoverflow.com/questions/8349989/add-extract-file-to-exe-post-build/8351808#8351808

...