登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
 内容搜索 网页 下载 源代码
热点文章
  利用鼠标键盘钩子截获密码
  利用鼠标键盘钩子截获密码
  如何将多个文件捆绑成一个可..
  如何将多个文件捆绑成一个可..
  内核级HOOK的几种实现与应用
  内核级HOOK的几种实现与应用
  书写基于内核的linux键盘纪录..
  书写基于内核的linux键盘纪录..
  CIH病毒原码
  CIH病毒原码
  编写进程/线程监视器
  编写进程/线程监视器
本站原创
  利用鼠标键盘钩子截获密码
  利用鼠标键盘钩子截获密码
最新招聘信息

您现在的位置:立华软件园->安全防线->黑客编程
W2K主机ARP表操作的实现
发表日期:2003-10-14作者:flashsky[] 出处:  

  现在ARP欺骗比较流行了,特别是针对交换网络的环境的WINDOWS系统,WINDOWSS默认会对接收到的ARP包就进行ARP表的修改,另外就是WINDOWS的ARP静态包ARP -S是没有效果的,设置了ARP -S的地址一样会接收到一个ARP欺骗包以后改变自己的ARP表?。去年我已经写了一个基于ARP中间进行NTLM认证攻击的东西,于是就在想怎么在交换环境中检测ARP欺骗呢。

  一种想法是直接嗅探网络中的ARP包进行分析,只是这种方法对于交换环境的网络是无效的。那么只能是在主机上针对收到的ARP包进行检测和分析了。但实际上如果用低层包拦截过滤的方式又会极大的影响网络的速度。如果我们根据ARP表的变化能主动通知就好了。实际上从技术上实现是可能的,因为一个秘密:对于ARP表,W2K系统是通过内建的SNMP来进行管理的,不管你的SNMP服务是否开启,呵呵,奇怪吧?(可能其他的WINDOWS系统也一样,但是我没作过测试)

  先我也一样很奇怪ARP这个程序是如何运行的,因为查遍了所有MSDN的文档都没有涉及到ARP表读取,修改的API。万般无奈之下,只有看ARP的汇编代码,才发现这个秘密。ARP -S命令也只是根据SNMP对应的OID接点的ARP表规范的ARP类型由3(动态)修改成4(静态),但是低层的TCP/IP协议栈在收到ARP包以后修改SNMP对应的ARP表,根本就没有检查其类型,这也是ARP -S命令无效的原因。那么如下代码就是根据ARP程序反汇编出的C程序的代码,主要是通过内建的SNMP操作获得ARP表和对ARP表进行操作,其中由于代码本身是我写成的一个ARP检测的工具的ARP核心的COM中COPY出来的,所以一定头文件定义,变量定义不是很全,本来是想发布这个工具的,但是没看见可以提交工具的地方,然后觉得给大家讲解源代码可能更符合安全焦点的FREE原则吧。主要是给大家阅读其原理然后在实用的,需要大家具备一点SNMP协议的知识。

char asnmpu[200];

char asnmpg[200];

char asnmpu1[32];

char asnmpg1[32];

//通过WINDOWS内建的SNMP读取ARP表

STDMETHODIMP Carpinfo::getarpinfo(int *num)

