NDIS HOOK是专业级防火墙使用的一种拦截技术,NDIS HOOK的重点是如何获得特定协议对应NDIS_PROTOCOL_BLOCK指针,获得了该指针,接下来就可以替换该协议所注册的收发函数,而达到拦截网络数据的目的。





     获 得NDIS_PROTOCOL_BLOCK指针的方法一般是用NdisRegisterProtocol注册一个新的协议,所获得的协议句柄实际上就是一 个NDIS_PROTOCOL_BLOCK指针,顺着该指针遍历NDIS_PROTOCOL_BLOCK链表,就可以找到你所要挂钩的协议所对应的 NDIS_PROTOCOL_BLOCK.之所以可以这样做,是因为每注册一个协议,系统都会把该协议对应的NDIS_PROTOCOL_BLOCK放置 在协议链表的开头,该协议链表每个元素都是NDIS_PROTOCOL_BLOCK类型,代表一个已经注册的协议。





     事 实上我们需要的只是TCPIP协议族的NDIS_PROTOCOL_BLOCK指针,毕竟TCP,IP,ARP,ICMP等等几乎所有我们感兴趣的协议, 都是在tcpip.sys协议驱动里面实现的。如果我们只需要TCPIP协议所对应的NDIS_PROTOCOL_BLOCK,那么上面的方法就有点繁琐 了。我们可以试着寻找更简便的方法来获得TCPIP协议的NDIS_PROTOCOL_BLOCK.





于 是我对tcpip.sys驱动进行了反汇编,发现NDIS_PROTOCOL_BLOCK指针存放在一个名为_ARPHandle的全局变量里面,所以如 果能找到_ARPHandle的地址,我们就成功了,我们完全可以把该全局变量的偏移量作为一个常量来使用,但这里纯粹为了拓宽思路,我介绍另一种找到该 全局变量的方法。





     Tcpip.sys有个导出函数叫IPDelayedNdisReEnumerateBindings,该函数内部曾经出现过_ARPHandle 的地址,为什么会出现它的地址呢,因为该函数内部调用过NdisReEnumerateProtocolBindings函数,懂得反汇编的应该知道,在 用call指令调用函数之前,必然会用到push指令将函数的参数压到栈里面去,不巧的是, NdisReEnumerateProtocolBindings函数只有一个参数,而该参数恰恰是一个NDIS_PROTOCOL_BLOCK指针类
型,在这里,实际上就是把_ARPHandle当作参数传给了





NdisReEnumerateProtocolBindings,所以_ARPHandle的地址必然会出现在push指令的后面,说具体一点,紧跟push指令的四个字节就是_ARPHandle的地址。





      所以具体的思路就是这样,先找到IPDelayedNdisReEnumerateBindings函数的地址,然后从该函数的地址开始搜索push指令的特征码,搜到了以后,把紧跟push指令的四个字节作为指向NDIS_PROTOCOL_BLOCK指针的指针返回。





     也许有的人会问,如果IPDelayedNdisReEnumerateBindings函数体内部出现过多次push指令,岂不是会搜出不正确的地址,事实上,虽然都叫push指令,然而在机器码级别是不同的,push指令的机器码表示有十几种之多,用来区别不同的寻址方式,调用NdisReEnumerateProtocolBindings 时用的push指令字节序列是0xff35,这个push指令表示后面紧跟的四个字节是一个内存地址,而不是一个立即数或者寄存器之类的。知道了这些,我 们就可以清楚,在一个有限的地址范围,0xff35的唯一性是可以得到满足的。根据我的观察,在win2000,winxp,win2003上面,IPDelayedNdisReEnumerateBindings本身是一个很短的函数,0xff35指令确实只出现过一次,所以该方法是很可靠的。





思路已经出来了,下面我把详细的代码给大家贴出来,理解这些代码需要对windows Pe格式有所了解,如果你不想理解也行,代码可以直接拿来用。





       以下是我写的一个 获取内核模块某个导出函数地址的 通用例程。这里主要是为了获取tcpip.sys模块的导出函数IPDelayedNdisReEnumerateBindings





   void* GetRoutineAddress(char* ModuleName,char* RoutineName)





{





       PIMAGE_DOS_HEADER dos_hdr;





    PIMAGE_NT_HEADERS nt_hdr;





    PIMAGE_EXPORT_DIRECTORY export_dir;





    ULONG *fn_name, *fn_addr, i;





      char* base;





      base=(char*)FindModule(ModuleName);//该函数用来获得内核模块的基地址





  





    if(!base)





        return NULL;





    DbgPrint("tcpip address:%p",base);





    dos_hdr = (PIMAGE_DOS_HEADER)base;





    if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE)





        return NULL;





    nt_hdr = (PIMAGE_NT_HEADERS)(base + dos_hdr->e_lfanew);





    export_dir = (PIMAGE_EXPORT_DIRECTORY)(base + nt_hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);





    fn_name = (ULONG *)(base + export_dir->AddressOfNames);





    fn_addr = (ULONG *)(base + export_dir->AddressOfFunctions);





    for (i = 0; i < export_dir->NumberOfNames; i++, fn_name++, fn_addr++)





    {





       





        if (strcmp(RoutineName, base + *fn_name) == 0)





        {





           





            return base + *fn_addr;





        }





    }





    return NULL;





}





以下是FindModule函数的实现:





void *

FindModule(char *name)

