Ringzer0Ctf back again

Hello world!

It’s been about three years since last and I’ve been doing a lot of things but blogging is not one of them. I’ve been looking at the Ringzer0 CTF again and will post some write ups but not all as it is good practice to do technical writing and to keep solving puzzles.

This week I’ve done the I saw a little elf challenge which I might post at a later time and just now I did the ASCII art challenge. We are presented with the following, A list of numbers written out with whitespace and x’es that need to be recognized and send back in the form of a string or a number. At first the approach was not obvious to me but what I decided to try was to treat it as patterns that need matching.

You have 2 seconds to send the number you see Send the answer back using https://ringzer0ctf.com/challenges/119/[number]

—– BEGIN MESSAGE —–

 xxx 
x   x
x   x
x   x
 xxx 

 xx  
x x  
  x  
  x  
xxxxx

 xxx 
x   x
  xx 
x   x
 xxx 

xxxxx
x    
 xxxx
    x
xxxxx
 xxx 
x   x
  xx 
x   x
 xxx 

 xx  
x x  
  x  
  x  
xxxxx

xxxxx
x    
 xxxx
    x
xxxxx
 xxx 
x   x 
  xx 
 x   
xxxxx

xxxxx
x    
 xxxx
    x
xxxxx
 xxx 
x   x
x   x
x   x
 xxx 

—– END MESSAGE —–

There is a repeating pattern to each letter so step one is to define what a character is. And that is a bunch of whitespace and X’s arranged in five lines with some differing spacing in between. Refreshing the challenge a number of times gives six different characters that we need to recognize 1,2,3(or 8),4,5 and 0. The ‘3’ is difficult to separate from an eight given the character width of whitespace but is clearly a three if you replace the characters with a ‘.’ for example.

Solving the challenge

In order to implement pattern matching we need to prepare the input. As we get the challenge is encoded in HTML with all what it entails. All can easily be implemented with a simple shell script.

curl -sb ../../cookies.txt https://ringzer0ctf.com/challenges/119 | grep -A1 “BEGIN” | tail -1 > msg.txt

Replacing ‘<br />’ line breaks and the whitespace with periods and some further cleaning up we can get a nice list of characters to work with with a new character starting each fifth line. This can easily be done with some ‘sed’. In the end there is an empty line that I’d like to get rid of in the beginning which ‘tail -c +2’ takes care of

xes=$(sed -re 's/(<br \/>)+/\n/g' < msg.txt | sed -re 's/&nbsp;/\./g' | \            
  sed -re 's/[\t\s]*//g' | tail -c +2)

Next we just have to take five lines at a time and match the string to a table. Matching the characters can be done like this:

match () {                                                                              
  if [ "$*" = ".xx.. x.x.. ..x.. ..x.. xxxxx" ]; then                                   
    echo "1"                                                                            
  elif [ "$*" = ".xxx. x...x. ..xx. .x... xxxxx" ]; then                                
    echo "2"                                                                            
  elif [ "$*" = ".xxx. x...x ..xx. x...x .xxx." ]; then                                 
    echo "3"                                                                            
  elif [ "$*" = ".x...x x....x .xxxxx .....x ....x" ]; then                             
    echo "4"                                                                            
  elif [ "$*" = "xxxxx x.... .xxxx ....x xxxxx" ]; then                                 
    echo "5"                                                                            
  elif [ "$*" = ".xxx. x...x x...x x...x .xxx." ]; then                                 
    echo "0"                                                                            
  else                                                                                  
    echo " "                                                                            
  fi                                                                                    
}

And iterating the characters is easily done with a for loop and head | tail

answer=""                                                                               
for char in {5..50..5}; do                                                              
  c=$(echo "$xes" | head -$char | tail -5)                                              
  d=$(match $c)                                                                         
  answer="${answer}${d}"                                                                
done 

And voila! We can easily parse the challenge and submit our answer with curl back again!

curl -sb ../../cookies.txt "https://ringzer0ctf.com/challenges/119/$answer" | grep FLAG

If I get more free time I might start doing some more technical write ups or blogs about BSD or embedded engineering but time is sparse right now.

/Linuxxon

Posted in Uncategorized | Tagged , , | Leave a comment

I hate mathematics (The challenge – not the science)

Easy peasy, we just have to convert the second and third arguments to decimal representation and pass it along to something that can perform a sum for us. For this application ‘bc’ will do the job swimmingly for us! Only one problem though, sadly we can’t really continue with the straight through pipeline of almost only native tools, well maybe we could come up with some fancy script that could do the conversion for us (awk feels like my first candidate for a try here) but alas I don’t really feel that’s the best use of my time. We can edit the program we used in the last challenge to convert any string of binary values to ascii easily to produce decmial representation of whatever base we throw at it. For this challenge we’ll need a converter for hex representation to decimal and one for binary to decimal.

