日記

日本語の勉強のためのブログ

uBlockOriginを使ってクリック済のリンクの色を変更する

以前こんな記事を書いた。

everykalax.hateblo.jp

これをuBlockOriginのフィルター機能で実現するには、uBlockOriginの「ダッシュボード」→「マイフィルター」に以下のフィルターを登録すればよい。

www.google.com##a:visited:style(color: green !important)

ドメインの部分(www.google.com)を変えれば別のサイトでも動作する。

参考

防衛省サイバーコンテスト 2024 writeup

32問中16問解けた。合計得点は188点で84位。あと数時間あれば…

進捗

あまり参考にならないかもしれないがwriteupを置いておく。
※解きながらwriteupを書いていたので、結局解けなかった問題についても記述してある。

Crypto

Information of Certificate (10)

Easy.crt ファイルは自己署名証明書です。証明書の発行者 (Issuer) のコモンネーム (CN) 全体を flag{} で囲んだものがフラグです。

証明書を開き、発行者欄のCNを見ればよい。

flag{QRK7rNJ3hShV.vlc-cybercontest.invalid}

Forensics

NTFS Data Hide (10)

NTFSDataHide フォルダに保存されている Sample.pptx を利用して、攻撃者が実行予定のスクリプトを隠しているようです。 仮想ディスクファイル NTFS.vhd を解析して、攻撃者が実行しようとしているスクリプトの内容を明らかにしてください。

この手の問題ははじめてだったので、よく使用されるツールから調べていく。 どうやら「FTK Imager」を使えばいいらしい。 起動したらウィンドウ左上の緑のボタンAdd Evidence Itemを押してImage Fileを選択、NTFS.vhdを指定してFinishを押す。これで左側のEvidence Treeに仮想ディスクのファイル構造が表示されるようになった。

…と思っていたがFTK Imagerでは解けなかった(ヒントを見てADSが鍵になっているとわかったものの、このツールではADSを確認できなかった)。代わりに「AutoPsy」というフォレンジックツールを導入したところ、NTFSDataHide/Sample.pptx:scriptというADSファイルが見つかった。中身を次に示す。

[System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('ZmxhZ3tkYXRhX2Nhbl9iZV9oaWRkZW5faW5fYWRzfQ=='))

このZmxhZ3tkYXRhX2Nhbl9iZV9oaWRkZW5faW5fYWRzfQ==という部分をbase64でデコードすればflagが得られる。

flag{data_can_be_hidden_in_ads}

NTFS File Delete (10)

NTFSFileDelete フォルダにフラグを記載した txt ファイルを保存したのですが、どうやら何者かによって消されてしまったようです。 問題「NTFS Data Hide」に引き続き、仮想ディスクファイル NTFS.vhd を解析して、削除された flag.txt に書かれていた内容を見つけ出してください。

FTK Imagerを利用し、NTFSFileDelete/flag.txtを確認すればよい。

flag{resident_in_mft}

HiddEN Variable (20)

このメモリダンプが取得された環境にはフラグが隠されています。 memdump.raw を解析して、フラグを見つけ出してください。

時間がなかったので即ヒントを開ける。Volatilityというツールで環境変数を確認すればよいとわかったのでpython3 vol.py -f ../memdump/memdump.raw windows.envarsを実行、大量のログの中にFLAG BDkPUNzMM3VHthkj2cVEjdRBqTJcfLMJaxT9si67RgJZ45PSとあったのでこれをbase58でデコード。

flag{volatile_environment_variable}

NTFS File Rename (20)

NTFSFileRename フォルダに保存されている Renamed.docx は、以前は別のファイル名で保存されていました。 問題「NTFS File Delete」に引き続き、仮想ディスクファイル NTFS.vhdを解析して、 Renamed.docx の元のファイル名を明らかにしてください。

FTK Imagerを利用。
(追記:AutoPsyだと瞬殺できると思う)

