Intro
Correctly configured AppLocker rules prevent the execution of untrusted executable files, scripts, and other potentially harmful content. However, it is essential to simplify the process of creating these rules by minimizing the overhead required to maintain them. And one of the popular way to do that is allowing execution of files signed by Microsoft and/or other well-known companies (HP, Oracle, Google, etc).
This is why tools like AaronLocker automatically generate rules that allow the execution of Microsoft-signed OS executable files. These files typically reside in directories like %Windir%
directories and loads DLLs using the LOAD_LIBRARY_SEARCH_SYSTEM32
flag, which prevents attacks where Microsoft-signed executable files load malicious libraries.
All modern Microsoft code is written with this security measure in mind. For example, here is a snippet from Microsoft’s Terminal project:
const PCWSTR pszConhostDllName = L"ConhostV1.dll";
// Load our implementation, and then Load/Launch the IO thread.
wil::unique_hmodule hConhostBin(LoadLibraryExW(pszConhostDllName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32));
Since LOAD_LIBRARY_SEARCH_SYSTEM32
forces LoadLibrary
to load DLLs exclusively from the %System32%
directory, attackers have lost the ability to inject malicious DLLs without Administrator or System privileges to replace these files. Also, take a look at functions like:
- AddDllDirectory
- SetDefaultDllDirectories
Another common approach in well-secured software is to use the WinVerifyTrust
Windows API to verify that a DLL loaded via LoadLibrary
is correctly signed with a valid certificate.
Unfortunately, some Microsoft executable files doesn’t use LOAD_LIBRARY_SEARCH_SYSTEM32
flag and are reused by attackers to carry out their attacks.
Once, I analyzed case when attacker use Microsoft Dism.exe and attacker’s DismCore.dll files. Dism.exe
, was a Microsoft-signed binary with the following certificate:



Below is the certificate in PEM:
-----BEGIN CERTIFICATE-----
MIIFBDCCA+ygAwIBAgITMwAAAXRp3hCLN2Wo1wAAAAABdDANBgkqhkiG9w0BAQsF
ADCBhDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEuMCwGA1UE
AxMlTWljcm9zb2Z0IFdpbmRvd3MgUHJvZHVjdGlvbiBQQ0EgMjAxMTAeFw0xNzA4
MTEyMDIzMzVaFw0xODA4MTEyMDIzMzVaMHAxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
ZnQgQ29ycG9yYXRpb24xGjAYBgNVBAMTEU1pY3Jvc29mdCBXaW5kb3dzMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyuCoDMzWlNVC+vhg3V+6NX6QuKLA
jZJuXxDdoGJ1eo8ZZTtlh5g462LV0LR1t8mbQQE5iU3QhtdSreQvV9OSfQKLLBfg
Pd/S8JKsA5hmpQB7+GTiBjI59/W2T3ANdpbszYJ7R7WjHcBDvCRK+2m4dFOjS45O
yzIsEpp411BcWbOWBpOBiulFOsqvPhaUWnaMfv3u95Nwc1RnFNJkSPPa/50gD4Ye
g2Bmfa7c3dDQr9pU6YJyvq7WhnYl9g3+qrLN/e71XHc9vjJEkIMzfp654a3EgM1f
vfcfRoXnB8gwAFGBWwggDuxYI7IiiTq02rfkxKFlyZAmuJqG7avckmBrQwIDAQAB
o4IBgDCCAXwwHwYDVR0lBBgwFgYKKwYBBAGCNwoDBgYIKwYBBQUHAwMwHQYDVR0O
BBYEFCYu9zida3q77NtVAqbC2phmlwnVMFIGA1UdEQRLMEmkRzBFMQ0wCwYDVQQL
EwRNT1BSMTQwMgYDVQQFEysyMjk4NzkrNzE5NTU1Y2ItNmRlMi00NDZjLWFjYmEt
ZDkwODk0YWNkODcyMB8GA1UdIwQYMBaAFKkpAjmOFsSXeM2Q+Z5PmuF8Va9TMFQG
A1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
Y3JsL01pY1dpblByb1BDQTIwMTFfMjAxMS0xMC0xOS5jcmwwYQYIKwYBBQUHAQEE
VTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz
L2NlcnRzL01pY1dpblByb1BDQTIwMTFfMjAxMS0xMC0xOS5jcnQwDAYDVR0TAQH/
BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAsDAOTTJRFPx4BeEahMFQT2AP2xGpWnOQ
4UPworK+VX5EX05sk/e/5nNs3rlHuZTs0G5EH3J8//93KB61rF7yhqhh3c0ZLSNu
g1Sssjqi2cZ4li3tyAwqBY2S1duDH9O64z23UMRQVf6ZbFLIMKd3p2+C1Z4CwcdW
fT2RujFB1OgJfy2x/hTadzgTdJajNttiYHbcDUgIuCIQNOEBSzZeH58mA91k3BqZ
2vJibyfW4C3JaXIfCX6P8cqA7i4QfD2nKPegweG9Cr4etSvGD4aat2B7oREHVtWC
XeHhqrvpa3rY5YvCoC7NoG34Gvhi6h2AhBpJaydMAVO66L2aNHbPmg==
-----END CERTIFICATE-----
An interesting aspect of Dism.exe
, as you may have already guessed, is that it does not use LoadLibraryEx
with the LOAD_LIBRARY_SEARCH_SYSTEM32 flag as shown below in disassembled code

