I am attempting to complete a challenge that states:
We've noticed that the aliens are sending messages between their ships, we think they're using XOR to encrypt the messages, and we've intercepted a key.
Set up a server listening on ("localhost", 10000) to intercept one of the alien messages. When you do perform a bitwise XOR on the message with the key "attackthehumans" and then respond with the encrypted data.
Tip: Read the response to get the flag.
After some research, I was able to come up with the following code. However, when I run it in the challenge's code editor, the only feedback I receive is "Error trying to connect to your server and recieving message back."
import socket
# Function to xor strings
def xor_string(string):
key = "attackthehumans"
bit_key = ''.join(format(ord(i), 'b') for i in key)
bit_data = ''.join(format(ord(i), 'b') for i in string)
xor_string = str(0)
for i in range(len(bit_key)):
if bit_data[i] == bit_key[i]:
xor_string = xor_string + str(0)
else:
xor_string = xor_string + str(1)
return xor_string
# Sets up server on localhost and port 10000
print("Setting up server...")
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 10000))
print("Server set up. Listening for connections...")
server.listen()
conn, addr = server.accept()
print("Connected by: {}".format(addr))
# Once connection is established, server receives data, XOR's it, sends it back, and
# waits for response to get the flag.
with conn:
print("Receiving data from connection... ")
data = conn.recv()
data = data.decode()
print("Data received: {}".format(data.decode()))
xor_data = xor_string(data)
conn.sendall(xor_data.encode())
response = conn.recv()
response = response.decode()
print(response)
I am not sure what I'm doing wrong. I can't figure out if it's the socket or the xor_string function. Any help would be appreciated.
This should be enough to do your XORing:
def xor_string(string):
key = b"attackthehumans"
key = key * (len(string)//len(key)+1)
res = bytes([k^s for (k,s) in zip(key,string)])
return res
Then your main code becomes:
print("Receiving data from connection... ")
data = conn.recv()
print("Data received:", data)
xor_data = xor_string(data)
conn.sendall(xor_data)
print(conn.recv())
Related
I am have an issue regarding a python assignment I was doing and would like to ask the community for some guidance. I am to use the socket module and argparse modules only for this assignment. I have created a socketserver.py file and a socketclient.py file. The connection between the server and client is fine. Now the purpose of the assignment is that the client is to send the Lottery game type, # of tickets, and # of lines per tickets using argparse. E.g. syntax for socketclient.py would be python3 -t Lotto_Max -n 2 -l 2. The output for the ticket game, ticket type and number of lines per ticket show up correctly on the server. However, they sometimes don't show correctly on the client, and am really stuck at the moment. Here is my following code....
Server Code
```socketserver.py code```
import socket
from random import sample
def main():
host = input("Please specify an IP address for this server's socket\t")
port = int(input('Please speciy a port number above 1024 for this socket.\t'))
kulmiye = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
kulmiye.bind((host, port))
except socket.error as egeh:
print('Socket bind failed. Error Code : ' + str(egeh[0]) + ' Message ' + egeh[1])
print('Socket bind accomplished...\n')
print("Listening for an incoming connection...")
kulmiye.listen()
conn, addr = kulmiye.accept()
print('Connected with ' + addr[0] + ':' + str(addr[1]))
while True:
server_data = conn.recv(1024).decode("utf-8")
game_data = server_data.split(",")
if not server_data:
break
if game_data[0] == "Lotto_Max":
nval = int(game_data[1])
lval = int(game_data[2])
for nval in range(nval):
for i in range(lval):
numbers = sample(range(1, 50), 7)
numbers.sort()
sortedd = str(numbers)
print(sortedd)
print("--------------------")
conn.sendall(sortedd.encode("utf-8"))
#conn.sendall(bytes(str(numbers),'utf-8'))
liners = "-----------------------"
conn.sendall(liners.encode("utf-8"))
print("From Client: " + str(game_data))
conn.sendall(b'goodbye')
# server_data = input('#\t')
break
else:
conn.close()
if __name__ == '__main__':
main()
Client Code
```socketclient.py code```
import socket
import argparse
def client():
host = input("Please specify the server's IP you want to connect to\t")
port = int(input("Please specify the server's port you want to connect to\t"))
kulmiye = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
kulmiye.connect((host, port))
# client_data = input("#\t")
# while True:
# client_data = input()
# if client_data == 'quit':
# kulmiye.close()
# sys.exit()
# if len(str.encode(client_data)) > 0:
# kulmiye.sendall(str.encode(client_data))
# server_response = str(kulmiye.recv(1024), "utf-8")
# print(server_response, end = " ")
kulmiye.sendall(bytes(tvar.encode("utf-8")))
kulmiye.sendall(bytes(','.encode("utf-8")))
kulmiye.sendall(bytes(str(nval).encode("utf-8")))
kulmiye.sendall(bytes(','.encode("utf-8")))
kulmiye.sendall(bytes(str(lval).encode("utf-8")))
server_data = kulmiye.recv(1024).decode("utf-8")
while server_data != 'goodbye':
server_data = kulmiye.recv(1024).decode("utf-8")
print('Server: \n' + server_data)
# client_data = input("#\t")
if not server_data:
break
kulmiye.close()
# this code block serves to give the user the ability to play lotto max
# with the amount of tickets and lines per ticket they would like
# Using the argparse module to allow the user to input command-line interfaces
parser = argparse.ArgumentParser(description='Welcome to OLG Gaming.')
parser.add_argument(
'-t',
type=str,
help="Pick the lottery you want to play",
required=True)
parser.add_argument(
'-n',
type=int,
help="Pick the amount of lottery tickets you want to play",
required=True)
parser.add_argument(
'-l',
type=int,
help="Pick the amount of lines you would like to play",
required=True)
# parser.add_argument('-o', type = str, help = "This is optional", required = False)
# parse_args will convert the argument strings into objects and will get
# stored in the cmdargs variable
cmdargs = parser.parse_args()
tvar = cmdargs.t # the t string argument that gets parsed into an object will get stored into a variable called tvar
# the n integer argument that gets parsed into an object will get stored
# into a variable called nval
nval = int(cmdargs.n)
# the l integer argument that gets parsed into an object will get stored
# into a variable called lval
lval = int(cmdargs.l)
if __name__ == "__main__":
client()
```code```
Server
python3 socketserver.py
specify localhost as IP
specify a port e.g. 4444
Client
python3 socketclient.py -t Lotto_Max -n 1 -l 1
specify an IP address to connect to the server (e.g. localhost or 127.0.0.1)
specify a port to connect to e.g. 4444
When the connection establishes between client and server, the server receives the client input and prints it on its end the gametype (Lotto_Max), number of tickets and lines per ticket
Server will output the resultse.g.
However, the client won't receive it indefinitely. Usually it'll get it about 25% of the time, and I am not sure why
One problem is here in the server:
server_data = conn.recv(1024).decode("utf-8")
conn.recv(1024) can receive any number of bytes from 0 (closed connection) to 1024. The line above assumes the whole message is received every time, but when it fails it only gets part of the message. Below I've modified your code so the server can process multiple client connections one at a time, and the client will connect/disconnect over and over again to hasten the failure:
Server:
import socket
from random import sample
def main():
host = ''
port = 4444
kulmiye = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
kulmiye.bind((host, port))
print('Socket bind accomplished...\n')
print("Listening for an incoming connection...")
kulmiye.listen()
while True:
conn, addr = kulmiye.accept()
print('Connected with ' + addr[0] + ':' + str(addr[1]))
with conn:
server_data = conn.recv(1024).decode("utf-8")
print(f'server_data={server_data}')
game_data = server_data.split(",")
print("From Client: " + str(game_data))
if server_data:
if game_data[0] == "Lotto_Max":
nval = int(game_data[1])
lval = int(game_data[2])
for nval in range(nval):
for i in range(lval):
numbers = sample(range(1, 50), 7)
numbers.sort()
sortedd = str(numbers)
print(sortedd)
print("--------------------")
conn.sendall(sortedd.encode("utf-8"))
liners = "-----------------------"
conn.sendall(liners.encode("utf-8"))
conn.sendall(b'goodbye')
if __name__ == '__main__':
main()
Client:
import socket
import argparse
def client():
host = 'localhost'
port = 4444
kulmiye = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
kulmiye.connect((host, port))
kulmiye.sendall(bytes(tvar.encode("utf-8")))
kulmiye.sendall(bytes(','.encode("utf-8")))
kulmiye.sendall(bytes(str(nval).encode("utf-8")))
kulmiye.sendall(bytes(','.encode("utf-8")))
kulmiye.sendall(bytes(str(lval).encode("utf-8")))
server_data = kulmiye.recv(1024).decode("utf-8")
while server_data != 'goodbye':
server_data = kulmiye.recv(1024).decode("utf-8")
print('Server: \n' + server_data)
# client_data = input("#\t")
if not server_data:
break
kulmiye.close()
tvar = 'Lotto_Max'
nval = 1
lval = 1
if __name__ == "__main__":
while True:
client()
Here's the result after 100s of successful connections. Note server_data between the successful and unsuccessful connection:
Connected with 127.0.0.1:12175
server_data=Lotto_Max,1,1
From Client: ['Lotto_Max', '1', '1']
[4, 7, 9, 12, 24, 31, 48]
--------------------
Connected with 127.0.0.1:12176
server_data=Lotto_Max,1,
From Client: ['Lotto_Max', '1', '']
Traceback (most recent call last):
File "C:\server.py", line 38, in <module>
main()
File "C:\server.py", line 24, in main
lval = int(game_data[2])
ValueError: invalid literal for int() with base 10: ''
conn.recv(1024) didn't receive the complete message (didn't get the final 1). TCP is a byte streaming protocol with no concept of message boundaries. You're code is responsible to call recv() and buffer the data until you have a complete message. You could send fixed-sized messages and call recv until you have that many bytes, terminate a message with a sentinel byte such as a newline(\n) and read until the sentinel is received, or send the size of the message first followed by the message bytes.
I won't solve it for you since it is an assignment, but as a hint socket.makefile can wrap the socket in a file-like object where you can call .read(n) to read exactly n bytes from a socket, or .readline() to read a \n-terminated line.
Here's a link to an answer of mine that demonstrates this: https://stackoverflow.com/a/55840026/235698
Another example of the streaming nature of TCP is on the client side. Sometimes, it prints:
-----------------------
Server:
goodbye
Server:
-----------------------goodbye
Server:
Server:
-----------------------
Server:
goodbye
The separate lines in the server:
conn.sendall(liners.encode("utf-8"))
conn.sendall(b'goodbye')
Sometimes get received by the single recv in the client:
server_data = kulmiye.recv(1024).decode("utf-8")
Again, this is due to the streaming nature of TCP and no message boundaries. If you sent each line terminated by a newline, you could call recv() a number of times until a newline was detected, then process just that line.
Another answer that illustrates this technique is here: https://stackoverflow.com/a/55186805/235698.
Thank you Mark Tolonen for your guidance. I still need to brush up how to handle TCP data stream. Nevertheless, I was able to achieve more desirable results using numerous
conn.sendall within my nested for loop. Happy camper!
I'm trying to make a server-client program, where server will listen to client's messages and depends on the message, will response. I send a message from client with username and content, server accept it and print a message to sending to client Till here is everything fine. But when it comes to sending a message server will throw and error:
`TypeError: byte indices must be integers or slices, not str`
It looks like this line is the problem, but I'm not sure....
`clientsocket.send(msg['header'] + msg['data'])`
here is a whole server code. Please let me know, if client code is necessary too please.
import socket
import time
import pickle
import select
HEADERSIZE = 10
IP = "127.0.0.1"
PORT = 1234
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((IP, PORT))
s.listen()
sockets_list = [s]
clients = {}
# Handles message receiving
def receive_message(clientsocket):
try:
message_header = clientsocket.recv(HEADERSIZE)
if not len(message_header):
return False
message_length = int(message_header.decode('utf-8').strip())
return {'header': message_header, 'data': clientsocket.recv(message_length)}
except:
return False
while True:
read_sockets, _, exception_socket = select.select(sockets_list, [], sockets_list)
for notified_socket in read_sockets:
if notified_socket == s:
clientsocket, address = s.accept()
user = receive_message(clientsocket)
if user is False:
continue
sockets_list.append(clientsocket)
clients[clientsocket] = user
print(f"Connection from {address[0]}:{address[1]} has been estabilished! User:{user['data'].decode('utf-8')}")
else:
message = receive_message(notified_socket)
if message is False:
print(f"Close connection from {clients[notified_socket]['data'].decode('utf-8')}")
sockets_list.remove(notified_socket)
del clients[notified_socket]
continue
user = clients[notified_socket]
#message_decoded = message['data'].decode('utf-8')
print(f'Received message from {user["data"].decode("utf-8")}: {message["data"].decode("utf-8")}')
for clientsocket in clients:
if clientsocket == notified_socket:
if message["data"].decode("utf-8") == "y":
#d = {1: "Hey", 2: "there"}
msg = pickle.dumps("th.jpeg")
print(msg)
msg = bytes(f'{len(msg):<{HEADERSIZE}}', "utf-8") + msg
clientsocket.send(msg['header'] + msg['data'])
else:
d = {1: "Hey", 2: "there"}
msg = pickle.dumps(d)
print(msg)
# msg = bytes(f'{len(msg):<{HEADERSIZE}}', "utf-8") + msg
clientsocket.send(msg['header'] + msg['data'])
for notified_socket in exception_socket:
sockets_list.remove(notified_socket)
del clients[notified_socket]
HERE is a whole error code:
Connection from 127.0.0.1:48480 has been estabilished! User:j
Received message from j: y
b'\x80\x03X\x07\x00\x00\x00th.jpegq\x00.'
Traceback (most recent call last):
File "server.py", line 69, in <module>
clientsocket.send(msg['header'] + msg['data'])
TypeError: byte indices must be integers or slices, not str
As You can see, it works till sending the message line
msg = pickle.dumps("th.jpeg") will encode the string "th.jpeg" as a bytes-object.
msg = bytes(f'{len(msg):<{HEADERSIZE}}', "utf-8") + msg just adds that bytes object to another bytes-object.
So msg is a simple bytes-object, not any kind of server packet or similar. Therefor it is not possible to subscribe msg with msg['header'] or any other string.
Your code seems a little weird but maybe just try this line:
clientsocket.send(msg)
Since you are already converting msg to a bytes-object, it can be sent to the client directly. You just have to decode it properly in the client.
my raspberry pi is the server and Im trying to send continuous message from rpi to android while recieving a command from client (android app),i really dont know if this is possible and how to do it is out of my reach and it is not a feedback message here is my code hope you will help me thank you.
import apptopi
from socket import *
from time import ctime
from nanpy import (ArduinoApi, SerialManager)
apptopi.setup()
connection = SerialManager()
a = ArduinoApi(connection = connection)
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
add = 0
add += 1
a = str(add) //**this is a sample that i want to send continously
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(0)
tcpSerSock.send(str.encode(a)) <== i really don't know how to send
continuously
while True:
print 'Waiting for connection'
tcpCliSock,addr = tcpSerSock.accept()
print '...connected from :', addr
try:
while True:
data = ''
data = tcpCliSock.recv(BUFSIZE)
if not data:
break
if data == ctrCmd[0]:
apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
apptopi.back()
print 'backward'
if data == ctrCmd[2]:
apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
apptopi.stp()
print 'stop'
except KeyboardInterrupt:
apptopi.close()
GPIO.cleanup()
tcpSerSock.close();
OK one approach is to use the select() function for this. There is information in the documentation about its operation.
As an example I've made a modified version of your program (see below). I don't have a raspberry pi, so that part of the code is commented out, but you can replace it as needed.
The example uses the timeout feature of select() to send "continuous" messages to clients whilst also monitoring them for incoming messages. You can adjust the message contents and timeout to whatever works for you. NB you may also need to respond to client messages, as this code only sends data to clients after a timeout. Make whatever changes you need.
import sys
import socket
import select
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(1)
print 'Waiting for connection'
sendInterval = 1.0 # interval(sec) for sending messages to connected clients
rxset = [tcpSerSock]
txset = []
while 1:
rxfds, txfds, exfds = select.select(rxset, txset, rxset, sendInterval)
if rxfds:
for sock in rxfds:
if sock is tcpSerSock:
# a client is connecting
tcpCliSock, addr = tcpSerSock.accept()
tcpCliSock.setblocking(0)
rxset.append(tcpCliSock)
print '...connected from :', addr
else:
# a client socket has data or has closed the connection
try:
data = sock.recv(BUFSIZE)
if not data:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
if data == ctrCmd[0]:
#apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
#apptopi.back()
print 'backward'
if data == ctrCmd[2]:
#apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
#apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
#apptopi.stp()
print 'stop'
except:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
# timeout - send data to any active client
for sock in rxset:
if sock is not tcpSerSock:
sock.send("Hello!\n")
The simple client program I used to test this is here:
import sys
import socket
import time
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = '127.0.0.1'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpCliSock.connect(ADDR)
time.sleep(1)
for i in range(len(ctrCmd)):
tcpCliSock.send(ctrCmd[i])
time.sleep(1)
data = tcpCliSock.recv(BUFSIZE)
print data
tcpCliSock.close()
Hope this helps, best of luck.
Hello I've been trying to make my python sock server connection counter to go down
but I can't figure out how I can do this
def client_thread(conn):
while True:
conn.send("Command: ")
data = conn.recv(1024)
if not data:
break
reply = "" + data
conn.sendall("\r")
if data == "!* Connections":
conn.sendall("[+] Clients Connected: %s \r\n" % (clients))
conn.close()
while True:
conn, addr = sock.accept()
clients = clients + 1
start_new_thread(client_thread, (conn,))
sock.close()
I needn't show you all of the code because its irrelevant to this issue,
I have provided the code that make's the counter go up when a new connection connects, but as said before I don't know how to make it go down when a connection leaves.
When trying to find solutions online there show's nothing that can help my issue
Here is a small sample how to realize a client counter with the select.select function. I actually took it from the great article select – Wait for I/O Efficiently on pymotw.com and added a client counter. Basically you look for readable sockets and try to receive data from them. If a socket returns nothing it means it has been closed and can be removed from the client list.
import queue
import socket
import select
clients = 0
sock = socket.socket()
sock.bind(('localhost', 5000))
sock.listen(5)
inputs = [sock]
outputs = []
msg_queues = {}
while inputs:
readable, writable, exceptional = select.select(
inputs, outputs, msg_queues)
for s in readable:
if s is sock:
conn, addr = sock.accept()
print('new connection from ', addr)
conn.setblocking(0)
inputs.append(conn)
msg_queues[conn] = queue.Queue()
# increment client counter
clients += 1
print('Clients: ', clients)
else:
# try to receive some data
data = s.recv(1024)
if data:
# if data available print it
print('Received {} from {}'.format(data, s.getpeername()))
msg_queues[s].put(data)
# add output channel for response
if s not in outputs:
outputs.append(s)
else:
# empty data will be interpreted as closed connection
print('Closing connection to ', s.getpeername())
# stop listening for input on the connection
if s in outputs:
outputs.remove(s)
# remove from inputs
inputs.remove(s)
s.close()
# decrement client counter
clients -= 1
del msg_queues[s]
print('Clients: ', clients)
Hi i'm trying to send multiple messages to the tcp server but in my client i got an error that data is referenced before assignment. If i send one message there will be no error but if i try to send more than one it returns the error.
tcp server:
class Connect(object):
def __init__(self):
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print('socket cannot be created')
server_address = ('169.254.34.240', 10000)
#print('starting up: ' + server_address)
self.sock.bind(server_address)
self.sock.listen(1)
def listen(self):
while True:
connection, client_address = self.sock.accept()
print('client connected')
try:
data = connection.recv(16)
print(data)
if data == "STATUS":
connection.sendall("vision=ready")
elif data == "MEASURE":
connection.sendall("vision=computing")
elif data == "GET_RESULT":
connection.sendall("x=1.5,y=0.25,z=0.14,a=0.15")
else:
connection.sendall("wrong command")
finally:
connection.close()
def main():
connect = Connect()
connect.listen()
if __name__=='__main__':
main()
my tcp client which is sending messages:
class Connect(object):
def __init__(self):
# Create a TCP/IP socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port on the server given by the caller
print('connecting to host')
self.sock.connect(('169.254.34.240',10000))
def send(self, command):
try:
message = command
print('sending: ' + message)
self.sock.sendall(message)
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = self.sock.recv(16)
amount_received += len(data)
print('received: ' + data)
finally:
self.sock.close()
return data
def main():
connect = Connect()
print connect.send("STATUS")
print connect.send("MEASURE")
if __name__=='__main__':
main()
so anyone an idea, i suppose i don't end correctly or something, i thought it had something to do about my while in the client?
The problem is that you are calling self.sock.close() after each request without creating a new socket. You will need to create a new socket after each time you close it.
You can solve this by creating a connection per request as follows:
class Connect(object):
def connect(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('connecting to host')
sock.connect(('127.0.0.1',10000))
return sock
def send(self, command):
sock = self.connect()
recv_data = ""
data = True
print('sending: ' + command)
sock.sendall(command)
while data:
data = sock.recv(1024)
recv_data += data
print('received: ' + data)
sock.close()
return recv_data
def main():
connect = Connect()
print connect.send("STATUS")
print connect.send("MEASURE")
Providing full stack trace would help, pointing to exact line, where is the problem present. Learn reading these stack traces, they look boring, but provide valuable information like source file and line where it comes from.
Reading your code I suspect, that it fails at finally block, where you return data.
data will not have assigned value in case, the while amount_received < amount_expected would not allow even the first round in the loop or if withing that loop would happen an exception on the line self.sock.recv(16).
Btw.: you are assuming, that length of response will be the same as length of request, but your server does not provide responses with such length.