9 Commits
1.0 ... 1.2

Author SHA1 Message Date
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
5 changed files with 1037 additions and 452 deletions

311
Cargo.lock generated
View File

@@ -2,26 +2,11 @@
# It is not intended for manual editing.
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]]
name = "anstream"
version = "0.6.19"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -34,9 +19,9 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.11"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
@@ -49,50 +34,29 @@ dependencies = [
[[package]]
name = "anstyle-query"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.9"
version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.59.0",
]
[[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",
"windows-sys 0.60.2",
]
[[package]]
name = "bitflags"
version = "2.9.1"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
[[package]]
name = "bytes"
@@ -102,15 +66,15 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cfg-if"
version = "1.0.1"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "clap"
version = "4.5.41"
version = "4.5.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f"
dependencies = [
"clap_builder",
"clap_derive",
@@ -118,9 +82,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.41"
version = "4.5.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730"
dependencies = [
"anstream",
"anstyle",
@@ -130,9 +94,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.41"
version = "4.5.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
dependencies = [
"heck",
"proc-macro2",
@@ -142,9 +106,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.5"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]]
name = "colorchoice"
@@ -161,29 +125,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "is_terminal_polyfill"
version = "1.70.1"
@@ -192,35 +139,19 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "libc"
version = "0.2.174"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "lock_api"
version = "0.4.13"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
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"
@@ -232,15 +163,6 @@ dependencies = [
"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]]
name = "once_cell_polyfill"
version = "1.70.1"
@@ -249,9 +171,9 @@ checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "parking_lot"
version = "0.12.4"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -259,15 +181,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.11"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
"windows-link",
]
[[package]]
@@ -278,37 +200,31 @@ checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "proc-macro2"
version = "1.0.95"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.5.13"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]]
name = "rustc-demangle"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
[[package]]
name = "same-file"
version = "1.0.6"
@@ -326,19 +242,13 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "signal-hook-registry"
version = "1.4.5"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
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"
@@ -357,12 +267,12 @@ dependencies = [
[[package]]
name = "socket2"
version = "0.5.10"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -373,9 +283,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.104"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
@@ -384,29 +294,26 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.46.1"
version = "1.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
dependencies = [
"backtrace",
"bytes",
"io-uring",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"slab",
"socket2",
"tokio-macros",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
name = "tokio-macros"
version = "2.5.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [
"proc-macro2",
"quote",
@@ -415,9 +322,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.18"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
name = "utf8parse"
@@ -443,21 +350,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "winapi-util"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.61.2",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
@@ -465,7 +369,25 @@ version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
"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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
@@ -474,14 +396,31 @@ 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",
"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]]
@@ -490,44 +429,92 @@ 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"

View File

@@ -6,5 +6,12 @@ edition = "2024"
[dependencies]
clap = { version = "4.5.41", features = ["derive"] }
colored = "3.0.0"
tokio = { version = "1.46.1", features = ["full"] }
tokio = { version = "1.48.0", features = ["full"] }
walkdir = "2.5.0"
[profile.release]
opt-level ="z"
lto = true
strip = true
codegen-units = 1
panic = "abort"

View File

@@ -1,2 +1,64 @@
# snaferrous
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.
-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}

425
src/main-bkup.rs Normal file
View File

@@ -0,0 +1,425 @@
/*
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<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.")]
threads: Option<usize>,
#[arg(short, long, help = "specific targets. should be comma separated.")]
targets: Option<String>,
}
struct ShareFinder{
id: usize,
tx: Sender<Message>,
}
#[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<Message>){
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::<Vec<&str>>()[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<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();
}
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;
}
}
}

View File

@@ -1,23 +1,34 @@
/*
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;
use tokio;
use tokio::sync::mpsc::{channel, Sender};
/*
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)]
#[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(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>,
#[arg(short, long, help = "specific targets. should be comma separated.")]
targets: Option<String>,
}*/
#[derive(Parser, Debug)]
#[command(version, about, long_about = Some("finds shares, but its written in rust which sometimes gets past EDR!"))]
@@ -25,94 +36,91 @@ struct Args{
#[arg(short, long, help = "path to save output file Defaults to not saving output.")]
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(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>,
}
struct ShareFinder{
id: usize,
tx: Sender<Message>,
#[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,
}
#[derive(Clone)]
struct FinderTask{
id: usize,
target: String,
tasktype: TaskType,
}
#[derive(Clone)]
struct Finding{
path: String,
keyword: Option<bool>
}
struct Message{
source: MessageType,
destination: MessageType,
content: String,
source: usize,
tasktype: TaskType,
finding: Option<Finding>,
task_finished: bool,
}
#[derive(Clone, PartialEq)]
enum MessageType{
ShareMessage,
InfoMessage,
ControlMessage,
#[derive(Clone)]
enum TaskType{
Share,
File,
Info,
}
async fn find_shares(task: ShareFinder, mut rx: Receiver<Message>){
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();
async fn task_handler(id: usize, current_task: FinderTask, tx: Sender<Message>){
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();
}
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{
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::<Vec<&str>>()[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();
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();
}
}
}
}
}
}
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::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 => {
let files_to_read = vec![
".txt",
".ini",
@@ -144,57 +152,125 @@ async fn find_info(task: ShareFinder, mut rx: Receiver<Message>){
"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 current_task.target.contains(extension){
let file_content_res = read_to_string(&current_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 message = Message{source: MessageType::InfoMessage, destination: MessageType::ControlMessage, content: format!("{}:Keyword match at {}", task.id, file_path.display())};
task.tx.send(message).await.unwrap();
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 message = Message{source: MessageType::InfoMessage, destination: MessageType::ControlMessage, content: format!("{}:file found at {}", task.id, file_path.display())};
task.tx.send(message).await.unwrap();
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 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!{
"
██▒▒
▒▒████ ▓▓████████▓▓
▒▒██████████ ██████████████
██████████████ ▒▒██████████████
████████████████ ████████████████
████████████████▓▓ ▓▓████████████████
██████████████████▓▓██████████████████████
██████████████████████████████████████████ ▓▓██
██████████████████████████████████████████ ▒▒████████
▒▒████ ██████████████████████████████████████████████ ██████████████
████████▓▓ ▒▒██████████████████████████████████████████████████████████████████
████████████████▓▓████████████████████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████████████████████████████████████▓▓
████████████████████████████████████████▓▓ ▓▓██████████████████████████████████
██████████████████████████████████▓▓ ████████████████████████████▒▒
██████████████████████████████ ████████████████████████
████████████████████████▓▓ ▓▓██████████████████
▒▒████████████████████▒▒ ████████████████
▒▒████████████████▒▒ /----------------------------------\\ ██████████████
██████████████▓▓ / \\ ████████████▓▓
██████████████ / \\ ▓▓████████████████████▓▓▓▓
▓▓████████████░░ / \\ ████████████████████████
░░██████████████ / |-| |-| \\ ▓▓██████████████████████▓▓
████████████████████████░░ / | | | | \\ ████████████████████████
▓▓██████████████████████████ / | | | | \\ ████████████████████████
██████████████████████████▒▒ / | | | | \\ ▒▒██████████████████████
██████████████████████████ / | | | | \\ ██████████████████████
░░██████████████████████████ / | | | | \\ ████████████████████▓▓
▒▒██████████████████████████ / | | | | \\ ████████████████▓▓
▓▓██████████████████████████ \\ | | | | / ██████████████
▓▓██████████████████████ \\ | | | | / ████████████
▓▓████████████████ \\ | | | | / ████████████
▓▓████████████ \\ | | | | / ████████████
████████████ \\ | | | | / ████████████
████████████▒▒ \\ | | | | / ██████████████▒▒
██████████████ \\ |-| |-| / ▓▓████████████████▓▓
██████████████ \\ / ██████████████████████
▒▒██████████████████ \\ / ▒▒████████████████████████
██████████████████████ \\ / ████████████████████████
██████████████████████████ \\----------------------------------/ ▓▓████████████████████████
██████████████████████████████ ░░████████████████████████▓▓
██████████████████████████████▒▒ ██████████████████████████
░░██████████████████████████████░░ ██████████████░░ ▒▒██████
████████████████████████████████ ████████████████
▒▒████████████████████████████████░░ ▒▒████████████████
██████▓▓▒▒ ██████████████████ ████████████████████
████████████████████▒▒ ▒▒████████████████████████
██████████████████████████▓▓▓▓▓▓████████████████████████████████▒▒
██████████████████████████████████████████████████████████████████
██████████████████████████████████████████████████████████████████
▓▓████████████████████████████████████████████████████████████████████
██████████████████████████████████████████████ ░░██████████████████
░░████████████████▒▒ ▒▒██████████████████ ████████████▒▒
▒▒██████████████ ████████████████ ██████
▓▓████████ ▓▓██████████████ ▒▒
▒▒████▒▒ ██████████████
██████████████
██████████████
__ __
/ _\\_ __ __ _ / _| ___ _ __ _ __ ___ _ _ ___
\\ \\| '_ \\ / _` | |_ / _ \\ '__| '__/ _ \\| | | / __|
_\\ \\ | | | (_| | _| __/ | | | | (_) | |_| \\__ \\
\\__/_| |_|\\__,_|_| \\___|_| |_| \\___/ \\__,_|___/
"
}
let args = Args::parse();
let mut outfile = PathBuf::new();
let mut file_threads = 5;
let mut share_threads = 5;
let mut threads = 10;
let mut save = false;
let mut computers = Vec::new();
if args.outfile.is_some(){
@@ -202,9 +278,7 @@ async fn main(){
save = true;
}
if args.threads.is_some(){
let threads = args.threads.unwrap() / 2;
file_threads = threads;
share_threads = threads;
threads = args.threads.unwrap();
}
if args.targets.is_some(){
println!("gathering the targets you gave me.");
@@ -225,7 +299,7 @@ async fn main(){
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 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();
@@ -253,177 +327,207 @@ async fn main(){
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 tasks = Vec::new();
let mut id_counter = 0;
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 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();
let (tx, mut rx) = channel(1024);
let mut running = Vec::new();
let mut continue_wihtout_save = false;
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);
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;
}
}
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 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);
}
}
}
}
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;
}
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;
break;
}
}
if sent{
sent_index.push(index);
}
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);
}
}
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();
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;
}
files_finished = 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();
}
}
}
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(){
break;
}
}
}