Wednesday, October 1, 2014

Vortex level 0

"If looks could kill they probably will, in games without frontiers - war without tears"

Wargame time. Vortex is the first target (probably regrettable, since that server is notoriously hard).
Here is the walkthrough for level0. Problem description can be found here:
http://overthewire.org/wargames/vortex/vortex0.html

I will try to cover all of the levels on this machine. I will post my complete answer, but I'm going to refrain from posting the actual passwords (just run the code if you really want them). Part of the fun of wargames is the agony that comes from trying to solve the damn things, so spoiler alert, use these resources sparingly. It's very easy to read the answer and cheat yourself out of the solution.
Big thanks to overthewire.org for continuing to host these games!

Some suggested reading for this level:
http://www.tutorialspoint.com/python/python_networking.htm
https://docs.python.org/2/library/struct.html
http://teaching.idallen.com/cst8214/08w/notes/bit_operations.txt

This level wants us to connect to a remote host on a specified port, and read four unsigned integers in host-byte order. We are told that the machine is little-endian format. Host-byte order is just a standard used to avoid confusion among little endian and big endian machines. We will read the four unsigned ints, add them together, send back the sum, and receive the solution. There's a catch though, the numbers we receive are quite large, and adding them together will almost always overflow past 32 bits. Thus, at each intermediate stage, we keep our answer to 32 bits by masking it with a 32-bit mask (0xffffffff)

Here's the code. I went with Python over C since I value my sanity;)

#!/usr/bin/python
from socket import *
from struct import *

host = "vortex.labs.overthewire.org" #Target host
port = 5842 #Target port
integer_sum = 0  #This will hold the sum of the received integers
s = socket(AF_INET, SOCK_STREAM) #create a socket connection
s.connect((host,port)) #connect to remote host
#We receive 4 unsigned ints, each 32 bit (4 byte) in Little Endian
for i in range(4): 
data = s.recv(4)
integer_sum += unpack("<I",data)[0]
integer_sum &= 0xffffffff
#unpack handles the network data in Little Endian format
s.send(pack("<I",(integer_sum)))
print s.recv(1024) #username:password
s.close()

We start by importing socket and struct (used for packing and unpacking network data).
We create variables for the host and the port, and then an int that will hold our sum.
we then create a connection-oriented socket and connect to the remote host and port.
The 4 loop will read call recv four times, each time reading in 4 bytes (32 bits) of data.
unpack("<I",data)[0] will take the network stream data in little-endian ( "<" ) format, read it as an unsigned int ("I") and store it in sum. We then consider only the first 32 bits of integer_sum by hitting it with the mask 0xffffffff (this could also be done only once at the end, before sending the sum to the host).
We then send it off (as a little endian unsigned int "<I"), receive the answer (or a "bzzzt, wrong" if you've made a mistake) and call it good. Level0 down, on to the next one!

No comments:

Post a Comment