利用LLKM处理网络通信---对抗IDS、Firewall-C / C++-优质IT资源分享社区

admin
管理员
管理员
  • UID1
  • 粉丝29
  • 关注4
  • 发帖数581
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:290回复:0

  利用LLKM处理网络通信---对抗IDS、Firewall

楼主#
更多 发布于:2016-05-07 22:09
 ★ 前言
            
             事实上我并没有翻译Phrack
55-12,它的文字如此之少,当然必须承认其中闪烁
             的智慧之光。阅读lifeline < mailto:
arai@hackers-pt.org >的程序,它就在文章
             里,然后再来看这篇文章。
            
 
             ★ 目录
            
             1. IDS、Firewall的某些特性
             2. LLKM能做什么
             3. 一个完整的LLKM例子,简单、临时改变TCP/IP协议栈的行为
4. 获取TCP自动机状态,更改出现在网络传输线路上的TCP标志位
5. 另外一种截留本机发送报文、修改、再发送技术
6.
内核模块里设置混杂模式
7. 内核模块里文件I/O操作
8. 内核包转发的讨论

★ 正文

1.
IDS、Firewall的某些特性

以snort为例,其大量IDS规则对TCP的PSH、ACK、SYN标志进行判断。比如,在
syn-flood告警中,判断短时间内出现的大量SYN包。而更多的对TCP数据区进行内容
鉴别前,判断了PSH+ACK标志。具体snort规则请参看snort源代码包中举例。

Firewall阻塞来自外部的TCP连接请求时,需要判断SYN标志。

IDS和Firewall还有个更重要的通性,对端口的敏感性。21、23、110、513等端
口都属于敏感端口,许多告警规则、阻塞规则是基于端口的。

2. LLKM能做什么

利用LLKM简单、临时改变TCP/IP协议栈的行为。考虑三种情况:

a. 更改出现在网络传输线路上的TCP标志位
b.
更改出现在网络传输线路上的端口
c. 对IP数据区(TCP协议部分)加密处理后传输

|
| | |
A Host
----+----- firewall -----+---- B Host
(内部) | | | (外部)
| | |
C
Host(IDS系统) | D Host(普通Sniffer)
|

假设A和B都是我们控制的主机,在这两台主机上都加载LLKM。防火墙不允许来自
外部的任何TCP连接请求,它靠的是判断SYN标志。现在B想telnet到A,LLKM将把B到A
的SYN标志换成ACK、PSH、RST、RES1、RES2中的任意一个或者几个的组合,以能渗透
通过防火墙为原则;A上的LLKM先于正常的TCP/IP协议栈接收到这个扭曲处理了的请
求报文,按照约定好的规则逆向处理,恢复SYN标志后再交给正常的TCP/IP协议栈处
理。同样,A回送SYN+ACK到B的时候,也做一些转换,B上LLKM会恢复成正常的
SYN+ACK。对于A、B上的TCP/IP协议栈,它们意识不到发生过转换,用netstat -na看
到的还是正常的、意料中的状态。对于防火墙,意识不到已经从外部主机成功访问了
内部主机。对于C、D,会看到奇怪的TCP标志出现。在做标志转换时,还需要考虑对
抗IDS规则,因具体情况而定。比如,避免在网络传输中出现PSH+ACK标志。

防火墙和IDS对端口相当敏感,比如不允许telnet、ftp协议通过,只允许http协
议通过。要做的仅仅是让A、B把23端口换成80端口出现在网络传输中。可能有人认为
修改双方的/etc/services文件更好些,当然,那也是一种可行的考虑。不过有太多
情况下利用LLKM动态修改端口更彻底更灵活。至于IDS,对于大多数非周知端口并不
敏感,意味着逃脱了监测。

最后要做的就是对IP数据区进行加密传输,IPSec能做到,可我需要的可能仅仅
是异或处理,仅仅是避开IDS的端口监测、内容监测。一个简单的insmod就能完成的
任务为什么一定要搬出IPSec呢。

3.
一个完整的LLKM例子,简单、临时改变TCP/IP协议栈的行为

例子程序的想法来自华中地区网络中心(bbs.whnet.edu.cn)Security版的
difeijing朋友,同时感谢AngelFalls朋友参与该版讨论,并提供了八篇谢绝转站的
<<Linux的TCP/IP协议栈阅读笔记>>。

程序演示了

a. LLKM的基本框架和技巧
b. 利用dev_add_pack()对本机即将发送出去的报文进行修改再发送

syn半开扫描依赖于被扫描主机返回ACK+RST标志和ACK+SYN标志两种情况,前者
意味着相应端口未开。connect扫描则完全依赖TCP连接的成功建立。difeijing提出
了这样一个想法,利用LLKM转换ACK+RST成ACK+SYN,此时syn半开扫描和connect扫描
都将认定相应端口是打开的。

--------------------------------------------------------------------------
/*
* File : openallport.c
* Author : scz < mailto:
scz@nsfocus.com >
* : 替换www.nsfocus.com
* Kernel : 2.2.16 or 2.2.14
* Complie : gcc -O3 -DMODULE -D__KERNEL__ -c openallport.c
* Usage :
insmod openallport.o [dev=eth0] -x -y -f
* Date : 2000-10-10 17:40
*/

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>

