Jump to content
Tuts 4 You

[C/C++, winapi] How to create an exe from another exe


skylark

Recommended Posts

Could anyone please shed some light on me about the process of creating an exe (outputting a compiled exe) from another exe? Like the loader/patcher programs, you put the name of the program you want to patch, put addresses and bytes, then click some "create patcher" button and the patcher-creator program outputs a patch.exe for you. Or like the keylogger or rat programs, after selecting desired settings, you click some "create server" button, and it outputs a server.exe for you.

I am somewhat lost about how this process is done, tried googling but couldn't find any source to learn (maybe I don't even know how to search on this topic). For starter, I want to make an adder program, say console_app_1.exe, I will input two values, a and b and that program will save another console_app_2.exe in a folder. When I run this console_app_2.exe, it won't take any input and is supposed to show me the result of a+b as console output.

I am coding in c++, so appreciated if the solution is in c/c++. Any help, code, tutorial or valid source to learn is much appreciated. Regards.

Link to comment

Hi, thanks for trying to help, but I don't fully understand it. Do I have to make a separate compiled exe/dll/bin file and add it as resource inside the main program? Once I have compiled it, how am I supposed to edit/modify the assembly code? That link you gave is talking about how to modify icons and such stuffs from the resource file, but I want to modify the code of the 2nd exe. Also, this main program has to be able to output the exe even if the user/tester doesn't have any c++ compiler installed in his pc.

Link to comment

Load the file into memory using any number of API / libraries, modify the data in memory that you wish to patch within the file. Then save the data in memory back to the file or create a new file with a different name. Most patchers will take the original file and rename it to <file name>.bak then save the new edited file as the original name.

Link to comment

Telling something similar to the above, in another words:

You should have first to create an executable as a generic template of a patcher and load it into your "patcher creator" as a byte sequence, knowing the offsets of the data to be filled for a particular target to be patched (such as address for patch, number of bytes to be patched, bytes for the patch), and then, when you know the target's patching data needed to be patched, modify via your tool the template bytes in the known offsets to become a valid and useful patcher for your target, and finally, dump to disk as a new file and rename as desired. Try to learn something about PE header not to corrupt the created file when dumped.

Best regards

Nacho_dj

Link to comment

Hi again, so I have been trying to accomplish that task and here is the method I followed so far :

1. Coded and compiled the template exe and embedded it as resource into the main exe.

2. Allocated space for a byte array and copied all the bytes of the embedded resource file in that array.

