{"id":19234618,"url":"https://github.com/vimpostor/copycat","last_synced_at":"2025-07-02T01:34:26.740Z","repository":{"id":41815318,"uuid":"480060242","full_name":"vimpostor/copycat","owner":"vimpostor","description":"A library for intercepting system calls","archived":false,"fork":false,"pushed_at":"2025-01-05T15:03:50.000Z","size":131,"stargazers_count":79,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-20T10:09:49.033Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://blog.mggross.com/intercepting-syscalls/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vimpostor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-10T15:34:16.000Z","updated_at":"2025-05-16T02:35:36.000Z","dependencies_parsed_at":"2024-12-07T23:22:36.602Z","dependency_job_id":"f8e89708-1992-4ed0-a426-fb77b05089e1","html_url":"https://github.com/vimpostor/copycat","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/vimpostor/copycat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vimpostor%2Fcopycat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vimpostor%2Fcopycat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vimpostor%2Fcopycat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vimpostor%2Fcopycat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vimpostor","download_url":"https://codeload.github.com/vimpostor/copycat/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vimpostor%2Fcopycat/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263060813,"owners_count":23407576,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T16:14:27.384Z","updated_at":"2025-07-02T01:34:26.717Z","avatar_url":"https://github.com/vimpostor.png","language":"C","readme":"# Copycat\n\n[![Continuous Integration](https://github.com/vimpostor/copycat/actions/workflows/ci.yml/badge.svg)](https://github.com/vimpostor/copycat/actions/workflows/ci.yml)\n\nThis library allows you to overwrite system calls of arbitrary binaries in an intuitive way.\nFor example the following snippet tricks `cat` into opening another file than was given:\n```bash\necho \"a\" \u003e /tmp/a\necho \"b\" \u003e /tmp/b\nCOPYCAT=\"/tmp/a /tmp/b\" copycat -- cat /tmp/a # this will print \"b\"\n# Success! cat was tricked into opening /tmp/b instead of /tmp/a\n```\n\nInternally `copycat` uses a modern [Seccomp Notifier](https://man7.org/linux/man-pages/man2/seccomp_unotify.2.html) implementation to reliably intercept system calls.\nThis is more elegant and much faster than usual `ptrace`-based implementations. However due to this relatively new Linux Kernel feature, `copycat` only works on **Linux 5.9** or higher. Additionally, due to a [Linux kernel bug not notifying the supervisor when a traced child terminates](https://lore.kernel.org/all/20240628021014.231976-2-avagin@google.com/), it is recommended to use **Linux 6.11** or higher.\n\n# Building\n\nNote: Arch users can install the [copycat-git](https://aur.archlinux.org/packages/copycat-git) AUR package.\n\n`copycat` is built with `cmake`:\n```bash\ncmake -B build\ncmake --build build\n\n# Usage\nCOPYCAT=\"source destination\" build/copycat -- /path/to/program\n\n# To install\ncmake --install build\n```\n\n# How does this work?\n\nHistorically, system call interception was done using `ptrace()`. This has the disadvantage of being very slow, as `ptrace()` will trigger twice per system call.\nUsing this method it is also incredibly cumbersome to overwrite system call arguments, and one quickly has to deal with architecture-specific quirks.\n\nRecent advancements in the [Seccomp Notifier](https://people.kernel.org/brauner/the-seccomp-notifier-cranking-up-the-crazy-with-bpf) API have made it possible to intercept any system call in a much more elegant way.\nThis also offers significant speed improvements, now the performance impact is closer to running the application in a container.\n\nFor a more detailed explanation see the [accompanying blog post](https://blog.mggross.com/intercepting-syscalls/).\n\n# Rules format\n\nRules can be supplied via the `$COPYCAT` environment variable. Alternatively create a file with the name `.copycat.conf` and add the rules, one rule per line.\n\nRules contain a source and destination that are split by a space. If the source ends with a trailing slash, the rule is recursive, i.e. the source is interpreted as directory and all folders and files within this directory are redirected.\nIf the destination also ends with a trailing slash, then a directory to directory mapping is created and the prefix is always replaced. If only the source ends with a trailing slash, then all files are mapped to the same location.\nOtherwise the rule matches source literally, i.e. the rule matches only the single file with the exact name like source.\n\n## Examples\n\n```bash\n# Redirect /tmp/a to /tmp/b\n/tmp/a /tmp/b\n# Redirect all files and folders in /tmp/f recursively to files and folders in /etc/f\n/tmp/f/ /etc/f/\n# Redirect all files and folders in /tmp/f to the single file /etc/f\n/tmp/f/ /etc/f\n```\n\n# Related work\n\n- [kafel](https://github.com/google/kafel) - This uses a similar approach for higher-level policy based filtering. It does not support modifying arguments of the system calls.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvimpostor%2Fcopycat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvimpostor%2Fcopycat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvimpostor%2Fcopycat/lists"}