Showing posts with label Perl. Show all posts
Showing posts with label Perl. Show all posts

Tuesday, January 12, 2010

Parsing tcp data without NetPacket::*

Just some code that i wrote that demonstrates how to extract the data contents of a packet without using the NetPackets::* suite of modules. Note that you would have to know the byte starting position(offset) of the data contents of the packet type in order to correctly extract what you will need. In this example, the offset that im using for DNS data is 55 (14 bytes for Ethernet, 20 for IP header, 8 for UDP header and 12 for some dns flags ). Therefore the DNS quesries start at the 55th byte in DNS query packets.

#!/usr/local/bin/perl
#
#
#
use strict;
use Net::Pcap;
##################

my $dev=$ARGV[0];
my $filter = 'udp dst port 53';
my $object;
my $filter_t;
my ($net,$mask,$err,$object);
##################

unless (defined $dev){
print 'Interface not set or is incorrect';
}

print "Sniffing on interface: $dev\n";

if (Net::Pcap::lookupnet($dev, \$net, \$mask, \$err) == -1){
die "Net::Pcap::lookupnet failed - $err";
}

$object = Net::Pcap::open_live($dev, 1500, 0 , 0, \$err );
unless (defined $object){
print 'Unable to create packet cxapture on device - ', $dev, ' - ', $err;
}

if (Net::Pcap::compile($object, \$filter_t, $filter, 1, $mask) == -1){
die 'Unable to compile filter string - ', $filter;
}

Net::Pcap::setfilter($object,$filter_t);
Net::Pcap::loop($object, -1, \&process_packets, 0);
Net::Pcap::close($object);
##########################################

sub process_packets{
my($user_data, $hdr, $pkt) = @_;
my $len = length($pkt);
for (my $count = 55; $count <= $len; $cout++){
my ($data) = sprintf ("%s", chr(ord(substr($pkt,$count,1))));
print "$data";
}
print "\n";
}

Thursday, January 7, 2010

Creating a sniffer using perl

Below is simple program i wrote to sniff live DNS requests so a network admin can have an idea of the websites that a user is requesting in real time.

#!/usr/local/bin/perl

#
#
#
use strict;
use Net::Pcap;
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
##################################

# Variable Declarations

my $filter_t;
my ($tcp,$ip,$ethernet);
my ($net,$mask,$err);
my $dev = $ARGV[0]; //takes the network card interface as the first parameter
my $filter = "udp dst port 53"; //this is the filter we are going to use, in tcpdump notaion
my $optimize = 1;
############################################

# Determine network number and mask for use later on when we're compiling our filter
if (Net::Pcap::lookupnet($dev, \$net, \$mask, \$err) == -1){
die 'Cannot determine network number and subnet mask - ' , $err;
}

# create a live pcap capture object
my $pcap_object = Net::Pcap::open_live($dev, 1500, 0, 0, \$err);
if (defined $err){
die 'Failed to create live capture on - ' , $dev , ' - ', $err;
}

Net::Pcap::compile($pcap_object, \$filter_t, $filter, $optimize, $mask); //compile our filter ,$filter and return it in the $filter_t variable
Net::Pcap::setfilter($pcap_object, $filter_t); //set the compliled filter, of $filter_t
Net::Pcap::loop($pcap_object, -1, \&capture_packets, '') || die 'Unable to perform packet capture'; //loop or sniff packets on the network infinitly
Net::Pcap::close($pcap_object); //close the pcap object gracefully
#######################################

# subroutine to handle each packet that is sniffed
sub capture_packets {
my ($user_data, $hdr, $pkt) = @_; //this line should always be present to handle the incoming packets, You refer to the incoming packets from $pkt as you would see from the next lines of code
my $ethernet = NetPacket::Ethernet->decode($pkt); //decodes the ethernet frame
my $ip = NetPacket::IP->decode($ethernet->{data}); // decodes the IP headers
my $tcp = NetPacket::TCP->decode($ip->{data}); // decodes the TCP data
print "$ip->{src_ip} -> $ip->{dest_ip} : "; // prints source to destination IP's
print "$tcp->{data}\n"; //prints the data contained in this packet
}

The unfortunate thing about dns request is that there can be so many of them, even when you request one website. For instance, try going to www.google.com. You would notice that you capture the dns request for www.google.com in addition to a couple other request that the google page itself has made for you.

Tuesday, December 29, 2009

Perl - Notes

I have decided to learn perl as i began to encouter many perl scripts used for forensics and pentesting. I believe it would help me learn more if i write my own tools and understand the entire process a little bit better. This blog would house my notes and cheat sheets from day one.

Perl is a case sensitive language.

Starting line of every perl program
#!/usr/local/bin/perl

Printing text:
print 'hello world';

When printing from a variable use double quotes instead of single quotes. Information within the single quotes are interpreted as is.
print "$var1";

Declare and assign a variable. This variable is known as a scalar variable. Scalar variables are simple variables containing only one element--a string, a number, or a reference. Strings may contain any symbol, letter, or number. Numbers may contain exponents, integers, or decimal values.
$var1 = 1;
$var1 = 'hello world';

