Python公式チュートリアルを頑張って読んでいる ラムダ・キーワード引数
これです。
言語はPythonが初めてです。
すごいひと「プログラミングは公式ドキュメント読めば分かるよ」
僕「わかりました!」
...
僕「メソッド?クラス?分からんやめよ」
僕「リストとかのこういうの(['kiwi', 'apple', 'banana'])入力するの面倒だからやめよ」
公式ドキュメント「1.やる気を高めよう」
僕「」
めちゃくちゃゆっくりなペースですが読んでます。
分かるひとには何を当たり前な事を...って感じですけど自分用の記録として。
4.7.5. ラムダ式
lambdaで名前の無い関数を作れる。
defでmake_incrementorって関数作って、その中にlambdaで関数作ってる↓
nは仮の引数?
>>> def make_incrementor(n):
... return lambda x: x + n
...
make_incrementorをfに代入してる。呼び出す時楽だからかな?↓
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
最初見たとき何で4,1,3,2の順番なのか5分ぐらい分からなかったw
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
これは辞書の二つ目の要素でソート「pair: pair[1]」してるのでアルファベットでソートされてる。
辞書の1つ目の要素でソート「pair: pair[0]」すれば数字でソートできる。
>>> pairs = [(1, "one"), (2, "two"), (3, "three"), (4, "four")]
>>> pairs.sort(key=lambda pair: pair[0])
>>> pairs
[('one', 1), ('two', 2), ('three', 3), ('four', 4)]
それか辞書の要素の順番を入れ替えるかすれば数字でソート出来る(これは無いか)
>>> pairs = [("one", 1), ("two", 2), ("three", 3), ("four", 4)]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[('one', 1), ('two', 2), ('three', 3), ('four', 4)]
4.7.2. キーワード引数
関数には必須引数とオプション引数を指定出来る。
↓のvoltageが必須引数、state,action,typeがオプション引数。
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")
parrot関数を呼び出す時、必須引数(ここだとvoltage)は入れないとだめ。
オプション引数は何も入れなければ、関数で指定されてる値が勝手に入る。
関数を呼び出す際に一緒に入れる引数は、カンマで区切られた順に割り当てられる?
parrot('a million', 'bereft of life', 'jump')なら、
voltage引数にはa millionが、
state引数にはbereft of lifeが、
action引数にはjumpが入る。
type引数は指定してないのでNorwegian Blueが入る。
引数を指定する事も出来る。
parrot(action='VOOOOOM', voltage=1000000)
これはだめらしい。
✖︎ parrot(voltage=5.0, 'dead')
多分これ↓ならok、引数を指定する場合は、指定してない引数よりも後ろにしなきゃいけないみたい。
◎ parrot('dead', voltage=5.0)
あとこれ。初見で全く意味が分からなくて理解するのに時間かかった。
↓関数作る
def cheeseshop(kind, *arguments, **keywords):
print("-- Do you have any", kind, "?")
print("-- I'm sorry, we're all out of", kind)
for arg in arguments:
print(arg)
print("-" * 40)
for kw in keywords:
print(kw, ":", keywords[kw])
↓関数呼び出す
cheeseshop("Limburger", "It's very runny, sir.",
"It's really very, VERY runny, sir.",
shopkeeper="Michael Palin",
client="John Cleese",
sketch="Cheese Shop Sketch")
↓出力
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch
def cheeseshop(kind, *arguments, **keywords):
↑の*argumentsで引数をカンマで区切ってたくさん指定出来るって意味らしい。
↑の例だと、⑴"It's very runny, sir.","It's really very, ⑵VERY runny, sir."で二つの引数を指定してる。forで回してる。
で、どっからが**keywords何だ?カンマでずっと区切ってるじゃん、ずっと*argumentsの範囲やろ。って思ってたけど、a=bみたいになってるやつを辞書として受け取ってるみたい。**keywordsが受け取ってるのはこいつら↓
shopkeeper="Michael Palin",
client="John Cleese",
sketch="Cheese Shop Sketch"
こちらの解説が分かりやすかった。
使いこなせるまでまだまだ先は長い...というかいつ使うんだろ...
CTF初心者がいきなり問題を作ってみた
初めての記事なので見難いところがあったらすみません!
作問する事になったきっかけ
偉い人「何でもいいからCTFの問題を一人一問絶対作る用に。」
とか突然言われて初めて作ってみた時の所感です。
SECCON予選開始30分で問題を解ける気がせず気分転換に風呂入ってそのままスマブラやって寝たなんて言えない
そもそもCTFって何よ?
一応分からない人向けにざっくり説明すると、CTFっていうのはCapture the Flagって言って旗取りゲームです。
情報セキュリティの技術を競うゲームです。
CTFは主に下記のテーマで出題されることが多いです。
- リバースエンジニアリング
- フォレンジックス
- Pwnable
- Web
- ネットワーク
各詳細は偉大なWikipediaさんに任せるとして、僕はネットワークジャンルで作問する事にしました。
ネットワークパケットを解析して、その中に隠されたFlag(旗)を見つけてもらうって感じのジャンルです。
どんな問題を作ろう?
0から問題を捻り出すのは時間的に無理があったので過去のWriteupをググりました。Writeupってのは実際に問題を解いた人がその問題の解き方をまとめたものです。
その中でも「CTF for ビギナーズ2015」のネットワークジャンルの問題とWriteupについて詳しくまとめられている記事があったのでとてもパクr参考にさせて頂きました!
問題と詳しい解説については記事を見て頂くとして、この問題の解法をざっくり説明するとこんな感じ
- pcapファイルをWireshark(パケット解析ソフト)で開く
- パケットを見ていくとFTPの通信を発見する
- FTPは暗号化されていないので通信内容が見えるのでは?と推測
- 見てみると1.txtと2.zipと3.txtをサーバーからダウンロードしてるのがわかる
- 1.txtは「ctf4b{This_communication_is」、3.txtは「_encrypted.}」とそれぞれflagの一部が書いてあることがわかる
- 2.zipはそのままでは何が入ってるのか分からないので、Zipファイルを取り出す必要がある
- Wiresharkの「Follow TCP Stream」という機能でZipファイルをゲット
- 展開すると「_not」という文字を確認
- 文字を組み合わせると「ctf4b{This_communication_is_not_encrypted.}」というflagを発見
- やったね!
これを似た感じで再現してみたって感じです。
環境準備
ファイルをやり取りするために、Virtual BOXでVMマシンを2台用意します。
何でもいいです。僕はxfceが好きなのでxubuntuにしました。
適当にVirtual Box上で2台デプロイします。
最初はホストとの通信用にDHCPでそれぞれ同じIPが振られてますが、VM間で通信するためにもう一つNICを作ります。下記サイトを参考にしました。
もしVM間で通信できなかったら、VMがグローバルツールにあるアダプターを使っているか確認してみてください。↓
↓の例だとVMに振るIPは33seg
VM間で通信が出来るようになったら片方のVMにFTPサービスを入れて設定します。
Linux - Ubuntu 14.04 - ftp サーバインストール
https://freebsd.sing.ne.jp/linux/02/02/05.html
後は実際に送るテキストファイルにFlagの一部を入れます。さっきのビギナーズ2015の問題の例だと、2.txtはZIPにしてますね!ここはアレンジし易いところだと思います。
僕は2.txtをzip化して拡張子を消して何のファイルかそのままでは分からない用にしました!
パケットをキャプチャする
準備が出来たらどっちのVMでもいいのでWiresharkを入れてキャプチャします。
普通にブラウザから落としていいと思います。使ってるNICを指定してキャプチャスタートします。
キャプチャが始まったらFTPコマンドでサーバにファイルをアップロードしていきます。あらかじめサーバにファイルを置いておいてダウンロードでもいいと思います。
ファイル転送が終わったらキャプチャをストップして、パケットを確認します。
下記のような感じでキャプチャファイルのpcapファイルを作りました。
後は自分で実際にpcapファイルからflagを取得出来るかを確認します。
作ってみた感想
- FTPコマンドを使ったことがなかったので苦労した
- Virtual Boxのネットワークアダプター周りが少し詳しくなった気がする
- パケットが全体で100個くらいしかないので、他の通信を色々混ぜれば難しく出来そう
- Writeupを読み漁るのは大事っぽい
人によってはバイナリや暗号問題の方が簡単に作れるって人もいるかもしれませんね(っていうかそっちの方が多いかも...)。
次はFTP以外ので何か作ってみたいと思います。ではでは!