Tematem artykułu jest analiza binarna plików ELF (skrót od Executable and Linkable Format) i zrozumienie ich struktury. We wpisie przedstawię przydatne narzędzia do analizy tego typu plików. W celach demonstracyjnych w katalogu test_virus/ przygotowałem demonstracyjny kod (Goblin), który zostanie zbudowany i wstrzyknięty do pliku wykonywalnego (ELF).
Uwaga! Ten dokument zawiera analizy niskopoziomowe plików ELF oraz fragmenty kodu przygotowane wyłącznie w celach edukacyjnych.
Przedstawiamy ELFa
ELF to standardowy format plików binarnych używany głównie w systemach typu Unix, takich jak Linux czy FreeBSD. Służy do przechowywania:
- programów wykonywalnych,
- bibliotek współdzielonych (np. plików
.so), - kodu obiektowego,
- zrzutów pamięci (
core dumps).
Jest odpowiednikiem plików .exe zapisanych w formacie PE (Portable Executable), znanych z systemu Windows.
Format ELF wykorzystywany jest również w projektach embedded jako wynikowy plik kompilacji. My skupimy się na plikach ELF dla architektury x86-64 (AMD64) uruchamianych na systemie Linux.
Struktura pliku ELF
Plik ELF zawiera:
- Nagłówek – wskazuje podstawowe informacje o pliku, takie jak: typ, architektura, rozmiar i lokalizacja tabeli programów oraz sekcji.
- Program Header Table – opisuje, w jaki sposób poszczególne części pliku ładowane są do pamięci.
- Sekcje – różne części pliku ELF, takie jak: kod wykonywalny, dane, symbole itp. Najważniejsze sekcje to:
- .text – zawiera kod wykonywalny. Ta sekcja zostanie załadowana do pamięci z prawem do wykonania.
- .rodata – zawiera dane tylko do odczytu, np. łańcuchy znaków. Ta sekcja zostanie załadowana do pamięci z prawem tylko do odczytu.
- .data – zawiera dane do odczytu i zapisu. Tutaj znajdują się zainicjalizowane zmienne i zmienne globalne.
- Section Header Table – szczegółowo opisuje poszczególne sekcje.

