Cyber Security Challenge

To all those interested, here is a copy of my email with my solution.

To whom it may concern,

Decoded this from the last challenge!

Congratulations  youve found and completed the REAL challenge. Your win
code is  cyb3r=s3cur1ty*ch@ll3nge+26-07-2010.

Please email this code to our team at
media@cybersecuritychallenge.org.uk. If youre the first person to do so,
and can prove you meet the eligibility criteria (British citizen
currently resident in the UK) we will be in touch to advise how to claim
your prize. Well done and good luck in the Cyber Security Challenge
competitions taking place throughout the rest of the year

Figured I would go through the process:

Task one

Copied the data into a file.

Created the following perl script:

#!/usr/bin/perluse MIME::Base64;

while(<STDIN>){    print decode_base64($_);}

I then piped the data through the script into another file

$ cat data | ./base64.pl > output

At a hunch, checked if it was an image.

$ evince output

Voila!

Task two

Noticed the squiggles, zoomed in a lot and noticed it covered 2 pixel strips, so converted the image to a bitmap, then created a very hacky C file to grab the data (after checking the wiki page for the  file format). It is quite hacky, but combined with an online binary to ascii converter, worked well. The C file was as follows:

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

void * imgdata;int datao(int x, int y);

int main(int argc, char *argv[]){

  FILE * fp;
  int w, h, o, off, i;
  int r, g, b, re;

  //Read binary data
  fp = fopen("output.bmp", "rb");

  fseek(fp, 0x0a, SEEK_SET);
  o = getc(fp);
  printf("1n", o);

  //First
  off = o + 1052 * 173;
  fseek(fp, off, SEEK_SET);
  for(i = 0; i < 350; i++){
    r = getc(fp);
    g = getc(fp);
    b = getc(fp);    

    if (r+g+b > 600)
      re = 1;
    else
      re = 0;

    if((i+1)%8)
      printf("%d", re);
    else
      printf("%d", re);
  }  

  printf("n2n", o);

  //section section
  for(i = 3; i <= 172; i++){
    off = o + (1052 * i) + 1047;
    fseek(fp, off, SEEK_SET);    

    r = getc(fp);
    g = getc(fp);
    b = getc(fp);    

    if (r+g+b > 600)
      re = 0;
    else
      re = 1;

    if((i+1)%8)
      printf("%d", re);
    else
      printf("%d", re);
  }

  printf("n3n", o);

  //third section  

  off = o;
  for(i = 349; i >= 0 ; i--){
    fseek(fp, off + (i*3), SEEK_SET);
    r = getc(fp);
    g = getc(fp);
    b = getc(fp);    

    if (r+g+b > 600)
      re = 0;
    else
      re = 1;

    if((i+1)%8)
      printf("%d", re);
    else
      printf("%d", re);  

  }
  printf("n4n", o);

  //forth section  

  for(i = 172; i >= 3; i--){
    off = o + (1052 * i) + 3 ;
    fseek(fp, off, SEEK_SET);    

    r = getc(fp);
    g = getc(fp);
    b = getc(fp);    

    if (r+g+b > 600)
      re = 0;
    else
      re = 1;

    if((i+1)%8)
      printf("%d", re);
    else
      printf("%d", re);
  }

  return 0;
}

//offst from data start

int datao(int x, int y){

  int width = 350;
  int height = 175;

  int offset = (y * width * 3) + x*3;
  return offset;
}

From this I got the following text:

Cyrnfr sbyybj guvf yvax:
uggcf://plorefrphevglpunyyratr.bet.hx/834wgc.ugzy
uggcf://plorefrphevglpunyyratr.bet.hx/834wgc.ugzy

Which after running through the following perl script:

#!/usr/bin/perl

use MIME::Base64;

while(<stdin>){  $_ =~ tr/a-zA-Z/n-za-mN-ZA-M/;  print $_;}

Which led me to …

Task three