3. Edited the values of the template variables. Took addresses for editing --> (new array's start address + offset that holds the value of the variable).

4. Wrote all the bytes of the array into disk and saved it as exe.

This is working fine and no bug detected so far, but I am going to use this for a bigger project and not sure if this way is efficient, or if could create bug in future. Could you please make some comments or opinions about my approach and tell me if this could be done in any more efficient and secure way? I am giving the main code section that I wrote, if possible guide me for some necessary improvement.

Spoiler

#include <iostream>
#include <Windows.h>
#include "resource.h"
using namespace std;

int main()
{
	//taking integer inputs for adding up
	int a, b;
	cin >> a >> b;

	//getting the resource handles and stuffs
	HRSRC hrsrc = FindResource(NULL, (LPCSTR)IDR_CF, RT_RCDATA);
	HGLOBAL hGlbl = LoadResource(NULL, hrsrc);
	BYTE* res = (BYTE*)LockResource(hGlbl);
	DWORD size = SizeofResource(NULL, hrsrc);

	//writing the resource in an allocated space
	BYTE * arr = (BYTE*)malloc(size + 10);
	memcpy(arr, res, size);

	//editing the pre-calculated offsets to change template values of a and b
	*(arr + 0x76A) = a;
	*(arr + 0x771) = b;

	//writing the bytes in a file
	HANDLE hFile = CreateFile("2.exe", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	if (hFile != INVALID_HANDLE_VALUE)
	{
		DWORD bytesWritten = 0;
		WriteFile(hFile, arr, size, &bytesWritten, NULL);
		CloseHandle(hFile);
	}
	
	//starting the new process
	STARTUPINFO si = { 0 };
	PROCESS_INFORMATION pi = { 0 };
	si.cb = sizeof(si);
	CreateProcess("2.exe", 0, 0, 0, 1, 0, 0, 0, &si, &pi);

	return 0;
}

 

 

Link to comment

Hi

Appending required data as overlay is better (It's my opinion !), In some case required data is bigger than stub(something like installers stub, etc).

 

Best Regards,

h4sh3m

Link to comment

i'd agree with the appending, though it depends on the size really, and requirements...

you could also make it one exe, that defaults to working as a patcher, but if a commandline is given it goes into 'generation' mode, either way it'll need to make a copy of itself..

other approach if appending is too difficult - put the 'script' in a resource, and use beginupdateresource / the resource api's to do the heavy lifting of altering the exe

at the end of the day though, you're just reinventing the wheel, there are many many many many patcher generators out there.. some that will be way more advanced

Link to comment

From your example code above, some suggestions:

Check for errors if you don't already in the real code. The various API calls can all fail for a number of reasons that you should check for errors.

You may want to avoid using malloc to define the space for the file and look into memory mapping instead. Allocating memory into a stack variable within main like that can lead to random crashes / issues. You may also hit allocate limits in general on larger files. 

 

Link to comment

Thanks for the comments. I will look into appending data as overlay. I am not accustomed to data overlay and coding for that, will research about it.

12 hours ago, evlncrn8 said:

either way it'll need to make a copy of itself..

at the end of the day though, you're just reinventing the wheel, there are many many many many patcher generators out there.. some that will be way more advanced

By "making a copy of itself", would it be better to fork the main exe, then editing the child with something like WriteProcessMemory, or editing the main exe itself in memory then dumping, or something else? And yeah, I know there are advanced patchers, I am not thinking about re-inventing something, I am trying to learn the inner mechanisms of already-existing stuffs, to grow knowledgebase you can say, also a few times I felt the need to make a custom loader for some specific program though. Whatever projects I will work on, could have been done without generating the 2nd exe, but I am working on it deliberately so that I can learn about it in the process, anyway. And your commandline argument passing for "generating" mode seems good, will think about implementing that.

5 hours ago, atom0s said:

Check for errors if you don't already in the real code.

You may want to avoid using malloc to define the space for the file and look into memory mapping instead. Allocating memory into a stack variable within main like that can lead to random crashes / issues. You may also hit allocate limits in general on larger files. 

Yeah I will put error-check codes, like checking if all the resource handles are valid before using them.

I used malloc here, but I was about to use new operator for my main code. Could new create that same type of crash? The pointer is a stack variable, but the memory is allocated in the heap, why should it create error? I will look into memory mapping. I can't think of any other method of doing that except using winapi functions like CreateFileMapping, please tell me if I should approach with that or something else.

Link to comment

fork would be idiotic (also fork isnt a windows concept).. why launch another process then also have to deal with aslr or similar (depending on how the exe was complied)..

keep it simple

make the executable

make code to process the resources or to work from the appended data (createfile->read->process)... 

then update the resource or the appended data with the new script or whatever..

for memory allocation just keep it simple - use virtualalloc.. 

mapping is pointless if you go the appended data route

and i dont see much point in mapping either if you're going the resources route either

Link to comment

I agree with the above post, but forking in Windows is definitely a thing :) Its uses are obscure though. If for some reason you have Windows Error Reporting enabled you may unwittingly run into Windows becoming too 'fork-happy' like this poor guy.

Link to comment

Before Vista, there were two syscalls to create a process on Windows: NtCreateProcess and NtCreateProcessEx. (the latter is just a version of NtCreateProcess that supports job levels.) Vista added NtCreateUserProcess. All of these are undocumented by Microsoft (not counting the kernel source comments which are quite detailed but not exactly public). In all versions of Windows, CreateProcess[A|W] forwards to CreateProcessInternalW, which is a very (very) big wrapper for one of these syscalls. From the prototypes you can see that the syscalls are quite different:

NTSTATUS
NTAPI
NtCreateProcessEx(
	_Out_ PHANDLE ProcessHandle,
	_In_ ACCESS_MASK DesiredAccess,
	_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
	_In_ HANDLE ParentProcess,
	_In_ ULONG Flags,
	_In_opt_ HANDLE SectionHandle,
	_In_opt_ HANDLE DebugPort,
	_In_opt_ HANDLE ExceptionPort,
	_In_ ULONG JobMemberLevel
	);

NTSTATUS
NTAPI
NtCreateUserProcess(
	_Out_ PHANDLE ProcessHandle,
	_Out_ PHANDLE ThreadHandle,
	_In_ ACCESS_MASK ProcessDesiredAccess,
	_In_ ACCESS_MASK ThreadDesiredAccess,
	_In_opt_ POBJECT_ATTRIBUTES ProcessObjectAttributes,
	_In_opt_ POBJECT_ATTRIBUTES ThreadObjectAttributes,
	_In_ ULONG ProcessFlags,
	_In_ ULONG ThreadFlags,
	_In_ PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
	_Inout_ PPS_CREATE_INFO CreateInfo,
	_In_ PPS_ATTRIBUTE_LIST AttributeList
	);

The last parameter to NtCreateUserProcess is an attribute list (the attributes on MSDN UpdateProcThreadAttribute roughly correspond to this, except the real syscall supports about twice as many). Only one attribute is actually required: the path to the executable to launch. Seems obvious right? Except if you look at the NtCreateProcess[Ex] prototype, you'll note there is no image path or attribute list. How CreateProcessInternalW worked in the XP days was basically the following sequence (highly abbreviated):

  • NtCreateFile
  • NtCreateSection
  • NtCreateProcessEx
  • NtQuerySection (to get e.g. image type, version, entry point and so on)
  • Allocate and write RTL_USER_PROCESS_PARAMETERS to process
  • Allocate a TEB and stack for the first thread and initialize it with a CONTEXT
  • NtCreateThread (NB: Vista also replaced this with an NtCreateThreadEx, but NtCreateUserProcess always creates the first thread itself)
  • Misc other stuff based on parameters passed in, cleanup etc.

Thanks to ReactOS it's possible to see how this was done exactly.

Anyway, if you look at the annotations on the functions you'll see that the section, despite being the most important piece of information about a process, is actually optional! Furthermore, NtCreateProcesss[Ex] has not been removed from Windows despite being replaced by NtCreateUserProcess basically everywhere. So to answer the question: you fork a process by obtaining a handle to it with PROCESS_CREATE_PROCESS access, and then calling NtCreateProcess or NtCreateProcessEx with this handle as the parent process. That's it :)

I can't speak for how Cygwin's fork() works as I don't know much about Cygwin. As far as I recall (it's been a while), forking using the method above results in a 'true' fork (meaning copy on write semantics), not a vfork. However it may not be POSIX-compliant for other reasons which would still require a custom wrapper implementation.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...