For fun I wrote a "launcher" program that uses your method. It works, I tested it with zoomin.exe as the payload.
Once you've created the launcher executable, open both it and the payload file (zoomin.exe in my case) in Notepad++, and copy (using the Edit | Paste Special | Copy Binary Content and Paste Binary Content menu options).
You can find whereabouts in the launcher file the payload goes by searching in Notepad++ for "File Goes Here" and "End".
Note, I do not recommend this in any way, it's fiddly, error-prone and can break easily with different compiler settings. The way I have solved this in the past is, as already commented, to add the payload as a resource, which is much more maintainable.
#include <stdio.h>
#define SIZE_OF_ZOOMIN_EXE 11264
char buffer[SIZE_OF_ZOOMIN_EXE] = "File Goes Here";
char end_of_buffer[] = "End";
int main()
{
FILE *fp = fopen("myzoomin.exe", "wb");
fwrite(buffer, sizeof(buffer), 1, fp);
fclose(fp);
return 0;
}
Here's an main() function for a self-installing service I wrote in C++ . In addition, the program allows the service to be run interactively.
int main( int argc, char *argv[] )
{
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SERVICE_NAME, Eng3ServiceStart },
{ NULL, NULL }
};
try {
if (argc >= 2) {
if (argc >= 3)
if (!(logfile = fopen(argv[2], "a")))
logfile = stdout;
if (0 == _stricmp(argv[1], "install")) {
DeleteEng3Service(); // ignore return value -- don't care if error
return CreateEng3Service();
}
else if (0 == _stricmp(argv[1], "uninstall"))
return DeleteEng3Service() ;
}
// not installing or uninstalling, start the service,
// passing it all the command-line arguments.
if (!StartServiceCtrlDispatcher( DispatchTable ) ) {
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
fprintf(logfile, "Failed to connect to service. Starting in console mode.\n");
return svcmain(argc, argv);
}
throw sys_ex();
}
} catch (exception& ex ) {
fprintf(logfile, ex.what());
}
}