Competition Number 2: Coding

74 lines of fun... and here it is, a network address scanner...
including some DNS resolution to get names for the addresses that are found.

There is a section of code based on a function given on the PHP manual pages, (I believe the socket creation page). that's a ping function.

I could have used exec(ping) and got the output from that. but I thought it was a little bit cleaner this way, as my script doesn't rely on any system components or external tools...

you need to have the extension to allow socket connections turned on in your php.ini file...
Code:
extension=php_sockets.dll
i'm running this from the command line under windows 7.

"c:\>c:\php\php.exe c:\network_scanner\scan.php"

to run this script successfully under windows 7 you need to have notifications set to never notify. I don't know why this is, a windows 7 problem, or a php problem, whatever it is the default security setting scuppers php's ability to creake socket connections.

there are 2 user inputs to the script, (start_address and mask).
your start address is the first address in the range that you want to scan, the mask is the subnet mask bits.

for example a subnet mask of 255.255.255.0 has 24 mask bits
255.255.255.128 has 25 mask bits
255.0.0.0 has 8 mask bits...
(if you can't convert these then google for a subnet calculator).

the script works by taking the start address that you put in, and converting it to binary,
then it looks at the amount of mask bits that you've specified, and generates a 32bit mask based on this number...

the script then starts a loop, incrementing the binary address until the address matches the constructed end of range address.

for each increment it does a basic ping of the address at the end it prints an array of all the addresses that have been pinged and that responded.

after that it does a DNS name resolution on each address, then prints another array that tells you the name associated with the address.


Code:
<?php
$start_address = "192.168.1.1";
$mask = "24";

//split range from dot seperated into array
    $octet = explode(".", $start_address);
    //convert decimal octets to binary in start address
    $binet[0] = str_pad(decbin($octet[0]), 8, '0',STR_PAD_LEFT);
    $binet[1] = str_pad(decbin($octet[1]), 8, '0',STR_PAD_LEFT);
    $binet[2] = str_pad(decbin($octet[2]), 8, '0',STR_PAD_LEFT);
    $binet[3] = str_pad(decbin($octet[3]), 8, '0',STR_PAD_LEFT);
    //construct 32bit binary string of start address
    $total = implode("", $binet);
    //split the binary string by the mask to find the bits that will change in the range
    $mbit = str_split($total, $mask);
    $filler = "11111111111111111111111111111111";
    //find how many filler bits are needed from the mask
    $fillbit = 32 - $mask;
    $fbits = str_split($filler, $fillbit);
    //construct end of range address
    $stop[0] = $mbit[0];
    $stop[1] = $fbits[0];
    $stops = implode("", $stop);
    //define array for recording results in
    $responsive_addresses = array();
    print "Pinging! :";
    //itterate through range (convert the binary range to decimal to increment since PHP doesn't do binary addtion easily)
    for($total=$total;bindec($total)<=bindec($stops);$total = decbin((bindec($total)+1)))
    {
        //split the start address (32bit binary string) into 4 octets
        $ip = str_split($total, 8);
        //convert the binary octets to decimal
        $ip[0] = bindec($ip[0]);
        $ip[1] = bindec($ip[1]);
        $ip[2] = bindec($ip[2]);
        $ip[3] = bindec($ip[3]);
        //make dotted decimal address from octets
        $addr = implode(".", $ip);
        print "$addr, ";
        $ping =NULL; //reset variable
        $ping = ping($addr);
        if ($ping != NULL)
        {
            //record the responsive addresses in an array.
            array_push($responsive_addresses, $addr);
        }
    }
    print "\r\n\npinged addresses = \r\n";
    print_r($responsive_addresses);
$no_addresses = sizeof($responsive_addresses);
for ($array_place=0;$array_place<$no_addresses;$array_place++)
{
    $hostname = gethostbyaddr($responsive_addresses[$array_place]);
    print "\r\nhostname = $hostname";
}
/*THIS PING FUNCTION IS BASED ON A PING FUNCTION FROM THE PHP MANUAL PAGES*/
function ping($host) {
    $package = "\x08\x00\x19\x2f\x00\x00\x00\x00\x70\x69\x6e\x67";
    /* create the socket, the last '1' denotes ICMP */
    $socket = socket_create(AF_INET, SOCK_RAW, 1);
    /* set socket receive timeout to 1 second */
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 1, "usec" => 10));
    /* connect socket */
    socket_connect($socket, $host, null);
    /* send ping packet */
    socket_send($socket, $package, strlen($package), 0);
    if(@socket_read($socket, 255)) {
      return 1;
    } else {
        return false;
    }
    socket_close($socket);
}
?>

I think that if I were to delete the comments, and change that concrete structure of the code, (which is a bit of a throw back from when I learned to code in C) I could probably reduce the amount of code to about 50 lines...

further functionality can be added to change the ping function to create a TCP socket connection to a specific service...

that'd be a more fully functioned network scanner.
 
Back
Top Bottom