コンテンツにスキップ

エキスパート

ファームウェア テスト

このレッスンでは、ファームウェア バイナリを展開し、テスト ドライバーを作成、パッケージ化、そしてテストする方法を順を追って説明します。これらのテクニックは、テスト対象としてソース コードやドキュメントのない Linux ファームウェアが与えられた場合に役に立ちます。


学習時間の目安: 20 分

このレッスンを終了すると、以下のことができるようになります。

  1. ファームウェア テストの課題を説明する。
  2. DGN2200v4 ルーター ファームウェア イメージのファームウェア テスト サンプルを順を追って説明する。
  3. 関数をテストし、LD_PRELOAD を使用して関数をオーバーライドする。
  4. ファームウェア テスト ドライバーを使用して Mayhem ランを実行する。

以下が必要です。

  1. Mayhem および Mayhem CLI
  2. Netgear N300
  3. MIPS ファームウェア イメージ
  4. ForAllSecure の bncov と互換性がある逆アセンブラ (このチュートリアルでは、Binary Ninja を使用しています)
  5. リバース エンジニアリングの高度な知識。このチュートリアルでは、MIPS アセンブリ コードおよび Binary Ninja の HLIL を参照します。
  6. Docker

ファームウェアの何が特殊なのか?

ファームウェア テストには、他のターゲットではそれほど問題にならない特殊な課題があり、効率的に対処するために、より高い専門知識とノウハウが必要になります。

特に、ファームウェア テストの課題には以下のようなものがあります。

  1. 物理的デバイスに存在する特殊なハードウェア機能に依存している
  2. x86 プロセッサ以外のアーキテクチャ
  3. glibc C 以外の標準ライブラリ
  4. ソース コードやドキュメントがない

このチュートリアルでは、ファームウェア テストにおいて、これらの課題に対処する方法を説明します。

サンプル: Netgear N300 (DGN2200v4)

このサンプルでは、Netgear N300 (以降は DGN2200v4 と表記) ルーター ファームウェア イメージを調べてみます。これは Linux のファームウェア ライブラリであり、上記の課題すべてを提示しているため、調べるのによいターゲットです。特に、このファームウェアには次の特徴があります。

  1. プログラムが同期処理のための特殊なハードウェア機能に依存している
  2. MIPS アーキテクチャ向けにコンパイルされている
  3. glibc C ではなく uClibc 標準ライブラリを使用している
  4. ソース コードがなく、対象バイナリにごく少数のデバッグ シンボルしかない

では、このファームウェアを展開し、テスト ドライバーを作成し、パッケージ化し、ファジングを行う方法を説明していきます。

環境のセットアップ

このチュートリアルのために、必要なツールおよびファイルをすべて含む Docker イメージが用意されています。そのため、提供されている Docker イメージを使用することが推奨されます。

次のコマンドを使用して Docker コンテナーをダウンロードし、実行します。

docker pull forallsecure/fuzzing-firmware
docker run -ti forallsecure/fuzzing-firmware

