I like to do simracing as a hobby (for those who don't now what this is: You spend hours to prepare for a virtual racing event and then crash in the first corner).
At some point, I've got involved in the administrative part, managing dedicated servers. For somebody who works mostly in (unixoid) shells, this became a nightmare expierience. Unresponsive, buggy software without proper documentation and a lot of 'known bugs', which the developer won't fix. Why? I don't know. The software needed for management looked like the usual enterprise-software-interfaces we all love to use.
For myself, using the software per hand was a no-go. I simply cannot spend 15 minutes on a task and 3 hours for debugging. Thats ridiculous. The need for automation was there.
A short check, what options I've had:
- Patching the binaries
- Reversing the code
- Fiddling around in the memory
- Search for undocumented features
- Monitor the applications behaviour
It was clear from the start that the first three options were no considerable options. As I wanted to release my expierience with the proof-of-concept at some point, knowingly breaking licenses did not feel good. What remained now? Searching around. Alot.
Software under the microscope
First thing I needed to find out was: What am I seeing? After a few days of analysing I knew that I was seeing an Java application, embedded in an portable JRE runtime (terribly old btw). Additional, binaries were built in VC++.
The route of the "what" was more a "nice to know" than anything else, as I did not want to do any reversing.
A search for hidden command line parameters went quite bad. Using common switches to see if applications are doing some kind of stdout was not that successfull as I hoped to. After spending some time investigating, I realized that a lot of command line switches were simply faulty or deprecated.
To find out what a software is doing, several methods could be used without having to look "into" the software itself. My first tool of choice was procmon to see what the application is doing in some situations, as the software was a Windows application.
I've found out that some of the dialog of one of the mandatory configuration tools stored it's data in %APPDATA%/local, allowing me to manipulate the data from the outside as I want to.
- No additional command line switches found
- Partly data manipulation possible from the outside
You may ask: Why not memory manipulation? For myself, I have a bit of expierience patching binaries, e. g. with Cutter/ Radare, but not reading data on runtime. I was a bit afraid to end in a rabbit hole, so I've decided not to follow this path.
Time for a robot
What do you, when you a) have no commandline and b) have no data interface? Correct, you click buttons. Not elegant, but working.
As I'm working with python here, I decided to utilize pywinauto for this project.
The biggest challenge was to find the correct paths to choose. When I want to archieve goal X, what buttons need to be clicked? What wait durations must be choosed? Which data needs to be set from the outside?
This was quite frustrating. Each time it looked promising, it broke again. It almost felt that the target software was more buggy than the proof of concept I was writing. But after weeks of ragequitting, it worked for the first time.
Together with the possibility to alter data using the stored data in %APPDATA%, the complete process could be automated for most cases. As I could not avoid completely to rely on thread.sleep() for wait situations, some deployments still remain a bit flaky.
Not each case could be automated, but for myself and for the proof of concept, this is completely fine 😎
All of my ideas were following the same idea: Manage the server without having to click buttons on the server itself, so I needed some kind of interface.
As the use of pywinauto allows reading data, I've added a flask-based HTTP API (not really REST, as it's only delivering some endpoints). Now I was able to deploy the server, reconfigure it or do some basic operations on it - like restarting.
With an HTTP-based interface a lot of features can be attached in theory, like a monitoring. But for myself, I'm happy with now only having to write a JSON file and do a POST request to get everything running 🙂
Conclusion for the complete Proof-of-Concept
In general, the whole process felt like a deep dive into a cesspit. With each thing I found out how the software worked I felt more disgusted. Features where simply not finished or the way it's implemented in the target software was just questionable. My tries to reach the developer if there are any chances for improvement where either ignored or just blocked.
You know may ask: Why the fuck did you do that? It was a challenge!
As I'm also doing some CTF challenges sometimes, it helped me to improve some skills how to understand the interna of a software - even if I can't look inside. A majority of the proof-of-concept was about the analysis of the software and not about scripting.
Photo by Patryk Grądys on Unsplash