1

Summary I have a need to embed an executable in my software. This executable is provided by my client and the client wishes that the executable should be embedded into the software that I am developing and should be extracted into memory and executed from there.

Details Details that I can reveal here:

We have build a software that is automating Adobe Photoshop for performing some tasks. In this software our client asked us to add facility to write/record user selected photos to a DVD/CD. DVD/CD recorded thus is not copyable!

For performing this task, the client supplied us with an executable that can record content to DVD/CD based on a text file (containing list of files to be burned) supplied to it! We are using this executable for writing/recording.

Now the client want us to embedded this file in the software that we have developed and when the user selects the option for writing/recording to DVD/CD the executable should be extracted in memory and executed from memory.

When we try to protect this executable with available software protection, software like SoftLocx, Enigma, SoftDog, WinICE, etc. the executable crashes that is why we took the decision to embed it in our software.

I hope now I have provided enough details.

Can we do something like this in VB6/Delphi?

16
  • I'm not sure extactly how to do it in VB6/Delphi but I guess you could embed the executable as a binary resource. Commented Dec 8, 2011 at 10:54
  • 7
    What language is your software written in? In must be either VB6 or Delphi. You can easily link the file as a resource and then extract to disk at runtime. But it will be trivial for a hacker to extract it. Even if you encrypt before linking as resource, your executable will extract this file to disk and the hacker can get hold of it. In other words, what you are proposing will not protect this executable from being copyied. Commented Dec 8, 2011 at 10:55
  • 2
    Ah, I see, execute from memory. That's not supported on Windows. Commented Dec 8, 2011 at 11:10
  • 2
    If he can provide the code as a .DLL instead, that can be loaded in-memory without the need to save it to disk (I have done this on several occasions). Commented Dec 8, 2011 at 12:11
  • 7
    Tell your client this is a horrific idea. Most virus scanners will choke on the executable code hidden inside another, and real-time AV software will choke on trying to execute it from memory in a way that mimics malware. Plus, your client is probably violating copyright law in most jurisdictions by using the third-party software in the way they're wanting to use it. Please encourage your client to do it correctly; add the Delphi code to your app that accepts a list of filenames and writes those files to CD/DVD. The IMAPI2 interfaces in Windows allow you to do this pretty easily. Commented Dec 8, 2011 at 12:43

2 Answers 2

2

Have you tried the last version of Enigma Virtual Box? I've been able to invoke a bundled EXE using this free tool. I think the latest enhancements to the virtual box tech shows up EVB first. If you try, make sure click share virtual system to child process.

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

Here is some (untested) code I found if you want to run EXE from memory. Maybe this can help.

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.

Example of use:

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;
Sign up to request clarification or add additional context in comments.

5 Comments

I have checked it but can't use it as I cannot get it to embed the target exe into my software and execute it from memory on demand.
Is that EXE compressed or protected? I had issue with compressed EXEs. In my case it was compressed with UPX. I decompressed it and I was then able to get it to work. I ran it with ShellExecuteEx.
I updated my post with some code that allows you to run EXE from memory. The code is untested, however. I found it just today.
Thanks for this code. I did manage to build an executable that will execute another exe embedded into it directly in memory. Of course it is still not stable but you code did get me started. Once again Thanks.
Cool, good to know your making progress. I was about to check in and see how it was coming along.
1

You can save the executable file as a resource and extract it at run time, however you will not be able to load it directly into memory and execute it. There is no feature in Windows to load an executable from memory.

You'll need to save it to disk first, and then execute it.

Technically, you could overflow your own buffers, but that's a hack and wouldn't be reliable.

This is also true for a .dll. There's no feature to load a dll from memory in Windows.

If the utility program needs to be copy protected, then it should have copy protection built in. Perhaps, it would be ideal to share the same copy protection scheme as the main application.

There are ways of securing calls to a dll to help ensure that only your program can call it, but without a better explanation of what your goal is, I'm reluctant to go into it further, so as not to waste your time.

There are also quite a few Delphi libraries for CD/DVD burning.

See this previous answer for more information about loading and extracting a resource:

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

1 Comment

It is not possible to convert the executable to dll as we do not have the code and our client has a different software developing firm who had developed this utility for them but now they both are not working together any more.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.