Sunday 8 September 2013

Exploit exercises - Protostar - Net 3

Last network level is a bit more challenging. There are a couple of traps here. The idea of the program is like that: it reads length(16-bit) of the future input, then reads that amount of bytes. First byte of the input should have the value of 23 to proceed to login function. Buffer with input data is used as an argument to the login function.



Then login function cuts out three parts : resource, username, password. Those values should be zero terminated strings and first byte as unsigned byte should contain length of string. After all data is being moved to the heap it is compared to the ("net3","awesomesauce","password") strings and if all matches it sends congratulation message.

It may sound quite easy and it is easy except some traps. Firstly, length of the message must be sent in network byte-order which is big endian, because of ntohs function (see man ntohs). In Ruby you can send size using pack('n'), where n is for network endianness. Secondly, you have to send lengthes of resource, username and password including 1 byte zero-terminator. So you need to add 1 to them. Finally, you cannot simple gets congratulation message. You have to get length in network byte order and then read that amount of bytes.

Code:
#!/usr/bin/ruby1.9.1
require "socket"

resource = "net3"
username = "awesomesauce"
password = "password"

sock = TCPSocket.new('127.0.0.1','2996')
first = [23].pack('C') + [resource.length + 1].pack('C') + resource +"\x00"
second = [username.length + 1].pack('C') + username + "\x00"
third = [password.length + 1].pack('C') + password + "\x00"
message = first + second + third
puts "#{first.length} - #{first.unpack("H*")}"
puts "#{second.length} - #{second.unpack("H*")}"
puts "#{third.length} - #{third.unpack("H*")}"
puts "Total:#{message.length} - #{[message.length].pack('n').unpack("H*")}"
sock.write ([message.length].pack('n') + message)
len = sock.read(2).unpack('n')
puts sock.read(len[0])
sock.close
Proof:
P.S.: It was very useful to be able to debug using strace and gdb, since both of them allows to follow children and trace data. To debug you have to obtain process id (using ps aux | grep net3). Then run strace -p pid -f . f is used to follow fork and strace child process system call as well. Also you can use gdb. Run gdb. Execute attach pid, where pid is your process id. Also execute set follow-fork child in gdb to follow child process after fork, because parent process just serves new connections. Then do whatever you want.

No comments:

Post a Comment