{

  int i;

  int j;

  int k;

  int numoid;

  int ip[256][4];

  char buffer[256];

  SnmpVarBindList a;//是在SNMP.h中定义的结构

  SnmpVarBindList b; 

  SnmpVarBind arpb[2];//在SNMP.h中定义的结构

  AsnInteger32 a1;  

  AsnInteger32 a2;  

  BOOL lok;  

  DWORD addr;

  DWORD addr1;

  ZeroMemory(asnmpu,200);

  ZeroMemory(asnmpg,200);

  ZeroMemory(asnmpu1,32);

  ZeroMemory(asnmpg1,32);

  addr = (DWORD)asnmpu;

  *(u_char *)addr = 1;

  addr = addr + 4;

  *(u_char *)addr = 3;

  addr = addr + 4;

  *(u_char *)addr = 6;

  addr = addr + 4;

  *(u_char *)addr = 1;

  addr = addr + 4;

  *(u_char *)addr= 2;

  addr = addr + 4;

  *(u_char *)addr= 1;

  addr = addr + 4;

  *(u_char *)addr= 4;

  addr = addr + 4;

  *(u_char *)addr= 22;

  addr = addr + 4;

  *(u_char *)addr= 1;

  addr = addr + 4;

  *(u_char *)addr= 2;

  //以上是构造ARP表在SNMP MIB中的MAC ARP地址接点的OID,在WINDOWS的SNMP请求中每个OID点是4个字节长度

  arpb[0].name.idLength = 10;

  //OID的长度

  arpb[0].name.ids = (unsigned int *)asnmpu;

  a.list = &arpb[0];

  a.len = 1;

  //构造了一个SnmpVarBindList请求,如果有多个SnmpVarBindList请求也可以增加len和对应的a.list中的内容

  a1 = 0;

  a2 = 0;

  addr = (DWORD)asnmpg;

  *(u_char *)addr = 1;

  addr = addr + 4;

  *(u_char *)addr = 3;

  addr = addr + 4;

  *(u_char *)addr = 6;

  addr = addr + 4;

  *(u_char *)addr = 1;

  addr = addr + 4;

  *(u_char *)addr= 2;

  addr = addr + 4;

  *(u_char *)addr= 1;

  addr = addr + 4;

  *(u_char *)addr= 4;

  addr = addr + 4;

  *(u_char *)addr= 22;

  addr = addr + 4;

  *(u_char *)addr= 1;

  addr = addr + 4;

  *(u_char *)addr= 4;

  //以上是构造ARP表在SNMP MIB中的ARP IP地址接点的OID,在WINDOWS的SNMP请求中每个OID点是4个字节长度

  arpb[1].name.idLength  = 10;

  arpb[1].name.ids = (unsigned int *)asnmpg;

  b.list  = &arpb[1];

  b.len = 1;

  * num = 0;

  for(i=0;i<256;i++)

  {

    ZeroMemory(buffer,256);

    lok=SnmpExtensionQuery(SNMP_PDU_GETNEXT,&a,&a2,&a1);    

    a1 = 0;

    a2 = 0;

    lok=SnmpExtensionQuery(SNMP_PDU_GETNEXT,&b,&a2,&a1);

    numoid = arpb[0].name.idLength - 14;

    addr= (DWORD)a.list->name.ids;    

    addr1 = (DWORD)asnmpg+40+4*numoid;    

    ip[i][0]=*(int *)(addr+40+4*numoid);

    ip[i][1]=*(int *)(addr+44+4*numoid);

    ip[i][2]=*(int *)(addr+48+4*numoid);

    ip[i][3]=*(int *)(addr+52+4*numoid);

    if(ip[i][0]==0 && ip[i][1]==0 && ip[i][2]==0 && ip[i][3]==0)

      break;

    if(i>0)

    {

      if(ip[i][0]==ip[0][0] && ip[i][1]==ip[0][1] && ip[i][2]==ip[0][2] && ip[i][3]==ip[0][3])

      {

        * num = i;

        m_arpnum = i;

        break;

      }

    }    

    addr = (DWORD)a.list ->name.ids ;

    j = sprintf(buffer,"%d.%d.%d.%d=",*(int *)(addr+44),*(int *)(addr+48),*(int *)(addr+52),*(int *)(addr+56));

    addr = (DWORD)a.list ->value.asnValue.string.stream ;

    k = sprintf(buffer+j,"%02x-%02x-%02x-%02x-%02x-%02x",*(u_char *)(addr+0),*(u_char *)(addr+1),*(u_char *)(addr+2),*(u_char *)(addr+3),*(u_char *)(addr+4),*(u_char *)(addr+5));

    addr = (DWORD)(b.list) ->value.asnValue.number;

    if(addr==4)

      sprintf(buffer+j+k,"=static");

    else if(addr==3)

      sprintf(buffer+j+k,"=dynamic");

    else

      sprintf(buffer+j+k,"=status:%d",addr);

    m_arpinfo[i] = buffer;

  }

  return S_OK;

}

