# Solved: Combine two programs into one image



## mt2002 (Sep 14, 2005)

Hey everyone,

This is for my software project so I decided to post it here. I am looking for a program (preferably command line for Windows) that can combine two programs into a single image.

By "combine", I mean to merge two programs into a single image so the end result of the image is as so:


```
Single image file------
[Program 1][Program 2]
```
Program 1 is a binary 16 bit / 32 bit assembly language program and Program 2 is a 32 bit C++ program, both running in supervisor mode. There are several reasons why I need this. Im having some trouble finding this on Google so if anyone has any links that would be great 

I suppose if we cant find any I can always write it myself... 

Thanks for any help


----------



## -Fabez- (Jul 28, 2008)

Do you want them to be executable from the merged file or do they just have to be merged into one file ?


----------



## lotuseclat79 (Sep 12, 2003)

Hi mt2002,

Have you thought about doing/trying the following:
Create a new c++ program that has one input parameter that can take the form of two values, e.g. 0, 1.

Case the parameters, and
0) switches to the assembler code done in-line, and
1) switches to the c++ coded program.

-- Tom


----------



## mt2002 (Sep 14, 2005)

Didnt know I would get responses so I decided to make it myself  It was easier then I thought 



> Do you want them to be executable from the merged file or do they just have to be merged into one file ?


The merged file would be executable. This is why I needed the binary program to be the first program inside of the file--it contains the instructions to set up the system and run the MSVC++ program.



> Have you thought about doing/trying the following:
> Create a new c++ program that has one input parameter that can take the form of two values, e.g. 0, 1.


Thats a cool idea but wont work in this case as I need both programs. The first program calls the second, and the second program relies on the first program. (The first program contains code that the MSVC++ program cannot do. Thus, to do those functions the MSVC++ program calls the first program).

Its not complete yet, but seems to be working so far. Heres the program in case anyone is interested:

*edit: I added comments for anyone who is interested 


```
#include <iostream>
#include <fstream>
#include <string>

//! program name
const std::string _strProgName = "merge.exe";

//! program interface
class prog {

	std::fstream	m_fOut;
	void display_parm_help ();

public:

	bool init (std::string& fIn);
	int run (int argc, char** argv);
	virtual ~prog ();
};

//! display help info if incorrect command line is used
void prog::display_parm_help () {

	std::cout << "Incorrect command line syntax" << std::endl;
	std::cout << "Syntax: " << _strProgName << " output_file file1 file2 file_n" << std::endl;
}

//! inits the program
//! in/ fIn - filename of output file to work with
bool prog::init (std::string& fIn) {

	//! open up the file in binary mode (and cleared out), create it if its not there
	m_fOut.open(fIn.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); 

	//! if file is not open, there was an error, bail out
	if (!m_fOut.is_open ()) {

		std::cout << "Unable to open output file \'" << fIn << "\', aborting..." << std::endl;
		return false;
	}

	return true;
}

//! dtor called at program exit
prog::~prog () {

	//! close the output file if its still open
	if (m_fOut.is_open ())
		m_fOut.close ();
}

//! main program core
int prog::run (int argc, char **argv) {

	//! argc containes number of command line paramaters passed.
	//! this program requires at least 4: program_name.exe, outfile, file1 and file2
	if (argc < 4) {

		//! its not, so bail out
		display_parm_help ();
		return 1;
	}

	//! paramater 1=output file name
	std::string str (argv[1]);

	//! initialize the program w/ the output file name. If fails return error
	if (!init (str))
		return 1;

	//! stores number of bytes written to output file
	int outLength = 0;

	//! for all of the input files in the paramater list...
	for (int i=2; i<argc; i++) {

		std::cout << "Merging file '" << argv[i] << "'..." << std::endl;

		//! open the file in binary mode
		std::fstream fIn (const_cast <char*> (argv[i]), std::ios_base::in | std::ios_base::binary);

		//! get size of file in bytes, store in length
		fIn.seekg (0, std::ios::end);
		int length = fIn.tellg();
		fIn.seekg (0, std::ios::beg);

		//! read the file into buffer
		char* buffer = new char [length];
		fIn.read (buffer, length);

		//! ...and write the buffer to the output file
		m_fOut.write (buffer, length);

		//! add number of bytes written and cleanup
		outLength+=length;
		delete [] buffer;
		fIn.close ();
	}

	std::cout << outLength << " bytes written to " << argv[1] << ", completed" << std::endl;

	return 0;
}

int main (int argc, char** argv) {

	//! just run the program passing in the command line paramamters
	prog merger;
	return merger.run (argc, argv);
}
```
To use it, just run it from command line like *merge.exe outputfile.bin prog1.sys prog2.exe prog3.exe* etc... It simply merges all files into outputfile.sys one after the other.


----------



## -Fabez- (Jul 28, 2008)

I'm interested in how this works, could you take some time to comment it please ? C++ has never been my strongpoint


----------



## mt2002 (Sep 14, 2005)

> I'm interested in how this works, could you take some time to comment it please ? C++ has never been my strongpoint


I added some comments  I cant explain how the image itself works though (Well, I *can*, but its a bit complex)

Hope this helps out a little


----------



## -Fabez- (Jul 28, 2008)

Thanks for the comments, I shall read through the code now, thanks


----------



## -Fabez- (Jul 28, 2008)

I have read through your comments and just wanted to make sure I get them, so can I ask you some questions about the code and the finished file please ?


----------



## mt2002 (Sep 14, 2005)

Go for it


----------



