UbuntuでUSBメモリの構造解析を行う

セキュリティ

Ubuntuを使ってUSBメモリの構造解析を行いましたので備忘録です。
後半は脱線して、データの復元実験になっています。

環境

Windows11home
VMware上でUbuntu25.04LTS

やりたいこと

USBメモリのファイル構造確認
削除したテキストデータがUbuntuで復元できるか

手順

VM上のUbuntuにUSBメモリを認識させる(マウント)

 UbuntuからUSBメモリにアクセスする必要があります。
 Ubuntuを起動した状態で、PCにUSBメモリを挿入すると自動でマウントされます。
 マウント先をWindowsにするのか、VMにするのか尋ねられるので、VM上のUbuntuを選択します。

検索窓から[disk]と検索して、「ディスク」アプリを起動させます。

USBメモリを認識していることがわかります。
マウント先は、/media/user_name/USBMEMORY
デバイスは、/dev/sdb
フォーマットは、NTFS
となっていることが確認できました。

データの確認方法

コンソールから次のコマンド入力で、USBメモリ内のファイルを確認できます

# データの確認
$ cd /media/{username}/USBMEMORY
$ ls
'System Volume Information'   testdata.txt
$ cat ./testdata.txt 
this is test data (データの内容)

# USBメモリ上にはテストデータファイルがおかれている。

USBメモリのデータを出力する

 ddコマンドはWindowsのロボコピーのようなコマンドです。
 ブロック単位でデータを扱うことができ、ファイルの属性情報を変更することなく複写することもできます。
 ddコマンドを使ってUSBメモリに保存されている情報を表示させると、バイナリデータまで表示しようとするので、文字化けします。
 可読部分にはブータブルディスクではないとの説明が記録されていますね。

# USBメモリのデータ表示(先頭512バイト)
# if -> inputfile (デバイス名を指定 今回だと/dev/sdb)
# bs -> bufferstring(一度に何バイト読み込むか)
# skip -> 先頭データをどれだけ読み飛ばすか
# count -> 何回読み込むか
# status=none -> 余分なデータを表示させない

# USBメモリのデータを先頭から512バイト読み込んだ様子

sudo dd if=/dev/sdb bs=512 skip=0 count=1 status=none
�q|�"�t   �>?���?<����3o��
       V���^��2�����This is not a bootable disk. Please insert a bootable floppy and
press any key to try again ... 

バイナリデータを含んでいるのでダンプ表示した方がよさそうです。

# 先頭から512バイト分のダンプデータを表示させた様子
# hexdump -C -> 16進数で表示し、ASCIIコードも出力する

$ > sudo dd if=/dev/sdb bs=512 skip=0 count=1 status=none | hexdump -C
00000000  eb 52 90 4e 54 46 53 20  20 20 20 00 02 08 00 00  |.R.NTFS    .....|
00000010  00 00 00 00 00 f8 00 00  3e 00 3f 00 00 00 00 00  |........>.?.....|
00000020  00 00 00 00 80 00 80 00  ff 3f 3c 00 00 00 00 00  |.........?<.....|
00000030  04 00 00 00 00 00 00 00  ff c3 03 00 00 00 00 00  |................|
00000040  f6 00 00 00 01 00 00 00  a9 33 06 6f ed f3 96 0d  |.........3.o....|
00000050  00 00 00 00 0e 1f be 71  7c ac 22 c0 74 0b 56 b4  |.......q|.".t.V.|
00000060  0e bb 07 00 cd 10 5e eb  f0 32 e4 cd 16 cd 19 eb  |......^..2......|
00000070  fe 54 68 69 73 20 69 73  20 6e 6f 74 20 61 20 62  |.This is not a b|
00000080  6f 6f 74 61 62 6c 65 20  64 69 73 6b 2e 20 50 6c  |ootable disk. Pl|
00000090  65 61 73 65 20 69 6e 73  65 72 74 20 61 20 62 6f  |ease insert a bo|
000000a0  6f 74 61 62 6c 65 20 66  6c 6f 70 70 79 20 61 6e  |otable floppy an|
000000b0  64 0d 0a 70 72 65 73 73  20 61 6e 79 20 6b 65 79  |d..press any key|
000000c0  20 74 6f 20 74 72 79 20  61 67 61 69 6e 20 2e 2e  | to try again ..|
000000d0  2e 20 0d 0a 00 00 00 00  00 00 00 00 00 00 00 00  |. ..............|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200