//改变ARP表内容,如果是一个不存在的IP则是增加一条ARP记录

STDMETHODIMP Carpinfo::changearp(BSTR ip, BSTR mac, int arptype, long mactype)

{

  char arpinfo[4][200];

  int i;

  u_char ipstr[4];

  u_char macstr[6];

  SnmpVarBindList a;

  SnmpVarBind arpb[4];

  AsnInteger32 a1;  

  AsnInteger32 a2;  

  BOOL lok;  

  char ipstr1[10];

  char macstr1[14];

  WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,ip,-1,ipstr1,10,NULL,NULL);

  WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,mac,-1,macstr1,14,NULL,NULL);

  for(i=0;i<4;i++)

  {

    ipstr[i]=hextoint(ipstr1[2*i+0])*16+hextoint(ipstr1[2*i+1]);

  }

  for(i=0;i<6;i++)

  {

    macstr[i]=hextoint(macstr1[2*i+0])*16+hextoint(macstr1[2*i+1]);

  }

  for(i=0;i<4;i++)

  {

    ZeroMemory(arpinfo[i],200);

    arpinfo[i][0]=1;

    arpinfo[i][4]=3;

    arpinfo[i][8]=6;

    arpinfo[i][12]=1;

    arpinfo[i][16]=2;

    arpinfo[i][20]=1;

    arpinfo[i][24]=4;

    arpinfo[i][28]=22;

    arpinfo[i][32]=1;

    arpinfo[i][36]=i+1;

    *(unsigned long *)(arpinfo[i]+40)=mactype;

    arpinfo[i][44]=ipstr[0];

    arpinfo[i][48]=ipstr[1];

    arpinfo[i][52]=ipstr[2];

    arpinfo[i][56]=ipstr[3];

    arpb[i].name.idLength = 15;

    arpb[i].name.ids = (unsigned int *)arpinfo[i];

    if(i==0)

    {

      arpb[i].value.asnType  = 2;

      arpb[i].value.asnValue.number = mactype;

    }

    if(i==1)

    {

      arpb[i].value.asnType = 4;

      arpb[i].value.asnValue.string.stream = macstr;

      arpb[i].value.asnValue.string.length = 6;

      arpb[i].value.asnValue.string.dynamic = 0;

    }

    if(i==2)

    {

      arpb[i].value.asnType = 0x40;

      arpb[i].value.asnValue.address.stream = ipstr;

      arpb[i].value.asnValue.address.length = 4;

      arpb[i].value.asnValue.address.dynamic = 0;

    }

    if(i==3)

    {

      arpb[i].value.asnType = 2;

      arpb[i].value.asnValue.number = arptype;

    }

  }

  //对ARP表的修改涉及到4个OID接点,分别进行处理,asnType代表了接点类型的格式

  a.list  = &arpb[0];

  a.len = 4;

  a1 = 0;

  a2 = 0;

  lok=SnmpExtensionQuery(SNMP_PDU_SET,&a,&a1,&a2);      

  return S_OK;

}

int Carpinfo::hextoint(char hexc)

{

  if (ascchar<='9') return(ascchar-'0');

  else if(ascchar<='F') return(ascchar-'A'+10);

  else return(ascchar-'a'+10);

}

  最后,其实熟悉SNMP的同志肯定会很容易想到通过SNMP TRAP就很容易达到ARP主动变化通知的目的,无需定期轮询ARP表,那就是留给你们的一个实现ARP欺骗检测的思路了。

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 W2K主机ARP表操作的实现
关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接

Copyright ©2001-2003 Allrights reserved
e_mail:站长:webmaster(at)lihuasoft.net
网站编程QQ群  
京ICP备05001064号

页面生成时间:0.00512