SECCON 2017 Online CTF Writeup


SECCON online CTF qualifying was held on December 9 - 10. Since I did not belong to the team, it was individual participation. In addition, this time I covered with the interim report of enPiT in Hakodate, and less time to tackle the problem😫.

This article is Student Advent Calendar 2017 14th.


Run me! (Programming 100pt)

The given source code is as follows.

import sys
def f(n):
    return n if n < 2 else f(n-2) + f(n-1)
print "SECCON{" + str(f(11011))[:32] + "}"

Processing does not end due to recursion when program is started. However, since this source code merely obtains the term 11011 of the Fibonacci sequence, I used the online tool. Looking at the script though we only need the first 32 digits.


putchar music (Programming 100pt)

This one line of C program works on Linux Desktop.
What is this movie's title?
Please answer the flag as SECCON{MOVIES_TITLE}, replace all alphabets with capital letters, and spaces with underscores.

I looked at the List of highest-grossing films and entered it in the answer form. SECCON{AVATAR}, SECCON{TITANIC}, SECCON{STAR_WARS}... What the heck. Flag is SECCON{STAR_WARS}. However, I cloudn't accept it, so let's attack with corrective action.

main(t,i,j){unsigned char p[]="###<f_YM\204g_YM\204g_Y_H #<f_YM\204g_YM\204g_Y_H #+-?[WKAMYJ/7 #+-?[WKgH #+-?[WKAMYJ/7hk\206\203tk\\YJAfkkk";for(i=0;t=1;i=(i+1)%(sizeof(p)-1)){double x=pow(1.05946309435931,p[i]/6+13);for(j=1+p[i]%6;t++%(8192/j);)putchar(t>>5|(int)(t*x));}}

I attempted to compile, but since it did not work well with gcc version, I've formatted the source code.


int main(int t, int i, int j){
  unsigned char p[]="###<f_YM\204g_YM\204g_Y_H #<f_YM\204g_YM\204g_Y_H #+-?[WKAMYJ/7 #+-?[WKgH #+-?[WKAMYJ/7hk\206\203tk\\YJAfkkk";

    double x=pow(1.05946309435931,p[i]/6+13);

$ gcc music.c -lm
$ ./a.out | aplay

After shaping, the compilation went well, so I piped it to Advanced Linux Sound Architecture, where the famous opening theme flowed. Great!


JPEG file (Binary 100pt)

JPEG file
Read this JPEG is broken.
It will be fixed if you change somewhere by 1 bit.

First of all, I analyzed it with famous tools.

$ file tktk-892009a0993d079214efa167cda2e7afc85e6b9cb38588cba9dab23eb6eb3d46 
tktk-892009a0993d079214efa167cda2e7afc85e6b9cb38588cba9dab23eb6eb3d46: JPEG image data, JFIF standard 1.01, resolution (DPI), density 192x192, segment length 16, baseline, precision 8, 339x53, frames 3
$ exiftool tktk-892009a0993d079214efa167cda2e7afc85e6b9cb38588cba9dab23eb6eb3d46 
ExifTool Version Number         : 10.10
File Name                       : tktk-892009a0993d079214efa167cda2e7afc85e6b9cb38588cba9dab23eb6eb3d46
Directory                       : .
File Size                       : 11 kB
File Modification Date/Time     : 2017:12:09 15:55:40+09:00
File Access Date/Time           : 2017:12:10 06:04:08+09:00
File Inode Change Date/Time     : 2017:12:10 06:04:08+09:00
File Permissions                : rwxrwx---
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : inches
X Resolution                    : 192
Y Resolution                    : 192
Image Width                     : 339
Image Height                    : 53
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 339x53
Megapixels                      : 0.018
$ binwalk tktk-892009a0993d079214efa167cda2e7afc85e6b9cb38588cba9dab23eb6eb3d46  
0             0x0             JPEG image data, JFIF standard 1.01

I should have used a binary editor to find out where it is broken, but since I found a useful restoration site I decided to use it as it is. Repair Your Damaged Pictures - Now! When I uploaded the file using the above site, I recovered the damaged JPEG file to some extent and got the flag.



Vigenere3d (Crypto 100pt)

In the problem sentence, the source code "Vigenere3d.py" is given.

import sys
def _l(idx, s):
    return s[idx:] + s[:idx]
def main(p, k1, k2):
    s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
    t = [[_l((i+j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
    i1 = 0
    i2 = 0
    c = ""
    for a in p:
        c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
        i1 = (i1 + 1) % len(k1)
        i2 = (i2 + 1) % len(k2)
    return c
print main(sys.argv[1], sys.argv[2], sys.argv[2][::-1])

Also, the log is as follows.

$ python Vigenere3d.py SECCON{**************************} **************

It is a three-dimensional Vigenere cipher as shown in the second line of the main function of the source code. What I knew was ...

  • Key 1 is the inverse of key 2.
  • The key length is 14 characters.
  • As seven plain text SECCON { seven characters have already been found.

Therefore, I wrote a script to find keys in ciphertext.

import sys

def drip_str(idx, s):
    return s[idx:] + s[:idx]

def encrypt(p, k1, k2):
    s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
    t = [[drip_str((i + j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
    i1 = 0
    i2 = 0
    c = ""
    for a in p:
        c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
        i1 = (i1 + 1) % len(k1)
        i2 = (i2 + 1) % len(k2)
    return c

# solver
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"

cipher = "POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9"
head = "SECCON{"

for i in range(len(head)):
    j = 1
    while (encrypt(cipher, key, key[::-1])[i] != head[i]):
        key = key[:i] + s[j] + key[i + 1:]
        j += 1
tmp = key[::-1]
key = key[:7] + tmp[:7]
print 'flag: ' + encrypt(cipher, key, key[::-1])


Log search (Web 100pt)

Log search
Search the flag on Elasticsearch.

I did not understand well, but when I repeatedly searched for "flag" and "response code 200", a flag text file was displayed🤔 f:id:takuzoo3868:20171212003432p:plain


SHA-1 is dead (Crypto 100pt)

  1. file1 != file2
  2. SHA1(file1) == SHA1(file2)
  3. SHA256(file1) <> SHA256(file2)
  4. 2017KiB < sizeof(file1) < 2018KiB
  5. 2017KiB < sizeof(file2) < 2018KiB (1KiB = 1024 bytes)

Although it may be cowardly, I used pdf which google publishes. I added a file to fill the pdf file with the remaining size to make it fit the size.

$ wget https://shattered.io/static/shattered-1.pdf && cp shattered-1.pdf a 
$ wget https://shattered.io/static/shattered-2.pdf && cp shattered-2.pdf b
$ dd if=/dev/zero of=tmp bs=1643000 count=1
$ cat tmp >> a
$ cat tmp >> b
$ sha1sum a b
fa004512dad796e9e5f7958e497166c4df54eb7a  a
fa004512dad796e9e5f7958e497166c4df54eb7a  b

A flag was displayed when uploading these.

SECCON {SHA-1_1995_2017?}


Total score is 600. Perhaps I should be able to aim higher. This is the problem that I challenged but was frustrated (It was a train traveling time !!! Nooooooo).

  • Baby Stack (Pwn 100pt)
  • Simon and Speck Block Ciphers (Crypto 100pt)
  • Powerful_Shell (Binary 300pt)

Also, since I have not solved any problem of "Pwnable", I want to challenge again while watching others' writeup. At the end, I'm looking for a team. I want to get a good result by participating in a lot of CTF which will be made more advanced.