原始套接字透析之实现路由欺骗

2010-08-28 10:50:18来源:西部e网作者:

    Windows系统保持着一张已知的路由器列表,我们可以使用route PRINT命令显示路由表,下面是笔者的电脑运行route PRINT命令后的结果:


  列表中到达某目的节点的第一项Gateway为默认路由器,如果默认路由器关闭,则位于列表第二项的路由器成为缺省路由器。缺省路由向发送者报告另一条到特定主机的更短路由,就是ICMP重定向。攻击者可利用ICMP重定向报文破坏路由,并伪装成路由器截获所有到某些目标网络或全部目标网络的IP数据包,进行窃听。

  显然,前文中我们只是讲解了发送ICMP Ping命令,可以编写更加通用的函数以便发送各种类型的ICMP报文。下面给出了美国北卡罗莱纳大学(University of North Carolina)计算机系的开放源代码的发送各类ICMP报文的程序:

// icmp:发送各类ICMP报文
icmp(type, code, dst, pa1, pa2) short type, code;
IPaddr dst;
char *pa1, *pa2;
{
 struct ep *pep;
 struct ip *pip;
 struct icmp *pic;
 Bool isresp, iserr;
 IPaddr src;
 int i, datalen;
 IcmpOutMsgs++;

 pep = icsetbuf(type, pa1, &isresp, &iserr);
 if (pep == 0)
 {
  IcmpOutErrors++;
  return SYSERR;
 }
 pip = (struct ip*)pep->ep_data;
 pic = (struct icmp*)pip->ip_data;

 datalen = IC_HLEN;

 /* we fill in the source here, so routing won't break it */

 if (isresp)
 {
  if (iserr)
  {
   if (!icerrok(pep))
   {
    freebuf(pep);
    return OK;
   } blkcopy(pic->ic_data, pip, IP_HLEN(pip) + 8);
   datalen += IP_HLEN(pip) + 8;
  }
  icsetsrc(pip);
 }
 else
  pip->ip_src = ip_anyaddr;
  pip->ip_dst = dst;

  pic->ic_type = (char)type;
  pic->ic_code = (char)code;
  if (!isresp)
  {
   if (type == ICT_ECHORQ)
    pic->ic_seq = (int)pa1;
   else
    pic->ic_seq = 0;
    pic->ic_id = getpid();
  }
  datalen += icsetdata(type, pip, pa2);

  pic->ic_cksum = 0;
  pic->ic_cksum = cksum(pic, datalen);

  ipsend(dst, pep, datalen, IPT_ICMP, IPP_INCTL, IP_TTL);
  return OK;
 }
 // icsetdata:根据报文类型填充相应的数据
 int icsetdata(type, pip, pa2)
 int type;
 struct ip *pip;
 char *pa2;
 {
  struct icmp *pic = (struct icmp *)pip->ip_data;
  int i, len;
 
  switch (type) {
   case ICT_ECHORP:
    len = pip->ip_len - IP_HLEN(pip) - IC_HLEN;
    if (isodd(len))
     pic->ic_data[len] = 0; /* so cksum works */
    return len;
   case ICT_DESTUR:
   case ICT_SRCQ:
   case ICT_TIMEX:
    pic->ic_mbz = 0; /* must be 0 */
    break;
   case ICT_REDIRECT:
    pic->ic_gw = (IPaddr)pa2;
    break;
   case ICT_PARAMP:
    pic->ic_ptr = (char) pa2;
    for (i=0; i<IC_PADLEN; ++i)
     pic->ic_pad[i] = 0;
     break;
   case ICT_MASKRP:
    blkcopy(pic->ic_data, &pa2, IP_ALEN);
    break;
   case ICT_ECHORQ:
    if ((int)pa2 > ECHOMAX(pip))
     pa2 = (char *)ECHOMAX(pip);
    for (i=0; i<(int)pa2; ++i)
     pic->ic_data[i] = i;
     return (int)pa2;
   case ICT_MASKRQ:
    blkcopy(pic->ic_data, &ip_anyaddr, IP_ALEN);
    return IP_ALEN;
  }
  return 0;
}

  而下面的代码则显示了计算机在收到ICMP redirect报文后的行为:

// icredirect:处理接收到的ICMP redirect报文,刷新路由缓存
int icredirect(pep) struct ep *pep;
{
 struct route *prt;
 struct ip *pip, *pip2;
 struct icmp *pic;
 IPaddr mask;

 pip = (struct ip*)pep->ep_data;
 pic = (struct icmp*)pip->ip_data;
 pip2 = (struct ip*)pic->ic_data;

 if (pic->ic_code == ICC_HOSTRD)
  mask = ip_maskall;
 else
  netmask(mask, pip2->ip_dst);
  prt = rtget(pip2->ip_dst, RTF_LOCAL);
  if (prt == 0)
  {
   freebuf(pep);
   return OK;
  }
  if (pip->ip_src == prt->rt_gw)
  {
   rtdel(pip2->ip_dst, mask);
   rtadd(pip2->ip_dst, mask, pic->ic_gw, prt->rt_metric, prt->rt_ifnum,IC_RDTTL);
  }
  rtfree(prt);
  freebuf(pep);
 return OK;
} 

  University of North Carolina完整的ICMP代码下载地址为:http://www.cs.unc.edu/~dewan/242/s00/xinu-pentium/icmp/
关键词:路由器