
elfloader は、ELFファイル用の超シンプルなローダーで、ELFのフラットなインメモリ表現を生成します。
これをRustと組み合わせれば、適切で安全な高水準言語でシェルコードを書くことができます。LLVMがターゲットにできる任意のターゲット(非常にエキゾチックなプラットフォームやABI向けのカスタムターゲット仕様を含む)を使用できます。32ビットシステムでの u64 の使用、境界チェック付き配列、アロケーションのドロップ処理などをお楽しみください:)
これは単純に、すべての LOAD セクションを連結し、ギャップがある場合はゼロ埋めを行い、1つの大きなフラットファイルにします。
このファイルには .bss セクションのゼロ初期化が含まれているため、シェルコードペイロードとして直接使用できます。
フェイルオープンなリンカスクリプトに時間を浪費したくないなら、これはおそらく良い方法です。
これはリロケーションを一切処理しません。元のELFが希望のアドレスにベースされていることを確認するのはあなたの責任です。
このツールを使うには、以下のようにします。
Usage: elfloader [--perms] [--binary] [--base=<addr>] <input ELF> <output>
--binary - Don't output a FELF, output the raw loaded image with no
metadata
--perms - Create a FELF0002 which includes permission data, overrides
--binary
--base=<addr> - Force the output to start at `<addr>`, zero padding from
the base to the start of the first LOAD segment if needed.
`<addr>` is default hex, can be overrided with `0d`, `0b`,
`0x`, or `0o` prefixes.
Warning: This does not _relocate_ to base, it simply starts
the output at `<addr>` (adding zero bytes such that the
output image can be loaded at `<addr>` instead of the
original ELF base)
<input ELF> - Path to input ELF
<output> - Path to output file
このツールをインストールするには、以下を実行します。
cargo install --path .
これで、シェルのどこからでも elfloader を使用できます!
このプロジェクトはライブで開発されました:
https://www.youtube.com/watch?v=x0V-CEmXQCQ
example_small_program に例があります。単に make または nmake を実行すると、8バイトの example.bin が生成されます。
pleb@gamey ~/elfloader/example_small_program $ make
cargo build --release
Finished release [optimized] target(s) in 0.03s
elfloader --binary target/aarch64-unknown-none/release/example_small_program example.bin
pleb@gamey ~/elfloader/example_small_program $ ls -l ./example.bin
-rw-r--r-- 1 pleb pleb 8 Nov 8 12:27 ./example.bin
pleb@gamey ~/elfloader/example_small_program $ objdump -d target/aarch64-unknown-none/release/example_small_program
target/aarch64-unknown-none/release/example_small_program: file format elf64-littleaarch64
Disassembly of section .text:
00000000133700b0 <_start>:
133700b0: 8b000020 add x0, x1, x0
133700b4: d65f03c0 ret
これで、Rustでシェルコードを書けます。 .data、.rodata、.bss などを出力するかどうか心配する必要はありません。このツールがすべて処理します!
さらに、.bss と .rodata を含む例もあります。
pleb@gamey ~/elfloader/example_program_with_data $ make
cargo build --release
Finished release [optimized] target(s) in 0.04s
elfloader --binary target/aarch64-unknown-none/release/example_program_with_data example.bin
pleb@gamey ~/elfloader/example_program_with_data $ ls -l ./example.bin
-rw-r--r-- 1 pleb pleb 29 Nov 8 12:39 ./example.bin
pleb@gamey ~/elfloader/example_program_with_data $ objdump -d target/aarch64-unknown-none/release/example_program_with_data
target/aarch64-unknown-none/release/example_program_with_data: file format elf64-littleaarch64
Disassembly of section .text:
0000000013370124 <_start>:
13370124: 90000000 adrp x0, 13370000 <_start-0x124>
13370128: 90000008 adrp x8, 13370000 <_start-0x124>
1337012c: 52800029 mov w9, #0x1 // #1
13370130: 91048000 add x0, x0, #0x120
13370134: 3904f109 strb w9, [x8, #316]
13370138: d65f03c0 ret
pleb@gamey ~/elfloader/example_program_with_data $ readelf -l target/aarch64-unknown-none/release/example_program_with_data
Elf file type is EXEC (Executable file)
Entry point 0x13370124
There are 4 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000120 0x0000000013370120 0x0000000013370120
0x0000000000000004 0x0000000000000004 R 0x1
LOAD 0x0000000000000124 0x0000000013370124 0x0000000013370124
0x0000000000000018 0x0000000000000018 R E 0x4
LOAD 0x000000000000013c 0x000000001337013c 0x000000001337013c
0x0000000000000000 0x0000000000000001 RW 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x0
Section to Segment mapping:
Segment Sections...
00 .rodata
01 .text
02 .bss
03
このツールは LOAD セクション以外は気にしません。ELFヘッダーからエンディアン(リトル vs ビッグ)とビット数(32 vs 64)を判断し、そこからプログラムヘッダの仮想アドレス(ロード先)、ファイルサイズ(初期化済みバイト数)、メモリサイズ(実際のメモリ領域のサイズ)に基づいてフラットイメージを作成します。バイトはファイルからオフセットとファイルサイズに基づいて初期化され、その後メモリサイズに達するまでゼロで拡張されます(または、メモリサイズがファイルサイズより小さい場合は切り詰められます)。
これらの LOAD セクションは、ギャップに対してゼロバイトパディングを施して連結されます。
これは非常にシンプルで、ELF入力に依存しないように設計されています。実行可能ファイル、オブジェクトファイル、共有オブジェクト、コアダンプなど、特に気にしません。単にメモリのフラットな表現を提供するだけであり、それ以上でもそれ以下でもありません。
これにより、任意のELFをシェルコードに変換したり、組み込みデバイスなどアクセスが難しい領域でロードしやすい単純なファイル形式に変換できます。個人的には、MIPS NT 4.0 ローダー用に開発しました。これによりRustコードを実行できます。
このツールはデフォルトでFELFファイル形式を生成します。これはFalk ELFです。これはシンプルなファイル形式です:
FELF0001 - Magic header
entry - 64-bit little endian integer of the entry point address
base - 64-bit little endian integer of the base address to load the image
<image> - Rest of the file is the raw image, to be loaded at `base` and jumped
into at `entry`
このツールはデフォルトでFELFファイル形式を生成します。これはFalk ELFです。これはパーミッション付きのシンプルなファイル形式です:
FELF0002 - Magic header
entry - 64-bit little endian integer of the entry point address
base - 64-bit little endian integer of the base address to load the image
<image> - Rest of the file is the raw image, to be loaded at `base` and jumped
into at `entry`
<perms> - Permissions, matching the bytes of <image> where the byte contains
the following flags bitwise or-ed together:
0x01 - Executable, 0x02 - Writable, 0x04 - Readable
Padding bytes will be 0x00, and thus have no permissions for any
access