ecn kg 発表
Post on 08-Jan-2016
60 views
Embed Size (px)
DESCRIPTION
ECN KG 発表. カーネルをハックしてみよう. ネットワークスタックをいぢる. FreeBSD のカーネルコードに printf をいれて処理を追ってみる 今日のターゲットは ICMP です!. まずは QEMU を手に入れよう. 既に QEMU をダウンロードしてありますよね? http://www.ht.sfc.keio.ac.jp/~sada/etc/qemu-0.7.zip 下記媒体でも配布します。 CD-R SD カード コンパクトフラッシュ QEMU を手に入れたら、ローカルの好きな場所においてください. FreeBSD@QEMU の起動. - PowerPoint PPT PresentationTRANSCRIPT
ECN KG
FreeBSDprintfICMP
QEMUQEMUhttp://www.ht.sfc.keio.ac.jp/~sada/etc/qemu-0.7.zipCD-RSDQEMU
FreeBSD@QEMU qemu-freebsd.batrootIPdhclient ed0port 22qemu-freebsd.batportQEMU 10.0.2.2FreeBSD 10.0.2.16
/usrsrcsysi386kernnetnetinetsysufsvmX86TCP/IPUnix
ICMP Echo Request, Reply ip_output()applicationether_output()arpresolve()rip_input()applicationip_input()ether_input()icmp_input()
ICMP ECHO RequestICMP Echo Request ping ip_output()IPether_output()arpresolve()arp
printfprintf#define DBG(fmt, arg...) printf("%s: "fmt "\n", __FUNCTION__, ## arg)
ip_outputsys/netinet/ip_output.c
- ip_output()(IP)ip_output(){ip = mtod(m, struct ip *); if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { ip->ip_v = IPVERSION; ip->ip_hl = hlen >> 2; ip->ip_id = ip_newid(); ipstat.ips_localout++; } else { hlen = ip->ip_hl
ip_output()()ip_output(){ dst = (struct sockaddr_in *)&ro->ro_dst;again: if (ip->ip_src.s_addr == INADDR_ANY) { /* Interface may have no addresses. */ if (ia != NULL) { ip->ip_src = IA_SIN(ia)->sin_addr; } }
ip_output()()ip_output(){ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); goto done; }}IP
IP headerip_vip_hltosip_tosip_lenip_idip_offTTLip_ttlip_pip_sumIPip_srcIPip_dst
32bit#define IP_ADDR_FORMAT(addr)\ ((addr) & 0xff), \ (((addr) >> 8) & 0xff), \ (((addr) >> 16) & 0xff), \ (((addr) >> 24) & 0xff)
DBG(ip_src %d.%d.%d.%d ip_dst %d.%d.%d.%d",IP_ADDR_FORMAT(ip->ip_src.s_addr), IP_ADDR_FORMAT(ip->ip_dst.s_addr));
cd /usr/src/sys/i386/compile/ECNmake kernelmake kernel-installmake clean make shutdown -r now
Pingdhclient ed0ping 10.0.2.2dmesg
splip_outputsplnet(), splx()FreeBSDsplnet(), splimp()splimpsplnetsplimp
spl
spl0splsoftclocksplnetsplttyI/OsplbioI/OsplimpI/Osplclocksplhighsplx(x)
ether_output()sys/net/if_ethersubr.c
ether_output(ARP)intether_output(){ case AF_INET: error = arpresolve(ifp, rt0, m, dst, edst); if (error) return (error == EWOULDBLOCK ? 0 : error);type = htons(ETHERTYPE_IP); break;
ARParpresolvARPether_output
ether_output()intether_output(){ M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT); if (m == NULL) senderr(ENOBUFS); eh = mtod(m, struct ether_header *); (void)memcpy(&eh->ether_type, &type, sizeof(eh->ether_type)); (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
M_PREPENDIPETHER
ICMPIPICMPIPeth
ether_output_frame()intether_output_frame(){ IFQ_HANDOFF(ifp, m, error); return (error);}
printf
Ether Headerstruct ether_header{u_char ether_dhost[6]; u_char ether_shost[6]; u_short ether_type;}IPv4type0x0800
MACdefine
voidmac_print(u_char *macaddr){ int n;printf("mac = ["); for (n=0; n
arpresolveether_output()ARPARPARP2arpresolveARParprequestarprequestARP
arpresolve(ARP)sys/netinet/if_ether.cintarpresolve(){ rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);. if ((rt->rt_expire == 0 || rt->rt_expire > time_second) && sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
arplookupARPARP
arpresolve(ARP)intarpresolve(){ if (rt->rt_expire) { rt->rt_flags &= ~RTF_REJECT; if (la->la_asked == 0 || rt->rt_expire != time_second) { rt->rt_expire = time_second; if (la->la_asked++ < arp_maxtries) { struct in_addr sin = SIN(rt->rt_ifa->ifa_addr)->sin_addr;
RT_UNLOCK(rt); arprequest(ifp, &sin, &SIN(dst)->sin_addr, IF_LLADDR(ifp));
ARPARPARParprequest()
arprequest(ARP)static void arprequest(){ if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) return;ARPmbuf ah->ar_pro = htons(ETHERTYPE_IP); ah->ar_hln = ifp->if_addrlen; ah->ar_pln = sizeof(struct in_addr);
(*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
ARP()if_ether.h struct arphdr { u_short ar_hrd; HW u_char ar_hln; u_char ar_pln; u_short ar_op; ARP};
struct ether_arp { struct arphdr ea_hdr; ARPu_char arp_sha[ETHER_ADDR_LEN]; MAC u_char arp_spa[4]; u_char arp_tha[ETHER_ADDR_LEN]; MAC u_char arp_tpa[4]; };
ether_arparphdr
IPMACARP
cd /usr/src/sys/i386/compile/ECNmake kernelmake kernel-installmake clean make shutdown -r now
dmesg
ICMP ECHO ReplyICMP Echo Reply ping ether_input()etherip_input()IPicmp_input()ICMP
ether_input()sys/net/if_ethersubr.c static voidether_input(){ eh = mtod(m, struct ether_header *); etype = ntohs(eh->ether_type); ether_demux(ifp, m);} ether_demuxether
ether_demux()voidether_demux(){ m_adj(m, ETHER_HDR_LEN);ether switch (ether_type) { case ETHERTYPE_IP: if (ip_fastforward(m)) return; isr = NETISR_IP; break; netisr_dispatch(isr, m); return;ether_type
ip_input(IP)schednetisrsys/netinet/ip_input.cvoidip_input(){ ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { ipstat.ips_badvers++; goto bad; }IP
ip_input() voidip_input(){if (hlen > sizeof (struct ip) && ip_dooptions(m, 0)) return;IP LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) {if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr && (!checkif || ia->ia_ifp == m->m_pkthdr.rcvif))
ip_input() voidip_input(){ if (ip->ip_off & (IP_MF | IP_OFFMASK)) { m = ip_reass(m); (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); return;
icmp_input(ICMP)sys/netinet/ip_icmp.cvoidicmp_input(){ ip = mtod(m, struct ip *); m->m_len -= hlen; m->m_data += hlen; icp = mtod(m, struct icmp *);
if (in_cksum(m, icmplen)) {
mbuficmpICMP ICMPIP
icmp_input(raw input)voidicmp_input(){ code = icp->icmp_code; switch (icp->icmp_type) {. case ICMP_ECHOREPLY: default: break; }raw: rip_input(m, off); return;
cd /usr/src/sys/i386/compile/ECNmake kernelmake kernel-installmake clean make shutdown -r now
pingICMP ECHO Request replyarp requestreply
(e.g.AA)
mtodmbufFlagsp218IP_FORWARDINGTypeM_PREPENDIP14IFQ_HANDOFF:if_var.h SIN:struct sockaddr_in sockaddr_dl Link-levelsockaddrnet/if_dl.h Ip_fastforward:Netisr_dispatchIP_MF: 10IP_OFFMASK8