upload files

This commit is contained in:
CHN-beta 2018-12-24 16:49:32 +08:00
parent 7b2196fbac
commit c299e03cc9
4 changed files with 275 additions and 0 deletions

30
Makefile Normal file
View File

@ -0,0 +1,30 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=xmurp-ua
PKG_RELEASE:=9
include $(INCLUDE_DIR)/package.mk
EXTRA_CFLAGS:= \
$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
MAKE_OPTS:=$(KERNEL_MAKE_FLAGS) \
SUBDIRS="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
CONFIG_xmurp-ua=m
define KernelPackage/xmurp-ua
SUBMENU:=Other modules
TITLE:=xmurp-ua
FILES:=$(PKG_BUILD_DIR)/xmurp-ua.ko
AUTOLOAD:=$(call AutoLoad,99,xmurp-ua)
KCONFIG:=
endef
define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) modules
endef
$(eval $(call KernelPackage,xmurp-ua))

2
src/Kconfig Normal file
View File

@ -0,0 +1,2 @@
config xmurp-ua
tristate "xmurp-ua"

1
src/Makefile Normal file
View File

@ -0,0 +1 @@
obj-${CONFIG_xmurp-ua} += xmurp-ua.o

242
src/xmurp-ua.c Normal file
View File

@ -0,0 +1,242 @@
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netdevice.h>
#include <linux/random.h>
static struct nf_hook_ops nfho;
enum char_scan_enum
{
next,
modified_and_next,
scan_finish,
reset,
};
enum skb_scan_ret
{
need_next_frag = 1,
ua_modified = 2,
};
// 根据得到的指针尝试扫描发现结尾或发现UA或更改UA后返回对应结果。
// 输入零指针则为重置状态。
inline u_int8_t char_scan(char *data)
{
const char str_ua_head[] = "User-Agent: ", str_ua[] = "XMURP/1.0", str_end[] = "\r\n\r\n";
// 不算'\0'长度分别为12、9、4
static enum
{
nothing_matching,
ua_head_matching,
ua_modifying,
end_matching,
} status = nothing_matching;
static u_int8_t covered_length;
if(data == 0)
{
status = nothing_matching;
covered_length = 0;
return reset;
}
while(true)
{
if(status == nothing_matching)
{
if(*data == str_ua_head[0])
{
status = ua_head_matching;
covered_length = 1;
return next;
}
else if(*data == str_end[0])
{
status = end_matching;
covered_length = 1;
return next;
}
else
return next;
}
else if(status == ua_head_matching)
{
if(*data == str_ua_head[covered_length])
{
covered_length++;
if(covered_length == 12)
{
status = ua_modifying;
covered_length = 0;
return next;
}
else
return next;
}
else
status = nothing_matching;
}
else if(status == ua_modifying)
{
if(*data == '\r')
{
status = nothing_matching;
return scan_finish;
}
else
{
if(covered_length < 9)
*data = str_ua[covered_length];
else
*data = ' ';
covered_length++;
return modified_and_next;
}
}
else if(status == end_matching)
{
if(*data == str_end[covered_length])
{
covered_length++;
if(covered_length == 4)
{
status = nothing_matching;
return scan_finish;
}
else
return next;
}
else
status = nothing_matching;
}
}
}
// 将数据逐字节发送给下一层根据下一层的结果扫描到结尾、扫描到UA、已更改UA确定是否扫描完毕以及是否发生了改动返回到上一层。
inline u_int8_t skb_scan(char *data_start, char *data_end)
{
register char *i;
register u_int8_t ret, modified = 0;
for(i = data_start; i < data_end; i++)
{
ret = char_scan(i);
if(ret == scan_finish)
return modified;
else if(ret == modified_and_next)
modified = ua_modified;
}
return modified + need_next_frag;
}
// 捕获数据包,检查是否符合条件。如果符合,则送到下一层,并根据下一层返回的结果,如果必要的话,重新计算校验和以及继续捕获下一个分片。
unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
register struct tcphdr *tcph;
register struct iphdr *iph;
register char *data_start, *data_end;
static u_int8_t catch_next_frag = 0;
static u_int32_t saddr, daddr, seq;
static u_int16_t sport, dport;
static u_int32_t n_ua_modified = 0, n_ua_modify_faild = 0;
register u_int8_t jump_to_next_function = 0, ret;
// 过滤发往外网的HTTP请求的包且要求包的应用层内容不短于3字节
if(skb == 0)
return NF_ACCEPT;
iph = ip_hdr(skb);
if(iph->protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcph = tcp_hdr(skb);
if(tcph->dest != 80)
return NF_ACCEPT;
data_start = (char *)tcph + tcph->doff * 4;
data_end = data_start + (iph->tot_len - iph->ihl * 4 - tcph->doff * 4);
if((iph->daddr & 0xffff0000) == 0xc0a80000)
return NF_ACCEPT;
// 决定是否发送到下一层
if(catch_next_frag && iph->saddr == saddr && iph->daddr == daddr &&
tcph->seq == seq && tcph->source == sport && tcph->dest == dport)
jump_to_next_function = 1;
else if(data_end - data_start > 3)
if(memcmp(data_start, "GET", 3) == 0 || memcmp(data_start, "POST", 4) == 0)
{
if(catch_next_frag)
{
n_ua_modify_faild++;
char_scan(0);
catch_next_frag = 0;
}
jump_to_next_function = 1;
}
if(!jump_to_next_function)
return NF_ACCEPT;
// 发送到下一层,并回收数据
ret = skb_scan(data_start, data_end);
// 处理返回值
if(ret & need_next_frag)
{
if(!catch_next_frag)
{
catch_next_frag = 1;
saddr = iph->saddr;
daddr = iph->daddr;
sport = tcph->source;
dport = tcph->dest;
}
seq = tcph->seq + (data_end - data_start);
}
else
catch_next_frag = 0;
if(ret & ua_modified)
{
n_ua_modified++;
if(n_ua_modified % 0x10000 == 0)
printk("xmurp-ua: successfully modified %d packages, faild to modify %d packages.",
n_ua_modified, n_ua_modify_faild);
tcph->check = 0;
iph->check = 0;
iph->check = ip_fast_csum((char *)ip_hdr(skb), ip_hdr(skb)->ihl);
skb->csum = skb_checksum(skb, iph->ihl * 4, skb->len - iph->ihl * 4, 0);
tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len - iph->ihl * 4, IPPROTO_TCP, skb->csum);
}
return NF_ACCEPT;
}
static int __init hook_init(void)
{
int ret;
nfho.hook = hook_funcion;
nfho.pf = NFPROTO_IPV4;
nfho.hooknum = NF_INET_POST_ROUTING;
nfho.priority = NF_IP_PRI_FILTER;
ret = nf_register_hook(&nfho);
printk("xmurp-ua start\n");
printk("nf_register_hook returnd %d\n", ret);
return 0;
}
//卸载模块
static void __exit hook_exit(void)
{
nf_unregister_hook(&nfho);
printk("xmurp-ua stop\n");
}
module_init(hook_init);
module_exit(hook_exit);