├── .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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
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 |
--------------------------------------------------------------------------------