Tokyo Westerns CTF 3rd 2017 write-up

# 概要
2017/09/02 09:00から2017/09/04 09:00まで行われていた、チームTokyo WesternsさんによるCTFです。

![result.png](https://qiita-image-store.s3.amazonaws.com/0/187971/2f64e67f-f87c-9d5e-94f3-d3f250b940d1.png)

チームnanimodekinaiで参加して174点取って159点でした。
何も出来なかったのでとりあえず戒めとしてwrite-upをQiitaに書きました。

# Welcome!!
The flag is "TWCTF{Welcome_To_TWCTF2017!!}".

```
TWCTF{Welcome_To_TWCTF2017!!}
```

# Just do it!
Pwn問題。
チームメンバーの方が解いてくださいました。感謝。

# Rev Rev Rev
Rev問題。
同じくチムメンが解いてくださいました。感謝。

# Freshen Uploader
Web問題。
ダウンロードリンクのアドレスが、

```
http://fup.chal.ctf.westerns.tokyo/download.php?f=6a92b449761226434f5fce6c8e87295a
```

のようになっているので、

```
f=../download.php
```

とすればdownload.phpが手に入る。1つ目のフラグはその中に記述されている。

```
TWCTF{then_can_y0u_read_file_list?}
```

フラグの内容の通り、file_listを入手したいが`f=file_list`としても何も手に入らない。
恐らく`../file_list`が目的のファイルなのだろうが、fの中身に文字列としての`"file_list"`が先頭以外で含まれているとphpが死ぬ。
いい解法が浮かびませんでした。
~~要するにWarmupも出来ない雑魚。~~

# Palindromes Pairs - Coding Phase -
PPC問題。
単語のリストが渡されて、その中から2つの単語を選んでくっつけた時に回文になる組み合わせをカウントする問題。
ソケット通信については https://dobon.net/vb/dotnet/internet/tcpclientserver.html を参考にしています。

```csharp
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static Queue<string> buffer = new Queue<string>();
        static string ReadLine(System.Net.Sockets.NetworkStream ns)
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                if (buffer.Count > 0)
                {
                    return buffer.Dequeue();
                }
                byte[] resBytes = new byte[256];
                int resSize = 0;
                do
                {
                    resSize = ns.Read(resBytes, 0, resBytes.Length);
                    if (resSize == 0)
                    {
                        return "{{{END}}}";
                    }
                    ms.Write(resBytes, 0, resSize);
                } while (ns.DataAvailable);
                foreach(var v in Encoding.ASCII.GetString(ms.GetBuffer(), 0, (int)ms.Length).Trim().Split('\n'))
                {
                    buffer.Enqueue(v);
                }
                if (buffer.Count <= 0)
                {
                    return "{{{END}}}";
                }
                return buffer.Dequeue();
            }
        }

        static void SendLine(System.Net.Sockets.NetworkStream ns, string str)
        {
            byte[] sendBytes = Encoding.ASCII.GetBytes(str + '\n');
            ns.Write(sendBytes, 0, sendBytes.Length);
        }

        static void Main(string[] args)
        {
            string host = "ppc1.chal.ctf.westerns.tokyo";
            int port = 8765;
            using (System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient(host, port))
            using (System.Net.Sockets.NetworkStream ns = tcp.GetStream())
            {
                string str = "";
                do
                {
                    str = ReadLine(ns);
                    Console.WriteLine(str);
                } while (str != "----- START -----");

                for (int count = 0; count < 50; count++)
                {
                    do
                    {
                        str = ReadLine(ns);
                        Console.WriteLine(str);
                    } while (!str.Contains("Input"));

                    str = ReadLine(ns);
                    Console.WriteLine(str);
                    int a = 0;
                    int n = int.Parse(str);
                    if (n == 0)
                        break;

                    str = ReadLine(ns);
                    Console.WriteLine(str);
                    string[] inputs = str.Split(' ');
                    for (int i = 0; i < n; i++)
                    {
                        for (int j = 0; j < n; j++)
                        {
                            bool b = true;
                            string cat = inputs[i] + inputs[j];
                            for (int k = 0; k < cat.Length / 2; k++)
                            {
                                if (cat[k] != cat[cat.Length - k - 1])
                                {
                                    b = false;
                                    break;
                                }
                            }
                            if (b)
                                a++;
                        }
                    }
                    Console.WriteLine(a);
                    SendLine(ns, a.ToString());
                }

                do
                {
                    str = ReadLine(ns);
                    Console.WriteLine(str);
                } while (str != "{{{END}}}");
                Console.ReadKey();
            }
        }
    }
}
```

```
####################################
#        Palindromes Pairs         #
####################################

(中略)

----- START -----
Input 1/50
37
k kkk kkk k k kkk kk kkk kk kk kkk kkk k kk kk kkk kkk k kk kk kkk k k kkk kk k
kk kk k kk k kk kk kk kk kk kkk
1369
Correct!
Input 2/50
47
pn x jqp kx nq nnp n nkq jn q x njx p j q nn x px jkn np xkk kp jk pn p xj q np
jq xx jnp qkj qj nx k qjk kk pp k xp nj pkq ppn nq q k qjq
171
Correct!
Input 3/50
41
y u nac ugc kpp vbu ul pa kk v n akc u l dn ya n ak vy vcy k n u ncn ckv a b yu
pv kpk n g pud v b a dby nn ak pp b
91
Correct!
Input 4/50
30
ul jx j nxk kl xk kx xux kkn exk k ekn e xe n uj jjl k n jje uk lxl ux lx jke uj
 k kxu kk el
54
Correct!
Input 5/50
16
gz jq kb peu wxm oqz u o o htv fqg w f xqv e j
10
Correct!

(中略)

Input 46/50
47
tm s us t t tm we ou wm ee uug hce sh cl ws t e i e i boq ic xm oh t thw e wb ou
 l mmg l i ie sc jxg sjo ihl mig m ouc qh b w u wu xb
91
Correct!
Input 47/50
49
mr aqb hva en rn orq v nbb n nm awi tbc vo zq xo tv a tx i wix m rox mzt qb r rs
n nhc q avi afm nx z zr f a vdc xxv cn e hf z t t ftv s z qih oe adb
56
Correct!
Input 48/50
4
bj hrt xsz yqf
0
Correct!
Input 49/50
33
fjw se mwj grs h ez fv ol ro q nws fla hq qzt hf lm d h z dv sq ae sls m lg g hd
 ngf v j hdz vr gqd
28
Correct!
Input 50/50
15
n ak nfn vrm azc az x p q xxq yf fkr vm rz xbo
6
Correct!
Congratulations! The Flag is 'TWCTF{find_favorite_smell}'.
{{{END}}}
```

```
TWCTF{find_favorite_smell}
```

# My Simple Cipher
Crypto問題。
メッセージの一部が分かっているのでいい感じに逆算可能(というかなんとなく書いてみたら解けた)

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            char[] msg = "TWCTF{xxxxxxxxxxxxxx}|xxxxxxxxxxxxx".ToCharArray();
            char[] key = new char[13];
            // むちゃくちゃ1行が長いけど、16進文字列をbyte[]の配列に直してるだけです。ゴミコードを書きがち。
            byte[] encrypted = "7c153a474b6a2d3f7d3f7328703e6c2d243a083e2e773c45547748667c1511333f4f745e".Select((n, i) => new { n = n, i = i }).GroupBy(x => x.i / 2).Select(x => x.Select(y => y.n)).Select(x => Convert.ToByte(new string(x.ToArray()), 16)).ToArray();
            for (int j = 0; j < msg.Length; j++)
                if (msg[j] != 'x')
                    for (int i = 0; i < 128; i++)
                        if ((msg[j] + i + encrypted[j]) % 128 == encrypted[j + 1])
                        {
                            key[j % 13] = (char)i;
                            msg[22 + (j % 13)] = (char)i;
                        }
            for (int j = 0; j < msg.Length; j++)
            {
                for (int i = 0; i < 128; i++)
                    if ((i + key[j % 13] + encrypted[j]) % 128 == encrypted[j + 1])
                        msg[j] = (char)i;
            }

            Console.WriteLine(new string(msg));
            Console.ReadKey();
        }
    }
}
```

```
TWCTF{Crypto-is-fun!}|ENJ0YHOLIDAY!
```

```
TWCTF{Crypto-is-fun!}
```

# Backpacker's Problem
PPC問題。
(たぶん)部分和問題。
負数も含む数列から合計が0になるsubsequenceを出力する問題。
数列の数値は大体多倍長整数じゃないと扱えなさそうな範囲。
各問では問題No * 10個の数列が出され、20問ある。
方針が上手く決まらず適当に組んだら5問目でTLEしました。残当。
~~私のプログラミングスキルが低くてT(LE) W(A) CTFって感じでした。~~

# pplc
PPC問題。
Pythonのevalに短いコードを突っ込んでいい感じに情報を得るやつです。

__private__
`__flag`メソッドにアクセスしたいけど、メソッドに使われている文字列(`__flag`が展開された、`_Private__flag`)の`"Private"`が入力にあるとプログラムが落ちてしまう。
つまりメソッド名を別の方法で取ってくれば良い。`dir()`が使える。

```
$ nc ppc1.chal.ctf.westerns.tokyo 10000
eval('p.%s()'%dir(p)[0])
TWCTF{__private is not private}
```

```
TWCTF{__private is not private}
```

__local__
よくわかりませんでした。

__comment__
Javadocみたいな感じでコメントをドキュメントにする機構がなんかあるじゃろって探したらありました。

```
$ nc ppc1.chal.ctf.westerns.tokyo 10002
comment_flag.__doc__
Welcome to unreadable area!
FLAG is TWCTF{very simple docstring}
```

```
FLAG is TWCTF{very simple docstring}
```

# 他の問題
手をつけてないか全く分からなかったかのどっちかです。
ダメダメ。

# まとめ
全然解けませんでした！！！！！！！
他の人のwrite-upみて知識を増やしていきたいです……