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
net1 is a network daemon that listens on port 2998. 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 net1 27882 ? Ss 0:00 /opt/protostar/bin/net1 27890 pts/1 S+ 0:00 grep net1 root@protostar:/home/user# netstat -nap|grep net1 tcp 0 0 0.0.0.0:2998 0.0.0.0:* LISTEN 27882/net1 user@protostar:~$ nc -vvvv localhost 2998 localhost.localdomain [127.0.0.1] 2998 (?) open ???lAAAA you didn't send the data properly sent 5, rcvd 38
Exploit
We need to connect to the network daemon, read the random bytes sent to us, convert to little endian and send back the equivalent ascii representation. Success will be indicated with the message ‘you correctly sent the data’.
#include "../common/common.c" #define NAME "net1" #define UID 998 #define GID 998 #define PORT 2998 void run() { char buf[12]; char fub[12]; char *q; unsigned int wanted; wanted = random(); sprintf(fub, "%d", wanted); if(write(0, &wanted, sizeof(wanted)) != sizeof(wanted)) { errx(1, ":(\n"); } if(fgets(buf, sizeof(buf)-1, stdin) == NULL) { errx(1, ":(\n"); } q = strchr(buf, '\r'); if(q) *q = 0; q = strchr(buf, '\n'); if(q) *q = 0; if(strcmp(fub, buf) == 0) { printf("you correctly sent the data\n"); } else { printf("you didn't send the data properly\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 :> */ srandom(time(NULL)); run(); }
I found that scripting my challenge helped me have greater control over reading the challenge bytes from the server and converting to little endian ready for sending back to the server as integer string.
my code can be found here https://github.com/muttiopenbts/protostar/blob/master/protostar-net1.py
""" This code is for protostar net1 challange. Will connect to net1 network daemon, read the bytes sent from the server, convert to little endian then decimal 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))) print 'Socket Connected to ' + host + ' on ip ' + remote_ip try: #Now receive data recv = s.recv(4096) print "Received: %s" %recv #Set the whole string hexval = recv.encode('hex') rev_bytes = struct.unpack("<L", recv)[0]#reverse bytes received for little endian print "challenge, send back hex 0x%s in little endian order %s then decimal %s" %(hexval,hex(rev_bytes),rev_bytes) s.sendall(str(rev_bytes)+"\n") recv = s.recv(4096) print recv except socket.error: #Send failed print 'Send failed' sys.exit() print 'Done.'
Test run
user@protostar:~$ python protostar-net1.py localhost 2998 Socket Created Ip address of localhost is 127.0.0.1 Socket Connected to localhost on ip 127.0.0.1 Received: ?#?6 challenge, send back hex 0xbd23bb36 in little endian order 0x36bb23bd then decimal 918234045 you correctly sent the data Done.
Thank you