contrast-agent 3.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.clang-format +5 -0
- data/.dockerignore +10 -0
- data/.gitignore +58 -0
- data/.gitmodules +6 -0
- data/.rspec +6 -0
- data/.simplecov +4 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +12 -0
- data/Rakefile +15 -0
- data/exe/contrast_service +29 -0
- data/ext/build_funchook.rb +48 -0
- data/ext/cs__assess_active_record_named/cs__active_record_named.c +47 -0
- data/ext/cs__assess_active_record_named/cs__active_record_named.h +10 -0
- data/ext/cs__assess_active_record_named/extconf.rb +2 -0
- data/ext/cs__assess_array/cs__assess_array.c +38 -0
- data/ext/cs__assess_array/cs__assess_array.h +9 -0
- data/ext/cs__assess_array/extconf.rb +2 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +50 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.h +17 -0
- data/ext/cs__assess_basic_object/extconf.rb +2 -0
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +86 -0
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +34 -0
- data/ext/cs__assess_fiber_track/extconf.rb +2 -0
- data/ext/cs__assess_hash/cs__assess_hash.c +64 -0
- data/ext/cs__assess_hash/cs__assess_hash.h +24 -0
- data/ext/cs__assess_hash/extconf.rb +2 -0
- data/ext/cs__assess_kernel/cs__assess_kernel.c +36 -0
- data/ext/cs__assess_kernel/cs__assess_kernel.h +10 -0
- data/ext/cs__assess_kernel/extconf.rb +2 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +47 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +18 -0
- data/ext/cs__assess_marshal_module/extconf.rb +2 -0
- data/ext/cs__assess_module/cs__assess_module.c +78 -0
- data/ext/cs__assess_module/cs__assess_module.h +25 -0
- data/ext/cs__assess_module/extconf.rb +2 -0
- data/ext/cs__assess_regexp/cs__assess_regexp.c +48 -0
- data/ext/cs__assess_regexp/cs__assess_regexp.h +22 -0
- data/ext/cs__assess_regexp/extconf.rb +2 -0
- data/ext/cs__assess_regexp_track/cs__assess_regexp_track.c +63 -0
- data/ext/cs__assess_regexp_track/cs__assess_regexp_track.h +29 -0
- data/ext/cs__assess_regexp_track/extconf.rb +2 -0
- data/ext/cs__assess_string/cs__assess_string.c +38 -0
- data/ext/cs__assess_string/cs__assess_string.h +19 -0
- data/ext/cs__assess_string/extconf.rb +2 -0
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +31 -0
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.h +13 -0
- data/ext/cs__assess_string_interpolation26/extconf.rb +2 -0
- data/ext/cs__common/cs__common.c +60 -0
- data/ext/cs__common/cs__common.h +28 -0
- data/ext/cs__common/extconf.rb +20 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.c +445 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.h +196 -0
- data/ext/cs__contrast_patch/extconf.rb +2 -0
- data/ext/cs__protect_kernel/cs__protect_kernel.c +37 -0
- data/ext/cs__protect_kernel/cs__protect_kernel.h +11 -0
- data/ext/cs__protect_kernel/extconf.rb +2 -0
- data/ext/cs__scope/cs__scope.c +96 -0
- data/ext/cs__scope/cs__scope.h +33 -0
- data/ext/cs__scope/extconf.rb +2 -0
- data/ext/extconf_common.rb +49 -0
- data/funchook/LICENSE +360 -0
- data/funchook/Makefile +29 -0
- data/funchook/Makefile.in +29 -0
- data/funchook/README.md +121 -0
- data/funchook/appveyor.yml +42 -0
- data/funchook/autogen.sh +3 -0
- data/funchook/autom4te.cache/output.0 +4976 -0
- data/funchook/autom4te.cache/requests +78 -0
- data/funchook/autom4te.cache/traces.0 +364 -0
- data/funchook/config.guess +1530 -0
- data/funchook/config.log +490 -0
- data/funchook/config.status +1016 -0
- data/funchook/config.sub +1773 -0
- data/funchook/configure +4976 -0
- data/funchook/configure.ac +59 -0
- data/funchook/distorm/COPYING +26 -0
- data/funchook/distorm/MANIFEST +25 -0
- data/funchook/distorm/MANIFEST.in +4 -0
- data/funchook/distorm/README.md +12 -0
- data/funchook/distorm/disOps/disOps.py +795 -0
- data/funchook/distorm/disOps/x86db.py +404 -0
- data/funchook/distorm/disOps/x86header.py +247 -0
- data/funchook/distorm/disOps/x86sets.py +1664 -0
- data/funchook/distorm/examples/cs/TestdiStorm/Program.cs +79 -0
- data/funchook/distorm/examples/cs/TestdiStorm/Properties/AssemblyInfo.cs +36 -0
- data/funchook/distorm/examples/cs/TestdiStorm/TestdiStorm.csproj +69 -0
- data/funchook/distorm/examples/cs/distorm-net.sln +26 -0
- data/funchook/distorm/examples/cs/distorm-net/CodeInfo.cs +23 -0
- data/funchook/distorm/examples/cs/distorm-net/DecodedInst.cs +15 -0
- data/funchook/distorm/examples/cs/distorm-net/DecodedResult.cs +14 -0
- data/funchook/distorm/examples/cs/distorm-net/DecomposedInst.cs +36 -0
- data/funchook/distorm/examples/cs/distorm-net/DecomposedResult.cs +14 -0
- data/funchook/distorm/examples/cs/distorm-net/Opcodes.cs +1268 -0
- data/funchook/distorm/examples/cs/distorm-net/Opcodes.tt +37 -0
- data/funchook/distorm/examples/cs/distorm-net/Operand.cs +25 -0
- data/funchook/distorm/examples/cs/distorm-net/Properties/AssemblyInfo.cs +36 -0
- data/funchook/distorm/examples/cs/distorm-net/diStorm3.cs +411 -0
- data/funchook/distorm/examples/cs/distorm-net/distorm-net.csproj +80 -0
- data/funchook/distorm/examples/cs/readme +3 -0
- data/funchook/distorm/examples/ddk/README +48 -0
- data/funchook/distorm/examples/ddk/distorm.ini +11 -0
- data/funchook/distorm/examples/ddk/dummy.c +15 -0
- data/funchook/distorm/examples/ddk/main.c +91 -0
- data/funchook/distorm/examples/ddk/makefile +1 -0
- data/funchook/distorm/examples/ddk/sources +10 -0
- data/funchook/distorm/examples/java/Makefile +23 -0
- data/funchook/distorm/examples/java/distorm/src/Main.java +43 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/CodeInfo.java +27 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedInst.java +32 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedResult.java +11 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedInst.java +89 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedResult.java +11 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/OpcodeEnum.java +131 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/Opcodes.java +1123 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/Operand.java +24 -0
- data/funchook/distorm/examples/java/distorm/src/diStorm3/distorm3.java +41 -0
- data/funchook/distorm/examples/java/jdistorm.c +405 -0
- data/funchook/distorm/examples/java/jdistorm.h +40 -0
- data/funchook/distorm/examples/java/jdistorm.sln +20 -0
- data/funchook/distorm/examples/java/jdistorm.vcproj +208 -0
- data/funchook/distorm/examples/linux/Makefile +15 -0
- data/funchook/distorm/examples/linux/main.c +181 -0
- data/funchook/distorm/examples/tests/Makefile +15 -0
- data/funchook/distorm/examples/tests/main.cpp +42 -0
- data/funchook/distorm/examples/tests/main.py +66 -0
- data/funchook/distorm/examples/tests/test_distorm3.py +1672 -0
- data/funchook/distorm/examples/tests/tests.sln +20 -0
- data/funchook/distorm/examples/tests/tests.vcxproj +82 -0
- data/funchook/distorm/examples/tests/tests.vcxproj.filters +22 -0
- data/funchook/distorm/examples/win32/disasm.sln +25 -0
- data/funchook/distorm/examples/win32/disasm.vcxproj +201 -0
- data/funchook/distorm/examples/win32/disasm.vcxproj.filters +14 -0
- data/funchook/distorm/examples/win32/main.cpp +163 -0
- data/funchook/distorm/include/distorm.h +482 -0
- data/funchook/distorm/include/mnemonics.h +301 -0
- data/funchook/distorm/make/linux/Makefile +28 -0
- data/funchook/distorm/make/mac/Makefile +24 -0
- data/funchook/distorm/make/win32/cdistorm.vcxproj +239 -0
- data/funchook/distorm/make/win32/cdistorm.vcxproj.filters +80 -0
- data/funchook/distorm/make/win32/distorm.sln +25 -0
- data/funchook/distorm/make/win32/resource.h +14 -0
- data/funchook/distorm/make/win32/resource.rc +99 -0
- data/funchook/distorm/python/distorm3/__init__.py +957 -0
- data/funchook/distorm/python/distorm3/sample.py +51 -0
- data/funchook/distorm/setup.cfg +10 -0
- data/funchook/distorm/setup.py +266 -0
- data/funchook/distorm/src/config.h +169 -0
- data/funchook/distorm/src/decoder.c +641 -0
- data/funchook/distorm/src/decoder.h +33 -0
- data/funchook/distorm/src/distorm.c +413 -0
- data/funchook/distorm/src/instructions.c +597 -0
- data/funchook/distorm/src/instructions.h +463 -0
- data/funchook/distorm/src/insts.c +7939 -0
- data/funchook/distorm/src/insts.h +64 -0
- data/funchook/distorm/src/mnemonics.c +284 -0
- data/funchook/distorm/src/operands.c +1290 -0
- data/funchook/distorm/src/operands.h +28 -0
- data/funchook/distorm/src/prefix.c +368 -0
- data/funchook/distorm/src/prefix.h +64 -0
- data/funchook/distorm/src/textdefs.c +172 -0
- data/funchook/distorm/src/textdefs.h +57 -0
- data/funchook/distorm/src/wstring.c +47 -0
- data/funchook/distorm/src/wstring.h +35 -0
- data/funchook/distorm/src/x86defs.h +82 -0
- data/funchook/include/funchook.h +123 -0
- data/funchook/install-sh +527 -0
- data/funchook/src/Makefile +70 -0
- data/funchook/src/Makefile.in +70 -0
- data/funchook/src/__strerror.h +109 -0
- data/funchook/src/config.h +101 -0
- data/funchook/src/config.h.in +100 -0
- data/funchook/src/decoder.o +0 -0
- data/funchook/src/distorm.o +0 -0
- data/funchook/src/funchook.c +440 -0
- data/funchook/src/funchook.o +0 -0
- data/funchook/src/funchook_internal.h +155 -0
- data/funchook/src/funchook_io.c +182 -0
- data/funchook/src/funchook_io.h +64 -0
- data/funchook/src/funchook_io.o +0 -0
- data/funchook/src/funchook_syscall.S +134 -0
- data/funchook/src/funchook_syscall.o +0 -0
- data/funchook/src/funchook_unix.c +480 -0
- data/funchook/src/funchook_unix.o +0 -0
- data/funchook/src/funchook_windows.c +397 -0
- data/funchook/src/funchook_x86.c +622 -0
- data/funchook/src/funchook_x86.o +0 -0
- data/funchook/src/instructions.o +0 -0
- data/funchook/src/insts.o +0 -0
- data/funchook/src/libfunchook.so +0 -0
- data/funchook/src/mnemonics.o +0 -0
- data/funchook/src/operands.o +0 -0
- data/funchook/src/os_func.c +115 -0
- data/funchook/src/os_func.h +75 -0
- data/funchook/src/os_func.o +0 -0
- data/funchook/src/os_func_unix.c +94 -0
- data/funchook/src/os_func_unix.o +0 -0
- data/funchook/src/os_func_windows.c +32 -0
- data/funchook/src/prefix.o +0 -0
- data/funchook/src/printf_base.c +1688 -0
- data/funchook/src/printf_base.h +46 -0
- data/funchook/src/printf_base.o +0 -0
- data/funchook/src/textdefs.o +0 -0
- data/funchook/src/wstring.o +0 -0
- data/funchook/test/Makefile +43 -0
- data/funchook/test/Makefile.in +43 -0
- data/funchook/test/funchook_test +0 -0
- data/funchook/test/libfunchook_test.c +25 -0
- data/funchook/test/libfunchook_test.so +0 -0
- data/funchook/test/libfunchook_test2.c +18 -0
- data/funchook/test/suffix.list +600 -0
- data/funchook/test/test_main.c +430 -0
- data/funchook/test/test_main.o +0 -0
- data/funchook/test/x86_64_test.S +10 -0
- data/funchook/test/x86_64_test.o +0 -0
- data/funchook/test/x86_test.S +339 -0
- data/funchook/win32/config.h +1 -0
- data/funchook/win32/funchook.sln +52 -0
- data/funchook/win32/funchook.vcxproj +188 -0
- data/funchook/win32/funchook.vcxproj.filters +84 -0
- data/funchook/win32/funchook_test.vcxproj +170 -0
- data/funchook/win32/funchook_test.vcxproj.filters +22 -0
- data/funchook/win32/funchook_test_dll.vcxproj +184 -0
- data/funchook/win32/funchook_test_dll.vcxproj.filters +30 -0
- data/funchook/win32/funchook_test_exe.def +3 -0
- data/lib/contrast-agent.rb +8 -0
- data/lib/contrast.rb +57 -0
- data/lib/contrast/agent.rb +80 -0
- data/lib/contrast/agent/assess.rb +45 -0
- data/lib/contrast/agent/assess/adjusted_span.rb +25 -0
- data/lib/contrast/agent/assess/class_reverter.rb +82 -0
- data/lib/contrast/agent/assess/contrast_event.rb +398 -0
- data/lib/contrast/agent/assess/frozen_properties.rb +41 -0
- data/lib/contrast/agent/assess/insulator.rb +53 -0
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +78 -0
- data/lib/contrast/agent/assess/policy/patcher.rb +85 -0
- data/lib/contrast/agent/assess/policy/policy.rb +116 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +289 -0
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +44 -0
- data/lib/contrast/agent/assess/policy/preshift.rb +94 -0
- data/lib/contrast/agent/assess/policy/propagation_method.rb +260 -0
- data/lib/contrast/agent/assess/policy/propagation_node.rb +127 -0
- data/lib/contrast/agent/assess/policy/propagator.rb +35 -0
- data/lib/contrast/agent/assess/policy/propagator/append.rb +54 -0
- data/lib/contrast/agent/assess/policy/propagator/base.rb +37 -0
- data/lib/contrast/agent/assess/policy/propagator/center.rb +73 -0
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +36 -0
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +62 -0
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +55 -0
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +26 -0
- data/lib/contrast/agent/assess/policy/propagator/next.rb +42 -0
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +50 -0
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +76 -0
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +27 -0
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +38 -0
- data/lib/contrast/agent/assess/policy/propagator/select.rb +86 -0
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +60 -0
- data/lib/contrast/agent/assess/policy/propagator/split.rb +49 -0
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +169 -0
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +81 -0
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +79 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +209 -0
- data/lib/contrast/agent/assess/policy/source_node.rb +62 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +209 -0
- data/lib/contrast/agent/assess/policy/trigger_node.rb +198 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +77 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +31 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +40 -0
- data/lib/contrast/agent/assess/properties.rb +392 -0
- data/lib/contrast/agent/assess/rule.rb +18 -0
- data/lib/contrast/agent/assess/rule/base.rb +72 -0
- data/lib/contrast/agent/assess/rule/csrf.rb +66 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_action.rb +28 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +69 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_watcher.rb +132 -0
- data/lib/contrast/agent/assess/rule/provider.rb +21 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +62 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +73 -0
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +121 -0
- data/lib/contrast/agent/assess/rule/redos.rb +68 -0
- data/lib/contrast/agent/assess/rule/response_scanning_rule.rb +47 -0
- data/lib/contrast/agent/assess/rule/response_watcher.rb +36 -0
- data/lib/contrast/agent/assess/rule/watcher.rb +36 -0
- data/lib/contrast/agent/assess/tag.rb +151 -0
- data/lib/contrast/agent/at_exit_hook.rb +33 -0
- data/lib/contrast/agent/class_reopener.rb +195 -0
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +26 -0
- data/lib/contrast/agent/deadzone/policy/policy.rb +57 -0
- data/lib/contrast/agent/disable_reaction.rb +24 -0
- data/lib/contrast/agent/exclusion_matcher.rb +190 -0
- data/lib/contrast/agent/feature_state.rb +379 -0
- data/lib/contrast/agent/inventory/policy/policy.rb +32 -0
- data/lib/contrast/agent/inventory/policy/trigger_node.rb +22 -0
- data/lib/contrast/agent/logger_manager.rb +116 -0
- data/lib/contrast/agent/middleware.rb +352 -0
- data/lib/contrast/agent/module_data.rb +16 -0
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +37 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +58 -0
- data/lib/contrast/agent/patching/policy/method_policy.rb +94 -0
- data/lib/contrast/agent/patching/policy/module_policy.rb +116 -0
- data/lib/contrast/agent/patching/policy/patch.rb +312 -0
- data/lib/contrast/agent/patching/policy/patch_status.rb +192 -0
- data/lib/contrast/agent/patching/policy/patcher.rb +310 -0
- data/lib/contrast/agent/patching/policy/policy.rb +138 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +80 -0
- data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +28 -0
- data/lib/contrast/agent/patching/policy/trigger_node.rb +81 -0
- data/lib/contrast/agent/protect/policy/policy.rb +37 -0
- data/lib/contrast/agent/protect/policy/trigger_node.rb +23 -0
- data/lib/contrast/agent/protect/rule.rb +58 -0
- data/lib/contrast/agent/protect/rule/base.rb +300 -0
- data/lib/contrast/agent/protect/rule/base_service.rb +88 -0
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +156 -0
- data/lib/contrast/agent/protect/rule/csrf.rb +118 -0
- data/lib/contrast/agent/protect/rule/csrf/csrf_evaluator.rb +103 -0
- data/lib/contrast/agent/protect/rule/csrf/csrf_token_injector.rb +85 -0
- data/lib/contrast/agent/protect/rule/default_scanner.rb +300 -0
- data/lib/contrast/agent/protect/rule/deserialization.rb +193 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +80 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +101 -0
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +40 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +143 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +101 -0
- data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +16 -0
- data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +38 -0
- data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +22 -0
- data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +19 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +20 -0
- data/lib/contrast/agent/protect/rule/xss.rb +24 -0
- data/lib/contrast/agent/protect/rule/xxe.rb +120 -0
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +82 -0
- data/lib/contrast/agent/railtie.rb +30 -0
- data/lib/contrast/agent/reaction_processor.rb +47 -0
- data/lib/contrast/agent/request.rb +493 -0
- data/lib/contrast/agent/request_context.rb +225 -0
- data/lib/contrast/agent/require_state.rb +61 -0
- data/lib/contrast/agent/response.rb +215 -0
- data/lib/contrast/agent/rewriter.rb +244 -0
- data/lib/contrast/agent/scope.rb +28 -0
- data/lib/contrast/agent/service_heartbeat.rb +37 -0
- data/lib/contrast/agent/settings_state.rb +148 -0
- data/lib/contrast/agent/socket_client.rb +125 -0
- data/lib/contrast/agent/thread.rb +26 -0
- data/lib/contrast/agent/tracepoint_hook.rb +51 -0
- data/lib/contrast/agent/version.rb +8 -0
- data/lib/contrast/api.rb +17 -0
- data/lib/contrast/api/.gitkeep +0 -0
- data/lib/contrast/api/connection_status.rb +49 -0
- data/lib/contrast/api/socket.rb +43 -0
- data/lib/contrast/api/speedracer.rb +206 -0
- data/lib/contrast/api/tcp_socket.rb +31 -0
- data/lib/contrast/api/unix_socket.rb +25 -0
- data/lib/contrast/common_agent_configuration.rb +86 -0
- data/lib/contrast/components/agent.rb +85 -0
- data/lib/contrast/components/app_context.rb +188 -0
- data/lib/contrast/components/assess.rb +67 -0
- data/lib/contrast/components/config.rb +135 -0
- data/lib/contrast/components/contrast_service.rb +113 -0
- data/lib/contrast/components/heap_dump.rb +34 -0
- data/lib/contrast/components/interface.rb +178 -0
- data/lib/contrast/components/inventory.rb +23 -0
- data/lib/contrast/components/logger.rb +92 -0
- data/lib/contrast/components/protect.rb +38 -0
- data/lib/contrast/components/sampling.rb +41 -0
- data/lib/contrast/components/scope.rb +106 -0
- data/lib/contrast/components/settings.rb +140 -0
- data/lib/contrast/config.rb +33 -0
- data/lib/contrast/config/agent_configuration.rb +24 -0
- data/lib/contrast/config/application_configuration.rb +27 -0
- data/lib/contrast/config/assess_configuration.rb +22 -0
- data/lib/contrast/config/assess_rules_configuration.rb +18 -0
- data/lib/contrast/config/base_configuration.rb +105 -0
- data/lib/contrast/config/default_value.rb +16 -0
- data/lib/contrast/config/exception_configuration.rb +21 -0
- data/lib/contrast/config/heap_dump_configuration.rb +23 -0
- data/lib/contrast/config/inventory_configuration.rb +20 -0
- data/lib/contrast/config/logger_configuration.rb +20 -0
- data/lib/contrast/config/protect_configuration.rb +20 -0
- data/lib/contrast/config/protect_rule_configuration.rb +37 -0
- data/lib/contrast/config/protect_rules_configuration.rb +30 -0
- data/lib/contrast/config/root_configuration.rb +26 -0
- data/lib/contrast/config/ruby_configuration.rb +39 -0
- data/lib/contrast/config/sampling_configuration.rb +22 -0
- data/lib/contrast/config/server_configuration.rb +23 -0
- data/lib/contrast/config/service_configuration.rb +22 -0
- data/lib/contrast/configuration.rb +214 -0
- data/lib/contrast/core_extensions/assess.rb +51 -0
- data/lib/contrast/core_extensions/assess/array.rb +58 -0
- data/lib/contrast/core_extensions/assess/assess_extension.rb +145 -0
- data/lib/contrast/core_extensions/assess/basic_object.rb +15 -0
- data/lib/contrast/core_extensions/assess/erb.rb +42 -0
- data/lib/contrast/core_extensions/assess/exec_trigger.rb +48 -0
- data/lib/contrast/core_extensions/assess/fiber.rb +125 -0
- data/lib/contrast/core_extensions/assess/hash.rb +22 -0
- data/lib/contrast/core_extensions/assess/kernel.rb +95 -0
- data/lib/contrast/core_extensions/assess/module.rb +14 -0
- data/lib/contrast/core_extensions/assess/regexp.rb +206 -0
- data/lib/contrast/core_extensions/assess/string.rb +75 -0
- data/lib/contrast/core_extensions/assess/tilt_template_trigger.rb +73 -0
- data/lib/contrast/core_extensions/delegator.rb +14 -0
- data/lib/contrast/core_extensions/eval_trigger.rb +52 -0
- data/lib/contrast/core_extensions/inventory.rb +22 -0
- data/lib/contrast/core_extensions/inventory/datastores.rb +37 -0
- data/lib/contrast/core_extensions/module.rb +42 -0
- data/lib/contrast/core_extensions/object.rb +27 -0
- data/lib/contrast/core_extensions/protect.rb +20 -0
- data/lib/contrast/core_extensions/protect/applies_command_injection_rule.rb +70 -0
- data/lib/contrast/core_extensions/protect/applies_deserialization_rule.rb +58 -0
- data/lib/contrast/core_extensions/protect/applies_no_sqli_rule.rb +81 -0
- data/lib/contrast/core_extensions/protect/applies_path_traversal_rule.rb +119 -0
- data/lib/contrast/core_extensions/protect/applies_sqli_rule.rb +63 -0
- data/lib/contrast/core_extensions/protect/applies_xxe_rule.rb +141 -0
- data/lib/contrast/core_extensions/protect/kernel.rb +30 -0
- data/lib/contrast/core_extensions/protect/psych.rb +7 -0
- data/lib/contrast/core_extensions/thread.rb +31 -0
- data/lib/contrast/internal_exception.rb +8 -0
- data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +48 -0
- data/lib/contrast/rails_extensions/assess/active_record.rb +32 -0
- data/lib/contrast/rails_extensions/assess/active_record_named.rb +61 -0
- data/lib/contrast/rails_extensions/assess/configuration.rb +26 -0
- data/lib/contrast/rails_extensions/buffer.rb +30 -0
- data/lib/contrast/rails_extensions/rack.rb +45 -0
- data/lib/contrast/security_exception.rb +14 -0
- data/lib/contrast/sinatra_extensions/assess/cookie.rb +26 -0
- data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +59 -0
- data/lib/contrast/tasks/service.rb +95 -0
- data/lib/contrast/utils/assess/sampling_util.rb +96 -0
- data/lib/contrast/utils/assess/tracking_util.rb +39 -0
- data/lib/contrast/utils/boolean_util.rb +33 -0
- data/lib/contrast/utils/cache.rb +69 -0
- data/lib/contrast/utils/class_util.rb +58 -0
- data/lib/contrast/utils/comment_range.rb +19 -0
- data/lib/contrast/utils/data_store_util.rb +23 -0
- data/lib/contrast/utils/duck_utils.rb +58 -0
- data/lib/contrast/utils/env_configuration_item.rb +52 -0
- data/lib/contrast/utils/environment_util.rb +152 -0
- data/lib/contrast/utils/freeze_util.rb +36 -0
- data/lib/contrast/utils/gemfile_reader.rb +191 -0
- data/lib/contrast/utils/hash_digest.rb +148 -0
- data/lib/contrast/utils/heap_dump_util.rb +113 -0
- data/lib/contrast/utils/invalid_configuration_util.rb +88 -0
- data/lib/contrast/utils/inventory_util.rb +126 -0
- data/lib/contrast/utils/io_util.rb +61 -0
- data/lib/contrast/utils/object_share.rb +117 -0
- data/lib/contrast/utils/operating_environment.rb +38 -0
- data/lib/contrast/utils/os.rb +49 -0
- data/lib/contrast/utils/path_util.rb +151 -0
- data/lib/contrast/utils/performs_logging.rb +152 -0
- data/lib/contrast/utils/preflight_util.rb +13 -0
- data/lib/contrast/utils/prevent_serialization.rb +52 -0
- data/lib/contrast/utils/rack_assess_session_cookie.rb +104 -0
- data/lib/contrast/utils/rails_assess_configuration.rb +95 -0
- data/lib/contrast/utils/random_util.rb +22 -0
- data/lib/contrast/utils/resource_loader.rb +23 -0
- data/lib/contrast/utils/ruby_ast_rewriter.rb +74 -0
- data/lib/contrast/utils/scope_util.rb +99 -0
- data/lib/contrast/utils/service_response_util.rb +116 -0
- data/lib/contrast/utils/service_sender_util.rb +98 -0
- data/lib/contrast/utils/sha256_builder.rb +69 -0
- data/lib/contrast/utils/sinatra_helper.rb +49 -0
- data/lib/contrast/utils/stack_trace_utils.rb +209 -0
- data/lib/contrast/utils/string_utils.rb +72 -0
- data/lib/contrast/utils/tag_util.rb +139 -0
- data/lib/contrast/utils/thread_tracker.rb +54 -0
- data/lib/contrast/utils/timer.rb +78 -0
- data/resources/assess/policy.json +1673 -0
- data/resources/csrf/inject.js +44 -0
- data/resources/deadzone/policy.json +55 -0
- data/resources/factory-bot-spec/spec_helper.rb +30 -0
- data/resources/inventory/policy.json +110 -0
- data/resources/protect/policy.json +417 -0
- data/resources/rubocops/kernel/catch_cop.rb +37 -0
- data/resources/rubocops/kernel/require_cop.rb +37 -0
- data/resources/rubocops/kernel/require_relative_cop.rb +33 -0
- data/resources/rubocops/module/autoload_cop.rb +37 -0
- data/resources/rubocops/module/const_defined_cop.rb +37 -0
- data/resources/rubocops/module/const_get_cop.rb +37 -0
- data/resources/rubocops/module/const_set_cop.rb +37 -0
- data/resources/rubocops/module/constants_cop.rb +37 -0
- data/resources/rubocops/module/name_cop.rb +37 -0
- data/resources/rubocops/object/class_cop.rb +37 -0
- data/resources/rubocops/object/freeze_cop.rb +37 -0
- data/resources/rubocops/object/frozen_cop.rb +37 -0
- data/resources/rubocops/object/is_a_cop.rb +37 -0
- data/resources/rubocops/object/method_cop.rb +37 -0
- data/resources/rubocops/object/respond_to_cop.rb +37 -0
- data/resources/rubocops/object/singleton_class_cop.rb +37 -0
- data/resources/rubocops/regexp/spelling_cop.rb +44 -0
- data/resources/rubocops/thread/new_cop.rb +39 -0
- data/resources/ruby-spec/ancestors_spec.rb +70 -0
- data/resources/ruby-spec/modulo_spec.rb +831 -0
- data/resources/ruby-spec/parameters_spec.rb +261 -0
- data/resources/ruby-spec/ruby_spec_spec_helper.rb +35 -0
- data/resources/test_marker.txt +1 -0
- data/ruby-agent.gemspec +129 -0
- data/service_executables/.gitkeep +0 -0
- data/service_executables/VERSION +1 -0
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +945 -0
|
Binary file
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
/* -*- indent-tabs-mode: nil -*-
|
|
2
|
+
*
|
|
3
|
+
* This file is part of Funchook.
|
|
4
|
+
* https://github.com/kubo/funchook
|
|
5
|
+
*
|
|
6
|
+
* Funchook is free software: you can redistribute it and/or modify it
|
|
7
|
+
* under the terms of the GNU General Public License as published by the
|
|
8
|
+
* Free Software Foundation, either version 2 of the License, or (at your
|
|
9
|
+
* option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* As a special exception, the copyright holders of this library give you
|
|
12
|
+
* permission to link this library with independent modules to produce an
|
|
13
|
+
* executable, regardless of the license terms of these independent
|
|
14
|
+
* modules, and to copy and distribute the resulting executable under
|
|
15
|
+
* terms of your choice, provided that you also meet, for each linked
|
|
16
|
+
* independent module, the terms and conditions of the license of that
|
|
17
|
+
* module. An independent module is a module which is not derived from or
|
|
18
|
+
* based on this library. If you modify this library, you may extend this
|
|
19
|
+
* exception to your version of the library, but you are not obliged to
|
|
20
|
+
* do so. If you do not wish to do so, delete this exception statement
|
|
21
|
+
* from your version.
|
|
22
|
+
*
|
|
23
|
+
* Funchook is distributed in the hope that it will be useful, but WITHOUT
|
|
24
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
25
|
+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
26
|
+
* for more details.
|
|
27
|
+
*
|
|
28
|
+
* You should have received a copy of the GNU General Public License
|
|
29
|
+
* along with Funchook. If not, see <http://www.gnu.org/licenses/>.
|
|
30
|
+
*/
|
|
31
|
+
#define PSAPI_VERSION 1
|
|
32
|
+
#include <stdint.h>
|
|
33
|
+
#include <windows.h>
|
|
34
|
+
#include <psapi.h>
|
|
35
|
+
#include "funchook_internal.h"
|
|
36
|
+
|
|
37
|
+
typedef struct page_info {
|
|
38
|
+
struct page_info *next;
|
|
39
|
+
struct page_info *prev;
|
|
40
|
+
int num_used;
|
|
41
|
+
char used[1];
|
|
42
|
+
} page_list_t;
|
|
43
|
+
|
|
44
|
+
const size_t page_size = PAGE_SIZE; /* 4K */
|
|
45
|
+
const size_t allocation_unit = ALLOCATION_UNIT; /* 64K */
|
|
46
|
+
|
|
47
|
+
static size_t max_num_pages = ALLOCATION_UNIT / PAGE_SIZE - 1; /* 15 */
|
|
48
|
+
static page_list_t page_list = {
|
|
49
|
+
&page_list,
|
|
50
|
+
&page_list,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
static const char *to_errmsg(DWORD err, char *buf, size_t bufsiz)
|
|
54
|
+
{
|
|
55
|
+
size_t len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
56
|
+
NULL, err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
|
57
|
+
buf, (DWORD)bufsiz, NULL);
|
|
58
|
+
if (len == 0) {
|
|
59
|
+
return "Unknown Error";
|
|
60
|
+
}
|
|
61
|
+
if (len >= bufsiz) {
|
|
62
|
+
len = bufsiz - 1;
|
|
63
|
+
}
|
|
64
|
+
while (len > 0 && (buf[len - 1] == '\r' || buf[len - 1] == '\n')) {
|
|
65
|
+
len--;
|
|
66
|
+
}
|
|
67
|
+
buf[len] = '\0';
|
|
68
|
+
return buf;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
funchook_t *funchook_alloc(void)
|
|
72
|
+
{
|
|
73
|
+
size_t size = ROUND_UP(funchook_size, page_size);
|
|
74
|
+
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
int funchook_free(funchook_t *funchook)
|
|
78
|
+
{
|
|
79
|
+
VirtualFree(funchook, 0, MEM_RELEASE);
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Reserve 64K bytes (allocation_unit) and use the first
|
|
84
|
+
* 4K bytes (1 page) as the control page.
|
|
85
|
+
*/
|
|
86
|
+
static int alloc_page_info(funchook_t *funchook, page_list_t **pl_out, void *hint)
|
|
87
|
+
{
|
|
88
|
+
void *addr;
|
|
89
|
+
page_list_t *pl;
|
|
90
|
+
#ifdef CPU_X86_64
|
|
91
|
+
void *old_hint = hint;
|
|
92
|
+
while (1) {
|
|
93
|
+
MEMORY_BASIC_INFORMATION mbi;
|
|
94
|
+
if (VirtualQuery(hint, &mbi, sizeof(mbi)) == 0) {
|
|
95
|
+
DWORD err = GetLastError();
|
|
96
|
+
char errbuf[128];
|
|
97
|
+
|
|
98
|
+
funchook_set_error_message(funchook, "Failed to execute VirtualQuery (addr=%p, error=%lu(%s))",
|
|
99
|
+
hint,
|
|
100
|
+
err, to_errmsg(err, errbuf, sizeof(errbuf)));
|
|
101
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
102
|
+
}
|
|
103
|
+
funchook_log(funchook, " process map: %016I64x-%016I64x %s\n",
|
|
104
|
+
(size_t)mbi.BaseAddress, (size_t)mbi.BaseAddress + mbi.RegionSize,
|
|
105
|
+
(mbi.State == MEM_FREE) ? "free" : "used");
|
|
106
|
+
if (mbi.State == MEM_FREE) {
|
|
107
|
+
size_t addr = ROUND_UP((size_t)mbi.BaseAddress, allocation_unit);
|
|
108
|
+
intptr_t diff = addr - (size_t)mbi.BaseAddress;
|
|
109
|
+
if (diff >= 0) {
|
|
110
|
+
if (mbi.RegionSize - diff >= allocation_unit) {
|
|
111
|
+
hint = (void*)addr;
|
|
112
|
+
funchook_log(funchook, " change hint address from %p to %p\n",
|
|
113
|
+
old_hint, hint);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
hint = (void*)((size_t)mbi.BaseAddress + mbi.RegionSize);
|
|
119
|
+
}
|
|
120
|
+
#else
|
|
121
|
+
hint = NULL;
|
|
122
|
+
#endif
|
|
123
|
+
pl = VirtualAlloc(hint, allocation_unit, MEM_RESERVE, PAGE_NOACCESS);
|
|
124
|
+
if (pl == NULL) {
|
|
125
|
+
DWORD err = GetLastError();
|
|
126
|
+
char errbuf[128];
|
|
127
|
+
|
|
128
|
+
funchook_set_error_message(funchook, "Failed to reserve memory %p (hint=%p, size=%"SIZE_T_FMT"u, errro=%lu(%s))",
|
|
129
|
+
pl, hint, allocation_unit,
|
|
130
|
+
err, to_errmsg(err, errbuf, sizeof(errbuf)));
|
|
131
|
+
return FUNCHOOK_ERROR_MEMORY_ALLOCATION;
|
|
132
|
+
}
|
|
133
|
+
funchook_log(funchook, " reserve memory %p (hint=%p, size=%"SIZE_T_FMT"u)\n", pl, hint, allocation_unit);
|
|
134
|
+
addr = VirtualAlloc(pl, page_size, MEM_COMMIT, PAGE_READWRITE);
|
|
135
|
+
if (addr == NULL) {
|
|
136
|
+
DWORD err = GetLastError();
|
|
137
|
+
char errbuf[128];
|
|
138
|
+
|
|
139
|
+
funchook_set_error_message(funchook, "Failed to commit memory %p for read-write (hint=%p, size=%"SIZE_T_FMT"u, error=%lu(%s))",
|
|
140
|
+
addr, pl, page_size,
|
|
141
|
+
err, to_errmsg(err, errbuf, sizeof(errbuf)));
|
|
142
|
+
VirtualFree(pl, 0, MEM_RELEASE);
|
|
143
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
144
|
+
}
|
|
145
|
+
funchook_log(funchook, " commit memory %p for read-write (hint=%p, size=%"SIZE_T_FMT"u)\n", addr, pl, page_size);
|
|
146
|
+
pl->next = page_list.next;
|
|
147
|
+
pl->prev = &page_list;
|
|
148
|
+
page_list.next->prev = pl;
|
|
149
|
+
page_list.next = pl;
|
|
150
|
+
*pl_out = pl;
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/*
|
|
155
|
+
* Get one page from page_list, commit it and return it.
|
|
156
|
+
*/
|
|
157
|
+
int funchook_page_alloc(funchook_t *funchook, funchook_page_t **page_out, uint8_t *func, rip_displacement_t *disp)
|
|
158
|
+
{
|
|
159
|
+
page_list_t *pl;
|
|
160
|
+
funchook_page_t *page = NULL;
|
|
161
|
+
size_t i;
|
|
162
|
+
|
|
163
|
+
for (pl = page_list.next; pl != &page_list; pl = pl->next) {
|
|
164
|
+
for (i = 0; i < max_num_pages; i++) {
|
|
165
|
+
if (!pl->used[i]) {
|
|
166
|
+
funchook_page_t *p = (funchook_page_t *)((size_t)pl + (i + 1) * page_size);
|
|
167
|
+
if (funchook_page_avail(funchook, p, 0, func, disp)) {
|
|
168
|
+
page = p;
|
|
169
|
+
goto exit_loop;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exit_loop:
|
|
175
|
+
if (page == NULL) {
|
|
176
|
+
/* no page_list is available. */
|
|
177
|
+
int rv = alloc_page_info(funchook, &pl, func);
|
|
178
|
+
if (rv != 0) {
|
|
179
|
+
return rv;
|
|
180
|
+
}
|
|
181
|
+
i = 0;
|
|
182
|
+
page = (funchook_page_t *)((size_t)pl + page_size);
|
|
183
|
+
}
|
|
184
|
+
if (VirtualAlloc(page, page_size, MEM_COMMIT, PAGE_READWRITE) == NULL) {
|
|
185
|
+
DWORD err = GetLastError();
|
|
186
|
+
char errbuf[128];
|
|
187
|
+
|
|
188
|
+
funchook_set_error_message(funchook, "Failed to commit page %p (base=%p(used=%d), idx=%"SIZE_T_FMT"u, size=%"SIZE_T_FMT"u, error=%lu(%s))",
|
|
189
|
+
page, pl, pl->num_used, i, page_size,
|
|
190
|
+
err, to_errmsg(err, errbuf, sizeof(errbuf)));
|
|
191
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
192
|
+
}
|
|
193
|
+
pl->used[i] = 1;
|
|
194
|
+
pl->num_used++;
|
|
195
|
+
funchook_log(funchook, " commit page %p (base=%p(used=%d), idx=%"SIZE_T_FMT"u, size=%"SIZE_T_FMT"u)\n",
|
|
196
|
+
page, pl, pl->num_used, i, page_size);
|
|
197
|
+
*page_out = page;
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/*
|
|
202
|
+
* Back to one page to page_list.
|
|
203
|
+
*/
|
|
204
|
+
int funchook_page_free(funchook_t *funchook, funchook_page_t *page)
|
|
205
|
+
{
|
|
206
|
+
page_list_t *pl = (page_list_t *)((size_t)page & ~(allocation_unit - 1));
|
|
207
|
+
size_t idx = ((size_t)page - (size_t)pl) / page_size - 1;
|
|
208
|
+
BOOL ok;
|
|
209
|
+
|
|
210
|
+
ok = VirtualFree(page, page_size, MEM_DECOMMIT);
|
|
211
|
+
if (!ok) {
|
|
212
|
+
DWORD err = GetLastError();
|
|
213
|
+
char errbuf[128];
|
|
214
|
+
|
|
215
|
+
funchook_set_error_message(funchook, "Failed to decommit page %p (base=%p(used=%d), idx=%"SIZE_T_FMT"u, size=%"SIZE_T_FMT"u, error=%lu(%s))",
|
|
216
|
+
page, pl, pl->num_used, idx, page_size,
|
|
217
|
+
err, to_errmsg(err, errbuf, sizeof(errbuf)));
|
|
218
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
219
|
+
}
|
|
220
|
+
funchook_log(funchook, " decommit page %p (base=%p(used=%d), idx=%"SIZE_T_FMT"u, size=%"SIZE_T_FMT"u)\n",
|
|
221
|
+
page, pl, pl->num_used, idx, page_size);
|
|
222
|
+
pl->num_used--;
|
|
223
|
+
pl->used[idx] = 0;
|
|
224
|
+
if (pl->num_used != 0) {
|
|
225
|
+
return 0;
|
|
226
|
+
}
|
|
227
|
+
/* all pages in this allocation unit are decommitted. delete this page_list */
|
|
228
|
+
pl->next->prev = pl->prev;
|
|
229
|
+
pl->prev->next = pl->next;
|
|
230
|
+
ok = VirtualFree(pl, 0, MEM_RELEASE);
|
|
231
|
+
if (!ok) {
|
|
232
|
+
DWORD err = GetLastError();
|
|
233
|
+
char errbuf[128];
|
|
234
|
+
|
|
235
|
+
funchook_set_error_message(funchook, "Failed to release memory %p (size=%"SIZE_T_FMT"u, error=%lu(%s))",
|
|
236
|
+
pl, allocation_unit,
|
|
237
|
+
err, to_errmsg(err, errbuf, sizeof(errbuf)));
|
|
238
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
239
|
+
}
|
|
240
|
+
funchook_log(funchook, " release memory %p (size=%"SIZE_T_FMT"u)\n",
|
|
241
|
+
pl, allocation_unit);
|
|
242
|
+
return 0;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
int funchook_page_protect(funchook_t *funchook, funchook_page_t *page)
|
|
246
|
+
{
|
|
247
|
+
char errbuf[128];
|
|
248
|
+
DWORD oldprot;
|
|
249
|
+
BOOL ok = VirtualProtect(page, page_size, PAGE_EXECUTE_READ, &oldprot);
|
|
250
|
+
|
|
251
|
+
if (ok) {
|
|
252
|
+
funchook_log(funchook, " protect page %p (size=%"SIZE_T_FMT"u, prot=read,exec)\n",
|
|
253
|
+
page, page_size);
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
256
|
+
funchook_set_error_message(funchook, "Failed to protect page %p (size=%"SIZE_T_FMT"u, prot=read,exec, error=%lu(%s))",
|
|
257
|
+
page, page_size,
|
|
258
|
+
GetLastError(), to_errmsg(GetLastError(), errbuf, sizeof(errbuf)));
|
|
259
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
int funchook_page_unprotect(funchook_t *funchook, funchook_page_t *page)
|
|
263
|
+
{
|
|
264
|
+
char errbuf[128];
|
|
265
|
+
DWORD oldprot;
|
|
266
|
+
BOOL ok = VirtualProtect(page, page_size, PAGE_READWRITE, &oldprot);
|
|
267
|
+
|
|
268
|
+
if (ok) {
|
|
269
|
+
funchook_log(funchook, " unprotect page %p (size=%"SIZE_T_FMT"u, prot=read,write)\n",
|
|
270
|
+
page, page_size);
|
|
271
|
+
return 0;
|
|
272
|
+
}
|
|
273
|
+
funchook_set_error_message(funchook, "Failed to unprotect page %p (size=%"SIZE_T_FMT"u, prot=read,write, error=%lu(%s))",
|
|
274
|
+
page, page_size,
|
|
275
|
+
GetLastError(), to_errmsg(GetLastError(), errbuf, sizeof(errbuf)));
|
|
276
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
int funchook_unprotect_begin(funchook_t *funchook, mem_state_t *mstate, void *start, size_t len)
|
|
280
|
+
{
|
|
281
|
+
char errbuf[128];
|
|
282
|
+
size_t saddr = ROUND_DOWN((size_t)start, page_size);
|
|
283
|
+
BOOL ok;
|
|
284
|
+
|
|
285
|
+
mstate->addr = (void*)saddr;
|
|
286
|
+
mstate->size = len + (size_t)start - saddr;
|
|
287
|
+
mstate->size = ROUND_UP(mstate->size, page_size);
|
|
288
|
+
ok = VirtualProtect(mstate->addr, mstate->size, PAGE_EXECUTE_READWRITE, &mstate->protect);
|
|
289
|
+
if (ok) {
|
|
290
|
+
funchook_log(funchook, " unprotect memory %p (size=%"SIZE_T_FMT"u) <- %p (size=%"SIZE_T_FMT"u)\n",
|
|
291
|
+
mstate->addr, mstate->size, start, len);
|
|
292
|
+
return 0;
|
|
293
|
+
}
|
|
294
|
+
funchook_set_error_message(funchook, "Failed to unprotect memory %p (size=%"SIZE_T_FMT"u) <- %p (size=%"SIZE_T_FMT"u, error=%lu(%s))",
|
|
295
|
+
mstate->addr, mstate->size, start, len,
|
|
296
|
+
GetLastError(), to_errmsg(GetLastError(), errbuf, sizeof(errbuf)));
|
|
297
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
int funchook_unprotect_end(funchook_t *funchook, const mem_state_t *mstate)
|
|
301
|
+
{
|
|
302
|
+
char errbuf[128];
|
|
303
|
+
DWORD oldprot;
|
|
304
|
+
BOOL ok = VirtualProtect(mstate->addr, mstate->size, mstate->protect, &oldprot);
|
|
305
|
+
|
|
306
|
+
if (ok) {
|
|
307
|
+
funchook_log(funchook, " protect memory %p (size=%"SIZE_T_FMT"u)\n",
|
|
308
|
+
mstate->addr, mstate->size);
|
|
309
|
+
return 0;
|
|
310
|
+
}
|
|
311
|
+
funchook_set_error_message(funchook, "Failed to protect memory %p (size=%"SIZE_T_FMT"u, error=%lu(%s))",
|
|
312
|
+
mstate->addr, mstate->size,
|
|
313
|
+
GetLastError(), to_errmsg(GetLastError(), errbuf, sizeof(errbuf)));
|
|
314
|
+
return FUNCHOOK_ERROR_MEMORY_FUNCTION;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
static IMAGE_IMPORT_DESCRIPTOR *get_image_import_descriptor(HMODULE hMod, DWORD *cnt)
|
|
318
|
+
{
|
|
319
|
+
IMAGE_DOS_HEADER *doshdr;
|
|
320
|
+
IMAGE_NT_HEADERS *nthdr;
|
|
321
|
+
IMAGE_DATA_DIRECTORY *dir;
|
|
322
|
+
|
|
323
|
+
if (memcmp(hMod, "MZ", 2) != 0) {
|
|
324
|
+
return NULL;
|
|
325
|
+
}
|
|
326
|
+
doshdr = (IMAGE_DOS_HEADER*)hMod;
|
|
327
|
+
nthdr = (PIMAGE_NT_HEADERS)((size_t)hMod + doshdr->e_lfanew);
|
|
328
|
+
dir = &nthdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
|
329
|
+
if (dir->VirtualAddress == 0) {
|
|
330
|
+
return NULL;
|
|
331
|
+
}
|
|
332
|
+
*cnt = dir->Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
|
333
|
+
return (IMAGE_IMPORT_DESCRIPTOR*)((size_t)hMod + dir->VirtualAddress);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
void *funchook_resolve_func(funchook_t *funchook, void *func)
|
|
337
|
+
{
|
|
338
|
+
char path[MAX_PATH];
|
|
339
|
+
HMODULE hMod;
|
|
340
|
+
BOOL ok;
|
|
341
|
+
IMAGE_IMPORT_DESCRIPTOR *desc_head, *desc;
|
|
342
|
+
uint8_t *fn = (uint8_t*)func;
|
|
343
|
+
size_t pos = 0;
|
|
344
|
+
DWORD cnt;
|
|
345
|
+
|
|
346
|
+
if (*funchook_debug_file != '\0') {
|
|
347
|
+
DWORD len = GetMappedFileNameA(GetCurrentProcess(), func, path, sizeof(path));
|
|
348
|
+
if (len > 0) {
|
|
349
|
+
funchook_log(funchook, " func %p is in %.*s\n", func, (int)len, path);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (fn[0] == 0xe9) {
|
|
353
|
+
fn = (fn + 5) + *(int*)(fn + 1);
|
|
354
|
+
funchook_log(funchook, " relative jump to %p\n", fn);
|
|
355
|
+
}
|
|
356
|
+
if (fn[0] == 0xff && fn[1] == 0x25) {
|
|
357
|
+
#ifdef CPU_X86_64
|
|
358
|
+
pos = (size_t)(fn + 6) + *(int*)(fn + 2);
|
|
359
|
+
#else
|
|
360
|
+
pos = *(size_t*)(fn + 2);
|
|
361
|
+
#endif
|
|
362
|
+
funchook_log(funchook, " indirect jump to addresss at %p\n", (void*)pos);
|
|
363
|
+
}
|
|
364
|
+
if (pos == 0) {
|
|
365
|
+
return func;
|
|
366
|
+
}
|
|
367
|
+
ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, func, &hMod);
|
|
368
|
+
if (!ok) {
|
|
369
|
+
return func;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
desc_head = get_image_import_descriptor(hMod, &cnt);
|
|
373
|
+
if (desc_head == NULL) {
|
|
374
|
+
return func;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
for (desc = desc_head; desc->Name != 0; desc++) {
|
|
378
|
+
IMAGE_THUNK_DATA *addr_thunk = (IMAGE_THUNK_DATA*)((char*)hMod + desc->FirstThunk);
|
|
379
|
+
|
|
380
|
+
while (addr_thunk->u1.Function != 0) {
|
|
381
|
+
if (pos == (size_t)&addr_thunk->u1.Function) {
|
|
382
|
+
func = (void*)addr_thunk->u1.Function;
|
|
383
|
+
if (*funchook_debug_file != '\0') {
|
|
384
|
+
DWORD len = GetMappedFileNameA(GetCurrentProcess(), func, path, sizeof(path));
|
|
385
|
+
if (len > 0) {
|
|
386
|
+
funchook_log(funchook, " -> func %p in %.*s\n", func, (int)len, path);
|
|
387
|
+
} else {
|
|
388
|
+
funchook_log(funchook, " -> func %p\n", func);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return func;
|
|
392
|
+
}
|
|
393
|
+
addr_thunk++;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return func;
|
|
397
|
+
}
|
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
/* -*- indent-tabs-mode: nil -*-
|
|
2
|
+
*
|
|
3
|
+
* This file is part of Funchook.
|
|
4
|
+
* https://github.com/kubo/funchook
|
|
5
|
+
*
|
|
6
|
+
* Funchook is free software: you can redistribute it and/or modify it
|
|
7
|
+
* under the terms of the GNU General Public License as published by the
|
|
8
|
+
* Free Software Foundation, either version 2 of the License, or (at your
|
|
9
|
+
* option) any later version.
|
|
10
|
+
*
|
|
11
|
+
* As a special exception, the copyright holders of this library give you
|
|
12
|
+
* permission to link this library with independent modules to produce an
|
|
13
|
+
* executable, regardless of the license terms of these independent
|
|
14
|
+
* modules, and to copy and distribute the resulting executable under
|
|
15
|
+
* terms of your choice, provided that you also meet, for each linked
|
|
16
|
+
* independent module, the terms and conditions of the license of that
|
|
17
|
+
* module. An independent module is a module which is not derived from or
|
|
18
|
+
* based on this library. If you modify this library, you may extend this
|
|
19
|
+
* exception to your version of the library, but you are not obliged to
|
|
20
|
+
* do so. If you do not wish to do so, delete this exception statement
|
|
21
|
+
* from your version.
|
|
22
|
+
*
|
|
23
|
+
* Funchook is distributed in the hope that it will be useful, but WITHOUT
|
|
24
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
25
|
+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
26
|
+
* for more details.
|
|
27
|
+
*
|
|
28
|
+
* You should have received a copy of the GNU General Public License
|
|
29
|
+
* along with Funchook. If not, see <http://www.gnu.org/licenses/>.
|
|
30
|
+
*/
|
|
31
|
+
#include "config.h"
|
|
32
|
+
#include <stdio.h>
|
|
33
|
+
#include <stdlib.h>
|
|
34
|
+
#include <stdint.h>
|
|
35
|
+
#include <string.h>
|
|
36
|
+
#include <distorm.h>
|
|
37
|
+
#include <mnemonics.h>
|
|
38
|
+
#ifdef WIN32
|
|
39
|
+
#include <windows.h>
|
|
40
|
+
#endif
|
|
41
|
+
#include "funchook_internal.h"
|
|
42
|
+
|
|
43
|
+
/* RIP-relative address information */
|
|
44
|
+
typedef struct {
|
|
45
|
+
uint8_t *addr; /* absolute address */
|
|
46
|
+
intptr_t raddr; /* relative address */
|
|
47
|
+
int offset;
|
|
48
|
+
int size;
|
|
49
|
+
} rip_relative_t;
|
|
50
|
+
|
|
51
|
+
typedef struct {
|
|
52
|
+
funchook_t *funchook;
|
|
53
|
+
rip_displacement_t *rip_disp;
|
|
54
|
+
const uint8_t *src;
|
|
55
|
+
const uint8_t *dst_base;
|
|
56
|
+
uint8_t *dst;
|
|
57
|
+
} make_trampoline_context_t;
|
|
58
|
+
|
|
59
|
+
#define NOP_INSTRUCTION 0x90
|
|
60
|
+
|
|
61
|
+
#if defined(__i386)
|
|
62
|
+
static int handle_x86_get_pc_thunk(make_trampoline_context_t *ctx, const _DInst *di);
|
|
63
|
+
static int handle_x86_get_pc_by_call_and_pop(make_trampoline_context_t *ctx, const _DInst *di);
|
|
64
|
+
#else
|
|
65
|
+
#define handle_x86_get_pc_thunk(ctx, di) (0)
|
|
66
|
+
#define handle_x86_get_pc_by_call_and_pop(ctx, di) (0)
|
|
67
|
+
#endif
|
|
68
|
+
|
|
69
|
+
static void log_instruction(funchook_t *funchook, const _CodeInfo *ci, const _DInst *dis);
|
|
70
|
+
static void get_rip_relative(const make_trampoline_context_t *ctx, rip_relative_t *rel_disp, rip_relative_t *rel_imm, const _DInst *di);
|
|
71
|
+
static int handle_rip_relative(make_trampoline_context_t *ctx, const rip_relative_t *rel, const _DInst *di);
|
|
72
|
+
|
|
73
|
+
int funchook_write_jump32(funchook_t *funchook, const uint8_t *src, const uint8_t *dst, uint8_t *out)
|
|
74
|
+
{
|
|
75
|
+
out[0] = 0xe9;
|
|
76
|
+
*(int*)(out + 1) = (int)(dst - (src + 5));
|
|
77
|
+
funchook_log(funchook, " Write jump32 0x%0"SIZE_T_WIDTH SIZE_T_FMT"x -> 0x%0"SIZE_T_WIDTH SIZE_T_FMT"x\n",
|
|
78
|
+
(size_t)src, (size_t)dst);
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#ifdef CPU_X86_64
|
|
83
|
+
|
|
84
|
+
int funchook_write_jump64(funchook_t *funchook, uint8_t *src, const uint8_t *dst)
|
|
85
|
+
{
|
|
86
|
+
src[0] = 0xFF;
|
|
87
|
+
src[1] = 0x25;
|
|
88
|
+
src[2] = 0x00;
|
|
89
|
+
src[3] = 0x00;
|
|
90
|
+
src[4] = 0x00;
|
|
91
|
+
src[5] = 0x00;
|
|
92
|
+
*(const uint8_t**)(src + 6) = dst;
|
|
93
|
+
funchook_log(funchook, " Write jump64 0x%0"SIZE_T_WIDTH SIZE_T_FMT"x -> 0x%0"SIZE_T_WIDTH SIZE_T_FMT"x\n",
|
|
94
|
+
(size_t)src, (size_t)dst);
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
int funchook_within_32bit_relative(const uint8_t *src, const uint8_t *dst)
|
|
99
|
+
{
|
|
100
|
+
int64_t diff = (int64_t)(dst - src);
|
|
101
|
+
return (INT32_MIN <= diff && diff <= INT32_MAX);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
int funchook_jump32_avail(const uint8_t *src, const uint8_t *dst)
|
|
105
|
+
{
|
|
106
|
+
return funchook_within_32bit_relative(src + 5, dst);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
#endif
|
|
110
|
+
|
|
111
|
+
int funchook_make_trampoline(funchook_t *funchook, rip_displacement_t *disp, const uint8_t *func, uint8_t *trampoline)
|
|
112
|
+
{
|
|
113
|
+
make_trampoline_context_t ctx;
|
|
114
|
+
_DInst dis[MAX_INSN_CHECK_SIZE];
|
|
115
|
+
unsigned int di_cnt = 0;
|
|
116
|
+
_CodeInfo ci;
|
|
117
|
+
_DecodeResult decres;
|
|
118
|
+
int rv;
|
|
119
|
+
unsigned int i;
|
|
120
|
+
|
|
121
|
+
memset(trampoline, NOP_INSTRUCTION, TRAMPOLINE_SIZE);
|
|
122
|
+
ctx.funchook = funchook;
|
|
123
|
+
ctx.rip_disp = disp;
|
|
124
|
+
ctx.src = func;
|
|
125
|
+
ctx.dst_base = ctx.dst = trampoline;
|
|
126
|
+
|
|
127
|
+
ci.codeOffset = (_OffsetType)(size_t)func;
|
|
128
|
+
ci.code = func;
|
|
129
|
+
ci.codeLen = MAX_INSN_CHECK_SIZE;
|
|
130
|
+
#ifdef CPU_X86_64
|
|
131
|
+
ci.dt = Decode64Bits;
|
|
132
|
+
#else
|
|
133
|
+
ci.dt = Decode32Bits;
|
|
134
|
+
#endif
|
|
135
|
+
ci.features = DF_STOP_ON_RET;
|
|
136
|
+
decres = distorm_decompose64(&ci, dis, MAX_INSN_CHECK_SIZE, &di_cnt);
|
|
137
|
+
if (decres != DECRES_SUCCESS) {
|
|
138
|
+
funchook_set_error_message(funchook, "Disassemble Error: %d", decres);
|
|
139
|
+
return FUNCHOOK_ERROR_DISASSEMBLY;
|
|
140
|
+
}
|
|
141
|
+
funchook_log(funchook, " Original Instructions:\n");
|
|
142
|
+
for (i = 0; i < di_cnt; i++) {
|
|
143
|
+
const _DInst *di = &dis[i];
|
|
144
|
+
rip_relative_t rel_disp;
|
|
145
|
+
rip_relative_t rel_imm;
|
|
146
|
+
|
|
147
|
+
log_instruction(funchook, &ci, di);
|
|
148
|
+
|
|
149
|
+
if (handle_x86_get_pc_thunk(&ctx, di)) {
|
|
150
|
+
;
|
|
151
|
+
} else if (handle_x86_get_pc_by_call_and_pop(&ctx, di)) {
|
|
152
|
+
di = &dis[++i];
|
|
153
|
+
log_instruction(funchook, &ci, di);
|
|
154
|
+
} else {
|
|
155
|
+
memcpy(ctx.dst, ctx.src, di->size);
|
|
156
|
+
get_rip_relative(&ctx, &rel_disp, &rel_imm, di);
|
|
157
|
+
rv = handle_rip_relative(&ctx, &rel_disp, di);
|
|
158
|
+
if (rv != 0) {
|
|
159
|
+
return rv;
|
|
160
|
+
}
|
|
161
|
+
rv = handle_rip_relative(&ctx, &rel_imm, di);
|
|
162
|
+
if (rv != 0) {
|
|
163
|
+
return rv;
|
|
164
|
+
}
|
|
165
|
+
ctx.src += di->size;
|
|
166
|
+
ctx.dst += di->size;
|
|
167
|
+
}
|
|
168
|
+
if (ctx.src - func >= JUMP32_SIZE) {
|
|
169
|
+
ctx.dst[0] = 0xe9; /* unconditional jump */
|
|
170
|
+
disp[0].dst_addr = ctx.src;
|
|
171
|
+
disp[0].src_addr_offset = (ctx.dst - ctx.dst_base) + 5;
|
|
172
|
+
disp[0].pos_offset = (ctx.dst - ctx.dst_base) + 1;
|
|
173
|
+
while (++i < di_cnt) {
|
|
174
|
+
const _DInst *di = &dis[i];
|
|
175
|
+
log_instruction(funchook, &ci, di);
|
|
176
|
+
get_rip_relative(&ctx, &rel_disp, &rel_imm, di);
|
|
177
|
+
if (func < rel_imm.addr && rel_imm.addr < func + JUMP32_SIZE) {
|
|
178
|
+
/* jump to the hot-patched region. */
|
|
179
|
+
funchook_set_error_message(funchook, "instruction jumping back to the hot-patched region was found");
|
|
180
|
+
return FUNCHOOK_ERROR_FOUND_BACK_JUMP;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/* too short function. Check whether NOP instructions continue. */
|
|
187
|
+
while (ctx.src - func < JUMP32_SIZE) {
|
|
188
|
+
if (*ctx.src != NOP_INSTRUCTION) {
|
|
189
|
+
funchook_set_error_message(funchook, "Too short instructions");
|
|
190
|
+
return FUNCHOOK_ERROR_TOO_SHORT_INSTRUCTIONS;
|
|
191
|
+
}
|
|
192
|
+
ctx.src++;
|
|
193
|
+
}
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
void funchook_log_trampoline(funchook_t *funchook, const uint8_t *trampoline)
|
|
198
|
+
{
|
|
199
|
+
_DInst dis[TRAMPOLINE_SIZE];
|
|
200
|
+
unsigned int di_cnt = 0;
|
|
201
|
+
_CodeInfo ci;
|
|
202
|
+
_DecodeResult decres;
|
|
203
|
+
unsigned int i;
|
|
204
|
+
|
|
205
|
+
if (*funchook_debug_file == '\0') {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
funchook_log(funchook, " Trampoline Instructions:\n");
|
|
210
|
+
ci.codeOffset = (_OffsetType)(size_t)trampoline;
|
|
211
|
+
ci.code = trampoline;
|
|
212
|
+
ci.codeLen = TRAMPOLINE_SIZE;
|
|
213
|
+
#ifdef CPU_X86_64
|
|
214
|
+
ci.dt = Decode64Bits;
|
|
215
|
+
#else
|
|
216
|
+
ci.dt = Decode32Bits;
|
|
217
|
+
#endif
|
|
218
|
+
ci.features = DF_NONE;
|
|
219
|
+
decres = distorm_decompose64(&ci, dis, TRAMPOLINE_SIZE, &di_cnt);
|
|
220
|
+
if (decres != DECRES_SUCCESS) {
|
|
221
|
+
funchook_log(funchook, " Failed to decode trampoline\n ");
|
|
222
|
+
for (i = 0; i < TRAMPOLINE_SIZE; i++) {
|
|
223
|
+
funchook_log(funchook, " %02x", trampoline[i]);
|
|
224
|
+
}
|
|
225
|
+
funchook_log(funchook, "\n");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
while (di_cnt > 0 && dis[di_cnt - 1].opcode == I_NOP) {
|
|
229
|
+
di_cnt--;
|
|
230
|
+
}
|
|
231
|
+
for (i = 0; i < di_cnt; i++) {
|
|
232
|
+
_DecodedInst dec;
|
|
233
|
+
distorm_format64(&ci, &dis[i], &dec);
|
|
234
|
+
funchook_log(funchook, " %0"SIZE_T_WIDTH SIZE_T_FMT"x (%02d) %-24s %s%s%s\n",
|
|
235
|
+
(size_t)dec.offset, dec.size, (char*)dec.instructionHex.p,
|
|
236
|
+
(char*)dec.mnemonic.p, dec.operands.length != 0 ? " " : "", (char*)dec.operands.p);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
#ifndef handle_x86_get_pc_thunk
|
|
241
|
+
/* special cases to handle "call __x86.get_pc_thunk.??"
|
|
242
|
+
* If the target instructions are "movl (%esp), %???; ret",
|
|
243
|
+
* use "movl di->addr + 5, %???" instead.
|
|
244
|
+
*/
|
|
245
|
+
static int handle_x86_get_pc_thunk(make_trampoline_context_t *ctx, const _DInst *di)
|
|
246
|
+
{
|
|
247
|
+
uint32_t eip = 0;
|
|
248
|
+
const char *reg_name = NULL;
|
|
249
|
+
|
|
250
|
+
if (*ctx->src == 0xe8) {
|
|
251
|
+
uint32_t first_4_bytes = *(uint32_t*)(size_t)INSTRUCTION_GET_TARGET(di);
|
|
252
|
+
|
|
253
|
+
eip = (uint32_t)(di->addr + 5);
|
|
254
|
+
switch (first_4_bytes) {
|
|
255
|
+
case 0xc324048b: /* 8b 04 24 c3: movl (%esp), %eax; ret */
|
|
256
|
+
reg_name = "ax";
|
|
257
|
+
*ctx->dst = 0xb8; /* movl di->addr + 5, %eax */
|
|
258
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
259
|
+
goto fixed;
|
|
260
|
+
case 0xc3241c8b: /* 8b 1c 24 c3: movl (%esp), %ebx; ret */
|
|
261
|
+
reg_name = "bx";
|
|
262
|
+
*ctx->dst = 0xbb; /* movl di->addr + 5, %ebx */
|
|
263
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
264
|
+
goto fixed;
|
|
265
|
+
case 0xc3240c8b: /* 8b 0c 24 c3: movl (%esp), %ecx; ret */
|
|
266
|
+
reg_name = "cx";
|
|
267
|
+
*ctx->dst = 0xb9; /* movl di->addr + 5, %ecx */
|
|
268
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
269
|
+
goto fixed;
|
|
270
|
+
case 0xc324148b: /* 8b 14 24 c3: movl (%esp), %edx; ret */
|
|
271
|
+
reg_name = "dx";
|
|
272
|
+
*ctx->dst = 0xba; /* movl di->addr + 5, %edx */
|
|
273
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
274
|
+
goto fixed;
|
|
275
|
+
case 0xc324348b: /* 8b 34 24 c3: movl (%esp), %esi; ret */
|
|
276
|
+
reg_name = "si";
|
|
277
|
+
*ctx->dst = 0xbe; /* movl di->addr + 5, %esi */
|
|
278
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
279
|
+
goto fixed;
|
|
280
|
+
case 0xc3243c8b: /* 8b 3c 24 c3: movl (%esp), %edi; ret */
|
|
281
|
+
reg_name = "di";
|
|
282
|
+
*ctx->dst = 0xbf; /* movl di->addr + 5, %edi */
|
|
283
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
284
|
+
goto fixed;
|
|
285
|
+
case 0xc3242c8b: /* 8b 2c 24 c3: movl (%esp), %ebp; ret */
|
|
286
|
+
reg_name = "bp";
|
|
287
|
+
*ctx->dst = 0xbd; /* movl di->addr + 5, %ebp */
|
|
288
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
289
|
+
goto fixed;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return 0;
|
|
293
|
+
|
|
294
|
+
fixed:
|
|
295
|
+
funchook_log(ctx->funchook, " use 'MOV E%c%c, 0x%x' instead of 'CALL __x86.get_pc_thunk.%s'\n",
|
|
296
|
+
reg_name[0] + 'A' - 'a',
|
|
297
|
+
reg_name[1] + 'A' - 'a',
|
|
298
|
+
eip, reg_name);
|
|
299
|
+
ctx->dst += 5;
|
|
300
|
+
ctx->src += 5;
|
|
301
|
+
return 1;
|
|
302
|
+
}
|
|
303
|
+
#endif
|
|
304
|
+
|
|
305
|
+
#ifndef handle_x86_get_pc_by_call_and_pop
|
|
306
|
+
static int handle_x86_get_pc_by_call_and_pop(make_trampoline_context_t *ctx, const _DInst *di)
|
|
307
|
+
{
|
|
308
|
+
uint32_t eip = 0;
|
|
309
|
+
const char *reg_name = NULL;
|
|
310
|
+
|
|
311
|
+
if (*ctx->src == 0xe8 && *(uint32_t*)(ctx->src + 1) == 0) {
|
|
312
|
+
eip = (uint32_t)(di->addr + 5);
|
|
313
|
+
switch (*(ctx->src + 5)) {
|
|
314
|
+
case 0x58: /* pop %eax */
|
|
315
|
+
reg_name = "EAX";
|
|
316
|
+
*ctx->dst = 0xb8; /* movl di->addr + 5, %eax */
|
|
317
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
318
|
+
goto fixed;
|
|
319
|
+
case 0x5b: /* pop %ebx */
|
|
320
|
+
reg_name = "EBX";
|
|
321
|
+
*ctx->dst = 0xbb; /* movl di->addr + 5, %ebx */
|
|
322
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
323
|
+
goto fixed;
|
|
324
|
+
case 0x59: /* pop %ecx */
|
|
325
|
+
reg_name = "ECX";
|
|
326
|
+
*ctx->dst = 0xb9; /* movl di->addr + 5, %ecx */
|
|
327
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
328
|
+
goto fixed;
|
|
329
|
+
case 0x5a: /* pop %edx */
|
|
330
|
+
reg_name = "EDX";
|
|
331
|
+
*ctx->dst = 0xba; /* movl di->addr + 5, %edx */
|
|
332
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
333
|
+
goto fixed;
|
|
334
|
+
case 0x5e: /* pop %esi */
|
|
335
|
+
reg_name = "ESI";
|
|
336
|
+
*ctx->dst = 0xbe; /* movl di->addr + 5, %esi */
|
|
337
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
338
|
+
goto fixed;
|
|
339
|
+
case 0x5f: /* pop %edi */
|
|
340
|
+
reg_name = "EDI";
|
|
341
|
+
*ctx->dst = 0xbf; /* movl di->addr + 5, %edi */
|
|
342
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
343
|
+
goto fixed;
|
|
344
|
+
case 0x5d: /* pop %ebp */
|
|
345
|
+
reg_name = "EBP";
|
|
346
|
+
*ctx->dst = 0xbd; /* movl di->addr + 5, %ebp */
|
|
347
|
+
*(uint32_t*)(ctx->dst + 1) = eip;
|
|
348
|
+
goto fixed;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return 0;
|
|
352
|
+
|
|
353
|
+
fixed:
|
|
354
|
+
funchook_log(ctx->funchook, " use 'MOV %s, 0x%x' instead of 'CALL 0x%x; POP %s'\n",
|
|
355
|
+
reg_name, eip, eip, reg_name);
|
|
356
|
+
ctx->dst += 5;
|
|
357
|
+
ctx->src += 6;
|
|
358
|
+
return 1;
|
|
359
|
+
|
|
360
|
+
}
|
|
361
|
+
#endif
|
|
362
|
+
|
|
363
|
+
static void log_instruction(funchook_t *funchook, const _CodeInfo *ci, const _DInst *dis)
|
|
364
|
+
{
|
|
365
|
+
_DecodedInst dec;
|
|
366
|
+
distorm_format64(ci, dis, &dec);
|
|
367
|
+
funchook_log(funchook, " %0"SIZE_T_WIDTH SIZE_T_FMT"x (%02d) %-24s %s%s%s\n",
|
|
368
|
+
(size_t)dec.offset, dec.size, (char*)dec.instructionHex.p,
|
|
369
|
+
(char*)dec.mnemonic.p, dec.operands.length != 0 ? " " : "", (char*)dec.operands.p);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
static void get_rip_relative(const make_trampoline_context_t *ctx, rip_relative_t *rel_disp, rip_relative_t *rel_imm, const _DInst *di)
|
|
373
|
+
{
|
|
374
|
+
int opsiz = 0;
|
|
375
|
+
int disp_offset = 0;
|
|
376
|
+
int imm_offset = 0;
|
|
377
|
+
int i;
|
|
378
|
+
|
|
379
|
+
memset(rel_disp, 0, sizeof(rip_relative_t));
|
|
380
|
+
memset(rel_imm, 0, sizeof(rip_relative_t));
|
|
381
|
+
|
|
382
|
+
/*
|
|
383
|
+
* Estimate total operand size and RIP-relative address offsets.
|
|
384
|
+
*/
|
|
385
|
+
for (i = 0; i < OPERANDS_NO && di->ops[i].type != O_NONE; i++) {
|
|
386
|
+
const _Operand *op = &di->ops[i];
|
|
387
|
+
switch (op->type) {
|
|
388
|
+
case O_IMM:
|
|
389
|
+
opsiz += op->size / 8;
|
|
390
|
+
break;
|
|
391
|
+
case O_PC:
|
|
392
|
+
rel_imm->addr = (uint8_t*)(size_t)(di->addr + di->size + di->imm.addr);
|
|
393
|
+
rel_imm->raddr = (intptr_t)di->imm.addr;
|
|
394
|
+
rel_imm->size = op->size;
|
|
395
|
+
imm_offset = opsiz;
|
|
396
|
+
opsiz += op->size / 8;
|
|
397
|
+
break;
|
|
398
|
+
case O_SMEM:
|
|
399
|
+
if (di->dispSize != 0 && op->index == R_RIP) {
|
|
400
|
+
rel_disp->addr = (uint8_t*)(size_t)(di->addr + di->size + di->disp);
|
|
401
|
+
rel_disp->raddr = (intptr_t)di->disp;
|
|
402
|
+
rel_disp->size = di->dispSize;
|
|
403
|
+
disp_offset = opsiz;
|
|
404
|
+
}
|
|
405
|
+
opsiz += di->dispSize / 8;
|
|
406
|
+
break;
|
|
407
|
+
case O_MEM:
|
|
408
|
+
case O_DISP:
|
|
409
|
+
opsiz += di->dispSize / 8;
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
switch (di->opcode) {
|
|
414
|
+
/* CMPSD */
|
|
415
|
+
case I_CMPEQSD:
|
|
416
|
+
case I_CMPLTSD:
|
|
417
|
+
case I_CMPLESD:
|
|
418
|
+
case I_CMPUNORDSD:
|
|
419
|
+
case I_CMPNEQSD:
|
|
420
|
+
case I_CMPNLTSD:
|
|
421
|
+
case I_CMPNLESD:
|
|
422
|
+
case I_CMPORDSD:
|
|
423
|
+
case I_VCMPEQSD:
|
|
424
|
+
case I_VCMPLTSD:
|
|
425
|
+
case I_VCMPLESD:
|
|
426
|
+
case I_VCMPUNORDSD:
|
|
427
|
+
case I_VCMPNEQSD:
|
|
428
|
+
case I_VCMPNLTSD:
|
|
429
|
+
case I_VCMPNLESD:
|
|
430
|
+
case I_VCMPORDSD:
|
|
431
|
+
case I_VCMPEQ_UQSD:
|
|
432
|
+
case I_VCMPNGESD:
|
|
433
|
+
case I_VCMPNGTSD:
|
|
434
|
+
case I_VCMPFALSESD:
|
|
435
|
+
case I_VCMPNEQ_OQSD:
|
|
436
|
+
case I_VCMPGESD:
|
|
437
|
+
case I_VCMPGTSD:
|
|
438
|
+
case I_VCMPTRUESD:
|
|
439
|
+
case I_VCMPEQ_OSSD:
|
|
440
|
+
case I_VCMPLT_OQSD:
|
|
441
|
+
case I_VCMPLE_OQSD:
|
|
442
|
+
case I_VCMPUNORD_SSD:
|
|
443
|
+
case I_VCMPNEQ_USSD:
|
|
444
|
+
case I_VCMPNLT_UQSD:
|
|
445
|
+
case I_VCMPNLE_UQSD:
|
|
446
|
+
case I_VCMPORD_SSD:
|
|
447
|
+
case I_VCMPEQ_USSD:
|
|
448
|
+
case I_VCMPNGE_UQSD:
|
|
449
|
+
case I_VCMPNGT_UQSD:
|
|
450
|
+
case I_VCMPFALSE_OSSD:
|
|
451
|
+
case I_VCMPNEQ_OSSD:
|
|
452
|
+
case I_VCMPGE_OQSD:
|
|
453
|
+
case I_VCMPGT_OQSD:
|
|
454
|
+
/* CMPSS */
|
|
455
|
+
case I_CMPEQSS:
|
|
456
|
+
case I_CMPLTSS:
|
|
457
|
+
case I_CMPLESS:
|
|
458
|
+
case I_CMPUNORDSS:
|
|
459
|
+
case I_CMPNEQSS:
|
|
460
|
+
case I_CMPNLTSS:
|
|
461
|
+
case I_CMPNLESS:
|
|
462
|
+
case I_CMPORDSS:
|
|
463
|
+
case I_VCMPEQSS:
|
|
464
|
+
case I_VCMPLTSS:
|
|
465
|
+
case I_VCMPLESS:
|
|
466
|
+
case I_VCMPUNORDSS:
|
|
467
|
+
case I_VCMPNEQSS:
|
|
468
|
+
case I_VCMPNLTSS:
|
|
469
|
+
case I_VCMPNLESS:
|
|
470
|
+
case I_VCMPORDSS:
|
|
471
|
+
case I_VCMPEQ_UQSS:
|
|
472
|
+
case I_VCMPNGESS:
|
|
473
|
+
case I_VCMPNGTSS:
|
|
474
|
+
case I_VCMPFALSESS:
|
|
475
|
+
case I_VCMPNEQ_OQSS:
|
|
476
|
+
case I_VCMPGESS:
|
|
477
|
+
case I_VCMPGTSS:
|
|
478
|
+
case I_VCMPTRUESS:
|
|
479
|
+
case I_VCMPEQ_OSSS:
|
|
480
|
+
case I_VCMPLT_OQSS:
|
|
481
|
+
case I_VCMPLE_OQSS:
|
|
482
|
+
case I_VCMPUNORD_SSS:
|
|
483
|
+
case I_VCMPNEQ_USSS:
|
|
484
|
+
case I_VCMPNLT_UQSS:
|
|
485
|
+
case I_VCMPNLE_UQSS:
|
|
486
|
+
case I_VCMPORD_SSS:
|
|
487
|
+
case I_VCMPEQ_USSS:
|
|
488
|
+
case I_VCMPNGE_UQSS:
|
|
489
|
+
case I_VCMPNGT_UQSS:
|
|
490
|
+
case I_VCMPFALSE_OSSS:
|
|
491
|
+
case I_VCMPNEQ_OSSS:
|
|
492
|
+
case I_VCMPGE_OQSS:
|
|
493
|
+
case I_VCMPGT_OQSS:
|
|
494
|
+
/* CMPPD */
|
|
495
|
+
case I_CMPEQPD:
|
|
496
|
+
case I_CMPLTPD:
|
|
497
|
+
case I_CMPLEPD:
|
|
498
|
+
case I_CMPUNORDPD:
|
|
499
|
+
case I_CMPNEQPD:
|
|
500
|
+
case I_CMPNLTPD:
|
|
501
|
+
case I_CMPNLEPD:
|
|
502
|
+
case I_CMPORDPD:
|
|
503
|
+
case I_VCMPEQPD:
|
|
504
|
+
case I_VCMPLTPD:
|
|
505
|
+
case I_VCMPLEPD:
|
|
506
|
+
case I_VCMPUNORDPD:
|
|
507
|
+
case I_VCMPNEQPD:
|
|
508
|
+
case I_VCMPNLTPD:
|
|
509
|
+
case I_VCMPNLEPD:
|
|
510
|
+
case I_VCMPORDPD:
|
|
511
|
+
case I_VCMPEQ_UQPD:
|
|
512
|
+
case I_VCMPNGEPD:
|
|
513
|
+
case I_VCMPNGTPD:
|
|
514
|
+
case I_VCMPFALSEPD:
|
|
515
|
+
case I_VCMPNEQ_OQPD:
|
|
516
|
+
case I_VCMPGEPD:
|
|
517
|
+
case I_VCMPGTPD:
|
|
518
|
+
case I_VCMPTRUEPD:
|
|
519
|
+
case I_VCMPEQ_OSPD:
|
|
520
|
+
case I_VCMPLT_OQPD:
|
|
521
|
+
case I_VCMPLE_OQPD:
|
|
522
|
+
case I_VCMPUNORD_SPD:
|
|
523
|
+
case I_VCMPNEQ_USPD:
|
|
524
|
+
case I_VCMPNLT_UQPD:
|
|
525
|
+
case I_VCMPNLE_UQPD:
|
|
526
|
+
case I_VCMPORD_SPD:
|
|
527
|
+
case I_VCMPEQ_USPD:
|
|
528
|
+
case I_VCMPNGE_UQPD:
|
|
529
|
+
case I_VCMPNGT_UQPD:
|
|
530
|
+
case I_VCMPFALSE_OSPD:
|
|
531
|
+
case I_VCMPNEQ_OSPD:
|
|
532
|
+
case I_VCMPGE_OQPD:
|
|
533
|
+
case I_VCMPGT_OQPD:
|
|
534
|
+
case I_VCMPTRUE_USPD:
|
|
535
|
+
/* CMPPS */
|
|
536
|
+
case I_CMPEQPS:
|
|
537
|
+
case I_CMPLTPS:
|
|
538
|
+
case I_CMPLEPS:
|
|
539
|
+
case I_CMPUNORDPS:
|
|
540
|
+
case I_CMPNEQPS:
|
|
541
|
+
case I_CMPNLTPS:
|
|
542
|
+
case I_CMPNLEPS:
|
|
543
|
+
case I_CMPORDPS:
|
|
544
|
+
case I_VCMPEQPS:
|
|
545
|
+
case I_VCMPLTPS:
|
|
546
|
+
case I_VCMPLEPS:
|
|
547
|
+
case I_VCMPUNORDPS:
|
|
548
|
+
case I_VCMPNEQPS:
|
|
549
|
+
case I_VCMPNLTPS:
|
|
550
|
+
case I_VCMPNLEPS:
|
|
551
|
+
case I_VCMPORDPS:
|
|
552
|
+
case I_VCMPEQ_UQPS:
|
|
553
|
+
case I_VCMPNGEPS:
|
|
554
|
+
case I_VCMPNGTPS:
|
|
555
|
+
case I_VCMPFALSEPS:
|
|
556
|
+
case I_VCMPNEQ_OQPS:
|
|
557
|
+
case I_VCMPGEPS:
|
|
558
|
+
case I_VCMPGTPS:
|
|
559
|
+
case I_VCMPTRUEPS:
|
|
560
|
+
case I_VCMPEQ_OSPS:
|
|
561
|
+
case I_VCMPLT_OQPS:
|
|
562
|
+
case I_VCMPLE_OQPS:
|
|
563
|
+
case I_VCMPUNORD_SPS:
|
|
564
|
+
case I_VCMPNEQ_USPS:
|
|
565
|
+
case I_VCMPNLT_UQPS:
|
|
566
|
+
case I_VCMPNLE_UQPS:
|
|
567
|
+
case I_VCMPORD_SPS:
|
|
568
|
+
case I_VCMPEQ_USPS:
|
|
569
|
+
case I_VCMPNGE_UQPS:
|
|
570
|
+
case I_VCMPNGT_UQPS:
|
|
571
|
+
case I_VCMPFALSE_OSPS:
|
|
572
|
+
case I_VCMPNEQ_OSPS:
|
|
573
|
+
case I_VCMPGE_OQPS:
|
|
574
|
+
case I_VCMPGT_OQPS:
|
|
575
|
+
case I_VCMPTRUE_USPS:
|
|
576
|
+
/* ohters */
|
|
577
|
+
case I_PI2FD:
|
|
578
|
+
case I_PI2FW:
|
|
579
|
+
case I_PF2IW:
|
|
580
|
+
case I_PF2ID:
|
|
581
|
+
case I_PSWAPD:
|
|
582
|
+
case I_VPBLENDVB:
|
|
583
|
+
case I_PFNACC:
|
|
584
|
+
opsiz++;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (rel_disp->size > 0) {
|
|
588
|
+
rel_disp->offset = di->size - opsiz + disp_offset;
|
|
589
|
+
funchook_log(ctx->funchook, " ip-relative %08x, absolute address= %0"SIZE_T_WIDTH SIZE_T_FMT"x, offset=%d, size=%d\n",
|
|
590
|
+
(uint32_t)rel_disp->raddr, (size_t)rel_disp->addr, rel_disp->offset, rel_disp->size);
|
|
591
|
+
}
|
|
592
|
+
if (rel_imm->size > 0) {
|
|
593
|
+
rel_imm->offset = di->size - opsiz + imm_offset;
|
|
594
|
+
funchook_log(ctx->funchook, " ip-relative %08x, absolute address= %0"SIZE_T_WIDTH SIZE_T_FMT"x, offset=%d, size=%d\n",
|
|
595
|
+
(uint32_t)rel_imm->raddr, (size_t)rel_imm->addr, rel_imm->offset, rel_imm->size);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/*
|
|
600
|
+
* Fix RIP-relative address in an instruction
|
|
601
|
+
*/
|
|
602
|
+
static int handle_rip_relative(make_trampoline_context_t *ctx, const rip_relative_t *rel, const _DInst *di)
|
|
603
|
+
{
|
|
604
|
+
if (rel->size == 32) {
|
|
605
|
+
if (*(int32_t*)(ctx->dst + rel->offset) != (uint32_t)rel->raddr) {
|
|
606
|
+
/* sanity check.
|
|
607
|
+
* reach here if opsiz and/or disp_offset are incorrectly
|
|
608
|
+
* estimated.
|
|
609
|
+
*/
|
|
610
|
+
funchook_set_error_message(ctx->funchook, "Invalid ip-relative offset %d. The value at the offset should be %08x but %08x",
|
|
611
|
+
rel->offset, (uint32_t)rel->raddr, *(int32_t*)(ctx->dst + rel->offset));
|
|
612
|
+
return FUNCHOOK_ERROR_IP_RELATIVE_OFFSET;
|
|
613
|
+
}
|
|
614
|
+
ctx->rip_disp[1].dst_addr = rel->addr;
|
|
615
|
+
ctx->rip_disp[1].src_addr_offset = (ctx->dst - ctx->dst_base) + di->size;;
|
|
616
|
+
ctx->rip_disp[1].pos_offset = (ctx->dst - ctx->dst_base) + rel->offset;
|
|
617
|
+
} else if (rel->size != 0) {
|
|
618
|
+
funchook_set_error_message(ctx->funchook, "Could not fix ip-relative address. The size is not 32.");
|
|
619
|
+
return FUNCHOOK_ERROR_CANNOT_FIX_IP_RELATIVE;
|
|
620
|
+
}
|
|
621
|
+
return 0;
|
|
622
|
+
}
|