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.

Saturday, April 7, 2018

A sample analysis walkthrough with RETouch

Here is an example how to analyze a malware with RETouch. The malware's hash (SHA256) is 63eaddbbe91031cb1d8f38cdbc679adacd232f97bbc061f02073d909c11c1594 and it can be found from VirusTotal. First I open datafile 63eaddbbe91031cb1d8f38cdbc679adacd232f97bbc061f02073d909c11c1594.bin (Word document). If I didn't know the SHA256, I would get the checksums first.
RETouch can calculate most commonly used hashes: MD5, SHA1 and SHA256.
Next, I check the strings that this binary file contains.
One string catches the attention: "powershell". Following strings look a lot like Base64 encoded data.
To extract Base64 data, I open binary file in hex view mode. After locating string "powershell", I select following text until I found '='-character.
I paste the text I copied from the hex view and convert Base64 to binary data.
Converted data's hex dump seems to have value zero in almost every second value. This indicates that hex dump could be Unicode encoded text.
The text really was Unicode encoded. Now I have PowerShell code which builds a string from numeric char values. I select only string building part of the code and execute the PowerShell code.
This gets the final unobfuscated code.
What the code actually does is not relevant now. The relevant thing in here is that RETouch has done its job.

Thursday, April 5, 2018

RETouch 1.0 released

RETouch is a windows application for deobfuscating and analyzing malicious scripts. Malicious scripts are commonly the first step of malware infection. Since script files are text-based, RETouch has functionality to handle texts and strings. For binary analyses there are plenty of excellent applications available. RETouch aims to be • extendible with scripting • "umbrella" for external applications Because malware and malicious scripts evolve quickly, the core functionality is just not enough. That is why RETouch provides easy scripting to extend its core functions.
Like any software with version number 1.0 this is far from perfect. I have started to program the next version with some features I left from version 1.0.