I am trying to write shellcode in assembly. I need to perform a /usr/bin/killall command AND a /usr/bin/wget command. I have both commands running perfectly in shellcode with the execve() syscall. But now I want to combine these 2, but this is not possible because the program exits when the first execve() call is executed. (from the man pages of execve() : execve() does not return on success).
How can I perform 2 execve() calls? Or is there another way to call both /usr/bin/killall and /usr/bin/wget from the same shell code?
Greets and thanks in advance!
When you use the exec-family of functions, the program you call it with is substituted into the current process. So when the first execve-call is made, your entire process image disappears, and thus second call is never made. To get around this you must fork another process before calling execve.
First of all, it is not possible to execute two execve() one after the other. Simply because, by definition, the execve() call will override the memory of the original process with the new one and you will never be able to switch back to the original process again.
The second option that you propose (merging /usr/bin/killall and /usr/bin/wget into the shellcode) is perfectly possible if the killall command is not killing the process executing the shellcode itself. If it is the case, I really need more information about why is this behavior is needed because it seems a bit absurd to me (but I certainly miss the context in which you are running your shellcode).
Related
Is there a way to start a child process without fork(), using execvp() exclusively?
The pedantic answer to your question is no. The only system call that creates a new process is fork. The system call underlying execvp (called execve) loads a new program into an existing process, which is a different thing.
Some species of Unix have additional system calls besides fork (e.g. vfork, rfork, clone) that create a new process, but they are only small variations on fork itself, and none of them are part of the POSIX standard that specifies the functionality you can count on on anything that calls itself a Unix.
The slightly more helpful answer is that you might be looking for posix_spawn, which is a library routine wrapping fork and exec into a single operation, but I find it more troublesome to use that correctly than to write my own fork+exec subroutine. YMMV.
posix_spawn is the only posix compliant way to create a child process without calling fork directly. I say 'directly' because historically posix_spawn would itself just call fork, or vfork. However, that is no longer the case in GNU/linux. posix_spawn itself may be more efficient than fork, in addition to perhaps being a stronger fit conceptually when code is attempting to run a different executable.
If you aren't worried about portability, you can abandon posix and couple yourself directly to the kernel you are targeting. On linux the system call to create a child process is clone. At the time of this answer the manual page provides documentation for three variants, including the relatively new clone3.
I believe you can take the example from the manual page and add an execvp call to childFunc. I have not tried it yet, though!
Unlike Windows systems, where creating a new process and executing a new process image happen in a single step, Linux and other UNIX-like systems do them as two distinct steps.
The fork function makes an exact duplicate of the calling process and actually returns twice, once to the parent process and once to the child process. The execvp function (and other functions in the exec family) executes a new process image in the same process, overwriting the existing process image.
You can call execvp without calling fork first. If so, that just means the currently running program goes away and is replaced with the given program. However, fork is the way to create a new process.
As user zwol has already explained, execve() does not fork a new process. Rather, it replaces the address space and CPU state of current process,
loads the new address space from the executable filename and starts it from
main() with argument list argv and environment variable list envp.
It keeps pid and open files.
int execve(const char *filename,char *const argv [],char *const envp[]);
filename: name of executable file to run
argv: Command line arguments
envp: environment variable settings (e.g., $PATH, $HOME, etc.)
posix_spawn. But it ignores failures of execvp() -- potentially because implementing this was regarded as too complicated.
If the fork and exec patter is used just to run a program without freeze the current program, what's the advantage, for example, over using this single line:
system("program &"); // run in background, don't freeze
The system function creates a new shell instance for running the program, which is why you can run it in the background. The main difference from fork/exec is that using system like this actually creates two processes, the shell and the program, and that you can't communicate directly with the new program via anonymous pipes.
fork+exec is much more lightweight than system(). The later will create a process for the shell, the shell will parse the command line given and invoke the required executables. This means more memory, more execution time, etc. Obviously, if the program will run in background, these extra resources will be consumed only temporarily, but depending on how frequently you use it, the difference will be quite noticeable.
The man page for system clearly says that system executes the command by "calling /bin/sh -c command", which means system creates at least two processes: /bin/sh and then the program (the shell startup files may spawn much more than one process)
This can cause a few problems:
portability (what if a system doesn't have access to /bin/sh, or does not use & to run a process in the background?)
error handling (you can't know if the process exited with an error)
talking with the process (you can't send anything to the process, or get anything out of it)
performance, etc
The proper way to do this is fork+exec, which creates exactly one process. It gives you better control over the performance and resource consumption, and it's much easier to modify to do simple, important things (like error handling).
I am trying to run a new process in background so it will be possible to continue working with parent process.
I used fork then execl. I tried to add to the execl command the argument & but it doesn't work:
execl("newproc","newproc","arg1","&",NULL);
Is there any solution?
The child will run in the background since you used fork. The child will keep running in parallel with the parent (if exec succeeded). If you care about whether the child process succeeded or not (and your code should) you should eventually call waitpid to collect its exit status. Otherwise you should call fork twice and have the intermediate process exit without waiting for the child, so that init adopts the grandchild process.
As #mah said, the & is unnecessary. But another change is needed to that line; execl is a variadic function, and function prototypes therefore don't take care of converting arguments to the correct type. Therefore the final argument should be passed as the correct type - just change it to (char*)NULL.
You mention that your code didn't work. While that could just be because of the spurious &, it may also be because of the first argument. The execl function does not search $PATH for the named program, so unless newproc is actually in the current directory, this execl() invocation will return. When execl returns, that always indicates that there is a problem. The simplest way to solve this is to use execlp() instead of execl(). The alternative approach is to specify an absolute path as the first argument. You can even specify a relative path as the first argument, but this is rarely useful.
The problem is that & is not a command line option to programs. Instead, it is merely special shell syntax which puts a command in the background. The distinguishing feature of background programs is that they are not connected to a terminal, and the terminal is not waiting for the process to complete. The proper function is daemon(). Do a man daemon to read up on how it is used.
& is not a command argument, its a flag that the shell uses to know to run the command in the background. In this case, you're performing the work of the shell... remove the &. Since you state you've called fork(), as long as you're only performing execl() in the child process after fork returns, you're already running in the background.
We are using C in Linux. Is there any possibility that system() function can behave in an unexpected manner, especially when we handle signals?
We found that sometimes, the system() function blocks the execution or it throws SIGSEGV.
e.g:
system ( "/bin/mv a b" );
Are there any known flaws in using system() that would explain this?
The system() function does what it is supposed to do perfectly well. The behaviour is pretty reliable as long as it is invoked correctly. It has two modes of operation:
Check whether there is a command interpreter available - when the argument is a null pointer.
Run the command given, waiting for the command to complete before returning.
So, the system() statement blocks until the shell that runs the command completes. On Unix-like systems, the command invoked is effectively:
"sh", "-c", "...argument to system...", NULL
This means that the string passed is interpreted by the shell. How long that takes depends on the command that is executed. You can consider using the shell notations to run the command in background if you need to:
system("( /bin/mv a b & )");
There are few circumstances where system() will itself generate SIGSEGV. You would have to pass it an invalid pointer, a pointer to somewhere invalid in the program.
The system() call is supposed to block until execution is finished. If it takes an hour to move a to b, the process or thread calling system() will block for an hour. Knowing this, strange behavior can be explained.
If you expect system() to return immediately, it probably means that you expect code that runs after calling it to have been entered by the time you see the strange behavior. It is very likely that, due to system() taking longer than expected, some area of memory wasn't allocated or initialized. This is likely the cause of the segmentation fault when another thread or process tried to access it.
In other words, if you didn't expect system() to block, you probably assumed that code coming after it would run much sooner than it actually did.
Debunking that would be a topic for another question. The answer to this one is no, you aren't seeing flaws in the system() function, it is behaving exactly as expected.
I have a directory monitoring application which works recursively by launching new processes.
I'd like to know if I'm the "root" process in this tree. I thought about trying to get the name of the caller process and check if it's the same as argv[0].
Is there a smarter way of doing this? Keep in mind, this is a Linux app.
Keep in mind, I don't have much time for this and I'm but a student, so a simple solution would be great.
Thanks for your time.
If you use fork() to create new processes, you can have a local variable initially set at zero that each child sets to 1 immediately after forking. Only the root process would still have it set at zero after a fork.
You could even increase it after each fork, which would let you know how deep in your process tree each process is.
EDIT:
If you cannot use this (e.g. because you do an exec() after fork), you can use any of the common ways that shells use to pass information to the programs that you launch:
Environment variables: call setenv() after fork() but before exec() - or add it in the environment when calling exec().
Use a special command line argument.
Use a special value for argv[0] when doing exec().
Have you the possibility to add an argument meaning "I'm not the root"? That seems the simplest approach.
If you are calling exec, add a special argument, or environment variable called "I_AM_NOT_THE_ROOT" which the child processes get, but the parent does not.
I recently used a command-line argument for this, but env variables might be more convenient.