Protostar exploits Net0

Introduction

Protostar exploits are a cool bunch of ctf type exercises that focus on Linux  binary exploits that progressively get harder. A ISO containing the OS and challenges can be downloaded.

The website with all information and downloads is at https://exploit-exercises.com/protostar/

Challenge

Test run

net0 is a network daemon that listens on port 2999. The iso image automatically starts the daemon for you. If we list the running processes you should see it.

user@protostar:~$ ps ax |grep net0
1740 ? Ss 0:00 /opt/protostar/bin/net0
5225 pts/2 S+ 0:00 grep net0
user@protostar:~$ sudo netstat -nap|grep net0
sudo: unable to resolve host protostar
tcp 0 0 0.0.0.0:2999 0.0.0.0:* LISTEN 1740/net0
user@protostar:~$ nc -vvv localhost 2999
DNS fwd/rev mismatch: localhost.localdomain != localhost.qualcomm.com
localhost.localdomain [127.0.0.1] 2999 (?) open
Please send '590895857' as a little endian 32bit int
AAAA
I'm sorry, you sent 1094795585 instead
 sent 5, rcvd 92

Exploit

We need to connect to the network daemon, read the random number sent to us and send back the integer value’s equivalent hex representation in little endian order. Success will be indicated with the message ‘Thank you sir/madam’.

#include "../common/common.c"

#define NAME "net0"
#define UID 999
#define GID 999
#define PORT 2999

void run()
{
 unsigned int i;
 unsigned int wanted;

 wanted = random();

 printf("Please send '%d' as a little endian 32bit int\n", wanted);

 if(fread(&i, sizeof(i), 1, stdin) == NULL) {
 errx(1, ":(\n");
 }

 if(i == wanted) {
 printf("Thank you sir/madam\n");
 } else {
 printf("I'm sorry, you sent %d instead\n", i);
 }
}

int main(int argc, char **argv, char **envp)
{
 int fd;
 char *username;

 /* Run the process as a daemon */
 background_process(NAME, UID, GID); 
 
 /* Wait for socket activity and return */
 fd = serve_forever(PORT);

 /* Set the client socket to STDIN, STDOUT, and STDERR */
 set_io(fd);

 /* Don't do this :>; */
 srandom(time(NULL));

 run();
}

I found that scripting my challenge helped me have greater control over reading the challenge integer value and converting to little endian ready for sending back to the server as raw bytes.

Here is my script https://github.com/muttiopenbts/protostar/blob/master/protostar-net0.py

"""
This code is for protostar net0 challange.
Will connect to net0 network daemon, read the decimal value send from server, convert to hex, then send back in little endian.
"""
import socket # for sockets
import sys # for exit
import re
import struct

try:
#create an AF_INET, STREAM socket (TCP)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
sys.exit()

print 'Socket Created'

host = sys.argv[1]
port = sys.argv[2]

try:
remote_ip = socket.gethostbyname( host )

except socket.gaierror:
#could not resolve
print 'Hostname could not be resolved. Exiting'
sys.exit()

print 'Ip address of ' + host + ' is ' + remote_ip

#Connect to remote server
s.connect((remote_ip, int(port)))

print 'Socket Connected to ' + host + ' on ip ' + remote_ip

try:
#Now receive data
recv = s.recv(4096)
print recv
m = re.search('\'(.+?)\'', recv) #search for decimal value between single quotes
if m:
found = m.group(1)

#Set the whole string
hexval = hex(int(found))
hexval = hexval[2:]#remove leading '0x' characters
rev_bytes = struct.pack('<L',int(found))#Convert big endian to little
print "challenge, %s send back hex %s in little endian %s" %(found,hexval,rev_bytes.encode('hex'))
s.sendall(rev_bytes)

recv = s.recv(4096)
print recv
except socket.error:
#Send failed
print 'Send failed'
sys.exit()

print 'Done.'

Testing the script

user@protostar:~$ python protostar-net0.py localhost 2999
Socket Created
Ip address of localhost is 127.0.0.1
Socket Connected to localhost on ip 127.0.0.1
Please send '157677536' as a little endian 32bit int

challenge, 157677536 send back hex 965f7e0 in little endian e0f76509
Thank you sir/madam

Done.

The script reads and extracts the string representing the challenge decimal value ‘157677536’, converts this to hexadecimal ‘0x965f7e0’ but because the program has this stored in little endian format we have to reverse the 8 bit chunks ‘0xe0 0xf7 0x65 0x09’ of the value and send them back to the server to have a successful match.

Thank you

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s