picoCTF 2018 writeup

問題数多いですね、ひたすらやりました。
26335ptsで、たぶん93位です。

CTF、たいていディレクトリがぐちゃぐちゃになるので、今回/tmpで作業をしていて、特に保存したものを除いて多くのソースコードは失われています。

大量なので雑に書きます、もっと書けというのがあればリクエストしてもらえれば書かないでもないかもしれません。書かれるかどうかは別にして、お気軽にどうぞ。

ジャンル別で書きます。

# Crypto

## Crypto Warmup 1
tableを見ると、明らかにvigenere
https://cryptii.com/pipes/vigenere-cipher

## Crypto Warmup 2
rot13
https://www.rot13.com/

## HEEEEEEERE'S Johnny!
john the ripper

## caesar cipher 1
caesar
https://cryptii.com/pipes/caesar-cipher

## hertz
quipqiupは最高
https://quipqiup.com/

## blaise's cipher
vigenere、Blaiseさんらしい
https://www.guballa.de/vigenere-solver

## hertz 2
quipqiupは最高

## Safe RSA
nよりcが小さい、eも小さい => p^e < nなのでcの三乗根を適当に求める

``` ruby
[(1..x).bsearch{|y| y**3 >= x}.to_s(16)].pack("H*")
```

## caesar cipher 2
バイナリっくcaesar。

``` ruby
256.times.map{|i| x.bytes.map{|b|b+i}.pack("C*")}.find{|d| d.include? 'pico'}
```

## rsa-madlibs
pari/gpでがんばっていく。手作業でやると時間足りないけど、問題は毎回同じだから、答えをメモりながら進めていく。

```
n = p * q
phi = (p-1) * (q-1)
d = lift(1/Mod(e,phi))
p = Mod(c,n)^d
```