The challenge looks like this:

9332 + 0x1a77 - 10010110011 = ? 

To fetch and clean up the message we can run the following command, the only difference is the regular expression that we use to run sed. It removes the leading tab character and removes everything between ‘=’ and end of the line, inclusively. We could ask sed to remove the operators as well if we’d like but nah, who cares (:

#!/bin/sh                                                                          
CHALLENGE=$(curl -sb ../../cookies.txt https://ringzer0ctf.com/challenges/32 | \   
  grep -A1 'BEGIN MESSAGE' | tail -1 | sed -re 's/\t|=.*$//g') 

The “real” task or “challenge” here is to mangle the input into something we can put into bc. For the last challenge we used a tool called ‘cut’ which will do the job for us, we just need call it three times and store the values somehow. For this, a shell script comes in handy and we can split up our “nice” pipeline within it.

FIRST=$( printf "$CHALLENGE" | cut -d ' ' -f 1)                                    
SECOND=$(printf "$CHALLENGE" | cut -d ' ' -f 3)                                    
THIRD=$( printf "$CHALLENGE" | cut -d ' ' -f 5)

The operators do seem to be static in the way that the first operation is always an addition and the second is always a subtraction from what I can see updating the challenge a couple of times. But parsing the operators to be variable isn’t that much of a hassle, just a couple of more cuts!

OP1=$(printf "$CHALLENGE" | cut -d ' ' -f 2)                                       
OP2=$(printf "$CHALLENGE" | cut -d ' ' -f 4) 

To mangle the representation of the second and third argument all we have to do is to pass them to our fancy conversion programs

SECOND=$(printf $SECOND | ./hex2dec)                                               
THIRD=$( printf $THIRD  | ./bin2dec)  

Now we just ask ‘bc’ to do the work for us and then we’re ready to submit our solution!

SOLUTION=$(printf "$FIRST $OP1 $SECOND $OP2 $THIRD" | bc)

I’ll paste the full script below and upload the conversion programs if you’re having difficulties converting the one from the last post. Cheers

#!/bin/sh                                                                               
                                                                                        
CHALLENGE=$(curl -sb ../../cookies.txt https://ringzer0ctf.com/challenges/32 | \        
  grep -A1 'BEGIN MESSAGE' | tail -1 | sed -re 's/  |=.*$//g')                          
                                                                                        
FIRST=$( printf "$CHALLENGE" | cut -d ' ' -f 1)                                                                                          
SECOND=$(printf "$CHALLENGE" | cut -d ' ' -f 3)                                         
THIRD=$( printf "$CHALLENGE" | cut -d ' ' -f 5)                                         
                                                                                        
OP1=$(printf "$CHALLENGE" | cut -d ' ' -f 2)                                            
OP2=$(printf "$CHALLENGE" | cut -d ' ' -f 4)                                            
                                                                                        
SECOND=$(printf $SECOND | ./hex2dec)                                                    
THIRD=$( printf $THIRD  | ./bin2dec)                                                    
                                                                                        
SOLUTION=$(echo "$FIRST $OP1 $SECOND $OP2 $THIRD" | bc)                                 
                                                                                        
# Submit it                                                                             
curl -sb ../../cookies.txt https://ringzer0ctf.com/challenges/32/$SOLUTION | \          
  grep -Po 'FLAG-\w+'
Posted in CTF, Hacking | Tagged , , | Leave a comment

Hash me again

This challenge is quite similar to the last one. So I’ll keep it short, the challenge is almost exactly the same as the last one. The only difference in the instructions is that the message to digest is a string of zeros and ones. The first thing to try i s running the last solution:

curl -sb ../../cookies.txt https://ringzer0ctf.com/challenges/13 | grep -P -A 1 'BEGIN MESSAGE' | tail -1 | sed -re 's/\t|<br \="">.*$//g' | head -c-1 | sha512sum | cut -d ' ' -f 1 | xargs -I {} curl -sb ../../cookies.txt https://ringzer0ctf.com/challenges/13/{} | grep -Po 'FLAG-\w+'$

But it doesn’t work… This can logically only be because of two reasons 1) Our assumption that the challenge is the same is wrong 2) Our nice looking but long pipeline is a bit too long and doesn’t finish within the timing requirements. By measuring the time taken to execute the whole chain of commands and trying to trim down on “unnecessary” flags on some commands I can state that the timing doesn’t seem to be the problem here so there is something wrong with how we have understood the challenge.

