Python socket server causing Error 1006 client-side - python

I am currently building a small socket server in Python, and a web-based client using the WebSocket JavaScript API, and the connection keeps closing after I send the first message.
I tryed connecting to //echo.websocket.org and sending a message and there's no problem there. So as I've read that Error meant a low-level implementation error, I'm assuming that it comes from my server, may am I doing the Handshake wrong. Here is the client code:
function init_game(){
socket = new WebSocket('ws://localhost:3003');
//socket = new WebSocket('ws://echo.websocket.org');
setupSocket();
}
function setupSocket(){
socket.onopen = function(){
console.log('Connection open !');
var msg = {cmd: 'hello', params: {}};
var data = JSON.stringify(msg);
console.log('Sending : ' + data);
socket.send(data);
};
socket.onmessage = function(e){
var data = e.data;
console.log('Received : ' + data);
handle(data);
};
socket.onerror = function(e){
console.log('ERROR : ' + e.code + " - " + e.reason);
};
socket.onclose = function(e){
console.log('CONNECTION CLOSED : ' + e.code + " - " + e.reason);
}
}
function handle(data){
//doing stuff
}
window.onload = init_game;
And here the server code:
class ClientThread(threading.Thread):
# Constructor
def __init__(self, conn, id, q):
threading.Thread.__init__(self)
self.conn_ = conn
self.id_ = id
self.name_ = ''
self.q_ = q
self.handshaken_ = True
self.encoded_ = False
# Main loop
def run(self):
raw_data = self.conn_.recv(1024)
if raw_data[:3] == 'GET':
self.handshaken_ = False
self.handshake(raw_data)
while True:
raw_data = self.conn_.recv(1024)
if len(raw_data) == 0:
continue
if self.handshaken_:
if self.encoded_:
raw_data = self.decode(raw_data).decode('utf-8')
try:
data = json.loads(raw_data)
cmd = data['cmd']
params = data['params']
self.handle(cmd, params)
except ValueError, e:
print 'Data received was not JSON'
else:
print 'Received something but Handshake is not done yet... Something is going wrong.'
# Decode encoded message received frmo the client
def decode(self, data):
frame = bytearray(data)
length = frame[1] & 127
indexFirstMask = 2
if length == 126:
indexFirstMask = 4
elif length == 127:
indexFirstMask = 10
indexFirstDataByte = indexFirstMask + 4
mask = frame[indexFirstMask:indexFirstDataByte]
i = indexFirstDataByte
j = 0
decoded = []
while i < len(frame):
decoded.append(frame[i] ^ mask[j%4])
i += 1
j += 1
return "".join(chr(byte) for byte in decoded)
# Performs handshake protocole in case it's needed
def handshake(self, get):
websocket_answer = (
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: {key}\r\n\r\n',
)
GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
raw_key = re.search('Sec-WebSocket-Key:\s+(.*?)[\n\r]+', get)
if raw_key != None:
# Create Handshake answer...
key = raw_key.groups()[0].strip()
handshake_key = b64encode(sha1(key + GUID).digest())
handshake = '\r\n'.join(websocket_answer).format(key=handshake_key)
# And send it to the client
self.conn_.send(handshake)
self.handshaken_ = True
self.encoded_ = True
else:
print 'No key found during Handshake.'
self.disconnect()
# Handle JSON commands send by the client
def handle(self, cmd, params):
# doing stuff
def disconnect(self):
print 'Disconnecting.'
pass
class MainServer(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.HOST = ''
self.PORT = 3003
self.socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.socket_.bind((self.HOST, self.PORT))
except socket.error as msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
self.clients_ = {1: Player(1), 2: Player(2)}
self.q_ = Queue()
def run(self):
self.socket_.listen(10)
nb_player = 0
new_id = 1
while nb_player < 2:
conn, addr = self.socket_.accept()
print 'A new player connected with ' + addr[0] + ':' + str(addr[1])
self.clients_[new_id].conn = conn
th = ClientThread(conn, new_id, self.q_)
th.start()
new_id += 1
nb_player += 1
while True:
data = self.q_.get(block=True)
self.handle(data['cmd'], data['params'])
def handle(self, cmd, params):
# doing stuff
if __name__ == '__main__':
serv = MainServer()
serv.start()
Please tell me if you need any other information.
Thanks !
Robin

Related

Client seems to hang after a specific reply from server

I am implementing an authentication process between a server and a client in order to exchange some information. I have created a function called serverToClientAuth on both server and client that carries out a basic back and forth communication to establish authenticated integrity checks of each other before exchanging some data.
When I run the server, followed by the client, the exchange occurs perfectly with encryption and hashing working as required but on the very last message from the server to the Client, the client seems to hang and is unable to exit the function and go back to normal operation Although the first 3 communications work fine, the last one does not for some reason.
I thought at first that it had something to do with the encryption/Decryption functions but as the first 3 operations work, I don't see why the last doesn't? It seems that the recieve_msg function is grabbing the last message instead of the authentication function, this is the final '12' output on the client window as seen below.
I have included both the server and client as well as the output of each below. If anyone has any idea as to why this hang is occurring, it would be greatly appreciated.
#Server.py
from socket import AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR, socket
from threading import Thread
from signal import signal, SIGINT
import sys
import os
import random
import rsa
WELCOME_MSG = 'Server is active and awaiting connections'
def nonceGenerator():
num = ""
for i in range(5):
rand = random.randint(0,1)
num += str(rand)
return num
def generateAKeys():
(publicKey, privateKey) = rsa.newkeys(1024)
with open('keys/APubKey.pem', 'wb') as p:
p.write(publicKey.save_pkcs1('PEM'))
with open('keys/APrivKey.pem', 'wb') as p:
p.write(privateKey.save_pkcs1('PEM'))
def generateBKeys():
(publicKey, privateKey) = rsa.newkeys(1024)
with open('keys/BPubKey.pem', 'wb') as p:
p.write(publicKey.save_pkcs1('PEM'))
with open('keys/BPrivKey.pem', 'wb') as p:
p.write(privateKey.save_pkcs1('PEM'))
def generateCKeys():
(publicKey, privateKey) = rsa.newkeys(1024)
with open('keys/CPubKey.pem', 'wb') as p:
p.write(publicKey.save_pkcs1('PEM'))
with open('keys/CPrivKey.pem', 'wb') as p:
p.write(privateKey.save_pkcs1('PEM'))
def generateSKeys():
(publicKey, privateKey) = rsa.newkeys(1024)
with open('keys/SPubKey.pem', 'wb') as p:
p.write(publicKey.save_pkcs1('PEM'))
with open('keys/SPrivKey.pem', 'wb') as p:
p.write(privateKey.save_pkcs1('PEM'))
def loadKeys():
with open('keys/SPubKey.pem', 'rb') as p:
SPubKey = rsa.PublicKey.load_pkcs1(p.read())
with open('keys/SPrivKey.pem', 'rb') as p:
SPrivKey = rsa.PrivateKey.load_pkcs1(p.read())
with open('keys/APubKey.pem', 'rb') as p:
APubKey = rsa.PublicKey.load_pkcs1(p.read())
with open('keys/APrivKey.pem', 'rb') as p:
APrivKey = rsa.PrivateKey.load_pkcs1(p.read())
with open('keys/BPubKey.pem', 'rb') as p:
BPubKey = rsa.PublicKey.load_pkcs1(p.read())
with open('keys/BPrivKey.pem', 'rb') as p:
BPrivKey = rsa.PrivateKey.load_pkcs1(p.read())
with open('keys/CPubKey.pem', 'rb') as p:
CPubKey = rsa.PublicKey.load_pkcs1(p.read())
with open('keys/CPrivKey.pem', 'rb') as p:
CPrivKey = rsa.PrivateKey.load_pkcs1(p.read())
return SPubKey, SPrivKey, APubKey, APrivKey, BPubKey, BPrivKey, CPubKey, CPrivKey
def encrypt(message, key):
return rsa.encrypt(message.encode('utf8'), key)
def decrypt(ciphertext, key):
try:
return rsa.decrypt(ciphertext, key).decode('utf8')
except:
return False
def sign(message, key):
return rsa.sign(message.encode('utf8'), key, 'SHA-1')
def verify(message, signature, key):
try:
return rsa.verify(message.encode('utf8'), signature, key,) == 'SHA-1'
except:
return False
def incoming_connections():
while True:
client, addr = SERVER.accept()
print(f'A client has connected {addr}')
# client.send(WELCOME_MSG.encode())
Thread(target=single_client, args=(client,)).start()
print('Client connected')
def single_client(client):
client_name = client.recv(BUFFERSIZE).decode()
#client_name = 'Anonymous'
welcome_msg = f'Welcome {client_name}.\nType exit() or press CTRL+D or CTRL+C to exit.\n'
client.send(welcome_msg.encode())
chat_msg = f'{client_name} has joined the room'
broadcast_msg(chat_msg.encode())
clients[client] = client_name
serverToClientAuth(client) #Begin Authentication process upon reciving client
while True:
msg = client.recv(BUFFERSIZE)
if msg == 'online()'.encode('utf8'):
real_clients_num, real_clients_name = get_clients()
client.send(f'Online users {real_clients_num} : {real_clients_name}'.encode('utf8'))
elif msg == EXIT_CMD.encode('utf8'):
print(f'{clients[client]} has disconnected ')
client.send('You are leaving the room...'.encode())
client.close()
client_leaving = clients[client]
del clients[client]
broadcast_msg(f'{client_leaving} has left the room!'.encode())
break
elif '#'.encode('utf8') in msg:
unicast_msg(msg, client)
else:
broadcast_msg(msg, clients[client] + ': ')
def get_clients():
real_clients_num = 0
real_clients_name = []
for k,v in clients.items():
if v != 'Anonymous':
real_clients_num += 1
real_clients_name.append(v)
return real_clients_num, real_clients_name
def broadcast_msg(msg, name=""):
for client in clients:
client.send(name.encode() + msg)
def unicast_msg(msg, client):
# Get only name by removing #
msg = msg.decode('utf8')
refered_client, client_msg = msg.split(' ',1)
client_to_connect = refered_client.strip('#')
for k,v in clients.items():
if v == client_to_connect:
k.send(f'{clients[client]} -> {client_to_connect}: {client_msg}'.encode('utf8'))
def receive_msg():
while True:
try:
msg = client_socket.recv(BUFFERSIZE).decode("utf8")
print(msg)
except OSError as error:
return error
def serverToClientAuth(client):
Ka=bytes('1', 'utf8')
Kb=bytes('2', 'utf8')
Kc=3
user = clients[client] #A, B or C
message1 = client.recv(1024) #Nonce Na, Nb or Nc
NEnc, sig1 = message1[:128], message1[128:]
N = decrypt(NEnc, SPrivKey)
if verify(N, sig1, APubKey):
Ns = nonceGenerator() #Servers Nonce
NNs = "{}|{}".format(N, Ns)
NNsEnc = encrypt(NNs, APubKey)
sig2 = sign(NNs, SPrivKey)
message2 = NNsEnc + sig2
client.send(message2)
message3 = client.recv(1024)
NsXX = decrypt(message3, SPrivKey)
print(NsXX)
NsXX = NsXX.split("|")
if NsXX[0] == Ns: #Does the Nonce that client returned match what was sent?
if NsXX[1] == 'B' and NsXX[2] == 'C':
message4 = Ka + Kb
client.send(message4)
print("Client " + user + " has been authenticated to the server\n")
elif NsXX[1] == 'A' and NsXX[2] == 'C':
message4 = "{}|{}".format(Ka, Kc)
client.send(message4.encode('utf8'))
print("Client " + user + " has been authenticated to the server\n")
elif NsXX[1] == 'A' and NsXX[2] == 'B':
message4 = "{}|{}".format(Ka, Kb)
client.send(message4.encode('utf8'))
print("Client " + user + " has been authenticated to the server\n")
else:
print("Unrecognised identifier")
else:
print("Replied nonce from Client does not match")
else:
print('The message signature could not be verified')
if __name__ == "__main__":
clients = {}
generateAKeys()
generateBKeys()
generateCKeys()
generateSKeys()
SPubKey, SPrivKey, APubKey, APrivKey, BPubKey, BPrivKey, CPubKey, CPrivKey = loadKeys()
HOST = '127.0.0.1'
PORT = 5000
BUFFERSIZE = 1024
ADDR = (HOST, PORT)
EXIT_CMD = "exit()"
SERVER = socket(AF_INET, SOCK_STREAM)
SERVER.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
SERVER.bind(ADDR)
SERVER.listen(2)
print("Waiting for connection...")
ACCEPT_THREAD = Thread(target=incoming_connections)
ACCEPT_THREAD.start()
ACCEPT_THREAD.join()
SERVER.close()
The server file ^^^
#Client A
from socket import AF_INET, socket, SOCK_STREAM
from threading import Thread
from signal import signal, SIGINT
import sys
import os
import random
import rsa
def nonceGenerator():
num = ""
for i in range(5):
rand = random.randint(0,1)
num += str(rand)
return num
def loadKeys():
with open('keys/APubKey.pem', 'rb') as p:
APubKey = rsa.PublicKey.load_pkcs1(p.read())
with open('keys/APrivKey.pem', 'rb') as p:
APrivKey = rsa.PrivateKey.load_pkcs1(p.read())
with open('keys/SPubKey.pem', 'rb') as p:
SPubKey = rsa.PublicKey.load_pkcs1(p.read())
return APubKey, APrivKey, SPubKey
def encrypt(message, key):
return rsa.encrypt(message.encode('utf8'), key)
def decrypt(ciphertext, key):
try:
return rsa.decrypt(ciphertext, key).decode('utf8')
except:
return False
def sign(message, key):
return rsa.sign(message.encode('utf8'), key, 'SHA-1')
def verify(message, signature, key):
try:
return rsa.verify(message.encode('utf8'), signature, key,) == 'SHA-1'
except:
return False
def receive_msg():
while True:
try:
msg = client_socket.recv(BUFFERSIZE).decode("utf8")
print(msg)
except OSError as error:
return error
def keyBoard_Input():
while True:
try:
msg = input()
if msg != 'exit()':
client_socket.send(msg.encode('utf8'))
else:
clean_exit()
except EOFError:
clean_exit()
def send_msg(data):
try:
msg = data
if msg != 'exit()':
client_socket.send(msg.encode('utf8'))
else:
clean_exit()
except EOFError:
clean_exit()
def clean_exit():
client_socket.send('exit()'.encode('utf8'))
client_socket.close()
sys.exit(0)
def handler(signal_received, frame):
clean_exit()
def serverToClientAuth(client):
Na = nonceGenerator()
NaEnc = encrypt(Na, SPubKey)
sig1 = sign(Na, APrivKey)
message1 = NaEnc + sig1
client_socket.send(message1)
message2 = client_socket.recv(1024)
NaNsEnc, sig2 = message2[:128], message2[128:]
NaNs = decrypt(NaNsEnc, APrivKey)
if verify(NaNs, sig2, SPubKey):
NaNs = NaNs.split("|")
if NaNs[0] == Na:
Ns = NaNs[1]
print(Ns)
NsBC = "{}|{}|{}".format(Ns, 'B', 'C')
NsBCEnc = encrypt(NsBC, SPubKey) #No signature needed anymore
message3 = NsBCEnc
client_socket.send(message3)
print('Client gets stuick here')
message4 = client_socket.recv(1024)
print(message4)
message4 = message4.split("|")
APubKey, CPubKey = message3[0], message3[1]
print("Client B is Authenticated to the Server")
print("Ka = " + APubKey)
print("Kc = " + CPubKey)
else:
print("Replied nonce from server does not match")
else:
print('The message signature could not be verified')
if __name__ == '__main__':
signal(SIGINT, handler)
HOST = '127.0.0.1'
PORT = 5000
BUFFERSIZE = 1024
ADDR = (HOST, PORT)
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(ADDR)
receive_thread = Thread(target=receive_msg)
receive_thread.start()
APubKey, APrivKey, SPubKey = loadKeys()
send_msg('A') #Assign Client ID at the moment the connection is initiated
serverToClientAuth(client_socket)
keyBoard_Input()
Client File ^^^^
Waiting for connection...
A client has connected ('127.0.0.1', 51407)
Client connected
01001|B|C
Client A has been authenticated to the server
Server response ^^^
Welcome A.
Type exit() or press CTRL+D or CTRL+C to exit.
01001
Client gets stuick here
12
Client Response ^^^
The '12' displayed here should be a '1|2' as that is the message sent by the server. However, it seems that the receive_msg function is actually taking the message instead of the function, causing the function to hang and wait for a message.

how to retrieve file from ftp server using scapy ??

I am trying to get the file through FTP protocol using scapy from the specified destination but it is failing even though i am able to create a connection and login to FTP server but file is not retrieved.
'''
! /usr/bin/python2.7
usage: sudo python2.7 client.py [ftp-server-ip]
username and password is currently hardcoded
'''
from scapy.all import *
from random import randint
import sys
class FTPClinet:
def __init__(self, dst):
self.sport = random.randint(1024, 65535)
# self.src = src
self.dst = "90.130.70.73"
self.next_seq = 1000
self.next_ack = 0
self.basic_pkt = IP(src="127.0.0.1",dst=self.dst)/TCP(sport=self.sport, dport=21)
self.tcp_flags = {
'TCP_FIN': 0x01,
'TCP_SYN': 0x02,
'TCP_RST': 0x04,
'TCP_PSH': 0x08,
'TCP_ACK': 0x10,
'TCP_URG': 0x20,
'TCP_ECE': 0x40,
'TCP_CWR': 0x80
}
def send_syn(self):
synack = None
ip = IP(dst=self.dst)
syn = TCP(sport=self.sport, dport=21, flags='S', seq=self.next_seq, ack=self.next_ack)
while not synack:
synack = sr1(ip/syn, timeout=1)
self.next_seq = synack[TCP].ack
return synack
def send_ack(self, pkt):
l = 0
ip = IP(dst=self.dst)
self.next_ack = pkt[TCP].seq + self.get_next_ack(pkt)
ack = TCP(sport=self.sport, dport=21, flags='A', seq=self.next_seq, ack=self.next_ack)
send(ip/ack)
def get_next_ack(self, pkt):
total_len = pkt.getlayer(IP).len
ip_hdr_len = pkt.getlayer(IP).ihl * 32 / 8
tcp_hdr_len = pkt.getlayer(TCP).dataofs * 32 / 8
ans = total_len - ip_hdr_len - tcp_hdr_len
return (ans if ans else 1)
def handshake(self):
synack = self.send_syn()
self.send_ack(synack)
print "sniff called"
sniff(timeout=4, lfilter=self.sniff_filter, prn=self.manage_resp)
print "Handshake complete"
def get_file(self, user, passwd, filen):
user = "USER " + user + '\r\n'
passwd = "PASS " + passwd + '\r\n'
filen = "RETR " +filen + '\r\n'
cwd = "PASV" + '\r\n'
pkt = self.basic_pkt
pkt[TCP].flags = 'AP'
pkt[TCP].seq = self.next_seq
pkt[TCP].ack = self.next_ack
ftp_user = pkt/user
self.send_pkt(ftp_user)
print "userid sent"
pkt[TCP].seq = self.next_seq
pkt[TCP].ack = self.next_ack
ftp_pass = pkt/passwd
self.send_pkt(ftp_pass)
print "password sent"
pkt[TCP].sport = pkt[TCP].sport - 1
pkt[TCP].dport = 20
pkt[TCP].seq = self.next_seq
pkt[TCP].ack = self.next_ack
ftp_filen = pkt/filen
self.send_pkt(ftp_filen)
print "retrieved file"
def sniff_filter(self, pkt):
return pkt.haslayer(IP) and pkt[IP].src==self.dst and pkt.haslayer(TCP) and pkt[TCP].dport == self.sport and pkt[TCP].sport == 21
def manage_resp(self, pkt):
print pkt.show()
if (pkt[TCP].flags == 16L):
self.next_seq = pkt[TCP].ack
elif (pkt[TCP].flags & self.tcp_flags['TCP_ACK']):
self.next_seq = pkt[TCP].ack
self.send_ack(pkt)
elif Raw in pkt:
print "raw packet khamar"
print pkt[Raw]
send_ack(pkt)
else:
print 'Unknown'
print pkt.show()
send_ack(pkt)
def send_p(self,pkt=None):
if pkt:
sr1(pkt)
sniff(timeout=4, lfilter=self.sniff_filter, prn=self.manage_resp)
return
def send_pkt(self, pkt=None):
if pkt:
send(pkt)
sniff(timeout=4, lfilter=self.sniff_filter, prn=self.manage_resp)
return
def close(self):
resp = None
pkt = self.basic_pkt
pkt[TCP].flags = 'FA'
pkt[TCP].seq = self.next_seq
pkt[TCP].ack = self.next_ack
print pkt.show()
while not resp:
resp = sr1(pkt, timeout=4)
# self.send_ack(resp)
self.send_pkt(resp)
h = FTPClinet(sys.argv[1])
h.handshake()
h.get_file("anonymous","","1KB.zip")
h.close()

Python Multi-threaded socket listener error with threads not releasing

I have 500+ units in the world that connects to my server and dump their data. Up to now i have been using a PHP script to act as a socket listener, but I need to go multi-threaded as the load is increasing and PHP can not keep up. I am quite new to Python and decided to use it for my new platform, over the past few days i have struggled and tried many examples to no avail. Through my search i came across some questions trying to answer this problem, but none did. I will attach my code.
The problem : as the units connect to the server and the server accepts it, the server creates a new thread to handle the connection, the problem comes when the unit drops the connection the thread stays open and active and the total thread count grows, and this is linked to the system limit : "number of open files", i can increase this limit but this only make it a time bomb , it does not solve this.
Please help.
#! /usr/bin/python
import multiprocessing
import socket
import sys
import pprint
import datetime
import MySQLdb
import time
import datetime
import re
import select
import resource
import threading
max_connections = 1024
max_connections_set = max_connections
resource.setrlimit(resource.RLIMIT_NOFILE, (max_connections_set, max_connections_set))
#the incomming port
the_global_port = xxxx #(any port)
#display id
the_global_id = "UNIT TYPE"
class ConnectionObject(object):
the_id = None
the_socket = None
the_socket_address = None
the_socket_address_ip = None
the_socket_address_port = None
the_server = None
the_process = None
the_process_id = None
the_process_name = None
the_imei = None
identifier = ""
# The class "constructor" - It's actually an initializer
def __init__(self, in_process_nr, in_process , in_socket , in_socket_address, in_server):
self.the_id = in_process_nr
self.the_process = in_process
self.the_process_id = self.the_process.exitcode
self.the_process_name = self.the_process.name
self.the_socket = in_socket
self.the_socket_address = in_socket_address
self.the_socket_address_ip = self.the_socket_address[0]
self.the_socket_address_port = self.the_socket_address[1]
self.the_server = in_server
self.identifier = str(self.the_id) + " " + str(self.the_process_name) + " " + str(self.the_socket_address_ip) + " " + str(self.the_socket_address_port) + " "
#end def init
#end def class
def processData(the_connection_object , the_data):
def mysql_open_connection_inside():
try:
the_conn = MySQLdb.connect(host= "127.0.0.1",
user="user",
passwd="password",
db="mydb")
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
time.sleep(30)
try:
the_conn = MySQLdb.connect(host= "127.0.0.1",
user="user",
passwd="password",
db="mydb")
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
print "Unexpected error:", sys.exc_info()[0]
raise
sys.exit(0)
#end time 2
#end try except
return the_conn
#end def mysql_open_connection
conn = mysql_open_connection_inside()
x = conn.cursor()
add_rawdata = ("INSERT INTO RawData"
"(ID,RawData,Type) "
"VALUES (%s, %s, %s)")
data_raw = ('123456', 'ABCD','')
records_inserted = 0
the_connection_object.the_imei = ""
#global clients
imei = ""
try:
thedata = ""
thedata = " ".join("{:02x}".format(ord(c)) for c in the_data)
record_to_save = ' '.join(thedata)
seqtoreply = ""
seqtoreply = "OK"
#reply part
if (seqtoreply != ""): #reply to unit
try:
the_connection_object.the_socket.sendall(seqtoreply)
#echoout(the_connection_object.identifier+"We Replyed With : " + seqtoreply)
except:
echoout(the_connection_object.identifier+"Send Reply Error : " + str(sys.exc_info()[1]))
#end except
#end of if
the_id = "some generated id"
data_raw = (the_id, werk_data, 'UNIT')
try:
x.execute(add_rawdata, data_raw)
conn.commit()
echoout(the_connection_object.identifier+"Raw Data Saved.")
except:
conn.rollback()
echoout(the_connection_object.identifier+" Raw Data NOT Saved : " + str(sys.exc_info()[1]))
#end of data save insert
#echoout("=============================")
endme = 1
echoout("")
conn.close()
#end try
except:
conn.close()
echoout(the_connection_object.identifier+"Error : " + str(sys.exc_info()[1]))
#end try except
#end def handel function
def handle_p(processnr, server, connection, address):
this_connection = ConnectionObject(processnr,multiprocessing.current_process(), connection, address, server)
thisprocess = multiprocessing.current_process()
this_connection.the_id = ""
the_address = this_connection.the_socket_address_ip
the_port = this_connection.the_socket_address_port
try:
echoout("New connection from : "+str(the_address)+" on port "+str(the_port))
close_the_socket = False
while True:
#--------------------- recive part -------------------------------------------------
data = connection.recv(512)
thedata = ""
thedata = " ".join("{:02x}".format(ord(c)) for c in data)
if ((thedata == "") or (thedata == " ") or (data == False)):
echoout("Socket Closed Remotely : No Data")
close_the_socket = True
break
#end - if data blank
else :
processData(this_connection, data)
#end there is data
echoout("=============================")
#end if while true
#end try
except:
print "handling request, Error : " + str(sys.exc_info()[1])
close_the_socket = True
connection.close()
finally:
close_the_socket = True
echoout("Closing socket")
connection.close()
#end try finally
#end def handel function
def mysql_update(update_statement, update_values):
conn_update = MySQLdb.connect(host= "127.0.0.1",
user="user",
passwd="password",
db="mydb")
x_update = conn_update.cursor(MySQLdb.cursors.DictCursor)
rawdata_data = (update_statement)
data_rawdata = (update_values)
allupdateok = False
#end if there is more
try:
x_update.execute(rawdata_data, data_rawdata)
conn_update.commit()
allupdateok = True
conn_update.close()
except:
conn_update.rollback()
allupdateok = False
conn_update.close()
print "Unexpected error:", sys.exc_info()[0]
raise
#end of data save insert
if (allupdateok == False):
echoout("Update Raw Data Table Error")
#end if update
return allupdateok
#end def mysqlupdate
def echoout(thestring):
datestring = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if (thestring != ""):
outstring = datestring + " " + thestring
print outstring
else :
outstring = thestring
print outstring
#end - def echoout
class Server(object):
threads = []
all_threads = []
high_proc = ""
def __init__(self, hostname, port):
self.hostname = hostname
self.port = port
def start(self):
echoout("Listening for conncetions")
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind((self.hostname, self.port))
self.socket.listen(10)
process_number = 1
inputs = [self.socket]
while True:
inready, outready, excready = select.select(inputs, [], [], 30);
for s in inready:
if s == self.socket:
conn, address = self.socket.accept()
high_processname = ""
echoout("Got a connection...")
process = threading.Thread(target=handle_p, args=(process_number,self, conn, address))
high_processname = process.name
self.high_proc = high_processname
process.daemon = True
process.start()
self.all_threads.append((process,conn))
ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
self.threads.append((process_number,conn,st,0,process))
process_number = process_number + 1
print "ACTIVE Threads = " + str(threading.activeCount())
the_total_count = 0
dead_count = 0
alive_count = 0
for the_thread in self.all_threads :
if (the_thread[0].is_alive() == True):
alive_count = alive_count + 1
else :
dead_count = dead_count + 1
the_thread[1].close()
the_thread[0].join(0.3)
self.all_threads.pop(the_total_count)
#end if alive else
the_total_count = the_total_count + 1
#end for threads
print "LIVE Threads = " + str(alive_count)
print "DEAD Threads = " + str(dead_count)
print "TOTAL Threads = " + str(the_total_count)
print ""
#end if s = socke, new connection
#end for loop
#end while truw
self.socket.close()
#end def start
#main process part
if __name__ == "__main__":
start_ip = "0.0.0.0"
start_port = the_global_port
#start server
server = Server(start_ip, start_port)
try:
print "Listening on " , start_port
server.start()
except:
print "unexpected, Error : " + str(sys.exc_info()[1])
finally:
print "shutting down"
active_clients = 0
for process in multiprocessing.active_children():
try:
active_clients = active_clients + 1
process.terminate()
#process.join()
except:
print "Process not killed = " + str(sys.exc_info()[1])
#end try except
#close mysql connection
print "Active clients = " + str(active_clients)
#end try finally
server.socket.close()
server.threads = []
server = None
print "All done."
#end def main
First of all, it is silly to use threads when you can have 500+ connected clients, you should go asynchronous - look at gevent for example for
a very good library, or at least use select (see Python documentation).
Then, your code to close the socket in handle_p looks good, indeed when
the recv() call comes back with an empty string it means the remote
end is disconnected so you break the while, fine.
However, it looks like the remote closed the connection but it is not
detected on your side (recv() doesn't return). The best would be
then to have a kind of heartbeat to know when you can close the
connection.

Python: How is this error being generated and how can I fix it?

I'm working on a simple server based guessing game. Part of the client side of things is that there is an ssl secured admin client that can access the server to request information. I am currently trying to add the certificates and stuff to the requests however when running the (admittedly incomplete) file I get a 'ValueError: file descriptor cannot be a negative integer (-1)' at line 65 of the following code:
import select
import socket
import ssl
import random
def CreateGame():
number = random.randrange(1,21,1)
##print(number)
return number
def Greetings():
member.send("Greetings\r\n".encode())
def Far():
member.send("Far\r\n".encode())
def Close():
member.send("Close\r\n".encode())
def Correct():
member.send("Correct\r\n".encode())
def AdminGreetings():
member.send("Admin-Greetings\r\n".encode())
def Who():
responce = ""
for connection in clientList:
if connection != member:
responce += str(clientList[connection])
member.send((str(responce)).encode())
member.close()
reader_list.remove(member)
del clientList[member]
def GameLogic(mNumber):
if("Guess: " + str(mNumber) + "\r\n" == guess):
Correct()
elif(("Guess: " + str(mNumber-3) + "\r\n" == guess) or
("Guess: " + str(mNumber-2) + "\r\n" == guess) or
("Guess: " + str(mNumber-1) + "\r\n" == guess) or
("Guess: " + str(mNumber+1) + "\r\n" == guess) or
("Guess: " + str(mNumber+2) + "\r\n" == guess) or
("Guess: " + str(mNumber+3) + "\r\n" == guess) ):
Close()
else:
Far()
#client socket
s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s1.bind(('',4000))
s1.listen(5)
#admin socket
s2 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s2.bind(('',4001))
s2.listen(5)
reader_list = [s1,s2]
clientList = {}
mNumber = CreateGame()
while True:
(read,write,error) = select.select(reader_list,[],[])
for member in read:
if member == s1:
(read,write) = s1.accept()
reader_list.append(read)
elif member == s2:
(read,write) = s2.accept()
reader_list.append(read)
sslSocket = ssl.wrap_socket(member,
keyfile="5cc515_server.key",
certfile="5cc515_server.crt",
server_side = True,
cert_reqs = ssl.CERT_REQUIRED,
ca_certs="5cc515_root_ca.crt")
else:
try:
message = member.recv(4092).decode()
sockAddr = member.getsockname()
if(message == "Hello\r\n"):
addr = str(sockAddr[0]) + " " + str(sockAddr[1]) + "\r\n"
clientList[member] = addr
if (sockAddr[1] == 4001):#is using port 4000
try:
ssl_s = ssl.wrap_socket(member,
keyfile="5cc515_server.key",
certfile="5cc515_server.crt",
server_side = True,
cert_reqs = ssl.CERT_REQUIRED,
ca_certs="5cc515_root_ca.crt")
##handshake stuff
AdminGreetings()
except:
break
else:
Greetings()
elif(message == "Who\r\n"):
##handshake stuff
Who()
else:
##print("try and assign guess")
guess = message
##print("game logic")
GameLogic(mNumber)
except:
print("recv failed")
member.close()
reader_list.remove(member)
del clientList[member]
break
I understand that without the crt and key this cant really be debugged, but since nothing is making changes to the reader_list[] i dont see why it goes from 2 to -ve...
anyway here is the other part (the admin client)
import socket
import select
import ssl
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
handshake = False
# send Hello
try:
while handshake == False:
print("create ssl socket")
sslSocket = ssl.wrap_socket(s,
keyfile="100297626.key",
certfile="100297626.crt",
server_side = False,
ca_certs="5cc515_root_ca.crt")
print("connect")
sslSocket.connect(("127.0.0.1", 4001))
print("send hello")
sslSocket.write("Hello\r\n".encode())
print("rec hello")
sslSocket.recv(80).decode()
sslSocket.send("Who\r\n".encode())
print(sslSocket.recv(4092).decode())
except:
print("Server Unavailable")
s.close()
Thanks in advance!
As line 65 is:
(read,write,error) = select.select(reader_list,[],[])
One must infer that the error comes from passing a socket with a fd of -1 to select.select in its read_list. Please run your code again but include the check that:
assert all(s.fileno() != -1 for s in reader_list)

Packet sniffer in python using pcapy impacket

I'm trying to create a packet sniffer using pcapy and impacket. I'm stuck with data extraction phase. Unfortunately impacket is not properly documented. At least i could n't find one. Could anyone tel me where to find the documentation or what functions i could use to extract data from captured packet?
edit
my current code
import datetime
import pcapy
import sys
from impacket.ImpactPacket import *
from impacket.ImpactDecoder import *
def main(argv):
dev='ppp0'
print "Sniffing device " + dev
cap = pcapy.open_live(dev , 65536 , 1 , 0)
while(1) :
try:
(header, packet) = cap.next()
eth= LinuxSLLDecoder().decode(packet)
ip=eth.child() #internet layer
trans=ip.child()#transport layer
try:
print 'protocol=',
if ip.get_ip_p() == UDP.protocol:
print 'UDP'
if ip.get_ip_p() == TCP.protocol:
print 'TCP','port=',trans.get_th_dport()
print trans.child()
if ip.get_ip_p() == ICMP.protocol:
print 'ICMP'
print 'src=',ip.get_ip_src(),'dest=',ip.get_ip_dst()
print ''
except:
pass
except pcapy.PcapError:
continue
if __name__ == "__main__":
main(sys.argv)
Sample Output
src= xxx.xxx.xxx.xx dest= xx.xxx.xx.xx
protocol= TCP port= 443
1703 0300 2400 0000 0000 0000 07e2 a2a5 ....$...........
09fe 5b15 3cf1 803d 0c83 8ada 082e 8269 ..[.<..=.......i
0007 8b33 7d6b 5c1a 01 ...3}k\..
What i want to do is extract more data, For example extract the url (if there is a url in packet)
Here is an example for a syn-port scanner with pcap and python and impacket.
Maybe you can tak the important parts out of it.
'''
synscan.py ...
see scan.py for parameters
this works extremely well an a windows that likes to communicate
scanning hosts in same ethernet is possible
scanning host not within the same ethernet may success but does not need to
many algorithms were tried
- raw socket support needs higher previleges
and is impossible because windows does not allow to sniff with them
or to submit sniffable packets
-> not implemented here
"Why do you need special libraries for TCP-SYN scans?"
thats why.
using pcap the program is devided into phases
usually it succeeds in phase 1.
phase 0:
add targets and phase 1
phase 1+: (parallel)
send arp request to resolve target
bombard it with the right packets
sniff
phase 2:
send out udp to resolve mac address by sniffing
send out raw socket tcp syn requests (need higher previleges) optional
phase 3:
if not yet succeeded in phase 1: = mac not found
bombard all macs with packets
phase 4:
bombard broadcasting [mac ff:ff:ff:ff:ff:ff] with packets
phase 5:
clean up - no use
use DEBUG_PHASE to show phases
currently only ipv4 is supported
'''
import sys
import time
import thread
import pcap # pcapy
import impacket
import random
import impacket.ImpactDecoder as ImpactDecoder
import impacket.ImpactPacket as ImpactPacket
import array
import scan
from scan import *
DEFAULT_SOCKET_TIMEOUT = 20
NOTIFY_TIMEOUT = 2
# argument incdeces for socket.socket(...)
SOCK_INIT_FAMILY = 0
SOCK_INIT_TYPE = 1
SOCK_INIT_PROTO = 2
STATE_STATE = 1
STATE_TIME = 0
PCAP_ARGS = ()
PCAP_KW = dict(promisc = True, timeout_ms = 0)
DEBUG = False
DEBUG_IFACE = False and DEBUG # put out which devices are set up
DEBUG_IP = False and DEBUG # print ip debug output for ip packets v4
DEBUG_ARP = False and DEBUG # send arp communication debug out
DEBUG_SYN = False and DEBUG # print out the syn requests sent
DEBUG_PACKET = False and DEBUG # packet inspection as seen by scanner
DEBUG_PHASE = True and DEBUG # scanner phases - 5
DEBUG_STATE = False and DEBUG # debug output about the state
DEBUG_PHASE2 = False and DEBUG # debug output about what is sent in phase 2
# you need higher previleges for some of these operations
ETHER_BROADCAST = (0xff,) * 6 # mac ff:ff:ff:ff:ff:ff
# --- Conversions --------------------------------------------------------------
def ip_tuple(ip):
'''Decode an IP address [0.0.0.0] to a tuple of bytes'''
return tuple(map(int, ip.split('.')))
def tuple_ip(ip):
'''Encode a a tuple of bytes to an IP address [0.0.0.0]'''
return '.'.join(map(str, (ip[0], ip[1], ip[2], ip[3])))
# --- Packet Creation --------------------------------------------------------------
def generate_empty_arp_request():
# build ethernet frame
eth = ImpactPacket.Ethernet()
eth.set_ether_type(0x0806) # this is an ARP packet
eth.set_ether_dhost(ETHER_BROADCAST)# destination host (broadcast)
# build ARP packet
arp = ImpactPacket.ARP()
arp.set_ar_hrd(1)
arp.set_ar_hln(6) # ethernet address length = 6
arp.set_ar_pln(4) # ip address length = 4
arp.set_ar_pro(0x800) # protocol: ip
arp.set_ar_op(1) # opcode: request
arp.set_ar_tha(ETHER_BROADCAST) # target hardware address (broadcast)
eth.contains(arp)
return eth, arp
def generate_empty_ip_packet():
eth = ImpactPacket.Ethernet()
#### values to be set:
# type, shost, dhost
eth.set_ether_type(0x800)
ip = ImpactPacket.IP()
#### values to be set:
# version, IHL, TOS, total_length, ID, Flags, Fragment offset,
# TTL, Protocol, Checksum, source_addr, destination_addr, options
ip.set_ip_v(4)
ip.set_ip_hl(5) # 5 * 32 bit
ip.set_ip_tos(0) # usal packet -> type of service = 0
# total_length
ip.set_ip_id(random.randint(1, 0xffff))
ip.set_ip_df(0) # flags redundant
ip.set_ip_off(0)
ip.set_ip_ttl(250)
ip.set_ip_p(6) # tcp = 6
eth.contains(ip)
return eth, ip
# --- Scanner --------------------------------------------------------------
def start_scan(timeout):
'''return a scanner object
'''
# mac addresses are used to send ethernet packages
mac_addresses = {} # ip : set([mac])
# threadsave access to the targets
targets_lock = thread.allocate_lock()
targets = [] # (family, (ip, port, ...))
# list of target names
target_hosts = set() # host ips
def is_target(host):
return host in target_hosts
def add_target(family, address):
target_hosts.add(address[IP])
mac_addresses.setdefault(address[IP], set())
with targets_lock:
targets.append((family, address))
def store_ip_mac_resolution_for(host):
for family, socktype, proto, canonname, address in \
socket.getaddrinfo(host, 0):
mac_addresses.setdefault(address[IP], set())
def associate_ip_mac(ip, mac):
if ip in mac_addresses or is_target(ip):
if type(mac) is list:
hashable_array_constructor = ('B', ''.join(map(chr, mac)))
else:
hashable_array_constructor = (mac.typecode, mac.tostring())
mac_addresses[ip].add(hashable_array_constructor)
def get_macs(host):
macs = set()
empty_set = set()
for family, socktype, proto, canonname, (ip, port) in \
socket.getaddrinfo(host, 0):
macs.update(mac_addresses.get(ip, empty_set))
return [array.array(*mac) for mac in macs]
def get_local_macs():
macs = set()
for ip in get_host_ips():
for mac in get_macs(ip):
macs.add((ip, tuple(mac.tolist())))
return macs
def ip_known(ip):
return bool(mac_addresses.get(ip, False))
def save_ip_mac_resolution(ether, ip_header):
source_ip = ip_header.get_ip_src()
source_mac = ether.get_ether_shost()
associate_ip_mac(source_ip, source_mac)
destination_ip = ip_header.get_ip_dst()
destination_mac = ether.get_ether_dhost()
associate_ip_mac(destination_ip, destination_mac)
## parse data directly from pcap
def find_connection_response(data):
# Parse the Ethernet packet
decoder = ImpactDecoder.EthDecoder()
find_connection_response_ethernet(decoder.decode(data))
def find_connection_response_ethernet(ether):
eth_type = ether.get_ether_type()
if eth_type == 0x800:
# Received an IP-packet (2048)
# Parse the IP packet inside the Ethernet packet
find_connection_response_ip(ether, ether.child())
elif eth_type == 0x0806:
store_mac_of_target(ether)
## arp response handling
def store_mac_of_target(ether):
arp = ether.child()
if arp.get_ar_op() in (2, ):
if DEBUG_ARP:print 'response'
# Received ARP Response
source_mac_addr = arp.get_ar_sha()
source_ip_addr = tuple_ip(arp.get_ar_spa())
destination_mac_addr = arp.get_ar_tha()
destination_ip_addr = tuple_ip(arp.get_ar_tpa())
if DEBUG_ARP:print source_mac_addr, source_ip_addr, destination_mac_addr, destination_ip_addr
if is_target(destination_ip_addr):
if DEBUG_ARP:print 'intersting:', destination_ip_addr, destination_mac_addr
associate_ip_mac(destination_ip_addr, destination_mac_addr)
if is_target(source_ip_addr):
if DEBUG_ARP:print 'intersting:', source_ip_addr, source_mac_addr
associate_ip_mac(source_ip_addr, source_mac_addr)
## tcp syn-ack response handling
def find_connection_response_ip(ether, ip_header):
save_ip_mac_resolution(ether, ip_header)
if ip_header.get_ip_p() == 0x6:
# Received a TCP-packet
# Parse the TCP packet inside the IP packet
if DEBUG_IP > 2:
print 'received ip packet: %s to %s' % (ip_header.get_ip_src(), \
ip_header.get_ip_dst())
source_ip = ip_header.get_ip_src()
destination_ip = ip_header.get_ip_dst()
if not is_target(source_ip):
return
if DEBUG_IP > 1:print 'found interest in: %s' % ip_header.get_ip_src()
find_connection_response_tcp(ip_header, ip_header.child())
def find_connection_response_tcp(ip_header, tcp_header):
# Only process SYN-ACK packets
source_ip = ip_header.get_ip_src()
source_port = tcp_header.get_th_sport()
destination_ip = ip_header.get_ip_dst()
destination_port = tcp_header.get_th_sport()
print targets
if tcp_header.get_SYN() and tcp_header.get_ACK():
# Get the source and destination IP addresses
# Print the results
if DEBUG_IP: print("Connection attempt %s:(%s) <- %s:%s" % \
(source_ip, source_port, \
destination_ip, destination_port))
if source_ip in target_hosts:
put_port(source_port)
elif tcp_header.get_SYN() and not tcp_header.get_ACK() and source_ip in get_host_ips():
# someone sent a syn request along
# asuming the acknoledge will come here, too
target = (socket.AF_INET, (destination_ip, destination_port))
if DEBUG_IP: print("Connection attempt %s:(%s) --> %s:%s" % \
(source_ip, source_port, \
destination_ip, destination_port))
with targets_lock:
try:
targets.remove(target)
except ValueError:
pass
def put_port(port):
sys.stdout.write(str(port) + '\n')
## syn packet sending
def send_syn(family, addr):
if family == socket.AF_INET:
send_syn_ipv4(addr)
elif family == socket.AF_INET6:
pass
else:
sys.stderr.write('Warning: in send_syn: family %s not supported\n' \
% family)
def send_syn_ipv4(address):
for packet in iter_syn_packets(address):
if DEBUG_PACKET:
print 'packet', id(packet)
send_packet(packet)
def iter_syn_packets(address):
for tcp in iter_tcp_packets(address):
for eth, ip in iter_eth_packets(address):
ip.contains(tcp)
packet = eth.get_packet()
yield packet
def get_host_ips():
return socket.gethostbyname_ex(socket.gethostname())[2]
def iter_eth_packets((target_ip, port)):
eth, ip = generate_empty_ip_packet()
for source_ip in get_host_ips():
ip.set_ip_src(source_ip)
ip.set_ip_dst(target_ip)
for source_mac in get_macs(source_ip):
eth.set_ether_shost(source_mac)
for target_mac in get_macs(target_ip):
eth.set_ether_dhost(target_mac)
yield eth, ip
def get_devices():
return scanning.values()
def iter_tcp_packets((_, target_port)):
tcp = ImpactPacket.TCP()
#### values to set:
# source port, destination port, sequence number, window, flags
source_port = random.randint(2048, 0xffff)
tcp.set_th_sport(source_port)
tcp.set_th_dport(target_port)
tcp.set_th_seq(random.randint(1, 0x7fffffff))
tcp.set_th_win(32768) # window -> discovered this as default
tcp.set_SYN()
yield tcp
# waiting and scanner interaction
keep_running = [1] # True
def wait():
if keep_running:
keep_running.pop() # keep_running = False
while scanning:
time.sleep(0.01)
## raw_input()
def add_scan((socketargs, addr)):
ip = addr[IP]
port = addr[PORT]
family = socketargs[SOCK_INIT_FAMILY]
if ip_known(ip):
send_syn(family, addr)
else:
add_target(family, addr)
notify(family, addr)
notified = {}
def notify(family, addr):
now = time.time()
if family == socket.AF_INET:
ip = addr[IP]
if notified.get(ip, 0) < now - NOTIFY_TIMEOUT:
notified[ip] = now
send_who_is_ipv4(ip)
elif family == socket.AF_INET6:
pass
else:
raise ValueError('unknown protocol family type %i' % family)
scanning_lock = thread.allocate_lock()
scanning = {} # device_name : device
def send_who_is_ipv4(target_ip):
eth, arp = generate_empty_arp_request()
arp.set_ar_tpa(ip_tuple(target_ip)) # target protocol address
for ip, mac in get_local_macs():
arp.set_ar_spa(ip_tuple(ip)) # source protocol address
arp.set_ar_sha(mac) # source hardware address
eth.set_ether_shost(mac) # source hardware address
if DEBUG_ARP: print 'send_who_is_ipv4: %s%s -> %s' % (ip, mac, target_ip)
send_packet(eth.get_packet())
def send_packet(packet):
t = -time.time()
for device in get_devices():
if DEBUG_PACKET:print device, repr(packet)
device.sendpacket(packet)
t -= time.time() - 0.002
if t > 0:
time.sleep(t)
def scan(device_name, device):
if DEBUG_IFACE: print 'dev up: %s' % device_name
with scanning_lock:
if device_name in scanning:
return
scanning[device_name] = device
try:
while device_name in scanning:
time, data = next(device)
find_connection_response(str(data))
finally:
with scanning_lock:
scanning.pop(device_name, None )
if DEBUG_IFACE: print 'dev down: %s' % device_name
def start_scans():
for device_name in pcap.findalldevs():
start_scan(device_name)
start_scan(pcap.lookupdev())
def start_scan(device_name):
device = pcap.pcap(device_name, *PCAP_ARGS, **PCAP_KW)
thread.start_new(scan, (device_name, device))
def notify_loop():
targets_lock.acquire()
while targets or phase:
targets_lock.release()
try:
do_notify()
except:
traceback.print_exc()
# iterate over scanner phases
try:
phases[0]()
except:
traceback.print_exc()
targets_lock.acquire()
targets_lock.release()
def get_state():
return len(targets)
last_state = [time.time(), get_state()]
def state_has_not_changed_for(timeout):
now = time.time()
state = get_state()
if state != last_state[STATE_STATE]:
last_state[STATE_TIME] = now
last_state[STATE_STATE] = state
if DEBUG_STATE: print 'state old:', last_state[STATE_TIME] + timeout < now
return last_state[STATE_TIME] + timeout < now
def reset_state():
now = time.time()
state = get_state()
last_state[STATE_TIME] = now
last_state[STATE_STATE] = state
target_save = [] # needed between phase 3 and 4
phases = []
phase = phases.append
#phase
def do_scanner_phase():
# wait for wait()
if keep_running: return
if DEBUG_PHASE: print 'initiated phase 1 = waiting'
reset_state()
phases.pop(0)
if not targets:
give_up()
#phase
def do_scanner_phase():
# wait to timeout without exiting wait
# send ip packets to the host to enable
if not state_has_not_changed_for(timeout): return
if DEBUG_PHASE: print 'initiated phase 2 = send packets'
send_packets_to_addresses_to_sniff_mac()
reset_state()
phases.pop(0)
if not targets:
give_up()
#phase
def do_scanner_phase():
# wait to timeout without exiting wait
# set all ip hosts to have all mac addresses
if not state_has_not_changed_for(timeout): return
if DEBUG_PHASE: print 'initiated phase 3 = send to all'
target_save.extend(targets[:])
associate_all_ip_with_all_mac_addresses()
reset_state()
phases.pop(0)
if not targets:
give_up()
#phase
def do_scanner_phase():
# wait to timeout without exiting wait
# start broadcasting instead of using real mac address
if not state_has_not_changed_for(timeout): return
if DEBUG_PHASE: print 'initiated phase 4 = broadcast'
if add_broadcast_to_all_mac_addresses():
with targets_lock:
targets.extend(target_save)
reset_state()
give_up()
#phase
def do_scanner_phase():
# wait to timeout without exiting wait
# give up
if not state_has_not_changed_for(timeout): return
if DEBUG_PHASE: print 'initiated phase 5 = give up'
for device_name in scanning.keys():
scanning.pop(device_name)
reset_state()
phases.insert(0, phases.pop(-1))
#phase
def do_scanner_phase():
pass
def give_up():
phases.insert(0, phases.pop(-2))
def send_packets_to_addresses_to_sniff_mac():
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for host in target_hosts:
send_udp(udp_sock, host)
try:
raw_sock = socket.socket(socket.AF_INET, socket.SOCK_RAW)
except:
sys.stderr.write('higher previleges needed to perform raw socket packet send\n')
return
for target in targets:
send_raw(raw_sock, target)
def send_raw(raw_sock, (family, addr)):
if family == socket.AF_INET:
send_raw_ipv4(raw_sock, addr)
elif family == socket.AF_INET6:
pass # todo: ipv6
else:
raise ValueError('invalid family %s' % (family,))
def send_raw_ipv4(raw_sock, addr):
for tcp in iter_tcp_packets(addr):
if DEBUG_PHASE2: print 'sending tcp raw', repr(tcp.get_packet()), addr
try:
raw_sock.sendto(tcp.get_packet(), addr)
except ():
pass
def send_udp(s, host):
# send an udp packet to sniff mac address
try:
s.sendto(':)', (host, random.randint(0, 0xffff)))
except socket_error as e:
if DEBUG_PHASE2: print 'failed: send to %r %s' % (host, e)
else:
if DEBUG_PHASE2: print 'succeded: send to %r' % (host,)
s.close()
def associate_all_ip_with_all_mac_addresses():
macs = set()
for mac in mac_addresses.values():
macs.update(mac)
for mac in mac_addresses.values():
mac.update(macs)
if DEBUG_PHASE: print 'macs:', [mac for mac in macs]
def add_broadcast_to_all_mac_addresses():
updated_mac = False
BC = ('B', ETHER_BROADCAST)
for mac in mac_addresses.values():
updated_mac = updated_mac or not BC in mac
mac.add(('B', ETHER_BROADCAST))
return updated_mac
def do_notify():
t = time.time()
notified = set()
for target in targets[:]:
ip = target[1][IP]
if ip in notified:
continue
if DEBUG_SYN:
print 'nofifying %s' % ip,
if ip_known(ip):
if DEBUG_SYN:print 'send_syn', target[PORT]
send_syn(*target)
targets.remove(target)
else:
if DEBUG_SYN:print 'notify'
notify(*target)
notified.add(ip)
t -= time.time() - NOTIFY_TIMEOUT
if t > 0:
time.sleep(t)
def start_notify_loop():
thread.start_new(notify_loop, ())
store_ip_mac_resolution_for(socket.gethostname())
start_scans()
start_notify_loop()
return obj(wait = wait, add_scan = add_scan)
def main():
host, ports, timeout = parseArgs(DEFAULT_SOCKET_TIMEOUT)
scanner = start_scan(timeout)
for connection in connections(host, ports):
scanner.add_scan(connection)
scanner.wait()
if __name__ == '__main__':
main()
I ran into similar problem. I guess when there is no documentation, the best documentation is the source code! And with python we are lucky to have source code most of the time. Anyway, I would suggest looking into ImpactDecoder.py and ImpactPacket.py. First one give some insights as far as how packets get decoded and second gives information on actual packets as a class and their methods. For instance, ImpactPacket.py and class PacketBuffer has following methods that you were probably looking for::
def set_bytes_from_string(self, data):
"Sets the value of the packet buffer from the string 'data'"
self.__bytes = array.array('B', data)
def get_buffer_as_string(self):
"Returns the packet buffer as a string object"
return self.__bytes.tostring()
def get_bytes(self):
"Returns the packet buffer as an array"
return self.__bytes
def set_bytes(self, bytes):
"Set the packet buffer from an array"
# Make a copy to be safe
self.__bytes = array.array('B', bytes.tolist())
def set_byte(self, index, value):
"Set byte at 'index' to 'value'"
index = self.__validate_index(index, 1)
self.__bytes[index] = value
def get_byte(self, index):
"Return byte at 'index'"
index = self.__validate_index(index, 1)
return self.__bytes[index]
def set_word(self, index, value, order = '!'):
"Set 2-byte word at 'index' to 'value'. See struct module's documentation to understand the meaning of 'order'."
index = self.__validate_index(index, 2)
ary = array.array("B", struct.pack(order + 'H', value))
if -2 == index:
self.__bytes[index:] = ary
else:
self.__bytes[index:index+2] = ary
def get_word(self, index, order = '!'):
"Return 2-byte word at 'index'. See struct module's documentation to understand the meaning of 'order'."
index = self.__validate_index(index, 2)
if -2 == index:
bytes = self.__bytes[index:]
else:
bytes = self.__bytes[index:index+2]
(value,) = struct.unpack(order + 'H', bytes.tostring())
return value
def set_long(self, index, value, order = '!'):
"Set 4-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."
index = self.__validate_index(index, 4)
ary = array.array("B", struct.pack(order + 'L', value))
if -4 == index:
self.__bytes[index:] = ary
else:
self.__bytes[index:index+4] = ary
def get_long(self, index, order = '!'):
"Return 4-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."
index = self.__validate_index(index, 4)
if -4 == index:
bytes = self.__bytes[index:]
else:
bytes = self.__bytes[index:index+4]
(value,) = struct.unpack(order + 'L', bytes.tostring())
return value
def set_long_long(self, index, value, order = '!'):
"Set 8-byte 'value' at 'index'. See struct module's documentation to understand the meaning of 'order'."
index = self.__validate_index(index, 8)
ary = array.array("B", struct.pack(order + 'Q', value))
if -8 == index:
self.__bytes[index:] = ary
else:
self.__bytes[index:index+8] = ary
def get_long_long(self, index, order = '!'):
"Return 8-byte value at 'index'. See struct module's documentation to understand the meaning of 'order'."
index = self.__validate_index(index, 8)
if -8 == index:
bytes = self.__bytes[index:]
else:
bytes = self.__bytes[index:index+8]
(value,) = struct.unpack(order + 'Q', bytes.tostring())
return value
def get_ip_address(self, index):
"Return 4-byte value at 'index' as an IP string"
index = self.__validate_index(index, 4)
if -4 == index:
bytes = self.__bytes[index:]
else:
bytes = self.__bytes[index:index+4]
return socket.inet_ntoa(bytes.tostring())
def set_ip_address(self, index, ip_string):
"Set 4-byte value at 'index' from 'ip_string'"
index = self.__validate_index(index, 4)
raw = socket.inet_aton(ip_string)
(b1,b2,b3,b4) = struct.unpack("BBBB", raw)
self.set_byte(index, b1)
self.set_byte(index + 1, b2)
self.set_byte(index + 2, b3)
self.set_byte(index + 3, b4)
The other super useful class from ImpactPacket.py is ProtocolLayer, that gives us following methods::
def child(self):
"Return the child of this protocol layer"
return self.__child
def parent(self):
"Return the parent of this protocol layer"
return self.__parent
So, basically impacket uses matreshka doll approach, and you can go to any layer you want using child and parent methods and use any methods of the PacketBuffer class on any layer. Pretty cool, huh? Furthermore, particular layers (or packets) have their specific methods but you would have to go dig ImpactPacket.py and ImpactDecoder.py if you want to find more about those.
Good luck and cheers mate!
Here is a sample code written in Python with working pcapy. This might be of help for many.
'''
Packet sniffer in python using the pcapy python library
Project website
http://oss.coresecurity.com/projects/pcapy.html
'''
import socket
from struct import *
import datetime
import pcapy
import sys
import socket
def main(argv):
#list all devices
devices = pcapy.findalldevs()
print devices
errbuf = ""
#ask user to enter device name to sniff
print "Available devices are :"
for d in devices :
print d
dev = raw_input("Enter device name to sniff : ")
print "Sniffing device " + dev
'''
open device
# Arguments here are:
# device
# snaplen (maximum number of bytes to capture _per_packet_)
# promiscious mode (1 for true)
# timeout (in milliseconds)
'''
socket.setdefaulttimeout(2)
s = socket.socket();
#s.settimeout(100);
#dev = 'eth0'
cap = pcapy.open_live(dev , 65536 , 1 , 1000)
#start sniffing packets
while(1) :
(header, packet) = cap.next()
#print ('%s: captured %d bytes, truncated to %d bytes' %(datetime.datetime.now(), header.getlen(), header.getcaplen()))
parse_packet(packet)
#start sniffing packets
#while(1) :
#print ('%s: captured %d bytes, truncated to %d bytes' %(datetime.datetime.now(), header.getlen(), header.getcaplen()))
#Convert a string of 6 characters of ethernet address into a dash separated hex string
def eth_addr (a) :
b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
return b
#function to parse a packet
def parse_packet(packet) :
#parse ethernet header
eth_length = 14
eth_header = packet[:eth_length]
eth = unpack('!6s6sH' , eth_header)
eth_protocol = socket.ntohs(eth[2])
print 'Destination MAC : ' + eth_addr(packet[0:6]) + ' Source MAC : ' + eth_addr(packet[6:12]) + ' Protocol : ' + str(eth_protocol)
#Parse IP packets, IP Protocol number = 8
if eth_protocol == 8 :
#Parse IP header
#take first 20 characters for the ip header
ip_header = packet[eth_length:20+eth_length]
#now unpack them :)
iph = unpack('!BBHHHBBH4s4s' , ip_header)
version_ihl = iph[0]
version = version_ihl >> 4
ihl = version_ihl & 0xF
iph_length = ihl * 4
ttl = iph[5]
protocol = iph[6]
s_addr = socket.inet_ntoa(iph[8]);
d_addr = socket.inet_ntoa(iph[9]);
print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr)
#TCP protocol
if protocol == 6 :
t = iph_length + eth_length
tcp_header = packet[t:t+20]
#now unpack them :)
tcph = unpack('!HHLLBBHHH' , tcp_header)
source_port = tcph[0]
dest_port = tcph[1]
sequence = tcph[2]
acknowledgement = tcph[3]
doff_reserved = tcph[4]
tcph_length = doff_reserved >> 4
print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Sequence Number : ' + str(sequence) + ' Acknowledgement : ' + str(acknowledgement) + ' TCP header length : ' + str(tcph_length)
h_size = eth_length + iph_length + tcph_length * 4
data_size = len(packet) - h_size
#get data from the packet
data = packet[h_size:]
#print 'Data : ' + data
#ICMP Packets
elif protocol == 1 :
u = iph_length + eth_length
icmph_length = 4
icmp_header = packet[u:u+4]
#now unpack them :)
icmph = unpack('!BBH' , icmp_header)
icmp_type = icmph[0]
code = icmph[1]
checksum = icmph[2]
print 'Type : ' + str(icmp_type) + ' Code : ' + str(code) + ' Checksum : ' + str(checksum)
h_size = eth_length + iph_length + icmph_length
data_size = len(packet) - h_size
#get data from the packet
data = packet[h_size:]
#print 'Data : ' + data
#UDP packets
elif protocol == 17 :
u = iph_length + eth_length
udph_length = 8
udp_header = packet[u:u+8]
#now unpack them :)
udph = unpack('!HHHH' , udp_header)
source_port = udph[0]
dest_port = udph[1]
length = udph[2]
checksum = udph[3]
print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Length : ' + str(length) + ' Checksum : ' + str(checksum)
h_size = eth_length + iph_length + udph_length
data_size = len(packet) - h_size
#get data from the packet
data = packet[h_size:]
#print 'Data : ' + data
#some other IP packet like IGMP
else :
print 'Protocol other than TCP/UDP/ICMP'
print
if __name__ == "__main__":
main(sys.argv)

Categories