• Advertisement
Sign in to follow this  

Executing remote programs using C

This topic is 4792 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I made a level editor for my game but it's a seperate program from my game. I have a menu option in my game to choose the level editor but I don't know how I can execute it from my game.

Share this post


Link to post
Share on other sites
Advertisement
Try eighter the ANSI C system() or Unix exec() family of functions, depending on your needs. Perhaps coupled with a fork() call to keep the original process running.
There's a few other things you might need to take care of too. Like SIGHUP handling if you want the child to outlive the parent, and catching SIGCHLD to avoid leaving zombie processes.
The Unix programming FAQ should cover any remaining details on how to do this properly.

Share this post


Link to post
Share on other sites
The thing is I want the original process to exit. As I'm looking at the man page for exec and it seems to be describing what I wan't. This bring up new questions, first, what would be the equivalent of exec in windows? and secons, how can I tell if my program is running of a windows maching or *nix machine?

Share this post


Link to post
Share on other sites
Quote:
Original post by subflood
The thing is I want the original process to exit. As I'm looking at the man page for exec and it seems to be describing what I wan't. This bring up new questions, first, what would be the equivalent of exec in windows? and secons, how can I tell if my program is running of a windows maching or *nix machine?

Exiting the original process is easy - just don't fork() before exec() and the original process will be taken over by the new one. Make sure you don't leave any open files (or any other inheritable resources) hanging around though.
In Win32 you'd use CreateProcess() instead. And provide a preprocessor define at compile time to detect which environment you're in (WIN32 seems to be automatically defined on most compilers).


#ifdef WIN32 /* windows? */
CreateProcess(..);
#else /* posix? */
execve(..);
#endif


Share this post


Link to post
Share on other sites
doynax: Are you sure that using exec causes the original program to exit?

I doubt that.. say your program has opened few windows and you use exec to launch a child process. Your original program just stops responding if it does not use threads or you have not forked a new process. Windows don't disappear.. of course you could close them first, but bottom line is that the original process does not exit. Is that even possible?

Shouldn't child process belong to a parent process? Is it so that exiting parent process without handling the child process causes the child to turn to a zombie process or does this happen only when child exits and parent does not handle the signal? Perhaps exiting parent process transfers the "parenthood" to the parent of the killed process.. I might be wrong though..

Share this post


Link to post
Share on other sites
Quote:
Original post by Winograd
doynax: Are you sure that using exec causes the original program to exit?

I doubt that.. say your program has opened few windows and you use exec to launch a child process. Your original program just stops responding if it does not use threads or you have not forked a new process. Windows don't disappear.. of course you could close them first, but bottom line is that the original process does not exit. Is that even possible?

There's no need to fork() off a new process since subflood wanted to original process to disappear.
And, no, exec() doesn't make the original process disappear. It does something better instead - it replaces the original process.
As I said earlier, you still have to close any remaining resources. But that's mostly files really, since just about everything is a file in Unix. For example you interface with X-Windows through TCP which is a socket which is a file.
Not that I advocate the "loop through all possible file descriptors and close them" approach, let your program exit normally instead. Bad things would happen whenever you encounter an alternative interface, like svgalib (I think later versions have some kind of workaround for this, but that's not the point).

Quote:
Original post by Winograd
Shouldn't child process belong to a parent process? Is it so that exiting parent process without handling the child process causes the child to turn to a zombie process or does this happen only when child exits and parent does not handle the signal? Perhaps exiting parent process transfers the "parenthood" to the parent of the killed process.. I might be wrong though..

The default action of a child process when a parent disappears is to exit, but this is sane thing to do in most cases. However if a parent doesn't read a child's exit code (through wait()) the child process will remain in the system as a zombie. None of this is a problem if you want to replace the original process though.

Overall I find the Unix process system to be one of the beautiful APIs designed to date. It's primary power lies in allowing you to use independent processes where other systems would need threads.

[Edited by - doynax on January 6, 2005 8:06:00 AM]

Share this post


Link to post
Share on other sites
With Win32 you will need to exit the current process, after you have created the new process, which you can do with ExitProcess, which will shutdown all your windows and threads created automatically. However, this is messy, so do a proper shutdown first.

eg.

MyShutdownFunc();
CreateProcess( ... );
ExitProcess(0);

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
And, no, exec() doesn't make the original process disappear. It does something better instead - it replaces the original process.


Ah.. I see (it would have been smart to read the man pages carefully first :)).. rating up if I can..
This is a bit of topic, but because you (doynax) seem to have pretty good knowledge on the exec area, tell me..
When the process image is replaced by a new one, does the new process inherit the file descriptors? Probably not...

and another one..
Is the new process and it's data and bss sections allocated to the same pages than the old process? I mean that if the old process had written something to address x and the new process has not overwritten it yet, then can it be recovered by the new process? This is probably highly dependant on the implementation of the exec family functions (and/or kernel)... but let's say we are on gnu/linux 2.6, an we have sufficiently new glibc (>=2.3)..

Share this post


Link to post
Share on other sites
Quote:
Original post by Winograd
Ah.. I see (it would have been smart to read the man pages carefully first :)).. rating up if I can..
This is a bit of topic, but because you (doynax) seem to have pretty good knowledge on the exec area, tell me..
When the process image is replaced by a new one, does the new process inherit the file descriptors? Probably not...
It does, this is actually a popular method of communication with child processes.
Before you fork() you can create a pipe() and afterwards replace a known file descriptor (probably 0, 1, 2 - stdin/out/err respectively) for the child process.