This one was tricky. I looked for ascii values on the data, reversed, big endian, little endian, looked for 7bit data compacted into 8, 7bit and parity (odd/even) and then only looking at bits which  passed the test.

Early on I noticed there were no ‘3’s in the data, but didn’t see the shocking clue.

Then I tried some basic frequency analysis, but as there were 56 unique entries it was probably a polyalphabetic cypher if it was. Tried the kasiski technique, ended up with random numbers, but tried none the less. I was convinced that the page name was a key, or something simple, like “cypher”. Alas, it was not true. Whilst looking at the binary for the 500th time looking for patterns of shifts which you could be employing, but finally I saw the solution. Turns out I was doing the rookie mistake of starting out complex.

Following is the ruby file used to decode the data:

class Cypherc

    attr_accessor :bytearray, :rawdata

    def initialize

        rawdata =  "68edcdec4e2c8eae8d2c8e2dedcd6e04d2042fedae52ceac04..."

        @rawdata = rawdata

        bytearray = []

        (0 ... rawdata.size/2).each do |i|

            bytearray &lt;&lt; "0x#{rawdata.slice!(0,2)}"

        end

        @bytearray = bytearray

    end

    def differencekeysize(length)

        diff = []

        initial = @bytearray[0]

        (1...@bytearray.size).each do |i|

            if (i%length &lt; 1)

                d = Integer(@bytearray[i]) - Integer(initial)

                initial = @bytearray[i]

                diff &lt;&lt; d

            end

        end

        return diff

    end

    def asciicharacters

        ac = {}

        (0...@bytearray.size).each do |i|

            if(Integer(bytearray[i]) &lt; 128)

                puts "#{i} : #{@bytearray[i]}"

                ac[i] = @bytearray[i]

            end

        end

        return ac

    end

    def paritycheck(byte, type = 1)

        #number of 1s

        binary = Integer(byte)

        tocheck = binary &amp; 0x7f

        par = binary &gt;&gt; 7

        ones = 0

        (0..7).each { |i|

            ones += tocheck &amp; 0x01

            tocheck = tocheck &gt;&gt; 1

        }

        ok = false

        if(type == 1)

            if par == 1 and ones.odd?

                ok = true

            elsif par == 0 and ones.even?

                ok = true

            end

        elsif(type == 2)

            if par == 1 and ones.even?

                ok = true

            elsif par == 0 and ones.odd?

                ok = true

            end

        end

        return ok

    end

    def bitvalue(byte)

        return byte &amp; 0x7f

    end

    def diffscan(index)

        diffs = []

        tocheck = @bytearray[index]

        (index+1 ... @bytearray.size).each{|b|

            diffs &lt;&lt; Integer(@bytearray[b]) - Integer(tocheck)

        }

        return diffs

    end

    def ngrams(n)

        bins = {}

        (0...@bytearray.size - n).each { |i|

            key = @bytearray.slice(i, n).to_s

            if bins[key].nil?

                bins[key] = 1

            else

                bins[key] += 1

            end

        }

        return bins

    end

    def bincheck

        bins = {}

        ks = 10

        (0 ... rawdata.size/ks).each {|i|

            bins[i] = rawdata.slice(ks*i, ks)

            t = []

            (0 ... bins[i].size/2).each do |j|

                t &lt;&lt; "0x#{bins[i].slice(j*2,2)}"

            end

            bins[i] = t

        }

        comp = []

        bins.each{ |k,v| comp &lt;&lt; bins[k][0] }

    end

    def shiftbits(byte)

        binary = Integer(byte)

        bottom = binary &gt;&gt; 5

        top = (binary &amp; 0x1f) &lt;&lt; 3

        return bottom ^ top

    end

    def decode

        @bytearray.each { |b|

            print "#{shiftbits(b).chr}"

        }

    end

end

c = Cypherc.new

c.decode

Those are my workings, 3 hours on the steg stuff probably, and much too long on the last challenge.

Looking forward to more challenges 🙂

Carl Ellis
http://www.jimhi.com

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.