
शेलकोड के लिए एक आर्किटेक्चर-स्वतंत्र ELF फ़ाइल फ्लैटनर
elfloader ELF फ़ाइलों के लिए एक अत्यंत सरल लोडर है जो ELF का एक फ्लैट इन-मेमोरी प्रतिनिधित्व उत्पन्न करता है।
इसे Rust के साथ जोड़ें और अब आप अपने शेलकोड को एक उचित, सुरक्षित, उच्च-स्तरीय भाषा में लिख सकते हैं। LLVM द्वारा लक्षित किया जा सकने वाला कोई भी लक्ष्य इस्तेमाल किया जा सकता है, जिसमें वास्तव में विदेशी प्लेटफ़ॉर्म और ABI के लिए कस्टम लक्ष्य विशिष्टताएँ शामिल हैं। 32-बिट सिस्टम पर u64 जैसी चीज़ों, बाउंड-चेक की गई सरणियों, आवंटन के ड्रॉप हैंडलिंग आदि का उपयोग करने का आनंद लें :)
यह बस सभी LOAD अनुभागों को एक साथ जोड़ता है, यदि कोई अंतराल हो तो शून्य-पैडिंग का उपयोग करके, एक बड़ी फ्लैट फ़ाइल में।
इस फ़ाइल में .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 का उपयोग कर सकते हैं!
यह प्रोजेक्ट यहाँ लाइव विकसित किया गया था:
example_small_program में एक उदाहरण है, बस make या nmake चलाएँ और यह एक example.bin उत्पन्न करना चाहिए जो 8 बाइट्स का है।
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 हेडर से एंडियननेस (लिटिल बनाम बिग) और बिटनेस (32 बनाम 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