Botpanel acts as a management panel for botnets, in which we could also invite friends, if we own a registered version.
So, let’s take a look at it:
We can use the password from the provided config, if running locally, but obviously it won’t be the correct password for the remote service.
Also this [TRIAL MODE] doesn’t look right. Thus, first, we have to:
find the correct password for the remote service
change trial mode to registered mode
Let’s take a look at the login handling
There’s a pretty obvious format string vulnerability in the login handler, which can be used to leak some stuff. We won’t be able to do “much” more than leaking with it, since the format string is limited to 12 characters, which just isn’t enought to do arbitrary writes.
But we’ll try to make the most out of it.
When doing format string exploits, I mostly just start with a little scanner, showing me the pointer and content of every format string parameter.
This will write an output file, which we can use to check, what to use for leaking
We could now check the other addresses with gdb, but for getting a quick overview we just replace the format string send with
and get
Without any real effort, we now have every leak at hand, we could possible need to exploit this any further.
For getting the server password, just send %20$s and note it somewhere. Since the password will not change, we don’t need to waste a try on retrieving it again and again.
Going through the binary at first, it might seem, as everything’s fine, every buffer is only read with a correct size, so no overflows will happen. There’s just this invite-mode, that’s only accessible when we’re not in trial mode. It will let you enter an IP and a port, starting a new thread, connecting to the specified machine and show them a menu, in which they can only send a feedback in the end.
Before getting into the feedback handling, we should find a way to get into registered mode.
So, if conf[1] isn’t T we’ll be out of trial mode. Well, though we cannot do much writing with our format string vuln from login, writing one single null byte is possible. Also, if you check where config is stored, you’ll see that it is accessable by the 5th format string parameter, so getting into registered mode boils down to just
We can now invite other clients, which will let the service connect back to the specified machine:
With this, we can invite a maximum of two other clients to the botpanel. After connecting, this will create a thread handling the clients. In invite_handler it will show them another menu, in which they can send feedback back to the service.
At first, this looks ok. The binary checks, that a valid feedback length is specified, before it will read to the feedback buffer, so nothing bad should happen.
But then again, feedback_len is a global variable and every client is running in a thread. Thus, feedback_len is shared over all threads, and one client changing this variable will also effect other clients.
Short attack plan:
Invite client 1
Invite client 2
Client 2 starts sending feedback
Specify a valid feedback length, getting into edit mode
Write some short feedback
Wait on the question Edit feedback
Client 1 start sending feedback
Specify a feedback length of 2000
Getting an error, that length would be invalid (but feedback_len is now 2000)
Back to client 2
Answer yes to Edit feedback
Client 2 can now send 2000 bytes into buffer, easily smashing it
I wrote three scripts for those tasks. In hindsight, it would have been even easier to just handle all three connections in one script, but well, ctf time ;)
Main exploit, connecting to the service, doing leaks and inviting the other two clients
Server 1, waiting for connection
Server 2, waiting for connection, doing a ropchain to execute a command in the thread of the main exploit
Main Exploit
This will do the leaking, writing it to a file for simple communication with our server scripts. It will then send two invites back to our own machine on port 6666 and 7777, where our secondary server scripts will be waiting.
The first one, will just wait 2 seconds (more than enough for the second script to get into the edit feedback block), and then overwrite the feedback length:
The second server script will read the leaks found by the main exploit and then enter directly into the edit feedback block by specifying a valid feedback length, and sending a small feedback.
It will then wait 3 seconds, so the first server script will have corrupted the feedback length size, and then edit the feedback, smashing the stack.
The ropchain will read the command, we want to execute, into bss and then just call system(buffer), which will execute the command and show the result in our main exploit terminal.
We’ll just open three terminals, and start the main exploit (1) and the script for server 1 (2) and server 2 (3)
(1) Starting main exploit:
(2) This will connect to our first server script
(3) This one is now waiting for the second script to send a valid feedback and get into edit mode
(2) Shortly after, the first server script will kick in again, changing the feedback length
(3) And finally our second server script can overflow the feedback, send our ropchain and the command we want to execute:
(1) which will now execute our command and show it in the main exploit terminal again 8)