02 December 2015

49 Shades of Grey - 125

We only have 49 shades of gray D:

#000000 to #f5f5f5... there's one shade missing! Find the hex value of the missing shade. Pound sign optional.

This is one of my personal favorites from the CTF, and I'm not entirely sure why. Regardless, all it takes is a little coding, pattern-finding, and logic.

The way I approached the problem was to first println every single pixel (in hexadecimal) in the image. After receiving a massive amount of text (I'll spare you the behemoth), I quickly scanned through all the values and noticed that quite a few of them repeated.

I decided that I'd remove any duplicates from the list, thus considerably narrowing down the previous amount of hexadecimals. Here's the list:

#dcdcdc #cdcdcd #bebebe #919191 #4b4b4b #d2d2d2 #c3c3c3
#414141 #191919 #f5f5f5 #141414 #828282 #646464 #a5a5a5
#0a0a0a #6e6e6e #969696 #5a5a5a #696969 #737373 #464646
#373737 #a0a0a0 #f0f0f0 #c8c8c8 #d7d7d7 #3c3c3c #ebebeb
#7d7d7d #282828 #787878 #aaaaaa #000000 #1e1e1e #8c8c8c
#323232 #232323 #e6e6e6 #e1e1e1 #b9b9b9 #9b9b9b #b4b4b4
#5f5f5f #878787 #afafaf #050505 #2d2d2d #555555 #0f0f0f

Interestingly, the amount of pixels above is equal to 49, just like in the problem title. Also, all those pixels are shades of grey, amounting to 49 shades of grey, implying that we're getting closer to the flag (as 50th shade of grey, aka the missing shade, is the flag).

One of the first things I noticed was the pattern/correlation between each hexadecimal value. It was as though every value had its reverse in its list (with the exception of hexadecimal values made up of one letter/number).

e.g. #414141 and #141414 were on the list, #0a0a0a and #a0a0a0, #696969 and #969696, etc.

I decided to remove any values whose reverse was on that list, along with any values whose hexadecimal value was made up of one letter or number (e.g. #000000, #aaaaaa, etc.).

After doing so, I was left with #050505 and #afafaf

At that point, it was clear to me that their reverse was the missing shade (and so the flag), but only one of the reverse values worked, rather than both.

It seemed strange that I was given two answers, but then I remember back to the question: the color range was from #000000 to #f5f5f5.

The reverse of #afafaf is #fafafa, which is not in the range between #000000 and #f5f5f5, eliminating that as the choice, hence leaving the only choice (and correct answer) to be #505050.

For reference, the code I used to solve the problem is below; it's written in Java.

 import java.io.*;  
 import java.util.*;  
 import javax.imageio.ImageIO;  
 import java.awt.image.BufferedImage;  
 public class GetPixelColor {  
      /**@param hex  
       * @return boolean (true or false)  
       * This method is used to remove any hexadecimals composed of the same letter  
       * e.g. #000000, #aaaaaa, #cccccc, etc. */  
      public static boolean sameLetter(String hex) {  
           String nuHex = hex.replace("#", "");  
           char[] lets = nuHex.toCharArray();  
           if(lets.length == 6) {  
                if((lets[0] == lets[1]) && (lets[1] == lets[2]) && (lets[2] == lets[3]) && (lets[3] == lets[4]) && (lets[4] == lets[5])) {  
                     return true;  
           return false;  
      /**@param hex  
       * @return The reversed version of hex  
       * This method is necessary to determine which hexadecimal values to remove, thus ultimately  
       * narrowing down the answers, as it returns the reversed vesion of the parameter  
       * e.g. "#ababab" yields "#bababa" */  
      public static String reverseHex(String hex) {  
           String nuHex = hex.replace("#", "");  
           String kek = new StringBuilder(nuHex).reverse().toString();  
           return "#" + kek;  
      public static void main(String args[]) throws IOException {  
           /** Get all the individual pixels in the image and put it into an array */  
           File file = new File(shades.png);  
           BufferedImage image = ImageIO.read(file);  
           int a = 0;  
           String[] allHex = new String[image.getWidth() * image.getHeight()];  
           for(int x = 0; x < image.getWidth(); x++) {  
                for(int y = 0; y < image.getHeight(); y++) {  
                     int clr = image.getRGB(x, y);  
                     int red = (clr & 0x00ff0000) >> 16;  
                     int green = (clr & 0x0000ff00) >> 8;  
                     int blue = (clr & 0x000000ff);  
                     String hex = String.format("#%02x%02x%02x", red, green, blue); // RBG -> Hexadecimal  
                     allHex[a] = hex;  
           /** Converted from Set to ArrayList so that I could get rid of any duplicate values */  
           Set<String> mySet = new HashSet<String>(Arrays.asList(allHex));  
           ArrayList<String> hexa = new ArrayList<String>();  
           for(String hex : mySet) {  
           /** We compare every String in the ArrayList with the reverse of the rest of the Strings.  
            * If the reverse of the String being compared is equal to other String, we replace its  
            * position with a blank character; if we were to merely remove the Strings, it'd  
            * jeopordize the entire loop */  
           for(int j = 0; j < hexa.size(); j++) {  
                for(int k = j + 1; k < hexa.size(); k++) {  
                     if(hexa.get(j).equals(reverseHex(hexa.get(k)))) {  
                          hexa.set(j, "");  
                          hexa.set(k, "");  
           /** Narrowing it down even more, now we're just removing any of the hexadecimals  
            * that are made up of the same letter.  
            * e.g. #000000, etc.  
            * The reason why we want to remove those hexs is because they don't fit the general  
            * reverse pattern we've noticed. The reverse of #000000 = #000000, thus eliminating  
            * that as an answer, hence the need to get rid of them */  
           for(int m = 0; m < hexa.size(); m++) {  
                if(sameLetter(hexa.get(m)) == true) {  
                     hexa.set(m, "");  
           /** Removes all the (many) blank items from the ArrayList */  
           while(hexa.contains("")) {  
           /** The rest is just extra code intended to be for your convenience */  
           String[] rev = new String[hexa.size()];  
           int z = 0;  
           for(String sup : hexa) {  
                rev[z] = reverseHex(sup);  
           System.out.println("Original Remaining Hexadecimal(s): " + hexa);  
           System.out.println("Reversed Remaining Hexadecimal(s): " + Arrays.toString(rev));  

Flag: #505050

easyCTF 2015

I'll be posting a couple of write-ups for easyCTF 2015. Stay tuned, I suppose.

13 November 2014

Potentially Hidden Password - 100

This Daedalus Corp. website loads images in a rather odd way... [Source Code]

It seems like a normal page, and there appears to be nothing special within its source code. I decided to view one of the images (individually) in general in hopes of finding something there.

There's nothing special about the image itself, but the URL seemed to stick out to me the most.


Specifically that last part (/file_loader.php?file=zone1.jpg).

I decided to do a test to confirm my suspicions. I replaced 'zone1' in the link with 'zone2'. Sure enough, as soon as I hit 'Enter', the second image popped up. Now I knew that this file loader was getting the images from a directory somewhere... perhaps where the flag is too?

I downloaded the Source Code given at the beginning of the problem and read through it.

Seemed like simple HTML and CSS, along with a little PHP. The part that I focused on the most was the PHP code, since it contained the flag file.

Here is the PHP implemented in the source code:

         $config_file = fopen("/resources/config/admin_mode.config", "r");  
         if (fgets($config_file) === "true") {  
          $flag_file = fopen("/resources/secrets/flag", "r");  
          echo fgets($flag_file);  

Based off what I could tell, the flag file was located within /resources/secrets/flag

So naturally, I pasted that text into the original link, so that it looked something akin to http://web2014.picoctf.com/potentially-hidden-password-3878213/file_loader.php?file=resources/secrets/flag

That only led me to this page, but that doesn't mean that my efforts were unfruitful.

I've found the directory that the flag should be in! It should be located within /resources/. Since the file only looks within /resources/files, would there be a way to go up to /resources/ and into other folders rather than only look within the files folder? Yep, there is.

To account for that, I should now add ../ (a directory traversal) before what I am about to type, since it, "tells the browser to move one level back toward the root directory before looking for the path to the file," (RootsWeb). Basically, it means to go up a path/folder.

I have to add ../ since the flag is within /resources/, but it isn't within /resources/files/. It's within /resources/secrets/flag.

 So now that we're within the /resources/ folder, we'll have to enter the /secrets/ folder and then from there get the flag from /flag. This part is relatively simple.

Adding secrets/flag after the ../ should do the trick since we'll be entering the /resources/secrets/flag folder (which is clearly where the flag file is located, according to the PHP).

The full link should look like: http://web2014.picoctf.com/potentially-hidden-password-3878213/file_loader.php?file=../secrets/flag

As expected, going to that link should get you to this page:

The only sentence (and flag) in the page is: i_like_being_included

* Unrelated note: Potentially Hidden Password... I bet that stands for PHP, doesn't it?

10 November 2014

This is the Endian - 40

This is the end! Solving this challenge will help you defeat Daedalus's cyborg. You can find more information about endianness and the problem here. The flag is the smallest possible program input that causes the program to print "Access Granted".
When I opened the page, I read over the problem and information. The input was supposed to be entered as a little-endian, meaning that the order of the addresses are reversed (e.g. "12345678" becomes "78563412").

The question wants answer[0] to be equal to 0x52657663 and answer[1] to be equal to 0x30646521. Both have to be equal to those values respectively, else it won't work.

The first thing to be noted is that the '0x' in front of the address should be removed when writing it in the input, so it should be 52657663 and 30646521 instead.

Now, back onto the topic of little-endians and reversed order, when you put in the correct input, the Data Preview box should look like this:

The thing is that if you try input the exact hex values for both answers, it won't even fit. That's because you're not supposed to input the hex value, you're supposed to input an ASCII character.

Let me try to simplify this... I'll start with answer[0]'s value... it's supposed to equal 52657663. I'm going to split the numbers in that value into groups of twos, so it'll now look like this: 52 65 76 63

Because it's a little-endian program, you'd have to enter the ASCII equivalent of 63 76 65 52. Fortunately, rather than Google 'hex to ascii' for a converter, you can simply write \x followed by the two-digit number, and it'll convert it to ASCII for you.

So \x63 would yield c, \x76 would yield v, and so on.

So answer[0]'s input value would be cveR

...But I still needed to input answer[1] as well.

Using the same method, I divided 30646521 into parts: 30 64 65 21. Then I reversed those parts: 21 65 64 30.

I entered \x21 \x65 \x64 \x30, which displayed !ed0

So, in sum, I basically just inputted \x63 \x76 \x65 \x52 \x21 \x65 \x64 \x30 and it was written as cveR!ed0

When I pressed 'Input' and ran the program, it displayed 'Input Granted!', meaning that the input was correct. Because it was correct, cveR!ed0 is the flag.

Edit: This problem inspired me to write a Java program that converts hexadecimal/byte to Little-Endian and Big-Endian. You can see it on my GitHub here, if you'd like, especially if you're having trouble inputting the address as a Little-Endian, or perhaps for future reference.

The Valley of Fear - 20

The hard drive may be corrupted, but you were able to recover a small chunk of text. Scribbled on the back of the hard drive is a set of mysterious numbers. Can you discover the meaning behind these numbers? (1, 9, 4) (4, 2, 8) (4, 8, 3) (7, 1, 5) (8, 10, 1)
I'll admit, I was a bit confused at first too, but I realised that the numbers did have to do with the text.

Each set of numbers, written as (x, y, z) represented something in the text file.

x = The paragraph number
y = The sentence/line number
z = The word number (in the sentence)

And don't worry, you don't have to worry about OBOB-ing (a.k.a. starting with 0 rather than 1).

... Alright, so I know that explanation might not have made a lot of sense, but I'll elaborate by giving an example...

For the first set (1, 9, 4) I'm going to go open the text file. I located the first paragraph (1), which I've highlighted:

Then I located the ninth sentence (9):

And, finally, the fourth word (4) of that particular sentence:

So the first word out of the five-word clue is 'the'. It might not have seemed like it initially, but after the second word was discovered, it became apparent that it would lead to the flag.

When continuing on with this method, the following sentence was spelled out: the flag is Ceremonial plates

The flag is, therefore, Ceremonial plates

Droid App - 80

An Android application was released for the toaster bots, but it seems like this one is some sort of debug version. Can you discover the presence of any debug information being stored, so we can plug this?
You can download the apk here.
The only thing needed is an apk decompiler and some programming knowledge.

I used decompileandroid to decompile the .apk package (after downloading it).

When the decompiling was complete, I downloaded the full contents of the APK.

I opened up the folder after it was downloaded (it was named 'source'), and, quite primitively, I know, searched through each subfolder, opening each and every file within it. Needless to say, the flag was located within one of the .java files in the 'picoapp' folder.

Its path is: sourcesrcpicoapp453picoctfcompicoapp

When I opened ToasterActivity.java, the flag immediately popped out at me.

The String created out of a char array in the ToasterActivity() constructor had 'flag' as its first four chars.

Being the lazy person I am, rather than manually remove all the commas, spaces, and apostrophes, I quickly wrote a simple Java program to do that for me because, you know, #yolo

However, there is a simpler way of printing out the flag: println'ing (printing) the variable containing the flag. The program is here:

 public class printFlag {  
      public static void main(String[] args) {  
           String entireFlag = new String(new char[] {'f', 'l', 'a', 'g', ' ',  
                     'i', 's', ':', ' ', 'w', 'h', 'a', 't',  
                     '_', 'd', 'o', 'e', 's', '_', 't', 'h',  
                     'e', '_', 'l', 'o', 'g', 'c', 'a', 't',  
                     '_', 's', 'a', 'y'});  

And, for your convenience, the Java program I'd initially written is also here:

 public class RemoveNonAlphaChars {  
      public static void main(String[] args) {  
           String entireFlag = ""  
                     + "'f', 'l', 'a', 'g', ' ', 'i', 's', ':', ' '"  
                     + ", "  
                     + "'w', "  
       + "'h', 'a', 't', '_', 'd', 'o', 'e', 's', '_', 't', "  
       + "'h', 'e',"  
       + "'_', 'l', 'o', 'g', 'c', 'a', 't', '_', "  
       + "'s', 'a', 'y'";  
           String noApos = entireFlag.replaceAll("'", "");  
           String noCom = noApos.replaceAll(",", "");  
           String flag = noCom.substring(noCom.indexOf(":") + 1, noCom.length());  
           String noSpace = flag.replaceAll(" ", "");  

Regardless of the method used, the flag is what_does_the_logcat_say

09 November 2014

Delicious! - 60

You have found the administrative control panel for the Daedalus Coperation Website: https://web2014.picoctf.com/delicious-5850932/login.php. Unfortunately, it requires that you be logged in. Can you find a way to convince the web site that you are, in fact, logged in?
This problem requires a cookie editor extension, and the best browser to solve this problem with would be Chrome, since it has good cookie editing extensions. I installed two cookie editing extensions for Chrome: (1) EditThisCookie and (2) Cookie Inspector.

You don't have to install both extensions, or even those extensions in specific, but I still did because of reasons.

After installing the extensions, open the administrative control panel link. It says that I'm not logged in because there are too many people that are logged in.

Now's the part where the cookie editors come in. Right-click and press 'Inspect Element'. Click on the 'EditThisCookie' pane. There should be 9 columns, and under the 'Value' column it should have the number 67.

Click on it and enter any number. When you're finished, refresh the page and keep entering different numbers until you reach this page:

The number I put in was '21'. The flag is session_cookies_are_the_most_delicious