Here's a short example without error or zombie handling.
int spawn(const char *cmd) {
int fds[2];

pipe(fds);

if(!fork()) { /* child? */
/* replace stdin with the input end of the pipe */
dup2(fds[0], 0);

close(fds[0]);
close(fds[1]);

execl(cmd, cmd);
}

/* parent? */
close(fds[0]);

/* return a file descriptor for sending data to the child process */
return fds[1];
}



Neat, eh? =)
Quote:
Original post by Winograd
Is the new process and it's data and bss sections allocated to the same pages than the old process? I mean that if the old process had written something to address x and the new process has not overwritten it yet, then can it be recovered by the new process? This is probably highly dependant on the implementation of the exec family functions (and/or kernel)... but let's say we are on gnu/linux 2.6, an we have sufficiently new glibc (>=2.3)..
No, you normally don't get to keep the memory contents. However you can flag a memory area as inheritable when allocating it (specify MAP_INHERIT to mmap() calls).

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
Quote:
Original post by Winograd
Is the new process and it's data and bss sections allocated to the same pages than the old process? I mean that if the old process had written something to address x and the new process has not overwritten it yet, then can it be recovered by the new process? This is probably highly dependant on the implementation of the exec family functions (and/or kernel)... but let's say we are on gnu/linux 2.6, an we have sufficiently new glibc (>=2.3)..
No, you normally don't get to keep the memory contents. However you can flag a memory area as inheritable when allocating it (specify MAP_INHERIT to mmap() calls).


Ok.. altough GNU libc does not document such flag (MAP_INHERIT).

So basicly, I could write some shellcode (refering to buffer overflow thread) into inheritable page. Set that page all the permissions I want. Then I would use exec to replace my exploitation process with the vulnerable process and overflow the stack and point the return address to the inherited page where my shellcode is located at. Correct?

Share this post


Link to post
Share on other sites
Quote:
Original post by Winograd
Ok.. altough GNU libc does not document such flag (MAP_INHERIT).
It's not a libc function and I don't know which flags are specified by posix eighter. I only have access to a BSD system right now so you'll have to check the manual page for mmap or do some googling for the equivalent on your system.

Quote:
Original post by Winograd
So basicly, I could write some shellcode (refering to buffer overflow thread) into inheritable page. Set that page all the permissions I want. Then I would use exec to replace my exploitation process with the vulnerable process and overflow the stack and point the return address to the inherited page where my shellcode is located at. Correct?
Yes, but that seems kinda pointless though. Unless the binary has SUID root permissions or something..
And don't forget PROT_EXEC (hopefully standard..) since you want to execute code in it.

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
Quote:
Original post by Winograd
Ok.. altough GNU libc does not document such flag (MAP_INHERIT).
It's not a libc function and I don't know which flags are specified by posix eighter. I only have access to a BSD system right now so you'll have to check the manual page for mmap or do some googling for the equivalent on your system.
Well, it is part of _GNU_ libc.. atleast info pages of GLIBC 2.3 describe it under MemoryMapped I/O. And I did check the man pages obviously.. there it was documanted also without the MAP_INHERIT.. the header file where the other flags are defined does not contain such flag, so I doubt that it is available under linux system at all (BSD spesific?).
Quote:
Original post by doynax
Quote:
Original post by Winograd
So basicly, I could write some shellcode (refering to buffer overflow thread) into inheritable page. Set that page all the permissions I want. Then I would use exec to replace my exploitation process with the vulnerable process and overflow the stack and point the return address to the inherited page where my shellcode is located at. Correct?
Yes, but that seems kinda pointless though. Unless the binary has SUID root permissions or something..

True. But there are many programs that often have SUID flag, such as X.
Quote:
Original post by doynax
And don't forget PROT_EXEC (hopefully standard..) since you want to execute code in it.
Yes, thats what I meant when saying "Set that page all the permissions I want."


Share this post


Link to post
Share on other sites
Quote:
Original post by Winograd
Well, it is part of _GNU_ libc.. atleast info pages of GLIBC 2.3 describe it under MemoryMapped I/O. And I did check the man pages obviously.. there it was documanted also without the MAP_INHERIT.. the header file where the other flags are defined does not contain such flag, so I doubt that it is available under linux system at all (BSD spesific?).

While that particular flag might not be implemented there might (should?) exist some equivalent operation.
GNU libc's mmap() function is little more than a thin wrapper around a specific system call. And on top of that one that depends heavily on what features the CPU itself provides (disallowing code execution in readable pages is a good example).
Unfortunately my man page doesn't specify a minimum set of "guaranteed" operations. Maybe posix gave up and marked the whole function as non-standard?

Note that normally you'd use the shared memory interface (shmget) for communicating through raw memory buffers. But I don't see how you could run any buffer overrun exploits through those.
Quote:
Original post by Winograd
True. But there are many programs that often have SUID flag, such as X.
Whoa.. Maybe I'm just old fashioned but my x-server doesn't have SUID permissions.
The only time I've dealt with them in the past has been to allow executing svgalib applications in user-mode, and even seems very risky on multi-user machines.
But then again I'm hardly a Unix expert, especially not on administrating secure multi-user machines.
Quote:
Original post by Winograd
Quote:
Original post by doynax
And don't forget PROT_EXEC (hopefully standard..) since you want to execute code in it.
Yes, thats what I meant when saying "Set that page all the permissions I want."
Sorry, I must've missed that part ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
Whoa.. Maybe I'm just old fashioned but my x-server doesn't have SUID permissions.
The only time I've dealt with them in the past has been to allow executing svgalib applications in user-mode, and even seems very risky on multi-user machines.
But then again I'm hardly a Unix expert, especially not on administrating secure multi-user machines.

Yep, either is mine. But by default XFree86 seems to install itself as SUID.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement