Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e08d19c565 | ||
|
|
f1e482529c | ||
|
|
0b1dd6759f | ||
|
|
ad65897eff | ||
|
|
2573d9aef9 | ||
|
|
095da32fb8 | ||
|
|
bcee32dc90 | ||
|
|
1e29992068 |
311
Cargo.lock
generated
311
Cargo.lock
generated
@@ -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 = "0.6.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
|
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"anstyle-parse",
|
"anstyle-parse",
|
||||||
@@ -34,9 +19,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.11"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
|
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-parse"
|
name = "anstyle-parse"
|
||||||
@@ -49,50 +34,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-query"
|
name = "anstyle-query"
|
||||||
version = "1.1.3"
|
version = "1.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
|
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-wincon"
|
name = "anstyle-wincon"
|
||||||
version = "3.0.9"
|
version = "3.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
|
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"once_cell_polyfill",
|
"once_cell_polyfill",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
|
||||||
|
|
||||||
[[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]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.1"
|
version = "2.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
@@ -102,15 +66,15 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.1"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.41"
|
version = "4.5.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
|
checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@@ -118,9 +82,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.41"
|
version = "4.5.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
|
checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@@ -130,9 +94,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.41"
|
version = "4.5.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
|
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -142,9 +106,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.7.5"
|
version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
@@ -161,29 +125,12 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"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]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
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.1"
|
||||||
@@ -192,35 +139,19 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.174"
|
version = "0.2.177"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.13"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
|
||||||
"scopeguard",
|
"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]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@@ -232,15 +163,6 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"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.1"
|
||||||
@@ -249,9 +171,9 @@ checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.4"
|
version = "0.12.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
|
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"parking_lot_core",
|
"parking_lot_core",
|
||||||
@@ -259,15 +181,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot_core"
|
name = "parking_lot_core"
|
||||||
version = "0.9.11"
|
version = "0.9.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
|
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -278,37 +200,31 @@ checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.95"
|
version = "1.0.101"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.40"
|
version = "1.0.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.13"
|
version = "0.5.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-demangle"
|
|
||||||
version = "0.1.25"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@@ -326,19 +242,13 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.5"
|
version = "1.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
|
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "slab"
|
|
||||||
version = "0.4.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.15.1"
|
version = "1.15.1"
|
||||||
@@ -357,12 +267,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.10"
|
version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
|
checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -373,9 +283,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.104"
|
version = "2.0.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -384,29 +294,26 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.46.1"
|
version = "1.48.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
|
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
|
||||||
"bytes",
|
"bytes",
|
||||||
"io-uring",
|
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"slab",
|
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.5.0"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -415,9 +322,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.18"
|
version = "1.0.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
@@ -443,21 +350,18 @@ 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 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-link"
|
||||||
version = "0.52.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
@@ -465,7 +369,25 @@ version = "0.59.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
@@ -474,14 +396,31 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc 0.52.6",
|
||||||
"windows_i686_gnu",
|
"windows_i686_gnu 0.52.6",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm 0.52.6",
|
||||||
"windows_i686_msvc",
|
"windows_i686_msvc 0.52.6",
|
||||||
"windows_x86_64_gnu",
|
"windows_x86_64_gnu 0.52.6",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
"windows_x86_64_msvc",
|
"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]]
|
[[package]]
|
||||||
@@ -490,44 +429,92 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnullvm"
|
name = "windows_i686_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
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]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
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]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||||
|
|||||||
@@ -6,5 +6,12 @@ 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"] }
|
tokio = { version = "1.48.0", features = ["full"] }
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level ="z"
|
||||||
|
lto = true
|
||||||
|
strip = true
|
||||||
|
codegen-units = 1
|
||||||
|
panic = "abort"
|
||||||
|
|||||||
62
README.md
62
README.md
@@ -1,2 +1,64 @@
|
|||||||
# 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.
|
||||||
|
|
||||||
|
-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
425
src/main-bkup.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
609
src/main.rs
609
src/main.rs
@@ -1,25 +1,23 @@
|
|||||||
/*
|
|
||||||
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 clap::Parser;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::ops::Index;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread;
|
|
||||||
use std::time::Duration;
|
|
||||||
use tokio;
|
|
||||||
use tokio::sync::mpsc::{channel, Sender, Receiver};
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use tokio;
|
||||||
|
use tokio::sync::mpsc::{channel, Sender};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
/*
|
||||||
|
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!"))]
|
#[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.")]
|
||||||
@@ -30,171 +28,178 @@ struct Args{
|
|||||||
|
|
||||||
#[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>,
|
||||||
}
|
}*/
|
||||||
|
|
||||||
struct ShareFinder{
|
#[derive(Parser, Debug)]
|
||||||
id: usize,
|
#[command(version, about, long_about = Some("finds shares, but its written in rust which sometimes gets past EDR!"))]
|
||||||
tx: Sender<Message>,
|
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(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)]
|
#[derive(Clone)]
|
||||||
|
struct FinderTask{
|
||||||
|
id: usize,
|
||||||
|
target: String,
|
||||||
|
tasktype: TaskType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Finding{
|
||||||
|
path: String,
|
||||||
|
keyword: Option<bool>
|
||||||
|
}
|
||||||
|
|
||||||
struct Message{
|
struct Message{
|
||||||
source: MessageType,
|
source: usize,
|
||||||
destination: MessageType,
|
tasktype: TaskType,
|
||||||
content: String,
|
finding: Option<Finding>,
|
||||||
|
task_finished: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone)]
|
||||||
enum MessageType{
|
enum TaskType{
|
||||||
ShareMessage,
|
Share,
|
||||||
InfoMessage,
|
File,
|
||||||
ControlMessage,
|
Info,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn find_shares(task: ShareFinder, mut rx: Receiver<Message>){
|
async fn task_handler(id: usize, current_task: FinderTask, tx: Sender<Message>){
|
||||||
println!("{} share task started!", task.id);
|
match current_task.tasktype{
|
||||||
let ping_recv = rx.recv().await;
|
TaskType::Share => {
|
||||||
if ping_recv.is_some(){
|
println!("scanning {}", current_task.target);
|
||||||
let message = Message{source: MessageType::ShareMessage, destination: MessageType::ControlMessage, content: String::from("pong!")};
|
let share_list_res = Command::new("net").arg("view").arg(current_task.target.clone()).arg("/all").output();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else{
|
if success_string.len() > 0{
|
||||||
error_string = share_list_res.err().unwrap().to_string();
|
let mut sent_lines = Vec::new();
|
||||||
}
|
|
||||||
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!("\\\\{}\\{}", current_task.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, keyword: None};
|
||||||
|
let message = Message{source: id, tasktype: TaskType::Share, finding: Some(finding), task_finished: false};
|
||||||
|
tx.send(message).await.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
TaskType::File => {
|
||||||
}
|
let mut sent_lines = Vec::new();
|
||||||
|
for entry_res in walkdir::WalkDir::new(current_task.target.clone()){
|
||||||
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(){
|
if entry_res.is_ok(){
|
||||||
let entry = entry_res.unwrap();
|
let entry = entry_res.unwrap();
|
||||||
let file_path = entry.into_path();
|
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(){
|
if file_path.file_name().is_some(){
|
||||||
file_name = file_path.file_name().unwrap().to_string_lossy().to_string();
|
let file_path_string = file_path.display().to_string();
|
||||||
}
|
if !sent_lines.contains(&file_path_string){
|
||||||
for extension in &files_to_read{
|
sent_lines.push(file_path_string.clone());
|
||||||
if file_name.contains(extension){
|
let finding = Finding{path: file_path_string, keyword: None};
|
||||||
let file_content_res = read_to_string(&file_path);
|
let message = Message{source: id, tasktype: TaskType::File, finding: Some(finding), task_finished: false};
|
||||||
if file_content_res.is_ok(){
|
tx.send(message).await.unwrap();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TaskType::Info => {
|
||||||
|
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",
|
||||||
|
];
|
||||||
|
let mut file_content = String::new();
|
||||||
|
for extension in &files_to_read{
|
||||||
|
if current_task.target.contains(extension){
|
||||||
|
let file_content_res = read_to_string(¤t_task.target);
|
||||||
|
if file_content_res.is_ok(){
|
||||||
|
file_content = file_content_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut sent_lines = Vec::new();
|
||||||
|
for thing in &interesting_info{
|
||||||
|
let file_name = current_task.target.clone();
|
||||||
|
if file_name.contains(thing) || file_content.contains(thing){
|
||||||
|
let sent_line = format!("keyword {}", file_name);
|
||||||
|
if !sent_lines.contains(&sent_line){
|
||||||
|
sent_lines.push(sent_line);
|
||||||
|
let finding = Finding{path: file_name, keyword: Some(true)};
|
||||||
|
let message = Message{source: id, tasktype: TaskType::Info, finding: Some(finding), task_finished: false};
|
||||||
|
tx.send(message).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let sent_line = format!("file {}", file_name);
|
||||||
|
if !sent_lines.contains(&sent_line){
|
||||||
|
sent_lines.push(sent_line);
|
||||||
|
let finding = Finding{path: file_name, keyword: Some(false)};
|
||||||
|
let message = Message{source:id, tasktype: TaskType::Info, finding: Some(finding),task_finished: false};
|
||||||
|
tx.send(message).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let 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]
|
#[tokio::main]
|
||||||
async fn main(){
|
async fn main(){
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let mut outfile = PathBuf::new();
|
let mut outfile = PathBuf::new();
|
||||||
let mut file_threads = 5;
|
let mut threads = 10;
|
||||||
let mut share_threads = 5;
|
|
||||||
let mut save = false;
|
let mut save = false;
|
||||||
let mut computers = Vec::new();
|
let mut computers = Vec::new();
|
||||||
if args.outfile.is_some(){
|
if args.outfile.is_some(){
|
||||||
@@ -202,9 +207,7 @@ async fn main(){
|
|||||||
save = true;
|
save = true;
|
||||||
}
|
}
|
||||||
if args.threads.is_some(){
|
if args.threads.is_some(){
|
||||||
let threads = args.threads.unwrap() / 2;
|
threads = args.threads.unwrap();
|
||||||
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.");
|
||||||
@@ -253,177 +256,207 @@ 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);
|
computers.push(computer_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if share_threads > computers.len(){
|
let mut tasks = Vec::new();
|
||||||
share_threads = computers.len();
|
let mut id_counter = 0;
|
||||||
//file_threads = computers.len();
|
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...");
|
println!("computer enumeration finished, starting task finder threads...");
|
||||||
let (maintx, mut mainrx) = channel(1024);
|
let (tx, mut rx) = channel(1024);
|
||||||
let mut share_tasks = Vec::new();
|
let mut running = Vec::new();
|
||||||
let mut share_txes = Vec::new();
|
let mut continue_wihtout_save = false;
|
||||||
let mut file_tasks = Vec::new();
|
loop{
|
||||||
let mut file_txes = Vec::new();
|
if running.len() < threads{
|
||||||
for id in 0..share_threads{
|
for _i in 0 .. threads{
|
||||||
println!("starting share task {}...", id);
|
if tasks.len() > 0{
|
||||||
let (share_tx,share_rx) = channel(1);
|
let task = tasks[0].clone();
|
||||||
let new_share_task = ShareFinder{id, tx: maintx.clone()};
|
tasks.remove(0);
|
||||||
share_handles.push(tokio::spawn(find_shares(new_share_task, share_rx)));
|
running.push(task.id.clone());
|
||||||
share_tasks.push(id);
|
tokio::spawn(task_handler(task.id, task, tx.clone()));
|
||||||
share_txes.push(share_tx.clone());
|
if running.len() >= threads{
|
||||||
let ping_message = Message{source: MessageType::ControlMessage, destination: MessageType::ShareMessage, content: String::from("ping!")};
|
break;
|
||||||
share_tx.send(ping_message).await.unwrap();
|
}
|
||||||
loop{
|
}
|
||||||
let rx_recv = mainrx.recv().await;
|
else{
|
||||||
if rx_recv.is_some(){
|
|
||||||
let message = rx_recv.unwrap();
|
|
||||||
if message.content == String::from("pong!"){
|
|
||||||
println!("{} ready!", id);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("didn't recieve file pong from {}", id);
|
|
||||||
}
|
}
|
||||||
}
|
if running.len() > 0{
|
||||||
for id in 0..file_threads{
|
let rxres = rx.try_recv();
|
||||||
println!("starting file task {}...", id);
|
if rxres.is_ok(){
|
||||||
let (file_tx, file_rx) = channel(1);
|
let mesage = rxres.unwrap();
|
||||||
let new_file_task = ShareFinder{id, tx: maintx.clone()};
|
if mesage.task_finished{
|
||||||
file_handles.push(tokio::spawn(find_info(new_file_task, file_rx)));
|
for index in 0 .. running.len(){
|
||||||
file_tasks.push(id);
|
if index == running.len(){
|
||||||
file_txes.push(file_tx.clone());
|
break;
|
||||||
let ping_message = Message{source: MessageType::ControlMessage, destination: MessageType::ShareMessage, content: String::from("ping!")};
|
}
|
||||||
file_tx.send(ping_message).await.unwrap();
|
else{
|
||||||
loop{
|
if running[index] == mesage.source{
|
||||||
let rx_recv = mainrx.recv().await;
|
running.remove(index);
|
||||||
if rx_recv.is_some(){
|
}
|
||||||
let message = rx_recv.unwrap();
|
}
|
||||||
if message.content == String::from("pong!"){
|
}
|
||||||
println!("{} ready!", id);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
println!("didn't recieve file pong from {}", id);
|
let finding = mesage.finding.unwrap();
|
||||||
}
|
match mesage.tasktype{
|
||||||
}
|
TaskType::Share => {
|
||||||
let mut current_computer = 0;
|
println!("{} {}", "share found!".green(), finding.path);
|
||||||
let mut shares_finished = false;
|
if save{
|
||||||
let mut files_finished = false;
|
let open_res = OpenOptions::new().create(true).append(true).open(&outfile);
|
||||||
let mut file_buffer = Vec::new();
|
if open_res.is_err(){
|
||||||
let mut finished_counter = 0;
|
if !continue_wihtout_save{
|
||||||
let mut empty_counter = 0;
|
eprintln!("{}", "error opening save file!".red());
|
||||||
let mut started = true;
|
eprintln!("{}", open_res.err().unwrap().to_string().red());
|
||||||
let mut handled_lines = Vec::new();
|
let mut proceed = String::new();
|
||||||
loop {
|
println!("continue anyway?");
|
||||||
if files_finished && shares_finished{
|
std::io::stdin().read_line(&mut proceed).unwrap();
|
||||||
break;
|
if proceed.to_lowercase().contains("y"){
|
||||||
}
|
continue_wihtout_save = true;
|
||||||
if !mainrx.is_empty(){
|
}
|
||||||
finished_counter = 0;
|
else{
|
||||||
empty_counter = 0;
|
exit(1);
|
||||||
started = true;
|
}
|
||||||
let rx_res = mainrx.recv().await;
|
}
|
||||||
if rx_res.is_some(){
|
}
|
||||||
let message = rx_res.unwrap();
|
else{
|
||||||
match message.destination{
|
let mut save_file = open_res.unwrap();
|
||||||
MessageType::ControlMessage => {
|
let write_res = write!(save_file,"share found! {}\n", finding.path);
|
||||||
let message_vec: Vec<&str> = message.content.split(":").collect();
|
if write_res.is_err(){
|
||||||
let _id = message_vec[0];
|
if !continue_wihtout_save{
|
||||||
let message_content = message_vec[1].to_string();
|
eprintln!("{}", "error writing to save file!".red());
|
||||||
match message_content{
|
eprintln!("{}", write_res.err().unwrap().to_string().red());
|
||||||
_ => {
|
let mut proceed = String::new();
|
||||||
if !handled_lines.contains(&message_content){
|
println!("proceed without saving?");
|
||||||
if save{
|
std::io::stdin().read_line(&mut proceed).unwrap();
|
||||||
let open_res = OpenOptions::new().append(true).create(true).open(&outfile);
|
if proceed.to_lowercase().contains("y"){
|
||||||
if open_res.is_ok(){
|
continue_wihtout_save = true;
|
||||||
let mut file = open_res.unwrap();
|
}
|
||||||
let write_res = write!(file, "{}\n", message_content);
|
else{
|
||||||
if write_res.is_err(){
|
exit(1);
|
||||||
eprintln!("{}", "error writing to outfile!".red());
|
|
||||||
eprintln!("{}", write_res.err().unwrap().to_string().red());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{}", message_content.green());
|
else{
|
||||||
handled_lines.push(message_content);
|
write_res.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
let new_task = FinderTask{id: id_counter, tasktype: TaskType::File, target: finding.path};
|
||||||
}
|
tasks.push(new_task);
|
||||||
MessageType::InfoMessage => {
|
id_counter += 1;
|
||||||
file_buffer.push(message.content);
|
}
|
||||||
}
|
TaskType::File => {
|
||||||
MessageType::ShareMessage => {}
|
let new_task = FinderTask{id: id_counter, tasktype: TaskType::Info, target: finding.path};
|
||||||
}
|
tasks.push(new_task);
|
||||||
}
|
id_counter += 1;
|
||||||
}
|
}
|
||||||
let mut sent = false;
|
TaskType::Info => {
|
||||||
if !shares_finished{
|
if finding.keyword.unwrap(){
|
||||||
for tx in &share_txes{
|
println!("{} {}", "keyword match at".green(), finding.path.green());
|
||||||
if tx.capacity() > 0{
|
if save{
|
||||||
let message = Message{source: MessageType::ShareMessage, destination: MessageType::ShareMessage, content: computers[current_computer].clone()};
|
let open_res = OpenOptions::new().create(true).append(true).open(&outfile);
|
||||||
tx.send(message).await.unwrap();
|
if open_res.is_err(){
|
||||||
sent = true;
|
if !continue_wihtout_save{
|
||||||
break;
|
eprintln!("{}", "error opening save file!".red());
|
||||||
}
|
eprintln!("{}", open_res.err().unwrap().to_string().red());
|
||||||
}
|
let mut proceed = String::new();
|
||||||
if sent{
|
println!("continue anyway?");
|
||||||
current_computer +=1;
|
std::io::stdin().read_line(&mut proceed).unwrap();
|
||||||
if current_computer == computers.len() {
|
if proceed.to_lowercase().contains("y"){
|
||||||
shares_finished = true;
|
continue_wihtout_save = true;
|
||||||
}
|
}
|
||||||
}
|
else{
|
||||||
}
|
exit(1);
|
||||||
if shares_finished{
|
}
|
||||||
if file_buffer.len() == 0{
|
}
|
||||||
empty_counter += 1;
|
}
|
||||||
}
|
else{
|
||||||
if empty_counter >= 100{
|
let mut save_file = open_res.unwrap();
|
||||||
finished_counter +=1;
|
let write_res = write!(save_file,"keyword match at {}\n", finding.path);
|
||||||
thread::sleep(Duration::from_millis(50));
|
if write_res.is_err(){
|
||||||
}
|
if !continue_wihtout_save{
|
||||||
}
|
eprintln!("{}", "error writing to save file!".red());
|
||||||
if file_buffer.len() > 0{
|
eprintln!("{}", write_res.err().unwrap().to_string().red());
|
||||||
let mut sent_index = Vec::new();
|
let mut proceed = String::new();
|
||||||
empty_counter = 0;
|
println!("proceed without saving?");
|
||||||
finished_counter = 0;
|
std::io::stdin().read_line(&mut proceed).unwrap();
|
||||||
let mut current_tx = 0;
|
if proceed.to_lowercase().contains("y"){
|
||||||
for index in 0 .. file_buffer.len() - 1{
|
continue_wihtout_save = true;
|
||||||
let mut sent = false;
|
}
|
||||||
let message = Message{source: MessageType::ControlMessage, destination: MessageType::InfoMessage, content: file_buffer[index].clone()};
|
else{
|
||||||
if file_txes[current_tx].capacity()> 0{
|
exit(1);
|
||||||
file_txes[current_tx].send(message).await.unwrap();
|
}
|
||||||
sent = true;
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
current_tx += 1;
|
write_res.unwrap();
|
||||||
if current_tx == file_txes.len(){
|
}
|
||||||
current_tx = 0;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 sent{
|
|
||||||
sent_index.push(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for index in sent_index{
|
|
||||||
file_buffer.remove(index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if finished_counter == 10{
|
if running.len() == 0 && tasks.len() == 0 && rx.is_empty(){
|
||||||
for tx in &file_txes{
|
break;
|
||||||
let done_message = Message{source: MessageType::ControlMessage, destination: MessageType::InfoMessage, content: String::from("0:||DONE||")};
|
|
||||||
tx.send(done_message).await.unwrap();
|
|
||||||
}
|
|
||||||
files_finished = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user