Poszczególne struktury zostaną dokładniej omówione w dalszej części artykułu na przykładach informacji zwracanych przez narzędzia do analizy plików ELF.
Narzędzia do pracy z plikami ELF
W poniższych przykładach wykorzystana zostanie aplikacja app skompilowana z kodu źródłowego znajdującego się w katalogu app/ projektu (patrz punkt: Zbudowanie projektu). Polecenia wykonywane były z poziomu katalogu build/, więc app/app odnosi się do naszej testowej aplikacji.
readelf – narzędzie do wyświetlania informacji o plikach ELF
Przykład wyświetlenia nagłówka ELF
% readelf app/app -h
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: 0x4003a0
Start of program headers: 64 (bytes into file)
Start of section headers: 10880 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 32
Section header string table index: 31
Przyjrzyjmy się wyświetlonemu nagłówkowi, który zdefiniowany jest przez poniższą strukturę znajdującą się w kodzie źródłowym jądra Linuxa:
typedef struct elf64_hdr {
unsigned char e_ident[16]; /* ELF "magic number" */
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
Pole e_ident jest 16-bajtową tablicą identyfikacyjną, która opisuje podstawowe cechy pliku ELF, jeszcze zanim parser pozna resztę nagłówka.
Struktura e_ident:
| e_ident | rozmiar |
| EI_MAG x7fELF | 4 bajty |
| EI_CLASS | 1 bajt |
| EI_DATA | 1 bajt |
| EI_VERSION | 1 bajt |
| EI_OSABI | 1 bajt |
| EI_ABIVERSION | 1 bajt |
| EI_PAD | 7 bajtów |
Pierwsze 4 bajty (0x7F 'E' 'L' 'F') jednoznacznie identyfikują plik jako ELF. Kolejne bajty określają między innymi architekturę (32/64), endianowość, ABI i jego wersję. Ostatnie 7 bajtów to EI_PAD wypełniony zerami dla stałej długości 16 bajtów. Wykorzystamy je do umieszczenia znacznika infekcji w nagłówku pliku ELF.
Inne ważne pola nagłówka to:
- Type – określa typ pliku ELF (np. EXEC – pliki wykonywalne).
- Entry point – adres, pod którym rozpoczyna się wykonywanie programu.
- Start of program headers – offset w pliku ELF, pod którym znajduje się Program Header Table.
- Start of section headers – offset w pliku ELF, pod którym znajduje się Section Header Table.
Wyświetlenie tabeli nagłówków programu
% readelf app/app -lW
Elf file type is EXEC (Executable file)
Entry point 0x4003a0
There are 13 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000400040 0x0000000000400040 0x0002d8 0x0002d8 R 0x8
INTERP 0x001000 0x0000000000401000 0x0000000000401000 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x0004cd 0x0004cd R E 0x1000
LOAD 0x001000 0x0000000000401000 0x0000000000401000 0x000468 0x000468 R 0x1000
LOAD 0x001dc8 0x0000000000402dc8 0x0000000000402dc8 0x000258 0x000390 RW 0x1000
DYNAMIC 0x001dd8 0x0000000000402dd8 0x0000000000402dd8 0x000200 0x000200 RW 0x8
NOTE 0x000318 0x0000000000400318 0x0000000000400318 0x000024 0x000024 R 0x4
NOTE 0x001408 0x0000000000401408 0x0000000000401408 0x000040 0x000040 R 0x8
NOTE 0x001448 0x0000000000401448 0x0000000000401448 0x000020 0x000020 R 0x4
GNU_PROPERTY 0x001408 0x0000000000401408 0x0000000000401408 0x000040 0x000040 R 0x8
GNU_EH_FRAME 0x00134c 0x000000000040134c 0x000000000040134c 0x00002c 0x00002c R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x001dc8 0x0000000000402dc8 0x0000000000402dc8 0x000238 0x000238 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .note.gnu.build-id .init .plt .text .fini
03 .interp .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .rodata .eh_frame_hdr .eh_frame .note.gnu.property .note.ABI-tag
04 .init_array .fini_array .dynamic .got .got.plt .data .bss
05 .dynamic
06 .note.gnu.build-id
07 .note.gnu.property
08 .note.ABI-tag
09 .note.gnu.property
10 .eh_frame_hdr
11
12 .init_array .fini_array .dynamic .got
Tabela nagłówków programu określa, jak poszczególne części pliku ELF są mapowane na segmenty w pamięci. Kolejne wpisy informują kernel, w jaki sposób dane z pliku ELF należy umieścić w pamięci procesu. Przykładowo pierwszy wiersz pokazuje, że nagłówek programu (PHDR) zaczyna się od offsetu 0x000040 w pliku, ma rozmiar 0x0002d8 bajtów i jest mapowany na adres wirtualny 0x0000000000400040. Wpis jest oznaczony jako tylko do odczytu (R).
Po załadowaniu tabeli nagłówków programu kernel może zdekodować kolejne struktury. Następny wpis wskazuje na interpreter programu, który ma zostać użyty do załadowania bibliotek. Kolejne wpisy opisują segmenty ładowane do pamięci (np. kod, dane). Warto też zwrócić uwagę na wyrównanie do rozmiaru strony (zwykle 4 KiB) – wykorzystamy tę właściwość do umieszczenia kodu wirusa. Jeden segment w pamięci może zawierać jedną lub więcej sekcji pliku ELF.
Wyświetlenie tabeli nagłówków sekcji
% readelf app/app -SW
There are 32 section headers, starting at offset 0x2a80:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .note.gnu.build-id NOTE 0000000000400318 000318 000024 00 A 0 0 4
[ 2] .init PROGBITS 000000000040033c 00033c 00001b 00 AX 0 0 4
[ 3] .plt PROGBITS 0000000000400360 000360 000040 10 AX 0 0 16
[ 4] .text PROGBITS 00000000004003a0 0003a0 00011e 00 AX 0 0 16
[ 5] .fini PROGBITS 00000000004004c0 0004c0 00000d 00 AX 0 0 4
[ 6] .interp PROGBITS 0000000000401000 001000 00001c 00 A 0 0 1
[ 7] .gnu.hash GNU_HASH 0000000000401020 001020 000028 00 A 8 0 8
[ 8] .dynsym DYNSYM 0000000000401048 001048 0000c0 18 A 9 1 8
[ 9] .dynstr STRTAB 0000000000401108 001108 000124 00 A 0 0 1
[10] .gnu.version VERSYM 000000000040122c 00122c 000010 02 A 8 0 2
[11] .gnu.version_r VERNEED 0000000000401240 001240 000050 00 A 9 2 8
[12] .rela.dyn RELA 0000000000401290 001290 000048 18 A 8 0 8
[13] .rela.plt RELA 00000000004012d8 0012d8 000048 18 AI 8 23 8
[14] .rodata PROGBITS 0000000000401320 001320 000029 00 A 0 0 8
[15] .eh_frame_hdr PROGBITS 000000000040134c 00134c 00002c 00 A 0 0 4
[16] .eh_frame PROGBITS 0000000000401378 001378 00008c 00 A 0 0 8
[17] .note.gnu.property NOTE 0000000000401408 001408 000040 00 A 0 0 8
[18] .note.ABI-tag NOTE 0000000000401448 001448 000020 00 A 0 0 4
[19] .init_array INIT_ARRAY 0000000000402dc8 001dc8 000008 08 WA 0 0 8
[20] .fini_array FINI_ARRAY 0000000000402dd0 001dd0 000008 08 WA 0 0 8
[21] .dynamic DYNAMIC 0000000000402dd8 001dd8 000200 10 WA 9 0 8
[22] .got PROGBITS 0000000000402fd8 001fd8 000010 08 WA 0 0 8
[23] .got.plt PROGBITS 0000000000402fe8 001fe8 000030 08 WA 0 0 8
[24] .data PROGBITS 0000000000403018 002018 000008 00 WA 0 0 4
[25] .bss NOBITS 0000000000403040 002020 000118 00 WA 0 0 64
[26] .comment PROGBITS 0000000000000000 002020 00005c 01 MS 0 0 1
[27] .annobin.notes PROGBITS 0000000000000000 00207c 00014f 01 MS 0 0 1
[28] .gnu.build.attributes NOTE 0000000000405158 0021cc 000144 00 0 0 4
[29] .symtab SYMTAB 0000000000000000 002310 0003a8 18 30 18 8
[30] .strtab STRTAB 0000000000000000 0026b8 000288 00 0 0 1
[31] .shstrtab STRTAB 0000000000000000 002940 00013b 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
Tabela nagłówków sekcji szczegółowo opisuje poszczególne sekcje pliku ELF zapisanego na dysku.
objdump – narzędzie do analizy i deasemblacji plików ELF
Przykład deasemblacji sekcji .text:
% objdump -M intel -d -j .text app/app
app/app: file format elf64-x86-64
Disassembly of section .text:
00000000004003a0 <_start>:
4003a0: f3 0f 1e fa endbr64
4003a4: 31 ed xor ebp,ebp
4003a6: 49 89 d1 mov r9,rdx
4003a9: 5e pop rsi
4003aa: 48 89 e2 mov rdx,rsp
4003ad: 48 83 e4 f0 and rsp,0xfffffffffffffff0
4003b1: 50 push rax
4003b2: 54 push rsp
4003b3: 45 31 c0 xor r8d,r8d
4003b6: 31 c9 xor ecx,ecx
4003b8: 48 c7 c7 86 04 40 00 mov rdi,0x400486
4003bf: ff 15 13 2c 00 00 call QWORD PTR [rip+0x2c13] # 402fd8 <__libc_start_main@GLIBC_2.34>
4003c5: f4 hlt
.
.
.
Pierwsza kolumna to offset, którego interpretacja może być różna w zależności od tego, czy patrzymy na program skompilowany jako PIE (Position Independent Executable), czy nie. Druga kolumna to kod maszynowy, który jest wykonywany przez procesor. Trzecia to dezasemblacja kodu maszynowego na instrukcje asemblera w składni Intel.
Odczyt sekcji .rodata:
% objdump -d -j .rodata app/app
app/app: file format elf64-x86-64
Disassembly of section .rodata:
0000000000401320 <_IO_stdin_used>:
401320: 01 00 02 00 00 00 00 00 ........
0000000000401328 <__dso_handle>:
...
401330: 48 65 6c 6c 6f 2c 20 49 20 61 6d 20 4c 69 6e 75 Hello, I am Linu
401340: 78 27 73 20 45 4c 46 21 00 x's ELF!.
Co się dzieje przed wywołaniem main()
W nagłówku ELF znajduje się entry point, czyli adres, od którego zaczyna się wykonywanie programu. Ale co jest pierwszą wykonywaną instrukcją?
Pierwsza instrukcja pochodzi zazwyczaj z pliku obiektowego crt0.o. W pliku tym znajduje się funkcja _start(), która przygotowuje środowisko dla programu i wywołuje funkcję main(). Wszystkie programy napisane w C domyślnie są linkowe z crt0.o, chyba że zostanie użyta opcja nostartfiles. Skorzystamy z niej w trakcie kompilacji naszego wirusa.
W kodzie kernela można znaleźć funkcję load_elf_binary() służącą do ładowania plików ELF, która korzysta z tych informacji.
Goblin
Nasz demonstracyjny wirus, tak jak goblin, jest całkiem niegroźny, wyświetla jedynie informację, że jego kod został wstrzyknięty i uruchomiony w ramach zmodyfikowanego pliku wykonywalnego ELF.
Budowa wirusa
Wirus należy skompilować jako PIE (Position Independent Executable), czyli musi być niezależny od adresu bazowego w pamięci. Oznacza to, że wszystkie odwołania do adresów muszą być względne, by umożliwić załadowanie wirusa w dowolnym miejscu w pamięci.
Wirus musi być również samowystarczalny, co oznacza, że nie może zależeć od zewnętrznych bibliotek ani zasobów. Przykładowo, nie może używać funkcji printf() ze standardowej biblioteki C. Chodzi o to, że bardzo trudno jest z poziomu wirusa zlokalizować funkcje z zewnętrznych bibliotek, które są dynamicznie ładowane.
Chcemy, aby kod wirusa można było wyciąć jako jeden cały blok binarny dający się wstrzyknąć do zainfekowanego programu. Zazwyczaj instrukcje wirusa są wykonywane przed kodem zainfekowanego programu. Nie chcemy dwukrotnie wykonywać kodu startowego biblioteki C. Dlatego musimy sami przygotować środowisko do wywołania funkcji main() wirusa, następnie przywrócić stan rejestrów i przekierować wykonanie do oryginalnych instrukcji zainfekowanego programu. Sprowadza się to do przygotowania własnego kodu startowego oraz skryptu linkera, aby poskładać wszystko w odpowiedni sposób.

Kod startowy
Najważniejsze części tego kodu to:
- Przygotowanie stosu przed wywołaniem funkcji
main()wirusa. - Przywrócenie stanu rejestrów po zakończeniu działania wirusa.
- Przekierowanie wykonania do oryginalnego punktu wejścia zainfekowanego programu, zrealizowane poprzez skok do odpowiedniego adresu w pamięci obliczonego podczas infekcji. Miejsce na wstawienie instrukcji skoku wyznaczają puste instrukcje
nopna końcu kodu startowego.
.section .text.start_parasite
.global _start
_start:
push %rax
push %rbx
push %rcx
push %rdx
push %rbp
push %rsi
push %rdi
push %r8
push %r9
push %rsp
call main
pop %rsp
pop %r9
pop %r8
pop %rdi
pop %rsi
pop %rbp
pop %rdx
pop %rcx
pop %rbx
pop %rax
/* offset from _start is 29
must be aligned with parasite_entry_jmp_offset inside Infector class */
.global _patch_return
_patch_return:
/*
place a jump instruction here to redirect execution to the original entry point
*/
nop
nop
nop
nop
nop
hlt
Kod główny wirusa
Nasz demonstracyjny wirus ma za zadanie jedynie wyświetlenie komunikatu na standardowym wyjściu. Już na pierwszy rzut oka widać, że różni się on od tradycyjnego „Hello, World!” w C. Jest to spowodowane ograniczeniami opisanymi powyżej.
Po pierwsze nie możemy użyć funkcji printf() z biblioteki standardowej C, ponieważ nie możemy polegać na zewnętrznych bibliotekach. Musimy użyć bezpośrednich wywołań systemowych do komunikacji z jądrem. Tablica znakowa jest zdefiniowana i zainicjalizowana w taki sposób, aby łańcuch znakowy nie został umieszczony w sekcji danych. Całość umieszczona jest w sekcji .text dla łatwiejszej ekstrakcji całego wirusa.
#include "helpers/sys.h"
int main() {
char str[21] = {0};
str[0] = 'H'; str[1] = 'e'; str[2] = 'l'; str[3] = 'l';
str[4] = 'o'; str[5] = ','; str[6] = ' '; str[7] = 'I';
str[8] = ' '; str[9] = 'a'; str[10] = 'm'; str[11] = ' ';
str[12] = 'G'; str[13] = 'o'; str[14] = 'b'; str[15] = 'l';
str[16] = 'i'; str[17] = 'n'; str[18] = '!'; str[19] = '\n';
str[20] = '\0';
write(1, str, strlen(str));
return 0;
}
Aby całość mogła zadziałać, potrzebny jest odpowiedni skrypt linkera oraz kompilacja z odpowiednimi flagami, z których najważniejsze to te mówiące o konieczności kompilacji jako PIE oraz o braku domyślnych plików startowych.
Szczegóły znajdują się w pliku test_virus/CMakeLists.txt projektu.
Wycięcie kodu wirusa
Skorzystajmy z narzędzia objcopy:
% objcopy -j .text -O binary test_virus/test_virus extracted
Przykładowa aplikacja wykorzystywana do infekcji
Aplikacja to typowy program „Hello, World!” w C++, skompilowany w standardowy sposób.
#include <iostream>
int gint = -1;
int main(int argc, char **argv)
{
std::cout << "Hello, I am Linux's ELF!" << std::endl;
return (gint + argc);
}
Program infekujący
Technika infekcji – Text Injection
Program infekujący modyfikuje plik ELF w celu wstrzyknięcia kodu wirusa. Proces ten obejmuje analizę struktury pliku ELF, znalezienie odpowiedniego miejsca na wstrzyknięcie kodu oraz aktualizację struktur pliku, aby uwzględnić nowy kod.
Technika ta jest znana jako text injection, ponieważ kod wirusa jest wstrzykiwany do segmentu zawierającego kod wykonywalny (.text). Jest to jedna z prostszych technik infekcji plików ELF, ponieważ nie wymaga dodawania nowych sekcji ani segmentów. Jej ograniczeniem jest konieczność znalezienia wystarczająco dużej przestrzeni w istniejącym segmencie kodu, aby pomieścić kod wirusa.
Implementacja programu infekującego
Klasa Infector, odpowiada za:
- Wykrywanie możliwości infekcji:
- Sprawdzenie rozmiaru pliku (musi być większy niż minimalny rozmiar).
- Sprawdzenie pierwszych 4 bajtów pliku (0x7F ‘E’ ‘L’ ‘F’).
- Sprawdzenie, czy plik jest już zainfekowany, aby nie infekować go kolejny raz. Znacznik infekcji VIR jest umieszczony w tablicy
&ehdr->e_ident[EI_PAD]w nagłówku ELF (podrozdział: readelf). Wykorzystaliśmy fakt, że te 7 bajtów jest zawsze wypełnione zerami w standardowych plikach ELF. Narzędzie xxd pozwala zobrazować zawartość tablicy e_ident przykładowego zainfekowanego pliku:% xxd infected_binary
00000000: 7f45 4c46 0201 0100 0056 4952 0000 0000 .ELF.....VIR.... - Walidacja typu pliku (tylko pliki wykonywalne).
- Weryfikacja architektury (x86-64).
- Znalezienie odpowiedniego miejsca na wstrzyknięcie kodu, które jest wystarczająco duże, aby pomieścić kod wirusa.
- Przeprowadzenie procesu infekcji:
- Umieszczenie znacznika infekcji w nagłówku ELF.
- Przekopiowanie kodu wirusa do znalezionego miejsca.
- Aktualizacja nagłówków programu i sekcji, aby uwzględnić nowy kod.
- Modyfikacja instrukcji skoku w kodzie startowym wirusa, aby przekierować wykonanie do oryginalnego punktu wejścia programu.
- Modyfikacja punktu wejścia programu, aby wskazywał na kod wirusa.
Zbudowanie projektu
Aby zbudować projekt, należy wykonać następujące kroki w katalogu głównym projektu:
% mkdir build
% cd build
% cmake ..
% make
Spowoduje to zbudowanie aplikacji, wirusa oraz programu infekującego. Zostanie przeprowadzony proces infekcji i uruchomienie zainfekowanego pliku wykonywalnego.
[ 12%] Building CXX object infector/CMakeFiles/infector.dir/infector.cpp.o
[ 25%] Building CXX object infector/CMakeFiles/infector.dir/main.cpp.o
[ 37%] Linking CXX executable infector
[ 37%] Built target infector
[ 50%] Building ASM object test_virus/CMakeFiles/test_virus.dir/startup_x86_64.S.o
[ 62%] Building CXX object test_virus/CMakeFiles/test_virus.dir/test_virus.cpp.o
[ 75%] Linking CXX executable test_virus
[ 75%] Built target test_virus
[ 87%] Building CXX object app/CMakeFiles/app.dir/app.cpp.o
[100%] Linking CXX executable app
[100%] Built target app
---------------------------------------------------
Extracting binary from test_virus, running infector and executing infected binary
Should be visible print from test_virus and app
---------------------------------------------------
Hello, I am Goblin!
Hello, I am Linux's ELF!
[100%] Built target run_test_virus
Infektora można użyć do infekcji dowolnego pliku ELF x86-64 na systemie Linux, pod warunkiem, że spełnia on kryteria opisane w dokumencie.
Pamiętaj jednak, że modyfikowanie plików wykonywalnych może naruszać zasady licencyjne oprogramowania oraz stanowić zagrożenie bezpieczeństwa.
% ./infector/infector /usr/bin/ls extracted infected_ls
% chmod +x infected_ls
% ./infected_ls
Hello, I am Goblin!
app CMakeCache.txt CMakeFiles cmake_install.cmake extracted infected_binary infected_ls infector Makefile test_virus

Podsumowanie
Artykuł przedstawia analizę plików ELF w celu zrozumienia ich struktury. Praktyczne zastosowanie tej wiedzy zostało zilustrowane poprzez stworzenie prostego wirusa ELF i programu infekującego. Wykorzystano do tego technikę text injection, której ograniczeniem jest możliwość wstrzyknięcia relatywnie niewielkiego kodu.
W rzeczywistości istnieje wiele bardziej zaawansowanych technik infekcji plików ELF, które pozwalają na większą elastyczność i skuteczność, ale są też bardziej skomplikowane w implementacji. Prawdziwe wirusy zdolne są do samoreplikacji, co wymaga dodatkowych mechanizmów do kopiowania swojego kodu do innych plików wykonywalnych. Zwiększa to zarówno złożoność implementacji jak i wielość kodu potrzebnego do realizacji takiego zadania.
Zachęcam Was do zapoznania się z kodem źródłowym zarówno wirusa, jak i programu infekującego, aby lepiej zrozumieć szczegóły implementacji.
Zostaw komentarz