diff --git a/Cargo.lock b/Cargo.lock index 9856663..bb95f25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,21 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -32,6 +47,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anstream" version = "0.6.17" @@ -137,6 +161,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "better-panic" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa9e1d11a268684cbd90ed36370d7577afb6c62d912ddff5c15fc34343e5036" +dependencies = [ + "backtrace", + "console", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -149,6 +183,18 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -158,6 +204,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "borsh" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" +dependencies = [ + "cfg_aliases", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -170,6 +225,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" + [[package]] name = "cc" version = "1.1.31" @@ -185,6 +246,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -199,6 +266,21 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_lex 0.2.4", + "indexmap", + "strsim 0.10.0", + "termcolor", + "textwrap", +] + [[package]] name = "clap" version = "4.5.20" @@ -221,8 +303,17 @@ checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", - "clap_lex", - "strsim", + "clap_lex 0.7.2", + "strsim 0.11.1", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", ] [[package]] @@ -231,12 +322,33 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "console" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "windows-sys", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -262,6 +374,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -336,12 +457,24 @@ dependencies = [ "generic-array", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "elf" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "exe" version = "0.5.6" @@ -360,6 +493,31 @@ dependencies = [ "widestring", ] +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "generic-array" version = "0.14.7" @@ -378,15 +536,21 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "goblin" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53ab3f32d1d77146981dea5d6b1e8fe31eedcb7013e5e00d6ccd1259a4b4d923" +checksum = "daa0a64d21a7eb230583b4c5f4e23b7e4e57974f96620f42a7e75e08ae66d745" dependencies = [ "log", "plain", "scroll", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -425,12 +589,40 @@ dependencies = [ "cc", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "inflate" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +dependencies = [ + "adler32", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -446,6 +638,59 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lancelot" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f6aefdab78ed7ff3bf239487d76a63483a2ac01ca99a8c7cf5b091351e656e7" +dependencies = [ + "ansi_term", + "anyhow", + "bitflags 1.3.2", + "bitvec", + "byteorder", + "chrono", + "goblin", + "lancelot-flirt", + "lazy_static", + "log", + "object", + "prost", + "regex", + "smallvec", + "smol_str", + "thiserror", + "widestring", + "zydis", +] + +[[package]] +name = "lancelot-flirt" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a10286b78d281dba7c2534da6c5ef13668e594c62e83495233c858f1877b912a" +dependencies = [ + "anyhow", + "better-panic", + "bitflags 1.3.2", + "bitvec", + "chrono", + "clap 3.2.25", + "fern", + "inflate", + "log", + "nom", + "regex", + "smallvec", + "thiserror", +] + +[[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.161" @@ -500,6 +745,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f2dd5c7f8aaf48a76e389068ab25ed80bdbc226b887f9013844c415698c9952" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.0" @@ -563,6 +814,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -602,7 +863,9 @@ version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ + "flate2", "memchr", + "ruzstd", ] [[package]] @@ -617,6 +880,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + [[package]] name = "parking_lot" version = "0.12.3" @@ -675,13 +944,36 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "quote" version = "1.0.37" @@ -691,6 +983,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "raw-window-handle" version = "0.5.2" @@ -706,12 +1004,50 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "ruzstd" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f" +dependencies = [ + "twox-hash", +] + [[package]] name = "ryu" version = "1.0.18" @@ -741,7 +1077,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.98", ] [[package]] @@ -761,7 +1097,7 @@ checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.98", ] [[package]] @@ -784,7 +1120,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.98", ] [[package]] @@ -825,6 +1161,28 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "smol_str" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d" +dependencies = [ + "borsh", + "serde", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" @@ -844,9 +1202,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -863,6 +1221,12 @@ dependencies = [ "serde_repr", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "termcolor" version = "1.4.1" @@ -872,6 +1236,32 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "time" version = "0.3.36" @@ -905,6 +1295,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + [[package]] name = "typenum" version = "1.17.0" @@ -933,10 +1333,11 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" name = "vestal" version = "0.1.0" dependencies = [ - "clap", + "clap 4.5.20", "elf", "exe", "goblin", + "lancelot", "syscalls", ] @@ -1006,7 +1407,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.98", "wasm-bindgen-shared", ] @@ -1028,7 +1429,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1223,3 +1624,24 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zydis" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfc13daee87922e0d6dc6137327be10327ad1cee0515ec775f898206193aaeb8" +dependencies = [ + "bitflags 1.3.2", + "cmake", + "serde", + "serde_derive", +] diff --git a/crates/vestal/Cargo.toml b/crates/vestal/Cargo.toml index 4c4cce5..2e0c126 100644 --- a/crates/vestal/Cargo.toml +++ b/crates/vestal/Cargo.toml @@ -5,10 +5,9 @@ edition = "2021" [dependencies] exe = "0.5.6" -goblin = "0.9.2" -clap = { version = "4.5.4", features = [ "cargo" ] } -#lancelot = "0.8.6 - -syscalls = "0.6.18" elf = "0.7.4" +goblin = "0.9.3" +clap = { version = "4.5.4", features = [ "cargo" ] } +lancelot = "0.9.7" +syscalls = "0.6.18" #falcon = "0.5.5" diff --git a/crates/vestal/src/vst.rs b/crates/vestal/src/dll.rs similarity index 65% rename from crates/vestal/src/vst.rs rename to crates/vestal/src/dll.rs index 0149be0..2b18b3a 100644 --- a/crates/vestal/src/vst.rs +++ b/crates/vestal/src/dll.rs @@ -1,3 +1,57 @@ +use crate::*; +use exe::pe::{VecPE, PtrPE}; +#[derive(Default)] +pub struct PEContext { + dlls: HashMap, +} +impl PEContext { + pub fn load (&mut self, name: &str, path: &PathBuf) -> Usually<()> { + let name = name.to_lowercase(); + if self.dlls.contains_key(&name) { + return Ok(()) + } + println!("\n(:= \"{}\" {:?})", name, path); + let dll = Dll::new(name.as_str(), path)?; + println!("(:= \"{}\" {:p}+{})", name, &dll.pe.buf, dll.pe.buf.len()); + let mut imports = vec![]; + for export in dll.goblin()?.imports.iter() { + //println!(" - {:8} + {:?} = {:?}", &export.rva, &export.offset, &export.name); + } + for import in dll.goblin()?.imports.iter() { + let dll = import.dll.to_lowercase(); + println!(" (-> {} {})", &dll, &import.name); + imports.push(dll); + } + self.dlls.insert(name.to_string(), dll); + for name in imports.iter() { + let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", name); + self.load(name, &PathBuf::from(path))?; + } + Ok(()) + } +} +struct Dll { + name: String, + path: PathBuf, + bang: Vec, + pe: PE, +} +impl Dll { + fn new (name: &str, path: &PathBuf) -> Usually { + let (bang, data) = slice_shebang(read(path)?.as_slice()); + let mut pe = PE::from_bytes(data.as_slice())?; + apply_relocations(&mut pe)?; + Ok(Self { + bang, + name: name.to_string(), + path: path.into(), + pe, + }) + } + fn goblin (&self) -> Usually { + Ok(goblin::pe::PE::parse(self.pe.buf.as_slice())?) + } +} use std::ffi::c_void; //typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); #[repr(C)] pub struct AEffect { diff --git a/crates/vestal/src/memrun.rs b/crates/vestal/src/exec.rs similarity index 57% rename from crates/vestal/src/memrun.rs rename to crates/vestal/src/exec.rs index f7df2f7..000744a 100644 --- a/crates/vestal/src/memrun.rs +++ b/crates/vestal/src/exec.rs @@ -1,3 +1,5 @@ +use crate::*; +use elf::file::Elf64_Ehdr; use std::fmt::{Debug, Display}; use syscalls::{Sysno, Errno, syscall}; @@ -55,3 +57,35 @@ fn run (fd: usize) { Ok(_) => (), } } + +fn make_elf () -> Vec { + let mut buffer = vec![0;1024*1024*1024]; + // https://wiki.osdev.org/ELF#ELF_Header + buffer[0x00..0x40].copy_from_slice(any_as_u8_slice(&Elf64_Ehdr { + e_ehsize: 0x40, // elf header size, + e_ident: [ // identification data + 0x7f, b'E', b'L', b'F', // magic bytes + 0x02, // 64-bit, 0x01 is 32-bit + 0x01, // little-endian + 0x01, // ELF header version + 0x00, // SysV ABI + 0x00, 0x00, 0x00, 0x00, // unused + 0x00, 0x00, 0x00, 0x00, // unused + ], + e_version: 0x01, // ELF version + e_type: 0x02, // executable + e_machine: 0x3e, // x86_64, 0x03 = x86 + e_flags: 0x00, // TODO machine flags, + e_entry: 0x00, // TODO entry point (from wrapper?) + + e_phnum: 0x00, // TODO program headers + e_phentsize: 0x00, // TODO why is there phent in my elf? + e_phoff: 0x00, // TODO program header table offset + + e_shnum: 0x00, // TODO section headers + e_shentsize: 0x00, // TODO section header entry size + e_shoff: 0x00, // TODO section header table offset + e_shstrndx: 0x00, // TODO section header table index something something + })); + buffer +} diff --git a/crates/vestal/src/execute.rs b/crates/vestal/src/execute.rs deleted file mode 100644 index 97d604d..0000000 --- a/crates/vestal/src/execute.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::*; -use syscalls::{Sysno, syscall}; -use elf::file::Elf64_Ehdr; -use std::ffi::CString; -use std::str::FromStr; -static NAME: &'static [u8] = &[b'\0']; -impl Vestal { - pub fn execute_path (&self, path: impl AsRef) -> Usually<()> { - self.inspect_path(path)?; - //let mut not_found = vec![]; - //for (dll, imports) in deps.iter() { - //if let Some(dll) = find_dll(dll)? { - //Self::from_data_dll(dll, |dll_buffer, dll_pe, dll_imports, dll_deps|{ - //Ok(()) - //}); - //for import in imports.iter() { - //println!(" {:8} + {:8} {:32}", import.rva, import.offset, import.name); - //} - //} else { - //println!("- {dll} NOT FOUND"); - //not_found.push(dll); - //} - //} - // TODO: call(main, AEffect::host_callback) - Ok(()) - } -} - -fn find_dll (dll: &str) -> Usually>> { - let dll = dll.to_lowercase(); - let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", dll); - let buffer = std::fs::read::(path.clone())?; - println!(" Found: {path} {}b", buffer.len()); - Ok(Some(buffer)) -} - -fn make_elf () -> Vec { - let mut buffer = vec![0;1024*1024*1024]; - // https://wiki.osdev.org/ELF#ELF_Header - buffer[0x00..0x40].copy_from_slice(any_as_u8_slice(&Elf64_Ehdr { - e_ehsize: 0x40, // elf header size, - e_ident: [ // identification data - 0x7f, b'E', b'L', b'F', // magic bytes - 0x02, // 64-bit, 0x01 is 32-bit - 0x01, // little-endian - 0x01, // ELF header version - 0x00, // SysV ABI - 0x00, 0x00, 0x00, 0x00, // unused - 0x00, 0x00, 0x00, 0x00, // unused - ], - e_version: 0x01, // ELF version - e_type: 0x02, // executable - e_machine: 0x3e, // x86_64, 0x03 = x86 - e_flags: 0x00, // TODO machine flags, - e_entry: 0x00, // TODO entry point (from wrapper?) - - e_phnum: 0x00, // TODO program headers - e_phentsize: 0x00, // TODO why is there phent in my elf? - e_phoff: 0x00, // TODO program header table offset - - e_shnum: 0x00, // TODO section headers - e_shentsize: 0x00, // TODO section header entry size - e_shoff: 0x00, // TODO section header table offset - e_shstrndx: 0x00, // TODO section header table index something something - })); - buffer -} -/// From https://stackoverflow.com/a/42186553 -fn any_as_u8_slice(p: &T) -> &[u8] { - unsafe { - ::core::slice::from_raw_parts( - (p as *const T) as *const u8, - ::core::mem::size_of::(), - ) - } -} diff --git a/crates/vestal/src/inspect.rs b/crates/vestal/src/inspect.rs deleted file mode 100644 index 4b0855a..0000000 --- a/crates/vestal/src/inspect.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::*; - -impl Vestal { - pub fn inspect_path (&self, path: impl AsRef) -> Usually { - let pe = crate::parse::Dll::from_path(path)?; - let pe = pe.with_entrypoint("VSTPluginMain")?; - let main = pe.entrypoint.as_ref().unwrap(); - println!("VSTPluginMain: {:?} + {:?}", &main.rva, &main.offset); - let deps = &pe.imports; - // TODO: load Wine libs - println!("Imports: {:#?}", deps.len()); - Ok((pe, buf)) - //Self::from_path(&path, |buffer, pe, main, deps|{ - - //if let Some(main) = main { - //println!("VSTPluginMain: {:?} + {:?}", &main.rva, &main.offset); - //} else { - //panic!("VSTPluginMain not found. This is not a valid VST plugin."); - //} - //println!("Imports: {:#?}", &pe.imports.len()); - //println!("Dependencies: {:#?}", &deps.len()); - //for (dll, imports) in deps.iter() { - //println!("- {dll}"); - //for import in imports.iter() { - //println!(" {:8} + {:8} {:32}", import.rva, import.offset, import.name); - //} - //} - //Ok(()) - //}) - //let image = VecPE::from_disk_file(path)?; - //let import_directory = ImportDirectory::parse(&image)?; - //for descriptor in import_directory.descriptors { - //let name = descriptor.get_name(&image)?.as_str()?; - //println!("\n{name}:"); - //for import in descriptor.get_imports(&image).unwrap() { - //match import { - //ImportData::Ordinal(x) => println!("{name} #{x}"), - //ImportData::ImportByName(s) => println!("{name} {s}") - //} - //} - //} - } -} diff --git a/crates/vestal/src/main.rs b/crates/vestal/src/main.rs index 08fbd9a..0e17816 100644 --- a/crates/vestal/src/main.rs +++ b/crates/vestal/src/main.rs @@ -1,33 +1,14 @@ -//mod execute; -//mod inspect; -mod reloc; -mod memrun; -//mod parse; -mod vst; +#![feature(slice_split_once)] +mod dll; +mod exec; pub(crate) use std::error::Error; pub(crate) use std::path::{Path, PathBuf}; pub(crate) use std::collections::HashMap; pub(crate) use std::fs::{read, canonicalize}; -pub(crate) use goblin::{error, Object, pe::{PE, import::Import, export::Export}}; +pub(crate) use lancelot::loader::pe::{PE, reloc::apply_relocations}; +pub(crate) use goblin::{error, Object, pe::{import::Import, export::Export}}; use clap::{arg, command, value_parser, ArgAction, Command}; - type Usually = Result>; - -type Sources = HashMap>; -type Context = HashMap; - -#[derive(Clone)] -struct Dll { - name: String, - path: PathBuf, - data: Vec, -} -impl Dll { - fn pe (&self) -> Usually { - read_pe(slice_shebang(&self.data)) - } -} - fn main () -> Usually<()> { let matches = command!() .arg(arg!([path] "Path to VST DLL").value_parser(value_parser!(PathBuf))) @@ -35,141 +16,32 @@ fn main () -> Usually<()> { //.arg(arg!(-s --stub "Provide stub import").required(false)) .get_matches(); if let Some(path) = matches.get_one::("path") { - let mut context: Context = HashMap::new(); - read_dll(&mut context, "vestal", &canonicalize(&path)?)?; + let mut context = crate::dll::PEContext::default(); + context.load("main", &canonicalize(&path)?)?; Ok(()) } else { panic!("Pass a path to a VST DLL.") } } - -fn read_dll (context: &mut Context, name: &str, path: &PathBuf) -> Usually<()> { - let name = canonical_name(&name); - if context.contains_key(&name) { - return Ok(()) +/// From https://stackoverflow.com/a/42186553 +pub fn any_as_u8_slice(p: &T) -> &[u8] { + unsafe { + ::core::slice::from_raw_parts( + (p as *const T) as *const u8, + ::core::mem::size_of::(), + ) } - println!("\n(:= \"{}\" {:?})", name, path); - let dll = Dll { name: name.to_string(), data: read(path)?, path: path.into(), }; - println!("(:= \"{}\" {:p}+{})", name, &dll.data, dll.data.len()); - let mut imports = vec![]; - for export in dll.pe()?.exports.iter() { - //println!(" - {:8} + {:?} = {:?}", &export.rva, &export.offset, &export.name); - } - for import in dll.pe()?.imports.iter() { - let dll = import.dll.to_lowercase(); - println!(" (-> {} {})", &dll, &import.name); - imports.push(dll); - } - context.insert(name.to_string(), dll); - for name in imports.iter() { - let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", name); - read_dll(context, name, &PathBuf::from(path))?; - } - Ok(()) } - -fn canonical_name (path: impl AsRef) -> String { - path.as_ref().to_path_buf().into_os_string().into_string() - .expect("failed to convert path") - .to_lowercase() -} - -fn slice_shebang (buffer: &[u8]) -> &[u8] { - let mut index = 2; - let mut slice = false; +/// You can manually patch DLLs by prepending +/// a `#!/usr/bin/env vestal` line to them. +pub fn slice_shebang (buffer: &[u8]) -> (Vec, Vec) { if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { - while let Some(c) = buffer.get(index) { - if *c == 0x0a { - slice = true; - break - } - index += 1; + if let Some((bang, data)) = buffer.split_once(|x|*x==0x0a) { + (bang.to_vec(), data.to_vec()) + } else { + (buffer.to_vec(), vec![]) } - } - if slice { - println!("Slice: {index}"); - &buffer[index+1..] } else { - buffer + (vec![], buffer.to_vec()) } } - -fn read_pe (buffer: &[u8]) -> Usually { - if let Object::PE(pe) = Object::parse(buffer)? { - Ok(pe) - } else { - panic!("not a PE") - } -} - -fn find_main <'a> (pe: &'a PE<'a>) -> &'a Export<'a> { - for export in pe.exports.iter() { - if let Some("VSTPluginMain") = export.name { - println!("VSTPluginMain found: {:?} + {:?}", export.rva, export.offset); - return export - } - } - panic!("no VSTPluginMain") -} - -fn resolve_imports ( - sources: &mut Sources, - context: &mut Context, -) -> Usually { - let mut updated: Context = Default::default(); - for (name, dll) in context.iter() { - //if let Some(dll) = dll { - //let imports = &dll.pe.imports; - //for import in dll.pe.imports.iter() { - //let dep = import.dll.to_lowercase(); - //if context.get(&dep).is_none() { - //updated.insert(dep, None); - //} - //} - //} else { - //let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", name); - //let data = read(&path)?; - //updated.insert(name.clone(), Some(Dll { - //name: name.clone(), - //path: path.into(), - //data: data.clone(), - //pe: read_pe(data.as_slice())? - //})); - //} - } - let count = updated.len(); - for (name, library) in updated.into_iter() { - context.insert(name, library); - } - Ok(count) -} - -fn find_dll (dll: &str) -> Option { - Some(format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", dll)) -} - -//#[derive(Debug, Parser)] -//#[command(version, about, long_about = None)] -//pub struct Vestal { - ///// Inspect a DLL - //Inspect { path: String }, - ///// Load a VST DLL into memory - //Execute { path: String }, - ///// Load a VST DLL from hashbang - //Loader { path: String } -//} - -//pub enum Arch { - //ThirtyTwo, - //SixtyFour, -//} - -//impl Vestal { - //pub fn run (&self) -> Usually<()> { - //match self { - //Self::Inspect { path } => { self.inspect_path(path.as_str())?; Ok(()) }, - //Self::Execute { path } => self.execute_path(path.as_str()), - //Self::Loader { path } => self.execute_path(path.as_str()), - //} - //} -//} diff --git a/crates/vestal/src/parse.rs b/crates/vestal/src/parse.rs deleted file mode 100644 index db6c739..0000000 --- a/crates/vestal/src/parse.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::*; - -pub struct Dll<'a> { - pub buffer: Vec, - pub pe: PE<'a>, - pub entrypoint: Option<&'a Export<'a>>, - pub exports: Vec<&'a Export<'a>>, - pub imports: HashMap>>, -} - -#[derive(Debug)] -pub enum DllError { - NotPE, - NoEntry(String) -} - -impl<'a> Dll<'a> { - pub fn from_path (path: impl AsRef) -> Usually { - Self::from_buffer(std::fs::read(path.as_ref())?) - } - pub fn from_buffer (buffer: Vec) -> Usually { - if let Object::PE(pe) = Object::parse(buffer.as_slice())? { - let mut imports: HashMap<_, _> = Default::default(); - for import in pe.imports.iter() { - let dll = import.dll.clone(); - if !imports.contains_key(dll) { - imports.insert(dll.to_string(), vec![]); - } - imports.get_mut(dll).unwrap().push(import); - } - let mut exports: Vec<_> = Default::default(); - for export in pe.exports.iter() { - exports.push(export) - } - Ok(Self { buffer, pe, imports, exports, entrypoint: None }) - } else { - Err("not a pe".into()) - } - } - pub fn with_entrypoint (self, name: &str) -> Usually { - for export in self.exports.iter() { - if let Some(name) = export.name { - self.entrypoint = Some(export); - return Ok(self) - } - } - return Err(format!("no entrypoint \"{name}\"").into()) - } -} - -fn slice_shebang (buffer: Vec) -> Vec { - let mut index = 2; - let mut slice = false; - if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { - while let Some(c) = buffer.get(index) { - if *c == 0x0a { - slice = true; - break - } - index += 1; - } - } - println!("Slice: {slice} {index}"); - if slice { buffer[index+1..].to_vec() } else { buffer } -} - -//impl Vestal { - - //pub fn from_path ( - //path: &impl AsRef, - //cb: impl Fn(&[u8], &PE, Option<&Export>, HashMap>)->Usually<()> - //) -> Usually<()> { - //println!("Path: {}", path.as_ref().display()); - //let buffer = std::fs::read(path.as_ref())?; - //Self::from_data(buffer.as_slice(), cb) - //} - - //pub fn from_data_dll ( - //mut buffer: &[u8], - //callback: impl Fn(&[u8], &PE, Option<&Export>, HashMap>)->Usually<()> - //) -> Usually<()> { - //println!("PE: {}b", buffer.len()); - //let mut index = 2; - //let mut slice = false; - //if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { - //while let Some(c) = buffer.get(index) { - //if *c == 0x0a { - //slice = true; - //break - //} - //index += 1; - //} - //} - //println!("Slice: {slice} {index}"); - //let buffer = if slice { &buffer[index+1..] } else { buffer }; - //if let Object::PE(ref pe) = Object::parse(buffer)? { - //let mut main = None; - //let mut imports: HashMap<_, _> = Default::default(); - //for import in pe.imports.iter() { - //let dll = import.dll.clone(); - //if !imports.contains_key(dll) { - //imports.insert(dll.to_string(), vec![]); - //} - //imports.get_mut(dll).unwrap().push(import); - //} - //for export in pe.exports.iter() { - //if let Some("VSTPluginMain") = export.name { - //main = Some(export); - //break - //} - //} - //callback(&buffer, pe, main, imports); - //Ok(()) - //} else { - //Err("not a PE".into()) - //} - //} - - //pub fn from_data ( - //mut buffer: &[u8], - //callback: impl Fn(&[u8], &PE, Option<&Export>, HashMap>)->Usually<()> - //) -> Usually<()> { - //println!("PE: {}b", buffer.len()); - //let mut index = 2; - //let mut slice = false; - //if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { - //while let Some(c) = buffer.get(index) { - //if *c == 0x0a { - //slice = true; - //break - //} - //index += 1; - //} - //} - //println!("Slice: {slice} {index}"); - //let buffer = if slice { &buffer[index+1..] } else { buffer }; - //if let Object::PE(ref pe) = Object::parse(buffer)? { - //let mut main = None; - //let mut imports: HashMap<_, _> = Default::default(); - //for import in pe.imports.iter() { - //let dll = import.dll.clone(); - //if !imports.contains_key(dll) { - //imports.insert(dll.to_string(), vec![]); - //} - //imports.get_mut(dll).unwrap().push(import); - //} - //for export in pe.exports.iter() { - //if let Some("VSTPluginMain") = export.name { - //main = Some(export); - //break - //} - //} - //callback(&buffer, pe, main, imports); - //Ok(()) - //} else { - //Err("not a PE".into()) - //} - //} - -//} diff --git a/crates/vestal/src/reloc.rs b/crates/vestal/src/reloc.rs deleted file mode 100644 index e37b97a..0000000 --- a/crates/vestal/src/reloc.rs +++ /dev/null @@ -1,174 +0,0 @@ -use crate::*; -/// From https://docs.rs/lancelot/latest/src/lancelot/loader/pe/reloc.rs.html#68-71 -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum RelocType { - /// The base relocation is skipped. This type can be used to pad a block. - Abs = 0, - /// The base relocation adds the high 16 bits of the difference to the - /// 16-bit field at offset. The 16-bit field represents the high value of a - /// 32-bit word. - Hi = 1, - /// The base relocation adds the low 16 bits of the difference to the 16-bit - /// field at offset. The 16-bit field represents the low half of a 32-bit - /// word. - Lo = 2, - /// The base relocation applies all 32 bits of the difference to the 32-bit - /// field at offset. - HiLo = 3, - /// The base relocation adds the high 16 bits of the difference to the - /// 16-bit field at offset. The 16-bit field represents the high value of a - /// 32-bit word. The low 16 bits of the 32-bit value are stored in the - /// 16-bit word that follows this base relocation. This means that this base - /// relocation occupies two slots. - HiAdj = 4, - /// The base relocation applies the difference to the 64-bit field at - /// offset. - Dir64 = 10, -} -impl From for RelocType { - fn from(value: u16) -> Self { - match value { - 0 => Self::Abs, - 1 => Self::Hi, - 2 => Self::Lo, - 3 => Self::HiLo, - 4 => Self::HiAdj, - 10 => Self::Dir64, - _ => panic!("Invalid RelocType value: {}", value), - } - } -} -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Relocation { - type_: RelocType, - address: VA, -} -pub struct RelocSectionData { - base_address: VA, - buf: Vec, -} -pub type VA = u64; -pub type RVA = u64; -impl RelocSectionData { - fn read_u16(&self, offset: usize) -> Usually { - if offset + 2 > self.buf.len() { - return Err("buffer too small".into()) - } - Ok(u16::from_le_bytes([ - self.buf[offset + 0], - self.buf[offset + 1], - ])) - } - fn read_u32(&self, offset: usize) -> Usually { - if offset + 4 > self.buf.len() { - return Err("buffer too small".into()) - } - Ok(u32::from_le_bytes([ - self.buf[offset + 0], - self.buf[offset + 1], - self.buf[offset + 2], - self.buf[offset + 3], - ])) - } - pub fn relocations(&self) -> Usually> { - let mut relocations = vec![]; - let mut offset = 0x0; - while offset < self.buf.len() { - let rva = self.read_u32(offset)? as u64; - let size = self.read_u32(offset + 4)? as usize; - println!("(reloc-block rva={rva:x} size={size:x})"); - const header_size: usize = 8; - const entry_size: usize = 2; - let entry_count = (size - header_size) / entry_size; - for entry_index in 0..entry_count { - let entry = self.read_u16(offset + header_size + (entry_index * entry_size))?; - let entry_type = RelocType::from(entry >> 12); - let entry_value = (entry & 0x0FFF) as u64; - let address = self.base_address + rva + entry_value; - println!("(reloc-entry addr={address:x} type={entry_type:?})"); - relocations.push(Relocation { - type_: entry_type, - address, - }); - } - offset += size; - } - Ok(relocations) - } - pub fn from_pe(pe: &PE) -> Usually> { - let opt_header = match pe.header.optional_header { - None => return Ok(None), - Some(opt_header) => opt_header, - }; - let reloc_table = match opt_header.data_directories.get_base_relocation_table() { - None => return Ok(None), - Some(reloc_table) => reloc_table, - }; - println!( - "(reloc-table {:#x}-{:#x})", - pe.module.address_space.base_address + reloc_table.virtual_address as RVA, - pe.module.address_space.base_address + reloc_table.virtual_address as RVA + reloc_table.size as RVA - ); - let buf = pe.module.address_space.read_bytes( - // goblin calls this a "virtual address", but its actually an RVA. - pe.module.address_space.base_address + reloc_table.virtual_address as RVA, - reloc_table.size as usize, - )?; - Ok(Some(RelocSectionData { - base_address: pe.module.address_space.base_address, - buf, - })) - } -} -pub fn apply_relocations(pe: &mut PE) -> Usually<()> { - let opt_header = match pe.optional_header { - None => return Ok(()), - Some(opt_header) => opt_header, - }; - let wanted = opt_header.windows_fields.image_base; - let found = pe.module.address_space.base_address; - if wanted == found { - println!("# reloc: no relocations necessary"); - return Ok(()); - } - let relocations = if let Ok(Some(reloc_data)) = RelocSectionData::from_pe(pe) { - reloc_data.relocations()? - } else { - println!("# reloc: no relocations found"); - return Ok(()); - }; - let delta = (found as i64) - (wanted as i64); - println!("# reloc: applying {} relocations", relocations.len()); - for relocation in relocations.iter() { - match relocation.type_ { - // https://github.com/abhisek/Pe-Loader-Sample/blob/9aed4b3f6cd33ef75a0e01c21ea9f81608bf96cf/src/PeLdr.cpp#L44 - RelocType::Abs => continue, - RelocType::Dir64 => { - println!("(reloc-dir64 {:x})", relocation.address); - let existing = pe.module.address_space.read_u64(relocation.address)?; - let updated = existing as i64 + delta; - pe.module.address_space.write_u64(relocation.address, updated as u64)?; - } - RelocType::HiLo => { - println!("(reloc-hi-lo)"); - let existing = pe.module.address_space.read_u32(relocation.address)?; - let updated = existing + (delta & 0xFFFF_FFFF) as u32; - pe.module.address_space.write_u32(relocation.address, updated)?; - } - RelocType::Hi => { - println!("(reloc-hi)"); - let existing = pe.module.address_space.read_u16(relocation.address)?; - let updated = existing + (((delta >> 16) & 0xFFFF) as u16); - pe.module.address_space.write_u16(relocation.address, updated)?; - } - RelocType::Lo => { - println!("(reloc-lo)"); - let existing = pe.module.address_space.read_u16(relocation.address)?; - let updated = existing + ((delta & 0xFFFF) as u16); - pe.module.address_space.write_u16(relocation.address, updated)?; - } - _ => unimplemented!(), - }; - } - Ok(()) -}