From 256d6e68bcee76e69be26b510af25ecd662b44c7 Mon Sep 17 00:00:00 2001 From: pyro Date: Fri, 17 Jul 2026 13:27:51 -0500 Subject: [PATCH] re-wrote the tool to use rayon instead of tokio for multitheading, its way faster now. Also worked on filtering out noise. --- Cargo.lock | 445 ++++++----------------- Cargo.toml | 3 +- src/main-bkup.rs | 425 ---------------------- src/main.rs | 915 +++++++++++++++++++++++++---------------------- 4 files changed, 610 insertions(+), 1178 deletions(-) delete mode 100644 src/main-bkup.rs diff --git a/Cargo.lock b/Cargo.lock index b7983e3..171cb49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -19,62 +19,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys", ] -[[package]] -name = "bitflags" -version = "2.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - [[package]] name = "clap" -version = "4.5.49" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -82,9 +64,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.49" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -94,9 +76,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -106,25 +88,87 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "colored" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + [[package]] name = "heck" version = "0.5.0" @@ -133,96 +177,52 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "libc" -version = "0.2.177" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.59.0", -] +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.41" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] -name = "redox_syscall" -version = "0.5.18" +name = "rayon" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ - "bitflags", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", ] [[package]] @@ -234,47 +234,17 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "signal-hook-registry" -version = "1.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - [[package]] name = "snaferrous" version = "1.2.0" dependencies = [ "clap", "colored", - "tokio", + "crossbeam", + "rayon", "walkdir", ] -[[package]] -name = "socket2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - [[package]] name = "strsim" version = "0.11.1" @@ -283,48 +253,20 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "tokio" -version = "1.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "utf8parse" @@ -342,19 +284,13 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -363,24 +299,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -389,132 +307,3 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" diff --git a/Cargo.toml b/Cargo.toml index 4136b6d..3bb6ed0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ edition = "2024" [dependencies] clap = { version = "4.5.41", features = ["derive"] } colored = "3.0.0" -tokio = { version = "1.48.0", features = ["full"] } +crossbeam = "0.8.4" +rayon = "1.12.0" walkdir = "2.5.0" [profile.release] diff --git a/src/main-bkup.rs b/src/main-bkup.rs deleted file mode 100644 index 0898a44..0000000 --- a/src/main-bkup.rs +++ /dev/null @@ -1,425 +0,0 @@ -/* -Author: Kevin (Kaged Pyro) Gunter -Purpose: I got tired of snaffler getting caught, so I rewrote it in rust, which edrs have trouble detecting. - -*/ -use clap::Parser; -use std::fmt::Debug; -use std::fs; -use std::fs::read_to_string; -use std::fs::OpenOptions; -use std::io::Write; -use std::ops::Index; -use std::path::PathBuf; -use std::process::exit; -use std::process::Command; -use std::thread; -use std::time::Duration; -use tokio; -use tokio::sync::mpsc::{channel, Sender, Receiver}; -use colored::Colorize; - -#[derive(Parser, Debug)] -#[command(version, about, long_about = Some("finds shares, but its written in rust which sometimes gets past EDR!"))] -struct Args{ - #[arg(short, long, help = "path to save output file Defaults to not saving output.")] - outfile: Option, - - #[arg(short, long, help = "number of threads to use, default to 10. \nNote thre thread count will be doubled, one set for share finder tasks, and one set for file and infor finding tasks.")] - threads: Option, - - #[arg(short, long, help = "specific targets. should be comma separated.")] - targets: Option, -} - -struct ShareFinder{ - id: usize, - tx: Sender, -} - -#[derive(Clone)] -struct Message{ - source: MessageType, - destination: MessageType, - content: String, -} - -#[derive(Clone, PartialEq)] -enum MessageType{ - ShareMessage, - InfoMessage, - ControlMessage, -} - - -async fn find_shares(task: ShareFinder, mut rx: Receiver){ - println!("{} share task started!", task.id); - let ping_recv = rx.recv().await; - if ping_recv.is_some(){ - let message = Message{source: MessageType::ShareMessage, destination: MessageType::ControlMessage, content: String::from("pong!")}; - task.tx.send(message).await.unwrap(); - } - loop{ - if rx.capacity() == 0{ - println!("rx is full for share finder {}", task.id); - } - let rx_res = rx.recv().await; - if rx_res.is_some(){ - let computer = rx_res.unwrap().content; - if computer == String::from("||DONE||"){ - let message = Message{source: MessageType::ShareMessage, destination: MessageType::ControlMessage, content: format!("{}:||DONE||", task.id)}; - task.tx.send(message).await.unwrap(); - break; - } - println!("scanning {}", computer); - let share_list_res = Command::new("net").arg("view").arg(computer.clone()).arg("/all").output(); - let mut error_string = String::new(); - let mut success_string = String::new(); - if share_list_res.is_ok(){ - let output = share_list_res.unwrap(); - if output.stdout.len() > 0{ - success_string = String::from_utf8_lossy(&output.stdout).to_string(); - } - - if output.stderr.len() > 0{ - error_string = String::from_utf8_lossy(&output.stderr).to_string(); - } - } - else{ - error_string = share_list_res.err().unwrap().to_string(); - } - if error_string.len() > 0{ - eprintln!("{}", "Error listing shares!".red()); - eprint!("{}", error_string.red()); - } - else if success_string.len() > 0{ - for line in success_string.lines(){ - if line.contains("Disk"){ - let share_name = line.split_whitespace().collect::>()[0]; - let share_path = format!("\\\\{}\\{}", computer, share_name); - let message = Message{source: MessageType::ShareMessage, destination: MessageType::InfoMessage, content: format!("{}:{}", task.id, share_path)}; - task.tx.send(message).await.unwrap(); - } - } - } - } - } -} - -async fn find_info(task: ShareFinder, mut rx: Receiver){ - println!("{} file task started!", task.id); - let ping_recv = rx.recv().await; - if ping_recv.is_some(){ - let message = Message{source: MessageType::ShareMessage, destination: MessageType::ControlMessage, content: String::from("pong!")}; - task.tx.send(message).await.unwrap(); - } - let files_to_read = vec![ - ".txt", - ".ini", - ".xml", - ".json", - ".config", - ".conf", - ".bat", - ".cmd", - ".sql", - ".ps1", - ".py", - ".vbscript" - ]; - - let interesting_info = vec![ - "password", - "pass", - "user", - "api", - "key", - "credit card", - "cc", - "ssn", - "social Security", - "tax", - "i9", - "it", - "identified", - "username", - ]; - loop{ - let rx_res = rx.recv().await; - if rx_res.is_some(){ - let message = rx_res.unwrap(); - let message_vec: Vec<&str> = message.content.split(":").collect(); - let path = message_vec[1]; - if path.contains("||DONE||"){ - let done_message = Message{source: MessageType::InfoMessage, destination: MessageType::ControlMessage, content: format!("{}:||DONE||", task.id)}; - task.tx.send(done_message).await.unwrap(); - } - for entry_res in walkdir::WalkDir::new(path){ - if entry_res.is_ok(){ - let entry = entry_res.unwrap(); - let file_path = entry.into_path(); - let mut file_name = String::new(); - let mut file_content = String::new(); - if file_path.file_name().is_some(){ - file_name = file_path.file_name().unwrap().to_string_lossy().to_string(); - } - for extension in &files_to_read{ - if file_name.contains(extension){ - let file_content_res = read_to_string(&file_path); - if file_content_res.is_ok(){ - file_content = file_content_res.unwrap(); - } - } - } - for thing in &interesting_info{ - if file_name.contains(thing) || file_content.contains(thing){ - let message = Message{source: MessageType::InfoMessage, destination: MessageType::ControlMessage, content: format!("{}:Keyword match at {}", task.id, file_path.display())}; - task.tx.send(message).await.unwrap(); - } - else{ - let message = Message{source: MessageType::InfoMessage, destination: MessageType::ControlMessage, content: format!("{}:file found at {}", task.id, file_path.display())}; - task.tx.send(message).await.unwrap(); - } - } - } - } - } - } -} - - - -#[tokio::main] -async fn main(){ - let args = Args::parse(); - let mut outfile = PathBuf::new(); - let mut file_threads = 1; - let mut share_threads = 1; - let mut save = false; - let mut computers = Vec::new(); - if args.outfile.is_some(){ - outfile = args.outfile.unwrap(); - save = true; - } - if args.threads.is_some(){ - let threads = args.threads.unwrap() / 2; - file_threads = threads; - share_threads = threads; - } - if args.targets.is_some(){ - println!("gathering the targets you gave me."); - let targets = args.targets.unwrap(); - if targets.contains(","){ - let split_targets: Vec<&str> = targets.split(",").collect(); - for target in split_targets{ - computers.push(target.to_string()); - } - } - else{ - computers.push(targets); - } - } - else{ - println!("no targets given, proceeding with domain computer enumeration..."); - println!("finding computers..."); - let command_string = String::from("net group \"domain computers\" /domain"); - let mut temp_file = fs::File::create("./temp.bat").unwrap(); - write!(temp_file, "{}", command_string).unwrap(); - let computer_res = Command::new(".\\temp.bat").output(); - let mut error_string = String::new(); - let mut success_string = String::new(); - fs::remove_file("./temp.bat").unwrap(); - if computer_res.is_ok(){ - let output = computer_res.unwrap(); - if output.stdout.len() > 0{ - success_string = String::from_utf8_lossy(&output.stdout).to_string(); - } - else if output.stderr.len() > 0{ - error_string = String::from_utf8_lossy(&output.stderr).to_string(); - } - } - else{ - error_string = computer_res.err().unwrap().to_string(); - } - if error_string.len() > 0{ - eprintln!("{}", "error getting computers!".red()); - eprintln!("{}", error_string.red()); - exit(1); - } - if success_string.len() > 0{ - for line in success_string.lines(){ - if line.contains("$"){ - let words:Vec<&str> = line.split_whitespace().collect(); - for word in words{ - let mut computer_name = word.to_string(); - computer_name.pop(); - println!("{} {}", "found".green(), computer_name.green()); - computers.push(computer_name); - } - } - } - } - } - if share_threads > computers.len(){ - share_threads = computers.len(); - //file_threads = computers.len(); - } - let mut share_handles = Vec::new(); - let mut file_handles = Vec::new(); - println!("computer enumeration finished, starting task finder threads..."); - let (maintx, mut mainrx) = channel(1024); - let mut share_tasks = Vec::new(); - let mut share_txes = Vec::new(); - let mut file_tasks = Vec::new(); - let mut file_txes = Vec::new(); - for id in 0..share_threads{ - println!("starting share task {}...", id); - let (share_tx,share_rx) = channel(1); - let new_share_task = ShareFinder{id, tx: maintx.clone()}; - share_handles.push(tokio::spawn(find_shares(new_share_task, share_rx))); - share_tasks.push(id); - share_txes.push(share_tx.clone()); - let ping_message = Message{source: MessageType::ControlMessage, destination: MessageType::ShareMessage, content: String::from("ping!")}; - share_tx.send(ping_message).await.unwrap(); - loop{ - let rx_recv = mainrx.recv().await; - if rx_recv.is_some(){ - let message = rx_recv.unwrap(); - if message.content == String::from("pong!"){ - println!("{} ready!", id); - break; - } - } - println!("didn't recieve file pong from {}", id); - } - } - for id in 0..file_threads{ - println!("starting file task {}...", id); - let (file_tx, file_rx) = channel(1); - let new_file_task = ShareFinder{id, tx: maintx.clone()}; - file_handles.push(tokio::spawn(find_info(new_file_task, file_rx))); - file_tasks.push(id); - file_txes.push(file_tx.clone()); - let ping_message = Message{source: MessageType::ControlMessage, destination: MessageType::ShareMessage, content: String::from("ping!")}; - file_tx.send(ping_message).await.unwrap(); - loop{ - let rx_recv = mainrx.recv().await; - if rx_recv.is_some(){ - let message = rx_recv.unwrap(); - if message.content == String::from("pong!"){ - println!("{} ready!", id); - break; - } - } - println!("didn't recieve file pong from {}", id); - } - } - let mut current_computer = 0; - let mut shares_finished = false; - let mut files_finished = false; - let mut file_buffer = Vec::new(); - let mut finished_counter = 0; - let mut empty_counter = 0; - let mut handled_lines = Vec::new(); - loop { - if files_finished && shares_finished{ - exit(0); - } - if !mainrx.is_empty(){ - finished_counter = 0; - empty_counter = 0; - let rx_res = mainrx.recv().await; - if rx_res.is_some(){ - let message = rx_res.unwrap(); - match message.destination{ - MessageType::ControlMessage => { - let message_vec: Vec<&str> = message.content.split(":").collect(); - let _id = message_vec[0]; - let message_content = message_vec[1].to_string(); - match message_content{ - _ => { - if !handled_lines.contains(&message_content){ - if save{ - let open_res = OpenOptions::new().append(true).create(true).open(&outfile); - if open_res.is_ok(){ - let mut file = open_res.unwrap(); - let write_res = write!(file, "{}\n", message_content); - if write_res.is_err(){ - eprintln!("{}", "error writing to outfile!".red()); - eprintln!("{}", write_res.err().unwrap().to_string().red()); - } - } - } - println!("{}", message_content.green()); - handled_lines.push(message_content); - } - - } - } - } - MessageType::InfoMessage => { - file_buffer.push(message.content); - } - MessageType::ShareMessage => {} - } - } - } - let mut sent = false; - if !shares_finished{ - for tx in &share_txes{ - if tx.capacity() > 0{ - let message = Message{source: MessageType::ShareMessage, destination: MessageType::ShareMessage, content: computers[current_computer].clone()}; - tx.send(message).await.unwrap(); - sent = true; - break; - } - } - if sent{ - current_computer +=1; - if current_computer == computers.len() { - shares_finished = true; - } - } - } - if shares_finished{ - if file_buffer.len() == 0{ - empty_counter += 1; - println!("empty counter: {}", empty_counter); - } - if empty_counter >= 100{ - finished_counter +=1; - println!("finished counter: {}", finished_counter); - thread::sleep(Duration::from_millis(50)); - } - } - if file_buffer.len() > 0{ - let mut sent_index = Vec::new(); - empty_counter = 0; - finished_counter = 0; - let mut current_tx = 0; - for index in 0 .. file_buffer.len() - 1{ - let mut sent = false; - let message = Message{source: MessageType::ControlMessage, destination: MessageType::InfoMessage, content: file_buffer[index].clone()}; - if file_txes[current_tx].capacity()> 0{ - file_txes[current_tx].send(message).await.unwrap(); - sent = true; - } - else{ - current_tx += 1; - if current_tx == file_txes.len(){ - current_tx = 0; - } - } - if sent{ - sent_index.push(index); - } - } - for index in sent_index{ - file_buffer.remove(index); - } - } - if finished_counter == 10{ - files_finished = true; - } - } -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 7a30fcd..ddd023c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,121 +1,172 @@ use clap::Parser; +use colored::Colorize; +use crossbeam::queue::SegQueue; use std::fmt::Debug; use std::fs; +use std::fs::File; use std::fs::read_to_string; -use std::fs::OpenOptions; use std::io::Write; +use std::io::stdin; use std::path::PathBuf; -use std::process::exit; use std::process::Command; -use colored::Colorize; -use tokio; -use tokio::sync::mpsc::{channel, Sender}; - +use std::process::exit; +use std::sync::Arc; +use std::sync::Mutex; +use std::time::Duration; +use std::time::Instant; /* -Author: Kevin (Bu4$t_Py40) Gunter +Author: Kevin (Kaged Pyro) Gunter Purpose: I got tired of snaffler getting caught, so I rewrote it in rust, which edrs have trouble detecting. + */ -#[derive(Parser, Debug)] +/*#[derive(Parser, Debug)] #[command(version, about, long_about = Some("finds shares, but its written in rust which sometimes gets past EDR!"))] struct Args{ #[arg(short, long, help = "path to save output file Defaults to not saving output.")] outfile: Option, + #[arg(short, long, help = "number of threads to use, default to 10. \\nNote thre thread count will be doubled, one set for share finder tasks, and one set for file and infor finding tasks.")] + threads: Option, + + #[arg(short, long, help = "specific targets. should be comma separated.")] + targets: Option, +}*/ + +#[derive(Parser, Debug)] +#[command(version, about, long_about = Some("finds shares, but its written in rust which sometimes gets past EDR!"))] +struct Args { + #[arg( + short, + long, + help = "path to save output file Defaults to not saving output." + )] + outfile: Option, + #[arg(long, help = "number of threads to use, default to 10.")] threads: Option, #[arg(short, long, help = "specific targets. should be comma separated.")] targets: Option, - #[arg(short, long, help = "specific targets that should be ignored. comma separated.")] + #[arg( + long, + help = "specific targets that should be ignored. comma separated." + )] filter_targets: Option, - #[arg(short, long, help = "echo all found files to the console, regardless of keyword matching. (all files will still be saved to the log file)")] + #[arg( + long, + help = "specific folder paths that should be ignored. comma separated." + )] + filter_data: Option, + + #[arg( + short, + long, + help = "echo all found files to the console, regardless of keyword matching. (all files will still be saved to the log file)" + )] verbose: bool, - #[arg(short, long, help = "scan only the current host's files")] + #[arg(short, long, help = "scan the current host's files")] local: bool, #[arg(short, long, help = "disable network discovery")] - diable_network: bool + diable_network: bool, +} + +struct AppState { + share_que: Arc>, + file_que: Arc>, + info_que: Arc>, + outfile: Option>>, + continue_without_saveing: bool, } #[derive(Clone)] -struct FinderTask{ - id: usize, +struct FinderTask { target: String, tasktype: TaskType, + findings: Vec, + outfile: Option>>, + verbose: bool, + filter: Vec, } -#[derive(Clone)] -struct Finding{ - path: String, - keyword: Option -} - -struct Message{ - source: usize, - tasktype: TaskType, - finding: Option, - task_finished: bool, -} - -#[derive(Clone)] -enum TaskType{ - Share, - File, - Info, -} - - -async fn task_handler(id: usize, current_task: FinderTask, tx: Sender){ - match current_task.tasktype{ - TaskType::Share => { - println!("scanning {}", current_task.target); - let share_list_res = Command::new("net").arg("view").arg(current_task.target.clone()).arg("/all").output(); - let mut success_string = String::new(); - if share_list_res.is_ok(){ - let output = share_list_res.unwrap(); - if output.stdout.len() > 0{ - success_string = String::from_utf8_lossy(&output.stdout).to_string(); +impl FinderTask { + fn run(&mut self) { + match self.tasktype { + TaskType::Share => { + println!("scanning {}", self.target); + let share_list_res = Command::new("net") + .arg("view") + .arg(self.target.clone()) + .arg("/all") + .output(); + let mut success_string = String::new(); + if share_list_res.is_ok() { + let output = share_list_res.unwrap(); + if output.stdout.len() > 0 { + success_string = String::from_utf8_lossy(&output.stdout).to_string(); + } + } + if success_string.len() > 0 { + let mut sent_lines = Vec::new(); + for line in success_string.lines() { + if line.contains("Disk") { + let share_name = line.split_whitespace().collect::>()[0]; + let share_path = format!("\\\\{}\\{}", self.target, share_name); + if !sent_lines.contains(&share_path) { + sent_lines.push(share_path.clone()); + let finding = Finding { path: share_path }; + println!("share found: {}", finding.path); + if let Some(outfile) = self.outfile.clone() { + if let Ok(mut file_lock) = outfile.lock() { + if let Err(e) = file_lock.write( + format!("share found: {}\r\n", finding.path).as_bytes(), + ) { + eprintln!("Error writing outfile! {e}"); + } + } + } + self.findings.push(finding); + } + } + } } } - if success_string.len() > 0{ + TaskType::File => { let mut sent_lines = Vec::new(); - for line in success_string.lines(){ - if line.contains("Disk"){ - let share_name = line.split_whitespace().collect::>()[0]; - let share_path = format!("\\\\{}\\{}", current_task.target, share_name); - if !sent_lines.contains(&share_path){ - sent_lines.push(share_path.clone()); - let finding = Finding{path: share_path, keyword: None}; - let message = Message{source: id, tasktype: TaskType::Share, finding: Some(finding), task_finished: false}; - tx.send(message).await.unwrap(); + for entry_res in walkdir::WalkDir::new(self.target.clone()) { + if entry_res.is_ok() { + let entry = entry_res.unwrap(); + let file_path = entry.into_path(); + if file_path.file_name().is_some() { + let file_path_string = file_path.display().to_string(); + if !sent_lines.contains(&file_path_string) { + sent_lines.push(file_path_string.clone()); + let finding = Finding { + path: file_path_string, + }; + if self.verbose { + println!("file found: {}", finding.path); + } + if let Some(outfile) = self.outfile.clone() { + if let Ok(mut lock) = outfile.lock() { + if let Err(e) = lock.write( + format!("file found: {}\r\n", finding.path).as_bytes(), + ) { + println!("error writing log file! {e}"); + } + } + } + self.findings.push(finding); + } } } } } - } - TaskType::File => { - let mut sent_lines = Vec::new(); - for entry_res in walkdir::WalkDir::new(current_task.target.clone()){ - if entry_res.is_ok(){ - let entry = entry_res.unwrap(); - let file_path = entry.into_path(); - if file_path.file_name().is_some(){ - let file_path_string = file_path.display().to_string(); - if !sent_lines.contains(&file_path_string){ - sent_lines.push(file_path_string.clone()); - let finding = Finding{path: file_path_string, keyword: None}; - let message = Message{source: id, tasktype: TaskType::File, finding: Some(finding), task_finished: false}; - tx.send(message).await.unwrap(); - } - } - } - } - } - TaskType::Info => { + TaskType::Info => { let files_to_read = vec![ ".txt", ".ini", @@ -128,198 +179,181 @@ async fn task_handler(id: usize, current_task: FinderTask, tx: Sender){ ".sql", ".ps1", ".py", - ".vbscript" + ".vbscript", ]; - let interesting_info = vec![ - "password", - "pass", - "user", - "api", - "key", - "credit card", - "cc", - "ssn", - "social Security", - "tax", - "i9", - "it", - "identified", - "username", - "admin", - "administrator", - ]; - let mut file_content = String::new(); - for extension in &files_to_read{ - if current_task.target.contains(extension){ - let file_content_res = read_to_string(¤t_task.target); - if file_content_res.is_ok(){ - file_content = file_content_res.unwrap(); - } - } - } - let mut sent_lines = Vec::new(); - for thing in &interesting_info{ - let file_name = current_task.target.clone(); - if file_name.contains(thing) || file_content.contains(thing){ - let sent_line = format!("keyword {}", file_name); - if !sent_lines.contains(&sent_line){ - sent_lines.push(sent_line); - let finding = Finding{path: file_name, keyword: Some(true)}; - let message = Message{source: id, tasktype: TaskType::Info, finding: Some(finding), task_finished: false}; - tx.send(message).await.unwrap(); - } - } - else{ - let sent_line = format!("file {}", file_name); - if !sent_lines.contains(&sent_line){ - sent_lines.push(sent_line); - let finding = Finding{path: file_name, keyword: Some(false)}; - let message = Message{source:id, tasktype: TaskType::Info, finding: Some(finding),task_finished: false}; - tx.send(message).await.unwrap(); + let interesting_info = vec![ + "password", + "pass", + "user", + "api", + "key", + "credit card", + "cc", + "ssn", + "social Security", + "tax", + "i9", + "it", + "identified", + "username", + "admin", + "administrator", + ]; + if files_to_read.iter().any(|e| self.target.contains(e)) { + if let Ok(file_content) = read_to_string(&self.target) { + if interesting_info.iter().any(|i| self.target.contains(i)) + || interesting_info.iter().any(|i| file_content.contains(i)) + { + if !self.filter.iter().any(|f| self.target.contains(f)) { + println!("keyword match: {}", self.target); + self.findings.push(Finding { + path: self.target.clone(), + }); + if let Some(outfile) = self.outfile.clone() { + if let Ok(mut file_lock) = outfile.lock() { + if let Err(e) = file_lock.write( + format!("keyword match: {}\r\n", self.target.clone()) + .as_bytes(), + ) { + println!("error writing log file, {e}"); + } + } + } + } + } } } } } } - let message = Message{source: id, tasktype: TaskType::Share, finding: None, task_finished: true}; - let send_res = tx.send(message).await; - if send_res.is_ok(){ - send_res.unwrap(); - } - else{ - println!("{}", send_res.err().unwrap()); - } } -#[tokio::main] -async fn main(){ -print!{ +#[derive(Clone)] +struct Finding { + path: String, +} + +#[derive(Clone)] +enum TaskType { + Share, + File, + Info, +} + +fn main() { + print! { " - ██▒▒ - ▒▒████ ▓▓████████▓▓ - ▒▒██████████ ██████████████ - ██████████████ ▒▒██████████████ - ████████████████ ████████████████ - ████████████████▓▓ ▓▓████████████████ - ██████████████████▓▓██████████████████████ - ██████████████████████████████████████████ ▓▓██ - ██████████████████████████████████████████ ▒▒████████ - ▒▒████ ██████████████████████████████████████████████ ██████████████ - ████████▓▓ ▒▒██████████████████████████████████████████████████████████████████ - ████████████████▓▓████████████████████████████████████████████████████████████████████████ - ██████████████████████████████████████████████████████████████████████████████████████████▓▓ - ████████████████████████████████████████▓▓ ▓▓██████████████████████████████████ - ██████████████████████████████████▓▓ ████████████████████████████▒▒ - ██████████████████████████████ ████████████████████████ - ████████████████████████▓▓ ▓▓██████████████████ - ▒▒████████████████████▒▒ ████████████████ - ▒▒████████████████▒▒ /----------------------------------\\ ██████████████ - ██████████████▓▓ / \\ ████████████▓▓ - ██████████████ / \\ ▓▓████████████████████▓▓▓▓ - ▓▓████████████░░ / \\ ████████████████████████ + ██▒▒ + ▒▒████ ▓▓████████▓▓ + ▒▒██████████ ██████████████ + ██████████████ ▒▒██████████████ + ████████████████ ████████████████ + ████████████████▓▓ ▓▓████████████████ + ██████████████████▓▓██████████████████████ + ██████████████████████████████████████████ ▓▓██ + ██████████████████████████████████████████ ▒▒████████ + ▒▒████ ██████████████████████████████████████████████ ██████████████ + ████████▓▓ ▒▒██████████████████████████████████████████████████████████████████ + ████████████████▓▓████████████████████████████████████████████████████████████████████████ + ██████████████████████████████████████████████████████████████████████████████████████████▓▓ + ████████████████████████████████████████▓▓ ▓▓██████████████████████████████████ + ██████████████████████████████████▓▓ ████████████████████████████▒▒ + ██████████████████████████████ ████████████████████████ + ████████████████████████▓▓ ▓▓██████████████████ + ▒▒████████████████████▒▒ ████████████████ + ▒▒████████████████▒▒ /----------------------------------\\ ██████████████ + ██████████████▓▓ / \\ ████████████▓▓ + ██████████████ / \\ ▓▓████████████████████▓▓▓▓ + ▓▓████████████░░ / \\ ████████████████████████ ░░██████████████ / |-| |-| \\ ▓▓██████████████████████▓▓ ████████████████████████░░ / | | | | \\ ████████████████████████ ▓▓██████████████████████████ / | | | | \\ ████████████████████████ ██████████████████████████▒▒ / | | | | \\ ▒▒██████████████████████ ██████████████████████████ / | | | | \\ ██████████████████████ ░░██████████████████████████ / | | | | \\ ████████████████████▓▓ -▒▒██████████████████████████ / | | | | \\ ████████████████▓▓ -▓▓██████████████████████████ \\ | | | | / ██████████████ - ▓▓██████████████████████ \\ | | | | / ████████████ - ▓▓████████████████ \\ | | | | / ████████████ - ▓▓████████████ \\ | | | | / ████████████ - ████████████ \\ | | | | / ████████████ - ████████████▒▒ \\ | | | | / ██████████████▒▒ - ██████████████ \\ |-| |-| / ▓▓████████████████▓▓ - ██████████████ \\ / ██████████████████████ +▒▒██████████████████████████ / | | | | \\ ████████████████▓▓ +▓▓██████████████████████████ \\ | | | | / ██████████████ + ▓▓██████████████████████ \\ | | | | / ████████████ + ▓▓████████████████ \\ | | | | / ████████████ + ▓▓████████████ \\ | | | | / ████████████ + ████████████ \\ | | | | / ████████████ + ████████████▒▒ \\ | | | | / ██████████████▒▒ + ██████████████ \\ |-| |-| / ▓▓████████████████▓▓ + ██████████████ \\ / ██████████████████████ ▒▒██████████████████ \\ / ▒▒████████████████████████ - ██████████████████████ \\ / ████████████████████████ - ██████████████████████████ \\----------------------------------/ ▓▓████████████████████████ - ██████████████████████████████ ░░████████████████████████▓▓ - ██████████████████████████████▒▒ ██████████████████████████ - ░░██████████████████████████████░░ ██████████████░░ ▒▒██████ - ████████████████████████████████ ████████████████ - ▒▒████████████████████████████████░░ ▒▒████████████████ - ██████▓▓▒▒ ██████████████████ ████████████████████ - ████████████████████▒▒ ▒▒████████████████████████ - ██████████████████████████▓▓▓▓▓▓████████████████████████████████▒▒ - ██████████████████████████████████████████████████████████████████ - ██████████████████████████████████████████████████████████████████ - ▓▓████████████████████████████████████████████████████████████████████ - ██████████████████████████████████████████████ ░░██████████████████ - ░░████████████████▒▒ ▒▒██████████████████ ████████████▒▒ - ▒▒██████████████ ████████████████ ██████ - ▓▓████████ ▓▓██████████████ ▒▒ - ▒▒████▒▒ ██████████████ - ██████████████ - ██████████████ + ██████████████████████ \\ / ████████████████████████ + ██████████████████████████ \\----------------------------------/ ▓▓████████████████████████ + ██████████████████████████████ ░░████████████████████████▓▓ + ██████████████████████████████▒▒ ██████████████████████████ + ░░██████████████████████████████░░ ██████████████░░ ▒▒██████ + ████████████████████████████████ ████████████████ + ▒▒████████████████████████████████░░ ▒▒████████████████ + ██████▓▓▒▒ ██████████████████ ████████████████████ + ████████████████████▒▒ ▒▒████████████████████████ + ██████████████████████████▓▓▓▓▓▓████████████████████████████████▒▒ + ██████████████████████████████████████████████████████████████████ + ██████████████████████████████████████████████████████████████████ + ▓▓████████████████████████████████████████████████████████████████████ + ██████████████████████████████████████████████ ░░██████████████████ + ░░████████████████▒▒ ▒▒██████████████████ ████████████▒▒ + ▒▒██████████████ ████████████████ ██████ + ▓▓████████ ▓▓██████████████ ▒▒ + ▒▒████▒▒ ██████████████ + ██████████████ + ██████████████ - __ __ - / _\\_ __ __ _ / _| ___ _ __ _ __ ___ _ _ ___ + __ __ + / _\\_ __ __ _ / _| ___ _ __ _ __ ___ _ _ ___ \\ \\| '_ \\ / _` | |_ / _ \\ '__| '__/ _ \\| | | / __| _\\ \\ | | | (_| | _| __/ | | | | (_) | |_| \\__ \\ \\__/_| |_|\\__,_|_| \\___|_| |_| \\___/ \\__,_|___/ " -} + } let args = Args::parse(); - let mut outfile = PathBuf::new(); - let mut threads = 10; - let mut save = false; let mut computers = Vec::new(); let mut filter_computers = Vec::new(); let mut network = true; - let file_filter = vec![ - String::from("ADMIN$") - ]; - if args.outfile.is_some(){ - outfile = args.outfile.unwrap(); - save = true; - } - if args.threads.is_some(){ - threads = args.threads.unwrap(); - } - if args.diable_network{ + if args.diable_network { network = false; } - if args.targets.is_some(){ + if args.targets.is_some() { println!("gathering the targets you gave me."); let targets = args.targets.unwrap(); - if targets.contains(","){ + if targets.contains(",") { let split_targets: Vec<&str> = targets.split(",").collect(); - for target in split_targets{ + for target in split_targets { computers.push(target.trim().to_lowercase()); } - } - else{ + } else { computers.push(targets); } + } else { + println!("no targets specified, proceeding with computer enumeration..."); } - if args.filter_targets.is_some(){ + if args.filter_targets.is_some() { println!("gathering the filter you specified!"); let given_filter = args.filter_targets.unwrap(); let filters: Vec<&str> = given_filter.split(",").collect(); - for filter in filters{ + for filter in filters { filter_computers.push(filter.trim().to_lowercase()); } } let hostname_res = Command::new("hostname").output(); - if hostname_res.is_ok(){ + if hostname_res.is_ok() { let hostname_output = hostname_res.unwrap(); - if hostname_output.stdout.len() > 0{ + if hostname_output.stdout.len() > 0 { let hostname_string = String::from_utf8_lossy(&hostname_output.stdout).to_string(); - if args.local{ + if args.local { computers.push(hostname_string.trim().to_lowercase()); - } - else{ + } else { filter_computers.push(hostname_string.trim().to_lowercase()); } } - if network{ - println!("no targets given, proceeding with domain computer enumeration..."); + if network { println!("finding computers..."); let command_string = String::from("net group \"domain computers\" /domain"); let mut temp_file = fs::File::create("./temp.bat").unwrap(); @@ -328,28 +362,26 @@ print!{ let mut error_string = String::new(); let mut success_string = String::new(); fs::remove_file("./temp.bat").unwrap(); - if computer_res.is_ok(){ + if computer_res.is_ok() { let output = computer_res.unwrap(); - if output.stdout.len() > 0{ + if output.stdout.len() > 0 { success_string = String::from_utf8_lossy(&output.stdout).to_string(); - } - else if output.stderr.len() > 0{ + } else if output.stderr.len() > 0 { error_string = String::from_utf8_lossy(&output.stderr).to_string(); } - } - else{ + } else { error_string = computer_res.err().unwrap().to_string(); } - if error_string.len() > 0{ + if error_string.len() > 0 { eprintln!("{}", "error getting computers!".red()); eprintln!("{}", error_string.red()); exit(1); } - if success_string.len() > 0{ - for line in success_string.lines(){ - if line.contains("$"){ - let words:Vec<&str> = line.split_whitespace().collect(); - for word in words{ + if success_string.len() > 0 { + for line in success_string.lines() { + if line.contains("$") { + let words: Vec<&str> = line.split_whitespace().collect(); + for word in words { let mut computer_name = word.to_string(); computer_name.pop(); computers.push(computer_name.trim().to_lowercase()); @@ -359,206 +391,241 @@ print!{ } } } - if filter_computers.len() > 0{ - computers.retain(|x| !filter_computers.iter().any(|y| y==x)); + if filter_computers.len() > 0 { + computers.retain(|x| !filter_computers.iter().any(|y| y == x)); } - let mut tasks = Vec::new(); - let mut id_counter = 0; - for computer in &computers{ + let mut state = AppState { + share_que: Arc::new(SegQueue::new()), + file_que: Arc::new(SegQueue::new()), + info_que: Arc::new(SegQueue::new()), + continue_without_saveing: false, + outfile: None, + }; + if let Some(outpath) = args.outfile { + if let Ok(outfile) = File::create(outpath) { + state.outfile = Some(Arc::new(Mutex::new(outfile))); + } else { + let mut continue_res = String::new(); + println!("error creating outfile!"); + println!("continue without saving? (Y/n"); + stdin().read_line(&mut continue_res).unwrap(); + if continue_res.to_lowercase().contains("y") { + state.continue_without_saveing = true; + } else { + exit(1); + } + } + } + let mut filter = vec![ + "C:\\Windows".to_string(), + "C$\\Windows".to_string(), + "C:\\Windows.old".to_string(), + "C$\\Windows.old".to_string(), + "ADMIN$\\".to_string(), + "ProgramData\\Microsoft".to_string(), + "\\AppData\\Local\\Microsoft\\Internet Explorer\\brndlog.txt".to_string(), + "desktop.ini".to_string(), + "AppData\\Local\\Packages\\Microsoft.Windows.Search".to_string(), + "AppData\\Local\\Microsoft\\Windows\\Shell\\DefaultLayouts.xml".to_string(), + "AppData\\Local\\Microsoft\\Internet Explorer\\IECompatData\\iecompatdata.xml".to_string(), + "Program Files\\WindowsPowerShell\\Modules\\Pester".to_string(), + "vk_swiftshader_icd.json".to_string(), + "AppxBlockMap.xml".to_string(), + "AppxManifest.xml".to_string(), + "MediaReceiverRegistrar.xml".to_string(), + "ContentDirectory.xml".to_string(), + "avtransport.xml".to_string(), + "ThirdPartyNotices.txt".to_string(), + "Program Files\\Common Files\\microsoft shared\\ink\\fsdefinitions".to_string(), + "Program Files\\Common Files\\microsoft shared\\ink\\Content.xml".to_string(), + "Program Files\\Common Files\\microsoft shared\\ink\\Alphabet.xml".to_string(), + "Diagnostics\\Simple\\Simple.Tests.ps1".to_string(), + "Microsoft.PowerShell.Operation.Validation.Format.ps1xml".to_string(), + "Test\\Microsoft.PowerShell.Operation.Validation.Tests.ps1".to_string(), + "PackageManagement.format.ps1xml".to_string(), + "PSGet.Format.ps1xml".to_string(), + "PSReadLine.format.ps1xml".to_string(), + "ResiliencyLinks\\WidevineCdm\\manifest.json.DATA".to_string(), + "Program Files (x86)\\Microsoft\\Edge\\Application".to_string(), + "Program Files (x86)\\Microsoft\\EdgeCore".to_string(), + "Program Files (x86)\\Microsoft.NET\\RedistList".to_string(), + "Program Files (x86)\\Microsoft.NET\\RedistList".to_string(), + "Program Files (x86)\\WindowsPowerShell\\Modules\\Microsoft.PowerShell.Operation.Validation".to_string(), + "Program Files (x86)\\WindowsPowerShell\\Modules\\PackageManagement".to_string(), + "Program Files (x86)\\WindowsPowerShell\\Modules\\PowerShellGet".to_string(), + "Program Files (x86)\\WindowsPowerShell\\Modules\\Pester".to_string(), + ]; + if let Some(user_filter) = args.filter_data { + user_filter.split(",").into_iter().for_each(|p| { + filter.push(p.to_string()); + }); + } + for computer in &computers { println!("found {}", computer); - let new_task = FinderTask{id: id_counter, target: computer.clone(), tasktype: TaskType::Share}; - tasks.push(new_task); - id_counter += 1; + let new_task = FinderTask { + target: computer.clone(), + tasktype: TaskType::Share, + findings: Vec::new(), + outfile: state.outfile.clone(), + verbose: args.verbose.clone(), + filter: filter.clone(), + }; + state.share_que.push(new_task); } - println!("computer enumeration finished, starting task finder threads..."); - let (tx, mut rx) = channel(1024); - let mut running = Vec::new(); - let mut continue_wihtout_save = false; - loop{ - if running.len() < threads{ - for _i in 0 .. threads{ - if tasks.len() > 0{ - let task = tasks[0].clone(); - tasks.remove(0); - running.push(task.id.clone()); - tokio::spawn(task_handler(task.id, task, tx.clone())); - if running.len() >= threads{ - break; - } - } - else{ - break; - } - } - } - if running.len() > 0{ - let rxres = rx.try_recv(); - if rxres.is_ok(){ - let mesage = rxres.unwrap(); - if mesage.task_finished{ - for index in 0 .. running.len(){ - if index == running.len(){ - break; - } - else{ - if running[index] == mesage.source{ - running.remove(index); - } - } - } - } - else { - let finding = mesage.finding.unwrap(); - match mesage.tasktype{ - TaskType::Share => { - println!("{} {}", "share found!".green(), finding.path); - if save{ - let open_res = OpenOptions::new().create(true).append(true).open(&outfile); - if open_res.is_err(){ - if !continue_wihtout_save{ - eprintln!("{}", "error opening save file!".red()); - eprintln!("{}", open_res.err().unwrap().to_string().red()); - let mut proceed = String::new(); - println!("continue anyway?"); - std::io::stdin().read_line(&mut proceed).unwrap(); - if proceed.to_lowercase().contains("y"){ - continue_wihtout_save = true; - } - else{ - exit(1); - } - } - } - else{ - let mut save_file = open_res.unwrap(); - let write_res = write!(save_file,"share found! {}\\n", finding.path); - if write_res.is_err(){ - if !continue_wihtout_save{ - eprintln!("{}", "error writing to save file!".red()); - eprintln!("{}", write_res.err().unwrap().to_string().red()); - let mut proceed = String::new(); - println!("proceed without saving?"); - std::io::stdin().read_line(&mut proceed).unwrap(); - if proceed.to_lowercase().contains("y"){ - continue_wihtout_save = true; - } - else{ - exit(1); - } - } - } - else{ - write_res.unwrap(); - } - } - } - if !file_filter.contains(&finding.path){ - let new_task = FinderTask{id: id_counter, tasktype: TaskType::File, target: finding.path}; - tasks.push(new_task); - id_counter += 1; - } - } - TaskType::File => { - let new_task = FinderTask{id: id_counter, tasktype: TaskType::Info, target: finding.path}; - tasks.push(new_task); - id_counter += 1; - } - TaskType::Info => { - if finding.keyword.unwrap(){ - println!("{} {}", "keyword match at".green(), finding.path.green()); - if save{ - let open_res = OpenOptions::new().create(true).append(true).open(&outfile); - if open_res.is_err(){ - if !continue_wihtout_save{ - eprintln!("{}", "error opening save file!".red()); - eprintln!("{}", open_res.err().unwrap().to_string().red()); - let mut proceed = String::new(); - println!("continue anyway?"); - std::io::stdin().read_line(&mut proceed).unwrap(); - if proceed.to_lowercase().contains("y"){ - continue_wihtout_save = true; - } - else{ - exit(1); - } - } - } - else{ - let mut save_file = open_res.unwrap(); - let write_res = write!(save_file,"keyword match at {}\\n", finding.path); - if write_res.is_err(){ - if !continue_wihtout_save{ - eprintln!("{}", "error writing to save file!".red()); - eprintln!("{}", write_res.err().unwrap().to_string().red()); - let mut proceed = String::new(); - println!("proceed without saving?"); - std::io::stdin().read_line(&mut proceed).unwrap(); - if proceed.to_lowercase().contains("y"){ - continue_wihtout_save = true; - } - else{ - exit(1); - } - } - } - else{ - write_res.unwrap(); - } - } - } - } - else{ - if args.verbose{ - println!("{} {}", "file found at".green(), finding.path.green()); - } - if save{ - let open_res = OpenOptions::new().create(true).append(true).open(&outfile); - if open_res.is_err(){ - if !continue_wihtout_save{ - eprintln!("{}", "error opening save file!".red()); - eprintln!("{}", open_res.err().unwrap().to_string().red()); - let mut proceed = String::new(); - println!("continue anyway?"); - std::io::stdin().read_line(&mut proceed).unwrap(); - if proceed.to_lowercase().contains("y"){ - continue_wihtout_save = true; - } - else{ - exit(1); - } - } - } - else{ - let mut save_file = open_res.unwrap(); - let write_res = write!(save_file,"file found! {}\\n", finding.path); - if write_res.is_err(){ - if !continue_wihtout_save{ - eprintln!("{}", "error writing to save file!".red()); - eprintln!("{}", write_res.err().unwrap().to_string().red()); - let mut proceed = String::new(); - println!("proceed without saving?"); - std::io::stdin().read_line(&mut proceed).unwrap(); - if proceed.to_lowercase().contains("y"){ - continue_wihtout_save = true; - } - else{ - exit(1); - } - } - } - else{ - write_res.unwrap(); - } - } - } - } - } - } - } - } - } - if running.len() == 0 && tasks.len() == 0 && rx.is_empty(){ + println!("Computers found!"); + let mut thread_count = rayon::current_num_threads(); + if let Some(count) = args.threads { + thread_count = count; + } + println!("starting finder ques..."); + let mut outputs = run_tasks( + state.share_que.clone(), + state.file_que.clone(), + state.info_que.clone(), + state.outfile.clone(), + thread_count, + args.verbose.clone(), + filter.clone(), + ); + let mut final_findings = Vec::new(); + loop { + if outputs.0.is_empty() + && outputs.1.is_empty() + && outputs.2.is_empty() + && outputs.3.is_empty() + { break; + } else { + final_findings.extend(outputs.3.clone()); + outputs = run_tasks( + outputs.0, + outputs.1, + outputs.2, + state.outfile.clone(), + thread_count, + args.verbose.clone(), + filter.clone(), + ); } } -} \ No newline at end of file + println!("file enumeration complete, happy hunting!"); +} + +fn run_tasks( + share_que: Arc>, + file_que: Arc>, + info_que: Arc>, + outfile: Option>>, + total_threads: usize, + verbose: bool, + filter: Vec, +) -> ( + Arc>, + Arc>, + Arc>, + Vec, +) { + let findings = Arc::new(Mutex::new(Vec::new())); + let ques = rayon::scope( + |scope| -> ( + Arc>, + Arc>, + Arc>, + ) { + for _ in 0..total_threads { + let findings_clone = findings.clone(); + let share_que = share_que.clone(); + let file_que = file_que.clone(); + let info_que = info_que.clone(); + let outfile = outfile.clone(); + let verbose = verbose.clone(); + let filter = filter.clone(); + let mut last_printed = Instant::now(); + scope.spawn(move |_| { + let mut local_findings = Vec::new(); + let mut work_remaining = true; + while work_remaining { + work_remaining = false; + if let Some(mut finder_task) = info_que.pop() { + work_remaining = true; + finder_task.run(); + local_findings.extend(finder_task.findings); + if Instant::now().duration_since(last_printed) + >= Duration::from_secs(30) + { + println!("{} share tasks remaining", share_que.len()); + println!("{} file tasks remaining", file_que.len()); + println!("{} info tasks remaining", info_que.len()); + println!("and we aint done yet!"); + last_printed = Instant::now(); + } + } else if let Some(mut finder_task) = file_que.pop() { + work_remaining = true; + finder_task.run(); + finder_task.findings.iter().for_each(|f| { + info_que.push(FinderTask { + target: f.path.clone(), + tasktype: TaskType::Info, + findings: Vec::new(), + outfile: outfile.clone(), + verbose, + filter: filter.clone(), + }); + }); + local_findings.extend(finder_task.findings); + if Instant::now().duration_since(last_printed) + >= Duration::from_secs(30) + { + println!("{} share tasks remaining", share_que.len()); + println!("{} file tasks remaining", file_que.len()); + println!("{} info tasks remaining", info_que.len()); + println!("and we aint done yet!"); + last_printed = Instant::now(); + } + } else if let Some(mut finder_task) = share_que.pop() { + work_remaining = true; + finder_task.run(); + finder_task.findings.iter().for_each(|f| { + file_que.push(FinderTask { + target: f.path.clone(), + tasktype: TaskType::File, + findings: Vec::new(), + outfile: outfile.clone(), + verbose, + filter: filter.clone(), + }); + }); + local_findings.extend(finder_task.findings); + if Instant::now().duration_since(last_printed) + >= Duration::from_secs(30) + { + println!("{} share tasks remaining", share_que.len()); + println!("{} file tasks remaining", file_que.len()); + println!("{} info tasks remaining", info_que.len()); + println!("and we aint done yet!"); + last_printed = Instant::now(); + } + } + if Instant::now().duration_since(last_printed) >= Duration::from_secs(30) { + println!("{} share tasks remaining", share_que.len()); + println!("{} file tasks remaining", file_que.len()); + println!("{} info tasks remaining", info_que.len()); + println!("and we aint done yet!"); + last_printed = Instant::now(); + } + } + *findings_clone.lock().unwrap() = local_findings; + }); + } + println!("{} share tasks remaining", share_que.len()); + println!("{} file tasks remaining", file_que.len()); + println!("{} info tasks remaining", info_que.len()); + return (share_que, file_que, info_que); + }, + ); + let mut new_findings = Vec::new(); + findings.lock().unwrap().iter().for_each(|f| { + new_findings.push(f.clone()); + }); + return (ques.0, ques.1, ques.2, new_findings); +}