{

    ULONG i, n, *q;

    PSYSTEM_MODULE_INFORMATION p;

    void *base;





    ZwQuerySystemInformation(SystemModuleInformation, &n, 0, &n);

    q = (ULONG *)ExAllocatePool(PagedPool, n);

    ZwQuerySystemInformation(SystemModuleInformation, q, n * sizeof (*q), 0);

   

    p = (PSYSTEM_MODULE_INFORMATION)(q + 1);

    base = NULL;

    for (i = 0; i < *q; i++) {

        if (_stricmp(p[i].ImageName + p[i].ModuleNameOffset, name) == 0) {

            base = p[i].Base;

          

            break;

        }

    }

       

    ExFreePool(q);

    return base;

}





以下是获取tcpip协议的NDIS_PROTOCOL_BLOCK指针的函数





   





   void* GetProtocolBlock()





{





    char* base;





    char bytes[]={0xff,0x35};





   





    base=GetRoutineAddress("tcpip.sys","IPDelayedNdisReEnumerateBindings");





     while(RtlCompareMemory(base,bytes,2)!=2)





    {





       base++;





    }





    





    return **((void***)(base+2));





    





}

探索NDIS HOOK新的实现方法(1)的更多相关文章

  1. iOS中的过期方法和新的替代方法

    关于iOS中的过期方法和新的替代方法 1.获取某些类的UINavigationBar的统一外观并设置UINavigationbar的背景 注:方法名改了但是基本使用方法不变 + (instancety ...

  2. 利用GBDT模型构造新特征具体方法

    利用GBDT模型构造新特征具体方法 数据挖掘入门与实战  公众号: datadw   实际问题中,可直接用于机器学**模型的特征往往并不多.能否从"混乱"的原始log中挖掘到有用的 ...

  3. 实现Square类,让其继承自Rectangle类,并在Square类增添新属性和方法,在2的基础上,在Square类中重写Rectangle类中的初始化和打印方法

    实现Square类,让其继承自Rectangle类,并在Square类增添新属性和方法,在2的基础上,在Square类中重写Rectangle类中的初始化和打印方法 #import <Found ...

  4. 安全性良好的operator=操作,和新的new方法(针对深度复制的情况)

    class B { }; class A { public: A& operator=(const A& a) { B* temp = b; //这里解决重复赋值的方法是用temp指向 ...

  5. java8在Collection中新增加的方法removeIf

    记得我在以前找工作的经历中,遇到过一个面试官问过我一个很基础的问题.问题是:有一个List中有10个元素,我现在想从中删除3个元素,请问怎么做?我当时也没想,就直接说,List的有自带的remove方 ...

  6. Eviews 9.0新功能——估计方法(ARDL、面板自回归、门限回归)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 9.2 估计功能 eviews9.0下载链接: ...

  7. js给原型增加新属性和方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 乐字节-Java8新特性之方法引用

    上一篇小乐介绍了<Java8新特性-函数式接口>,大家可以点击回顾.这篇文章将接着介绍Java8新特性之方法引用. Java8 中引入方法引用新特性,用于简化应用对象方法的调用, 方法引用 ...

  9. linux,添加新硬盘的方法

    一.物理机添加一块新的硬盘方法(目的是把后加的磁盘直接加在现有的上面,不用再分区挂载)1.首先要确定现有系统在那块盘上  [root@localhost ~]# df -lhFilesystem    ...

随机推荐

  1. Eclipse中安装SVN插件的艰难旅程

    我们写Java程序的人都知道Eclipse,也装过一些插件,比如Android开发的使用需要安装ADT等,如果代码提交的话我们可能需要安装git和svn的插件,但是这个插件我以前听过,但是一直没有安装 ...

  2. 几何向量gcd+暴力枚举——cf552

    两两枚举点(xi,yi)(xj,yj)对于第三个点(xk,yk),只要向量ik和ij方向不同即可 只要(xj-xi,yj-yi) 和 (xk-xi,yk-yi)化简后不相同即可,用每个点开个map存下 ...

  3. JS中的call()、apply() 以及 bind()方法用法总结

    JS中的call()方法和apply()方法用法总结  : 讲解: 调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域. function add(c,d){ return thi ...

  4. ES数据导入导出

    ES数据导入导出   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ...

  5. mac下nginx

    配置文件位置 /usr/local/etc/nginx/nginx.conf 简单命令 nginx -s quit 退出 nginx -s reload 重新加载 nginx -t 测试nginx.c ...

  6. robotframework悬浮菜单定位问题

      有些菜单是悬浮菜单,鼠标点上去下级元素才会显示.比如在第一个菜单中选择后会触发二级菜单的某事件,触发二级菜单又去点三级菜单.. 最开始就用click element去点击了,可是菜单会缩回去,就有 ...

  7. mvc 前台传入后台

    转自:http://blog.csdn.net/huangyezi/article/details/45274553 一个很简单的分部视图,Model使用的是列表,再来看看调用该分部视图的action ...

  8. CentOS6.8搭建LNMP环境

    selinux可能会致使编译安装失败,我们先禁用它.永久禁用,需要重启生效 sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/g’ /etc/selinux/c ...

  9. PAT_A1041#Be Unique

    Source: PAT A1041 Be Unique (20 分) Description: Being unique is so important to people on Mars that ...

  10. 拾遗:systemctl --user

    参考:https://wiki.gentoo.org/wiki/Systemd systemd 支持普通用户定义的 unit[s] 开机启动 systemctl --user enable/disab ...