├── .editorconfig ├── .github └── workflows │ ├── ci.yml │ └── print-info.yml ├── .gitignore ├── .gitmodules ├── .idea ├── .gitignore ├── Koaloader.iml ├── cmake.xml ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── misc.xml └── modules.xml ├── CMakeLists.txt ├── README.adoc ├── UNLICENSE.txt ├── build.ps1 ├── res └── Koaloader.config.json └── src ├── koaloader ├── koaloader.cpp └── koaloader.hpp └── main.cpp /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = crlf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | max_line_length = 120 10 | tab_width = 4 11 | ij_continuation_indent_size = 8 12 | ij_formatter_off_tag = @formatter:off 13 | ij_formatter_on_tag = @formatter:on 14 | ij_formatter_tags_enabled = false 15 | ij_smart_tabs = false 16 | ij_visual_guides = none 17 | ij_wrap_on_typing = false 18 | 19 | [.editorconfig] 20 | ij_editorconfig_align_group_field_declarations = false 21 | ij_editorconfig_space_after_colon = false 22 | ij_editorconfig_space_after_comma = true 23 | ij_editorconfig_space_before_colon = false 24 | ij_editorconfig_space_before_comma = false 25 | ij_editorconfig_spaces_around_assignment_operators = true 26 | 27 | [{*.c,*.c++,*.cc,*.cp,*.cpp,*.cu,*.cuh,*.cxx,*.h,*.h++,*.hh,*.hp,*.hpp,*.hxx,*.i,*.icc,*.ii,*.inl,*.ino,*.ipp,*.m,*.mm,*.pch,*.tcc,*.tpp,version.gen.rc}] 28 | max_line_length = 100 29 | ij_c_add_brief_tag = false 30 | ij_c_add_getter_prefix = true 31 | ij_c_add_setter_prefix = true 32 | ij_c_align_dictionary_pair_values = false 33 | ij_c_align_group_field_declarations = false 34 | ij_c_align_init_list_in_columns = true 35 | ij_c_align_multiline_array_initializer_expression = true 36 | ij_c_align_multiline_assignment = true 37 | ij_c_align_multiline_binary_operation = true 38 | ij_c_align_multiline_chained_methods = false 39 | ij_c_align_multiline_for = true 40 | ij_c_align_multiline_ternary_operation = false 41 | ij_c_array_initializer_comma_on_next_line = false 42 | ij_c_array_initializer_new_line_after_left_brace = false 43 | ij_c_array_initializer_right_brace_on_new_line = false 44 | ij_c_array_initializer_wrap = normal 45 | ij_c_assignment_wrap = off 46 | ij_c_binary_operation_sign_on_next_line = false 47 | ij_c_binary_operation_wrap = normal 48 | ij_c_blank_lines_after_class_header = 0 49 | ij_c_blank_lines_after_imports = 1 50 | ij_c_blank_lines_around_class = 1 51 | ij_c_blank_lines_around_field = 0 52 | ij_c_blank_lines_around_field_in_interface = 0 53 | ij_c_blank_lines_around_method = 1 54 | ij_c_blank_lines_around_method_in_interface = 1 55 | ij_c_blank_lines_around_namespace = 0 56 | ij_c_blank_lines_around_properties_in_declaration = 0 57 | ij_c_blank_lines_around_properties_in_interface = 0 58 | ij_c_blank_lines_before_imports = 1 59 | ij_c_blank_lines_before_method_body = 0 60 | ij_c_block_brace_placement = end_of_line 61 | ij_c_block_brace_style = end_of_line 62 | ij_c_block_comment_at_first_column = true 63 | ij_c_catch_on_new_line = false 64 | ij_c_class_brace_style = end_of_line 65 | ij_c_class_constructor_init_list_align_multiline = true 66 | ij_c_class_constructor_init_list_comma_on_next_line = false 67 | ij_c_class_constructor_init_list_new_line_after_colon = never 68 | ij_c_class_constructor_init_list_new_line_before_colon = if_long 69 | ij_c_class_constructor_init_list_wrap = normal 70 | ij_c_copy_is_deep = false 71 | ij_c_create_interface_for_categories = true 72 | ij_c_declare_generated_methods = true 73 | ij_c_description_include_member_names = true 74 | ij_c_discharged_short_ternary_operator = false 75 | ij_c_do_not_add_breaks = false 76 | ij_c_do_while_brace_force = never 77 | ij_c_else_on_new_line = false 78 | ij_c_enum_constants_comma_on_next_line = false 79 | ij_c_enum_constants_wrap = on_every_item 80 | ij_c_for_brace_force = never 81 | ij_c_for_statement_new_line_after_left_paren = false 82 | ij_c_for_statement_right_paren_on_new_line = false 83 | ij_c_for_statement_wrap = off 84 | ij_c_function_brace_placement = end_of_line 85 | ij_c_function_call_arguments_align_multiline = false 86 | ij_c_function_call_arguments_align_multiline_pars = false 87 | ij_c_function_call_arguments_comma_on_next_line = false 88 | ij_c_function_call_arguments_new_line_after_lpar = false 89 | ij_c_function_call_arguments_new_line_before_rpar = false 90 | ij_c_function_call_arguments_wrap = normal 91 | ij_c_function_non_top_after_return_type_wrap = normal 92 | ij_c_function_parameters_align_multiline = true 93 | ij_c_function_parameters_align_multiline_pars = false 94 | ij_c_function_parameters_comma_on_next_line = false 95 | ij_c_function_parameters_new_line_after_lpar = true 96 | ij_c_function_parameters_new_line_before_rpar = true 97 | ij_c_function_parameters_wrap = normal 98 | ij_c_function_top_after_return_type_wrap = normal 99 | ij_c_generate_additional_eq_operators = true 100 | ij_c_generate_additional_rel_operators = true 101 | ij_c_generate_class_constructor = true 102 | ij_c_generate_comparison_operators_use_std_tie = false 103 | ij_c_generate_instance_variables_for_properties = ask 104 | ij_c_generate_operators_as_members = true 105 | ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT} 106 | ij_c_if_brace_force = never 107 | ij_c_in_line_short_ternary_operator = true 108 | ij_c_indent_block_comment = true 109 | ij_c_indent_c_struct_members = 4 110 | ij_c_indent_case_from_switch = true 111 | ij_c_indent_class_members = 4 112 | ij_c_indent_directive_as_code = false 113 | ij_c_indent_implementation_members = 0 114 | ij_c_indent_inside_code_block = 4 115 | ij_c_indent_interface_members = 0 116 | ij_c_indent_interface_members_except_ivars_block = false 117 | ij_c_indent_namespace_members = 4 118 | ij_c_indent_preprocessor_directive = 0 119 | ij_c_indent_visibility_keywords = 0 120 | ij_c_insert_override = true 121 | ij_c_insert_virtual_with_override = false 122 | ij_c_introduce_auto_vars = false 123 | ij_c_introduce_const_params = false 124 | ij_c_introduce_const_vars = false 125 | ij_c_introduce_generate_property = false 126 | ij_c_introduce_generate_synthesize = true 127 | ij_c_introduce_globals_to_header = true 128 | ij_c_introduce_prop_to_private_category = false 129 | ij_c_introduce_static_consts = true 130 | ij_c_introduce_use_ns_types = false 131 | ij_c_ivars_prefix = _ 132 | ij_c_keep_blank_lines_before_end = 2 133 | ij_c_keep_blank_lines_before_right_brace = 2 134 | ij_c_keep_blank_lines_in_code = 2 135 | ij_c_keep_blank_lines_in_declarations = 2 136 | ij_c_keep_case_expressions_in_one_line = false 137 | ij_c_keep_control_statement_in_one_line = true 138 | ij_c_keep_directive_at_first_column = true 139 | ij_c_keep_first_column_comment = true 140 | ij_c_keep_line_breaks = true 141 | ij_c_keep_nested_namespaces_in_one_line = false 142 | ij_c_keep_simple_blocks_in_one_line = true 143 | ij_c_keep_simple_methods_in_one_line = true 144 | ij_c_keep_structures_in_one_line = true 145 | ij_c_lambda_capture_list_align_multiline = false 146 | ij_c_lambda_capture_list_align_multiline_bracket = false 147 | ij_c_lambda_capture_list_comma_on_next_line = false 148 | ij_c_lambda_capture_list_new_line_after_lbracket = false 149 | ij_c_lambda_capture_list_new_line_before_rbracket = false 150 | ij_c_lambda_capture_list_wrap = off 151 | ij_c_line_comment_add_space = false 152 | ij_c_line_comment_at_first_column = true 153 | ij_c_method_brace_placement = end_of_line 154 | ij_c_method_call_arguments_align_by_colons = true 155 | ij_c_method_call_arguments_align_multiline = false 156 | ij_c_method_call_arguments_special_dictionary_pairs_treatment = true 157 | ij_c_method_call_arguments_wrap = off 158 | ij_c_method_call_chain_wrap = off 159 | ij_c_method_parameters_align_by_colons = true 160 | ij_c_method_parameters_align_multiline = false 161 | ij_c_method_parameters_wrap = off 162 | ij_c_namespace_brace_placement = end_of_line 163 | ij_c_parentheses_expression_new_line_after_left_paren = false 164 | ij_c_parentheses_expression_right_paren_on_new_line = false 165 | ij_c_place_assignment_sign_on_next_line = false 166 | ij_c_property_nonatomic = true 167 | ij_c_put_ivars_to_implementation = true 168 | ij_c_refactor_compatibility_aliases_and_classes = true 169 | ij_c_refactor_properties_and_ivars = true 170 | ij_c_release_style = ivar 171 | ij_c_retain_object_parameters_in_constructor = true 172 | ij_c_semicolon_after_method_signature = false 173 | ij_c_shift_operation_align_multiline = true 174 | ij_c_shift_operation_wrap = normal 175 | ij_c_show_non_virtual_functions = false 176 | ij_c_space_after_colon = true 177 | ij_c_space_after_colon_in_foreach = true 178 | ij_c_space_after_colon_in_selector = false 179 | ij_c_space_after_comma = true 180 | ij_c_space_after_cup_in_blocks = false 181 | ij_c_space_after_dictionary_literal_colon = true 182 | ij_c_space_after_for_semicolon = true 183 | ij_c_space_after_init_list_colon = true 184 | ij_c_space_after_method_parameter_type_parentheses = false 185 | ij_c_space_after_method_return_type_parentheses = false 186 | ij_c_space_after_pointer_in_declaration = true 187 | ij_c_space_after_quest = true 188 | ij_c_space_after_reference_in_declaration = true 189 | ij_c_space_after_reference_in_rvalue = false 190 | ij_c_space_after_structures_rbrace = true 191 | ij_c_space_after_superclass_colon = true 192 | ij_c_space_after_type_cast = true 193 | ij_c_space_after_visibility_sign_in_method_declaration = true 194 | ij_c_space_before_autorelease_pool_lbrace = true 195 | ij_c_space_before_catch_keyword = true 196 | ij_c_space_before_catch_left_brace = true 197 | ij_c_space_before_catch_parentheses = true 198 | ij_c_space_before_category_parentheses = true 199 | ij_c_space_before_chained_send_message = true 200 | ij_c_space_before_class_left_brace = true 201 | ij_c_space_before_colon = true 202 | ij_c_space_before_colon_in_foreach = false 203 | ij_c_space_before_comma = false 204 | ij_c_space_before_dictionary_literal_colon = false 205 | ij_c_space_before_do_left_brace = true 206 | ij_c_space_before_else_keyword = true 207 | ij_c_space_before_else_left_brace = true 208 | ij_c_space_before_for_left_brace = true 209 | ij_c_space_before_for_parentheses = true 210 | ij_c_space_before_for_semicolon = false 211 | ij_c_space_before_if_left_brace = true 212 | ij_c_space_before_if_parentheses = true 213 | ij_c_space_before_init_list = false 214 | ij_c_space_before_init_list_colon = true 215 | ij_c_space_before_method_call_parentheses = false 216 | ij_c_space_before_method_left_brace = true 217 | ij_c_space_before_method_parentheses = false 218 | ij_c_space_before_namespace_lbrace = true 219 | ij_c_space_before_pointer_in_declaration = false 220 | ij_c_space_before_property_attributes_parentheses = false 221 | ij_c_space_before_protocols_brackets = true 222 | ij_c_space_before_quest = true 223 | ij_c_space_before_reference_in_declaration = false 224 | ij_c_space_before_superclass_colon = true 225 | ij_c_space_before_switch_left_brace = true 226 | ij_c_space_before_switch_parentheses = true 227 | ij_c_space_before_template_call_lt = false 228 | ij_c_space_before_template_declaration_lt = false 229 | ij_c_space_before_try_left_brace = true 230 | ij_c_space_before_while_keyword = true 231 | ij_c_space_before_while_left_brace = true 232 | ij_c_space_before_while_parentheses = true 233 | ij_c_space_between_adjacent_brackets = false 234 | ij_c_space_between_operator_and_punctuator = false 235 | ij_c_space_within_empty_array_initializer_braces = false 236 | ij_c_spaces_around_additive_operators = true 237 | ij_c_spaces_around_assignment_operators = true 238 | ij_c_spaces_around_bitwise_operators = true 239 | ij_c_spaces_around_equality_operators = true 240 | ij_c_spaces_around_lambda_arrow = true 241 | ij_c_spaces_around_logical_operators = true 242 | ij_c_spaces_around_multiplicative_operators = true 243 | ij_c_spaces_around_pm_operators = false 244 | ij_c_spaces_around_relational_operators = true 245 | ij_c_spaces_around_shift_operators = true 246 | ij_c_spaces_around_unary_operator = false 247 | ij_c_spaces_within_array_initializer_braces = true 248 | ij_c_spaces_within_braces = true 249 | ij_c_spaces_within_brackets = false 250 | ij_c_spaces_within_cast_parentheses = false 251 | ij_c_spaces_within_catch_parentheses = false 252 | ij_c_spaces_within_category_parentheses = false 253 | ij_c_spaces_within_empty_braces = false 254 | ij_c_spaces_within_empty_function_call_parentheses = false 255 | ij_c_spaces_within_empty_function_declaration_parentheses = false 256 | ij_c_spaces_within_empty_lambda_capture_list_bracket = false 257 | ij_c_spaces_within_empty_template_call_ltgt = false 258 | ij_c_spaces_within_empty_template_declaration_ltgt = false 259 | ij_c_spaces_within_for_parentheses = false 260 | ij_c_spaces_within_function_call_parentheses = false 261 | ij_c_spaces_within_function_declaration_parentheses = false 262 | ij_c_spaces_within_if_parentheses = false 263 | ij_c_spaces_within_lambda_capture_list_bracket = false 264 | ij_c_spaces_within_method_parameter_type_parentheses = false 265 | ij_c_spaces_within_method_return_type_parentheses = false 266 | ij_c_spaces_within_parentheses = false 267 | ij_c_spaces_within_property_attributes_parentheses = false 268 | ij_c_spaces_within_protocols_brackets = false 269 | ij_c_spaces_within_send_message_brackets = false 270 | ij_c_spaces_within_switch_parentheses = false 271 | ij_c_spaces_within_template_call_ltgt = false 272 | ij_c_spaces_within_template_declaration_ltgt = false 273 | ij_c_spaces_within_template_double_gt = true 274 | ij_c_spaces_within_while_parentheses = false 275 | ij_c_special_else_if_treatment = true 276 | ij_c_superclass_list_after_colon = never 277 | ij_c_superclass_list_align_multiline = true 278 | ij_c_superclass_list_before_colon = if_long 279 | ij_c_superclass_list_comma_on_next_line = false 280 | ij_c_superclass_list_wrap = on_every_item 281 | ij_c_tag_prefix_of_block_comment = at 282 | ij_c_tag_prefix_of_line_comment = back_slash 283 | ij_c_template_call_arguments_align_multiline = false 284 | ij_c_template_call_arguments_align_multiline_pars = false 285 | ij_c_template_call_arguments_comma_on_next_line = false 286 | ij_c_template_call_arguments_new_line_after_lt = false 287 | ij_c_template_call_arguments_new_line_before_gt = false 288 | ij_c_template_call_arguments_wrap = off 289 | ij_c_template_declaration_function_body_indent = false 290 | ij_c_template_declaration_function_wrap = split_into_lines 291 | ij_c_template_declaration_struct_body_indent = false 292 | ij_c_template_declaration_struct_wrap = split_into_lines 293 | ij_c_template_parameters_align_multiline = false 294 | ij_c_template_parameters_align_multiline_pars = false 295 | ij_c_template_parameters_comma_on_next_line = false 296 | ij_c_template_parameters_new_line_after_lt = false 297 | ij_c_template_parameters_new_line_before_gt = false 298 | ij_c_template_parameters_wrap = off 299 | ij_c_ternary_operation_signs_on_next_line = true 300 | ij_c_ternary_operation_wrap = normal 301 | ij_c_type_qualifiers_placement = before 302 | ij_c_use_modern_casts = true 303 | ij_c_use_setters_in_constructor = true 304 | ij_c_while_brace_force = never 305 | ij_c_while_on_new_line = false 306 | ij_c_wrap_property_declaration = off 307 | 308 | [{*.cmake,CMakeLists.txt}] 309 | ij_cmake_align_multiline_parameters_in_calls = false 310 | ij_cmake_force_commands_case = 2 311 | ij_cmake_keep_blank_lines_in_code = 2 312 | ij_cmake_space_before_for_parentheses = true 313 | ij_cmake_space_before_if_parentheses = true 314 | ij_cmake_space_before_method_call_parentheses = false 315 | ij_cmake_space_before_method_parentheses = false 316 | ij_cmake_space_before_while_parentheses = true 317 | ij_cmake_spaces_within_for_parentheses = false 318 | ij_cmake_spaces_within_if_parentheses = false 319 | ij_cmake_spaces_within_method_call_parentheses = false 320 | ij_cmake_spaces_within_method_parentheses = false 321 | ij_cmake_spaces_within_while_parentheses = false 322 | 323 | [{*.har,*.json,*.jsonc}] 324 | indent_size = 2 325 | ij_json_keep_blank_lines_in_code = 1 326 | ij_json_keep_indents_on_empty_lines = false 327 | ij_json_keep_line_breaks = true 328 | ij_json_space_after_colon = true 329 | ij_json_space_after_comma = true 330 | ij_json_space_before_colon = true 331 | ij_json_space_before_comma = false 332 | ij_json_spaces_within_braces = false 333 | ij_json_spaces_within_brackets = false 334 | ij_json_wrap_long_lines = false 335 | 336 | [{*.md,*.apinotes,*.yaml,*.yml,.clang-format,.clang-tidy,_clang-format}] 337 | indent_size = 2 338 | max_line_length = 1000 339 | 340 | 341 | [/src/exports/**] 342 | max_line_length = 1000 343 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | on: push 3 | 4 | jobs: 5 | ci: 6 | name: CI 7 | uses: acidicoala/KoalaBox/.github/workflows/build-and-package.yml@15d5cfc2e515bc72e47da6c0c563820cff98551f 8 | permissions: 9 | contents: write 10 | with: 11 | modules: >- 12 | [ 13 | "audioses", 14 | "d3d9", 15 | "d3d10", 16 | "d3d11", 17 | "dinput8", 18 | "dwmapi", 19 | "dxgi", 20 | "glu32", 21 | "hid", 22 | "iphlpapi", 23 | "msasn1", 24 | "msimg32", 25 | "mswsock", 26 | "opengl32", 27 | "profapi", 28 | "propsys", 29 | "textshaping", 30 | "version", 31 | "winhttp", 32 | "wldp", 33 | "winmm", 34 | "xinput9_1_0" 35 | ] 36 | 37 | zip_command: > 38 | cp res/Koaloader.config.json artifacts/Koaloader.config.json && 39 | cd artifacts && 40 | zip ../$ZIP_NAME ./* -r 41 | 42 | config: Release 43 | -------------------------------------------------------------------------------- /.github/workflows/print-info.yml: -------------------------------------------------------------------------------- 1 | name: Print information 2 | on: workflow_dispatch 3 | 4 | jobs: 5 | print_dlls: 6 | name: Print system DLLs 7 | runs-on: windows-2022 8 | steps: 9 | - name: Print 64-bit system DLLs 10 | run: ls C:/Windows/System32 11 | 12 | - name: Print 32-bit system DLLs 13 | run: ls C:/Windows/SysWOW64 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "KoalaBox"] 2 | path = KoalaBox 3 | url = ../../acidicoala/KoalaBox 4 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | /dictionaries/ 7 | vcs.xml -------------------------------------------------------------------------------- /.idea/Koaloader.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/cmake.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 17 | 18 | 20 | 21 | 22 | 24 | 25 | 26 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.24) 2 | 3 | project(Koaloader VERSION 3.0.2) 4 | 5 | include(KoalaBox/cmake/KoalaBox.cmake) 6 | 7 | add_subdirectory(KoalaBox EXCLUDE_FROM_ALL) 8 | 9 | # Get module variable 10 | SET(MODULE "" CACHE STRING "Some user-specified option") 11 | if (NOT MODULE) 12 | message(FATAL_ERROR "Option 'MODULE' must be set") 13 | endif () 14 | 15 | configure_version_resource("https://github.com/acidicoala/Koaloader") 16 | 17 | # Setup linker exports 18 | 19 | set( 20 | KOALOADER_SOURCES 21 | src/koaloader/koaloader.cpp 22 | src/koaloader/koaloader.hpp 23 | src/main.cpp 24 | ) 25 | 26 | configure_linker_exports( 27 | FORWARDED_DLL "C:/Windows/System32/${MODULE}" 28 | INPUT_SOURCES_DIR "" 29 | INPUT_DLLS "C:/Windows/System32/${MODULE}.dll" 30 | DEP_SOURCES "${KOALOADER_SOURCES}" 31 | ) 32 | 33 | configure_build_config() 34 | 35 | add_library(Koaloader SHARED ${KOALOADER_SOURCES} ${GENERATED_LINKER_EXPORTS} ${VERSION_RESOURCE}) 36 | 37 | configure_output_name(${MODULE}) 38 | 39 | configure_include_directories() 40 | 41 | target_link_libraries(Koaloader PRIVATE KoalaBox) 42 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = 🐨 Koaloader 📥 2 | 3 | A collection of DLLs that use search order hijacking to automatically inject specified DLLs. 4 | 5 | == 🔗 Links 6 | 7 | https://cs.rin.ru/forum/viewtopic.php?p=2536753#p2536753[Official forum topic] 8 | 9 | == 🚀 Usage 10 | 11 | Simply place one of the proxy dlls where a process is attempting to load it and set up the config file to load the DLLs that you wish to inject. 12 | 13 | === 📚 Supported proxies 14 | 15 | NOTE: ➕ If you wish to see another proxy DLL supported, feel free to request it in the official forum topic, specifying the DLL name and describing its use case. 16 | 17 | .Click to see all proxies 18 | [%collapsible] 19 | ==== 20 | * [x] *audioses.dll* 21 | * [x] *d3d9.dll* 22 | * [x] *d3d10.dll* 23 | * [x] *d3d11.dll* 24 | * [x] *dinput8.dll* 25 | * [x] *dwmapi.dll* 26 | * [x] *dxgi.dll* 27 | * [x] *glu32.dll* 28 | * [x] *hid.dll* 29 | * [x] *iphlpapi.dll* 30 | * [x] *msasn1.dll* 31 | * [x] *msimg32.dll* 32 | * [x] *mswsock.dll* 33 | * [x] *opengl32.dll* 34 | * [x] *profapi.dll* 35 | * [x] *propsys.dll* 36 | * [x] *textshaping.dll* 37 | * [x] *version.dll* 38 | * [x] *winhttp.dll* 39 | * [x] *wldp.dll* 40 | * [x] *winmm.dll* 41 | * [x] *xinput9_1_0.dll* 42 | ==== 43 | 44 | == ⚙ Configuration 45 | 46 | :fn-search-dirs: search directoriesfootnote:fn-search-dirs[Search directories include the directory where Koaloader DLL is located as well as the working directory of the target process.] 47 | 48 | Koaloader comes with a configuration file `Koaloader.config.json`, which will be the same for any proxy dll. 49 | The config file conforms to the standard JSON format. 50 | The description of each available option is presented below: 51 | 52 | `logging`:: 53 | Enables or disables logging into a `Koaloader.log` file. 54 | Possible values: `true`, `false` (default). 55 | 56 | `enabled`:: 57 | Entirely enables or disables Koaloader injection. 58 | Can be used to quickly disable Koaloader without modifying files on disk. 59 | Possible values: `true` (default), `false`. 60 | 61 | `auto_load`:: Enables or disables automatic loading of well-known DLLs. 62 | This can be used to automatically inject DLLs without `Koaloader.config.json` config file. 63 | When enabled, Koaloader will first try to find a well-known DLL in parent directories of the {fn-search-dirs}. 64 | If it failed to do so, it will recursively go through all files in {fn-search-dirs} directory and search for files with well-known file names. 65 | Default: `true`. 66 | A list of well-known filenames (Names ending in 32 and 64 are loaded only by 32-bit and 64-bit binaries respectively): 67 | * `Unlocker.dll`, `Unlocker32.dll`, `Unlocker64.dll` 68 | * `Lyptus.dll`, `Lyptus32.dll`, `Lyptus64.dll` 69 | * `ScreamAPI.dll`,`ScreamAPI32.dll`,`ScreamAPI64.dll` 70 | * `SmokeAPI.dll`,`SmokeAPI32.dll`,`SmokeAPI64.dll` 71 | * `UplayR1Unlocker.dll`, `UplayR1Unlocker32.dll`, `UplayR1Unlocker64.dll` 72 | * `UplayR2Unlocker.dll`, `UplayR2Unlocker32.dll`, `UplayR2Unlocker64.dll` 73 | 74 | `targets`:: 75 | A list of strings that specify targeted executables. 76 | This can be used to prevent unintended loading by irrelevant executables. 77 | Koaloader will inject modules if, and only if: 78 | * The list of targets is empty, **or** 79 | * The list of targets includes an executable that has loaded Koaloader. 80 | 81 | `modules`:: A list of objects that describe modules that will be loaded in the order they were defined. 82 | Each object has the following properties: 83 | + 84 | [horizontal] 85 | `path`::: A string that specifies absolute or relative path to a DLL. 86 | The relative path is with respect to the working directory, which may be different from the executable directory. 87 | `required`::: A boolean that marks the module as required for loading. 88 | This can be used to specify behaviour when Koaloader fails to load a given module. 89 | Failure to load required modules will result in a crash with message box, whereas in not required modules Koaloader will simply print the error in the log file. 90 | Default: `true`. 91 | 92 | You can refer to the following config as an example. 93 | 94 | [sidebar] 95 | 96 | -- 97 | 98 | Here we have defined 2 DLLs to load: 99 | 100 | * `target.dll` - via a path that is relative to the current working directory of the executable 101 | * `eucalyptus.dll` - via an absolute path. 102 | 103 | [source,json] 104 | ---- 105 | { 106 | "logging": true, 107 | "enabled": true, 108 | "auto_load": false, 109 | "targets": [ 110 | "program32.exe", 111 | "program64.exe" 112 | ], 113 | "modules": [ 114 | { 115 | "path": "target.dll", 116 | "required": true 117 | }, 118 | { 119 | "path": "C:/users/acidicoala/eucalyptus.dll", 120 | "required": false 121 | } 122 | ] 123 | } 124 | ---- 125 | -- 126 | 127 | == 🏗️ Building from source 128 | 129 | === 🚦 Requirements 130 | 131 | :fn-lower-ver: footnote:lower-versions[Older versions may be supported as well.] 132 | 133 | * CMake v3.24 (Make sure that cmake is available from powershell) 134 | * Visual Studio 2022{fn-lower-ver}. 135 | * Tested on Windows 11 SDK (10.0.22621.0){fn-lower-ver}. 136 | 137 | === 👨‍💻 Commands 138 | 139 | Clone the project with its submodules: 140 | 141 | [source,powershell] 142 | ---- 143 | git clone --recurse-submodules https://github.com/acidicoala/Koaloader.git 144 | ---- 145 | 146 | Run the build script with desired parameters: 147 | 148 | [source,powershell] 149 | ---- 150 | ./build.ps1 $Arch $Config $Proxy 151 | ---- 152 | 153 | where 154 | 155 | [horizontal] 156 | `$Arch`:: Program architecture. 157 | Valid values: 158 | * `32` 159 | * `64` 160 | 161 | `$Config`:: Build configuration. 162 | Valid values: 163 | * `Debug` 164 | * `Release` 165 | * `RelWithDebInfo` 166 | 167 | `$Proxy`:: Proxy DLL to build. 168 | Any DLL from `C:/Windows/System32` that includes only named exports is valid. 169 | 170 | Example: 171 | 172 | [source,powershell] 173 | ---- 174 | ./build.ps1 64 Release d3d11 175 | ---- 176 | 177 | The final DLL will be located at 178 | `build\$Arch\$Proxy\$Config` 179 | 180 | === Potential improvements 181 | 182 | * [ ] DLLs with unnamed exports (by ordinal) 183 | * [ ] DLLs that are missing from System32 directory 184 | 185 | === Miscellaneous notes 186 | 187 | * Version is defined in link:CMakeLists.txt[CMakeLists.txt] 188 | * CMake project likely needs to be reloaded after changing files in the link:res[res] directory. 189 | * GitHub actions will build the project on every push to `master`, but will prepare a draft release only if the last commit was tagged. 190 | * Proxy DLLs for CI releases need to be defined in link:.github/workflows/ci.yml[ci.yml] 191 | 192 | == 👋 Acknowledgements 193 | 194 | SmokeAPI makes use of the following open source projects: 195 | 196 | * https://github.com/libcpr/cpr[C++ Requests] 197 | * https://github.com/nlohmann/json[JSON for Modern C++] 198 | * https://github.com/stevemk14ebr/PolyHook_2_0[PolyHook 2] 199 | * https://github.com/gabime/spdlog[spdlog] 200 | 201 | == 📄 License 202 | 203 | This software is licensed under the https://unlicense.org/[Unlicense], terms of which are available in link:UNLICENSE.txt[UNLICENSE.txt] 204 | -------------------------------------------------------------------------------- /UNLICENSE.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | # Usage examples: 2 | # build.ps1 32 Release dinput8 3 | # build.ps1 64 Release version 4 | 5 | Set-Location (Get-Item $PSScriptRoot) 6 | 7 | . ./KoalaBox/build.ps1 KoalaBox @args 8 | 9 | $proxy = $args[2] 10 | if ($proxy -eq '') { 11 | throw "Proxy DLL cannot be empty." 12 | } else { 13 | $Env:MODULE = $proxy 14 | } 15 | 16 | $Env:BUILD_DIR = "build\$arch\$proxy" 17 | 18 | Build-Project 19 | -------------------------------------------------------------------------------- /res/Koaloader.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging": true, 3 | "enabled": true, 4 | "auto_load": true, 5 | "targets": [], 6 | "modules": [] 7 | } -------------------------------------------------------------------------------- /src/koaloader/koaloader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace koaloader { 10 | 11 | Config config = {}; 12 | 13 | const auto bitness = std::to_string(8 * sizeof(uintptr_t)); 14 | 15 | Path self_directory; 16 | 17 | bool loaded = false; 18 | 19 | bool is_loaded_by_target() { 20 | if (config.targets.empty()) { 21 | return true; 22 | } 23 | 24 | const auto process_handle = koalabox::win_util::get_module_handle(nullptr); 25 | const auto executable_path = Path(koalabox::win_util::get_module_file_name(process_handle)); 26 | const auto executable_name = executable_path.filename().string(); 27 | 28 | bool target_found = false; 29 | for (const auto& target: config.targets) { 30 | if (target < equals > executable_name) { 31 | LOG_DEBUG("Target found: '{}'", target) 32 | target_found = true; 33 | break; 34 | } 35 | } 36 | 37 | return target_found; 38 | } 39 | 40 | Set generate_well_known_modules() { 41 | const Set well_known_names{ 42 | "Unlocker", 43 | "Lyptus", 44 | "ScreamAPI", 45 | "SmokeAPI", 46 | "UplayR1Unlocker", 47 | "UplayR2Unlocker", 48 | }; 49 | 50 | Set well_known_modules; 51 | 52 | for (const auto& name: well_known_names) { 53 | well_known_modules.insert(name + ".dll"); 54 | well_known_modules.insert(name + bitness + ".dll"); 55 | } 56 | 57 | return well_known_modules; 58 | } 59 | 60 | void inject_module(const Path& path, bool required) { 61 | try { 62 | koalabox::win_util::load_library_or_throw(path); 63 | 64 | LOG_INFO(R"(✅ Loaded module: "{}")", path.string()) 65 | 66 | loaded = true; 67 | } catch (const Exception& e) { 68 | const auto message = fmt::format( 69 | "Error loading module \"{}\":\n\t{}", path.string(), e.what() 70 | ); 71 | 72 | if (required) { 73 | koalabox::util::panic(message); 74 | } else { 75 | LOG_WARN("{}", message) 76 | } 77 | } 78 | } 79 | 80 | /** 81 | * Since `directory_iterator` and `recursive_directory_iterator` 82 | * don't share a common interface, we have to use these dirty tricks 83 | * to keep the code DRY. 84 | */ 85 | enum class ControlOperation { 86 | NO_OP, 87 | CONTINUE_OP, 88 | RETURN_OP 89 | }; 90 | 91 | #define PROCESS_CONTROL_OPERATION(RESULT) \ 92 | switch (RESULT) { \ 93 | case ControlOperation::CONTINUE_OP: continue; \ 94 | case ControlOperation::RETURN_OP: return; \ 95 | case ControlOperation::NO_OP: {}; \ 96 | } 97 | 98 | ControlOperation process_file(const std::filesystem::directory_entry& entry) { 99 | LOG_TRACE(R"(Processing file: "{}")", entry.path().string()) 100 | 101 | // Skip directories 102 | if (entry.is_directory()) { 103 | return ControlOperation::CONTINUE_OP; 104 | } 105 | 106 | const auto& path = entry.path(); 107 | 108 | // Skip files without filename 109 | if (not path.has_filename()) { 110 | return ControlOperation::CONTINUE_OP; 111 | } 112 | 113 | // Skip non-DLLs 114 | if (path.extension().string() < not_equals > ".dll") { 115 | return ControlOperation::CONTINUE_OP; 116 | } 117 | 118 | const auto filename = path.filename().string(); 119 | 120 | const static auto well_known_modules = generate_well_known_modules(); 121 | 122 | for (const auto& dll: well_known_modules) { 123 | if (filename < equals > dll) { 124 | inject_module(path, true); 125 | 126 | return ControlOperation::RETURN_OP; 127 | } 128 | } 129 | 130 | return ControlOperation::NO_OP; 131 | } 132 | 133 | void inject_modules(const Path& starting_directory) { 134 | using namespace std::filesystem; 135 | 136 | LOG_DEBUG(R"(Beginning search in "{}")", starting_directory.string()) 137 | 138 | if (config.auto_load) { 139 | LOG_INFO("🤖 Entering auto-loading mode") 140 | 141 | const static directory_options dir_options = ( 142 | directory_options::follow_directory_symlink | 143 | directory_options::skip_permission_denied 144 | ); 145 | 146 | // First try searching in parent directories 147 | LOG_DEBUG("Searching in parent directories") 148 | 149 | auto current = starting_directory; 150 | Path previous; 151 | do { 152 | for (const auto& entry: directory_iterator(current, dir_options)) { 153 | PROCESS_CONTROL_OPERATION(process_file(entry)) 154 | } 155 | 156 | previous = current; 157 | current = current.parent_path(); 158 | } while (not equivalent(current, previous)); 159 | 160 | // Then recursively go over all files in current working directory 161 | LOG_DEBUG("Searching in subdirectories") 162 | 163 | for (const auto& entry: recursive_directory_iterator(starting_directory, dir_options)) { 164 | PROCESS_CONTROL_OPERATION(process_file(entry)) 165 | } 166 | } else { 167 | for (const auto& module: config.modules) { 168 | auto path = Path(module.path); 169 | 170 | if (path.is_absolute()) { 171 | inject_module(path, module.required); 172 | } else { 173 | inject_module(path, false); 174 | 175 | if (not loaded) { 176 | inject_module(self_directory / path, false); 177 | } 178 | 179 | if (not loaded) { 180 | koalabox::util::panic( 181 | "Error loading module with relative path. Search locations:\n{}\n{}", 182 | absolute(path).string(), absolute(self_directory / path).string() 183 | ); 184 | } 185 | } 186 | } 187 | } 188 | } 189 | 190 | void init(const HMODULE& self_module) { 191 | try { 192 | DisableThreadLibraryCalls(self_module); 193 | 194 | self_directory = koalabox::loader::get_module_dir(self_module); 195 | 196 | try { 197 | const auto config_path = self_directory / "Koaloader.config.json"; 198 | const auto config_str = koalabox::io::read_file(config_path); 199 | config = Json::parse(config_str); 200 | } catch (const Exception& e) {} 201 | 202 | if (config.logging) { 203 | koalabox::logger::init_file_logger(self_directory / "Koaloader.log.log"); 204 | } 205 | 206 | LOG_INFO("🐨 {} 📥 v{} | Compiled at '{}'", PROJECT_NAME, PROJECT_VERSION, __TIMESTAMP__) 207 | 208 | const auto exe_path = koalabox::win_util::get_module_file_name_or_throw(nullptr); 209 | LOG_DEBUG(R"(Executable path: "{}" [{}-bit])", exe_path, bitness) 210 | LOG_DEBUG(R"(Current working directory: "{}")", std::filesystem::current_path().string()) 211 | LOG_DEBUG(R"(Koaloader directory: "{}")", self_directory.string()) 212 | 213 | if (config.enabled) { 214 | if (is_loaded_by_target()) { 215 | inject_modules(self_directory); 216 | 217 | if (not loaded) { 218 | inject_modules(std::filesystem::absolute(".")); 219 | } 220 | } else { 221 | LOG_DEBUG("Not loaded by target process. Skipping injections.") 222 | } 223 | } else { 224 | LOG_DEBUG("Koaloader is not enabled in config") 225 | } 226 | 227 | LOG_INFO("🚀 Initialization complete") 228 | } catch (const Exception& e) { 229 | koalabox::util::panic("Initialization error: {}", e.what()); 230 | } 231 | } 232 | 233 | void shutdown() { 234 | LOG_INFO("💀 Shutdown complete") 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/koaloader/koaloader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace koaloader { 6 | 7 | struct Module { 8 | String path; 9 | bool required = true; 10 | 11 | NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Module, path, required) 12 | }; 13 | 14 | struct Config { 15 | bool logging = false; 16 | bool enabled = true; 17 | bool auto_load = true; 18 | Vector targets; 19 | Vector modules; 20 | 21 | NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Config, logging, enabled, auto_load, targets, modules) 22 | }; 23 | 24 | extern Config config; 25 | 26 | void init(const HMODULE& self_module); 27 | 28 | void shutdown(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define DLL_EXPORT(TYPE) extern "C" __declspec(dllexport) TYPE WINAPI 5 | 6 | DLL_EXPORT(BOOL) DllMain(HINSTANCE instance, DWORD reason, LPVOID) { 7 | if (reason == DLL_PROCESS_ATTACH) { 8 | koaloader::init(instance); 9 | } else if (reason == DLL_PROCESS_DETACH) { 10 | koaloader::shutdown(); 11 | } 12 | 13 | return TRUE; 14 | } 15 | --------------------------------------------------------------------------------