## SpyFi
この手の問題、またあるだろうしスクリプトめんどいので[まとめた](https://kcz.kibe.la/shared/entries/f307b469-bac9-4945-af81-adb60d216710)。
ECBなので、block sizeが16byteであることも考えて、`fying code is: ?`の1文字をあてるため、

```
[16*n bytes data]fying code is: afying code is: bfying code is: c...fying code is: zPADDING_DATA[data]
```
の暗号文のなかで、2回でてくる暗号ブロックを探す。

## Super Safe RSA
nがたったの260bit程度。msieveで力技で素因数分解する。今やったら3min 49secで解けた。

## eleCTRic
毎回カウンタの初期値が一緒。
flag_xxxxxxxxxxxxxxxxxxxx.txtの暗号結果を当てたいわけなので、
flag!xxxxxxxxxxxxxxxxxxxx.txtをファイル名にしたshare codeを作って、
!の位置のbyteを256個全探索してdecryptする。

## Magic Padding Oracle
今回の知見of the CTFなので、[まとめた](https://kcz.kibe.la/shared/entries/3e8c8f2f-55e5-45fc-bf91-6a6a13342b54)

## Super Safe RSA 2
eがでかいので雑にWiener's attackを試す。あたった。

## Super Safe RSA 3
factorコマンドで十分。

## James Brahm Returns [まだ]
（なんかがんばって解けてしまった、いつか書く）

# Binary Exploitation

## buffer overflow 0 
SEGVさせるだけで勝ち、strcpyは悪い子

## buffer overflow 1
winのアドレスはnmとかで調べる。
そのアドレスをリトルエンディアンで1000個くらい書いて送る。

## leak-me
nameにたくさんデータを入れると、strcatでNULL byteがうしろに動いて、それでpassword fgetsで上書きされる。Hello, password.

## shellcode
shell-stormとかから適当に持ってくる

## buffer overflow 2
やっていく。nmとかでwinを調べる。
本番のときは引数の順番とか忘れたので両方試した。あとleadingのサイズも1000/4個くらい試した。

## got-2-learn-libc
サーバ上でlddしてlibcのパス調べて、putsとsystemのアドレスの差分を調べて、systemにuseful stringを渡す。

## echooo
flag_ptrをローカル変数にのせてくれているので、それを%pでleakしたあとに、%sする。
でも今考えたら、べつに%sしなくても%[n]$pをたくさんならべるだけでいい気がする。

## authenticate
%nでauthenticatedに適当なものを書く

## got-shell?
exit GOTにwinのアドレスを書く。

## rop chain

```
win_function1 addr
win_function2 addr
flag addr
0xBAAAAAAD
0xDEADBAAD
```

## buffer overflow 3
まぁcanary.txtがFIFOとかだったらウケるけど、固定っぽいので、1byteずつ当てていく。

## echo back
ソースコード失ってしまった。あとで書き直して載せる。
入力をprintfしてる。確かGOT overwriteでprintfをsystemにして、putsをvuln(i.e. 0x080485ab)とかにした気がする。

## are you root?
mallocしているのはuser構造体=12byteなのに、freeしているのはstrdupでとってきたuser->name。

```
> login aaaaaaaaABCD
> reset
> login a
> show
Logged in as a [1145258561]
```

## gps
シェルコードにNOP sledを添えて。（後者のほうが大きいが）

## can-you-gets-me
やる、としか言いようがない。
S
# Web Exploitation

## Inspect Me
cssとjsとhtmlを覗く。どうして3つに分けなかったんだろう。

## Client Side is Still Bad
HTMLを覗く。
standard MD5 implementationは一体どこへ。

## Logon
CookieのadminをTrueにする

## Irish Name Repo
SQLi。`admin'--`

## No Login [たすけて、とけない]
たすけて、とけない

## Secret Agent
Chrome DevtoolでUserAgentをgooglebotにする

## Buttons
Chrome Devtoolで`<input type="submit">`を追加する

## The Vault
SQLi。`admin'--` (既視感)

## Artisinal Handcrafted HTTP 3
がんばってGET, POSTをする。

```
POST / HTTP/1.1
Host: flag.local
Content-Length: xxx
Content-Type: application/ww-url-form-encoded

xxx
```
みたいな。

## Flaskcards
`{{config}}`

## fancy-alive-monitoring
サーバ側のチェックは末尾のほうが甘いので、`1.1.1.1; echo hoge`とかが通る。

## Secure Logon
AESのIVをいじってadminを1にする。

## Flaskcards Skeleton Key
`{{config}}`でSECRET_KEYを抜いたら、同じSECRET_KEYで適当なFlaskサーバを立てて、適当なCookieに署名させる。

## A Simple Question
blind SQLi。

``` ruby
a=[*?A..?Z,*?a..?z,*?1..?9].sort.reverse
100.times.inject(""){|s,x| p s;s+a.bsearch{|c| `curl -Fanswer="'or answer>='#{s+c}'-- " http://2018shell3.picoctf.com:15987/answer2.php`.tap{|x| p x}.include? "close"}} 
```

## Flaskcards and Freedom
template injectionでshellとる。

# General Skills

## General Warmup 1-3, Resources, grep 1, net cat, strings, pipe
はい

## grep 2
`find -type f | xargs fgrep pico`

## Aca-Shell-A
クソ問っぽい

```
ls
cd secret
ls
rm intel*
echo 'Drop it in!'
cd ..
cd executables
ls
./dontLookHere
cd ..
whoami
cd ..
cp /tmp/TopSecret passwords
cd passwords
cat TopSecret
```

## environ
`env`

## ssh-keyz
.

## what base is this?
がんばる

## you can't see me
`cat [Tab]`

## absolutely relative
home directoryで実行

## in out error
grep picoしたらでてきた

## learn gdb
gdbで実行して、タイミングよくCtrl-Cして、`x/s flag_buf`

## roulette
get_longは最後の一桁でLONG_MAXを超えてもそのまま返る。これをsignedでみれば負の数なので、負の金額掛けられる。
ローカルでパッチ当ててrand当てをして3回当てたあと、負の額掛けて負ける。

## store
1000掛けて負の数になる個数だけ偽物を買う。

# Reversing

## Reversing Warmup 1
revのwarmupはstringsしとけばいいって相場が決まってる

## Reversing Warmup 2
decodeするんじゃ

## assembly-0
引数のどちらかを返しているっぽいので両方submitしてみる

## assembly-1

``` as
.data
fmt:
.asciz "0x%x\n"

.text
.globl main
main:
    push 0x15e
        call asm1
        push eax
.att_syntax
        push $fmt
.intel_syntax noprefix
        call printf
        call exit
```
これくっつけて実行する

## be-quick-or-be-dead-1
ループ終了条件の値でcall calculate_keyをmov eax, valueとバイナリエディタ(vim)でつぶす。

## quackme
読んでXORする。

## assembly-2
assembly-1と同じ

## be-quick-or-be-dead-2
関数名的にフィボナッチなので、1015番目のフィボナッチ数でcallをつぶす

## be-quick-or-be-dead-3
6項間漸化式をrubyに書き直して、つぶす。

## quackme up
本番は真面目に読んだけど、よく見たらこれただの辞書作り問題っぽい。

``` ruby
a=[*?a..?z,*?A..?Z,*?0..?9,?{,?},?_]; a.join
b='00 30 20 50 40 70 60 90 80 B0 A0 D0 C0 F0 E0 11 01 31 21 51 41 71 61 91 81 B1 02 32 22 52 42 72 62 92 82 B2 A2 D2 C2 F2 E2 13 03 33 23 53 43 73 63 93 83 B3 15 05 35 25 55 45 75 65 95 85 A1 C1 E3'.split
c='11 80 20 E0 22 53 72 A1 01 41 55 20 A0 C0 25 E3 95 20 15 35 20 15 00 70 C1'.split
puts c.map{|x| a[b.index x]}
```

## Radix's Terminal
クソ問っぽい。
radix = base -> base64
`strings -n20 radix | head -n1 | base64 -d`

## assembly-3
assembly-1と同じ。

## keygen-me-1
16文字目がチェックディジット。頑張って読む。もしくはそれだけ気づいたら、16文字目全探索してもいいかもしれない。

## assembly-4
``` sh
nasm -f elf comp.nasm
gcc -m32 comp.o
./a.out
```

## keygen-me-2
z3に解かせる式をもってくるのがめんどうくさい...

## circuit123
``` python
def verify_z3(x, chalbox):
    length, gates, check = chalbox
    b = [Bool("x%d" % i) for i in range(length)]
    for name, args in gates:
        if name == 'true':
            b.append(True)
        else:
            u1 = Xor(b[args[0][0]] , args[0][1])
            u2 = Xor(b[args[1][0]] , args[1][1])
            if name == 'or':
                b.append(Or(u1 , u2))
            elif name == 'xor':
                b.append(Xor(u1 , u2))
    s = Solver()
    s.append(Xor(b[check[0]], check[1]))
    print(s.check())
    print(s.model())
    return
```

verifyをこれに置き換える。

# Forensics
そろそろ書くのが面倒。勘弁:bow:

solved:

- Forensics Warmup 1
- Forensics Warmup 2
- Desrouleaux
- Reading Between the Eyes
- Recovering From the Snap
- admin panel
- hex editor
- Truly an Artist
- now you don't
- What's My Name?
- core
- LoadSomeBits