#データ中に*が表示されているのは、連続した[0]データを省略しているとのことでした。

 データの頭部分を確認すると、
   NTFS
の文字列があることから、NTFSでフォーマットされていることがわかります。

解析キット(sleuthkit)を使用してみる

 sleuthkitという解析用ライブラリがあると聞き、さっそく使ってみました。
 わからないことも多いのですが、こちらの記の説明が非常にわかりやすかったので参考にさせていただきました。(https://qiita.com/iria_piyo/items/f3e9468f03e23f779c8d

インストール

aptでインストールするので、インストール自体は何も難しいところはありません。
 公式サイトはこちら https://www.sleuthkit.org/index.php
 フォレンジックツールで有名なAutopsyを作っている方ですね。

# sleuthkitのインストール
$ > sudo apt install sleuthkit

 基本となるディスクシステムのレイアウトを表示させます。
 次のコマンドで実行しました。
 実行には管理者権限が必要です。

# ディスクシステムのレイアウト表示
$ >  sudo fsstat /dev/sdb
FILE SYSTEM INFORMATION
--------------------------------------------
File System Type: NTFS
Volume Serial Number: 0D96F3ED6F0633A9
OEM Name: NTFS    
Volume Name: USBMEMORY
Version: Windows XP

METADATA INFORMATION
--------------------------------------------
First Cluster of MFT: 4
First Cluster of MFT Mirror: 246783
Size of MFT Entries: 1024 bytes
Size of Index Records: 4096 bytes
Range: 0 - 256
Root Directory: 5

CONTENT INFORMATION
--------------------------------------------
Sector Size: 512
Cluster Size: 4096
Total Cluster Range: 0 - 493566
Total Sector Range: 0 - 3948542

$AttrDef Attribute Values:
$STANDARD_INFORMATION (16)   Size: 48-72   Flags: Resident
$ATTRIBUTE_LIST (32)   Size: No Limit   Flags: Non-resident
$FILE_NAME (48)   Size: 68-578   Flags: Resident,Index
$OBJECT_ID (64)   Size: 0-256   Flags: Resident
$SECURITY_DESCRIPTOR (80)   Size: No Limit   Flags: Non-resident
$VOLUME_NAME (96)   Size: 2-256   Flags: Resident
$VOLUME_INFORMATION (112)   Size: 12-12   Flags: Resident
$DATA (128)   Size: No Limit   Flags: 
$INDEX_ROOT (144)   Size: No Limit   Flags: Resident
$INDEX_ALLOCATION (160)   Size: No Limit   Flags: Non-resident
$BITMAP (176)   Size: No Limit   Flags: Non-resident
$REPARSE_POINT (192)   Size: 0-16384   Flags: Non-resident
$EA_INFORMATION (208)   Size: 8-8   Flags: Resident
$EA (224)   Size: 0-65536   Flags: 
$LOGGED_UTILITY_STREAM (256)   Size: 0-65536   Flags: Non-resident

いろいろな情報が表示されているのがわかりますが、私の力では有効活用できそうにありません。

ファイルとフォルダの一覧を取得する

次のコマンドでファイルとフォルダの一覧が取得できました。

# ファイルとフォルダの一覧を取得
$ > sudo fls /dev/sdb -a
r/r 4-128-1:	$AttrDef
r/r 8-128-2:	$BadClus
r/r 8-128-1:	$BadClus:$Bad
r/r 6-128-1:	$Bitmap
r/r 7-128-1:	$Boot
d/d 11-144-2:	$Extend
r/r 2-128-1:	$LogFile
r/r 0-128-1:	$MFT
r/r 1-128-1:	$MFTMirr
r/r 9-128-2:	$Secure:$SDS
r/r 9-144-7:	$Secure:$SDH
r/r 9-144-10:	$Secure:$SII
r/r 10-128-1:	$UpCase
r/r 10-128-2:	$UpCase:$Info
r/r 3-128-3:	$Volume
d/d 5-144-3:	.
d/d 36-144-1:	System Volume Information
r/r 39-128-1:	testdata.txt
V/V 256:	$OrphanFiles

 このUSBメモリには、ファイルは1個しか保存していないのですが、裏ではこんなにたくさんのファイルが作られているのですね。
 ちなみに、ファイルかフォルダの判断は
  r/r → ファイル
  d/d → フォルダ
とのことでした。
 NTFSでは、ファイルの管理を、inode番号で管理しているとのこと。
 testdata.txt のinode番号は「39-128-1」となります。

削除済データの確認

次のコマンドでは、過去に削除されたデータのinode番号が確認できます。
ファイル名が確認できないので、内容は勘だよりです(調べ方あるのかな?)

# 削除されたデータの一覧
$ > sudo fls /dev/sdb -dr
-/r * 16:	$OrphanFiles/OrphanFile-16
-/r * 17:	$OrphanFiles/OrphanFile-17
-/r * 18:	$OrphanFiles/OrphanFile-18
-/r * 19:	$OrphanFiles/OrphanFile-19
-/r * 20:	$OrphanFiles/OrphanFile-20
-/r * 21:	$OrphanFiles/OrphanFile-21
-/r * 22:	$OrphanFiles/OrphanFile-22
-/r * 23:	$OrphanFiles/OrphanFile-23

結構残っているのですね。

データのステータスを表示

inode番号を使ってファイルのステータス情報を表示させるコマンドは次の通りです。

# inode番号を使ってファイルのステータスを表示させる
$ > sudo istat /dev/sdb 39-128-1
MFT Entry Header Values:
Entry: 39        Sequence: 1
$LogFile Sequence Number: 4203978
Allocated File
Links: 1

$STANDARD_INFORMATION Attribute Values:
Flags: Archive
Owner ID: 0
Security ID: 266  (S-1-5-21-1475737012-*********-********)
Created:	2025-10-05 13:10:28.676903600 (JST)
File Modified:	2025-10-05 13:04:40.960203200 (JST)
MFT Modified:	2025-10-05 13:10:30.206093100 (JST)
Accessed:	2025-10-05 13:16:19.829337800 (JST)

$FILE_NAME Attribute Values:
Flags: Archive
Name: testdata.txt
Parent MFT Entry: 5 	Sequence: 5
Allocated Size: 24   	Actual Size: 19
Created:	2025-10-05 13:10:28.676903600 (JST)
File Modified:	2025-10-05 13:04:40.960203200 (JST)
MFT Modified:	2025-10-05 13:10:30.206093100 (JST)
Accessed:	2025-10-05 13:16:19.829337800 (JST)

$OBJECT_ID Attribute Values:
Object Id: 334e76e7-a18f-11f0-bac0-********

Attributes: 
Type: $STANDARD_INFORMATION (16-0)   Name: N/A   Resident   size: 72
Type: $FILE_NAME (48-2)   Name: N/A   Resident   size: 90
Type: $OBJECT_ID (64-3)   Name: N/A   Resident   size: 16
Type: $DATA (128-1)   Name: N/A   Resident   size: 19

ファイルの作成日、更新日、作成者の属性がわかるようです。

データの内容を表示、別ファイルに出力

inode番号を使ってファイルの内容を表示させるコマンドは次の通りです。

# inode番号を使ってファイルの内容を表示させる
$ > sudo icat /dev/sdb 39-128-1
this is test data

# 結果をファイル出力する
$ > sudo icat /dev/sdb 39-128-1 > out.txt
$ > cat ./out.txt 
this is test data

今回はテキストファイルだったのでそのままデータの内容が表示できましたが、画像だったりするとバイナリで表示する必要がありますね。

データを削除して表示させる

 先ほど表示させたtestdata.txtの内容を
   書き換え → 保存 → ファイル名変更 → 削除
し、この値を表示することができるか実験しました。
 キャッシュデータを読み込んでくる心配があったので、データを削除した後、USBメモリを一度外して再マウントしてあります。
 次のコマンドで削除データを表示させます。

# 削除されたデータ一覧の表示
$ > sudo fls /dev/sdc -dr (/dev/sdb -> dev/sdcに変わっています)
-/r * 16:	$OrphanFiles/OrphanFile-16
-/r * 17:	$OrphanFiles/OrphanFile-17
-/r * 18:	$OrphanFiles/OrphanFile-18
-/r * 19:	$OrphanFiles/OrphanFile-19
-/r * 20:	$OrphanFiles/OrphanFile-20
-/r * 21:	$OrphanFiles/OrphanFile-21
-/r * 22:	$OrphanFiles/OrphanFile-22
-/r * 23:	$OrphanFiles/OrphanFile-23 (ここまでは前の実験)
-/r * 39-128-1:	$OrphanFiles/OrphanFile-39
-/r * 44-128-2:	$OrphanFiles/OrphanFile-44
-/r * 45-128-2:	$OrphanFiles/OrphanFile-45
-/r * 48-128-2:	$OrphanFiles/OrphanFile-48
-/r * 49-128-2:	$OrphanFiles/OrphanFile-49

 先ほどまで表示されていないデータがいくつも増えています。
 削除に手間取ったからか、いくつもファイルができていました。
 データを順番に確認していきます。

# 削除データの確認

$ > sudo icat /dev/sdc 49-128-2
# 何も表示されない
$ > sudo icat /dev/sdc 48-128-2
# 何も表示されない
$ > sudo icat /dev/sdc 45-128-2
# 何も表示されない
$ > sudo icat /dev/sdc 44-128-2
# 何も表示されない
$ > sudo icat /dev/sdc 39-128-1
this is test data
# 削除データが表示された

データを書き換えて保存したため、このような形になったのではないかと思います。
一番最初のデータだけが残り、このほかのデータは何も表示されまでんでした。

新規作成したファイルを削除して内容を復元する

次のコマンドでファイルを新規作成し、文字入力をした後削除しました。

# ファイルを新規作成し、文字列を入れたファイルを削除する

# ファイルの新規作成
$ > touch newfile.txt
$ > ls (USBMEMORYフォルダ)
'System Volume Information'   newfile.txt(新しいファイル)
$ nano newfile.txt 
$ cat newfile.txt 
onew file (書き込んだ文字列)
# 書き込んだ文字列

$ rm newfile.txt 
$ ls
'System Volume Information'
# 作成したファイルが消えている

次の方法で復元します。

# 削除ファイル一覧の表示
$ sudo fls /dev/sdc -dr
-/r * 16:	$OrphanFiles/OrphanFile-16
-/r * 17:	$OrphanFiles/OrphanFile-17
-/r * 18:	$OrphanFiles/OrphanFile-18
-/r * 19:	$OrphanFiles/OrphanFile-19
-/r * 20:	$OrphanFiles/OrphanFile-20
-/r * 21:	$OrphanFiles/OrphanFile-21
-/r * 22:	$OrphanFiles/OrphanFile-22
-/r * 23:	$OrphanFiles/OrphanFile-23
-/r * 39-128-1:	$OrphanFiles/OrphanFile-39
-/r * 44-128-2:	$OrphanFiles/OrphanFile-44
-/r * 45-128-2:	$OrphanFiles/OrphanFile-45
-/r * 48-128-2:	$OrphanFiles/OrphanFile-48
-/r * 49-128-2:	$OrphanFiles/OrphanFile-49 (ここまでは前の実験)
-/r * 51-128-2:	$OrphanFiles/OrphanFile-51
-/r * 52-128-5:	$OrphanFiles/OrphanFile-52

# 復元
$ sudo icat /dev/sdc 52-128-5
# 何も表示されない
$ sudo icat /dev/sdc 51-128-2
onew file

一度保存して削除したデータを表示することができました。
削除する際にファイル名を変えたり、データの内容を更新したりすると、復元できないことがあることがわかりました。

USBメモリのフォーマット

WindowsでUSBメモリーをフォーマット(論理)した上もう一度次のコマンドで確認したところ、削除データがなくなっていました。

# フォーマットしたUSBメモリに対する削除データの表示
$ sudo fls /dev/sdc -dr
# 何も表示されない

フォーマット大事ですね。
今回は論理フォーマットをしただけなのですが、ファイル名が表示されなくなるので、この方法では復元できなくなりました。

思ったこと

今回は、USBメモリの構造を確認したいと思って始めましたが、削除データの復元に脱線してしまいました。
データを保存したり削除する仕組みは、バージョンによって変わることがあるので、あくまでも参考値となります。
 削除データを復元する仕組みがわかっただけで満足です。
 USBメモリは定期的にフォーマットしましょう。