CS177: Project 1 - Simple Network Client (10% of project score)
The goals of this project are:
The project is an individual project. It is due on Thursday, April 20, 2023, 23:59:59 PST (no deadline extensions; late flags will not be accepted).
Implement a simple network client
The goal of this project is to implement a simple network client. This client should connect to a remote service and exchange a sequence of messages without hanging or crashing. This is important because all our lab projects leverage the CTFd infrastructure, and this will require you to connect to and interact with various remote services.
As a first step, please register with our CTFd site. We shared the information about the location of this site in Piazza. Once you have registered, you can log in and go to "Challenges." There, you find the instructions to spin up the server instance for you (which is running in a Docker container). The site will give you the address and port where your server is running and listening for your connections.
Once you have launched your service, you can start to implement your client. This client should connect to the server. Then, it will interact with the server in multiple rounds. The goal is to implement a very simple (key, value)-storage system. In a nutshell, in each round, the server will ask the client to store or retrieve a value, or it requests some status information. Once the server is convinced that the client works properly, it will send a flag. The goal of your client is to obtain that flag.
Each round consists of three messages:
In this project, we implement a simple protocol-buffer-based protocol between the client and server. At first, it may seem a lot of work to implement all the different types and fields of the messages (that are described below). This is where protobufs will make your life much easier. The use of protobuf and its libraries make it very convenient to define the format of messages and to read and write the data.
For our project, each exchange between the client and the server has two parts. The first part is a fixed-length unsigned short integer (which we call m_len) that indicates the length of the following message. For the second part, which is the actual message, we will be using protobuf. The exact format is as follows:
The objective of this project is to implement a robust TCP client that we will need as the basis for the subsequent security challenges. One common stumbling block is that many developer are unaware that, as a stream or byte-oriented protocol, TCP makes no particular guarantees that a send of n bytes will be matched with a recv of n bytes. In practice, this means that it is not enough when reading data to simply read an expected n bytes, but instead, one must anticipate short reads and receive in a loop until all expected bytes have been accumulated.
The server will issue a series of set (Type 2), get (Type 4), and status (Type 7) messages. Once your client has convinced the server that it correctly implements the protocol over a number of rounds, it will send you the flag (Type 10).
You don't need to use any persistent storage for keeping the key, value pairs. You can simply hold everything in memory while you interact with the server.
You can use any language to implement the client, since you will only interact with our service over the network. But I would recommend Python as a great choice.