回调函数 及 hook函数有没有签证优先级别别设置

         
您现在的位置:&&>&&>&&>&&>&&>&正文
用HOOK函数自动关闭IE广告窗口
来源:()  【】 
&&在用IE浏览某些网站的时候,网站主页会弹出一些广告网页。所以每当打开这样的网页时,总得手动关闭广告页,感觉比较麻烦。那么,是否可以编写程序来判断打开的网页是否是弹出广告,然后自动关闭这些广告,避免每次手动关闭弹出窗口的麻烦?在一些报刊上介绍了某些解决方法,以下就通过钩子(HOOK)函数截获消息的方法进行讨论:&& 1、弹出式广告框也是IE浏览窗口,一般来说,它是一个无菜单、无工具栏窗口。所以可以在桌面上打开一个窗口时,首先判断该窗口类型是否是“IEFrame”,接着判断IEFrame的子窗口类型“WorkerW”的属性是否是不可见(这是一般弹出式广告窗口的特征),这样就可以向该窗口发出关闭的消息,以上步骤一般能自动关闭大部分弹出广告框。&& 2、通过WINDOWS编程中的钩子(HOOK)函数解决截获在桌面上打开窗口的消息。钩子函数的基本原理就是对WINDOWS系统的某些动作注册,当发生这些事件时首先调用预先设置的回调函数,回调函数处理后,再由原来的函数处理。这里回调函数的作用正是实现1中叙述的功能。因为这里实现的钩子函数是监视其它进程窗口产生的消息,所以必须用动态链接库实现。&& 主要代码如下:&& 在动态链接库中,实现钩子回调函数。&& LRESULT CALLBACK CallWndProc(&& int nCode, // hook code&& WPARAM wParam, // current-process flag&& LPARAM lParam // address of strUCture with message data&& )&& {&& CWPSTRUCT *pCwp = NULL;&& CString strClassN&& HWND hWnd = NULL;&& unsigned long ulStyle = 0;&& BOOL bIsClosed = FALSE;&& if (nCode & 0)&& {&& return CallNextHookEx(gHook, nCode, wParam, lParam);&& }&& if (NULL != lParam)&& {&& pCwp = (CWPSTRUCT *)lP&& if (WM_SHOWWINDOW == pCwp-&message)&& {&& ::GetClassName(pCwp-&hwnd, strClassName.GetBufferSetLength(128), 128);&& //IE窗口的类型为IEFrame&& if (0 == pareNoCase("IEFrame"))&& {&& hWnd = ::GetWindow(pCwp-&hwnd, GW_CHILD);&& if (NULL == hWnd)&& {&& bIsClosed = TRUE;&& }&& while (NULL != hWnd)&& {&& ::GetClassName(hWnd, strClassName.GetBufferSetLength(127), 127);&& //IEFrame的子窗口包含窗口类型WorkerW&& if (0 == pareNoCase("WorkerW"))&1&&&
文章责编:gaoxiaoliang& 看了本文的网友还看了
?&&( 15:51:47)?&&( 14:16:20)?&&( 14:14:40)?&&( 14:13:00)?&&( 14:10:55)?&&( 14:02:35)
? ?   ? ?   ? ?   ? ?   ? ?
? ?   ? ?   ?
?   ? ?    ? ?   ? ?   ? ?   ? ?
? ?   ? ?
实用工具 |
| 大全 | 大全
     |
版权声明:如果网所转载内容不慎侵犯了您的权益,请与我们联系,我们将会及时处理。如转载本内容,请注明出处。
Copyright & 2004-
 网 All Rights Reserved 
中国科学院研究生院权威支持(北京) 电 话:010- 传 真:010-网络编程(40)
向Netfilter中注册自己的hook函数
& & & &&数据包在协议栈中传递时会经过不同的HOOK点,而每个HOOK点上又被Netfilter预先注册了一系列hook回调函数,当每个清纯的数据包到达这些点后会被这些可恶hook函数轮番调戏一番。有时候我们就在想,只让系统自带的这些恶棍来快活,我自己能不能也make一个hook出来和它们同流合污呢?答案是肯定的。
& & & &我们来回顾一下目前系统中已经注册了的hook函数可分为以下几类:
& & & &它们在协议栈中位置如下:
& & & &首先我们心里要非常清楚的知道我们将要开发的这个hook函数位于哪个HOOK点的什么级别,它的前后分别是哪些函数,这一点很重要,因为遇到问题时至少心里有个谱。
& & & &我们今天讲的这个hook函数功能很简单,主要是向大家展示开发流程和方法。细节性的东西还需要每个人日积月累的修炼才行。
&&&&&&&&要注册一个hook函数需要用到nf_register_hook()或者nf_register_hooks()系统API和一个struct nf_hook_ops{}类型的结构体对象。最简单的hook函数如下:
MODULE_LICENSE(&GPL&);
MODULE_AUTHOR(&koorey KING&);
MODULE_DESCRIPTION(&My hook test&);
static int pktcnt = 0;
//我们自己定义的hook回调函数,丢弃每第5×n(n=1,2,3,4…)个ICMP报文。
static unsigned int myhook_func(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
&& const struct iphdr *iph = (*skb)-&nh.
&& if(iph-&protocol == 1){
&&&&& atomic_inc(&pktcnt);
&&&&& if(pktcnt%5 == 0){
&&&&&&&&&& printk(KERN_INFO &%d: drop an ICMP pkt to %u.%u.%u.%u !\n&, pktcnt,NIPQUAD(iph-&daddr));
&&&&&&&&&& return NF_DROP;
&& return NF_ACCEPT;
static struct nf_hook_ops nfho={
&&&&&&& .hook&&&&&&&&&& = myhook_func,& //我们自己的hook回调处理函数
&&&&&&& .owner&&&&&&&&& = THIS_MODULE,
&&&&&&& .pf&&&&&&&&&&&& = PF_INET,
&&&&&&& .hooknum&&&&&&& = NF_IP_LOCAL_OUT, //挂载在本地出口处
&&&&&&& .priority&&&&&& = NF_IP_PRI_FIRST,& //优先级最高
static int __init myhook_init(void)
&& &return nf_register_hook(&nfho);
static void __exit myhook_fini(void)
&&& nf_unregister_hook(&nfho);
module_init(myhook_init);
module_exit(myhook_fini);
&&&&&&&我们在LOCAL_OUT这个HOOK点上,以最高优先级NF_IP_PRI_FIRST注册了一个名为myhook_func()的函数。从本机发出的所有数据包从协议栈进入Netfilter框架时,最先都会被该函数所看到,然后我们在这里就可以“胡作非为”了。
&&&&&&&这个模块最后会被编译成名为myhook.ko的驱动模块,然后用insmod来将其加载。具体操作流程如下:
& & & &可以看到,我们自己的hook函数已经成功run起来了。我们可能不仅局限于做这么简单一个hook,没什么意义,也没啥成就感。况且这种hook压根儿就没有存在的价值,因为我们完全可以通过iptables来配置相应的规则而达到同样的目的。
&&&&&&&OK,那我们就改造一下刚写的这个hook。让它实现的功能是:每收到5个ICMP报文就向指定的IP地址发送一个UDP报文。由于这个功能的开发牵扯到内核协议栈编程,关于协议栈部分打算在以后的系列博文中详细阐述。这里仅做个简单的普及入门就可以了。
&&&&&&我们要实现的功能是从内核中发一个报文,这完全不同于之前在用户层通过socket套接字编程的模式。
Godbach兄的文章,以及内核版的精华帖《教你修改以及重构skb》都是非常经典的参考文章。不太明白的童鞋可以去拜读一下:。
&&&&&&再重申一下我们的目标,每收到5个ICMP报文就向指定IP(例如118.6.24.132)发送一个UDP报文。这里我是在内核里自己去DIY一个新的skb出来,构造数据包和发送数据包的过程如下:
#define&&& ETH&&& &eth0&&&//接口名称
#define&&& SIP&&&& &192.168.6.130&&//接口的IP地址
#define&&& DIP&&&& &118.6.24.132&&//要发送UDP报文的目的IP地址
#define&&& SPORT&& 39804& &//源端口
#define&&& DPORT&& 6980&&&&//目的端口
unsigned char&SMAC[ETH_ALEN] = {0x00,0x0C,0x29,0x33,0x2C,0x3C};&//eth0网卡地址
unsigned char&DMAC[ETH_ALEN] = {0x00,0x50,0x56,0xF4,0x8B,0xB3};&//默认网关的网卡地址
static int build_and_xmit_udp(char * eth, u_char * smac, u_char * dmac,
&&&&&&& &&&&&u_char * pkt, int pkt_len,u_long sip, u_long dip,
&&&&&&&&&&&& u_short sport, u_short dport)
& struct sk_buff * skb = NULL;
& struct net_device * dev = NULL;
& struct ethhdr * ethdr = NULL;
& struct iphdr * iph = NULL;
& struct udphdr * udph = NULL;
& u_char * pdata = NULL;
& if(NULL == smac || NULL == dmac)
& if(NULL == (dev= dev_get_by_name(eth)))
&&//通过alloc_skb()来为一个新的skb申请内存结构
& skb =&alloc_skb(pkt_len + sizeof(struct iphdr) + sizeof(struct udphdr) + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
& if(NULL == skb)
&&skb_reserve(skb, LL_RESERVED_SPACE(dev));
& skb-&dev =
& skb-&pkt_type = PACKET_OTHERHOST;
& skb-&protocol = __constant_htons(ETH_P_IP);
& skb-&ip_summed = CHECKSUM_NONE;
& skb-&priority = 0;
& skb-&nh.iph = (struct iphdr*)skb_put(skb, sizeof(struct iphdr));
& skb-&h.uh = (struct udphdr*)skb_put(skb, sizeof(struct udphdr));
& pdata =&skb_put(skb, pkt_len);&//预留给上层用于数据填充的接口
&&&& if(NULL != pkt)
&&& &&&&memcpy(pdata, pkt, pkt_len);
&&//“从上往下”填充skb结构,依次是UDP层--IP层--MAC层
& udph = (struct udphdr *)skb-&h.
& memset(udph, 0, sizeof(struct udphdr));
& udph-&source =
& udph-&dest =
& skb-&csum = 0;
& udph-&len = htons(sizeof(struct udphdr)+pkt_len);
& udph-&check = 0;
&&//填充IP层
& iph = (struct iphdr*)skb-&nh.
& iph-&version = 4;
& iph-&ihl = sizeof(struct iphdr)&&2;
& iph-&frag_off = 0;
& iph-&protocol = IPPROTO_UDP;
& iph-&tos = 0;
& iph-&daddr =
& iph-&saddr =
& iph-&ttl = 0x40;
& iph-&tot_len = __constant_htons(skb-&len);
& iph-&check = 0;
& iph-&check = ip_fast_csum((unsigned char *)iph,iph-&ihl);
& skb-&csum = skb_checksum(skb, iph-&ihl*4, skb-&len - iph-&ihl * 4, 0);
& udph-&check = csum_tcpudp_magic(sip, dip, skb-&len - iph-&ihl * 4, IPPROTO_UDP, skb-&csum);
&&//填充MAC层
& skb-&mac.raw =&skb_push(skb, 14);
& ethdr = (struct ethhdr *)skb-&mac.
& memcpy(ethdr-&h_dest, dmac, ETH_ALEN);
& memcpy(ethdr-&h_source, smac, ETH_ALEN);
& ethdr-&h_proto = __constant_htons(ETH_P_IP);
&&//调用dev_queue_xmit()发送报文
& if(0 & dev_queue_xmit(skb))
& &if(NULL != skb)
&&&&&&& dev_put (dev);
&&&&&&& kfree_skb (skb);
& &return(NF_ACCEPT);
& & & &上面这部分代码看不懂没关系,因为它需要比较熟练的内核协议栈编程知识,大家可以从整体上对其有个感性的把握就可以了。后面如果有时间我会再写个TCP/IP内核协议栈分析的系列文章,虽然CU上有很多大牛已经在写了,但每个人的收获不一样,和大家分享也是学习的另一种形式。好了,闲话不多说。我们这个hook的最终版本在“”下载。
&&&&&&&接下来,激动人心的时刻又到了,我们来验证一下我们的hook函数是否可以按预期一样地进行工作。编译和加载流程如前面所述。我们为上层应用层往UDP报文中填充数据预留了接口,所以我们可以以如下的形式来调用build_and_xmit_udp()接口:
build_and_xmit_udp(ETH,SMAC,DMAC,”hello”,5,in_aton(SIP),in_aton(DIP),htons(SPORT),htons(DPORT));
& & & &通过wireshark抓包来验证一下是不是每收到5个ICMP报文就往118.6.24.132地址发送一个内容仅有“hello”字符串的UDP报文:
& & & &经过这么一番“改造”,我们自定义这个hook函数算是有点特色了。至此我们今天的内容就全部讲完了。估计有些人可能觉得还少了点什么,有没有悟性比较高的童鞋提出几点质疑来?没错,就是我们这个hook里设置的IP地址是固定的,包括MAC地址、源和目的端口以及发送的内容。用户空间我们根本没法对这些属性进行操作,骤然间,这个模块的可操作性和易用性大打折扣。那么我们到底如何才能从用户空间来操作这个新注册的hook呢?
& & & &未完,待续…
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:34845次
排名:千里之外
原创:28篇
转载:207篇
(1)(2)(4)(22)(68)(29)(29)(51)(7)(16)(2)(2)(2)(5)(1)(4)新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 14, 距离下一级还需 186 积分
论坛徽章:0
HOOK函数的调用过程应该是:
#define NF_HOOK---&#define NF_HOOK_THRESH---&nf_hook_thresh---&nf_hook_slow---&nf_iterate---&elem-&hook ----&ipt_hook----&ipt_do_table
我一直没搞清楚的是:nf_iterate中的elem-&hook怎么跳转到函数ipt_hook ? 求大神!谢谢!
下附nf_iterate()代码:
unsigned int nf_iterate(struct list_head *head,
& & & & & & & & & & & & struct sk_buff **skb,
& & & & & & & & & & & & int hook,
& & & & & & & & & & & & const struct net_device *indev,
& & & & & & & & & & & & const struct net_device *outdev,
& & & & & & & & & & & & struct list_head **i,
& & & & & & & & & & & & int (*okfn)(struct sk_buff *),
& & & & & & & & & & & & int hook_thresh)
& & & & /*
& & & &&&* The caller must not block between calls to this
& & & &&&* function because of risk of continuing from deleted element.
& & & &&&*/
& & & & list_for_each_continue_rcu(*i, head) {
& & & & & & & & struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
& & & & & & & & if (hook_thresh & elem-&priority)
& & & & & & & & & & & &
& & & & & & & & /* Optimization: we don't need to hold module
& && && && && && & reference here, since function can't sleep. --RR */
& & & & & & & & verdict = elem-&hook(hook, skb, indev, outdev, okfn);
& & & & & & & & if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
& & & & & & & & & & & & if (unlikely((verdict & NF_VERDICT_MASK)
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & NF_MAX_VERDICT)) {
& & & & & & & & & & & & & & & & NFDEBUG(&Evil return from %p(%u).\n&,
& & & & & & & & & & & & & & & && && && &elem-&hook, hook);
& & & & & & & & & & & & & & & &
& & & & & & & & & & & & }
& & & & & & & & & & & & if (verdict != NF_REPEAT)
& & & & & & & & & & & & & & & &
& & & & & & & & & & & & *i = (*i)-&
& & & & & & & & }
& & & & return NF_ACCEPT;
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
稍有积蓄, 积分 270, 距离下一级还需 230 积分
论坛徽章:1
可以看一下net/ipv4/netfilter/iptable_filter.c中的init函数
static int __init iptable_filter_init(void)
& && &&&ret = register_pernet_subsys(&iptable_filter_net_ops);
& && &&&if (ret & 0)
& && && && && &
& && &&&/* Register hooks */
& && &&&filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
/*filter_ops应该就是elem,iptables_filter_hook就是你上面说ipt_hook,elem的hook就是iptables_filter_hook,在iptables_filter_hook中会返回ipt_do_table*/
& && &&&if (IS_ERR(filter_ops)) {
& && && && && & ret = PTR_ERR(filter_ops);
& && && && && & unregister_pernet_subsys(&iptable_filter_net_ops);
白手起家, 积分 14, 距离下一级还需 186 积分
论坛徽章:0
多谢!我学习下看!回复
philarlala
白手起家, 积分 14, 距离下一级还需 186 积分
论坛徽章:0
请问下,我的iptable_filter的init函数怎么和你的不一样?我用的内核是2.6.20的!
static int __init iptable_filter_init(void)
& & & & if (forward & 0 || forward & NF_MAX_VERDICT) {
& & & & & & & & printk(&iptables forward must be 0 or 1\n&);
& & & & & & & & return -EINVAL;
& & & & /* Entry 1 is the FORWARD hook */
& & & & initial_table.entries[1].target.verdict = -forward - 1;
& & & & /* Register table */
& & & & ret = ipt_register_table(&packet_filter, &initial_table.repl);
& & & & if (ret & 0)
& & & & & & & &
& & & & /* Register hooks */
& & & & ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
& & & & if (ret & 0)
& & & & & & & & goto cleanup_
cleanup_table:
& & & & ipt_unregister_table(&packet_filter);
philarlala
稍有积蓄, 积分 270, 距离下一级还需 230 积分
论坛徽章:1
内核版本不一样,我的是3.14的,这个应该不影响理解xt_hook_link中封装的就是nf_register_hooks回复
大富大贵, 积分 18198, 距离下一级还需 1802 积分
论坛徽章:15
楼上说的对,不管内核版本的细节怎么调整,基本关系是不变的:
*& &nf_iterater: 遍历链表中的回调函数(netfilter hooks);
*& &nf_registers_hook:在链表中添加回调函数
论坛徽章:36
内核中大量使用register 的机制,一个函数指针,指向一个 hook 或者 handler 之类的。HOOK 就是如此。

我要回帖

更多关于 优先级别 英文 的文章

 

随机推荐