/*
* 2.2.16内核的/usr/include/linux/version.h文件里定义了这个宏
* 但2.0.35内核里没有定义
*/
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) (((a) << 16)
+ ((b) << 8) + (c))
#endif

#if LINUX_VERSION_CODE >
KERNEL_VERSION(2,2,0)
#include <asm/uaccess.h>
#endif

static struct device * openallport_dev = NULL;
static char * dev =
NULL;

/* 定义insmod命令行参数 */
#if LINUX_VERSION_CODE >
KERNEL_VERSION(2,2,0)
MODULE_PARM( dev, "s" );
#endif

static
inline u_long csum_tcpudp_nofold ( u_long saddr, u_long daddr,
u_short len,
u_short proto,
unsigned int sum )
{
__asm__
("
addl %1, %0
adcl %2, %0
adcl %3, %0
adcl $0, %0
"
: "=r" ( sum )
:
"g" ( daddr ), "g" ( saddr ), "g" ( ( ntohs( len ) << 16 ) + proto * 256
), "0" ( sum )
);
return sum;
}

static inline unsigned int
csum_fold ( unsigned int sum )
{
__asm__
("
addl %1, %0
adcl
$0xffff, %0
"
: "=r" ( sum )
: "r" ( sum << 16 ), "0" ( sum
& 0xffff0000 )
);
return( ( ~sum ) >> 16 );
} /* end of
csum_fold */

static inline u_short check_tcpudp ( u_long saddr, u_long
daddr,
u_short len, u_short proto,
unsigned int sum )
{
return(
csum_fold( csum_tcpudp_nofold( saddr, daddr, len, proto, sum ) ) );
} /* end
of check_tcpudp */

int openallport_rcv ( struct sk_buff * skb, struct
device * dv, struct packet_type * pt )
{
/* 注意pkt_type是什么 */
if ( (
skb->pkt_type == PACKET_OUTGOING ) && ( skb->protocol ==
__constant_htons( ETH_P_IP) ) )
{
if ( ( skb->nh.iph->version == 4
) && ( skb->nh.iph->protocol == IPPROTO_TCP ) ) /* 不考虑ipv6 */
{
skb->h.raw = skb->nh.raw + ( skb->nh.iph->ihl << 2
);
if ( ( skb->h.th->ack == 1 ) && ( skb->h.th->rst == 1
) )
{
u_short size;
int doff = 0;

skb->h.th->rst = 0;
skb->h.th->syn = 1;
size = ntohs( skb->nh.iph->tot_len ) - (
skb->nh.iph->ihl * 4 ); /* IP数据区长度 */
doff = skb->h.th->doff
<< 2; /* TCP头部长度 */
/* 重新计算校验和 */
skb->csum = 0;
skb->csum = csum_partial( skb->h.raw + doff, size - doff, 0 ); /* data
checksum */
skb->h.th->check = 0;
skb->h.th->check =
check_tcpudp( skb->nh.iph->saddr, /* tcp or udp checksum */
skb->nh.iph->daddr,
size,
IPPROTO_TCP,
csum_partial(
skb->h.raw, doff, skb->csum ) );
}
}
}
kfree_skb( skb );
return( 0 );
} /* end of openallport_rcv */

static struct
packet_type openallport_packet_type =
{
__constant_htons( ETH_P_ALL ),
/* 此时可以接收到来自lo的回送报文,比如本机发送出去的 */
NULL, /* All devices */
openallport_rcv,
NULL, /* 如果是2.4内核,这里可以考虑设置成非零,但是openallport_rcv需要改变 */
NULL,
};

int init_module ( void ) /* 模块初始化 */
{
if ( dev
!= NULL )
{
openallport_dev = dev_get( dev );
if ( openallport_dev
!= NULL )
{
openallport_packet_type.dev = openallport_dev;
}
}
dev_add_pack( &openallport_packet_type );
EXPORT_NO_SYMBOLS;
return( 0 );
} /* end of init_module */

void cleanup_module (
void ) /* 模块卸载 */
{
dev_remove_pack( &openallport_packet_type );
return;
} /* end of cleanup_module */
--------------------------------------------------------------------------

openallport_packet_type变量的第一个成员必须是__constant_htons( ETH_P_ALL )











优质IT资源分享社区为你提供此文。 [font=Tahoma  ]
本站有大量优质C、C++教程视频,资料等资源,包含C,C++基础教程,高级进阶教程等等,教程视频资源涵盖传智播客,极客学院,达内,北大青鸟,猎豹网校等等IT职业培训机构的培训教学视频,价值巨大。欢迎点击下方链接查看。 [font=Tahoma  ]

C、C++教程视频
优质IT资源分享社区(www.itziyuan.top)
一个免费,自由,开放,共享,平等,互助的优质IT资源分享网站。
专注免费分享各大IT培训机构最新培训教学视频,为你的IT学习助力!

!!!回帖受限制请看点击这里!!!
!!!资源失效请在此版块发帖说明!!!

[PS:按 CTRL+D收藏本站网址~]

——“优质IT资源分享社区”管理员专用签名~

本版相似帖子

游客