13 Commits

Author SHA1 Message Date
pyro 0ef453427b changed the parsing logic to use proper iteraters intead of for loops,
and refined the filters and keywords a bit.
2026-07-17 17:14:37 -05:00
pyro 256d6e68bc re-wrote the tool to use rayon instead of tokio for multitheading, its
way faster now. Also worked on filtering out noise.
2026-07-17 13:27:51 -05:00
pyro57000 df9c8899b2 cleaned up the initial comments 2025-10-23 15:16:19 -05:00
pyro57000 ec23b722f1 added some basic filtering 2025-10-20 13:10:55 -05:00
pyro57000 c97e05008d added ascii art 2025-10-17 10:51:07 -05:00
pyro57000 e08d19c565 updated the cargo.toml to optimize the binary
also removed some debugging print statements to
clean up the output when running in a real
environment.
2025-10-17 09:40:10 -05:00
Pyro57000 f1e482529c Update README.md 2025-10-16 17:48:21 -05:00
pyro57000 0b1dd6759f fixed formatting more 2025-10-16 17:46:58 -05:00
pyro57000 ad65897eff fixed readme formatting 2025-10-16 17:46:39 -05:00
Pyro57000 2573d9aef9 Update README.md 2025-10-16 17:43:57 -05:00
pyro57000 095da32fb8 updated the readme some more 2025-10-16 17:43:09 -05:00
pyro57000 bcee32dc90 updated the readme! 2025-10-16 17:39:33 -05:00
pyro57000 1e29992068 re-wrote the tool, it actually works now! 2025-10-16 17:34:16 -05:00
4 changed files with 851 additions and 738 deletions
Generated
+123 -347
View File
@@ -2,26 +2,11 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.19" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-parse", "anstyle-parse",
@@ -34,83 +19,44 @@ dependencies = [
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.11" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]] [[package]]
name = "anstyle-parse" name = "anstyle-parse"
version = "0.2.7" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [ dependencies = [
"utf8parse", "utf8parse",
] ]
[[package]] [[package]]
name = "anstyle-query" name = "anstyle-query"
version = "1.1.3" version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys",
] ]
[[package]] [[package]]
name = "anstyle-wincon" name = "anstyle-wincon"
version = "3.0.9" version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"once_cell_polyfill", "once_cell_polyfill",
"windows-sys 0.59.0", "windows-sys",
] ]
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "backtrace"
version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-targets",
]
[[package]]
name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[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.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.41" version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@@ -118,9 +64,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.41" version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@@ -130,9 +76,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.41" version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@@ -142,30 +88,86 @@ dependencies = [
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.7.5" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.4" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]] [[package]]
name = "colored" name = "colored"
version = "3.0.0" version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys",
] ]
[[package]] [[package]]
name = "gimli" name = "crossbeam"
version = "0.31.1" version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 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]] [[package]]
name = "heck" name = "heck"
@@ -173,141 +175,55 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "io-uring"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
dependencies = [
"bitflags",
"cfg-if",
"libc",
]
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.1" version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "libc"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "lock_api"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
]
[[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",
]
[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell_polyfill" name = "once_cell_polyfill"
version = "1.70.1" version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "parking_lot"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.95" version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.40" version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "redox_syscall" name = "rayon"
version = "0.5.13" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [ dependencies = [
"bitflags", "either",
"rayon-core",
] ]
[[package]] [[package]]
name = "rustc-demangle" name = "rayon-core"
version = "0.1.25" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]] [[package]]
name = "same-file" name = "same-file"
@@ -318,53 +234,17 @@ dependencies = [
"winapi-util", "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.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]] [[package]]
name = "snaferrous" name = "snaferrous"
version = "0.1.0" version = "1.2.0"
dependencies = [ dependencies = [
"clap", "clap",
"colored", "colored",
"tokio", "crossbeam",
"rayon",
"walkdir", "walkdir",
] ]
[[package]]
name = "socket2"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@@ -373,51 +253,20 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.104" version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "tokio"
version = "1.46.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
dependencies = [
"backtrace",
"bytes",
"io-uring",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"slab",
"socket2",
"tokio-macros",
"windows-sys 0.52.0",
]
[[package]]
name = "tokio-macros"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.18" version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]] [[package]]
name = "utf8parse" name = "utf8parse"
@@ -435,99 +284,26 @@ dependencies = [
"winapi-util", "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]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.9" version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys",
] ]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [ dependencies = [
"windows-targets", "windows-link",
] ]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[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_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[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_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[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_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+10 -2
View File
@@ -1,10 +1,18 @@
[package] [package]
name = "snaferrous" name = "snaferrous"
version = "0.1.0" version = "1.2.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
clap = { version = "4.5.41", features = ["derive"] } clap = { version = "4.5.41", features = ["derive"] }
colored = "3.0.0" colored = "3.0.0"
tokio = { version = "1.46.1", features = ["full"] } crossbeam = "0.8.4"
rayon = "1.12.0"
walkdir = "2.5.0" walkdir = "2.5.0"
[profile.release]
opt-level ="z"
lto = true
strip = true
codegen-units = 1
panic = "abort"
+68
View File
@@ -1,2 +1,70 @@
# snaferrous # snaferrous
snafflerish but rusty! snafflerish but rusty!
Currently it just looks for some hardcoded keywords to determine if a file has sensitive infomation, but it works!
# USAGE:
snaferrous [OPTIONS]
Options:
-o, --outfile <OUTFILE> path to save output file Defaults to not saving output.
--threads <THREADS> number of threads to use, default to 10.
-t, --targets <TARGETS> specific targets. should be comma separated.
-f, --filter_targets <targets> specific targets that should be ingored. Comma separated.
-l, --local scan the current hot's file system (defaults to false)
-d --disable_network disable network file discovery
-v, --verbose echo all found files to the console, regardless of keyword matching. (all files will still be saved to the log file)
-h, --help Print help (see more with '--help')
-V, --version Print version
# Compiling:
`git clone https://github.com/Pyro57000/snaferrous.git`
`cd snafferous`
`cargo build --target x86_64-pc-windows-gnu --release`
then your .exe will be in the targets/x86_64-pc-windows-gnu/release folder!
# Tool Output.
By default the tool will only print the found shares and files with keyword matches to the console.
If you give it the -v flag then it will print all files it finds to the console.
By default it only gives output to the console, but if you give it an outfile with the -o flag it will save findings to that file.
If it can't open the output file or write to it for any reason it will ask you if you want to continue without saving anyway.
Findings will be structured like the following:
shares - share found! {path to the share}
keyword matchs - keyword match at {path to the file}
file - file found at {path to the file}
+549 -288
View File
@@ -1,118 +1,166 @@
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::io::Write;
use std::io::stdin;
use std::path::PathBuf;
use std::process::Command;
use std::process::exit;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use std::time::Instant;
/* /*
Author: Kevin (Kaged Pyro) 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. 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)] /*#[derive(Parser, Debug)]
#[command(version, about, long_about = Some("finds shares, but its written in rust which sometimes gets past EDR!"))] #[command(version, about, long_about = Some("finds shares, but its written in rust which sometimes gets past EDR!"))]
struct Args{ struct Args{
#[arg(short, long, help = "path to save output file Defaults to not saving output.")] #[arg(short, long, help = "path to save output file Defaults to not saving output.")]
outfile: Option<PathBuf>, outfile: Option<PathBuf>,
#[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.")] #[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<usize>, threads: Option<usize>,
#[arg(short, long, help = "specific targets. should be comma separated.")] #[arg(short, long, help = "specific targets. should be comma separated.")]
targets: Option<String>, targets: Option<String>,
}*/
#[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<PathBuf>,
#[arg(long, help = "number of threads to use, default to 10.")]
threads: Option<usize>,
#[arg(short, long, help = "specific targets. should be comma separated.")]
targets: Option<String>,
#[arg(
long,
help = "specific targets that should be ignored. comma separated."
)]
filter_targets: Option<String>,
#[arg(
long,
help = "specific folder paths or file names that should be ignored. comma separated."
)]
filter_data: Option<String>,
#[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 the current host's files")]
local: bool,
#[arg(short, long, help = "disable network discovery")]
disable_network: bool,
} }
struct ShareFinder{ struct AppState {
id: usize, share_que: Arc<SegQueue<FinderTask>>,
tx: Sender<Message>, file_que: Arc<SegQueue<FinderTask>>,
info_que: Arc<SegQueue<FinderTask>>,
outfile: Option<Arc<Mutex<File>>>,
continue_without_saveing: bool,
} }
#[derive(Clone)] #[derive(Clone)]
struct Message{ struct FinderTask {
source: MessageType, target: String,
destination: MessageType, tasktype: TaskType,
content: String, findings: Vec<Finding>,
outfile: Option<Arc<Mutex<File>>>,
verbose: bool,
filter: Vec<String>,
} }
#[derive(Clone, PartialEq)] impl FinderTask {
enum MessageType{ fn run(&mut self) {
ShareMessage, match self.tasktype {
InfoMessage, TaskType::Share => {
ControlMessage, println!("scanning {}", self.target);
} let share_list_res = Command::new("net")
.arg("view")
.arg(self.target.clone())
async fn find_shares(task: ShareFinder, mut rx: Receiver<Message>){ .arg("/all")
println!("{} share task started!", task.id); .output();
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(); let mut success_string = String::new();
if share_list_res.is_ok() { if share_list_res.is_ok() {
let output = share_list_res.unwrap(); let output = share_list_res.unwrap();
if output.stdout.len() > 0 { if output.stdout.len() > 0 {
success_string = String::from_utf8_lossy(&output.stdout).to_string(); 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();
} }
} if success_string.len() > 0 {
else{ let mut sent_lines = Vec::new();
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() { for line in success_string.lines() {
if line.contains("Disk") { if line.contains("Disk") {
let share_name = line.split_whitespace().collect::<Vec<&str>>()[0]; let share_name = line.split_whitespace().collect::<Vec<&str>>()[0];
let share_path = format!("\\\\{}\\{}", computer, share_name); let share_path = format!("\\\\{}\\{}", self.target, share_name);
let message = Message{source: MessageType::ShareMessage, destination: MessageType::InfoMessage, content: format!("{}:{}", task.id, share_path)}; if !sent_lines.contains(&share_path) {
task.tx.send(message).await.unwrap(); 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);
} }
} }
} }
} }
} }
TaskType::File => {
walkdir::WalkDir::new(self.target.clone())
.into_iter()
.for_each(|e| {
if let Ok(entry) = e {
if self
.filter
.iter()
.any(|f| !entry.path().to_string_lossy().contains(f))
{
let file_path = entry.into_path();
let new_finding = Finding {
path: file_path.display().to_string(),
};
if !self.findings.iter().any(|f| f.path == new_finding.path) {
if self.verbose {
println!("file found: {}", new_finding.path);
} }
self.findings.push(new_finding);
async fn find_info(task: ShareFinder, mut rx: Receiver<Message>){
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();
} }
}
}
});
}
TaskType::Info => {
if !self.filter.iter().any(|f| self.target.contains(f)) {
let files_to_read = vec![ let files_to_read = vec![
".txt", ".txt",
".ini", ".ini",
@@ -125,7 +173,7 @@ async fn find_info(task: ShareFinder, mut rx: Receiver<Message>){
".sql", ".sql",
".ps1", ".ps1",
".py", ".py",
".vbscript" ".vbscript",
]; ];
let interesting_info = vec![ let interesting_info = vec![
@@ -136,49 +184,87 @@ async fn find_info(task: ShareFinder, mut rx: Receiver<Message>){
"key", "key",
"credit card", "credit card",
" cc ", " cc ",
"_cc_",
"-cc-",
"ssn", "ssn",
" ssn ",
"_ssn_",
"-ssn-",
"social Security", "social Security",
"tax", "tax",
"i9", "i9",
" it ", " it ",
"_it_",
"-it-",
"identified", "identified",
"username", "username",
"admin",
"administrator",
]; ];
loop{ let file_path = PathBuf::from(self.target.clone());
let rx_res = rx.recv().await; if file_path.is_file() {
if rx_res.is_some(){ if file_path.exists() {
let message = rx_res.unwrap(); let mut read = false;
let message_vec: Vec<&str> = message.content.split(":").collect(); if let Some(filename) = file_path.file_name() {
let path = message_vec[1]; if files_to_read
if path.contains("||DONE||"){ .iter()
let done_message = Message{source: MessageType::InfoMessage, destination: MessageType::ControlMessage, content: format!("{}:||DONE||", task.id)}; .any(|r| filename.to_string_lossy().contains(r))
task.tx.send(done_message).await.unwrap(); {
} if let Ok(file_content) = read_to_string(&file_path) {
for entry_res in walkdir::WalkDir::new(path){ read = true;
if entry_res.is_ok(){ if interesting_info.iter().any(|i| {
let entry = entry_res.unwrap(); filename.to_string_lossy().contains(i)
let file_path = entry.into_path(); || file_content.contains(i)
let mut file_name = String::new(); }) && !self
let mut file_content = String::new(); .filter
if file_path.file_name().is_some(){ .iter()
file_name = file_path.file_name().unwrap().to_string_lossy().to_string(); .any(|f| file_path.to_string_lossy().contains(f))
} {
for extension in &files_to_read{ if !self.findings.iter().any(|f| f.path == self.target)
if file_name.contains(extension){ {
let file_content_res = read_to_string(&file_path); self.findings.push(Finding {
if file_content_res.is_ok(){ path: self.target.clone(),
file_content = file_content_res.unwrap(); });
println!("keyword match: {}", self.target);
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: {}\n",
self.target.clone()
)
.as_bytes(),
) {
println!("error writing to log {e}");
}
}
}
}
}
}
}
if !read {
if interesting_info
.iter()
.any(|i| filename.to_string_lossy().contains(i))
{
println!("keyword match: {}", self.target);
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: {}\n",
self.target.clone()
)
.as_bytes(),
) {
println!("error writing to log {e}");
}
}
} }
} }
} }
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();
} }
} }
} }
@@ -187,24 +273,96 @@ async fn find_info(task: ShareFinder, mut rx: Receiver<Message>){
} }
} }
#[derive(Clone)]
struct Finding {
path: String,
}
#[derive(Clone)]
enum TaskType {
Share,
File,
Info,
}
fn main() {
print! {
"
██▒▒
▒▒████ ▓▓████████▓▓
▒▒██████████ ██████████████
██████████████ ▒▒██████████████
████████████████ ████████████████
████████████████▓▓ ▓▓████████████████
██████████████████▓▓██████████████████████
██████████████████████████████████████████ ▓▓██
██████████████████████████████████████████ ▒▒████████
▒▒████ ██████████████████████████████████████████████ ██████████████
████████▓▓ ▒▒██████████████████████████████████████████████████████████████████
████████████████▓▓████████████████████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████████████████████████████████████▓▓
████████████████████████████████████████▓▓ ▓▓██████████████████████████████████
██████████████████████████████████▓▓ ████████████████████████████▒▒
██████████████████████████████ ████████████████████████
████████████████████████▓▓ ▓▓██████████████████
▒▒████████████████████▒▒ ████████████████
▒▒████████████████▒▒ /----------------------------------\\ ██████████████
██████████████▓▓ / \\ ████████████▓▓
██████████████ / \\ ▓▓████████████████████▓▓▓▓
▓▓████████████░░ / \\ ████████████████████████
░░██████████████ / |-| |-| \\ ▓▓██████████████████████▓▓
████████████████████████░░ / | | | | \\ ████████████████████████
▓▓██████████████████████████ / | | | | \\ ████████████████████████
██████████████████████████▒▒ / | | | | \\ ▒▒██████████████████████
██████████████████████████ / | | | | \\ ██████████████████████
░░██████████████████████████ / | | | | \\ ████████████████████▓▓
▒▒██████████████████████████ / | | | | \\ ████████████████▓▓
▓▓██████████████████████████ \\ | | | | / ██████████████
▓▓██████████████████████ \\ | | | | / ████████████
▓▓████████████████ \\ | | | | / ████████████
▓▓████████████ \\ | | | | / ████████████
████████████ \\ | | | | / ████████████
████████████▒▒ \\ | | | | / ██████████████▒▒
██████████████ \\ |-| |-| / ▓▓████████████████▓▓
██████████████ \\ / ██████████████████████
▒▒██████████████████ \\ / ▒▒████████████████████████
██████████████████████ \\ / ████████████████████████
██████████████████████████ \\----------------------------------/ ▓▓████████████████████████
██████████████████████████████ ░░████████████████████████▓▓
██████████████████████████████▒▒ ██████████████████████████
░░██████████████████████████████░░ ██████████████░░ ▒▒██████
████████████████████████████████ ████████████████
▒▒████████████████████████████████░░ ▒▒████████████████
██████▓▓▒▒ ██████████████████ ████████████████████
████████████████████▒▒ ▒▒████████████████████████
██████████████████████████▓▓▓▓▓▓████████████████████████████████▒▒
██████████████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████████████
▓▓████████████████████████████████████████████████████████████████████
██████████████████████████████████████████████ ░░██████████████████
░░████████████████▒▒ ▒▒██████████████████ ████████████▒▒
▒▒██████████████ ████████████████ ██████
▓▓████████ ▓▓██████████████ ▒▒
▒▒████▒▒ ██████████████
██████████████
██████████████
#[tokio::main]
async fn main(){ __ __
/ _\\_ __ __ _ / _| ___ _ __ _ __ ___ _ _ ___
\\ \\| '_ \\ / _` | |_ / _ \\ '__| '__/ _ \\| | | / __|
_\\ \\ | | | (_| | _| __/ | | | | (_) | |_| \\__ \\
\\__/_| |_|\\__,_|_| \\___|_| |_| \\___/ \\__,_|___/
"
}
let args = Args::parse(); let args = Args::parse();
let mut outfile = PathBuf::new();
let mut file_threads = 5;
let mut share_threads = 5;
let mut save = false;
let mut computers = Vec::new(); let mut computers = Vec::new();
if args.outfile.is_some(){ let mut filter_computers = Vec::new();
outfile = args.outfile.unwrap(); let mut network = true;
save = true; if args.disable_network {
} network = false;
if args.threads.is_some(){
let threads = args.threads.unwrap() / 2;
file_threads = threads;
share_threads = threads;
} }
if args.targets.is_some() { if args.targets.is_some() {
println!("gathering the targets you gave me."); println!("gathering the targets you gave me.");
@@ -212,20 +370,39 @@ async fn main(){
if targets.contains(",") { if targets.contains(",") {
let split_targets: Vec<&str> = targets.split(",").collect(); let split_targets: Vec<&str> = targets.split(",").collect();
for target in split_targets { for target in split_targets {
computers.push(target.to_string()); computers.push(target.trim().to_lowercase());
} }
} } else {
else{
computers.push(targets); computers.push(targets);
} }
} else {
println!("no targets specified, proceeding with computer enumeration...");
} }
else{ if args.filter_targets.is_some() {
println!("no targets given, proceeding with domain computer enumeration..."); 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 {
filter_computers.push(filter.trim().to_lowercase());
}
}
let hostname_res = Command::new("hostname").output();
if hostname_res.is_ok() {
let hostname_output = hostname_res.unwrap();
if hostname_output.stdout.len() > 0 {
let hostname_string = String::from_utf8_lossy(&hostname_output.stdout).to_string();
if args.local {
computers.push(hostname_string.trim().to_lowercase());
} else {
filter_computers.push(hostname_string.trim().to_lowercase());
}
}
if network {
println!("finding computers..."); println!("finding computers...");
let command_string = String::from("net group \"domain computers\" /domain"); let command_string = String::from("net group \"domain computers\" /domain");
let mut temp_file = fs::File::create("./temp.bat").unwrap(); let mut temp_file = fs::File::create("./temp.bat").unwrap();
write!(temp_file, "{}", command_string).unwrap(); write!(temp_file, "{}", command_string).unwrap();
let computer_res = Command::new(".\\temp.bat").output(); let computer_res = Command::new(".\\\\temp.bat").output();
let mut error_string = String::new(); let mut error_string = String::new();
let mut success_string = String::new(); let mut success_string = String::new();
fs::remove_file("./temp.bat").unwrap(); fs::remove_file("./temp.bat").unwrap();
@@ -233,12 +410,10 @@ async fn main(){
let output = computer_res.unwrap(); 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(); 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(); error_string = String::from_utf8_lossy(&output.stderr).to_string();
} }
} } else {
else{
error_string = computer_res.err().unwrap().to_string(); error_string = computer_res.err().unwrap().to_string();
} }
if error_string.len() > 0 { if error_string.len() > 0 {
@@ -253,177 +428,263 @@ async fn main(){
for word in words { for word in words {
let mut computer_name = word.to_string(); let mut computer_name = word.to_string();
computer_name.pop(); computer_name.pop();
println!("{} {}", "found".green(), computer_name.green()); computers.push(computer_name.trim().to_lowercase());
computers.push(computer_name);
} }
} }
} }
} }
} }
if share_threads > computers.len(){
share_threads = computers.len();
//file_threads = computers.len();
} }
let mut share_handles = Vec::new(); if filter_computers.len() > 0 {
let mut file_handles = Vec::new(); computers.retain(|x| !filter_computers.iter().any(|y| y == x));
println!("computer enumeration finished, starting task finder threads..."); }
let (maintx, mut mainrx) = channel(1024); let mut state = AppState {
let mut share_tasks = Vec::new(); share_que: Arc::new(SegQueue::new()),
let mut share_txes = Vec::new(); file_que: Arc::new(SegQueue::new()),
let mut file_tasks = Vec::new(); info_que: Arc::new(SegQueue::new()),
let mut file_txes = Vec::new(); continue_without_saveing: false,
for id in 0..share_threads{ outfile: None,
println!("starting share task {}...", id); };
let (share_tx,share_rx) = channel(1); if let Some(outpath) = args.outfile {
let new_share_task = ShareFinder{id, tx: maintx.clone()}; if let Ok(outfile) = File::create(outpath) {
share_handles.push(tokio::spawn(find_shares(new_share_task, share_rx))); state.outfile = Some(Arc::new(Mutex::new(outfile)));
share_tasks.push(id); } else {
share_txes.push(share_tx.clone()); let mut continue_res = String::new();
let ping_message = Message{source: MessageType::ControlMessage, destination: MessageType::ShareMessage, content: String::from("ping!")}; println!("error creating outfile!");
share_tx.send(ping_message).await.unwrap(); 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".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(),
"Program Files\\Internet Explorer".to_string(),
"Program Files\\Windows Defender".to_string(),
"Program Files\\WindowsApps".to_string(),
"Program Files\\WindowsPowerShell\\Modules\\PackageManagement".to_string(),
"Program Files (x86)\\Internet Explorer".to_string(),
"Program Files (x86)\\Microsoft".to_string(),
"ProgramData\\ntuser.pol".to_string(),
"ProgramData\\USOShared".to_string(),
"AppData\\Local\\ConnectedDevicesPlatform".to_string(),
"AppData\\Local\\Microsoft\\Internet Explorer".to_string(),
"ntuser.dat".to_string(),
"ntuser.ini".to_string(),
"Program Files (x86)\\Windows Defender".to_string(),
"AppData\\Local\\Microsoft\\Windows\\WinX".to_string(),
"AppData\\Local\\Microsoft_Corporation".to_string(),
"AppData\\Roaming\\Microsoft\\Internet Explorer".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 {
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!("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 { loop {
let rx_recv = mainrx.recv().await; if outputs.0.is_empty()
if rx_recv.is_some(){ && outputs.1.is_empty()
let message = rx_recv.unwrap(); && outputs.2.is_empty()
if message.content == String::from("pong!"){ && outputs.3.is_empty()
println!("{} ready!", id); {
break; 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(),
);
} }
} }
println!("didn't recieve file pong from {}", id); println!("file enumeration complete, happy hunting!");
}
}
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 started = true;
let mut handled_lines = Vec::new();
loop {
if files_finished && shares_finished{
break;
}
if !mainrx.is_empty(){
finished_counter = 0;
empty_counter = 0;
started = true;
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);
} }
fn run_tasks(
share_que: Arc<SegQueue<FinderTask>>,
file_que: Arc<SegQueue<FinderTask>>,
info_que: Arc<SegQueue<FinderTask>>,
outfile: Option<Arc<Mutex<File>>>,
total_threads: usize,
verbose: bool,
filter: Vec<String>,
) -> (
Arc<SegQueue<FinderTask>>,
Arc<SegQueue<FinderTask>>,
Arc<SegQueue<FinderTask>>,
Vec<Finding>,
) {
let findings = Arc::new(Mutex::new(Vec::new()));
let ques = rayon::scope(
|scope| -> (
Arc<SegQueue<FinderTask>>,
Arc<SegQueue<FinderTask>>,
Arc<SegQueue<FinderTask>>,
) {
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) {
MessageType::InfoMessage => { println!("{} share tasks remaining", share_que.len());
file_buffer.push(message.content); println!("{} file tasks remaining", file_que.len());
} println!("{} info tasks remaining", info_que.len());
MessageType::ShareMessage => {} println!("and we aint done yet!");
last_printed = Instant::now();
} }
} }
*findings_clone.lock().unwrap() = local_findings;
});
} }
let mut sent = false; println!("{} share tasks remaining", share_que.len());
if !shares_finished{ println!("{} file tasks remaining", file_que.len());
for tx in &share_txes{ println!("{} info tasks remaining", info_que.len());
if tx.capacity() > 0{ return (share_que, file_que, info_que);
let message = Message{source: MessageType::ShareMessage, destination: MessageType::ShareMessage, content: computers[current_computer].clone()}; },
tx.send(message).await.unwrap(); );
sent = true; let mut new_findings = Vec::new();
break; findings.lock().unwrap().iter().for_each(|f| {
} new_findings.push(f.clone());
} });
if sent{ return (ques.0, ques.1, ques.2, new_findings);
current_computer +=1;
if current_computer == computers.len() {
shares_finished = true;
}
}
}
if shares_finished{
if file_buffer.len() == 0{
empty_counter += 1;
}
if empty_counter >= 100{
finished_counter +=1;
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{
for tx in &file_txes{
let done_message = Message{source: MessageType::ControlMessage, destination: MessageType::InfoMessage, content: String::from("0:||DONE||")};
tx.send(done_message).await.unwrap();
}
files_finished = true;
}
}
} }