I haven’t done much work with Ruby, but this little challenge from the Internetwache CTF looked interesting.
Challenge:
Ruby’s count (exp50)
Description: Hi, my name is Ruby. I like converting characters into ascii values and then calculating the sum.
Service: 188.166.133.53:12037
Solution
The first thing to do was to poke the service using netcat:
> nc 188.166.133.53 12037 Let me count the ascii values of 10 characters: > 123 WRONG!!!! Only 10 characters matching /^[a-f]{10}$/ !
So, my first input of 123 failed, but the RegEx displayed in the error message tells us that the expected input is 10 characters in the range ‘a’ through ‘f’. Lets try again.
> nc 188.166.133.53 12037 Let me count the ascii values of 10 characters: > abcdefabcd Sum is: 991 That's not enough (991 < 1020) :(
Better, the code seems to be adding up the ACSII values of the input to generate the test value. Let’s check that with a simple string of 10 ‘a’ characters. ‘a’ is ASCII 97, so 10 * 97 should be 970:
> nc 188.166.133.53 12037 Let me count the ascii values of 10 characters: > aaaaaaaaaa Sum is: 970 That's not enough (970 < 1020) :(
Great. So, the biggest value character we can use is ‘f’ (ACSII 102):
> nc 188.166.133.53 12037 Let me count the ascii values of 10 characters: > ffffffffff Sum is: 1020 That's not enough (1020 < 1020) :(
OK. That’s interesting. We can’t generate a higher number, and we can’t send any more characters. Any attempt to insert a sly non-printing char or other underhand extra characters is caught by the RegEx.
Help me Google, you’re my only hope!
I quickly found this StackOverflow question about Ruby RegEx:
http://stackoverflow.com/questions/577653/difference-between-a-z-and-in-ruby-regular-expressions
It seems that Ruby RegEx with ^ and $ fails to handle newlines properly, let’s try that. I can’t work out how to pipe an arbitrary string into netcat, so Python will have to do it for me:
import sys from telnetlib import Telnet tn = Telnet('188.166.133.53', 12037) sys.stdout.write(tn.read_until('words we never see', 0.5)) tn.write('ffffffffff\nf') sys.stdout.write(tn.read_until('words we never see', 0.5)) tn.close()
We’re squeezing another ‘f’ in after the newline. Running the code gives this result:
Let me count the ascii values of 10 characters: Sum is: 1132 IW{RUBY_R3G3X_F41L}
PING! 50 points and my first Ruby challenge completed, even if I did have to use Python to do it.