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
net2 is a network daemon that listens on port 2997. The iso image automatically starts the daemon for you. If we list the running processes you should see it.
root@protostar:/home/user# ps ax |grep net2 1662 ? Ss 0:00 /opt/protostar/bin/net2 28632 pts/1 S+ 0:00 grep net2 root@protostar:/home/user# netstat -nap|grep net2 tcp 0 0 0.0.0.0:2997 0.0.0.0:* LISTEN 1662/net2 localhost.localdomain [127.0.0.1] 2997 (?) open eO?t?`?7FBH? AAAA sorry, try again. invalid sent 5, rcvd 42
Exploit
We need to connect to the network daemon, read four random numbers sent to us, reverse byte order them and send back the sum of all the numbers in little endian order. Success will be indicated with the message ‘you added them correctly’.
#include "../common/common.c" #define NAME "net2" #define UID 997 #define GID 997 #define PORT 2997 void run() { unsigned int quad[4]; int i; unsigned int result, wanted; result = 0; for(i = 0; i &lt; 4; i++) { quad[i] = random(); result += quad[i]; if(write(0, &(quad[i]), sizeof(result)) != sizeof(result)) { errx(1, ":(\n"); } } if(read(0, &wanted, sizeof(result)) != sizeof(result)) { errx(1, ":<\n"); } if(result == wanted) { printf("you added them correctly\n"); } else { printf("sorry, try again. invalid\n"); } } 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 :&gt; */ srandom(time(NULL)); run(); }
I found that scripting my challenge helped me have greater control over reading the challenge integer values 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-net2.py
""" This code is for protostar net2 challange. Will connect to net2 network daemon, read 4 integers reverse byte order, add them up, reverse order total and send back to server. """ import socket import sys 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))) s.settimeout(2) #Raise exception if no data received after 2 seconds, Use this timeout to begin processing data received from server. print 'Socket Connected to ' + host + ' on ip ' + remote_ip recv_array = [] total = 0 try: #Now receive data while True: recv = s.recv(4096) recv_array.append(recv) print "Received: %s" %recv except socket.timeout: print("Timeout. Server has finished sending data. Time to add up all the values.") for bytes in recv_array: hexval = bytes.encode('hex') integer = struct.unpack("<L", bytes)[0] #L=unsigned long 4 bytes, < little endian and unpacked to integer total += integer print "Received bytes %s converted little endian %s which resulted in an integer %s" %(hexval, hex(integer), integer) rev_bytes = struct.pack("<L", total)#reverse bytes received for little endian print "Total up the integers %s, reverse byte order from %s to %s and send" %(total, hex(total), rev_bytes.encode('hex')) print "Sending challenge to server" 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-net2.py localhost 2997
Socket Created
Ip address of localhost is 127.0.0.1
Socket Connected to localhost on ip 127.0.0.1
Received: ??`
Received: Du3
Received: Y?Bj
Received: Pm
Timeout. Server has finished sending data. Time to add up all the values.
Received bytes ba926004 converted little endian 0x46092ba which resulted in an integer 73437882
Received bytes 44750033 converted little endian 0x33007544 which resulted in an integer 855668036
Received bytes 59f1426a converted little endian 0x6a42f159 which resulted in an integer 1782772057
Received bytes 50166d1f converted little endian 0x1f6d1650 which resulted in an integer 527242832
Total up the integers 3239120807, reverse byte order from 0xc1110fa7L to a70f11c1 and send
Sending challenge to server
you added them correctly
Done.
The script reads four integers from the network socket, reverse byte orders each one, totals up the values, reverse orders the total and send back to the server.
Thank you