エキスパート
ファームウェア テスト¶
このレッスンでは、ファームウェア バイナリを展開し、テスト ドライバーを作成、パッケージ化、そしてテストする方法を順を追って説明します。これらのテクニックは、テスト対象としてソース コードやドキュメントのない Linux ファームウェアが与えられた場合に役に立ちます。
学習時間の目安: 20 分
このレッスンを終了すると、以下のことができるようになります。
- ファームウェア テストの課題を説明する。
DGN2200v4
ルーター ファームウェア イメージのファームウェア テスト サンプルを順を追って説明する。- 関数をテストし、
LD_PRELOAD
を使用して関数をオーバーライドする。 - ファームウェア テスト ドライバーを使用して Mayhem ランを実行する。
以下が必要です。
- Mayhem および Mayhem CLI
- Netgear N300
- MIPS ファームウェア イメージ
- ForAllSecure の bncov と互換性がある逆アセンブラ (このチュートリアルでは、Binary Ninja を使用しています)
- リバース エンジニアリングの高度な知識。このチュートリアルでは、MIPS アセンブリ コードおよび Binary Ninja の HLIL を参照します。
- Docker
ファームウェアの何が特殊なのか?¶
ファームウェア テストには、他のターゲットではそれほど問題にならない特殊な課題があり、効率的に対処するために、より高い専門知識とノウハウが必要になります。
特に、ファームウェア テストの課題には以下のようなものがあります。
- 物理的デバイスに存在する特殊なハードウェア機能に依存している
- x86 プロセッサ以外のアーキテクチャ
- glibc C 以外の標準ライブラリ
- ソース コードやドキュメントがない
このチュートリアルでは、ファームウェア テストにおいて、これらの課題に対処する方法を説明します。
サンプル: Netgear N300 (DGN2200v4
)¶
このサンプルでは、Netgear N300 (以降は DGN2200v4
と表記) ルーター ファームウェア イメージを調べてみます。これは Linux のファームウェア ライブラリであり、上記の課題すべてを提示しているため、調べるのによいターゲットです。特に、このファームウェアには次の特徴があります。
- プログラムが同期処理のための特殊なハードウェア機能に依存している
- MIPS アーキテクチャ向けにコンパイルされている
- glibc C ではなく uClibc 標準ライブラリを使用している
- ソース コードがなく、対象バイナリにごく少数のデバッグ シンボルしかない
では、このファームウェアを展開し、テスト ドライバーを作成し、パッケージ化し、ファジングを行う方法を説明していきます。
環境のセットアップ¶
このチュートリアルのために、必要なツールおよびファイルをすべて含む 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 つです。
- ユーザーとやりとりする Web サーバー
- データベース マネージャーなどのカスタム内部バイナリ
他の類似のファームウェア (別のメーカーの類似のモデルなど) を取得し、スクリプトを使用して、どれがそれぞれのシステムに固有のバイナリであるかを比較すると、注目するべきバイナリを発見できるでしょう。この方法では、ある程度のノイズが発生する可能性がありますが (たとえば 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
をルート ディレクトリとして「再マウント」します。
呼び出される cmd
は new-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
を開いて調べてみます。
main
の 0x4130d4
で高レベル IL ビュー (HLIL) を使用すると、sub_408f78
の呼び出しが失敗した後に失敗しているように見えます。sub_408f78
はさらに semget
を呼び出しています。
semget
はおそらく ipc
の呼び出しで失敗しており (これらのセマフォはプロセス間通信に使用されるため)、それを回避または修正する必要があります。すぐさまバイナリ パッチに飛びつきたくなるかもしれませんが、このバイナリは実際には動的リンクされるため、代わりに LD_PRELOAD
を使用することで、バイナリを変更することなく動作を変えることができます。
逆アセンブラからわかるもう 1 つのことは、この main
関数が単に HTTP リクエストに応答するだけでなく、他にも多くの処理を行っていることです。また、さまざまなルーターの立ち上げ処理も行っているようです。
これは、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);
}
見てのとおり、このテスト ドライバーは、ほとんど通常と変わりません。いくつか違いがあります。
- main を使用するのではなく、libc の main (実際の main を呼び出す関数) から開始します。
- そのため、最後にリターンするのではなく終了する必要があります (libc の main は、実際の main の戻り値で exit を呼び出します)。
- 関数を直接呼び出すのではく、関数ポインターを作成してそれを呼び出す必要があります。
このテスト ドライバーに関して注目すべき点がいくつかあります。
- リクエストと接続アドレスの両方をテストします。特別なケースや誤って処理されたアドレスがないかをチェックします。
- 各リクエストを
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.ファームウェア テストに関する課題を説明する。
- 特に、ファームウェア テストの課題には以下のようなものがあります。
- 物理的デバイスに存在する特殊なハードウェア機能に依存している
- x86 プロセッサ以外のアーキテクチャ
- glibc C 以外の標準ライブラリ
- ソース コードやドキュメントがない
2.DGN2200v4
ルーターのファームウェア イメージをサンプルとしてファームウェア テストの手順を実行する。
- このサンプルでは、Netgear N300 (以降は
DGN2200v4
と表記) ルーター ファームウェア イメージを調べてみます。これは Linux のファームウェア ライブラリであり、上記の課題すべてを提示しているため、調べるのによいターゲットです。特に、このファームウェアには次の特徴があります。- プログラムが同期処理のための特殊なハードウェア機能に依存している
- MIPS アーキテクチャ向けにコンパイルされている
- glibc C ではなく uClibc 標準ライブラリを使用している
- ソース コードがなく、対象バイナリにごく少数のデバッグ シンボルしかない
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