From 5b67a53e9c5392d057145400ca3722d926a796ce Mon Sep 17 00:00:00 2001 From: fed <58637860+fedddddd@users.noreply.github.com> Date: Thu, 16 Feb 2023 19:09:44 +0100 Subject: [PATCH] Make lua vms safer --- src/client/component/filesystem.hpp | 11 +++++ src/client/component/ui_scripting.cpp | 53 ++++++++++++++--------- src/client/game/scripting/lua/context.cpp | 42 +++++++++++++----- 3 files changed, 76 insertions(+), 30 deletions(-) diff --git a/src/client/component/filesystem.hpp b/src/client/component/filesystem.hpp index 978258f7..bdc9f506 100644 --- a/src/client/component/filesystem.hpp +++ b/src/client/component/filesystem.hpp @@ -17,4 +17,15 @@ namespace filesystem std::string get_safe_path(const std::filesystem::path& path); bool safe_write_file(const std::string& file, const std::string& data, bool append = false); + + template + std::function + safe_io_func(const std::function& func) + { + return [func](const std::string& path) + { + const auto safe_path = filesystem::get_safe_path(path); + return func(safe_path); + }; + } } diff --git a/src/client/component/ui_scripting.cpp b/src/client/component/ui_scripting.cpp index 2f2fa360..a384907d 100644 --- a/src/client/component/ui_scripting.cpp +++ b/src/client/component/ui_scripting.cpp @@ -142,17 +142,6 @@ namespace ui_scripting } } - template - std::function - safe_io_func(const std::function& func) - { - return [func](const std::string& path) - { - const auto safe_path = filesystem::get_safe_path(path); - return func(safe_path); - }; - } - script_value json_to_lua(const nlohmann::json& json) { if (json.is_object()) @@ -231,16 +220,17 @@ namespace ui_scripting { const auto lua = get_globals(); - lua["io"]["fileexists"] = safe_io_func(utils::io::file_exists); + lua["io"] = table(); + lua["io"]["fileexists"] = filesystem::safe_io_func(utils::io::file_exists); lua["io"]["writefile"] = filesystem::safe_write_file; - lua["io"]["filesize"] = safe_io_func(utils::io::file_size); - lua["io"]["createdirectory"] = safe_io_func(utils::io::create_directory); - lua["io"]["directoryexists"] = safe_io_func(utils::io::directory_exists); - lua["io"]["directoryisempty"] = safe_io_func(utils::io::directory_is_empty); - lua["io"]["listfiles"] = safe_io_func>(utils::io::list_files); - lua["io"]["removefile"] = safe_io_func(utils::io::remove_file); - lua["io"]["removedirectory"] = safe_io_func(utils::io::remove_directory); - lua["io"]["readfile"] = safe_io_func( + lua["io"]["filesize"] = filesystem::safe_io_func(utils::io::file_size); + lua["io"]["createdirectory"] = filesystem::safe_io_func(utils::io::create_directory); + lua["io"]["directoryexists"] = filesystem::safe_io_func(utils::io::directory_exists); + lua["io"]["directoryisempty"] = filesystem::safe_io_func(utils::io::directory_is_empty); + lua["io"]["listfiles"] = filesystem::safe_io_func>(utils::io::list_files); + lua["io"]["removefile"] = filesystem::safe_io_func(utils::io::remove_file); + lua["io"]["removedirectory"] = filesystem::safe_io_func(utils::io::remove_directory); + lua["io"]["readfile"] = filesystem::safe_io_func( static_cast(utils::io::read_file)); using game = table; @@ -683,6 +673,29 @@ namespace ui_scripting hks_package_require_hook.create(0x1402B4DA0, hks_package_require_stub); hks_start_hook.create(0x140328BE0, hks_start_stub); hks_shutdown_hook.create(0x1403203B0, hks_shutdown_stub); + + // remove unsafe functions + utils::hook::nop(0x1402D885A, 1); + utils::hook::jump(0x14031E700, 0x1402D86E0); + + utils::hook::jump(0x1402BFCC0, removed_function_stub); // io + utils::hook::jump(0x14017EE60, removed_function_stub); // profile + utils::hook::jump(0x1402C0150, removed_function_stub); // os + utils::hook::jump(0x14017F730, removed_function_stub); // serialize + utils::hook::jump(0x1402C0FF0, removed_function_stub); // hks + utils::hook::jump(0x14017EC60, removed_function_stub); // debug + utils::hook::nop(0x1402BFC48, 5); // coroutine + + utils::hook::jump(0x1402B7FD0, removed_function_stub); + utils::hook::jump(0x1402B7C40, removed_function_stub); + utils::hook::jump(0x1402BAC30, removed_function_stub); + + utils::hook::jump(0x1402B5480, removed_function_stub); + utils::hook::jump(0x1402C2030, removed_function_stub); + utils::hook::jump(0x1402C2180, removed_function_stub); + + utils::hook::jump(0x1402B6F70, removed_function_stub); + utils::hook::jump(0x1402BD890, removed_function_stub); } }; } diff --git a/src/client/game/scripting/lua/context.cpp b/src/client/game/scripting/lua/context.cpp index fba42a88..522262e0 100644 --- a/src/client/game/scripting/lua/context.cpp +++ b/src/client/game/scripting/lua/context.cpp @@ -12,9 +12,12 @@ #include "component/mods.hpp" #include "component/localized_strings.hpp" #include "component/scheduler.hpp" +#include "component/filesystem.hpp" #include "game/ui_scripting/execution.hpp" +#include "lualib.h" + #include #include @@ -39,6 +42,22 @@ namespace scripting::lua ); } + void remove_unsafe_functions(sol::state& state) + { + state["package"]["searchers"][3] = sol::lua_value{state, sol::lua_nil}; + state["package"]["searchers"][4] = sol::lua_value{state, sol::lua_nil}; + + state["os"]["execute"] = sol::lua_value{state, sol::lua_nil}; + state["os"]["exit"] = sol::lua_value{state, sol::lua_nil}; + state["os"]["getenv"] = sol::lua_value{state, sol::lua_nil}; + state["os"]["remove"] = sol::lua_value{state, sol::lua_nil}; + state["os"]["rename"] = sol::lua_value{state, sol::lua_nil}; + state["os"]["setlocale"] = sol::lua_value{state, sol::lua_nil}; + state["os"]["tmpname"] = sol::lua_value{state, sol::lua_nil}; + + state["package"]["loadlib"] = sol::lua_value{state, sol::lua_nil}; + } + void setup_json(sol::state& state) { const auto json = state.safe_script(json_script, &sol::script_pass_on_error); @@ -48,15 +67,18 @@ namespace scripting::lua void setup_io(sol::state& state) { - state["io"]["fileexists"] = utils::io::file_exists; - state["io"]["writefile"] = utils::io::write_file; - state["io"]["filesize"] = utils::io::file_size; - state["io"]["createdirectory"] = utils::io::create_directory; - state["io"]["directoryexists"] = utils::io::directory_exists; - state["io"]["directoryisempty"] = utils::io::directory_is_empty; - state["io"]["listfiles"] = utils::io::list_files; - state["io"]["copyfolder"] = utils::io::copy_folder; - state["io"]["readfile"] = static_cast(utils::io::read_file); + state["io"] = sol::table::create(state.lua_state()); + state["io"]["fileexists"] = filesystem::safe_io_func(utils::io::file_exists); + state["io"]["writefile"] = filesystem::safe_write_file; + state["io"]["filesize"] = filesystem::safe_io_func(utils::io::file_size); + state["io"]["createdirectory"] = filesystem::safe_io_func(utils::io::create_directory); + state["io"]["directoryexists"] = filesystem::safe_io_func(utils::io::directory_exists); + state["io"]["directoryisempty"] = filesystem::safe_io_func(utils::io::directory_is_empty); + state["io"]["listfiles"] = filesystem::safe_io_func>(utils::io::list_files); + state["io"]["removefile"] = filesystem::safe_io_func(utils::io::remove_file); + state["io"]["removedirectory"] = filesystem::safe_io_func(utils::io::remove_directory); + state["io"]["readfile"] = filesystem::safe_io_func( + static_cast(utils::io::read_file)); } void setup_vector_type(sol::state& state) @@ -807,7 +829,6 @@ namespace scripting::lua { this->state_.open_libraries(sol::lib::base, sol::lib::package, - sol::lib::io, sol::lib::string, sol::lib::os, sol::lib::math, @@ -830,6 +851,7 @@ namespace scripting::lua return this->folder_; }; + remove_unsafe_functions(this->state_); setup_io(this->state_); setup_json(this->state_); setup_vector_type(this->state_);