## pvc_ (Feb 18, 2008)

does this run both applications at the same time? because it seems like it just reads two programs and writes them back to back. To run them, you'll have to separate the two.


----------



## mt2002 (Sep 14, 2005)

> does this run both applications at the same time? because it seems like it just reads two programs and writes them back to back. To run them, you'll have to separate the two.


Neither--the image itself runs as a single program.

The image works do to the way they are written. ie; the first program runs the 2nd program directly after the image is loaded into memory. --They are not treated as separate programs but rather a complete image.

I should add that this was for my systems bootloader which is composed of two programs and is self hosted. I can add more details of how the image works if you are interested.

If they were both PE executables (or similar) this may not work as a single image though--Im not too sure...It works fine for what I need though.


----------



## -Fabez- (Jul 28, 2008)

Thanks for taking the time to answer some questions 

1) Can the both programs see each other E.g. The first one can call the second one and the second one can call the first one ?

2) Does it work with two Windows .Exe's ?

3) Does the second .Exe automatically execute after the first .Exe terminates or ends ?


----------



## mt2002 (Sep 14, 2005)

Are these questions in relation to my software or any software? I have only used it for my software which I personally dont consider a normal case.



> 1) Can the both programs see each other E.g. The first one can call the second one and the second one can call the first one ?


In my software, yes. I believe it should be possible with any software though as its treated as a single file by the host operating system or executive.



> 2) Does it work with two Windows .Exe's ?


It should. Will it run depends on how you jump between the two programs within the code and if Windows loads it as a flat binary file or a PE executable.

If the 1st program is loaded as a flat binary, you may need to use assembly language. If its loaded as a PE executable it should work fine.

An easy way of testing is doing it the way I do it: Parse the 2nd programs header information by referencing the memory right after the 1st program in memory and call its entry point of the 2nd program from the 1st. I can show you my code for an example but keep in mind its in assembly.

It would be interesting to see what happens here though 



> 3) Does the second .Exe automatically execute after the first .Exe terminates or ends ?


What do you mean by "execute"? Technically the 2nd program file is directly after the first in memory, but this also includes all header information and so on as well..

The 1st program would need to parse the header info of the 2nd program (See previous question) in order to obtain the entry point address of the 2nd program and execute it.


----------



## pvc_ (Feb 18, 2008)

I think we're both interested more in knowing how you parse the header for the second program because we had a similar discussion in another topic:

http://forums.techguy.org/software-development/758838-roll-my-own.html


----------



## mt2002 (Sep 14, 2005)

Its simply a manner of parsing the 2nd programs header info to obtain the entry point address to call it. Assuming it is merged with the 1st program, and the 1st program is flat binary, this is relatively easy (It did require 3 rewrites of execute_loader() though..hehe)

I added some extra comments to help clarify some things. execute_loader() is what I am currently using to execute the 2nd program, which is a PE executable that I merged with merge.exe. I also took out some other irrelevant code that my system uses to pass information to the 2nd program.


```
execute_loader:

	; STARTUP_SYS_END is the address of the end of 1st program
	; and is the address of the 1st byte in second program

	; you dont need to load the second program as its already in memory
	; right after us

	; get file sig (PE00) of second program, store in ebx

  	mov	ebx, [STARTUP_SYS_END+60]
	add	ebx, STARTUP_SYS_END

	; get entry point offset in code section

	add	ebx, 24
	mov	eax, [ebx]		; _IMAGE_FILE_HEADER is 20 bytes + size of sig (4 bytes)
	add	ebx, 16			; address of entry point
	mov	ebp, dword [ebx]	; get entry point offset in code section

	; add image base

	add	ebx, 12			; image base is offset 8 bytes from entry point
	mov	eax, dword [ebx]	; add image base
	mov	edi, eax
	add	ebp, eax

	; get size of image in bytes

	add	ebx, 28			; size of image offset 24 bytes from image base
	mov	eax, [ebx]

	; copy the program to the address it exepects to be at
	; iirc this is in MSVC++ linker settings->advanced->base address

	cld
	mov	esi, STARTUP_SYS_END
	mov	ecx, eax
	rep	movsd

	; call entry point of 2nd program

	cli
	call	ebp			; Execute osloader

	; halt system if 2nd program returns

	cli
	hlt
```
Ill post the PE file header structures a little later if you need them.


----------



## -Fabez- (Jul 28, 2008)

So if I was to merge two Windows .Exe's how would they call each other, would it be a file name or a memory address? I'm asking because I am thinking of using your method to create my password protection program. My idea was to bind the password checker to the actual program and have them run in sequence, would that work ? That also brings up another question, if I exit the first program before it reaches the end of its code, will it still execute the second program ?


----------



## mt2002 (Sep 14, 2005)

> So if I was to merge two Windows .Exe's how would they call each other, would it be a file name or a memory address?


memory address would be the only way. There is no reason to use another filename--else they would still be two separate programs.

I suppose it would be possible to merge two *.exe's that can be executed by Windows. ie; we can have merger.exe -- after merging the programs -- update the image files PE header information to match that of the new program file and treat the image file as itself a complete PE program.

Doing it this way, Windows will load the entire image into memory in one go thinking its one program.



> My idea was to bind the password checker to the actual program and have them run in sequence, would that work ?


Yes, it should. Its an interesting idea 



> That also brings up another question, if I exit the first program before it reaches the end of its code, will it still execute the second program ?


In its current state it wont.

Ill see if I can update merger.exe to better support PE files for you  Im interested if it will work.


----------