別の方法として、次のツールを手動でインストールすることもできます。

  • QEMU user static (例: apt-get install -y qemu-user-static)
  • Binwalk (例: python -m pip install git+https://github.com/ReFirmLabs/binwalk)
  • Jefferson (例: python -m pip install git+https://github.com/sviehb/jefferson)
  • MIPS クロス コンパイラ
  • Mayhem CLI

Docker を使用する場合でも、上記のように手動で環境をセットアップする場合でも、bncov プラグインがインストールされた Binary Ninja にアクセスできることを確認してください。

ファームウェアを展開する

カスタム ファームウェアの配置や暗号化のために、ファームウェアを展開するのが困難な場合があります。幸運なことに、このサンプルを含めた多くのファームウェアは、単なる圧縮ファイル システムです。つまり、binwalk などの既製のツールで簡単に展開できます。次のコマンドを実行して展開します。

$ binwalk -Me DGN2200v4-V1.0.0.126_1.0.126.chk
Scan Time:     2022-02-25 20:04:48
Target File:   /fuzzing-firmware/DGN2200v4-V1.0.0.126_1.0.126.chk
MD5 Checksum:  3b504ce5df0ea5cbd66b473fca1ec73f
Signatures:    410

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
58            0x3A            JFFS2 filesystem, big endian

Note

e オプションは展開を意味し、M オプションはファームウェア内にネストされたコンテナーがある場合、再帰的に展開することを意味します。

binwalk の実行後、展開されたファームウェアは _DGN2200v4-V1.0.0.126_1.0.126.chk.extracted にあります。

他の作業を行う前に、展開されたファームウェアをクリーンアップします。具体的には、binwalk は多数の出力を作成しますが、必要なのはファイルシステムだけです。そのため、展開されたフォルダーからファイルシステムを移動して root に名前を変更します。

$ mv _DGN2200v4-V1.0.0.126_1.0.126.chk.extracted/jffs2-root/fs_1 root
$ rm -rf _DGN2200v4-V1.0.0.126_1.0.126.chk.extracted

root フォルダーにファイルシステムを移動したので、中のバイナリを調べてテストできるようになりました。

ターゲットを選択する

ファームウェアを展開したら、テスト対象のバイナリを特定する必要があります。ルーターのターゲットとして適した選択肢は次の 2 つです。

  1. ユーザーとやりとりする Web サーバー
  2. データベース マネージャーなどのカスタム内部バイナリ

他の類似のファームウェア (別のメーカーの類似のモデルなど) を取得し、スクリプトを使用して、どれがそれぞれのシステムに固有のバイナリであるかを比較すると、注目するべきバイナリを発見できるでしょう。この方法では、ある程度のノイズが発生する可能性がありますが (たとえば 2 つのルーターのうち 1 つは sqlite を使用し、もう 1 つは postgres を使用しているなど)、精査するべきバイナリの量を大幅に減らすのに役立つため、最初の一歩としてよいやり方です。

このチュートリアルでは、DGN2200v4 の httpd Web サーバーを調べることにします。組み込みシステム (特にルーター) のWeb サーバーは非常に興味深いものです。単に Web サーバーであるだけでなく、デバイスの起動、認証、プロセス管理など多くの機能を制御していることがよくあるからです。同じ理由で、実行が難しい場合もあります。

httpd の概要

まず、httpd がどのようなバイナリであるかを確認しましょう。次のコマンドを実行して、新しく作成された root フォルダーの内部にある httpd バイナリをチェックします。

$ file root/usr/sbin/httpd
root/usr/sbin/httpd: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped

結果からは、非標準 libc (uClibc) を使用する 32 ビットの MIPS バイナリであることがわかります。これらの障害を 1 つずつ克服していきます。

バイナリは MIPS バイナリであり、おそらくこのチュートリアルを MIPS ボックスでは実行していないでしょうから、httpd やその他の調べたいバイナリをテストするには、QEMU を使用する必要があります。

さらに、バイナリを適切な環境で実行するために、chroot を使用してルート ディレクトリを展開したファイルシステムのルートに「再マウント」する必要があります。chroot コマンド形式は次のとおりです。

$ chroot <new-root-directory> <cmd>

Info

上記の chroot コマンドは、 cmd を実行している間、new-root-directory をルート ディレクトリとして「再マウント」します。

呼び出される cmdnew-root-directory 内のファイルにだけアクセスできるため、chroot 環境では静的にリンクされた QEMU を使用する必要があります (通常、QEMU を実行するには、ホストの共有ライブラリへのアクセスが必要です)。

$ cp `which qemu-mips-static` root

すべて準備が整ったので、実際に httpd を実行してみましょう。

$ chroot root /qemu-mips-static /usr/sbin/httpd
/usr/sbin/httpd: can't load library 'libssl.so.0.9.7'

Note

root フォルダーにルート ディレクトリが変更されているので、qemu-mips-static および httpd には絶対パスを使用します。

おやおや。このターゲットを正常に実行するには、もう少していねいに対処する必要があるようです。

httpd を実行できるようにする

不足しているライブラリを見つけて LD_LIBRARY_PATH 環境変数に追加しましょう。

Note

続行するには、root/tmp のシンボリック リンクを削除し、root/tmp の実際のディレクトリを作成する必要があります。

$ find root -name libssl.so.0.9.7
root/lib/public/libssl.so.0.9.7
$ ls -l root/tmp
lrwxrwxrwx 1 root root 8 Feb 25 20:18 root/tmp -> /var/tmp
$ unlink root/tmp
$ mkdir -p root/tmp
$ chroot root /qemu-mips-static -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd
shm ID: 262152
Semaphore Create Failed.

Tip

次のような問題が表示される場合

root@f5c3f91750ae:/fuzzing-firmware# chroot root /qemu-mips-static -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd
shm ID: 0
Get a correct Segment_ID: 0 and semaphore ID:0
Can't find handler for ASP command: usb_cgi_get_register_state();
Can't find handler for ASP command: usb_cgi_get_invite_state();
Can't find handler for ASP command: check_is_index()
Can't find handler for ASP command: wds_cgi_get_param("base_station_addr");
Can't find handler for ASP command: wds_cgi_get_param("link_rate");
Can't find handler for ASP command: wds_cgi_get_param("signal_strength");
Can't find handler for ASP command: wds_cgi_get_param("repeater1_addr");
Can't find handler for ASP command: wds_cgi_get_param("repeater2_addr");
Can't find handler for ASP command: wds_cgi_get_param("repeater3_addr");
Can't find handler for ASP command: wds_cgi_get_param("repeater4_addr");
root@f5c3f91750ae:/fuzzing-firmware# /var/run/httpd.pid: No such file or directory

rm root/tmp/shm_id を実行してから再実行します。そうすると問題が解決され、先に進めるはずです。

QEMU-strace オプションを指定して調査しましょう。

$ chroot root /qemu-mips-static -strace -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd
...
271 open("/tmp/shm_id",O_WRONLY|O_CREAT|O_TRUNC,0666) = 3
271 ioctl(3,21517,2147481080,0,0,0) = -1 errno=89 (Function not implemented)
271 brk(0x0069b000) = 0x0069b000
271 write(1,0x7f52d2a8,15)shm ID: 229383
= 15
271 write(3,0x699070,6) = 6
271 close(3) = 0
271 ipc(21,229383,0,2147481280) = 0
271 ipc(2,123456,1,1974) = -1 errno=17 (File exists)
271 write(1,0x7f52d2a8,25)Semaphore Create Failed.
= 25
271 exit(1)

-strace の出力から判断すると、失敗の原因は、共有メモリ操作 (shm = 共有メモリ) に関する IPC および IOCTL の問題である可能性があります。共有メモリ操作は QEMU のあまりサポートが充実していない機能です。

確実に明らかにするには、逆アセンブラを使うしかありません。Binary Ninja で root/usr/sbin/httpd およびその依存関係 root/lib/libnvram.so を開いて調べてみます。

main0x4130d4 で高レベル IL ビュー (HLIL) を使用すると、sub_408f78 の呼び出しが失敗した後に失敗しているように見えます。sub_408f78 はさらに semget を呼び出しています。

sub_408f78

*Subroutine at 0x408f78*

semget

*Semget*

semget はおそらく ipc の呼び出しで失敗しており (これらのセマフォはプロセス間通信に使用されるため)、それを回避または修正する必要があります。すぐさまバイナリ パッチに飛びつきたくなるかもしれませんが、このバイナリは実際には動的リンクされるため、代わりに LD_PRELOAD を使用することで、バイナリを変更することなく動作を変えることができます。

逆アセンブラからわかるもう 1 つのことは、この main 関数が単に HTTP リクエストに応答するだけでなく、他にも多くの処理を行っていることです。また、さまざまなルーターの立ち上げ処理も行っているようです。

router_bringup

*Router bring-up code*

これは、main ではない場所からプログラムに入ったほうがよい可能性を示しています。ありがたいことに、HTTP 解析コードを見つけられれば、やはり LD_PRELOAD を使用して内部関数を直接ドライバー テストできます。

LD_PRELOAD を使用して関数をドライバー テストする

まず、HTTP リクエスト解析関数を直接ターゲットとすることに集中します。リバース エンジニアリングによって、この関数は 0x408f90 にあることがわかります。さらにリバース エンジニアリングを行うと、この関数のシグニチャは次のようであることがわかります。

void parse_http_req(char *http_req, void *unk, int32_t inet_addr, int32_t out_fd)

いったんやり方を覚えれば、LD_PRELOAD で個々の関数をドライバー テストするのは簡単です。同じ名前の関数を LD_PRELOAD テスト ドライバーに定義し、その中でテスト対象の関数を呼び出すことで、libc の main (今回の例では __uClibc_main) をオーバーライドします。

// harness.c

#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>

// the real signature is longer but turns out it doesn't matter
void __uClibc_main(void *main, int argc, char** argv)
{
    char req[4096 + 1];
    int32_t in_addr;

    if (argc != 2) {
        printf("Usage: %s <fuzz-file>\n", argv[0]);
        exit(1);
    }

    char *fuzzfile = argv[1];
    int fd = open(fuzzfile, O_RDONLY);

    int n_read = read(fd, &in_addr, sizeof(in_addr));
    if (n_read != sizeof(in_addr)) exit(1);

    n_read = read(fd, req, sizeof(req) - 1);
    if (n_read < 0) exit(1);
    req[n_read] = 0;

    fprintf(stderr, "Request: %s\n\n", req);

    // declare a function pointer pointing to the real parse_http_req
    void (*parse_http_req)(char *, void *, int32_t, int) = (void *)0x408f90;

    // Skip a lot of device init and get right to the server setup and http handler
    parse_http_req(req, NULL, in_addr, STDERR_FILENO);

    // need to exit here b/c this function is expected to not return
    exit(0);
}

見てのとおり、このテスト ドライバーは、ほとんど通常と変わりません。いくつか違いがあります。

  1. main を使用するのではなく、libc の main (実際の main を呼び出す関数) から開始します。
  2. そのため、最後にリターンするのではなく終了する必要があります (libc の main は、実際の main の戻り値で exit を呼び出します)。
  3. 関数を直接呼び出すのではく、関数ポインターを作成してそれを呼び出す必要があります。

このテスト ドライバーに関して注目すべき点がいくつかあります。

  1. リクエストと接続アドレスの両方をテストします。特別なケースや誤って処理されたアドレスがないかをチェックします。
  2. 各リクエストを stderr に出力し、出力 FD として stderr を parse_http_req に渡します。これによって、Mayhem でテストを実行したとき、コマンドラインで視覚的に結果を参照することができます。

LD_PRELOAD は、指定された共有オブジェクトで共有ライブラリをオーバーロードすることによって動作するため、harness.c も共有ライブラリとしてコンパイルする必要があります。

$ /fuzzing-firmware/cross-compiler-mips/bin/mips-gcc harness.c -o root/harness.so -shared -fPIC

LD_PRELOAD テスト ドライバーをコンパイルできたので、テスト ファイルを作成しましょう。これは、テスト ドライバーがファイルを受け取るからです。LD_PRELOAD 環境変数と test.txt 引数を追加した以外は、前と同じように httpd を実行できます。

$ echo AAAABBBBCCCC > root/test.txt
$ chroot root /qemu-mips-static -E LD_PRELOAD=/harness.so -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd
Usage: /usr/sbin/httpd <fuzz-file>
$ chroot root /qemu-mips-static -E LD_PRELOAD=/harness.so -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd test.txt
Request: BBBBCCCC


qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

残念。まだクラッシュします。再び -strace を使用して理由を確認しましょう。

$ chroot root /qemu-mips-static -strace -E LD_PRELOAD=/harness.so -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd test.txt &
...
97 ipc(23,1074866065,131072,438) = -1 errno=2 (No such file or directory)
97 ipc(21,-1,0,2147275888) = -1 errno=22 (Invalid argument)
97 ipc(2,1074866065,1,1974) = -1 errno=17 (File exists)
97 ipc(2,1074866065,1,512) = 0
97 rt_sigprocmask(SIG_BLOCK,0x7ffcd400,NULL) = 0
97 ipc(1,0,1,0) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x0000001f} ---
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

依然として IPC コードでクラッシュしているように見えます。しかしどこで? parse_http_req からの呼び出しの大部分は acosNvramConfig_ に関連しているようです。GDB を使用してブレークし、内部でクラッシュしていないかをチェックしてみましょう。QEMU-g <port> 引数を指定することで、gdb-multiarch とともに QEMU を使用することができます。

$ chroot root /qemu-mips-static -g 1234 -E LD_PRELOAD=/harness.so -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd test.txt &
$ gdb-multiarch -q root/usr/sbin/httpd
(gdb) target remote :1234
Remote debugging using :1234
...
(gdb) break acosNvramConfig_match
Breakpoint 1 at 0x4ade90
(gdb) continue
...
Breakpoint 1, 0x004ade90 in acosNvramConfig_match ()
(gdb) finish
...
Program received signal SIGSEGV, Segmentation fault.
0x7f6f5f90 in ?? ()

クラッシュは acosNvramConfig_match のどこかで発生したため、この関数をオーバーライドすることでクラッシュを修正できるはずです。やってみましょう。

LD_PRELOAD で関数をオーバーライドする

LD_PRELOAD を使用すると、動的にリンクされる任意の関数をオーバーライドできます。今回は、acosNvramConfig_match でプログラムがクラッシュしていることがわかりました。ですから、この関数をスキップするか再実装することで関数をオーバーライドすれば、クラッシュをまとめて避けられるはずです。

テスト ドライバー harness.so に match 関数のオーバーライドを追加しましょう。

int acosNvramConfig_match(char *key, char *value) {
    printf("acosNvramConfig_match(%s, %s)\n", key, value);
    return 0;
}

次に、新しいバージョンのテスト ドライバーを実行します。

$ /fuzzing-firmware/cross-compiler-mips/bin/mips-gcc harness.c -o root/harness.so -shared -fPIC
$ chroot root /qemu-mips-static -E LD_PRELOAD=/harness.so -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd test.txt
...
acosNvramConfig_match(passwordrecovered_debug2, 1)
acosNvramConfig_match(passwordrecovered_debug, 1)
acosNvramConfig_match(http_rmenable, 1)
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

残念ながら、まだ セグメンテーション違反が発生するようです。それでも、strace の出力を見ると、前と同じ呼び出しパターンのようです。残りの acosNvramConfig_* ファミリーのオーバーライドを追加しましょう (これを演習とします)。

$ chroot root /qemu-mips-static -E LD_PRELOAD=/harness.so -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd test.txt
Request: BBBBCCCC
...
acosNvramConfig_get(local_ip9)
acosNvramConfig_get(local_ip10)
acosNvramConfig_match(rm_access, ip_single)
acosNvramConfig_match(rm_access, ip_range)
acosNvramConfig_match(rm_access, ip_list)
acosNvramConfig_match(rm_access, all)

すばらしい! テスト ドライバーを使用して httpd を実行してもクラッシュが起きなくなりました。しかし、stderr を出力ファイル記述子として渡したにもかかわらず、出力が表示されません。これは、parse_http_req が acosNvramConfig_* の出力に依存していることを表しているに違いありません。つまり、オーバーライドが元の処理をより忠実に再現する必要があることを示しています。

現時点では、単にデフォルト値 (0 または空文字列) を返しているだけです。そうではなく、ファームウェア イメージの /etc/nvram から値を取得して返すようテスト ドライバーを変更します。

ついに、テスト ドライバーを使用して httpd を実行すると、期待した結果が出力されるようになりました。

$ chroot root /qemu-mips-static -E LD_PRELOAD=/harness.so -E LD_LIBRARY_PATH=/lib/public/ /usr/sbin/httpd test.txt
...
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="NETGEAR DGN2200v4"
x-frame-options: SAMEORIGIN
Set-Cookie: XSRF_TOKEN=1222440606; Path=/
Content-type: text/html

<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<title></title></head>
<body><h1></h1>
<p></p></body>
</html>

今度は、ファームウェアおよびコンパイル済みコードを Mayhem に持っていきます。

Mayhem に持っていく

驚くべきことに、いったんファームウェアをローカルで実行できるようにした後は、Mayhem に持っていくのは簡単です。これまでのチュートリアルで学んだとおり、Mayhem はパッケージが次のような構造を持つと期待します。

my-package/
    Mayhemfile
    root/
        usr/
        bin/
        etc/
        ...
    [tests/]
        ...

幸運なことに、展開されたファームウェアは、すでにルート フォルダーに似ています (Mayhem パッケージのルート フォルダーはミニファイルシステムに他なりません)。ですから、ファームウェアとテスト ドライバーを Mayhem パッケージ化するには、Mayhemfile を追加するだけです。もちろん、テスト ドライバーを LD_PRELOAD すること、またライブラリがどこにあるかが Mayhem にわかるよう、環境変数を指定する必要があります。

project: netgear-n300
target: parse_http_request

cmds:
- cmd: /usr/sbin/httpd @@
  env:
    LD_LIBRARY_PATH: /lib/public
    LD_PRELOAD: /harness.so

ファームウェアのルート ディレクトリおよび Mayhemfile を含むディレクトリから mayhem run を実行できるようになりました。

$ ls
Mayhemfile harness.c root
$ mayhem run .
/var/folders/4z/qn09fnw164dd4jrghzws9q1h0000gn/T/tmp4ra3bszk/testsuite.tgz 100% |########################| Time:  0:00:00   1.4 KiB/s
Syncing /var/folders/4z/qn09fnw164dd4jrghzws9q1h0000gn/T/tmppqpnt2py 100% |###########################| Time:  0:00:00
/var/folders/4z/qn09fnw164dd4jrghzws9q1h0000gn/T/tmpd7x8xrim/root.tgz 100% |##########################| Time:  0:00:01   1.4 MiB/s
Run started: netgear-n300/parse-http-request/1
Run URL: https://tutorial.forallsecure.com:443/mayhemuser/netgear-n300/parse-http-request/1

Tip

Mayhem ランを正常に実行できない場合、次のように、root フォルダーから残りのシンボリック リンクを削除する必要があるかもしれません: find root -type l -delete終了したら、Mayhem ランを再実行します。

🔍 確認 N300 ファームウェア テスト

解答

n300-firmware-fuzzing.tgz ファイルをダウンロードし、Mayhem で n300 ファームウェアをテストするための正しいセットアップを取得します。

✏️ まとめと振り返り

このレッスンでは、ファームウェア バイナリを展開し、テスト ドライバーを作成し、パッケージ化し、テストする方法を学びました。


学習内容

1.ファームウェア テストに関する課題を説明する。
  • 特に、ファームウェア テストの課題には以下のようなものがあります。
    1. 物理的デバイスに存在する特殊なハードウェア機能に依存している
    2. x86 プロセッサ以外のアーキテクチャ
    3. glibc C 以外の標準ライブラリ
    4. ソース コードやドキュメントがない
2.DGN2200v4 ルーターのファームウェア イメージをサンプルとしてファームウェア テストの手順を実行する。
  • このサンプルでは、Netgear N300 (以降は DGN2200v4 と表記) ルーター ファームウェア イメージを調べてみます。これは Linux のファームウェア ライブラリであり、上記の課題すべてを提示しているため、調べるのによいターゲットです。特に、このファームウェアには次の特徴があります。
    1. プログラムが同期処理のための特殊なハードウェア機能に依存している
    2. MIPS アーキテクチャ向けにコンパイルされている
    3. glibc C ではなく uClibc 標準ライブラリを使用している
    4. ソース コードがなく、対象バイナリにごく少数のデバッグ シンボルしかない
3.LD_PRELOAD を使用して関数をドライバー テストおよびオーバーライドする。
  • いったんやり方を覚えれば、 LD_PRELOAD で個々の関数をドライバー テストするのは簡単です。同じ名前の関数を LD_PRELOAD テスト ドライバーに定義し、その中でテスト対象の関数を呼び出すことで、libc の main (今回の例では __uClibc_main) をオーバーライドします。
4.ファームウェア テスト ドライバーを含むターゲットに対して Mayhem ランを実行する。
  • テスト ドライバーを LD_PRELOAD すること、またライブラリがどこにあるかが Mayhem にわかるよう、環境変数を指定する必要があります。

    1
    2
    3
    4
    5
    6
    7
    8
    project: netgear-n300
    target: parse_http_request
    
    cmds:
    - cmd: /usr/sbin/httpd @@
    env:
        LD_LIBRARY_PATH: /lib/public
        LD_PRELOAD: /harness.so