[root]/$LogFileにファイルの変更履歴が記されている(参考リンク)。 そのため$LogFileをエクスポートし、「LogFileParser」で詳しく調べる。

LogFileParserを実行すると複数のファイルが出力されるが、そのうちLogFileParser_vXXX\LogFile_XXX\LogFile_FileNames.csvにファイル名の変遷が記されている。 このファイルをExcelで開く。MftRefがMFTのレコード番号、つまりMFT(マスターファイルテーブル)におけるファイルの通し番号を示す。大雑把に言えば、この問題においては、MftRefが同じであれば同じファイルであるといってよい。 Renamed.docxと同じMftRefを持つファイルはjournaling_system_is_powerful.docxであるから、このファイルがリネームされてRenamed.docxになったと考えられる。

flag{journaling_system_is_powerful}

My Secret (30、解けなかった)

問題「HiddEN Variable」に引き続き、メモリダンプファイル memdump.raw を解析して、秘密(Secret)を明らかにしてください。

即ヒント開ける。7zip関連のプロセスを見ればよいとのことなので

$ python3 vol.py -f ../memdump/memdump.raw windows.pstree.PsTree | grep 7z 
**** 5516  100.03468    7z.exean0xe206bb303080  4       -       1       False   2023-12-26 00:51:23.000000      N/A     \Device\HarddiskVolume3\Program Files\7-Zip\7z.exe      7z  x -pY0uCanF1ndTh1sPa$$w0rd C:\Users\vauser\Documents\Secrets.7z -od:\        C:\Program Files\7-Zip\7z.exe

このSecrets.7zをダンプする。

$ python3 vol.py -f ../memdump/memdump.raw windows.dumpfiles --pid="5516"
Volatility 3 Framework 2.6.1
Progress:  100.00       PDB scanning finished
Cache   FileObject      FileName        Result

DataSectionObject 0xe206bbc4a2f0        Secrets.7z      Error dumping file
SharedCacheMap  0xe206bbc4a2f0  Secrets.7z      file.0xe206bbc4a2f0.0xe206bbabada0.SharedCacheMap.Secrets.7z.vacb
ImageSectionObject      0xe206bbc491c0  7z.dll  file.0xe206bbc491c0.0xe206bb46d770.ImageSectionObject.7z.dll.img
ImageSectionObject      0xe206bba6c490  7z.exe  file.0xe206bba6c490.0xe206b8b49730.ImageSectionObject.7z.exe.img
ImageSectionObject      0xe206b6121570  KernelBase.dll  file.0xe206b6121570.0xe206b610dc10.ImageSectionObject.KernelBase.dll.img
ImageSectionObject      0xe206b61210c0  win32u.dll      file.0xe206b61210c0.0xe206b62e17c0.ImageSectionObject.win32u.dll.img
ImageSectionObject      0xe206b9139e80  cryptbase.dll   file.0xe206b9139e80.0xe206b912bcc0.ImageSectionObject.cryptbase.dll.img
ImageSectionObject      0xe206b6122380  msvcp_win.dll   file.0xe206b6122380.0xe206b610e460.ImageSectionObject.msvcp_win.dll.img
ImageSectionObject      0xe206b6122ce0  gdi32full.dll   file.0xe206b6122ce0.0xe206b610e9a0.ImageSectionObject.gdi32full.dll.img
ImageSectionObject      0xe206b611bed0  oleaut32.dll    file.0xe206b611bed0.0xe206b62d5a50.ImageSectionObject.oleaut32.dll.img
ImageSectionObject      0xe206b61213e0  combase.dll     file.0xe206b61213e0.0xe206b62d6a20.ImageSectionObject.combase.dll.img
ImageSectionObject      0xe206b6122e70  ucrtbase.dll    file.0xe206b6122e70.0xe206b62da2b0.ImageSectionObject.ucrtbase.dll.img
ImageSectionObject      0xe206b61229c0  sechost.dll     file.0xe206b61229c0.0xe206b62d6cf0.ImageSectionObject.sechost.dll.img
ImageSectionObject      0xe206b611b3e0  advapi32.dll    file.0xe206b611b3e0.0xe206b62e1010.ImageSectionObject.advapi32.dll.img
ImageSectionObject      0xe206b6121250  imm32.dll       file.0xe206b6121250.0xe206b62d7cc0.ImageSectionObject.imm32.dll.img
ImageSectionObject      0xe206b611c380  rpcrt4.dll      file.0xe206b611c380.0xe206b62e3cd0.ImageSectionObject.rpcrt4.dll.img
ImageSectionObject      0xe206b611c830  user32.dll      file.0xe206b611c830.0xe206b62d5d00.ImageSectionObject.user32.dll.img
ImageSectionObject      0xe206b611c9c0  gdi32.dll       file.0xe206b611c9c0.0xe206b62e3a20.ImageSectionObject.gdi32.dll.img
ImageSectionObject      0xe206b611c510  msvcrt.dll      file.0xe206b611c510.0xe206b62e06c0.ImageSectionObject.msvcrt.dll.img
ImageSectionObject      0xe206b611ce70  kernel32.dll    file.0xe206b611ce70.0xe206b62e3520.ImageSectionObject.kernel32.dll.img
ImageSectionObject      0xe206b0ef9940  ntdll.dll       file.0xe206b0ef9940.0xe206b0bc5010.ImageSectionObject.ntdll.dll.img

