A catalogue of writeups from past CTFs
This project is maintained by alran
The cryptic clue for this challenge was Gotta be fast <IP ADDRESS>:<PORT>
When we hit the ip address and port with netcat, we got a base64 encoded string back. If we waited too long, the connection would close. However, if we quickly decoded the string and pasted it in the connection, we would get a prompt saying that we were correct, followed by a morse code string.
nc <IP ADDRESS> <PORT>
We realized that there were only four types of string the connection sent back: base64, morse code, binary, and hex, in that order.
Base64 decoding is fairly straightforward in ruby.
Base64.decode64(string)
To convert the morse code, we wrote a simple script that split the data at ‘ ‘ and converted the data to an ascii character.
morse_code.split(' ').map { |letter| morse_dictionary[letter] }.join('')
For the last two types, we used ruby’s pack
method to convert the binary and hex strings into human-readable format.
[binary_data].pack("B*")
...
[hex.tr(' ', '')].pack('H*')
Last, we created a simple loop that requested bytes from the socket, decoded the data based on the question number (we kept track of this as part of the script), and sent the answer back to the socket.
loop do
response = socket.recv(1000)
question = response.split("\n")[0]
answer = send("question_#{ question_number % 4 }", question)
question_number += 1
socket.write(answer + "\n")
end
In our actual implementation, we used “puts” to print the response from the socket once the question number was greater than 50. This way, we could keep our program relatively fast (we wanted to finish before the connection closed) but still get the flag once we reached the end.
require 'socket'
require 'base64'
socket = TCPSocket.new('172.31.2.59', 51966)
socket.recv(1000)
question_number = 0
def question_0(question)
Base64.decode64(question)
end
def question_1(morse_code)
morse_dict = {".-"=>"a", "-..."=>"b", "-.-."=>"c", "-.."=>"d", "."=>"e", "..-."=>"f", "--."=>"g", "...."=>"h", ".."=>"i", ".---"=>"j", "-.-"=>"k", ".-.."=>"l", "--"=>"m", "-."=>"n", "---"=>"o", ".--."=>"p", "--.-"=>"q", ".-."=>"r", "..."=>"s", "-"=>"t", "..-"=>"u", "...-"=>"v", ".--"=>"w", "-..-"=>"x", "-.--"=>"y", "--.."=>"z", " "=>" ", ".----"=>"1", "..---"=>"2", "...--"=>"3", "....-"=>"4", "....."=>"5", "-...."=>"6", "--..."=>"7", "---.."=>"8", "----."=>"9", "-----"=>"0"}
letters = morse_code.split(' ')
letters = letters.map do |letter|
morse_dict[letter]
end
letters.join('').upcase
end
def question_2(question)
[question].pack("B*")
end
def question_3(hex)
[hex.tr(' ', '')].pack('H*')
end
loop do
response = socket.recv(1000)
question = response.split("\n")[0]
answer = send("question_#{ question_number % 4 }", question)
question_number += 1
socket.write(answer + "\n")
end
Def Con 2018 - OpenCTF - Aug 12, 2018