{"id":13546108,"url":"https://github.com/gamozolabs/mesos","last_synced_at":"2026-04-08T13:32:49.815Z","repository":{"id":50416924,"uuid":"169938691","full_name":"gamozolabs/mesos","owner":"gamozolabs","description":"Binary coverage tool without binary modification for Windows","archived":false,"fork":false,"pushed_at":"2020-08-12T23:16:39.000Z","size":184,"stargazers_count":423,"open_issues_count":6,"forks_count":43,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-11-03T14:35:02.714Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/gamozolabs.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}},"created_at":"2019-02-10T03:19:19.000Z","updated_at":"2024-10-23T22:06:03.000Z","dependencies_parsed_at":"2022-09-06T15:51:57.702Z","dependency_job_id":null,"html_url":"https://github.com/gamozolabs/mesos","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamozolabs%2Fmesos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamozolabs%2Fmesos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamozolabs%2Fmesos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamozolabs%2Fmesos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gamozolabs","download_url":"https://codeload.github.com/gamozolabs/mesos/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246860282,"owners_count":20845637,"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-08-01T12:00:31.789Z","updated_at":"2026-04-08T13:32:49.804Z","avatar_url":"https://github.com/gamozolabs.png","language":"Rust","funding_links":[],"categories":["Vulnerability Assessment","Rust"],"sub_categories":["Binary Analysis \u0026 Reversing"],"readme":"![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]![Bag of Mesos][meso]\r\n\r\n# Summary\r\n\r\nMesos is a tool to gather binary code coverage on all user-land Windows targets without need for source or recompilation. It also provides an automatic mechanism to save a full minidump of a process if it crashes under mesos.\r\n\r\nMesos is technically just a really fast debugger, capable of handling tens of millions of breakpoints. Using this debugger, we apply breakpoints to every single basic block in a program. These breakpoints are removed as they are hit. Thus, mesos converges to 0-cost coverage as gathering coverage only has a cost the first time the basic block is hit.\r\n\r\n# Why?\r\n\r\nThis is effectively the successor of my 5+ year old Chrome IPC fuzzer. It doesn't have any fuzz components in it, but it is a high-performance debugger. This debugger can apply millions of breakpoints to gather coverage, and handle thousands of breakpoints per second to modify memory to inject inputs.\r\n\r\nThis strategy has worked out well for me historically and still is my go-to tooling for fuzzing targets on live systems.\r\n\r\nOut of the box it can be used to gather simple code coverage but it's designed to be easily modified to add fast breakpoint handlers to inject inputs. For example, put a breakpoint after `NtReadFile()` returns and modify the buffer in flight. I used this in Chrome to modify inbound IPC traffic in the browser.\r\n\r\n# Features\r\n\r\n## Code coverage\r\n\r\n![code coverage][code coverage]\r\n\r\n## Automatic full minidump saving\r\n\r\n![Crash being saved][crash saving]\r\n\r\n## IDA Coloring\r\n\r\n![IDA gettin colored up][ida coloring]\r\n\r\n# Quick Usage Guide\r\n\r\nSet `%PATH%` such that `idat64.exe` is in it:\r\n\r\n```\r\npath %PATH%;\"C:\\Program Files\\IDA 7.2\"\r\n```\r\n\r\nGenerate mesos (the first time will be slow):\r\n\r\n```\r\npowershell .\\offline_meso.ps1 \u003cpid\u003e\r\npython generate_mesos.py process_ida\r\n```\r\n\r\nGather coverage on target!\r\n\r\n```\r\ncargo build --release\r\ntarget\\release\\mesos.exe \u003cpid\u003e\r\n```\r\n\r\nApplying 1.6 million breakpoints? No big deal.\r\n\r\n```\r\nC:\\dev\\mesos\u003etarget\\release\\mesos.exe 13828\r\nmesos  is 64-bit: true\r\ntarget is 64-bit: true\r\n[      0.003783] Applied       5629 breakpoints (      5629 total breakpoints) notepad.exe\r\n[      0.028071] Applied      61334 breakpoints (     66963 total breakpoints) ntdll.dll\r\n[      0.035298] Applied      25289 breakpoints (     92252 total breakpoints) kernel32.dll\r\n[      0.058815] Applied      55611 breakpoints (    147863 total breakpoints) kernelbase.dll\r\n...\r\n[      0.667417] Applied      11504 breakpoints (   1466344 total breakpoints) oleacc.dll\r\n[      0.676151] Applied      19557 breakpoints (   1485901 total breakpoints) textinputframework.dll\r\n[      0.705431] Applied      66650 breakpoints (   1552551 total breakpoints) coreuicomponents.dll\r\n[      0.717276] Applied      25202 breakpoints (   1577753 total breakpoints) coremessaging.dll\r\n[      0.720487] Applied       7557 breakpoints (   1585310 total breakpoints) ntmarta.dll\r\n[      0.732045] Applied      28569 breakpoints (   1613879 total breakpoints) iertutil.dll\r\n```\r\n\r\n# API\r\n\r\nCurrently this tool has a `debugger` lib you can easily bring in and start using to make custom debuggers. However this API is not finalized yet. I suggest not building anything using it yet as it may change very quickly. Once this message is removed it's probably stable :)\r\n\r\n# Performance\r\n\r\n- We can register (request breakpoints to be at module load) about ~6 million/second\r\n- We can apply them (actually install the breakpoints into the target at about ~3 million/second\r\n- We can clear breakpoints at about 15 million/second\r\n- We can hit and handle about 10k breakpoints/second\r\n\r\nGiven breakpoints are cleared as they're hit for coverage, that means you can observe 10k _new_ blocks per second. Once you've hit a breakpoint they no longer have a performance cost!\r\n\r\n```\r\nC:\\dev\\mesos\\examples\\benchmark\u003ecargo run --release\r\n    Finished release [optimized + debuginfo] target(s) in 0.03s\r\n     Running `target\\release\\benchmark.exe`\r\nmesos  is 64-bit: true\r\ntarget is 64-bit: true\r\nRegistered    1000000 breakpoints in   0.162230 seconds |  6164072.8 / second\r\nApplied       1000000 breakpoints in   0.321347 seconds |  3111897.0 / second\r\nCleared       1000000 breakpoints in   0.067024 seconds | 14920028.6 / second\r\nHit            100000 breakpoints in  10.066440 seconds |     9934.0 / second\r\n```\r\n\r\n# Usage\r\n\r\nTo use mesos there are 3 major steps. First, the modules of a running process are saved. Second, these modules are loaded in IDA which then outputs a list of all basic blocks into the `meso` format. And finally, `mesos` is run against a target process to gather coverage!\r\n\r\n## Creating meso_deps.zip\r\n\r\nThis step is the first thing we have to do. We create a ZIP file containing all of the modules loaded into a given PID.\r\n\r\nThis script requires no internet and is designed to be easily dropped onto new VMs so mesos can be generated for your target application. It depends on PowerShell v5.0 or later which is installed by default on Windows 10 and Windows Server 2016.\r\n\r\nRun, with `\u003cpid\u003e` replaced with the process ID you want to gather coverage on:\r\n\r\n```\r\nC:\\dev\\mesos\u003epowershell .\\offline_meso.ps1 8484\r\nPowershell is 64-bit: True\r\nTarget     is 64-bit: True\r\n\r\nC:\\dev\\mesos\u003e\r\n```\r\n\r\n_Optionally you can supply `-OutputZip \u003czipfile\u003e` to change the output zip file name_\r\n\r\nThis will create a `meso_deps.zip` that if you look at contains all of the modules used in the process you ran the script targeting.\r\n\r\n### Example output:\r\n\r\n```\r\nC:\\dev\\mesos\u003epowershell .\\offline_meso.ps1 8484 -OutputZip testing.zip\r\nPowershell is 64-bit: True                                                                                                                                         Target     is 64-bit: True                                                                                                                                                                                                                                                                                                            C:\\dev\\mesos\u003epowershell Expand-Archive testing.zip -DestinationPath example                                                                                        \r\nC:\\dev\\mesos\u003epowershell Get-ChildItem example -rec -File -Name\r\ncache\\c_\\program files\\common files\\microsoft shared\\ink\\tiptsf.dll\r\ncache\\c_\\program files\\intel\\optaneshellextensions\\iastorafsserviceapi.dll\r\ncache\\c_\\program files\\widcomm\\bluetooth software\\btmmhook.dll\r\ncache\\c_\\program files (x86)\\common files\\adobe\\coresyncextension\\coresync_x64.dll\r\n...\r\n```\r\n\r\n## Generating meso files\r\n\r\nTo generate meso files we operate on the `meso_deps.zip` we created in the last step. It doesn't matter where this zip came from. This allows the zip to have come from a VM that the PowerShell script was run on.\r\n\r\nBasic usage is:\r\n\r\n```\r\npython generate_mesos.py process_ida\r\n```\r\n\r\nThis will use the `meso_deps.zip` file as an input, and use IDA to process all executables in the zip file and figure out where their basic blocks are.\r\n\r\nThis will create a cache folder with a bunch of files in it. These files are named based on the module name, the modules TimeDateStamp in the PE header, and the ImageSize field in the PE header. This is what DLLs are uniqued by in the PDB symbol store, so it should be good enough for us here too.\r\n\r\nYou'll see there are files with no extension (these are the original binaries), there are files with `.meso` extensions (the breakpoint lists), and `.i64` files (the cached IDA database for the original binary).\r\n\r\n### Symbol resolution\r\n\r\nThere is no limitation on what can make these meso files. The quality of the symbol resolution depends on the tool you used to generate and it's ability to resolve symbols. For example with IDA if you have public/private symbols your `_NT_SYMBOL_PATH` should be configured correctly.\r\n\r\n### More advanced usage\r\n\r\nCheck the programs usage for the most recent usage. But there are `_whitelist` and `_blacklist` options that allow you to use a list of strings to filter the amount of mesos generated.\r\n\r\nThis is helpful as coverage outside of your target module is probably not relevant and just introduces overheads and unnecessary processing.\r\n\r\n```\r\nC:\\dev\\mesos\u003epython generate_mesos.py\r\nUsage:\r\n    generate_mesos.py process_ida\r\n        Processes all files in the meso_deps.zip file\r\n\r\n    generate_mesos.py process_ida_whitelist \u003cstr 1\u003e \u003cstr 2\u003e \u003cstr ...\u003e\r\n        Processes files only containing one of the strings provided\r\n\r\n    generate_mesos.py process_ida_blacklist \u003cstr 1\u003e \u003cstr 2\u003e \u003cstr ...\u003e\r\n        Processes files all files except for those containing one of the provided strings\r\n\r\nExamples:\r\n\r\n    python generate_mesos.py process_ida_whitelist system32\r\n        Only processes files in `system32`\r\n\r\n    python generate_mesos.py process_ida_blacklist ntdll.dll\r\n        Process all files except for `ntdll.dll`\r\n\r\nPath requirements for process_ida_*: must have `idat64.exe` in your PATH\r\n```\r\n\r\n### Example usage\r\n\r\n```\r\nC:\\dev\\mesos\u003epython generate_mesos.py process_ida_whitelist system32\r\nProcessing cache/c_/windows/system32/advapi32.dll\r\nProcessing cache/c_/windows/system32/bcryptprimitives.dll\r\nProcessing cache/c_/windows/system32/cfgmgr32.dll\r\n...\r\nProcessing cache/c_/windows/system32/user32.dll\r\nProcessing cache/c_/windows/system32/uxtheme.dll\r\nProcessing cache/c_/windows/system32/win32u.dll\r\nProcessing cache/c_/windows/system32/windows.storage.dll\r\nProcessing cache/c_/windows/system32/wintypes.dll\r\n```\r\n\r\n## Meso usage\r\n\r\nNow we're onto the actual debugger. We've created meso files to tell it where to put breakpoints in each module.\r\n\r\nFirst we need to build it with Rust!\r\n\r\n```\r\ncargo build --release\r\n```\r\n\r\nAnd then we can simply run it with a PID!\r\n\r\n```\r\ntarget\\release\\mesos.exe \u003cpid\u003e\r\n```\r\n\r\n### Command-line options\r\n\r\nCurrently there are few options to mesos, run mesos without arguments to get the most recent list.\r\n\r\n```\r\nC:\\dev\\mesos\u003etarget\\release\\mesos.exe\r\nUsage: mesos.exe \u003cpid\u003e [--freq | --verbose | --print] \u003cexplicit meso file 1\u003e \u003cexplicit meso file ...\u003e\r\n    --freq               - Treats all breakpoints as frequency breakpoints\r\n    --verbose            - Enables verbose prints for debugging\r\n    --print              - Prints breakpoint info on every single breakpoint\r\n    [explicit meso file] - Load a specific meso file regardless of loaded modules\r\n\r\nStandard usage: mesos.exe \u003cpid\u003e\r\n```\r\n\r\n### Example usage\r\n\r\n```\r\nC:\\dev\\mesos\u003etarget\\release\\mesos.exe 13828\r\nmesos  is 64-bit: true\r\ntarget is 64-bit: true\r\n[      0.004033] Applied       5629 breakpoints (      5629 total breakpoints) notepad.exe\r\n[      0.029248] Applied      61334 breakpoints (     66963 total breakpoints) ntdll.dll\r\n[      0.037032] Applied      25289 breakpoints (     92252 total breakpoints) kernel32.dll\r\n[      0.062844] Applied      55611 breakpoints (    147863 total breakpoints) kernelbase.dll\r\n...\r\n[      0.739059] Applied      66650 breakpoints (   1552551 total breakpoints) coreuicomponents.dll\r\n[      0.750266] Applied      25202 breakpoints (   1577753 total breakpoints) coremessaging.dll\r\n[      0.754485] Applied       7557 breakpoints (   1585310 total breakpoints) ntmarta.dll\r\n[      0.766119] Applied      28569 breakpoints (   1613879 total breakpoints) iertutil.dll\r\n...\r\n[     23.544097] Removed 5968 breakpoints in imm32.dll\r\n[     23.551529] Syncing code coverage database...\r\n[     23.675103] Sync complete (169694 total unique coverage entries)\r\nDetached from process 13828\r\n```\r\n\r\n#### Why not use `cargo run`?\r\n\r\nWhen running in `cargo run` the Ctrl+C handler does not work correctly, and does not allow us to detach from the target program cleanly.\r\n\r\n# Limitations\r\n\r\nSince this relies on a tool (IDA) to identify blocks, if the tool incorrectly identifies a block it could result in us inserting a breakpoint over data. Further it's possible to miss coverage if a block is not correctly found.\r\n\r\n# Why doesn't it do more?\r\n\r\nWell. It really just allows fast breakpoints. Feel free to rip it apart and add your own hooks to functions. It could easily be used to fuzz things :)\r\n\r\n# Why IDA?\r\n\r\nI tried a bunch of tools and IDA was the only one that seemed to work well. Binja probably would also work well but I don't have it installed and I'm not familiar with the API. I have a coworker who wrote a plugin for it and that'll probably get pull requested in soon.\r\n\r\n_The meso files are just simple files, anyone can generate them from any tool_\r\n\r\n# Technical Details\r\n\r\n## Minidump autogenned filenames\r\n\r\nThe generated minidump filenames are designed to give a high-level of glance value at crashes. It includes things like the exception type, faulting address, and rough classification of the bug.\r\n\r\nCurrently if it's an access violation we apply the following classification:\r\n\r\n- Determine the access type (read, write, execute)\r\n    - For reads the filename contains: \"read\"\r\n    - For writes the filename contains: \"WRITE\"\r\n    - For execute the filename contains: \"DEP\"\r\n- Determine if it's a non-canonical 64-bit address\r\n    - For non-canonical addresses the filename contains: NONCANON\r\n- Otherwise determine if it's a NULL dereference (within 32 KiB +- of NULL)\r\n    - Will put \"null\" in the filename\r\n- Otherwise it's considered a non-null deref and \"HIGH\" appears in the filename\r\n\r\nIt's intended that more severe things are in all caps to give higher glance value of prioritizing which crash dumps to look into more.\r\n\r\nExample minidump filename for chrome:\r\n\r\n```\r\ncrash_c0000005_chrome_child.dll+0x2c915c0_WRITE_null.dmp\r\n```\r\n\r\n## Meso file format\r\n\r\nComing soon (once it's stable)\r\n\r\n[meso]: assets/meso_bag.png\r\n[crash saving]: assets/crash_saving.png\r\n[code coverage]: assets/code_coverage.png\r\n[ida coloring]: assets/ida_coloring.png\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamozolabs%2Fmesos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgamozolabs%2Fmesos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamozolabs%2Fmesos/lists"}