views:

442

answers:

7

I am developing a library that uses one or more helper executable in the course of doing business. My current implementation requires that the user have the helper executable installed on the system in a known location. For the library to function properly the helper app must be in the correct location and be the correct version.

I would like to removed the requirement that the system be configured in the above manner.

Is there a way to bundle the helper executable in the library such that it could be unpacked at runtime, installed in a temporary directory, and used for the duration of one run? At the end of the run the temporary executable could be removed.

I have considered automatically generating an file containing an unsigned char array that contains the text of the executable. This would be done at compile time as part of the build process. At runtime this string would be written to a file thus creating the executable.

Would it be possible to do such a task without writing the executable to a disk (perhaps some sort of RAM disk)? I could envision certain virus scanners and other security software objecting to such an operation. Are there other concerns I should be worried about?

The library is being developed in C/C++ for cross platform use on Windows and Linux.

+1  A: 

Slightly different approach than using an unsigned char* array is to put the entire executable binary as resource of the dll. At runtime, you can save the binary data as a local temp file and execute the app. I'm not sure if there is a way to execute an executable in memory, though.

Kei
+7  A: 

"A clever person solves a problem. A wise person avoids it." — Albert Einstein

In the spirit of this quote I recommend that you simply bundle this executable along with the end-application.

Just my 2 cents.

StackedCrooked
I like the quote :) +1
Idan K
My goal is to avoid forcing the developers of the end-application (be it my organization or a third party) from managing the helper applications.
Marc
@Marc, I understand, and I appreciate your ambition. Give it a try. Write out the file in RAM, and run it from there. I don't know how to do this though, please post your solution if you find it. I found this little utility, maybe it will help: http://deadnode.org/sw/bin2h/
StackedCrooked
Also, for what it's worth. The Poco C++ library (Poco Foundation to be precise) provides cross-platform utilities for launching processes, and also for creating temp files. This may aid you as well.
StackedCrooked
A: 

There is a way in Windows to run an executable from within memory without writing it to disk. The problem is that due to modern security systems (DEP) this probably won't work on all systems and almost any anti-malware scanner will detect it and warn the user.

My advice is to simply package the executable into your distribution, it's certainly the most reliable way to achieve this.

milan1612
DEP is not a problem at all. You merely need to tell Windows that it should now treat a block of memory as code, and no longer as data. And that function call obviously has to come from existing code. Even programs stupid enough to call gets() will not subsequently mark that buffer as executable.
MSalters
+1  A: 

For the library to function properly the helper app must be in the correct location

On Windows, would that be the Program Files directory or System32 directory?

This might be a problem. When an application is installed, particularly in a corporate environment, it usually happens in an context with administrative rights. On Vista and later with UAC enabled (the default), this is necessary to write to certain directories. And most Unix flavours have had sensible restrictions like that for as long as anyone can remember.

So if you try to do it at the time the host application calls into your library, that might not be in a context with sufficient rights to install the files, and so your library would put constraints on the host application.

(Another thing that will be ruled out is Registry changes, or config file updates on the various Unices, if the host application doesn't have the ability to elevate the process to an administrative level.)

Having said all that, you say you're considering unpacking the helpers into a temporary directory, so maybe this is all moot.

Daniel Earwicker
A: 

Well, my first thought would be: what does this helper executable do that couldn't be done within your library's code itself, perhaps using a secondary thread if necessary. This might be something to consider.

But as for the actual question... If your "library" is actually bundled up as a dll (or even an exe) then at least Windows has relatively simpe support for embedding files within your library.

The resource mechanism that allows things like version information and icons to be embedded within executables can also allow arbitrary chunks of data. Since I don't know what development environment you're using, I can't say exactly how to do this. But roughly speaking, you'd need to create a custom resource with a type of "FILE" or something sensible like that and point it at the exe you want to embed.

Then, when you want to extract it, you would write something like

HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_MY_EMBEDDED_FILE), "FILE");
HGLOBAL hResourceData = LoadResource(NULL, hResource);
LPVOID pData = LockResource(hResourceData);
HANDLE hFile = CreateFile("DestinationPath\\Helper.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwBytesWritten = 0;
WriteFile(hFile, pData, SizeofResource(NULL, hResource), &dwBytesWritten, NULL);
CloseHandle(hFile);

(filling in your own desired path, filename, and any appropriate error checking of course)

After that, the helper exe exists as a normal exe file and so you can execute it however you normally would.

For removing the file after use, you should investigate the flags for CreateFile, particularly FILE_FLAG_DELETE_ON_CLOSE. You might also look at using MoveFileEx when combining the MOVEFILE_DELAY_UNTIL_REBOOT flag with NULL passed for the new file name. And of course, you could always delete it in your own code if you can tell when the executable has ended.

I don't know enough about Linux executables, so I don't know if a similar feature is available there.

If Linux doesn't provide any convenient mechanism and/or if this idea doesn't suit your needs in Windows, then I suppose your idea of generating an unsigned char array from the contents of the helper exe would be the next best way to embed the exe in your library.

TheUndeadFish
+2  A: 

You can use xxd to convert a binary file to a C header file.

$ echo -en "\001\002\005" > x.binary

$ xxd -i x.binary 
unsigned char x_binary[] = {
  0x01, 0x02, 0x05
};
unsigned int x_binary_len = 3;

xxd is pretty standard on *nix systems, and it's available on Windows with Cygwin or MinGW, or Vim includes it in the standard installer as well. This is an extremely cross-platform way to include binary data into compiled code.

Another approach is to use objcopy to append data on to the end of an executable -- IIRC you can obtain objcopy and use it for PEs on Windows.

One approach I like a little better than that is to just append raw data straight onto the end of your executable file. In the executable, you seek to the end of the file, and read in a number, indicating the size of the attached binary data. Then you seek backwards that many bytes, and fread that data and copy it out to the filesystem, where you could treat it as an executable file. This is incidentally the way that many, if not all, self-extracting executables are created.

If you append the binary data, it works with both Windows PE files and *nix ELF files -- neither of them read past the "limit" of the executable.

Of course, if you need to append multiple files, you can either append a tar/zip file to your exe, or you'll need a slightly more advance data structure to read what's been appended.

You'll also probably want to UPX your executables before you append them.

You might also be interested in the LZO library, which is reportedly one of the fastest-decompressing compression libraries. They have a MiniLZO library that you can use for a very lightweight decompressor. However, the LZO libraries are GPL licensed, so that might mean you can't include it in your source code unless your code is GPLed as well. On the other hand, there are commercial licenses available.

Mark Rushakoff
+1  A: 

Qt has an excellent method of achieving this: QResource

"The Qt resource system is a platform-independent mechanism for storing binary files in the application's executable."

You don't say if you are currently using Qt, but you do say "C++ for cross platform use on Windows and Linux", so even if you aren't using it, you may want to consider starting.

KeyserSoze