Challenge info
It's pretty obvious that this is a script written in the python interpreter's interactive mode.
Here is the commented code for better explanation:
>>> import base64 #importing base64 library >>> msg = msg + " "+ base64.b64encode(data) #encoding "data" in base64 #then adding it to local variable "msg" >>> y = [] #creating an empty list "y" >>> for i in range(0,len(msg)): #For loop y.append(ord(msg[i]) + i) # getting the ordinal (Unicode value) of each character of "msg" # then adding the loop's iterator "i" to it # then append the result to the list "y" created in line 4 >>> y = y[::-1] #reversing the list "y" >>> y #printing "y" in the interpreter [249, 264, 274, 285, 287, 256, 233, 279, 289, 245, 245, 277, 288, 241, 241, 273, 280, 271, 241, 242, 217, 224, 253, 266, 267, 215, 249, 250, 266, 225, 279, 247, 278, 204, 204, 241, 200, 237, 259, 248, 254, 233, 196, 244, 247, 242, 251, 239, 252, 243, 188, 236, 248, 255, 243, 222, 181, 197, 202, 202, 250, 235, 197, 198, 232, 201, 194, 220, 232, 239, 168, 206, 224, 181, 197, 214, 217, 177, 177, 199, 216, 189, 157, 204, 222, 207, 173, 174, 221, 185, 148, 194, 214, 169, 204, 174, 195, 172, 139, 187, 162, 153, 207, 174, 196, 203, 191, 170, 129, 145, 148, 150, 195, 149, 125, 171, 140, 137, 153, 151, 100, 164, 182, 162, 164, 95, 165, 171, 165, 178, 169, 165, 164, 166, 156, 85, 153, 155, 166, 81, 149, 165, 143, 149, 76, 144, 129, 73, 154, 140, 145, 136, 133, 139, 66, 130, 64, 132, 144, 126, 60, 144, 137, 146, 56, 139, 119, 125, 136, 51, 137, 128, 126, 122, 46, 86, 44, 57, 124, 110, 111, 117, 103, 119, 120, 86, 34, 106, 72]
And since we want to reverse what the author did, so we'll start from the bottom up.
This is what the author did (in order):
- Encode "data" in base64.
- Concatenate (add) "data" to "msg".
- For each character of that encoded "data", grab the ordinal (unicode value).
- Add "i" to that unicode value.
- Add each value to our list
- Reverse the list
So, we'll do the inverse of each step, starting from step 5 to step 1. I'll use python (Python 3.6), but you could use any language you like.
This is our plan:
- Reverse the list
- Take each value from the list
- Subtract "i" (iterator) from each character
- Then grab the character equivalent to the ordinal (unicode value) we have after subtraction.
- After finishing all the characters, read the message to find out what it says, and to know where the encoded base64 data is.
- Decode the "data" in base64.
Lets go.
.
1. Reverse the list:
There are many ways to reverse a list in python. We could just use the same one that the author used in the challenge's script.
y = y[::-1]
Here are 2 other ways to do it in python.
2. Take each character from the list (i.e. a For loop)
I used a for-loop, similar to the one in the challenge's script:
y = [249, 264, 274, 285, 287, 256, 233, 279, 289, 245, 245, 277, 288, 241, 241, 273, 280, 271, 241, 242, 217, 224, 253, 266, 267, 215, 249, 250, 266, 225, 279, 247, 278, 204, 204, 241, 200, 237, 259, 248, 254, 233, 196, 244, 247, 242, 251, 239, 252, 243, 188, 236, 248, 255, 243, 222, 181, 197, 202, 202, 250, 235, 197, 198, 232, 201, 194, 220, 232, 239, 168, 206, 224, 181, 197, 214, 217, 177, 177, 199, 216, 189, 157, 204, 222, 207, 173, 174, 221, 185, 148, 194, 214, 169, 204, 174, 195, 172, 139, 187, 162, 153, 207, 174, 196, 203, 191, 170, 129, 145, 148, 150, 195, 149, 125, 171, 140, 137, 153, 151, 100, 164, 182, 162, 164, 95, 165, 171, 165, 178, 169, 165, 164, 166, 156, 85, 153, 155, 166, 81, 149, 165, 143, 149, 76, 144, 129, 73, 154, 140, 145, 136, 133, 139, 66, 130, 64, 132, 144, 126, 60, 144, 137, 146, 56, 139, 119, 125, 136, 51, 137, 128, 126, 122, 46, 86, 44, 57, 124, 110, 111, 117, 103, 119, 120, 86, 34, 106, 72] #the message in the challenge y = y[::-1] #reversing the list for i in range(0,len(y)): value = y[i] print(value) #printing each value just for fun
3. Subtract "i" (iterator) from each character
We should subtract "i", because the user added "i" to each value. This "i" is based on the loop's current position.
y = [....] #the message in the challenge y = y[::-1] #reversing the list for i in range(0,len(y)): value = y[i] #print(value) #printing each value just for fun ordinal = y[i] - i; #subtracted "i" from each value in our list
4. Grab the character which is equivalent to the ordinal
Now we have a number. How did the author calculate this number?
He used python's built-in "ord( )" function to calculate the unicode value of each character from the original message.
What is the inverse of that?
Python's built-in "chr( )" function. It returns to us the original character from the unicode value we supply to it.
So our code now will look like this:
y = [....] #the message in the challenge y = y[::-1] #reversing the list for i in range(0,len(y)): value = y[i] print(value) #printing each value just for fun ordinal = y[i] - i; #subtracted "i" from each value in our list original_character = chr(ordinal) #return the original character from the unicode value
We should store the result characters in a string, so that we could print out and read the message.
So our code is:
y = [....] #the message in the challenge y = y[::-1] #reversing the list msg = "" # an empty string. we will add our characters to it in the loop for i in range(0,len(y)): value = y[i] print(value) #printing each value just for fun ordinal = y[i] - i; #subtracted "i" from each value in our list original_character = chr(ordinal) #return the original character from the unicode value msg += original_character
5. Read the message
We just use the "print( )" function:
print(msg)
This is what I got:
It's obvious that the highlighted part below is the base64-encoded "data". Lets decode it.
6. Decode "data" in base64
We could just use an online base64 decoder. But why not do it in python?
Python has a built-in library called "base64". Inside it, there is a function called "b64decode". Lets use it.
import base64 #must import the base64 library to use it y = [...] #the message in the challenge y = y[::-1] msg = "" # an empty string. we will add our characters to it in the loop for i in range(0,len(y)): value = y[i] ordinal = y[i] - i; #subtracted "i" from each value in our list original_character = chr(ordinal) #return the original character from the unicode value msg += original_character #print(msg) #printing our msg #Hi Stranger. I know that you are a hacker We have the following data RSBDb3JwIFB1YmxpYyBJb1QgQnJva2VyIGhvc3RlZCBieSBlY2xpcHNlIGlzIHB1Ymxpc2hpbmcgc2VjcmV0X21zZyBjYW4geW91IGdldCBpdCBmb3IgdXM= base64_data = "RSBDb3JwIFB1YmxpYyBJb1QgQnJva2VyIGhvc3RlZCBieSBlY2xpcHNlIGlzIHB1Ymxpc2hpbmcgc2VjcmV0X21zZyBjYW4geW91IGdldCBpdCBmb3IgdXM=" data = base64.b64decode(base64_data) print(data)
This is the "data" printed:
It says that an "IoT Broker" hosted at "eclipse" is publishing a "secret_msg". Ok, it appreas that we've finished one part of this challenge. Lets continue.
.
Second part of the challenge
"What is an IOT broker?" you may ask. A quick google search will give you this result:
One of the messaging protocols used by "message brokers" is MQTT.
MQTT stands for MQ Telemetry Transport. It is a publish/subscribe, extremely simple and lightweight messaging protocol, designed for constrained devices and low-bandwidth
And guess what website offers a free MQTT server (broker) you can play with? Eclipse.org ?
Lets download any free MQTT client, and connect to eclipse's MQTT server. I used MQTT.fx .
After download, install, and runnning, this is what we get:
Configure it to connect to Eclipse's server (broker) like this:
Then connect. After the connection is successful, you can subscribe to any topic to receive the messages that are transmitted for this topic.
I subscribed to the following: "E Corp", "E-corp", and "secret_msg". Remember?
'E Corp Public IoT Broker hosted by eclipse is publishing secret_msg can you get it for us'
And after waiting a couple of seconds, I got this message.
We could conclude that it is encoded in base64 because we see the characteristic padding (the two equal signs "==" at the end). Lets decode it online.
Lets wait 2 minutes to get the flag ?
This is what I got after waiting.. 30 more messages..
One of them is this:
And the rest is just numbers:
They're probably unicode values like we saw earlier.
Lets copy the numbers manually from those 29 messages, and then put them in a list:
secret_msg = [83,97,108,117,115,108,97,98,123,49,95,83,116,48,108,51,95,66,114,48,107,51,114,95,70,108,52,103,125]
Then loop through this list, decode each character, add them all together and print the decoded message:
secret_msg = [83,97,108,117,115,108,97,98,123,49,95,83,116,48,108,51,95,66,114,48,107,51,114,95,70,108,52,103,125] secret_msg_decoded = "" for i in secret_msg: decoded_character = chr(i) secret_msg_decoded += decoded_character print(secret_msg_decoded)
And we got our flag:
.
I wanted to show you how to automate the connection to the MQTT-broker using python. It's really easy and straight forward, and we wont have to copy the unicode values manually... but that'll be later in another post.
Thanks for reading.