diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 1c9606c6..e4468096 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -12,7 +12,8 @@ namespace bool use_gdb{false}; bool concise_logging{false}; bool verbose_logging{false}; - std::string root_filesystem{"./root"}; + std::string registry_path{"./registry"}; + std::string emulation_root{}; }; void watch_system_objects(windows_emulator& win_emu, const bool cache_logging) @@ -107,7 +108,8 @@ namespace emulator_settings settings{ .application = args[0], - .root_filesystem = options.root_filesystem, + .registry_directory = options.registry_path, + .emulation_root = options.emulation_root, .arguments = parse_arguments(args), .silent_until_main = options.concise_logging, }; @@ -209,14 +211,23 @@ namespace { options.concise_logging = true; } + else if (arg == "-e") + { + if (args.size() < 2) + { + throw std::runtime_error("No emulation root path provided after -e"); + } + arg_it = args.erase(arg_it); + options.emulation_root = args[0]; + } else if (arg == "-r") { if (args.size() < 2) { - throw std::runtime_error("No root path provided after -r"); + throw std::runtime_error("No registry path provided after -r"); } arg_it = args.erase(arg_it); - options.root_filesystem = args[0]; + options.registry_path = args[0]; } else { diff --git a/src/windows-emulator-test/emulation_test_utils.hpp b/src/windows-emulator-test/emulation_test_utils.hpp index b183ccad..f36ce716 100644 --- a/src/windows-emulator-test/emulation_test_utils.hpp +++ b/src/windows-emulator-test/emulation_test_utils.hpp @@ -35,7 +35,7 @@ namespace test inline windows_emulator create_sample_emulator(emulator_settings settings, emulator_callbacks callbacks = {}) { settings.application = "c:/test-sample.exe"; - settings.root_filesystem = get_emulator_root(); + settings.emulation_root = get_emulator_root(); return windows_emulator{std::move(settings), std::move(callbacks)}; } diff --git a/src/windows-emulator/file_system.hpp b/src/windows-emulator/file_system.hpp index 8f8e46b0..d76f3a52 100644 --- a/src/windows-emulator/file_system.hpp +++ b/src/windows-emulator/file_system.hpp @@ -7,7 +7,7 @@ class file_system { public: - file_system(std::filesystem::path root, windows_path working_dir) + file_system(std::filesystem::path root, windows_path working_dir = "C:\\") : root_(std::move(root)), working_dir_(std::move(working_dir)) { @@ -26,6 +26,7 @@ class file_system } #endif + // TODO: Sanitize path to prevent traversal! return this->root_ / full_path.to_portable_path(); } diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 3509b5d8..b739123a 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -1530,7 +1530,7 @@ namespace if (!f->enumeration_state || query_flags & SL_RESTART_SCAN) { f->enumeration_state.emplace(file_enumeration_state{}); - f->enumeration_state->files = scan_directory(c.win_emu.file_sys.translate(f->name)); + f->enumeration_state->files = scan_directory(c.win_emu.file_sys().translate(f->name)); } auto& enum_state = *f->enumeration_state; @@ -2586,7 +2586,7 @@ namespace const emulator_object /*default_casing_table_size*/) { const auto locale_file = - utils::io::read_file(c.win_emu.file_sys.translate(R"(C:\Windows\System32\locale.nls)")); + utils::io::read_file(c.win_emu.file_sys().translate(R"(C:\Windows\System32\locale.nls)")); if (locale_file.empty()) { return STATUS_FILE_INVALID; @@ -2826,14 +2826,14 @@ namespace if (create_disposition & FILE_CREATE) { std::error_code ec{}; - std::filesystem::create_directory(c.win_emu.file_sys.translate(f.name), ec); + create_directory(c.win_emu.file_sys().translate(f.name), ec); if (ec) { return STATUS_ACCESS_DENIED; } } - else if (!std::filesystem::is_directory(c.win_emu.file_sys.translate(f.name))) + else if (!std::filesystem::is_directory(c.win_emu.file_sys().translate(f.name))) { return STATUS_OBJECT_NAME_NOT_FOUND; } @@ -2855,7 +2855,7 @@ namespace FILE* file{}; - const auto error = open_unicode(&file, c.win_emu.file_sys.translate(f.name), mode); + const auto error = open_unicode(&file, c.win_emu.file_sys().translate(f.name), mode); if (!file) { @@ -2900,7 +2900,7 @@ namespace c.win_emu.log.print(color::dark_gray, "--> Querying file attributes: %s\n", u16_to_u8(filename).c_str()); - const auto local_filename = c.win_emu.file_sys.translate(filename).string(); + const auto local_filename = c.win_emu.file_sys().translate(filename).string(); struct _stat64 file_stat{}; if (_stat64(local_filename.c_str(), &file_stat) != 0) diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 168f17a4..479b40a4 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -216,7 +216,9 @@ namespace setup_gdt(emu); - context.registry = registry_manager(win_emu.root_directory / "registry"); + context.registry = + registry_manager(win_emu.get_emulation_root().empty() ? settings.registry_directory + : win_emu.get_emulation_root() / "registry"); context.kusd.setup(settings.use_relative_time); @@ -268,7 +270,7 @@ namespace allocator.make_unicode_string(proc_params.CommandLine, command_line); allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath, - win_emu.file_sys.get_working_directory().u16string()); + win_emu.file_sys().get_working_directory().u16string()); allocator.make_unicode_string(proc_params.ImagePathName, application_str); const auto total_length = allocator.get_next_address() - context.process_params.value(); @@ -280,7 +282,7 @@ namespace apiset_location apiset_loc = apiset_location::file; - if (win_emu.root_directory.empty()) + if (win_emu.get_emulation_root().empty()) { #ifdef OS_WINDOWS apiset_loc = apiset_location::host; @@ -292,7 +294,7 @@ namespace context.peb.access([&](PEB64& peb) { peb.ImageBaseAddress = nullptr; peb.ProcessParameters = context.process_params.ptr(); - peb.ApiSetMap = build_api_set_map(emu, allocator, apiset_loc, win_emu.root_directory).ptr(); + peb.ApiSetMap = build_api_set_map(emu, allocator, apiset_loc, win_emu.get_emulation_root()).ptr(); peb.ProcessHeap = nullptr; peb.ProcessHeaps = nullptr; @@ -825,15 +827,15 @@ std::unique_ptr create_default_x64_emulator() windows_emulator::windows_emulator(const emulator_settings& settings, emulator_callbacks callbacks, std::unique_ptr emu) - : windows_emulator(settings.root_filesystem, std::move(emu)) + : windows_emulator(settings.emulation_root, std::move(emu)) { if (!settings.working_directory.empty()) { - this->file_sys.set_working_directory(settings.working_directory); + this->file_sys().set_working_directory(settings.working_directory); } else { - this->file_sys.set_working_directory(settings.application.parent()); + this->file_sys().set_working_directory(settings.application.parent()); } this->silent_until_main_ = settings.silent_until_main && !settings.disable_logging; @@ -843,12 +845,19 @@ windows_emulator::windows_emulator(const emulator_settings& settings, emulator_c this->setup_process(settings); } -windows_emulator::windows_emulator(const std::filesystem::path& root_path, std::unique_ptr emu) - : root_directory{absolute(root_path)}, - file_sys(root_directory / "filesys", u"C:\\"), +windows_emulator::windows_emulator(const std::filesystem::path& emulation_root, std::unique_ptr emu) + : emulation_root_{emulation_root.empty() ? emulation_root : absolute(emulation_root)}, + file_sys_(emulation_root_.empty() ? emulation_root_ : emulation_root_ / "filesys"), emu_(std::move(emu)), - process_(*emu_, file_sys) + process_(*emu_, file_sys_) { +#ifndef OS_WINDOWS + if (this->get_emulation_root().empty()) + { + throw std::runtime_error("Emulation root directory can not be empty!"); + } +#endif + this->setup_hooks(); } @@ -857,7 +866,7 @@ void windows_emulator::setup_process(const emulator_settings& settings) auto& emu = this->emu(); auto& context = this->process(); - context.mod_manager = module_manager(emu, this->file_sys); // TODO: Cleanup module manager + context.mod_manager = module_manager(emu, this->file_sys()); // TODO: Cleanup module manager setup_context(*this, settings); @@ -1119,7 +1128,7 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count) void windows_emulator::serialize(utils::buffer_serializer& buffer) const { buffer.write(this->use_relative_time_); - this->file_sys.serialize(buffer); + this->file_sys().serialize(buffer); this->emu().serialize(buffer); this->process_.serialize(buffer); this->dispatcher_.serialize(buffer); @@ -1136,7 +1145,7 @@ void windows_emulator::deserialize(utils::buffer_deserializer& buffer) }); buffer.read(this->use_relative_time_); - this->file_sys.deserialize(buffer); + this->file_sys().deserialize(buffer); this->emu().deserialize(buffer); this->process_.deserialize(buffer); @@ -1148,7 +1157,7 @@ void windows_emulator::save_snapshot() this->emu().save_snapshot(); utils::buffer_serializer serializer{}; - this->file_sys.serialize(serializer); + this->file_sys().serialize(serializer); this->process_.serialize(serializer); this->process_snapshot_ = serializer.move_buffer(); @@ -1168,7 +1177,7 @@ void windows_emulator::restore_snapshot() this->emu().restore_snapshot(); utils::buffer_deserializer deserializer{this->process_snapshot_}; - this->file_sys.deserialize(deserializer); + this->file_sys().deserialize(deserializer); this->process_.deserialize(deserializer); // this->process_ = *this->process_snapshot_; } diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 914b868b..e88a522f 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -29,14 +29,15 @@ struct emulator_settings { windows_path application{}; windows_path working_directory{}; - std::filesystem::path root_filesystem{}; + std::filesystem::path registry_directory{"./registry"}; + std::filesystem::path emulation_root{}; std::vector arguments{}; bool disable_logging{false}; bool silent_until_main{false}; bool use_relative_time{false}; }; -enum class apiset_location +enum class apiset_location : uint8_t { host, file, @@ -47,7 +48,7 @@ enum class apiset_location class windows_emulator { public: - windows_emulator(const std::filesystem::path& root_path, + windows_emulator(const std::filesystem::path& emulation_root, std::unique_ptr emu = create_default_x64_emulator()); windows_emulator(const emulator_settings& settings, emulator_callbacks callbacks = {}, std::unique_ptr emu = create_default_x64_emulator()); @@ -133,10 +134,25 @@ class windows_emulator return this->callbacks_; } - std::filesystem::path root_directory{}; - file_system file_sys; + file_system& file_sys() + { + return this->file_sys_; + } + + const file_system& file_sys() const + { + return this->file_sys_; + } + + const std::filesystem::path& get_emulation_root() + { + return this->emulation_root_; + } private: + std::filesystem::path emulation_root_{}; + file_system file_sys_; + emulator_callbacks callbacks_{}; bool use_relative_time_{false}; bool silent_until_main_{false};