file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.datを7zで解凍したがエラーが出る。パスワードが違う?

$ 7z  x -pY0uCanF1ndTh1sPa$$w0rd file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,6 CPUs Intel(R) Core(TM) i5-8500 CPU @ 3.00GHz (906EA),ASM,AES-NI)

Scanning the drive for archives:
1 file, 4096 bytes (4 KiB)

Extracting archive: file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat

WARNINGS:
There are data after the end of archive

--
Path = file.0xe206bbc4a2f0.0xe206bb499920.DataSectionObject.Secrets.7z.dat
Type = 7z
WARNINGS:
There are data after the end of archive
Physical Size = 418
Tail Size = 3678
Headers Size = 146
Method = LZMA2:12 7zAES
Solid = -
Blocks = 1

ERROR: Data Error in encrypted file. Wrong password? : Secrets.rtf

Sub items Errors: 1

Archives with Errors: 1

Warnings: 1

Sub items Errors: 1

別の方法でダンプを試みたがダメだった。

$ python3 vol.py -f ../memdump/memdump.raw windows.dumpfiles --physaddr 0xe206bbc4a2f0   
Volatility 3 Framework 2.6.1
Progress:  100.00       PDB scanning finished
Cache   FileObject      FileName        Result
(※注:何も出力されなかった)

Miscellaneous

Une Maison (10)

画像 maison.jpg の中にフラグが隠されています。探してみてください。

stringsでもfileでも異常なし。steghideも違った。 わからずヒント1を開くと、

メタデータやバイナリの解析は必要ありません。

とのこと。とりあえず画像検索してみると似た画像が出てきたが、一部異なる部分がある。よく見るとバーコードになっていたため、そこを切り出してGoogle Lensに投げるとflagが得られた。

切り取ったバーコード

flag{$50M!}

String Obfuscation (10)

難読化された Python コード string_obfuscation.py ファイルからフラグを抽出してください。

ソースコードを見ると

FLAG = chr(51)+chr(70)+chr(120)+chr(89)+chr(70)+chr(109)+chr(52)+chr(117)+chr(84)+chr(89)+chr(68)+chr(70)+chr(70)+chr(122)+chr(109)+chr(98)+chr(51)

との表記があるので、これをそのままprintしてやればよい。

