This pull request adds the ability to support multiple simultaneous clients. Detailed development notes are available in #14.
Changelist
Creation of a common data-frame that is used to transfer information between client and server.
Communication chain was modified
Clients now send initial notification to server to request stager, which includes the client's configuration options.
Server now receives and interprets client options from client, instead of them being hard coded.
All clients now need to store their own ID, pipename, and desired architecture.
Client ID value must be unique for each client.
Server now utilizes a queue to handle new clients, and each session with new a client will now spawn a new thread on the server.
The server now respects the block time independently for each client, as that is now handled within the client's thread.
The server can now support multiple clients simultaneously.
A new timer is created on the server to specify how often it should poll for new clients.
Server now has a new class Beacon used to track the state of each session.
New functions send_server_notification() and check_for_new_clients() added to the base skeleton of transports
Detailed changes
For my own accounting purposes, and for the sanity of anyone else trying to work with this, the below section basically contains a more thorough and detailed breakdown of the changes mentioned in the overview above. This section is probably redundant, and likely only relevant if you intend on modifying the code. Readers seeking additional reference are encouraged to see #14.
Base logic modifications
A number of changes were added to the base logic of the client and server communication chain.
Most importantly, each client is now required to store their own desired options, as they will be communicated to the server. This allows us to support instances where a user desires to use different pipe names, architectures, and/or block timers.
Previously, the server would send a stager and wait for a client to acknowledge that they have received it. Now, the client will instead send an initialization message to the server, that contains the options used to generate the desired stager.
The server will now check for new clients via the transport independently of handling communication with each client.
Finally, a common dataframe was created that is used to pass information between the client and server.
Common Dataframe
To facilitate communication for multiple clients, a data frame was created that contains the client's id and data to be transferred within that frame. First, the "data" field of the frame is base64 encoded, then the entire frame is base64 encode to prevent issues in transit and with encoder.encode(). This base64 encoded string is then passed to encoder.encode().
The frame itself is simply a python list. The client ID MUST be the first element of that list, and the data MUST be the second element. Eventually, this will likely be converted into a dictionary, but preliminary tests have shown no issues with this approach.
import base64
from ast import literal_eval
# `encoded_data_frame` is the data received from the transport after already being passed through `encoder.decode()`
decoded_df = base64.b64decode(encoded_data_frame)
raw_data_frame = literal_eval(decoded_df)
decoded_data_frame = [raw_data_frame[0], base64.b64decode(raw_data_frame[1])]
This pull request adds the ability to support multiple simultaneous clients. Detailed development notes are available in #14.
Changelist
ID
,pipename
, anddesired architecture
.ID
value must be unique for each client.Beacon
used to track the state of each session.send_server_notification()
andcheck_for_new_clients()
added to the base skeleton of transportsDetailed changes
For my own accounting purposes, and for the sanity of anyone else trying to work with this, the below section basically contains a more thorough and detailed breakdown of the changes mentioned in the overview above. This section is probably redundant, and likely only relevant if you intend on modifying the code. Readers seeking additional reference are encouraged to see #14.
Base logic modifications
A number of changes were added to the base logic of the client and server communication chain.
Most importantly, each client is now required to store their own desired options, as they will be communicated to the server. This allows us to support instances where a user desires to use different pipe names, architectures, and/or block timers.
Previously, the server would send a stager and wait for a client to acknowledge that they have received it. Now, the client will instead send an initialization message to the server, that contains the options used to generate the desired stager.
The server will now check for new clients via the transport independently of handling communication with each client.
Finally, a common dataframe was created that is used to pass information between the client and server.
Common Dataframe
To facilitate communication for multiple clients, a data frame was created that contains the client's id and data to be transferred within that frame. First, the "data" field of the frame is base64 encoded, then the entire frame is base64 encode to prevent issues in transit and with
encoder.encode()
. This base64 encoded string is then passed toencoder.encode()
.The frame itself is simply a python list. The
client ID
MUST be the first element of that list, and the data MUST be the second element. Eventually, this will likely be converted into a dictionary, but preliminary tests have shown no issues with this approach.Sending dataframe example
Receiving dataframe example