Created
May 23, 2025 11:21
-
-
Save cr0nx/588d910144549e5f7a5136b7fd662466 to your computer and use it in GitHub Desktop.
memfd_create blocker using Python+bpftrace -> Kill the ppid of memfd_create call
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import subprocess | |
| import os | |
| import signal | |
| import re | |
| # bpftrace script (embedded) | |
| BPFTRACE_SCRIPT = """ | |
| #include <linux/sched.h> | |
| #include <linux/cred.h> | |
| tracepoint:raw_syscalls:sys_enter | |
| /args->id == 319/ { // 319 is the syscall number for memfd_create | |
| $name = str(args->args[0], 128); | |
| $flags = args->args[1]; | |
| $parent_pid = ((struct task_struct *)curtask)->parent->pid; | |
| $parent_uid = ((struct task_struct *)curtask)->parent->cred->uid.val; | |
| printf("PID %d (%s) called memfd_create(name=%s, flags=%d), parent PID %d, parent UID %d\\n", | |
| pid, comm, $name, $flags, $parent_pid, $parent_uid); | |
| } | |
| """ | |
| def main(): | |
| # Write bpftrace script to a temporary file | |
| with open("/tmp/memfd_trace_ppid_uid.bt", "w") as f: | |
| f.write(BPFTRACE_SCRIPT) | |
| try: | |
| # Run bpftrace as a subprocess | |
| process = subprocess.Popen( | |
| ["sudo", "bpftrace", "/tmp/memfd_trace_ppid_uid.bt"], | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE, | |
| text=True | |
| ) | |
| # Regex to parse bpftrace output | |
| pattern = re.compile(r"PID (\d+) \((.*?)\) called memfd_create\(name=(.*?), flags=(\d+)\), parent PID (\d+), parent UID (\d+)") | |
| print("Monitoring memfd_create calls and sending SIGKILL to parent PIDs (UID 1000-2000)... Ctrl-C to exit") | |
| # Read bpftrace output | |
| for line in process.stdout: | |
| print(f"Raw output: {line.strip()}") # Debug: print raw line | |
| match = pattern.search(line.strip()) | |
| if match: | |
| pid = int(match.group(1)) | |
| comm = match.group(2) | |
| name = match.group(3) | |
| flags = int(match.group(4)) | |
| parent_pid = int(match.group(5)) | |
| parent_uid = int(match.group(6)) | |
| print(f"Parsed: PID {pid} ({comm}), name={name}, flags={flags}, parent PID {parent_pid}, parent UID {parent_uid}") | |
| # Check UID range (1000-2000) | |
| if 1000 <= parent_uid <= 2000: | |
| try: | |
| if os.path.exists(f"/proc/{parent_pid}"): | |
| os.kill(parent_pid, signal.SIGKILL) | |
| print(f"Sent SIGKILL to parent PID {parent_pid} (UID {parent_uid})") | |
| else: | |
| print(f"Parent PID {parent_pid} does not exist") | |
| except OSError as e: | |
| print(f"Failed to send SIGKILL to parent PID {parent_pid}: {e}") | |
| else: | |
| print(f"Parent UID {parent_uid} outside range 1000-2000, skipping SIGKILL") | |
| else: | |
| print(f"Failed to parse line: {line.strip()}") | |
| # Print stderr (for bpftrace errors) | |
| for line in process.stderr: | |
| print(f"bpftrace error: {line.strip()}") | |
| except KeyboardInterrupt: | |
| print("\nStopping bpftrace...") | |
| process.terminate() | |
| process.wait() | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| finally: | |
| if os.path.exists("/tmp/memfd_trace_ppid_uid.bt"): | |
| os.remove("/tmp/memfd_trace_ppid_uid.bt") | |
| if __name__ == "__main__": | |
| main() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Find more interesting stuff here: https://edu.defensive-security.com/