$ python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> FLAG = chr(51)+chr(70)+chr(120)+chr(89)+chr(70)+chr(109)+chr(52)+chr(117)+chr(84)+chr(89)+chr(68)+chr(70)+chr(70)+chr(122)+chr(109)+chr(98)+chr(51)
>>> print(FLAG)
3FxYFm4uTYDFFzmb3

flag{3FxYFm4uTYDFFzmb3}

Where Is the Legit Flag? (20)

fakeflag.py を実行しても偽のフラグが出力されてしまいます。難読化されたコードを解読し、本物のフラグを見つけ出してください。

fakeflag.pyの難読化を解除すると、次のようになる。

exec(chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(32)+chr(122)+chr(108)+chr(105)+chr(98)+chr(44)+chr(32)+chr(98)+chr(97)+chr(115)+chr(101)+chr(54)+chr(52)) 
# ↳ exec("import zlib, base64")

TANAKA = "eJyNVG1320QT/Z5z8h+GhNYvcR35JZZdaCGhT6D0gQTiFKjjlpU0ljZe7272xYpoy2/vrJRA+MA56IOPrJ29e+feO7sP84JJ2CohsEqYELBlktsCWM64tA6E3+gKEjSm6u/uXBzPz+AZtBY/vRx91Unffv908vOrw9PXz7/E23h/nf2mtp9/Gz05fn9zbv8sB18f/P7DWa9o/5/1f/Hf6KMlhzfJ9YvZ/x4NKzk185PNF6vud3uf/Xjx0eV/PLsUvz4ev/tw1bq6au3u7MNxorYIK5Yi4K0WRAhWyoAuKstTJiDDlFuuZB9C9WvOwEq2RpBsg2CUlxk4Is5XPIXEMGubwlNqVpVc5mB9nqN1BAG2LjeYM5OFpRVumCAUTPF+31yVtAhb+oB0OLcsN4ikjUTmCih8jqCVoSODUpdvLl+9JK0W8fhJdBD1dnfg7pnG3UGPS9ceT7vdQYdW9uFstQLtjVYWQTBiwiwYb6hJ65jDDUpHoPcIYfP03ahTo4yG/Sg8zb/WaNwKkPel8QQeQ3R7etqLh/CB3qKoF8/gbfO2mBwtF9GypvDCm9D4WipHbYsKLCP1S4MuLTADmzISw6gyiHGP3h52euMY+ArmxpNLguhHNY/B8JBaG0TwCAaDnjJZOy1MezjpPCQ3ig6O7pQ4HHYJa9adLQMXOBfeglMIFp0jH0pOCm8ZBZJSialrHIGLQJECnFmwBQqSvqk0zLkKtFGZT5GEo9Iz7yzPSF3MLUhynYw0NpximLzxXISmWchCU39soWRiDZqRHE04eF64lRfAsi0n2JrCCdaomlXBowBGKU0qMtFQHNYYpmYfzgPzBAu25SHAiv65Jk1esoT6K9TmDhCON4psoLhT7FO1aXKfKhnOqR3ykjwq6Zs3pslFG8K+hqXVzKzJLWVSmuJ6gqxWQY7cMF0fEqRvtWjLpSTIJr3XWFKo00Jp6oXoZaiRVqklmh8RNAy7+uHnWhGhf33ai7/9DQ5xWfeRlJiA4wiKkl544yjYoZu7S2XBl38h/Ldd4SbglAZoJu3hoRRHDs9hHA+nT/9Bhp7EIFs//OhoRoej8WQSQxemo3h69HBV02mu7Q5H46M4no46tUPzgqTOC7jxiBIytiF6YAXXGk1Ve8YMt3WQls2OkyqEKQyzUXRBhYwqT83QQKGjJVtQbVN6pike3CFUoVIijV7SZMx6wk/CjUzXcfCxIbe3Eip/P91e46z0MtGz6fjjHmHt7nwCLpe/Qg=="

