如何实现Netcat连接服务器时自动执行指定二进制程序?
实现方式解析
这种通过Netcat连接端口后自动执行程序并绑定标准流的功能,核心是将网络套接字(Socket)与程序的标准输入/输出/错误流(stdin/stdout/stderr)做重定向,常见实现方式有两种:
1. 借助inetd/xinetd服务(CTF平台最常用)
inetd是类Unix系统上的超级守护进程,xinetd是它的增强版,专门用来管理基于网络的服务。配置后,当有客户端连接指定端口时,它会自动fork子进程并将Socket的文件描述符重定向到子进程的标准流,最后执行目标程序。
配置示例(xinetd)
创建一个配置文件(比如/etc/xinetd.d/pwn_challenge):
service pwn_challenge { type = UNLISTED socket_type = stream protocol = tcp wait = no user = nobody # 用低权限用户运行,避免权限风险 server = /home/pwn/your_challenge_binary port = 9004 # 对应nc连接的端口 disable = no }
配置生效后,xinetd会监听9004端口:当你用nc pwnable.kr 9004连接时,xinetd会:
- 接受Socket连接
- fork一个子进程
- 将子进程的0(stdin)、1(stdout)、2(stderr)文件描述符替换为Socket的fd
- 调用execve执行指定的二进制程序
此时程序的所有IO操作都会直接通过网络连接和你的本地终端交互。
2. 自定义监听程序(灵活可控)
如果需要更定制化的逻辑,也可以自己写一个Socket监听程序,手动处理连接和流重定向。以下是简化示例:
Python实现
import socket import os import sys def handle_connection(conn): # 将Socket的fd复制到标准流的fd(0,1,2) os.dup2(conn.fileno(), 0) os.dup2(conn.fileno(), 1) os.dup2(conn.fileno(), 2) # 执行目标二进制程序,替换当前进程 os.execve('/home/pwn/challenge', ['challenge'], os.environ) def main(): server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_sock.bind(('0.0.0.0', 9004)) server_sock.listen(5) while True: client_conn, client_addr = server_sock.accept() # fork子进程处理连接,父进程继续监听 pid = os.fork() if pid == 0: server_sock.close() handle_connection(client_conn) client_conn.close() sys.exit(0) else: client_conn.close() if __name__ == '__main__': main()
C语言实现(核心逻辑)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> int main() { int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serv_addr = { .sin_family = AF_INET, .sin_port = htons(9004), .sin_addr.s_addr = INADDR_ANY }; bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); listen(sockfd, 5); while (1) { int connfd = accept(sockfd, NULL, NULL); if (fork() == 0) { close(sockfd); // 重定向标准流到Socket dup2(connfd, 0); dup2(connfd, 1); dup2(connfd, 2); close(connfd); // 执行目标程序 execl("/home/pwn/challenge", "challenge", NULL); exit(0); } close(connfd); } return 0; }
关键原理
无论是用inetd还是自定义程序,核心都是**dup2系统调用**:它会将指定的文件描述符(这里是Socket的连接fd)复制到目标fd(0、1、2对应标准流),使得程序后续的IO操作都直接指向网络连接,而非终端。
内容的提问来源于stack exchange,提问作者natitati
相关产品推荐
相关产品推荐