This oversight allows it to load a DLL from unintended locations, bypassing applocker typical rules.
DismCore.dll
as you see the disassembled code above is one of the libraries that Dism.exe
searches for and loads upon execution. Due to the improper use of LoadLibrary
, Dism.exe
loads the DLL from the current directory instead of restricting it to %System32%
with LOAD_LIBRARY_SEARCH_SYSTEM32
. At the same time, since Dism.exe
is signed with a valid Microsoft private key/certificate, we can bypass the default AppLocker rules in the attacked computer.
CreateObjectFromModule calls DllGetClassObject which is used by the attackers in their DismCore.dll as we see later,

retrieves the current executable file path using GetRunningExeFolder
, concatenates it with the string "DismCore.dll"
, and loads it into its virtual address space using LoadLibraryEx
and then executes DllGetClassObject
.
DismCore.dll
is a C# .NET-built executable containing embedded shellcode, which is actually based on FireEye’s DueDLLigence project: https://github.com/fireeye/DueDLLigence.
Interesting that projects’ README describes approach with dism.exe and DllGetClassObject and the other ones so, IT security team need to add correspond rules to theirs system to detect such kind of activity.
Now, let’s take a look at DismCore.dll in DnSpy. Interesting that attackers didn’t even change assembly info before building the code

So, when bogus dism.exe calls DllGetClassObject from this DLL
public static bool DllGetClassObject()
{
DueDilly.RunShellcode();
return false;
}
Then RunShellcode is executed. It, in turn, calls DueDilly.ExecCreateThread() which performs shell decrypting as described here – https://recallfor.xyz/the-story-of-one-attack-shell-decryption/ and inserting into legitime process by the code shown below
IntPtr intPtr2 = DueDilly.VirtualAlloc(IntPtr.Zero, (uint)array.Length, DueDilly.MEM_COMMIT, DueDilly.PAGE_READWRITE);
bool flag3 = intPtr2 == IntPtr.Zero;
if (!flag3)
{
Marshal.Copy(array, 0, intPtr2, array.Length);
uint num6;
bool flag4 = !DueDilly.VirtualProtect(intPtr2, (uint)array.Length, DueDilly.PAGE_EXECUTE_READ, out num6);
if (flag4)
{
DueDilly.VirtualFree(intPtr2, 0U, DueDilly.FreeType.Release);
}
else
{
IntPtr intPtr = DueDilly.CreateThread((IntPtr)0, 0U, intPtr2, IntPtr.Zero, 0U, ref num);
bool flag5 = intPtr == IntPtr.Zero;
if (flag5)
{
DueDilly.VirtualFree(intPtr2, 0U, DueDilly.FreeType.Release);
}
else
{
DueDilly.WaitForSingleObject(intPtr, uint.MaxValue);
}
}
}
One interesting aspect here is that this dll code starts Notepad.exe
string process = DueDilly.DefProcPath;
// ...
DueDilly.PROCESS_INFORMATION process_INFORMATION = DueDilly.StartProcess(process);
you should see unusual activity (based on parent/child process starts) in your SIEM system, as well as in Sysmon or AppLocker logs
And the last moment regarding this attack. If we check the shell code in hex editor we will notice that there is interesting signature as shown below
41 58 41 58 5E 59 5A 41 58 41 59 41 5A 48 83 (XAX^YZAXAYAZH in ASCII)

Googling lets us to find article which describes payloads with the similar sequence of bytes , for an example:
- https://ciberseguridad.blog/analizando-y-detectando-los-reverse-meterpreter-http-de-metasploit-con-radare2
- https://github.com/giMini/PowerMemory/blob/master/PowerProcess/Inject-ShellCodeInProcess.ps1
- https://damonmohammadbagher.github.io/Posts/ebookBypassingAVsByCsharpProgramming/index.htm?page=Chapter%201.html
and we can create YAR rule for Metasploit shell
rule MetasploitShell {
meta:
description = ""Yara Rule wininet meterpreter reverse x64""
author = ""...""
reference = ""Internal Research""
strings:
$sequence1 = { 48 85 C0 74 67 48 01 D0 50 8B 48 18 44 8B 40 20 49 01 D0 E3 56 48 FF C9 41 8B 34 88 48 01 D6 4D 31 C9 48 31 C0 AC 41 C1 C9 0D 41 01 C1 38 E0 75 F1 4C 03 4C 24 08 45 39 D1 75 D8 58 44 8B 40 24 49 01 D0 66 41 8B 0C 48 44 8B 40 1C 49 01 D0 41 8B 04 88 48 01 D0 41 58 41 58 5E 59 5A 41 58 41 59 41 5A 48 83 EC 20 41 52 FF E0 58 }
$sequence2 = { 41 59 5A 48 8B 12 E9 4F FF FF FF 5D 6A 00 49 BE 77 69 6E 69 6E 65 74 00 41}
condition:
all of them