TAKAHASHI = [0x7a,0x7a,0x7a,0x12,0x18,0x12,0x1d,0x12,0x07,0x7b,0x36,0x37,0x3c,0x30,0x36,0x37,0x67,0x65,0x31,0x7d,0x67,0x65,0x36,0x20,0x32,0x31,0x7b,0x20,0x20,0x36,0x21,0x23,0x3e,0x3c,0x30,0x36,0x37,0x7d,0x31,0x3a,0x3f,0x29,0x7b,0x30,0x36,0x2b,0x36]
exec(bytes([WATANABE ^ 0b01010011 for WATANABE in reversed(TAKAHASHI)]))
# ↳ exec(b'exec(zlib.decompress(base64.b64decode(TANAKA)))')

ここでexec(b'exec(zlib.decompress(base64.b64decode(TANAKA)))')を実行すると、以下のコードが実行される。

# Than volleyball vanish against lumpy berry.
SATO = '[QI3?)c^J:6RK/FV><ex7#kdYov$G0-A{qPs~w1@+`MO,h(La.WuCp5]i ZbjD9E%2yn8rTBm;f*H"!NS}tgz=UlX&4_|\'\\'
# Above face explain for physical decision.
# Via snake name round terrific brass.
# Following suggestion sound regarding female recess.
# Toward vessel disagree beneath huge porter.
SUZUKI = [74-0+0,
        87*1,int(48**1),
# Off purpose land as rural statement.
        int(8_3),int(32.00000),int('34'),
        76 & 0xFF,72 | 0x00,79 ^ 0x00,[65][0],
# During knot rely save wretched scarecrow.
        (2),47 if True else 0,int(12/1),10 % 11,ord(chr(26)),
        30+5,int(48/2*2),9*9]
#  Plus toe settle with vast insect.
#  Save hands shelter with ratty produce.
#  Outside legs nest versus tranquil relation.
#  As walk pat round rightful advice.
# Beside payment train by large key.
# Past behavior post toward unable home.
#  Among place complain considering unknown current.
( #  Around spark scorch above spotty grape.
    ''#  Underneath jewel chop past dependent rifle.
    .    join                          ([
        #  Since cobweb tie off hurt string.
SATO[i]         #  Since cobweb tie off hurt string.
for i in SUZUKI
        # if i > 4728:
        #     break
        # t = 234667 * 83785
        # print(t/3457783)
#  Through queen dam of slippery comparison.
])
#  By wall stroke without secret wash.
)
#  Opposite yoke need beside superb lumber.
print("flog{8vje9wunbp984}")

これを整形したコードを次に示す。

SATO = '[QI3?)c^J:6RK/FV><ex7#kdYov$G0-A{qPs~w1@+`MO,h(La.WuCp5]i ZbjD9E%2yn8rTBm;f*H"!NS}tgz=UlX&4_|\'\\'
SUZUKI = [74-0+0,87*1,int(48**1),int(8_3),int(32.00000),int('34'),76 & 0xFF,72 | 0x00,79 ^ 0x00,[65][0],(2),47 if True else 0,int(12/1),10 % 11,ord(chr(26)),30+5,int(48/2*2),9*9]
(''.join([SATO[i] for i in SUZUKI]))
print("flog{8vje9wunbp984}")

注目すべきなのは3行目の(''.join([SATO[i] for i in SUZUKI]))である。この処理の結果はどこからも参照されていないので、試しにprintしてみる。するとflagが得られた。

flag{PHmN2ILK6vsa}

Network

FileExtract (10)

添付の FileExtract.pcapng ファイルからフラグを見つけ出し、解答してください。

wiresharkで添付ファイルを開く。ファイル -> オブジェクトをエクスポート → FTP-DATAをクリックすると、s3cr3t.zipなるファイルをエクスポートできる。しかしパスワードがかかっており解凍できない。 パケットを眺めると230 Login successfulという記述が見つかったため、この前後のパケットを見ると、Request: PASS br2fWWJjjab3という記述を発見。br2fWWJjjab3をパスワードとしたところ、s3cr3t.zipを解凍することができ、中身のファイルfl@gを確認できた。

