Apr 27, 2018

[C#] Directory Hashing utility

Hello all, has been a little while since I posted anything, so I figured I would throw up a quick little project I needed for a specific task.  Recently I was tasked with sorting out a DFSR group policy synchronization issue.  During the troubleshooting process I was continuously trying to compare the folders to see if they were in sync. This is where I came up with my little Directory Hashing utility.

What does it do?

  • Provide a SHA256 hash of a directory
  • Provide a SHA256 comparison of two directories
  • Allows you to include extensions
  • Allows you to include directory names
  • Allows you to provide a file pattern

To determine the hash values of a directory, we simply perform a Directory.GetFiles, where we provide the path and a pattern of either *.* or of users choice.  We strip out the path from the filename, and compare filename with or without extension.

using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace DirHash
{
    internal class Program
    {
        private static string _pattern = "*.*";
        private static bool _includeExtension = false;
        private static bool _includeDirectories = false;
        private static string _dir1Name, _dir2Name = string.Empty;

        private static void Main(string[] args)
        {
            Console.WriteLine("Directory Hasher v.01 - Written by Netektives Technology\r\n");
            if (args.Length == 0)
            {
                Console.WriteLine("Usage:");
                Console.WriteLine("\tDirHash <dirname>\t\tCompute hash of provided directory");
                Console.WriteLine("\tDirHash <dir1> <dir2>\t\tCompare hashes of provided directories");
                Console.WriteLine("\tDirHash -p *.* <dir1>\t\tCompute hash of provided directory and file pattern");
                Console.WriteLine("\tDirHash -i <dir1> <dir2>\tCompare hashes of provided directories, including extensions");
                Console.WriteLine("\tDirHash -d <dir1>\t\tCompute hash of files and directory names of provided directory");
                return;
            }

            for (var i = 0; i<args.Length;i++)
            {
                if (args[i].ToLowerInvariant().StartsWith("-p"))
                {
                    _pattern = args[i + 1];
                    i++;
                }
                else if (args[i].ToLowerInvariant().StartsWith("-i")) _includeExtension = true;
                else if (args[i].ToLowerInvariant().StartsWith("-d")) _includeDirectories = true;
                else if (string.IsNullOrEmpty(_dir1Name)) _dir1Name = args[i];
                else if (string.IsNullOrEmpty(_dir2Name)) _dir2Name = args[i];
            }

            if (string.IsNullOrEmpty(_dir2Name))
                Console.WriteLine($"Hash of directory {_dir1Name}: {ComputeDirectoryHash(_dir1Name)}");
            else
            {
                var hash1 = ComputeDirectoryHash(_dir1Name);
                var hash2 = ComputeDirectoryHash(_dir2Name);
                Console.WriteLine($"Hash comparison for \r\n{_dir1Name}\r\n{_dir2Name}\r\nMatch: {hash1.Equals(hash2)}");
            }
        }

        private static string ComputeDirectoryHash(string dirPath)
        {
            if (!System.IO.Directory.Exists(dirPath))
            {
                Console.WriteLine("Directory provided does not exist!");
                return string.Empty;
            }
            var dirFiles = System.IO.Directory.GetFiles(dirPath, _pattern);
            if (dirFiles.Length == 0)
            {
                Console.WriteLine("Directory contains no files!");
                return string.Empty;
            }
            var concatDirFiles = new StringBuilder();
            foreach (var file in dirFiles)
                concatDirFiles.Append(_includeExtension ? System.IO.Path.GetFileName(file) : System.IO.Path.GetFileNameWithoutExtension(file));
            if (_includeDirectories)
            {
                var dirDirs = System.IO.Directory.GetDirectories(dirPath);
                if (dirDirs.Length > 0)
                    foreach (var dir in dirDirs)
                        concatDirFiles.Append(dir.Substring(dir.LastIndexOf(@"\")+1, dir.Length - (dir.LastIndexOf(@"\")+1)));
            }

            return ComputeSha256Hash(concatDirFiles.ToString());
        }

        private static string ComputeSha256Hash(string value)
        {
            var bytes = Encoding.UTF8.GetBytes(value);
            var sha256Managed = new SHA256Managed();
            var hash = sha256Managed.ComputeHash(bytes);
            return hash.Aggregate(string.Empty, (current, h) => current + h.ToString("x2"));
        }
    }
}
Oct 20, 2017

Microsoft Office Windows Dynamic Data Exchange (DDE) Mitigations

Out with the old, in with the new. Are macro trojans a thing of the past, or just put off to the side while the new kid on the block gets to show off for a bit? That’s the question behind Dynamic Data Exchange method of executing a payload. Using this technique, which has been available since Windows 2.0, allows an attacker to give the user a different prompt when sending a document with a malicious payload, and in some cases, can change it to say whatever they want!

If you’re looking to spin your head around for a bit reading up on the technical specs, here is a link from Microsoft outlining DDE

I’m going to share with you a couple of methods that can be used to mitigate this threat, in various environments.

Let’s start out with the basics, of getting the registry changes that will be needed:

(Credit to: https://gist.github.com/wdormann for sharing this!)

Let’s start out by saving a copy of the disable_ddeauto.reg file somewhere on your network, or local machine. If you’re saving it on your network, put it on a shared drive, and set the permissions to read only.

Here are some ways you can import this registry file:


reg.exe IMPORT disable_ddeauto.reg

DisableDDE.bat


%windir%\system32\reg.exe IMPORT \\server\share\disable_ddeauto.reg

DisableDDE.ps1


[Diagnostics.Process]::Start("reg.exe","import \\server\share\disable_ddeauto.reg")

By placing either of these methods in the Logon policy under User Settings, will ensure that Office 2010-2016 will block

The following script can be converted easily into a base 64 string

DisableDDE-Direct.ps1


New-Item -Path c:\temp -Force
(New-Object System.Net.WebClient).DownloadFile("https://gist.githubusercontent.com/wdormann/732bb88d9b5dd5a66c9f1e1498f31a1b/raw/6d19917f59f1d20c46ddc9c97765bc6ef4f2814e/disable_ddeauto.reg", "c:\temp\disable_ddeauto.reg")
[Diagnostics.Process]::Start("reg.exe", "import c:\temp\disable_ddeauto.reg")
Remove-Item -Path C:\temp\disable_ddeauto.reg -Force

Finally if you have a method of “firing and forgetting” to multiple systems to protect, you can convert to a base64 value and push through a command line:


$stringToEncode =
{
New-Item -Path c:\temp -Force
(New-Object System.Net.WebClient).DownloadFile("https://gist.githubusercontent.com/wdormann/732bb88d9b5dd5a66c9f1e1498f31a1b/raw/6d19917f59f1d20c46ddc9c97765bc6ef4f2814e/disable_ddeauto.reg", "c:\temp\disable_ddeauto.reg")
[Diagnostics.Process]::Start("reg.exe", "import c:\temp\disable_ddeauto.reg")
Remove-Item -Path C:\temp\disable_ddeauto.reg -Force
}
$base64 = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($stringToEncode))

With it’s output (please don’t rely on mine! 😉)


powershell.exe -ex bypass -enc DQAKAE4AZQB3AC0ASQB0AGUAbQAgAC0AUABhAHQAaAAgAGMAOgBcAHQAZQBtAHAAIAAtAEYAbwByAGMAZQANAAoAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQARgBpAGwAZQAoACIAaAB0AHQAcABzADoALwAvAGcAaQBzAHQALgBnAGkAdABoAHUAYgB1AHMAZQByAGMAbwBuAHQAZQBuAHQALgBjAG8AbQAvAHcAZABvAHIAbQBhAG4AbgAvADcAMwAyAGIAYgA4ADgAZAA5AGIANQBkAGQANQBhADYANgBjADkAZgAxAGUAMQA0ADkAOABmADMAMQBhADEAYgAvAHIAYQB3AC8ANgBkADEAOQA5ADEANwBmADUAOQBmADEAZAAyADAAYwA0ADYAZABkAGMAOQBjADkANwA3ADYANQBiAGMANgBlAGYANABmADIAOAAxADQAZQAvAGQAaQBzAGEAYgBsAGUAXwBkAGQAZQBhAHUAdABvAC4AcgBlAGcAIgAsACAAIgBjADoAXAB0AGUAbQBwAFwAZABpAHMAYQBiAGwAZQBfAGQAZABlAGEAdQB0AG8ALgByAGUAZwAiACkADQAKAFsARABpAGEAZwBuAG8AcwB0AGkAYwBzAC4AUAByAG8AYwBlAHMAcwBdADoAOgBTAHQAYQByAHQAKAAiAHIAZQBnAC4AZQB4AGUAIgAsACAAIgBpAG0AcABvAHIAdAAgAGMAOgBcAHQAZQBtAHAAXABkAGkAcwBhAGIAbABlAF8AZABkAGUAYQB1AHQAbwAuAHIAZQBnACIAKQANAAoAUgBlAG0AbwB2AGUALQBJAHQAZQBtACAALQBQAGEAdABoACAAQwA6AFwAdABlAG0AcABcAGQAaQBzAGEAYgBsAGUAXwBkAGQAZQBhAHUAdABvAC4AcgBlAGcAIAAtAEYAbwByAGMAZQANAAoA

Good luck and happy protecting!

 

 

Jul 22, 2017

WMI Querying Techniques, Part 2 – Command Line

Photo by Jason Rosewell on Unsplash

In this post, we will be going over various WMI command line techniques and options, we’ll cover the built in alias, as well as using alternate namespaces and paths, and let’s not forget running remotely!  Let’s get started!

WMIC Aliases

One of the nice things Microsoft did when providing a command line utility for access WMI objects, is building Aliases on top of the more commonly used WMI Classes.  To follow along in any of our excercises today, you should open a command prompt or two as Administrator if you can.  If you don’t have Admin rights, that’s ok, you can do some of the querying as well.  Hopefully you read the last article on Wbemtest, we will keep that open to get some properties and methods as needed.

From your command prompt, type in “wmic /?” to get a list of commands and aliases.  Today we will be playing around with Process, Service, and Product. Faster IT has a good article mapping the Aliases and Classes. read more

Page 1 of 5
1 2 3 5