Exploit Exercises - Protostar Net 2

So far, these Net challenges in Protostar have been pretty easy. This challenge, Net 2 got a small bit tougher.

We are given the following code:

#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 < 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 :> */
 srandom(time(NULL));

 run();
}

From this code, we can see a daemon is listening on port 2997. It is going to output 4 random unsigned integers in little-endian format. It then will expect the sum of all 4 of those integers to be returned in little-endian format.

I was able to solve this with the following code:

#!/usr/bin/env python

# Protostar Net 2
# http://exploit-exercises.com/protostar/net2
# Matt Andreko
# twitter: @mandreko
# contact: matt [at] mattandreko.com

from socket import *
from struct import *
from optparse import OptionParser

def main(host, port):

 s = socket(AF_INET, SOCK_STREAM)
 s.connect((host, port))

 sum = 0

 # Loop over the 4 unsigned integers being read in, and them to "sum"
 for x in range(4):
  data = s.recv(4)
  little_endian = int(unpack("<I", data)[0])
  print "[*] integer " + str(x) + ": " + str(little_endian)
  sum += little_endian

 print "[*] Sum: " + str(sum)

 # Handle integer overflow by doing a logical AND with 0xffffffff
 sum &= 0xffffffff

 # Convert the sum back to little-endian, to send back over the wire
 sum_packed = pack("<I", sum)

 s.send(sum_packed)
 print s.recv(1024)

 s.close()

if __name__ == "__main__":
    parser = OptionParser("usage: %prog [options]")
    parser.add_option("-H", "--host", dest="hostname", default="127.0.0.1", 
     type="string", help="Target to run against")
    parser.add_option("-p", "--port", dest="portnum", default=2997, 
     type="int", help="Target port")

    (options, args) = parser.parse_args()
    
    main(options.hostname, options.portnum)

When I run that code, I get the following output:

C:\Protostar>net2.py -H 192.168.1.132
[] integer 0: 1724850170
[] integer 1: 692469090
[] integer 2: 630776982
[] integer 3: 1691529294
[*] Sum: 4739625536
you added them correctly

comments powered by Disqus