Sii Polska

SII UKRAINE

SII SWEDEN

  • Szkolenia
  • Kariera
Dołącz do nas Kontakt
Wstecz

Sii Polska

SII UKRAINE

SII SWEDEN

Wstecz
ELFy i Gobliny Linuxa

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:

  1. Nagłówek – wskazuje podstawowe informacje o pliku, takie jak: typ, architektura, rozmiar i lokalizacja tabeli programów oraz sekcji.
  2. Program Header Table – opisuje, w jaki sposób poszczególne części pliku ładowane są do pamięci.
  3. 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.
  4. Section Header Table – szczegółowo opisuje poszczególne sekcje.
Struktura pliku ELF
Ryc. 1 Struktura pliku ELF

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_identrozmiar
EI_MAG x7fELF4 bajty
EI_CLASS1 bajt
EI_DATA1 bajt
EI_VERSION1 bajt
EI_OSABI1 bajt
EI_ABIVERSION1 bajt
EI_PAD7 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.

Wstrzykiwanie wirusa
Ryc. 2 Wstrzykiwanie wirusa

Kod startowy

Najważniejsze części tego kodu to:

  1. Przygotowanie stosu przed wywołaniem funkcji main() wirusa.
  2. Przywrócenie stanu rejestrów po zakończeniu działania wirusa.
  3. 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 nop na 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:

  1. 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.
  2. 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
oferty pracy

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.

Pliki

5/5
Ocena
5/5
Avatar

O autorze

Łukasz Gęsieniec

Inżynier oprogramowania embedded z ponad 16 letnim doświadczeniem w pracy z mikrokontrolerami, systemami wieloprocesorowymi i technologiami komunikacyjnymi. Pracował z technologiami radiowymi (GSM, Wi Fi, RF Mesh) oraz interfejsami typowymi dla systemów wbudowanych. Specjalizuje się w C/C++, RTOS ach oraz debugowaniu złożonych problemów systemowych na Linuxie. Interesuje się bezpieczeństwem IT i inżynierią wsteczną

Wszystkie artykuły autora

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Cię również zainteresować

Dołącz do nas

Sprawdź oferty pracy

Pokaż wyniki
Dołącz do nas Kontakt

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?