iPhoneバックアップデータから素で電話番号一覧などを抽出する
iPhoneが、水没にともない使えなくなりました。 私ではありません。某知り合いです。
教訓としては、iPhoneは洗濯機に入れるな、ということに尽きます。
で、お助けマンとなります。 以前のバックアップデータから、すぐに業務に必要な電話番号一覧などを抽出します。 以前といっても半年前データでしたが、ないとあるとでは大違い。
sqlite3とシェルスクリプトを走らせることができれば、OS環境は問わないと思います(多分)。
iPhoneのバックアップデータは、macOSの場合は
/Users/ユーザ名/Library/Application Support/MobileSync/Backup/
にあります。
ハッシュ値で、バックアップ時点ごとのパスができてます。
/Users/ユーザ名/Library/Application Support/MobileSync/Backup/10663fbacfbe以下略
みたいな感じ。
/Users/ユーザ名/Library/Application Support/MobileSync/Backup/10663fbacfbe以下略/Info.plist
に、基本情報がはいってます。
<key>Device Name</key>
<string>iPhone-X-MY-device-2</string>
とかみれば、どのiPhoneのいつのbackupかはわかります。
事故を増幅させないように、うえのbackupをそのまま使わず、 /tmp/なりなんなりに、コピーして、試してください。
同じパス階層に、Manifest.dbってのがあって、こいつが、メインのdbです。(sqlite3の)。
ただし、欲しい<情報>に対応して、それぞれデータベースが乱立しています。
とにかく本人が確保したいのは、3つで
- 電話番号
- ショートメッセージ
- LINEチャット
です。
次のようスクリプトを書きます。 /tmp/Backup/などで、走らせます。
#!/bin/bash
# バックアップID
BACKUP_ID="上のハッシュ値のパス" # 10663fbacfbe以下略の部分
# 1. 各データベースのパス(LINEはManifest.dbからファイル名を取得)
#これは任意のハッシュ値にみえながら、実は、電話番号、smsの一意のデータベース名
PHONE_DB="$BACKUP_ID/31/31bb7ba8914766d4ba40d6dfb6113c8b614be442"
SMS_DB="$BACKUP_ID/3d/3d0d7e5fb2ce288813306e4d4636395e047a3d28"
LINE_HASH=$(sqlite3 "$BACKUP_ID/Manifest.db" "SELECT fileID FROM Files WHERE relativePath LIKE '%Line.sqlite' LIMIT 1;")
LINE_DB="$BACKUP_ID/${LINE_HASH:0:2}/$LINE_HASH"
# 2. 3つ並べて実行
sqlite3 "$PHONE_DB" ".read phone.sql" > /tmp/phone.txt
sqlite3 "$SMS_DB" ".read sms.sql" > /tmp/sms.txt
sqlite3 "$LINE_DB" ".read line.sql" > /tmp/line.txt
同じディレクトリにおく3つのsqlですが
それぞれのsqlは
phone.sql
SELECT
p.Last AS "姓",
p.First AS "名",
m.value AS "電話番号"
FROM
ABMultiValue m
JOIN
ABPerson p ON m.record_id = p.ROWID
WHERE
m.property = 3;
sms.sql
SELECT
datetime(m.date / 1000000000 + 978307200, 'unixepoch', 'localtime') AS "日時",
h.id AS "相手の宛先(電話番号/ID)",
m.is_from_me AS "自分が送信(1=はい, 0=いいえ)",
m.text AS "メッセージ本文"
FROM
message m
LEFT JOIN
handle h ON m.handle_id = h.ROWID
ORDER BY
m.date DESC;
line.sql
SELECT
datetime(m.ZTIMESTAMP / 1000, 'unixepoch', 'localtime') AS "日時",
COALESCE(g.ZNAME, u_chat.ZNAME, '個人トーク') AS "トークルーム名",
CASE
WHEN m.ZSENDER IS NULL THEN '自分'
ELSE u_sender.ZNAME
END AS "発言者",
m.ZTEXT AS "メッセージ本文"
FROM
ZMESSAGE m
-- チャットルームの紐付け
LEFT JOIN
ZCHAT c ON m.ZCHAT = c.Z_PK
-- グループチャットの場合のルーム名取得
LEFT JOIN
ZGROUP g ON c.ZMID = g.ZID
-- 1対1チャットの場合の相手のユーザー名取得
LEFT JOIN
ZUSER u_chat ON c.ZMID = u_chat.ZMID
-- メッセージ発言者の名前取得(NULLなら自分)
LEFT JOIN
ZUSER u_sender ON m.ZSENDER = u_sender.Z_PK
WHERE
m.ZTEXT IS NOT NULL
ORDER BY
m.ZTIMESTAMP DESC;
ご覧のようにLINEは他社の情報なので、Manifest.dbから、Lineのsqliteデータベース名を取得したうえで、動作させます。
ともかく、これで必要最小限のデータは確保できました。 (LINE画面でバックアップ設定をしてないと、携帯をかえるだけで過去履歴が消えて終わる^^;、という伝説があるLINEチャットも、単なるテキストですけど、取得可能なのは、便利でしょw)