Measuring the length of the messages this time we can see that they’re constantly 8184 characters long – this is interesting, a power of two! The number of ones and zeros is evenly divisible by eight so if we were to group the characters by eight we would get bytes that could represent ascii text which could be what we’re supposed to digest. Other than that the message first has to be converted into ascii our pipeline from the last challenge will do the job, and being a pipeline it has the advantage of allowing us just to add another program to do just that in the right moment of processing! Pipes are wonderful!

Now, how would you go about converting a string of binary to ascii? I don’t know of a super simple program that can handle this for us sadly. But I do have a C-program I wrote for a class on software reliability that will come in handy. It’s no way near what I’d like it to be to show it really but it’s something I cobbled together to solve my problem then and it will solve our problem now. It works by two steps, gathering all the input and generating all the output, what would be great would be if it threaded and running the input and output in parallel but the sub-optimal design of my converter was enough to complete the challenge so that’s a project for another time!

The nice thing about the program is that the inputbuffer is handled and allocated in segments as more data comes in, not that great as it’s in no way parallelized, but by small adjustments it can handle near infinite (as infinite as your memory and max range of a long int) string representations of numbers in different bases. More things that could become a project another time 🙂

Well, well, I’ll go through the basics of the operating mechanics of the program so it’s available if you’d like to take a look or perhaps make it better than the enough it provides for us today!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define EXIT_SUCCESS 0
#define EXIT_MEMORY_ERROR 1
#define EXIT_READ_ERROR 2

#define BLOCK_SIZE 512
#define BASE 2

typedef char target_t;

int read_input(char **buffer_ptr)
{
  long num_blocks = 0;
  char *buf = malloc(BLOCK_SIZE);
  char *free_index = buf;
  int free_space;

  if (buf == NULL) {
    return EXIT_MEMORY_ERROR;
  } else {
    num_blocks++;
    free_space = BLOCK_SIZE;
  }

  while (fgets(free_index, 9 , stdin)) {
    int len = strlen(free_index);
    free_index += len;

    /* Separate ascii */
    if (len == 8) {
      *free_index = ' ';
      free_index++;
      len++;
    }

    /* If buffer was filled, extend it */
    if (len >= free_space-1) {
      int diff = free_index-buf;
      int new_size = BLOCK_SIZE*(num_blocks+1);
      buf = realloc(buf,new_size);
      if (buf == free_index-diff) {
        if (errno == ENOMEM) {
          return EXIT_MEMORY_ERROR;
        } else {
          /* Successfully extended buffer */
          free_space = buf+BLOCK_SIZE*num_blocks+1 - free_index;
        }
      } else {
        /* Update pointers as realloc moved stuff */
        free_index = buf+diff;
        free_space = buf+new_size - free_index;
      }
      num_blocks++;
    } else {
      free_space -= len;
    }
  }

  *buffer_ptr = buf;
  return 0;
}

int parse_input(char *buf, int base, target_t **array_ptr, long *array_len)
{
  target_t *array;
  target_t *array_index;
  char *startptr, *endptr;
  /* Worst case is all signle digit numbers so max amount of numbers is
   * strlen(buf) / 2 - probably alright to be pessimistic
   */
  array = malloc((strlen(buf)/2)*sizeof(target_t));
  if (array == NULL) {
    return EXIT_MEMORY_ERROR;
  }

  array_index = array;
  startptr = buf;
  while (1) {
    target_t val = strtol(startptr, &endptr, base);
    if (endptr == startptr || endptr == NULL) {   /* Reached end */
      break;
    } else {
      *(array_index++) = val;
      startptr = endptr;
    }
  }

  *array_ptr = array;
  *array_len = array_index - array;
  return 0;
}

int main(long argc, char* argv[])
{
  int i;
  long key;
  long retval;
  char *buf;
  target_t *array;
  long array_length;

  /* Read input */
  retval = read_input(&buf);

  if (retval == EXIT_MEMORY_ERROR) {
    fprintf(stderr, "Memory error, idc\n");
    return retval;
  }

  /* Parse input */
  retval = parse_input(buf, BASE, &array, &array_length);
  if (retval == EXIT_MEMORY_ERROR) {
    fprintf(stderr, "Memory error, idc\n");
    return retval;
  }
  free(buf);

  for (i = 0; i < array_length; i++) {
    printf("%c", array[i]);
  }

  return EXIT_SUCCESS;
}

If you’re on a linux system you can compile the program above by running the command below and putting it the pipeline before we perform the message digest!

gcc -o bin2ascii bin2ascii.c

Good luck!

Posted in CTF, Hacking | Leave a comment

