URoad-Homeを分解してみた4~フラッシュのダンプ&解析~

投稿者: | 3月 28, 2024

目次

はじめに

久しぶりにURoad-Homeの方に触れます。今回はフラッシュのダンプを取ってみます。

URoad-Home関係の記事とその概要の一覧はこちら

大まかな流れ

大まかな流れとしては、U-Boot上でmdコマンドを使ってフラッシュのバイナリをコンソールに出して、それをteratermのログ機能で保存します。その後、Pythonを用いてバイナリファイルに変換します。

U-Bootのカーネルパラメータ(bootarg)を変更してもうまく行かず、今回の方法と次の記事で書くOSコマンドインジェクションでダンプを取ることができました。今回は前者の方法を書きます。後者は次回の記事で書きます。

手順

1. U-Bootのコンソールに入る
URoad-Homeを分解してみた2を元にteratermで接続できU-Bootのコンソールに入っている状態にしてください。

2. ログを記録する
Teratermの機能であるログの保存を使用します。
右上のファイル→ログから適当な場所に適当な名前で保存してください。
1つのパーティションに1つのログファイルとすると良いです。追記・上書き保存に気をつけてください。

3. mdでのフラッシュのバイナリを出力
BF000000からフラッシュのアドレスとなるので、それぞれのパーティションを表示させるには
bootloader:md BF000000 40000
Config:md BF040000 20000
Factory:md BF060000 20000
Kernel:md BF080000 730000
Kernel2:md BF7C0000 730000
Wimax:md BFF00000 100000
となります。Wimaxに関しては無理やりC0000000を読もうとしてクラッシュするので注意が必要です。
1つのログファイルに1つのパーティションとしてください。一度にフラッシュのすべてを読み出すこともできますが、番地が飛んだりして面倒なことになるのでおすすめしません。

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
teraterm.log
ログの保存中

4. ログの取得を終了

5. 2~4を繰り返してすべてのパーティションのログファイルを取得する

6. ログファイルを整える
ログファイルの1行目は実行したコマンド、最終行には、uroad-3000>みたいなのが記録されているので、メモ帳などで開き、それを取り除きます。

7. ログファイルをバイナリファイルに変換
mdで表示をすると右側にアドレス、中央にバイナリ、右にアスキーコードがでるので、中央のバイナリ部分を抽出してバイナリファイルを作成します。
Pythonを使用します。以下のコードを使用しました。

import sys
import os

def log2bin(file_path):
    # ログファイルからバイナリデータを抽出し、新しいバイナリファイルに書き込む
    # 入力ファイル名から拡張子を分離
    base_name, ext = os.path.splitext(file_path)
    # 出力ファイル名の生成(入力ファイル名をbinに)
    output_file_path = f"{base_name}.bin"

    # ログファイルを読み込み、各行からバイナリデータを抽出して新しいバイナリファイルに書き込む
    with open(file_path, 'r') as file, open(output_file_path, 'wb') as output_file:
        for line in file:
            # 各行からバイナリ部分のみを抽出
            binary_data = line[10:49].replace(" ", "")
            # バイナリデータをバイト配列に変換してファイルに書き込む
            output_file.write(bytes.fromhex(binary_data))

    return output_file_path

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python script.py <input_file>")
    else:
        input_file_path = sys.argv[1]
        output_file_path = log2bin(input_file_path)
        print(f"Converted file saved as: {output_file_path}")

ログファイル(例teratermlog.log)を引数として与えて、実行するとバイナリファイル(teratermlog.bin)に変換してくれます。ログファイルがあるのと同じディレクトリで実行してください。

8. リトルエンディアンをビッグエンディアンに変換

取得したファイルはすべてリトルエンディアンとなっており、そのままではbinwalkなどが全く使用できないので、変換します。先程と同じようにPyhtonを使用します。以下のコードを使用しました。

import sys
import os

def convert_endian(input_file_name):
    # 入力ファイル名から拡張子を分離
    base_name, ext = os.path.splitext(input_file_name)
    # 出力ファイル名の生成(入力ファイル名に "_endian" を追加)
    output_file_name = f"{base_name}_endian{ext}"
    
    # ファイルを読み込み、各32ビット(4バイト)ごとにエンディアンを変換する
    with open(input_file_name, 'rb') as input_file, open(output_file_name, 'wb') as output_file:
        while True:
            # 4バイトずつ読み込む
            chunk = input_file.read(4)
            if not chunk:
                break
            # エンディアンを変換に変換
            converted_chunk = chunk[::-1]
            output_file.write(converted_chunk)
    
    return output_file_name

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python script.py <input_file>")
    else:
        input_file_path = sys.argv[1]
        output_file_path = convert_endian(input_file_path)
        print(f"Converted file saved as: {output_file_path}")

リトルエンディアンのファイルteratermlog_binary.binをビッグエンディアンに変換し、teratermlog_binary_endian.binとして出力します。使い方は、引数に変換したいファイル名を指定してください。

9. 確認
FavBinEditなどでバイナリファイルを開き、抜けが無いか確認します。行数が足りるかどうかで確認すると良いです。UARTなので信頼性が低いので必須です。

解析

とりあえずbinwalkにかけてみた感じです。
Bootloader
U-Bootです。

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
binwalk
U-Boot 1.1.3
Bootloaderをbinwalkにかけたところ

Config
U-Bootのconfigかな

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
binwalk
Configをbinwalkにかけたところ

Factory
Configのバックアップか、nvramですかね

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
binwalk
Factoryをbinwalkにかけたところ

Kernel
Linuxカーネル、LZMAが確認できます。展開は後でします。

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
binwalk
uImage Linux MIPS
Kernelをbinwalkにかけたところ

Kernel2
Kernelのバックアップです。U-Bootのコンソールでbootm BF7C0000とかすると起動できます。多分Kernelと同じ内容です。

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
binwalk
uImage Linux MIPS
Kernek2をbinwalkをかけたところ

Wimax
とてつもない量が出力されます。ファイルシステムがJFFS2のことはわかるんですが、展開しても似たようなものしか出てきません。

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
binwalk
JFFS2 filesystem little endian
Wimaxをbinwalkにかけたところ

/の展開

今回はramdiskとなっているので、Kernelを

binwalk -Me Kerenelのバイナリファイル

で実行すれば展開でき、ファイルを確認できます。

URoad-Homeを分解してみた4~フラッシュのダンプ&解析~
URoad-Home
URoad-3000
binwalk
ramdisk
展開したところ

telnetが入ってますね。/etc/passwdが見当たりません。nvramから読み出して使ってるのかな…

焼き直す

ミスした時とかに本体にダンプファイルを焼く時は、U-Boot上でtftpbootかloadbでメモリにコピーし、フラッシュをeraseしてcpして焼く感じになると思います。なお、ビッグエンディアンのバイナリファイルではなく、リトルエンディアンのファイルを焼くことに注意してください(再変換か、変換前のファイルか)。

おわりに

U-Bootのmdコマンドでダンプを取るという話を聞いたことがあったので試してみました。思ってたよりは時間もかからず楽でしたが、一度に全部のダンプを取ろうとすると抜けが発生してしまい、完璧では無いなーって感じでした。
実を言うと、Wimax以外のパーティションは次の記事で紹介するOSコマンドインジェクションを使ってダンプを取りました。そっちのほうが楽な気がします。

URoad-Home関係の記事とその概要の一覧はこちら

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)