{"id":17912737,"url":"https://github.com/dergoegge/semsan","last_synced_at":"2025-09-11T00:44:20.256Z","repository":{"id":242690985,"uuid":"810259415","full_name":"dergoegge/semsan","owner":"dergoegge","description":"Semantics Sanitizer: Fuzz Driven Characterization Testing","archived":false,"fork":false,"pushed_at":"2024-08-21T14:00:30.000Z","size":181,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-08-21T15:53:52.127Z","etag":null,"topics":["differential-fuzzing","fuzzing"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dergoegge.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":"2024-06-04T10:59:33.000Z","updated_at":"2024-08-21T15:53:54.411Z","dependencies_parsed_at":"2024-08-19T12:46:49.126Z","dependency_job_id":null,"html_url":"https://github.com/dergoegge/semsan","commit_stats":null,"previous_names":["dergoegge/semsan"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dergoegge%2Fsemsan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dergoegge%2Fsemsan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dergoegge%2Fsemsan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dergoegge%2Fsemsan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dergoegge","download_url":"https://codeload.github.com/dergoegge/semsan/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221922096,"owners_count":16902262,"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":["differential-fuzzing","fuzzing"],"created_at":"2024-10-28T19:46:46.519Z","updated_at":"2024-10-28T19:46:47.040Z","avatar_url":"https://github.com/dergoegge.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"*Note: This is still a work in progress.*\n\n# Semantics Sanitizer\n\nMany software projects have to ensure that the behaviour of some of their\ncomponents does not change when the software is modified. For example, the\nbehaviour for implementations of cryptographic primitives should **always**\nremain the same, regardless of which version of the software is being used.\n\nSimply not modifying software once it has reached maturity seems like a simple\nsolution to this problem. However, all software needs a bare minimum amount of\nmaintenance to ensure it can continue to run on old and new systems. In\npratice, most software regularly receives invasive changes, such as\nrefactoring, performance improvements and new features.\n\nThe problem is often exasturbated by the fact that modifying software is not\nthe only avenue for behavioural differences. The CPU architecture used to\nexecute the software on or the compiler used to create the binaries can also\naffect program behaviour.\n\nSemantics Sanitizer's primary goal is to ease continuous differential fuzzing\nof the same piece of software across different revisions, architectures and\ncompilers.\n\n## Design\n\nSemSan is a coverage-guided fuzzer based on\n[LibAFL](https://github.com/AFLplusplus/LibAFL) and consists of two executors,\none for each harness being differentially fuzzed (primary, secondary). Each\nexecutor has an observer attached to it that collects an output value (which\ncharaterizes the semantics of the program under test) for each fuzz iteration.\nFor each input, the executors are run in sequence and the collected output\nvalues are compared. Should the output values not match then a semantic\ndifference has been found.\n\nOutput values are collected through a shared memory region. Harnesses can\nattach and write to the shared memory through the shared memory ID set by\nSemSan on the `SEMSAN_CHARACTERIZATION_SHMEM_ID` environment variable. Note\nthat the shared memory is only 32 bytes in size and harnesses should only write\na hash (or otherwise short summary) to it.\n\nSemSan loads the initial seeds from disk into memory and evolves the corpus in\nmemory, it is not persisted to disk. Inputs that trigger semantic differences\nare written to disk.\n\nAt the moment, SemSan supports afl style fork server executors (for targets\ncompiled with `afl-clang-{fast,lto,fast++,lto++}` or `afl-{gcc,g++}-fast`) and\n`libafl_qemu` executors (for emulating targets on different architectures). In\nthe future, the aim is to also support snapshot based executors (e.g.\nfull-system `libafl_qemu` or `nyx`).\n\n## Usage\n\n```\nUsage: semsan [OPTIONS] \u003cPRIMARY\u003e \u003cSECONDARY\u003e \u003cCOMMAND\u003e\n\nCommands:\n  fuzz      Differentially fuzz the primary and secondary harness\n  minimize  Minimize a solution\n  help      Print this message or the help of the given subcommand(s)\n\nArguments:\n  \u003cPRIMARY\u003e    Path to the binary of the primary harness to fuzz\n  \u003cSECONDARY\u003e  Path to the binary of the secondary harness to fuzz\n\nOptions:\n      --debug\n          Print various things that help with debugging SemSan itself.\n      --debug-children\n          Redirect the executors' std{out,err} to SemSan's std{out,err}. Useful for debugging solutions and harnesses.\n      --timeout \u003cTIMEOUT\u003e\n          Maximum amount of time a single input is allowed to run (in milliseconds per executor). [default: 1000]\n      --comparator \u003cCOMPARATOR\u003e\n          Choose differential value comparator function [default: equal] [possible values: not-equal, equal, less-than, less-than-or-equal, greater-than, greater-than-or-equal, custom]\n      --solution-exit-code \u003cSOLUTION_EXIT_CODE\u003e\n          Exit code for solutions [default: 71]\n      --qemu-entry \u003cQEMU_ENTRY\u003e\n          Symbol for the qemu entry breakpoint [default: LLVMFuzzerTestOneInput]\n      --primary-args \u003cPRIMARY_ARGS\u003e\n          Arguments to pass to the primary harness\n      --secondary-args \u003cSECONDARY_ARGS\u003e\n          Arguments to pass to the secondary harness\n      --args \u003cSHARED_ARGS\u003e\n          Arguments to pass to both harnesses\n      --ignore-exit-kind\n          Don't report differences in exit kind (e.g. crashes or timeouts) as behavioral differences\n  -h, --help\n          Print help\n```\n\nThe `--qemu-entry` option is only available if SemSan was compiled for\nemulation (e.g. `--features qemu_x86_64`).\n\n### Fuzzing\n\n```\nDifferentially fuzz the primary and secondary harness\n\nUsage: semsan \u003cPRIMARY\u003e \u003cSECONDARY\u003e fuzz [OPTIONS] --seeds \u003cSEEDS\u003e --solutions \u003cSOLUTIONS\u003e\n\nOptions:\n      --ignore-solutions\n          Keep fuzzing even if a solution has already been found\n      --foreign-corpus \u003cFOREIGN_CORPUS\u003e\n          Foreign fuzzer corpus to pull in inputs from\n      --foreign-sync-interval \u003cFOREIGN_SYNC_INTERVAL\u003e\n          Interval for syncing the foreign fuzzer corpus (in seconds) [default: 10]\n      --no-secondary-coverage\n          Don't collect coverage feedback for the secondary executor\n      --seeds \u003cSEEDS\u003e\n          Seed corpus directory\n      --solutions \u003cSOLUTIONS\u003e\n          Directory in which solutions (differential finds) will be stored\n  -h, --help\n          Print help\n```\n\n### Minimizing Solutions\n\n```\nMinimize a solution\n\nUsage: semsan \u003cPRIMARY\u003e \u003cSECONDARY\u003e minimize [OPTIONS] \u003cSOLUTION\u003e \u003cSOLUTIONS\u003e\n\nArguments:\n  \u003cSOLUTION\u003e   Path to the solution to minimize\n  \u003cSOLUTIONS\u003e  Directory storing minimized solutions\n\nOptions:\n      --iterations \u003cITERATIONS\u003e  Number of iterations to attempt minimization for [default: 128]\n  -h, --help                     Print help\n```\n\n### Comparators\n\nBy default SemSan will check for equality when comparing the observed output\nvalues but that is configurable with the `--comparator` option. Currently, the\nonly supported comparators are `not-equal`, `equal`, `less-than`,\n`less-than-or-equal`, `greater-than`, `greater-than-or-equal` and `custom`.\n\nUsing comparators other than `equal` can be useful when the harnesses under\ntest are allowed to behave differently to some extend.\n\nCustom comparators allow the user to provide their own comparison function by\n`LD_PRELOAD`ing a library. The custom comparator function should be defined as\na function called `semsan_custom_comparator` which should return `false` if the\noutput values indicate a solution.\n\n```C\nbool semsan_custom_comparator(const uint8_t *o1, size_t o1_len,\n                              const uint8_t *o2, size_t o2_len) {\n  // Custom comparator logic ...\n}\n```\n\nExample usage:\n\n```\nLD_PRELOAD=$PWD/custom_comp.so semsan \u003cprimary\u003e \u003csecondary\u003e --comparator custom fuzz \\\n  --seeds \u003cseeds\u003e --solutions \u003csolutions\u003e\n```\n\n### Ensembling with other engines\n\nSemSan is not meant to be used in isolation as it is quite a primitive fuzzer\non its own (e.g. no input-to-state, no corpus persistence). It is highly\nrecommended to ensemble SemSan with state of the art coverage-guided fuzzers\nsuch as [afl++](https://github.com/AFLplusplus/AFLplusplus),\n[honggfuzz](https://github.com/google/honggfuzz) or\n[libFuzzer](https://www.llvm.org/docs/LibFuzzer.html).\n\nThe `--foreign-corpus` option can be used for this purpose. It prompts SemSan\nto regularly load new inputs from the passed directory into it's in memory\ncorpus. The frequency of syncing with the foreign corpus can be adjusted with\nthe `--foreign-sync-interval` option.\n\n### Examples\n\nSee the [`examples/`](examples/) directory.\n\n## Related Work\n\n* [Finding Unstable Code via Compiler-Driven Differential\n  Testing](https://shao-hua-li.github.io/assets/pdf/2023_asplos_compdiff.pdf)\n* [LibAFL based fuzzer for differential fuzzing across\n  architectures](https://github.com/dergoegge/libdimpl)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdergoegge%2Fsemsan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdergoegge%2Fsemsan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdergoegge%2Fsemsan/lists"}