![]() |
列表中到達某目的節點的第一項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/