N=1

主にコンピュータ技術関連のことを投稿。 / 投稿は個人の意見であり所属団体の立場を代表するものではありません。

マインドフルネス瞑想の個人的なサーベイ

瞑想の効果についてまとめた。

背景

私がことあるごとに話題にしているマインドフルネスというのは初見だとなんか胡散臭い感じがしますよね。

もともとアメリカ人のオリエンタリズム(あまり長い歴史を持たないアメリカ人の東洋神秘主義に対する憧れ)から、主に富裕層でヨガとか禅とか瞑想とかが流行ったのだと推察している。スティージョブズが長年やっていたのも曹洞宗の座禅だし、映画監督のデイビッドリンチも超越瞑想というちょっとオカルトが感じられるものにかなり入れ込んでいる。私からするとかなり胡散臭く感じるので、分析はしても実践はしたいと思わない。

しかしそこは欧米人なので後付けでガツガツと科学的なエビデンスを追いかけていったのではないだろうか。2000年以降で活発に論文が出ていて、ここ数年では得られる効果とそれに対する効率的なメソッドがかなり確立してきた。有名なのが Google で実践された情動コントロールの研修だ。"心理的安全性"が日本のエンジニアコミュニティでも一般的な語になったが、この研修パッケージ内に科学エビデンスに基づいた"マインドフルネス瞑想"が社会的スキルの成熟に役立つという話もあったのだ。

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 !!

http://source.darkarmy.xyz/

ソースコード index.php の配布もある。

$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 において

  1. is_numeric が true
  2. 文字列長が1から3
  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=&register-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=&register-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

https://ctf.csaw.io

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 で調べると、"ゼロ幅スペースステガノグラフィ"に関連するツールを見つけた。

github.com

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 が最適だった。

www.timetimer.com

  • 面積で残り時間を視認できる
  • 単機能
  • アラームを切れる
  • 時計のチクタク音が無い

もともと子供やASDなどもスコープに入れたツールであり押さえるべきところが押さえられている。

欠点は価格だ。安いモデルでも5,000円以上する。Time Timer 自体は学生の頃から知っていたが高すぎて手が出なかった。自作も検討していたがずっと放置していた。

忘れていたころに、類似の IoT デバイスで Kotobo という、30分タイマーを通知するだけのボタンが登場した。とても欲しいと思ったがこれはなんと 12,980円もする。

koto-ha.co.jp


これを買う前に類似の機能を持ったより安価なもので効果を知っておきたいなと思い、ふと Time Timer を思い出して Kotobo の半値以下なら買ってしまうか、と決断したのである。

Unboxing

インテリアに馴染むような小型モデルで、Time Timer MOD というのがあり 5,000円ちょっとで買った。確か昔は買える場所が少なかったような気がするが、今では楽天の玩具屋などでも扱っている。

f:id:ishn:20191228094549j:plain

外箱はおしゃれ。

f:id:ishn:20191228094739j:plain

内容物はこれ。

f:id:ishn:20191228094828j:plain

本体は柔らかいシリコンカバーがついていて雑に扱ってもいいようになっている。このカバーにカラーバリエーションがあるらしく、それで MOD というらしい。
f:id:ishn:20191228095057j:plain

背面はアラーム音のスイッチと電池蓋がある。電池は同梱されておらず、単三電池1本と蓋を開けるためのメガネ用ドライバーが必要。蓋、ネジは固めなので、小さい子供に渡しても問題なさそうだ。

www.youtube.com

文字盤中央の取っ手を回すだけで自動でカウントダウンが始まる。アラーム音はこんな感じで4回鳴って終了。ずっと鳴り続けたりはしないのが素晴らしい。

使用感

良い

  • 赤い面積で残り時間が直感的にわかる。これを求めていた。
  • 中央の取っ手を回す以外に操作が無い。面倒が無いので頻繁にリセットできる。

欠点

  • 大きすぎず小さすぎず絶妙なサイズ感だけど、大人が使う場合は堅牢性よりも携帯性が重要な気がするので薄くしてもらった方がいいかも。オフィスでも家でも使いたい。

ポモドーロテクニックにも使えるけどそれ以外でも、分単位の締め切りのある作業をする際にバッファを持たせたタイマーを作っておき、チラチラと眺めるのはとても効果があった。やはり残り時間が面積で認識できるのは大きいと感じた。少なくなってくると、意味のない作業は切り捨てたり落とし所を考え始めるようになる。

あとは、音、操作性、視認性でストレスを全く感じないのも良い。

まぁここまでツールの話を書いてしまったけど、実際は睡眠、運動、食事、精神が全て整っていることが一番大事。その上でさらに締め切りを意識した活動が苦手ということを認識したのでこれで改善できそう、という話です。

使用感が気になる人は Android だと Visual Timer という無料アプリがあったので試してみて欲しい。

play.google.com

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 変数で決める。

一度実行すると上書きされる。実用上はそんなもんでいいのではないかな。元の 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
    • 指定したリージョンで EC2 インスタンスを探す。省略した場合は ~/.aws/configure に設定したリージョンになる。それも無ければ us-east-1 が設定される。
  • -i identity_file
    • キーペアのファイルを指定する。ssh で適切にデフォルトが設定されているならば省略してもよい。
  • -q
    • quiet mode / セキュリティグループの設定警告や実行予定の ssh コマンドを出力しない。
  • --profile profile
    • ~/.aws/configure や ~/.aws/credentials のプロファイル切り替え
  • --dry-run
    • 実際には実行しない。インスタンスのユーザ名、IP アドレスを知りたいだけのときに有用。
  • instance
    • i- で始まっていればインスタンス ID をもとに、それ以外なら EC2 インスタンスに設定した Name タグをもとに、パブリック IP アドレスを自動で取得して ssh の対象ホストとする。
  • 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 エラーの対応

gist.github.com

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, サブネット順にソートしたりしてるんだよ。


gist.github.com