The RingZer0 CTF Challenges

As this is my week off from work I though I would start, albeit slowly, with some capture the flag challenges. A few, or rather more than ten, years ago I hung around Hack This Site so rationally I went back but only to see that it hasn’t really been updated. This spring I spuriously made my way some of Over the wire challenges but now I looked around for something new. What I found was RingZer0 (https://ringzer0ctf.com) which has as of now 296 challenges and ~25k registered users.

Reasonably I started with the first challenge that comes up, a coding challenge called “Hash me if you can”, a reference to the movie “Catch me if you can” following the life and escapades of Frank Abignale who’s a social engineer and overall smart guy traversing life and the globe whilst keeping a step ahead of the FBI. Anyhow, the challenge promts you this text:

You have 2 seconds to hash this message using sha512 algorithm
Send the answer back using https://ringzer0ctf.com/challenges/13/[your_hash] 

and a message in the following format:

----- BEGIN MESSAGE -----
RVxzHYkAtMDZoK0PSQtwY9cn3BJAlN93zws7lDyEf1uuCk9k1tHPsJ2maCMmfLfF7yCj10N6S7rkiqv9J2P2CHfDaSPftUKrjdAa3e7LcoWkFhkfaZ8Cxd5xVLDfwexFhYFb2CN4QzfmHqrHfpaCt50fHtk3xHyFw3GowjjdJpphFHPKWPdgL4linwbL3zgptMEPWOSw38DzFj9rYdyz7JIl5JWZ92ftFK8soROiPiHkrHCgK0GIzeUvOGkNyq7405meM1ms9TCrr4x1V3Ak7kGLQRpf7maYim2VdfddZGugAR8lKzwIJ3kqKAwINxwVJpHNuLQkhbrISqTtPg2p9cGKC3igqE10TzDeakphmGP4XzoCGgSGjogMhoSySKoC9SG93VhfsXafmoHTvqpFEvhMKZbtzpVz7sz1eG6wt6BGl9pHpFcU1kxB9yVzOHZMZoD3UzpevRKHR0e6wgRnqePqDAQh7FTXUmRFM7J8OkFvbJsxQaK7fpoIQ5QOBzBlMiQofqmUARgBrzZ8zz6EPldvgT9HjBTVKAaPQmAh4HJm6ylwYh1Ds4ZyOZ6XqPJ0gJGWW73QED3A1eWPlNjEI83nXZaeFK4LjBx5yrM3UFtMKgsWUBqtzjGn9HrEhmgqODmdVZ6Gvpi5wARh28Ash6FgDXKLaQ2PkeS64ODp4Mkqc2y40Yn7VSepGP0HwSmHX4ERJ76DJhUMaiH06UYSD279IXH4GTBtO5bn38RCfBefJL6GwUoZNlZm9wgFgIZUE08xYP04h5aQG6m3RBSvMHHM4Oiam7VRYUfNz5HG0InxEAqm19IEHfgBToB6lnOa7TNxPl4GTh4oHlBzk93Re9iYnKVzYAAVkdjZpdw9lqnTBOiLObtTbCHpctO0TeM4iVTxZgwawKTXp1z33SM4kkjnEYeo3RibC2zr8WsuxbiN2HGWqjQBu0PYOTdHBlJ3d9lcVEwjFFWyctktD0UXQzMvjP3K1CE4BQ6nktxPYjd1Dok6f5UWuwhDcae3DIY5
----- END MESSAGE -----

The challenge can be solved in nearly an infinite amount of ways so to choose one that we’re comfortable with and that can solve the challenge is our first step. To do this we can list what we need to achieve:

  1. Fetch the message to hash
  2. Hash the message
  3. Submit the hash to the correct address

We can achieve all this with a python script using a http library like requests, a nice c program or as there are programs dedicated these tasks ready and waiting in our linux environment we can use a simple oneliner in a shell of your choosing. I like shells and it gives us an opportunity to get more familiar with tools that we use regularly anyway so we’ll use a simple shell script.

1. Fetching the message

The first step of fetching the message, and presumably starting the timer, can be done with several programs at your fingertips (wget, curl, etc). I’ll be using curl for this challenge. To fetch your specific challenge you’ll need to be logged in, this is tracked by a cookie called ‘PHPSESSID’ which tracks your current browser session. For a later challenge I might create a bit of
a framework to sign in and automate this step across challenges but for now we’ll just log in with our regular browser, Firefox, and pass the session
cookie to curl for our requests. Fetching the message we’re supposed to hash can be done easily with this command:

curl -sb PHPSESSID=[your cookie] https://ringzer0ctf.com/challenges/13

Easy! But this doesn’t fetch just the message we want but the whole page, no problem we can parse out the message quickly using other handy command line tools. The message is isolated by the markers begin message and end message above, we can easily use these, as long as there are no others hidden in the page, to isolated the message by piping the output of curl to the following command:

grep -A 1 'BEGIN MESSAGE' | tail -1

2. Hash the message

Almost there! If we look at the output of this it isn’t really as clean as we need it. There are tabs and HTML line breaks that we need to clear up,  easily done with a stream editor and the power of regular expressions!

sed -re 's/\t|<br \/>.*$//g'

This might look a bit unreadable but if you don’t read regex but what we are asking sed to do is to substitute all tabs and ‘<br />’ (plus anything inbetween <br /> and the end of the line) with nothing, everywhere in the stream. We might think that we are ready to send this nice looking output the hash function already but there are hidden forces that will ruin the hash if we just pipe this to the hashing function.

We can compare the hash of the message we fetch and the output of our processed command line pipe and see that they do not match. We can compare the two strings with hexdump to see what is going on.

A hexdump of the copied message gives us this output:

printf "[our message]" | hexdump
0000000 5652 7a78 5948 416b 4d74 5a44 4b6f 5030
...
00003f0 3566 5755 7775 4468 6163 3365 4944 3559
0000400

A hexdump of the pipe gives us:

0000000 5652 7a78 5948 416b 4d74 5a44 4b6f 5030
...
00003f0 3566 5755 7775 4468 6163 3365 4944 3559
0000400 000a
0000401

There is one byte extra that we can’t have in the output of our pipe, a new line that ruins the hash for us. But no worries, this is easily taken care of by adding another stage in the pipeline which removes the last byte. Now the message is ready the be hashed!

head -c -1 | sha512sum

3. Submitting our result

Now we have the tools in place to programmatically fetch the message, clean it up and hash it. All that is left is to submit it! This is done by a HTTP
request to the address in the challenge prompt and we can use curl again to perform this request. The hash now looks like this:

d1666bf465316aea7ef2b3210051b1dd248a3523076f7d51548463260cb3f5e6cccf2188ac7917b83edec61c309876b0f65dcacabba1c39c6189d022d4b140f1 -

That dash on the end indicates the hash was calculated from standard input and not a specified filename. That needs to go, easily done with the command cut! In order to specify the address for curl to access the whole url needs to be supplied as an argument but our hash is passed in a pipeline… We can tackle this easily in two ways, execute the first two parts in one go and use the output as a command line argument for curl which would look something like this:

curl -sb 'PHPSESSID=[cookie]' https://ringzer0ctf.com/challenges/13/$([everything we did before])

Easy enough but not all that pretty and as we already did everything up to this point using pipes we might as well see it through! xargs is the program for us in this situation, it a neat utility to pass the standard output of one program as an argument to the next. I confess this might not really be that different from the other solution but it keeps the flow of data linear and adds lots of readability instead of nesting commands in each other. The main difference is that the first solution uses the to store the immediate result on place it on the argument vector for the outer execution of curl whereas we use xargs to do it and execute curl for us. But readability is important as well so I’ll go with xargs.

cut -d ' ' -f 1 | xargs -I {} curl -sb 'PHPSESSID=[cookie]' https://ringzer0ctf.com/challenges/13/{}

If we run this:

curl -sb PHPSESSID=[cookie] https://ringzer0ctf.com/challenges/13 | grep -P -A 1 'BEGIN MESSAGE' | tail -1 | sed -re 's/\t|
.*$//g' | head -c-1 | sha512sum | cut -d ' ' -f 1 | xargs -I {} curl -sb PHPSESSID=[cookie] https://ringzer0ctf.com/challenges/13/{} 

we complete the challenge, hopefully within the timing requirements and in the HTML we get back we find the flag to submit as proof we completed the challenge. We can easily parse it out by adding the following to our pipeline:

grep -Po 'FLAG-\w+'

If someone reads this I hope you might pick up on something, the awesomeness that is the unix command line and piping perhaps?

Good luck!

/Linuxxon

Posted in CTF, Hacking | Tagged , , | 1 Comment

Hello World!

Welcome to my blog, this isn’t going to be anything I really care about but
simply a way for me to organize my thoughts, make note taking and documentation a more involved and fun part of projects, hobbies and other stuff. Maybe it might be helpful to anyone else who comes across the same problems I do and gets something out of it.

I think, the topics will mostly focus around software engineering, some
hardware design as I’m (almost) an embedded systems engineer, and other
hacking, tinkering and such.

Cheers,
Rasmus

Posted in Uncategorized | Leave a comment