Declare an Array:
@food = ("rice", "eggs", "orange");

Accessing a portion of an array
print "$food[1]"; //this here would print eggs with reference to the above example

Finding length of array just involves redifing the array as a scalar variable. For instance
@food = ("rice", "eggs", "orange");
print "$3"; // This would output '3'

Add and Remove elements from an array
  • push() - adds an element to the end of an array.
  • unshift() - adds an element to the beginning of an array.
  • pop() - removes the last element of an array.
  • shift() - removes the first element of an array.


Concatanate two string variables;
print $string.$linebreak;

Opening a file and printing its contents like the unix program 'cat'
$file_path = '/root/myfile.txt';
open (file1, "$file_path");
@mydata = ;
close(file1);
print @mydata;

Formating Characters
http://www.tizag.com/perlT/perlstrings.php

Regular Expression Cheat Cheets
http://www.cs.tut.fi/~jkorpela/perl/regexp.html

Using substrings.
To use substr() to grab a substring, you need to give it both a string variable to pick something out of and an offset (which starts at 0). The first argument of substr() is the string we want to take something from and the second argument is the offset, or where we want to start at. Substr function can take a third and forth argument, third being the length and forth being a replacement string value.

$mystr = "hello world";

$mystr1 = substr($mystr, 2);
$mystr2 = substr($mystr, 2, 3);
$mystr3 = substr($mystr, 6, 5, "there");

print "$mystr1";
// this would print 'llo world'
print "$mystr2"; // this would print 'llo'
print "$mystr"; // this would print 'hello there'. Note we are printing $mystr and not mystr3 here

Transforming strings into arrays with split function
$mystr = 'the/boy/walked/fast';
@myarr = split('/', $mystr);
print "@myarr"; // this prints 'the boy walked fast'

Likewise we can join elements of an array into a scalar string.
@array = ("David","Larry","Roger","Ken","Michael","Tom");
@array2 = qw(Pizza Steak Chicken Burgers);

@array = ("a") x 10;
print "@array"; //would print the character 'a' 10 times

# JOIN 'EM TOGETHER
$firststring = join(", ",@array);
$secondstring = join(" ",@array2);

Sorting arrays
@myarr = ("chicken" , "eggs", "apples");
@myarr = sort(@myarr);

Conditions and loops are Similar in syntax to C.
[While loop]
$a = ; //Read input from keyboard
while ($a ne "kill")
{
print "wrong";
$a = ; //Read input from keyboard
}

print "Correct";

[For loop]
" for ($x = 0; $x < style="color: rgb(255, 0, 0);">{
print "$x\n";
}

[until statement]
$a = 1;
do

{
print $a;
$a++;
}
while ($a <>

[If statement]
" $a = "hello" ; "
if (length ($a) > 3)
{
print "more than 3 characters";
}

[RE expression] using =~ or !~
$word = "Hello my good friend";
if ($word =~ /my/)
{
print "found the word: my"
exit;
}
print "Not found";

The opposite of the above would be to use '!~' instead of '=~'.

Substitution/replacement:
$word = "canada states";
$word =~ s/canada/United/ //replaces only the first occurance of the string canada with United
$word =~ s/canada/United/g //the addition of the g in the end would replace all occurances of the string. It represents global change.
$word =~ s/[Hh][Oo][Pp][Ee]/Hope/g //This pretty much ignores the case. The next example is a better way to do this
$word =~ s/CanADa/Canada/gi // The 'i' in the end ignores case

$search = "the";
s/$search/xxx/g;

will replace every occurrence of the with xxx. If you want to replace every occurence of there then you cannot do s/$searchre/xxx/ because this will be interpolated as the variable $searchre. Instead you should put the variable name in curly braces so that the code becomes $search = "the";

s/${search}re/xxx/;

Character Translation
$a = "abc";
$a =~ tr/abc/boy/; // will trnaslate a to a b, b to an o and c to a y
print $a; // will print boy

$count = ($a =~ tr/*/*/); //the statement here counts the number of asterisks in the $sentence variable and stores that in the $count variable.

However, the dash is still used to mean "between". This statement converts $_ to upper case. tr/a-z/A-Z/;

Sorting Arrays of words
@array1 = ("orange","yellow","Red","green,","blue");
@sorted = sort(@array1); //Sorts in alphabetical order
@sorted_reversed = sort {$b cmp $a} (array1); //sorts in reverse order

Sorting arrays of numbers
@array1 = (5,7,2,4,1,8,6);
@sorted = sort (@array1); //sorts in alphabetical order
@sorted_reversed = sort {$b <=> $a} (@array1); //sorts in reverse order

Key Functions to remember
my $position = index($longString, $shortstring); //returns the position of a character or substring in a string
splice (@myarr, 2 , 3); // If you have an array of 7 elements, this function reads all the 5 elements and starting from with position two(which is actually the third position, as the first element starts with a 0) cuts the next three elements.