mirror of
https://github.com/CHN-beta/xmurp-ua.git
synced 2024-10-22 19:38:44 +08:00
first use git
This commit is contained in:
commit
dd3cab6aa8
30
Makefile
Normal file
30
Makefile
Normal 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
2
src/Kconfig
Normal file
@ -0,0 +1,2 @@
|
||||
config xmurp-ua
|
||||
tristate "xmurp-ua"
|
1
src/Makefile
Normal file
1
src/Makefile
Normal file
@ -0,0 +1 @@
|
||||
obj-${CONFIG_xmurp-ua} += xmurp-ua.o
|
242
src/xmurp-ua.c
Normal file
242
src/xmurp-ua.c
Normal 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);
|
Loading…
Reference in New Issue
Block a user