Mike's Design Study
Contents |
Intro
For my design study, I decided to base it on the assignment for COSC 429. The goal of this assigment is to create two programs hence called the implant and the controller. The basic purpose of the implant is to transmit information about the host that it is running on to the controller(runnning in a different host), at the request of the controller. The basic purpose of the controller is to provide an interface to a user to extract information from the host that the implant is running on. This information includes (but is not necessarily limited to):
-Keystrokes
-Names of the processes running on the host.
-Names of the user accounts running on the hosts.
-A screenshot of what is currently displayed on the monitor of the host.
-Directories and files.
I wrote the implant and the controller in C# using the Visual Studio development environment. I decided to implement networking features of the implant and controller using asynchrounous socket programming.
Class Diagram
The diagram displayed is the current state of the model I created to implement the features of the assigment for the purposes of this design study.
BreakDown of Main Classes
These classes represent the classes that I designed for my model.
Connection
This class represents the network connection between the implant and the host. This class encapsulates a Socket object and uses it to perform the network related functions required by the implant and the controller. Thus the controller and implant class both have an instance of this class as a field.
Command
This class is an abstract class that represents the instructions to the implant sent by the controller. It has two virtual methods execute() and DeSerialize() and a non virtual method called serialize(). Based on the subclasses that are derived from Command, the execute method will behave differently. For example running the execute method of an instance of the ListActiveUsersCommand will run code that retrieves the names of the user accounts on the host. Before execute completes, it creates the appropriate instance of Reply inserting the retrieved information, and uses the Implant class to send the reply back to the controller. In order for Command (and Reply) objects to be sent accross a network connection, they have to be converted into byte array representations of the object, which is the purpose of the serialize method and conversely the purpose of the deserialize method is to revert these byte array represeantations back into their respective Command objects.
Reply
This class is another abstract class that represents the information sent back to the controller from the implant. It also has two virtual methods notify() and Deserialise. The purpose of the notify() method is to call call an event on the controller so that any event handlers attatched to that specific event may react to said event. The event that is called depends on what sublclass of Reply is running the notify method. The serialize and deserialize methods are for used for the same purposes as stated in the Command class.
Controller
This class represents the force that drives sending commands and receiving receiving replies. Its main purpose in a nutshell is to send commands to an connected implant and then wait for the reply. The sendCommand(Command aCommand) method can be used by whatever is containing the Controller class (like a gui class) to send Command objects to the implant. When sendCommand is called it first serializes the Command using the Command's own serialize method and then passes the (serialized) data in the call to its Connection object's send(byte[] theData) method. Lastly the Controller calls its own receiveReply. . Receiving Replies is pretty much the reverse of sending Commands. First the controller calls its Connection object's receiveData which tells the connection to asynchrounoysly receive data from the controller. When the all the data has been received, the Received event is fired in the connection passing the byte array to the event. The Controller's receivedHandler then creates a new instance of Reply, uses the Reply's deserialize method pssing into it the byte array. The Reply's notify method is then called which fires an event in the Controller that registered handlers can then respond to.
The controller class also has a number of events that are basically driven by the Reply objects that get received. Thus objects that contain an instance of Controller can register event handlers to respond various events and use the data(lists of processes, lists of users, TreeNodes representing directories etc), with GUI classes in mind and also for logging perhaps.
Implant
This is pretty much the same as controller, but instead receives Command objects (running their execute methods) and sends the appropriate Reply objects to the controller. It is a Singleton class.
Breakdown of Other Classes
These classes represent classes that I found on the internet to complete some of the features of the assignment or data classes.
KeyboardHooker
This class that represents the keylogging features of the assigment. It's one quirk is that it has to be initialised before the implant is actually run. It also makes use of WIN32 API function calls in order to implement the capturing of keystrokes. This forces these the methods that use these API calls to be static. I modified this class to caintain an event called Keypress and also defined the appropriate handlers. This class is used by the an instance of KeylogCommand to register an Keypress handler so that whenever a key is pressed it sends a KeylogReply (which contains a string representing the key pressed) back to the controller.
StateObject
This class is a data class that stores a reference to a Socket object, a byte array, and a List<byte> collection. Its intent basically was to store data in the List collection when the Connection class had to call it's Socket object's asynchronous receive method multiple times in order to receive all the data. This StateObject basically acted as a place dump all the received data into until all the data was received.
Using this class did not help with my problem, but I figured it out without having using it.
Patterns Used =
Singleton
This is the only pattern that I excplicitly used in the process of creating my model. The singleton is the implant class. The rational for using this was because I thought I needed a global variable that represented the Implant for my Command objects to use when using the implant to send Reply objects to the controller.
On Principles and Smells
Principles Followed
Do the simplest thing that could possibly work - Due to the amount of time I had to complete this design study, as I had to come up with a design and then code it, having to fulfill some specific requirements, I explicitly tried my best to make the model as simple as possible. Its probably not too bad with 5 major classes. I hope its not too simple.
Program to the interface not to the implementation - With the way the Controller and Implant objects use Reply and Command objects respectively, they don't have to know anything about the specific derived classes (of command and reply objects respectively) in order to use them.
One key abstraction - I think I did alright with regards to this principle, as each (major) class represents a unique part of the the assigment. There is an exception though with the Implant and the Controller. I think it is possible to merge the two classes because they basically share the same behavior and also use the same connection object. So perhaps there are only 3 key abstractions in the domain of the assigment. The only thing I can smell from doing this is the large class smell, the Controller is preatty big as it is already with its numerous events.
Liskov substitution principle - My model follows this principle becuase Controller and Implant dont know ahead of time what sort of Reply and command objects they will be receiving respectively. All they know is that they are supposed to receive an instance of Command or Reply and run their respective execute and inform methods.
Smells and other Bad Stuff
Duplicate code smell - This smell comes from the serialize methods of the Reply and Command objects. They both serialize exactly the same way, but I feel that it might be not worth making a Serializer class because it might be an irrelevant class and also because there are not enough objects that need to be serialized in my model.
Single responsibility principle - One instance of my model breaking this principle is the Connection class, because according the the single responsibility rule, my conncection class should only handle one responsibility which is either managing connections or dealing with data transfer. However in this case I think it is alright becuase the connection class encapsulates a library class that also has multiple responsibilities, and handles only 2 responsibilities.
Some Coupling - There exists some data coupling between Command and Implant where Command Objects when they use the Implant to send Reply Objects. Data coupling also exists between Controller and Reply. Controller passes itself in the Reply objects notify method, and Reply objects trigger the passed Controller object's OnEventName passing to it the Reply object's data. There are more examples available but the ones mentioned are the most glaring ones. My rationale for doing it this way was to prevent the type switch smell when receiving a Command or Reply .
Final Comments
The 429 assigment is basically done, as it is now the controller and the imlpant can do their jobs. Although one thing isnt working properly which is the keylogger feature I'm pretty sure I'll nail it. With working on the model first, creating a GUI for the controller or the implant will be pretty much a breeze. Although I encountered some time consuming bugs, they had more to do with my inexperience in asynchrounous socket programming than actual problems in the model itself. Although I can't say I enjoyed doing this design study, I think I at least improved my designing ability which will be useful to me in the future.
Source Code and Resources Used
Source Code
File:AssignmentClassLibrary1.zip
Reseources
C# Network Programming by Richard Blum