{"id":13508100,"url":"https://github.com/pmem/syscall_intercept","last_synced_at":"2025-09-17T20:32:11.667Z","repository":{"id":18919535,"uuid":"85574916","full_name":"pmem/syscall_intercept","owner":"pmem","description":"The system call intercepting library","archived":true,"fork":false,"pushed_at":"2025-01-06T16:26:18.000Z","size":511,"stargazers_count":639,"open_issues_count":31,"forks_count":123,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-03-11T10:50:10.979Z","etag":null,"topics":["intercepting-library","syscalls"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pmem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2017-03-20T12:36:18.000Z","updated_at":"2025-03-04T03:20:55.000Z","dependencies_parsed_at":"2024-11-01T07:31:22.330Z","dependency_job_id":"74a84993-f9cc-403c-945f-7937273575c8","html_url":"https://github.com/pmem/syscall_intercept","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pmem/syscall_intercept","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmem%2Fsyscall_intercept","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmem%2Fsyscall_intercept/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmem%2Fsyscall_intercept/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmem%2Fsyscall_intercept/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmem","download_url":"https://codeload.github.com/pmem/syscall_intercept/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmem%2Fsyscall_intercept/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275658721,"owners_count":25504776,"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","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["intercepting-library","syscalls"],"created_at":"2024-08-01T02:00:47.975Z","updated_at":"2025-09-17T20:32:11.297Z","avatar_url":"https://github.com/pmem.png","language":"C","readme":"# PROJECT NOT UNDER ACTIVE MANAGEMENT #  \nThis project will no longer be maintained by Intel.  \nIntel has ceased development and contributions including, but not limited to, maintenance, bug fixes, new releases, or updates, to this project.  \nIntel no longer accepts patches to this project.  \n If you have an ongoing need to use this project, are interested in independently developing it, or would like to maintain patches for the open source software community, please create your own fork of this project.  \n  \n# syscall_intercept\n\n[![Build Status](https://travis-ci.org/pmem/syscall_intercept.svg)](https://travis-ci.org/pmem/syscall_intercept)\n[![Coverage Status](https://codecov.io/github/pmem/syscall_intercept/coverage.svg)](https://codecov.io/gh/pmem/syscall_intercept)\n[![Coverity Scan Build Status](https://scan.coverity.com/projects/12890/badge.svg)](https://scan.coverity.com/projects/syscall_intercept)\n\nUserspace syscall intercepting library.\n\n# Dependencies #\n\n## Runtime dependencies ##\n\n * libcapstone -- the disassembly engine used under the hood\n\n## Build dependencies ##\n\n# Local build dependencies #\n\n * C99 toolchain -- tested with recent versions of GCC and clang\n * cmake\n * perl -- for checking coding style\n * pandoc -- for generating the man page\n\n### Travis CI build dependencies ###\n\nThe travis builds use some scripts to generate a docker images, in which syscall_intercept is built/tested.\nThese docker images are pushed to Dockerhub, to be reused in later travis builds.\nThe scripts expect four environment variables to be set in the travis environment:\n * DOCKERHUB_REPO - where to store the docker images used for building\n    e.g. in order to refer to a Dockerhub repository at https://hub.docker.com/r/pmem/syscall_intercept, this variable\n    should contain the string \"pmem/syscall_intercept\"\n * DOCKERHUB_USER - used for logging into Dockerhub\n * DOCKERHUB_PASSWORD - used for logging into Dockerhub\n * GITHUB_REPO - where the repository is available on github (e.g. \"pmem/syscall_intercept\" )\n\n### How to build ###\n\nBuilding libsyscall_intercept requires cmake.\nExample:\n```sh\ncmake path_to_syscall_intercept -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang\nmake\n```\nalternatively:\n```sh\nccmake path_to_syscall_intercept\nmake\n```\n\nThere is an install target. For now, all it does, is cp.\n```sh\nmake install\n```\n\nComing soon:\n```sh\nmake test\n```\n\n# Synopsis #\n\n```c\n#include \u003clibsyscall_intercept_hook_point.h\u003e\n```\n```sh\ncc -lsyscall_intercept -fpic -shared source.c -o preloadlib.so\n\nLD_PRELOAD=preloadlib.so ./application\n```\n\n##### Description: #####\n\nThe system call intercepting library provides a low-level interface\nfor hooking Linux system calls in user space. This is achieved\nby hotpatching the machine code of the standard C library in the\nmemory of a process. The user of this library can provide the\nfunctionality of almost any syscall in user space, using the very\nsimple API specified in the libsyscall_intercept\\_hook\\_point.h header file:\n```c\nint (*intercept_hook_point)(long syscall_number,\n\t\t\tlong arg0, long arg1,\n\t\t\tlong arg2, long arg3,\n\t\t\tlong arg4, long arg5,\n\t\t\tlong *result);\n```\n\nThe user of the library shall assign to the variable called\nintercept_hook_point a pointer to the address of a callback function.\nA non-zero return value returned by the callback function is used\nto signal to the intercepting library that the specific system\ncall was ignored by the user and the original syscall should be\nexecuted. A zero return value signals that the user takes over the\nsystem call. In this case, the result of the system call\n(the value stored in the RAX register after the system call)\ncan be set via the *result pointer. In order to use the library,\nthe intercepting code is expected to be loaded using the\nLD_PRELOAD feature provided by the system loader.\n\nAll syscalls issued by libc are intercepted. Syscalls made\nby code outside libc are not intercepted. In order to\nbe able to issue syscalls that are not intercepted, a\nconvenience function is provided by the library:\n```c\nlong syscall_no_intercept(long syscall_number, ...);\n```\n\nThree environment variables control the operation of the library:\n\n*INTERCEPT_LOG* -- when set, the library logs each syscall intercepted\nto a file. If it ends with \"-\" the path of the file is formed by appending\na process id to the value provided in the environment variable.\nE.g.: initializing the library in a process with pid 123 when the\nINTERCEPT_LOG is set to \"intercept.log-\" will result in a log file named\nintercept.log-123.\n\n*INTERCEPT_LOG_TRUNC -- when set to 0, the log file from INTERCEPT_LOG\nis not truncated.\n\n*INTERCEPT_HOOK_CMDLINE_FILTER* -- when set, the library\nchecks the command line used to start the program.\nHotpatching, and syscall intercepting is only done, if the\nlast component of the command used to start the program\nis the same as the string provided in the environment variable.\nThis can also be queried by the user of the library:\n```c\nint syscall_hook_in_process_allowed(void);\n```\n\n##### Example: #####\n\n```c\n#include \u003clibsyscall_intercept_hook_point.h\u003e\n#include \u003csyscall.h\u003e\n#include \u003cerrno.h\u003e\n\nstatic int\nhook(long syscall_number,\n\t\t\tlong arg0, long arg1,\n\t\t\tlong arg2, long arg3,\n\t\t\tlong arg4, long arg5,\n\t\t\tlong *result)\n{\n\tif (syscall_number == SYS_getdents) {\n\t\t/*\n\t\t * Prevent the application from\n\t\t * using the getdents syscall. From\n\t\t * the point of view of the calling\n\t\t * process, it is as if the kernel\n\t\t * would return the ENOTSUP error\n\t\t * code from the syscall.\n\t\t */\n\t\t*result = -ENOTSUP;\n\t\treturn 0;\n\t} else {\n\t\t/*\n\t\t * Ignore any other syscalls\n\t\t * i.e.: pass them on to the kernel\n\t\t * as would normally happen.\n\t\t */\n\t\treturn 1;\n\t}\n}\n\nstatic __attribute__((constructor)) void\ninit(void)\n{\n\t// Set up the callback function\n\tintercept_hook_point = hook;\n}\n```\n\n```sh\n$ cc example.c -lsyscall_intercept -fpic -shared -o example.so\n$ LD_LIBRARY_PATH=. LD_PRELOAD=example.so ls\nls: reading directory '.': Operation not supported\n```\n\n# Under the hood: #\n\n##### Assumptions: #####\nIn order to handle syscalls in user space, the library relies\non the following assumptions:\n\n- Each syscall made by the applicaton is issued via libc\n- No other facility attempts to hotpatch libc in the same process\n- The libc implementation is already loaded in the processes\nmemory space when the intercepting library is being initialized\n- The machine code in the libc implementation is suitable\nfor the methods listed in this section\n- For some more basic assumptions, see the section on limitations.\n\n##### Disassembly: #####\nThe library disassembles the text segment of the libc loaded\ninto the memory space of the process it is initialized in. It\nlocates all syscall instructions, and replaces each of them\nwith a jump to a unique address. Since the syscall instruction\nof the x86_64 ISA occupies only two bytes, the method involves\nlocating other bytes close to the syscall suitable for overwriting.\nThe destination of the jump (unique for each syscall) is a\nsmall routine, which accomplishes the following tasks:\n\n1. Optionally executes any instruction that originally\npreceded the syscall instruction, and was overwritten to\nmake space for the jump instruction\n2. Saves the current state of all registers to the stack\n3. Translates the arguments (in the registers) from\nthe Linux x86_64 syscall calling convention to the C ABI's\ncalling convention used on x86_64\n4. Calls a function written in C (which in turn calls\nthe callback supplied by the library user)\n5. Loads the values from the stack back into the registers\n6. Jumps back to libc, to the instruction following the\noverwritten part\n\n##### In action: #####\n\n*Simple hotpatching:*\nReplace a mov and a syscall instruction with a jmp instruction\n```\nBefore:                         After:\n\ndb2a0 \u003c__open\u003e:                 db2b0 \u003c__open\u003e:\ndb2aa: mov $2, %eax           /-db2aa: jmp e0000\ndb2af: syscall                |\ndb2b1: cmp $-4095, %rax       | db2b1: cmp $-4095, %rax ---\\\ndb2b7: jae db2ea              | db2b7: jae db2ea           |\ndb2b9: retq                   | db2b9: retq                |\n                              | ...                        |\n                              | ...                        |\n                              \\_...                        |\n                                e0000: mov $2, $eax        |\n                                ...                        |\n                                e0100: call implementation /\n                                ...                       /\n                                e0200: jmp db2aa ________/\n```\n*Hotpatching using a trampoline jump:*\nReplace a syscall instruction with a short jmp instruction,\nthe destination of which is a regular jmp instruction.\nThe reason to use this, is that a short jmp instruction\nconsumes only two bytes, thus fits in the place of a syscall\ninstruction. Sometimes the instructions directly preceding\nor following the syscall instruction can not be overwritten,\nleaving only the two bytes of the syscall instruction\nfor patching.\nThe hotpatching library looks for place for the trampoline jump\nin the padding found to the end of each routine. Since the start\nof all routines is aligned to 16 bytes, often there is a padding\nspace between the end of a symbol, and the start of the next symbol.\nIn the example below, this padding is filled with 7 byte long\nnop instruction (so the next symbol can start at the address 3f410).\n```\nBefore:                         After:\n\n3f3fe: mov %rdi, %rbx           3f3fe: mov %rdi, %rbx\n3f401: syscall                /-3f401: jmp 3f430\n3f403: jmp 3f415              | 3f403: jmp 3f415 ----------\\\n3f407: retq                   | 3f407: retq                |\n                              \\                            |\n3f408: nopl 0x0(%rax,%rax,1)  /-3f408: jmp e1000           |\n                              | ...                        |\n                              | ...                        |\n                              \\_...                        |\n                                e1000: nop                 |\n                                ...                        |\n                                e1100: call implementation /\n                                ...                       /\n                                e1200: jmp 3f403 ________/\n\n```\n\n# Limitations: #\n* Only Linux is supported\n* Only x86\\_64 is supported\n* Only tested with glibc, although perhaps it works\nwith some other libc implementations as well\n* There are known issues with the following syscalls:\n  * clone\n  * rt_sigreturn\n\n# Debugging: #\nBesides logging, the most important factor during debugging is to make\nsure the syscalls in the debugger are not intercepted. To achieve this, use\nthe INTERCEPT_HOOK_CMDLINE_FILTER variable described above.\n\n```\nINTERCEPT_HOOK_CMDLINE_FILTER=ls \\\n\tLD_PRELOAD=libsyscall_intercept.so \\\n\tgdb ls\n```\n\nWith this filtering, the intercepting library is not activated in the gdb\nprocess itself.\n","funding_links":[],"categories":["\u003ca id=\"9eee96404f868f372a6cbc6769ccb7f8\"\u003e\u003c/a\u003e新添加的","C","\u003ca id=\"9eee96404f868f372a6cbc6769ccb7f8\"\u003e\u003c/a\u003e工具","others"],"sub_categories":["\u003ca id=\"31185b925d5152c7469b963809ceb22d\"\u003e\u003c/a\u003e新添加的"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmem%2Fsyscall_intercept","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmem%2Fsyscall_intercept","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmem%2Fsyscall_intercept/lists"}