It is now one year since I wrote the first blog post about RustRAT. Even though I did not start writing any actual code until this year, I still consider this some kind of anniversary. On this anniversary, few of the goals I set for version 0.1 remain. However, as I have worked on RustRAT, I have come to realise that quite a lot remains until RustRAT is something I would consider using in an engagement.

There were quite a few weeks without any commits before the most recent commit. It started when I attempted to add support for sending output from rats to the C2 server. I decided to use closures for this to include the id of the job sending the output. This caused a lot of problems, mostly because I had hacked everything together quickly without properly considering the consequences for my choices, and how they would limit further development.

In addition to things I had to change to make the new functionality work, I also wanted to get rid of some of the ugly things I had done, such as having a static RefCell as some sort of singleton. This resulted in me going over parts of the code and trying to fix things wherever I felt like it. There are still quite a few problems, and I will probably spend a lot of time trying to make the source more idiomatic rust-like before the planned 0.2 release. In particular, I am quite liberal with Rc<RefCell<T>>, although some of this can be excused in my opinion, as I want a shared hash table of functions that can be called, and I do not see any ways to do this. clone() is also liberally used, and I am pretty sure many of these calls could be avoided. One final thing I would mention is that in the rust code I pass arrays containing cryptographic keys around in a rather haphazard manner. The keys are not zeroed when they go out of scope either. I would not be too concerned about this if it were not for that it just feels wrong to me, triggering my inner appsec alarms.

While I did some work on cleaning up the rat, the server was left mostly untouched, and a lot of cleaning up remains for the server. Bad design of the server actually cost me an hour or two of debugging. While designing the functionality to receive output from tasks, I forgot to make the server send a reply when handling certain requests. This resulted in one-shot channels being dropped and the server just returning an error message. Now, this was not too bad, but I cannot help the feeling that this could have been avoided entirely by designing the server in such a way that output always has to be sent, as every request is supposed to have a reply.

That is it for this update. I am currently working on a very simple UI for the server. After that I will be making some sort of useful WASM script before I can finally celebrate version 0.1.