flag{6qhFJSHAP4A4}

Programming

Logistic Map (10)

下記のロジスティック写像について、x_0 = 0.3 を与えた時の x_9999 の値を求め、小数第7位までの値を答えてください(例:flag{0.1234567})。なお、値の保持と計算には倍精度浮動小数点数を使用してください。 x_{n+1} = 3.99 x_n (1 - x_n)

Pythonで解いた。

x: float = 0.3
for i in range(1, 10000): # x_1 ... x_9999
    x = 3.99 * x * (1 - x)

print(x)
# -> 0.8112735...

flag{0.8112735}

Trivia

The Original Name of AES (10)

Advanced Encryption Standard (AES) は、公募によって策定された標準暗号です。 現在採用されているアルゴリズムの候補名は何だったでしょうか?

wikipediaを見る。

Advanced Encryption Standard (AES) は、アメリカが2001年に標準暗号として定めた共通鍵暗号アルゴリズムである。アメリカ国立標準技術研究所(NIST)が公募し、Rijndael(ラインダール)がAESとして採用された。 (https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard より引用)

flag{Rijndael}

CVE Record of Lowest Number (10)

最も番号が若い CVE レコードのソフトウェアパッケージにおいて、脆弱性が指摘された行を含むソースファイル名は何でしょう?

最も番号が若いCVEレコードは、GitHubに上がっているCVEリストより、CVE-1999-0001であるとわかる。 この脆弱性の詳細を調べると、

BSD 由来の TCP/IP 実装の ip_input.c により、リモート攻撃者は細工されたパケットを介してサービス拒否 (クラッシュまたはハング) を引き起こすことができます。 (https://www.cvedetails.com/cve/CVE-1999-0001/ より引用、google翻訳使用)

とあるので、脆弱性が指摘された行を含むソースファイル名ip_input.cである。

flag{ip_input.c}

MFA Factors (10)

多要素認証に使われる本人確認のための3種類の情報の名前は何でしょう?それぞれ漢字2文字で、50音の辞書順で並べて「・」で区切ってお答えください。

IPAによると多要素認証に使われる本人確認のための3種類の情報は記憶情報、所持情報、生体情報である。

flag{記憶・所持・生体}

Web

Browsers Have Local Storage (10)

http://10.10.10.30 にアクセスしてフラグを見つけ出し、解答してください。

問題タイトルにあるように、ローカルストレージにflagが書いてある。ブラウザのF12キーを押して開発者ツールを起動し、アプリケーション -> ストレージ -> ローカルストレージで確認できる。

FLAG{Th1s_1s_The_fIrst_flag}

Are You Introspective? (10、解けなかった)

http://10.10.10.31 にアクセスしてフラグを見つけ出し、解答してください。 このサイトでは GraphQL が使用されているため、まずは endpoint を探す必要があります。

そもそもエンドポイントとは何かというと、APIの呼び出しが行われる場所APIにアクセスするためのURIのことらしい。

エンドポイントを探す必要があるが、goctopus(docker run --rm -it escapetech/goctopus:latest -a 10.10.10.31)を使用しても見つからなかった。

Insecure (20)

あなたは社内ポータルサイト(http://10.10.10.33)の管理者に依頼されて、profile ページが安全に保護されているかチェックすることになりました。 以下のログイン情報を用いてサイトにログインし、管理者の profile ページに記載されている秘密の情報を見つけてください。 なお、依頼の際に「管理者ページのidは0だよ」というヒントをもらっています。

testUserとしてログイン後、ページ下部の「プロフィールを見る」(http://10.10.10.33/show_profile.php?id=1)をクリックすると、プロフィールページ(http://10.10.10.33/profile_success.php)に遷移した。 次に、管理者のidが0であるというヒントを利用し、管理者のプロフィール(http://10.10.10.33/show_profile.php?id=0)にアクセスしてみたが、エラーページ(http://10.10.10.33/profile_error.php)に遷移してしまった。

そこで、BurpSuiteを用いて強引に管理者プロフィールにアクセスする。具体的には、

  1. BurpSuiteを起動、InterceptをONにしてから「プロフィールを見る」(http://10.10.10.33/show_profile.php?id=1)をクリック
  2. BurpSuiteでid=0id=1に書き換えてForward
  3. http://10.10.10.33/profile_error.phpにリダイレクトされるので、同じくBurpSuiteで遷移先をprofile_error.phpからprofile_success.phpに書き換えてForward

以上のプロセスを踏むことで管理者プロフィールにアクセスでき、フラグを得られる。

FLAG{1qaz7ujmbgt5}

Variation (20、解けなかった)

http://10.10.10.32 のWebサーバーで下記形式の XSS を発生させ、フラグを入手してください。 <script>alert(1)</script>

与えられたWebページでNameを入力してSubmitボタンを押すと、入力したNameが表示されるという問題。 試しに<script>alert(1)</script>を入力したところ、Hey, scriptalert(1)/scriptと表示された。 <>が削除されているため、パーセントエンコーディングして%3Cscript%3Ealert(1)%3C/script%3Eを入力してみたが、そのままHey, %3Cscript%3Ealert(1)%3C/script%3Eと出力されてしまう。

パーティションの移動

中古PCを買ったら1つのSSDがCドライブとDドライブに分割されていた。
個人的にDドライブは使わないため、Cドライブに統一しようとしたが、

EFIシステムパーティション:Cドライブ:回復パーティション:Dドライブ

のようにC・Dドライブが隣り合っておらず、簡単にはマージできない。

図1. 購入時のパーティションの様子(ディスク0に注目。なおDドライブのパーティションはすぐ削除してしまったため、未割り当てと記載されている)

買ってすぐなので初期化も構わないと考え、少々強引な方法でドライブの統合を行うことにした。

環境

  • Windows 11 Pro
    • Homeエディションでもいけると思う

方法

1. 回復ドライブの作成

失敗したときのお守りを作っておく。 あくまでも起動すらしなくなった際のお守りであり、基本的に使うことはないと思うが一応。

2. パーティションを移動

適当なソフトを使って移動する。今回は以下に沿って「AOMEI Partition Assistant Standard」というソフトを使用した。これで正常に統合できれば終了だが…

www.diskpart.com

非常にわかりやすく直感的に移動できたのはいいが、回復パーティションの表示がおかしくなっている

図2. 移動後のパーティションの様子。「正常(回復パーティション)」という表記が消えている

追記:diskpartで確認したところちゃんと回復パーティションとして認識されていた。実際に回復環境も動作するようなので問題なさそう。

図3. diskpartでの確認結果

M5Stack core2で能登地方の強震モニタを表示する

余震が続いているのもあり、Vivaldiのウェブパネルに強震モニタを表示しているが、常時表示しておくのが面倒なのでM5Stack core2にやらせたい。
全国版の強震モニタについてはM5Stack(core2ではない)で作成された方がいらっしゃる↓ため、これをcore2に移植しつつ、能登地方バージョンに改変する。

www.ria-lab.com

作成した能登地方バージョンはGitHubに置いた。

github.com

以下、移植時の改変点などを記載する。

ボード情報やライブラリの変更

ボード情報やライブラリ名をcore2用に書き換える必要がある。書き換え後は以下の通り。

main.cpp<M5Stack.h><M5Core2.h>に置換)

#include <AnimatedGIF.h>
#include <Arduino.h>
#include <HTTPClient.h>
#include <M5Core2.h>
#include <WiFi.h>
#include <WiFiMulti.h>
(後略)

platformio.ini

[env:m5stack-core2]
platform = espressif32
board = m5stack-core2
framework = arduino
monitor_speed = 115200
lib_deps = 
    bitbank2/AnimatedGIF@^1.3.2
    paulstoffregen/Time@^1.6
    mbed-kazushi2008/HTTPClient@0.0.0+sha.cf5d7427a9ec
    m5stack/M5Core2@^0.1.8

※なお、monitor_speedについてはシリアルモニタの文字化け防止*1に記載したもので、必須ではない。

音声をバイブに変更

core2では音の鳴らし方が変更されたようで、移植にあたり対応が必要となる。 しかし対応が難しいと感じたため、バイブレーションで代用することにした。

具体的には、main.cppに次のような関数

void vibrate(unsigned int vibLength = 500) {
  M5.Axp.SetLDOEnable(3, true);
  delay(vibLength);
  M5.Axp.SetLDOEnable(3, false);
}

を定義して、M5.Speakerの関数が使われている部分をすべてvibrate()で置換した。

能登地方を表示する

強震モニタの画像のURLに_notoを付け加えることで、能登地方のマップを表示させることができる*2

具体的にはmain.cpp内のURLを以下のように変更すればよい。

http://www.kmoni.bosai.go.jp/data/map_img/CommonImg/
-> http://www.kmoni.bosai.go.jp/data/map_img/CommonImg_noto/
http://www.kmoni.bosai.go.jp/data/map_img/EstShindoImg/
-> http://www.kmoni.bosai.go.jp/data/map_img/EstShindoImg_noto/
http://www.kmoni.bosai.go.jp/data/map_img/PSWaveImg/
-> http://www.kmoni.bosai.go.jp/data/map_img/PSWaveImg_noto/
http://www.kmoni.bosai.go.jp/data/map_img/RealTimeImg/
-> http://www.kmoni.bosai.go.jp/data/map_img/RealTimeImg_noto/

しかし、強震モニタ背景に表示される日本地図の画像CommonImg/base_map_w.gifが16.4kBなのに対し、能登地方の地図画像を指すCommonImg_noto/base_map_w.gifは50.9kBと非常に大きい。そのため次のように画像ダウンロード用のバッファ容量を増やしておく必要がある点に注意。

main.cpp

(前略)
unsigned long file_buffer_size;    // ダウンロードしたサイズ
unsigned char file_buffer[51000];  // ダウンロード用のバッファ
(後略)

GPU使用可能なtensorflowが入ったconda環境の構築

minicondaを入れてから仮想環境を構築するまで、以下のコードでまとめて実行できる。
GPUのドライバ設定等はすでに済んだものとする

Ubuntu 22.04.3 LTS & NVIDIA RTX A4500が載ったサーバで動作確認済。

# minicondaをダウンロードして実行権限を与える
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
chmod a+x Miniconda3-latest-Linux-x86_64.sh

# インストールする。実行後にライセンス全部読んでyes -> インストール場所確認してEnter -> initしていいかと聞かれるのでyes
./Miniconda3-latest-Linux-x86_64.sh 

# シェルを再起動
exec $SHELL -l
# 仮想環境を作る。ここではtensorflow2.12.0、Python3.11の環境を作っている。動作確認でうまくいかない場合はこのバージョンをいろいろ変えてみよう
conda create -n tf-2.12.0 tensorflow=2.12.0=gpu_py311h65739b5_0 -y

# 作った仮想環境に入る(これは毎回起動時にやる必要がある)
conda activate tf-2.12.0

# 動作確認。GPUが使えるかチェックする。実行してGPUのリストが出てくればOK
python -c "import tensorflow as tf;print(tf.config.list_physical_devices('GPU'))"

補足

  • 仮想環境リストを表示するにはconda info -e
  • 仮想環境を削除するときはconda remove -n <仮想環境名> --all

参考リンク