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.
Files changed (500) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +5 -0
  3. data/.dockerignore +10 -0
  4. data/.gitignore +58 -0
  5. data/.gitmodules +6 -0
  6. data/.rspec +6 -0
  7. data/.simplecov +4 -0
  8. data/Gemfile +7 -0
  9. data/LICENSE.txt +12 -0
  10. data/Rakefile +15 -0
  11. data/exe/contrast_service +29 -0
  12. data/ext/build_funchook.rb +48 -0
  13. data/ext/cs__assess_active_record_named/cs__active_record_named.c +47 -0
  14. data/ext/cs__assess_active_record_named/cs__active_record_named.h +10 -0
  15. data/ext/cs__assess_active_record_named/extconf.rb +2 -0
  16. data/ext/cs__assess_array/cs__assess_array.c +38 -0
  17. data/ext/cs__assess_array/cs__assess_array.h +9 -0
  18. data/ext/cs__assess_array/extconf.rb +2 -0
  19. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +50 -0
  20. data/ext/cs__assess_basic_object/cs__assess_basic_object.h +17 -0
  21. data/ext/cs__assess_basic_object/extconf.rb +2 -0
  22. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +86 -0
  23. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.h +34 -0
  24. data/ext/cs__assess_fiber_track/extconf.rb +2 -0
  25. data/ext/cs__assess_hash/cs__assess_hash.c +64 -0
  26. data/ext/cs__assess_hash/cs__assess_hash.h +24 -0
  27. data/ext/cs__assess_hash/extconf.rb +2 -0
  28. data/ext/cs__assess_kernel/cs__assess_kernel.c +36 -0
  29. data/ext/cs__assess_kernel/cs__assess_kernel.h +10 -0
  30. data/ext/cs__assess_kernel/extconf.rb +2 -0
  31. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +47 -0
  32. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +18 -0
  33. data/ext/cs__assess_marshal_module/extconf.rb +2 -0
  34. data/ext/cs__assess_module/cs__assess_module.c +78 -0
  35. data/ext/cs__assess_module/cs__assess_module.h +25 -0
  36. data/ext/cs__assess_module/extconf.rb +2 -0
  37. data/ext/cs__assess_regexp/cs__assess_regexp.c +48 -0
  38. data/ext/cs__assess_regexp/cs__assess_regexp.h +22 -0
  39. data/ext/cs__assess_regexp/extconf.rb +2 -0
  40. data/ext/cs__assess_regexp_track/cs__assess_regexp_track.c +63 -0
  41. data/ext/cs__assess_regexp_track/cs__assess_regexp_track.h +29 -0
  42. data/ext/cs__assess_regexp_track/extconf.rb +2 -0
  43. data/ext/cs__assess_string/cs__assess_string.c +38 -0
  44. data/ext/cs__assess_string/cs__assess_string.h +19 -0
  45. data/ext/cs__assess_string/extconf.rb +2 -0
  46. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +31 -0
  47. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.h +13 -0
  48. data/ext/cs__assess_string_interpolation26/extconf.rb +2 -0
  49. data/ext/cs__common/cs__common.c +60 -0
  50. data/ext/cs__common/cs__common.h +28 -0
  51. data/ext/cs__common/extconf.rb +20 -0
  52. data/ext/cs__contrast_patch/cs__contrast_patch.c +445 -0
  53. data/ext/cs__contrast_patch/cs__contrast_patch.h +196 -0
  54. data/ext/cs__contrast_patch/extconf.rb +2 -0
  55. data/ext/cs__protect_kernel/cs__protect_kernel.c +37 -0
  56. data/ext/cs__protect_kernel/cs__protect_kernel.h +11 -0
  57. data/ext/cs__protect_kernel/extconf.rb +2 -0
  58. data/ext/cs__scope/cs__scope.c +96 -0
  59. data/ext/cs__scope/cs__scope.h +33 -0
  60. data/ext/cs__scope/extconf.rb +2 -0
  61. data/ext/extconf_common.rb +49 -0
  62. data/funchook/LICENSE +360 -0
  63. data/funchook/Makefile +29 -0
  64. data/funchook/Makefile.in +29 -0
  65. data/funchook/README.md +121 -0
  66. data/funchook/appveyor.yml +42 -0
  67. data/funchook/autogen.sh +3 -0
  68. data/funchook/autom4te.cache/output.0 +4976 -0
  69. data/funchook/autom4te.cache/requests +78 -0
  70. data/funchook/autom4te.cache/traces.0 +364 -0
  71. data/funchook/config.guess +1530 -0
  72. data/funchook/config.log +490 -0
  73. data/funchook/config.status +1016 -0
  74. data/funchook/config.sub +1773 -0
  75. data/funchook/configure +4976 -0
  76. data/funchook/configure.ac +59 -0
  77. data/funchook/distorm/COPYING +26 -0
  78. data/funchook/distorm/MANIFEST +25 -0
  79. data/funchook/distorm/MANIFEST.in +4 -0
  80. data/funchook/distorm/README.md +12 -0
  81. data/funchook/distorm/disOps/disOps.py +795 -0
  82. data/funchook/distorm/disOps/x86db.py +404 -0
  83. data/funchook/distorm/disOps/x86header.py +247 -0
  84. data/funchook/distorm/disOps/x86sets.py +1664 -0
  85. data/funchook/distorm/examples/cs/TestdiStorm/Program.cs +79 -0
  86. data/funchook/distorm/examples/cs/TestdiStorm/Properties/AssemblyInfo.cs +36 -0
  87. data/funchook/distorm/examples/cs/TestdiStorm/TestdiStorm.csproj +69 -0
  88. data/funchook/distorm/examples/cs/distorm-net.sln +26 -0
  89. data/funchook/distorm/examples/cs/distorm-net/CodeInfo.cs +23 -0
  90. data/funchook/distorm/examples/cs/distorm-net/DecodedInst.cs +15 -0
  91. data/funchook/distorm/examples/cs/distorm-net/DecodedResult.cs +14 -0
  92. data/funchook/distorm/examples/cs/distorm-net/DecomposedInst.cs +36 -0
  93. data/funchook/distorm/examples/cs/distorm-net/DecomposedResult.cs +14 -0
  94. data/funchook/distorm/examples/cs/distorm-net/Opcodes.cs +1268 -0
  95. data/funchook/distorm/examples/cs/distorm-net/Opcodes.tt +37 -0
  96. data/funchook/distorm/examples/cs/distorm-net/Operand.cs +25 -0
  97. data/funchook/distorm/examples/cs/distorm-net/Properties/AssemblyInfo.cs +36 -0
  98. data/funchook/distorm/examples/cs/distorm-net/diStorm3.cs +411 -0
  99. data/funchook/distorm/examples/cs/distorm-net/distorm-net.csproj +80 -0
  100. data/funchook/distorm/examples/cs/readme +3 -0
  101. data/funchook/distorm/examples/ddk/README +48 -0
  102. data/funchook/distorm/examples/ddk/distorm.ini +11 -0
  103. data/funchook/distorm/examples/ddk/dummy.c +15 -0
  104. data/funchook/distorm/examples/ddk/main.c +91 -0
  105. data/funchook/distorm/examples/ddk/makefile +1 -0
  106. data/funchook/distorm/examples/ddk/sources +10 -0
  107. data/funchook/distorm/examples/java/Makefile +23 -0
  108. data/funchook/distorm/examples/java/distorm/src/Main.java +43 -0
  109. data/funchook/distorm/examples/java/distorm/src/diStorm3/CodeInfo.java +27 -0
  110. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedInst.java +32 -0
  111. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecodedResult.java +11 -0
  112. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedInst.java +89 -0
  113. data/funchook/distorm/examples/java/distorm/src/diStorm3/DecomposedResult.java +11 -0
  114. data/funchook/distorm/examples/java/distorm/src/diStorm3/OpcodeEnum.java +131 -0
  115. data/funchook/distorm/examples/java/distorm/src/diStorm3/Opcodes.java +1123 -0
  116. data/funchook/distorm/examples/java/distorm/src/diStorm3/Operand.java +24 -0
  117. data/funchook/distorm/examples/java/distorm/src/diStorm3/distorm3.java +41 -0
  118. data/funchook/distorm/examples/java/jdistorm.c +405 -0
  119. data/funchook/distorm/examples/java/jdistorm.h +40 -0
  120. data/funchook/distorm/examples/java/jdistorm.sln +20 -0
  121. data/funchook/distorm/examples/java/jdistorm.vcproj +208 -0
  122. data/funchook/distorm/examples/linux/Makefile +15 -0
  123. data/funchook/distorm/examples/linux/main.c +181 -0
  124. data/funchook/distorm/examples/tests/Makefile +15 -0
  125. data/funchook/distorm/examples/tests/main.cpp +42 -0
  126. data/funchook/distorm/examples/tests/main.py +66 -0
  127. data/funchook/distorm/examples/tests/test_distorm3.py +1672 -0
  128. data/funchook/distorm/examples/tests/tests.sln +20 -0
  129. data/funchook/distorm/examples/tests/tests.vcxproj +82 -0
  130. data/funchook/distorm/examples/tests/tests.vcxproj.filters +22 -0
  131. data/funchook/distorm/examples/win32/disasm.sln +25 -0
  132. data/funchook/distorm/examples/win32/disasm.vcxproj +201 -0
  133. data/funchook/distorm/examples/win32/disasm.vcxproj.filters +14 -0
  134. data/funchook/distorm/examples/win32/main.cpp +163 -0
  135. data/funchook/distorm/include/distorm.h +482 -0
  136. data/funchook/distorm/include/mnemonics.h +301 -0
  137. data/funchook/distorm/make/linux/Makefile +28 -0
  138. data/funchook/distorm/make/mac/Makefile +24 -0
  139. data/funchook/distorm/make/win32/cdistorm.vcxproj +239 -0
  140. data/funchook/distorm/make/win32/cdistorm.vcxproj.filters +80 -0
  141. data/funchook/distorm/make/win32/distorm.sln +25 -0
  142. data/funchook/distorm/make/win32/resource.h +14 -0
  143. data/funchook/distorm/make/win32/resource.rc +99 -0
  144. data/funchook/distorm/python/distorm3/__init__.py +957 -0
  145. data/funchook/distorm/python/distorm3/sample.py +51 -0
  146. data/funchook/distorm/setup.cfg +10 -0
  147. data/funchook/distorm/setup.py +266 -0
  148. data/funchook/distorm/src/config.h +169 -0
  149. data/funchook/distorm/src/decoder.c +641 -0
  150. data/funchook/distorm/src/decoder.h +33 -0
  151. data/funchook/distorm/src/distorm.c +413 -0
  152. data/funchook/distorm/src/instructions.c +597 -0
  153. data/funchook/distorm/src/instructions.h +463 -0
  154. data/funchook/distorm/src/insts.c +7939 -0
  155. data/funchook/distorm/src/insts.h +64 -0
  156. data/funchook/distorm/src/mnemonics.c +284 -0
  157. data/funchook/distorm/src/operands.c +1290 -0
  158. data/funchook/distorm/src/operands.h +28 -0
  159. data/funchook/distorm/src/prefix.c +368 -0
  160. data/funchook/distorm/src/prefix.h +64 -0
  161. data/funchook/distorm/src/textdefs.c +172 -0
  162. data/funchook/distorm/src/textdefs.h +57 -0
  163. data/funchook/distorm/src/wstring.c +47 -0
  164. data/funchook/distorm/src/wstring.h +35 -0
  165. data/funchook/distorm/src/x86defs.h +82 -0
  166. data/funchook/include/funchook.h +123 -0
  167. data/funchook/install-sh +527 -0
  168. data/funchook/src/Makefile +70 -0
  169. data/funchook/src/Makefile.in +70 -0
  170. data/funchook/src/__strerror.h +109 -0
  171. data/funchook/src/config.h +101 -0
  172. data/funchook/src/config.h.in +100 -0
  173. data/funchook/src/decoder.o +0 -0
  174. data/funchook/src/distorm.o +0 -0
  175. data/funchook/src/funchook.c +440 -0
  176. data/funchook/src/funchook.o +0 -0
  177. data/funchook/src/funchook_internal.h +155 -0
  178. data/funchook/src/funchook_io.c +182 -0
  179. data/funchook/src/funchook_io.h +64 -0
  180. data/funchook/src/funchook_io.o +0 -0
  181. data/funchook/src/funchook_syscall.S +134 -0
  182. data/funchook/src/funchook_syscall.o +0 -0
  183. data/funchook/src/funchook_unix.c +480 -0
  184. data/funchook/src/funchook_unix.o +0 -0
  185. data/funchook/src/funchook_windows.c +397 -0
  186. data/funchook/src/funchook_x86.c +622 -0
  187. data/funchook/src/funchook_x86.o +0 -0
  188. data/funchook/src/instructions.o +0 -0
  189. data/funchook/src/insts.o +0 -0
  190. data/funchook/src/libfunchook.so +0 -0
  191. data/funchook/src/mnemonics.o +0 -0
  192. data/funchook/src/operands.o +0 -0
  193. data/funchook/src/os_func.c +115 -0
  194. data/funchook/src/os_func.h +75 -0
  195. data/funchook/src/os_func.o +0 -0
  196. data/funchook/src/os_func_unix.c +94 -0
  197. data/funchook/src/os_func_unix.o +0 -0
  198. data/funchook/src/os_func_windows.c +32 -0
  199. data/funchook/src/prefix.o +0 -0
  200. data/funchook/src/printf_base.c +1688 -0
  201. data/funchook/src/printf_base.h +46 -0
  202. data/funchook/src/printf_base.o +0 -0
  203. data/funchook/src/textdefs.o +0 -0
  204. data/funchook/src/wstring.o +0 -0
  205. data/funchook/test/Makefile +43 -0
  206. data/funchook/test/Makefile.in +43 -0
  207. data/funchook/test/funchook_test +0 -0
  208. data/funchook/test/libfunchook_test.c +25 -0
  209. data/funchook/test/libfunchook_test.so +0 -0
  210. data/funchook/test/libfunchook_test2.c +18 -0
  211. data/funchook/test/suffix.list +600 -0
  212. data/funchook/test/test_main.c +430 -0
  213. data/funchook/test/test_main.o +0 -0
  214. data/funchook/test/x86_64_test.S +10 -0
  215. data/funchook/test/x86_64_test.o +0 -0
  216. data/funchook/test/x86_test.S +339 -0
  217. data/funchook/win32/config.h +1 -0
  218. data/funchook/win32/funchook.sln +52 -0
  219. data/funchook/win32/funchook.vcxproj +188 -0
  220. data/funchook/win32/funchook.vcxproj.filters +84 -0
  221. data/funchook/win32/funchook_test.vcxproj +170 -0
  222. data/funchook/win32/funchook_test.vcxproj.filters +22 -0
  223. data/funchook/win32/funchook_test_dll.vcxproj +184 -0
  224. data/funchook/win32/funchook_test_dll.vcxproj.filters +30 -0
  225. data/funchook/win32/funchook_test_exe.def +3 -0
  226. data/lib/contrast-agent.rb +8 -0
  227. data/lib/contrast.rb +57 -0
  228. data/lib/contrast/agent.rb +80 -0
  229. data/lib/contrast/agent/assess.rb +45 -0
  230. data/lib/contrast/agent/assess/adjusted_span.rb +25 -0
  231. data/lib/contrast/agent/assess/class_reverter.rb +82 -0
  232. data/lib/contrast/agent/assess/contrast_event.rb +398 -0
  233. data/lib/contrast/agent/assess/frozen_properties.rb +41 -0
  234. data/lib/contrast/agent/assess/insulator.rb +53 -0
  235. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +78 -0
  236. data/lib/contrast/agent/assess/policy/patcher.rb +85 -0
  237. data/lib/contrast/agent/assess/policy/policy.rb +116 -0
  238. data/lib/contrast/agent/assess/policy/policy_node.rb +289 -0
  239. data/lib/contrast/agent/assess/policy/policy_scanner.rb +44 -0
  240. data/lib/contrast/agent/assess/policy/preshift.rb +94 -0
  241. data/lib/contrast/agent/assess/policy/propagation_method.rb +260 -0
  242. data/lib/contrast/agent/assess/policy/propagation_node.rb +127 -0
  243. data/lib/contrast/agent/assess/policy/propagator.rb +35 -0
  244. data/lib/contrast/agent/assess/policy/propagator/append.rb +54 -0
  245. data/lib/contrast/agent/assess/policy/propagator/base.rb +37 -0
  246. data/lib/contrast/agent/assess/policy/propagator/center.rb +73 -0
  247. data/lib/contrast/agent/assess/policy/propagator/custom.rb +36 -0
  248. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +62 -0
  249. data/lib/contrast/agent/assess/policy/propagator/insert.rb +55 -0
  250. data/lib/contrast/agent/assess/policy/propagator/keep.rb +26 -0
  251. data/lib/contrast/agent/assess/policy/propagator/next.rb +42 -0
  252. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +50 -0
  253. data/lib/contrast/agent/assess/policy/propagator/remove.rb +76 -0
  254. data/lib/contrast/agent/assess/policy/propagator/replace.rb +27 -0
  255. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +38 -0
  256. data/lib/contrast/agent/assess/policy/propagator/select.rb +86 -0
  257. data/lib/contrast/agent/assess/policy/propagator/splat.rb +60 -0
  258. data/lib/contrast/agent/assess/policy/propagator/split.rb +49 -0
  259. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +169 -0
  260. data/lib/contrast/agent/assess/policy/propagator/trim.rb +81 -0
  261. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +79 -0
  262. data/lib/contrast/agent/assess/policy/source_method.rb +209 -0
  263. data/lib/contrast/agent/assess/policy/source_node.rb +62 -0
  264. data/lib/contrast/agent/assess/policy/trigger_method.rb +209 -0
  265. data/lib/contrast/agent/assess/policy/trigger_node.rb +198 -0
  266. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +77 -0
  267. data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +31 -0
  268. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +40 -0
  269. data/lib/contrast/agent/assess/properties.rb +392 -0
  270. data/lib/contrast/agent/assess/rule.rb +18 -0
  271. data/lib/contrast/agent/assess/rule/base.rb +72 -0
  272. data/lib/contrast/agent/assess/rule/csrf.rb +66 -0
  273. data/lib/contrast/agent/assess/rule/csrf/csrf_action.rb +28 -0
  274. data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +69 -0
  275. data/lib/contrast/agent/assess/rule/csrf/csrf_watcher.rb +132 -0
  276. data/lib/contrast/agent/assess/rule/provider.rb +21 -0
  277. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +62 -0
  278. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +73 -0
  279. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +121 -0
  280. data/lib/contrast/agent/assess/rule/redos.rb +68 -0
  281. data/lib/contrast/agent/assess/rule/response_scanning_rule.rb +47 -0
  282. data/lib/contrast/agent/assess/rule/response_watcher.rb +36 -0
  283. data/lib/contrast/agent/assess/rule/watcher.rb +36 -0
  284. data/lib/contrast/agent/assess/tag.rb +151 -0
  285. data/lib/contrast/agent/at_exit_hook.rb +33 -0
  286. data/lib/contrast/agent/class_reopener.rb +195 -0
  287. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +26 -0
  288. data/lib/contrast/agent/deadzone/policy/policy.rb +57 -0
  289. data/lib/contrast/agent/disable_reaction.rb +24 -0
  290. data/lib/contrast/agent/exclusion_matcher.rb +190 -0
  291. data/lib/contrast/agent/feature_state.rb +379 -0
  292. data/lib/contrast/agent/inventory/policy/policy.rb +32 -0
  293. data/lib/contrast/agent/inventory/policy/trigger_node.rb +22 -0
  294. data/lib/contrast/agent/logger_manager.rb +116 -0
  295. data/lib/contrast/agent/middleware.rb +352 -0
  296. data/lib/contrast/agent/module_data.rb +16 -0
  297. data/lib/contrast/agent/patching/policy/after_load_patch.rb +37 -0
  298. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +58 -0
  299. data/lib/contrast/agent/patching/policy/method_policy.rb +94 -0
  300. data/lib/contrast/agent/patching/policy/module_policy.rb +116 -0
  301. data/lib/contrast/agent/patching/policy/patch.rb +312 -0
  302. data/lib/contrast/agent/patching/policy/patch_status.rb +192 -0
  303. data/lib/contrast/agent/patching/policy/patcher.rb +310 -0
  304. data/lib/contrast/agent/patching/policy/policy.rb +138 -0
  305. data/lib/contrast/agent/patching/policy/policy_node.rb +80 -0
  306. data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +28 -0
  307. data/lib/contrast/agent/patching/policy/trigger_node.rb +81 -0
  308. data/lib/contrast/agent/protect/policy/policy.rb +37 -0
  309. data/lib/contrast/agent/protect/policy/trigger_node.rb +23 -0
  310. data/lib/contrast/agent/protect/rule.rb +58 -0
  311. data/lib/contrast/agent/protect/rule/base.rb +300 -0
  312. data/lib/contrast/agent/protect/rule/base_service.rb +88 -0
  313. data/lib/contrast/agent/protect/rule/cmd_injection.rb +156 -0
  314. data/lib/contrast/agent/protect/rule/csrf.rb +118 -0
  315. data/lib/contrast/agent/protect/rule/csrf/csrf_evaluator.rb +103 -0
  316. data/lib/contrast/agent/protect/rule/csrf/csrf_token_injector.rb +85 -0
  317. data/lib/contrast/agent/protect/rule/default_scanner.rb +300 -0
  318. data/lib/contrast/agent/protect/rule/deserialization.rb +193 -0
  319. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +80 -0
  320. data/lib/contrast/agent/protect/rule/no_sqli.rb +101 -0
  321. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +40 -0
  322. data/lib/contrast/agent/protect/rule/path_traversal.rb +143 -0
  323. data/lib/contrast/agent/protect/rule/sqli.rb +101 -0
  324. data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +16 -0
  325. data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +38 -0
  326. data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +22 -0
  327. data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +19 -0
  328. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +20 -0
  329. data/lib/contrast/agent/protect/rule/xss.rb +24 -0
  330. data/lib/contrast/agent/protect/rule/xxe.rb +120 -0
  331. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +82 -0
  332. data/lib/contrast/agent/railtie.rb +30 -0
  333. data/lib/contrast/agent/reaction_processor.rb +47 -0
  334. data/lib/contrast/agent/request.rb +493 -0
  335. data/lib/contrast/agent/request_context.rb +225 -0
  336. data/lib/contrast/agent/require_state.rb +61 -0
  337. data/lib/contrast/agent/response.rb +215 -0
  338. data/lib/contrast/agent/rewriter.rb +244 -0
  339. data/lib/contrast/agent/scope.rb +28 -0
  340. data/lib/contrast/agent/service_heartbeat.rb +37 -0
  341. data/lib/contrast/agent/settings_state.rb +148 -0
  342. data/lib/contrast/agent/socket_client.rb +125 -0
  343. data/lib/contrast/agent/thread.rb +26 -0
  344. data/lib/contrast/agent/tracepoint_hook.rb +51 -0
  345. data/lib/contrast/agent/version.rb +8 -0
  346. data/lib/contrast/api.rb +17 -0
  347. data/lib/contrast/api/.gitkeep +0 -0
  348. data/lib/contrast/api/connection_status.rb +49 -0
  349. data/lib/contrast/api/socket.rb +43 -0
  350. data/lib/contrast/api/speedracer.rb +206 -0
  351. data/lib/contrast/api/tcp_socket.rb +31 -0
  352. data/lib/contrast/api/unix_socket.rb +25 -0
  353. data/lib/contrast/common_agent_configuration.rb +86 -0
  354. data/lib/contrast/components/agent.rb +85 -0
  355. data/lib/contrast/components/app_context.rb +188 -0
  356. data/lib/contrast/components/assess.rb +67 -0
  357. data/lib/contrast/components/config.rb +135 -0
  358. data/lib/contrast/components/contrast_service.rb +113 -0
  359. data/lib/contrast/components/heap_dump.rb +34 -0
  360. data/lib/contrast/components/interface.rb +178 -0
  361. data/lib/contrast/components/inventory.rb +23 -0
  362. data/lib/contrast/components/logger.rb +92 -0
  363. data/lib/contrast/components/protect.rb +38 -0
  364. data/lib/contrast/components/sampling.rb +41 -0
  365. data/lib/contrast/components/scope.rb +106 -0
  366. data/lib/contrast/components/settings.rb +140 -0
  367. data/lib/contrast/config.rb +33 -0
  368. data/lib/contrast/config/agent_configuration.rb +24 -0
  369. data/lib/contrast/config/application_configuration.rb +27 -0
  370. data/lib/contrast/config/assess_configuration.rb +22 -0
  371. data/lib/contrast/config/assess_rules_configuration.rb +18 -0
  372. data/lib/contrast/config/base_configuration.rb +105 -0
  373. data/lib/contrast/config/default_value.rb +16 -0
  374. data/lib/contrast/config/exception_configuration.rb +21 -0
  375. data/lib/contrast/config/heap_dump_configuration.rb +23 -0
  376. data/lib/contrast/config/inventory_configuration.rb +20 -0
  377. data/lib/contrast/config/logger_configuration.rb +20 -0
  378. data/lib/contrast/config/protect_configuration.rb +20 -0
  379. data/lib/contrast/config/protect_rule_configuration.rb +37 -0
  380. data/lib/contrast/config/protect_rules_configuration.rb +30 -0
  381. data/lib/contrast/config/root_configuration.rb +26 -0
  382. data/lib/contrast/config/ruby_configuration.rb +39 -0
  383. data/lib/contrast/config/sampling_configuration.rb +22 -0
  384. data/lib/contrast/config/server_configuration.rb +23 -0
  385. data/lib/contrast/config/service_configuration.rb +22 -0
  386. data/lib/contrast/configuration.rb +214 -0
  387. data/lib/contrast/core_extensions/assess.rb +51 -0
  388. data/lib/contrast/core_extensions/assess/array.rb +58 -0
  389. data/lib/contrast/core_extensions/assess/assess_extension.rb +145 -0
  390. data/lib/contrast/core_extensions/assess/basic_object.rb +15 -0
  391. data/lib/contrast/core_extensions/assess/erb.rb +42 -0
  392. data/lib/contrast/core_extensions/assess/exec_trigger.rb +48 -0
  393. data/lib/contrast/core_extensions/assess/fiber.rb +125 -0
  394. data/lib/contrast/core_extensions/assess/hash.rb +22 -0
  395. data/lib/contrast/core_extensions/assess/kernel.rb +95 -0
  396. data/lib/contrast/core_extensions/assess/module.rb +14 -0
  397. data/lib/contrast/core_extensions/assess/regexp.rb +206 -0
  398. data/lib/contrast/core_extensions/assess/string.rb +75 -0
  399. data/lib/contrast/core_extensions/assess/tilt_template_trigger.rb +73 -0
  400. data/lib/contrast/core_extensions/delegator.rb +14 -0
  401. data/lib/contrast/core_extensions/eval_trigger.rb +52 -0
  402. data/lib/contrast/core_extensions/inventory.rb +22 -0
  403. data/lib/contrast/core_extensions/inventory/datastores.rb +37 -0
  404. data/lib/contrast/core_extensions/module.rb +42 -0
  405. data/lib/contrast/core_extensions/object.rb +27 -0
  406. data/lib/contrast/core_extensions/protect.rb +20 -0
  407. data/lib/contrast/core_extensions/protect/applies_command_injection_rule.rb +70 -0
  408. data/lib/contrast/core_extensions/protect/applies_deserialization_rule.rb +58 -0
  409. data/lib/contrast/core_extensions/protect/applies_no_sqli_rule.rb +81 -0
  410. data/lib/contrast/core_extensions/protect/applies_path_traversal_rule.rb +119 -0
  411. data/lib/contrast/core_extensions/protect/applies_sqli_rule.rb +63 -0
  412. data/lib/contrast/core_extensions/protect/applies_xxe_rule.rb +141 -0
  413. data/lib/contrast/core_extensions/protect/kernel.rb +30 -0
  414. data/lib/contrast/core_extensions/protect/psych.rb +7 -0
  415. data/lib/contrast/core_extensions/thread.rb +31 -0
  416. data/lib/contrast/internal_exception.rb +8 -0
  417. data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +48 -0
  418. data/lib/contrast/rails_extensions/assess/active_record.rb +32 -0
  419. data/lib/contrast/rails_extensions/assess/active_record_named.rb +61 -0
  420. data/lib/contrast/rails_extensions/assess/configuration.rb +26 -0
  421. data/lib/contrast/rails_extensions/buffer.rb +30 -0
  422. data/lib/contrast/rails_extensions/rack.rb +45 -0
  423. data/lib/contrast/security_exception.rb +14 -0
  424. data/lib/contrast/sinatra_extensions/assess/cookie.rb +26 -0
  425. data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +59 -0
  426. data/lib/contrast/tasks/service.rb +95 -0
  427. data/lib/contrast/utils/assess/sampling_util.rb +96 -0
  428. data/lib/contrast/utils/assess/tracking_util.rb +39 -0
  429. data/lib/contrast/utils/boolean_util.rb +33 -0
  430. data/lib/contrast/utils/cache.rb +69 -0
  431. data/lib/contrast/utils/class_util.rb +58 -0
  432. data/lib/contrast/utils/comment_range.rb +19 -0
  433. data/lib/contrast/utils/data_store_util.rb +23 -0
  434. data/lib/contrast/utils/duck_utils.rb +58 -0
  435. data/lib/contrast/utils/env_configuration_item.rb +52 -0
  436. data/lib/contrast/utils/environment_util.rb +152 -0
  437. data/lib/contrast/utils/freeze_util.rb +36 -0
  438. data/lib/contrast/utils/gemfile_reader.rb +191 -0
  439. data/lib/contrast/utils/hash_digest.rb +148 -0
  440. data/lib/contrast/utils/heap_dump_util.rb +113 -0
  441. data/lib/contrast/utils/invalid_configuration_util.rb +88 -0
  442. data/lib/contrast/utils/inventory_util.rb +126 -0
  443. data/lib/contrast/utils/io_util.rb +61 -0
  444. data/lib/contrast/utils/object_share.rb +117 -0
  445. data/lib/contrast/utils/operating_environment.rb +38 -0
  446. data/lib/contrast/utils/os.rb +49 -0
  447. data/lib/contrast/utils/path_util.rb +151 -0
  448. data/lib/contrast/utils/performs_logging.rb +152 -0
  449. data/lib/contrast/utils/preflight_util.rb +13 -0
  450. data/lib/contrast/utils/prevent_serialization.rb +52 -0
  451. data/lib/contrast/utils/rack_assess_session_cookie.rb +104 -0
  452. data/lib/contrast/utils/rails_assess_configuration.rb +95 -0
  453. data/lib/contrast/utils/random_util.rb +22 -0
  454. data/lib/contrast/utils/resource_loader.rb +23 -0
  455. data/lib/contrast/utils/ruby_ast_rewriter.rb +74 -0
  456. data/lib/contrast/utils/scope_util.rb +99 -0
  457. data/lib/contrast/utils/service_response_util.rb +116 -0
  458. data/lib/contrast/utils/service_sender_util.rb +98 -0
  459. data/lib/contrast/utils/sha256_builder.rb +69 -0
  460. data/lib/contrast/utils/sinatra_helper.rb +49 -0
  461. data/lib/contrast/utils/stack_trace_utils.rb +209 -0
  462. data/lib/contrast/utils/string_utils.rb +72 -0
  463. data/lib/contrast/utils/tag_util.rb +139 -0
  464. data/lib/contrast/utils/thread_tracker.rb +54 -0
  465. data/lib/contrast/utils/timer.rb +78 -0
  466. data/resources/assess/policy.json +1673 -0
  467. data/resources/csrf/inject.js +44 -0
  468. data/resources/deadzone/policy.json +55 -0
  469. data/resources/factory-bot-spec/spec_helper.rb +30 -0
  470. data/resources/inventory/policy.json +110 -0
  471. data/resources/protect/policy.json +417 -0
  472. data/resources/rubocops/kernel/catch_cop.rb +37 -0
  473. data/resources/rubocops/kernel/require_cop.rb +37 -0
  474. data/resources/rubocops/kernel/require_relative_cop.rb +33 -0
  475. data/resources/rubocops/module/autoload_cop.rb +37 -0
  476. data/resources/rubocops/module/const_defined_cop.rb +37 -0
  477. data/resources/rubocops/module/const_get_cop.rb +37 -0
  478. data/resources/rubocops/module/const_set_cop.rb +37 -0
  479. data/resources/rubocops/module/constants_cop.rb +37 -0
  480. data/resources/rubocops/module/name_cop.rb +37 -0
  481. data/resources/rubocops/object/class_cop.rb +37 -0
  482. data/resources/rubocops/object/freeze_cop.rb +37 -0
  483. data/resources/rubocops/object/frozen_cop.rb +37 -0
  484. data/resources/rubocops/object/is_a_cop.rb +37 -0
  485. data/resources/rubocops/object/method_cop.rb +37 -0
  486. data/resources/rubocops/object/respond_to_cop.rb +37 -0
  487. data/resources/rubocops/object/singleton_class_cop.rb +37 -0
  488. data/resources/rubocops/regexp/spelling_cop.rb +44 -0
  489. data/resources/rubocops/thread/new_cop.rb +39 -0
  490. data/resources/ruby-spec/ancestors_spec.rb +70 -0
  491. data/resources/ruby-spec/modulo_spec.rb +831 -0
  492. data/resources/ruby-spec/parameters_spec.rb +261 -0
  493. data/resources/ruby-spec/ruby_spec_spec_helper.rb +35 -0
  494. data/resources/test_marker.txt +1 -0
  495. data/ruby-agent.gemspec +129 -0
  496. data/service_executables/.gitkeep +0 -0
  497. data/service_executables/VERSION +1 -0
  498. data/service_executables/linux/contrast-service +0 -0
  499. data/service_executables/mac/contrast-service +0 -0
  500. metadata +945 -0
@@ -0,0 +1,182 @@
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
+ #if defined __linux
32
+ #define _GNU_SOURCE
33
+ #endif
34
+ #include <string.h>
35
+ #include <errno.h>
36
+
37
+ #ifdef WIN32
38
+ #include <windows.h>
39
+ #else
40
+ #include <fcntl.h>
41
+ #endif
42
+
43
+ #include "funchook_io.h"
44
+ #include "printf_base.h"
45
+ #include "os_func.h"
46
+
47
+ int funchook_io_open(funchook_io_t *io, const char *path, int mode)
48
+ {
49
+ #ifdef WIN32
50
+ DWORD access_mode = GENERIC_READ;
51
+ DWORD creation_disp = 0;
52
+ if (mode == FUNCHOOK_IO_WRITE) {
53
+ access_mode = GENERIC_WRITE;
54
+ creation_disp = CREATE_ALWAYS;
55
+ io->append = 0;
56
+ } else if (mode == FUNCHOOK_IO_APPEND) {
57
+ access_mode = GENERIC_WRITE;
58
+ creation_disp = OPEN_ALWAYS;
59
+ io->append = 1;
60
+ }
61
+ io->file = CreateFileA(path, access_mode, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, creation_disp, FILE_ATTRIBUTE_NORMAL, NULL);
62
+ #else
63
+ int flags = O_RDONLY;
64
+ if (mode == FUNCHOOK_IO_WRITE) {
65
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
66
+ } else if (mode == FUNCHOOK_IO_APPEND) {
67
+ flags = O_WRONLY | O_CREAT | O_APPEND;
68
+ }
69
+ io->file = open(path, flags, 0666);
70
+ #endif
71
+ io->ptr = io->end = io->buf;
72
+ return io->file != INVALID_FILE_HANDLE ? 0 : -1;
73
+ }
74
+
75
+ int funchook_io_close(funchook_io_t *io)
76
+ {
77
+ if (io->file != INVALID_FILE_HANDLE) {
78
+ #ifdef WIN32
79
+ CloseHandle(io->file);
80
+ #else
81
+ close(io->file);
82
+ #endif
83
+ io->file = INVALID_FILE_HANDLE;
84
+ }
85
+ return 0;
86
+ }
87
+
88
+ char *funchook_io_gets(char *s, int size, funchook_io_t *io)
89
+ {
90
+ char *p = s;
91
+ char *e = s + size - 1;
92
+ while (p < e) {
93
+ if (io->ptr == io->end) {
94
+ #ifdef WIN32
95
+ DWORD len;
96
+ if (!ReadFile(io->file, io->buf, sizeof(io->buf), &len, NULL)) {
97
+ len = 0;
98
+ }
99
+ #else
100
+ int len = read(io->file, io->buf, sizeof(io->buf));
101
+ #endif
102
+ if (len <= 0) {
103
+ if (p != s) {
104
+ break;
105
+ }
106
+ return NULL;
107
+ }
108
+ io->ptr = io->buf;
109
+ io->end = io->buf + len;
110
+ }
111
+ if ((*(p++) = *(io->ptr++)) == '\n') {
112
+ break;
113
+ }
114
+ }
115
+ *p = '\0';
116
+ return s;
117
+ }
118
+
119
+ #define IO_PUTC(c, io) do { \
120
+ if (io->ptr == io->buf + sizeof(io->buf)) { \
121
+ if (funchook_io_flush(io) != 0) { \
122
+ return -1; \
123
+ } \
124
+ } \
125
+ *(io->ptr++) = (c); \
126
+ } while (0)
127
+
128
+ int funchook_io_putc(char c, funchook_io_t *io)
129
+ {
130
+ #ifdef WIN32
131
+ if (c == '\n') {
132
+ IO_PUTC('\r', io);
133
+ }
134
+ #endif
135
+ IO_PUTC(c, io);
136
+ return (unsigned char)c;
137
+ }
138
+
139
+ int funchook_io_puts(const char *s, funchook_io_t *io)
140
+ {
141
+ while (*s) {
142
+ #ifdef WIN32
143
+ if (*s == '\n') {
144
+ IO_PUTC('\r', io);
145
+ }
146
+ #endif
147
+ IO_PUTC(*(s++), io);
148
+ }
149
+ return 0;
150
+ }
151
+
152
+ int funchook_io_vprintf(funchook_io_t *io, const char *format, va_list ap)
153
+ {
154
+ return printf_base((pfb_putc_t)funchook_io_putc, io, format, ap);
155
+ }
156
+
157
+ int funchook_io_flush(funchook_io_t *io)
158
+ {
159
+ if (io->ptr != io->buf) {
160
+ #ifdef WIN32
161
+ DWORD len = (DWORD)(io->ptr - io->buf);
162
+ DWORD wlen;
163
+ if (io->append) {
164
+ LARGE_INTEGER ll;
165
+ ll.QuadPart = 0;
166
+ if (!SetFilePointerEx(io->file, ll, NULL, FILE_END)) {
167
+ return -1;
168
+ }
169
+ }
170
+ if (!WriteFile(io->file, io->buf, len, &wlen, NULL) || wlen != len) {
171
+ return -1;
172
+ }
173
+ #else
174
+ size_t len = io->ptr - io->buf;
175
+ if (write(io->file, io->buf, len) != len) {
176
+ return -1;
177
+ }
178
+ #endif
179
+ io->ptr = io->buf;
180
+ }
181
+ return 0;
182
+ }
@@ -0,0 +1,64 @@
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
+ #ifndef FUNCHOOK_IO_H
32
+ #define FUNCHOOK_IO_H 1
33
+ #include <stdarg.h>
34
+
35
+ typedef struct {
36
+ #ifdef WIN32
37
+ #define INVALID_FILE_HANDLE INVALID_HANDLE_VALUE
38
+ void *file;
39
+ int append;
40
+ #else
41
+ #define INVALID_FILE_HANDLE -1
42
+ int file;
43
+ #endif
44
+ char *ptr;
45
+ char *end;
46
+ char buf[128];
47
+ } funchook_io_t;
48
+
49
+ #define FUNCHOOK_IO_READ 0
50
+ #define FUNCHOOK_IO_WRITE 1
51
+ #define FUNCHOOK_IO_APPEND 2
52
+
53
+ /*
54
+ * stdio-like functions
55
+ */
56
+ int funchook_io_open(funchook_io_t *io, const char *path, int mode);
57
+ int funchook_io_close(funchook_io_t *io);
58
+ char *funchook_io_gets(char *s, int size, funchook_io_t *io);
59
+ int funchook_io_putc(char c, funchook_io_t *io);
60
+ int funchook_io_puts(const char *s, funchook_io_t *io);
61
+ int funchook_io_vprintf(funchook_io_t *io, const char *format, va_list ap);
62
+ int funchook_io_flush(funchook_io_t *io);
63
+
64
+ #endif /* FUNCHOOK_IO_H */
@@ -0,0 +1,134 @@
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
+ #ifdef __APPLE__
32
+ #define funchook_os_syscall _funchook_os_syscall
33
+ #define funchook_os_errno _funchook_os_errno
34
+ #define hidden private_extern
35
+ #endif
36
+
37
+ #ifdef __x86_64__
38
+ .text
39
+ .p2align 4,,15
40
+ .globl funchook_os_syscall
41
+ .hidden funchook_os_syscall
42
+ funchook_os_syscall:
43
+ movq %rdi, %rax /* syscall number */
44
+ #ifdef __APPLE__
45
+ addq $0x2000000, %rax
46
+ #endif
47
+ movq %rsi, %rdi /* 1st argument */
48
+ movq %rdx, %rsi /* 2nd argument */
49
+ movq %rcx, %rdx /* 3rd argument */
50
+ movq %r8, %r10 /* 4th argument */
51
+ movq %r9, %r8 /* 5th argument */
52
+ movq 8(%rsp), %r9 /* 6th argument */
53
+ syscall
54
+ #ifdef __APPLE__
55
+ jnc 1f
56
+ #else
57
+ cmpq $-4096, %rax
58
+ jbe 1f
59
+ negl %eax
60
+ #endif
61
+ movq funchook_os_errno@GOTPCREL(%rip), %rdi
62
+ movl %eax, (%rdi)
63
+ movq $-1, %rax
64
+ 1:
65
+ ret
66
+ #endif
67
+
68
+ #if defined(__i386__) && defined(__linux__)
69
+ .text
70
+ .p2align 4,,15
71
+ .globl funchook_os_syscall
72
+ .hidden funchook_os_syscall
73
+ funchook_os_syscall:
74
+ pushl %ebx
75
+ pushl %esi
76
+ pushl %edi
77
+ pushl %ebp
78
+ movl 20(%esp), %eax /* syscall number */
79
+ movl 24(%esp), %ebx /* 1st argument */
80
+ movl 28(%esp), %ecx /* 2nd argument */
81
+ movl 32(%esp), %edx /* 3rd argument */
82
+ movl 36(%esp), %esi /* 4th argument */
83
+ movl 40(%esp), %edi /* 5th argument */
84
+ movl 44(%esp), %ebp /* 6th argument */
85
+ call *%gs:0x10 // or int $0x80
86
+ cmpl $-4096, %eax
87
+ jbe 1f
88
+ call funchook.get_pc_thunk.cx
89
+ addl $_GLOBAL_OFFSET_TABLE_, %ecx
90
+ movl funchook_os_errno@GOT(%ecx), %ecx
91
+ negl %eax
92
+ movl %eax, (%ecx)
93
+ movl $-1, %eax
94
+ 1:
95
+ popl %ebp
96
+ popl %edi
97
+ popl %esi
98
+ popl %ebx
99
+ ret
100
+
101
+ funchook.get_pc_thunk.cx:
102
+ movl (%esp), %ecx
103
+ ret
104
+ #endif
105
+
106
+ #if defined(__i386__) && defined(__APPLE__)
107
+ .text
108
+ .p2align 4,,15
109
+ .globl funchook_os_syscall
110
+ .hidden funchook_os_syscall
111
+ funchook_os_syscall:
112
+ popl %ecx /* return address */
113
+ popl %eax /* syscall number */
114
+ pushl %ecx
115
+ int $0x80
116
+ pushl %ecx
117
+ jc L_1
118
+ /* success. return %eax */
119
+ ret
120
+ /* failure. set %eax to funchook_os_errno and return -1 */
121
+ L_1:
122
+ call L_2
123
+ L_2:
124
+ popl %ecx /* get current eip */
125
+ movl L_funchook_os_errno$non_lazy_ptr-L_2(%ecx), %edx
126
+ movl %eax, (%edx)
127
+ movl $-1, %eax
128
+ ret
129
+
130
+ .section __IMPORT,__pointers,non_lazy_symbol_pointers
131
+ L_funchook_os_errno$non_lazy_ptr:
132
+ .indirect_symbol funchook_os_errno
133
+ .long 0
134
+ #endif
@@ -0,0 +1,480 @@
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 <stdint.h>
34
+ #include <limits.h>
35
+ #include <string.h>
36
+ #include <unistd.h>
37
+ #include <errno.h>
38
+ #include <sys/mman.h>
39
+ #include <dlfcn.h>
40
+ #ifdef __linux
41
+ #include <elf.h>
42
+ #include <link.h>
43
+ #endif
44
+ #ifdef __APPLE__
45
+ #include <stdlib.h>
46
+ #include <mach/mach.h>
47
+ #endif
48
+ #include "funchook_io.h"
49
+ #include "funchook_internal.h"
50
+
51
+ #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
52
+ #define MAP_ANONYMOUS MAP_ANON
53
+ #endif
54
+
55
+ const size_t page_size = PAGE_SIZE;
56
+
57
+ funchook_t *funchook_alloc(void)
58
+ {
59
+ size_t size = ROUND_UP(funchook_size, page_size);
60
+ void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
61
+ if (mem == (void*)-1) {
62
+ return NULL;
63
+ }
64
+ return (funchook_t*)mem;
65
+ }
66
+
67
+ int funchook_free(funchook_t *funchook)
68
+ {
69
+ size_t size = ROUND_UP(funchook_size, page_size);
70
+ munmap(funchook, size);
71
+ return 0;
72
+ }
73
+
74
+ #ifdef CPU_X86_64
75
+
76
+ typedef struct memory_map memory_map_t;
77
+ static int memory_map_open(funchook_t *funchook, memory_map_t *mmap);
78
+ static int memory_map_next(memory_map_t *mmap, size_t *start, size_t *end);
79
+ static void memory_map_close(memory_map_t *mmap);
80
+
81
+ #if defined(__linux)
82
+ static char scan_address(const char **str, size_t *addr_p)
83
+ {
84
+ size_t addr = 0;
85
+ const char *s = *str;
86
+
87
+ while (1) {
88
+ char c = *(s++);
89
+
90
+ if ('0' <= c && c <= '9') {
91
+ addr = (addr * 16) + (c - '0');
92
+ } else if ('a' <= c && c <= 'f') {
93
+ addr = (addr * 16) + (c - 'a' + 10);
94
+ } else {
95
+ *str = s;
96
+ *addr_p = addr;
97
+ return c;
98
+ }
99
+ }
100
+ }
101
+
102
+ struct memory_map {
103
+ funchook_io_t io;
104
+ };
105
+
106
+ static int memory_map_open(funchook_t *funchook, memory_map_t *mm)
107
+ {
108
+ char buf[64];
109
+ if (funchook_io_open(&mm->io, "/proc/self/maps", FUNCHOOK_IO_READ) != 0) {
110
+ funchook_set_error_message(funchook, "Failed to open /proc/self/maps (%s)",
111
+ funchook_strerror(errno, buf, sizeof(buf)));
112
+ return FUNCHOOK_ERROR_INTERNAL_ERROR;
113
+ }
114
+ return 0;
115
+ }
116
+
117
+ static int memory_map_next(memory_map_t *mm, size_t *start, size_t *end)
118
+ {
119
+ char buf[PATH_MAX];
120
+ const char *str = buf;
121
+
122
+ if (funchook_io_gets(buf, sizeof(buf), &mm->io) == NULL) {
123
+ return -1;
124
+ }
125
+ if (scan_address(&str, start) != '-') {
126
+ return -1;
127
+ }
128
+ if (scan_address(&str, end) != ' ') {
129
+ return -1;
130
+ }
131
+ return 0;
132
+ }
133
+
134
+ static void memory_map_close(memory_map_t *mm)
135
+ {
136
+ funchook_io_close(&mm->io);
137
+ }
138
+
139
+ #elif defined(__APPLE__)
140
+
141
+ struct memory_map {
142
+ mach_port_t task;
143
+ vm_address_t addr;
144
+ };
145
+
146
+ static int memory_map_open(funchook_t *funchook, memory_map_t *mm)
147
+ {
148
+ mm->task = mach_task_self();
149
+ mm->addr = 0;
150
+ return 0;
151
+ }
152
+
153
+ static int memory_map_next(memory_map_t *mm, size_t *start, size_t *end)
154
+ {
155
+ vm_size_t size;
156
+ vm_region_basic_info_data_64_t info;
157
+ mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
158
+ memory_object_name_t object = 0;
159
+
160
+ if (vm_region_64(mm->task, &mm->addr, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &info_count, &object) != KERN_SUCCESS) {
161
+ return -1;
162
+ }
163
+ *start = mm->addr;
164
+ *end = mm->addr + size;
165
+ mm->addr += size;
166
+ return 0;
167
+ }
168
+
169
+ static void memory_map_close(memory_map_t *mm)
170
+ {
171
+ return;
172
+ }
173
+
174
+ #else
175
+ #error unsupported OS
176
+ #endif
177
+
178
+ static int get_free_address(funchook_t *funchook, void *func_addr, void *addrs[2])
179
+ {
180
+ memory_map_t mm;
181
+ size_t prev_end = 0;
182
+ size_t start, end;
183
+ int rv;
184
+
185
+ if ((rv = memory_map_open(funchook, &mm)) != 0) {
186
+ return rv;
187
+ }
188
+ addrs[0] = addrs[1] = NULL;
189
+
190
+ while (memory_map_next(&mm, &start, &end) == 0) {
191
+ funchook_log(funchook, " process map: %0"SIZE_T_WIDTH SIZE_T_FMT"x-%0"SIZE_T_WIDTH SIZE_T_FMT"x\n",
192
+ start, end);
193
+ if (prev_end + page_size <= start) {
194
+ if (start < (size_t)func_addr) {
195
+ size_t addr = start - page_size;
196
+ if ((size_t)func_addr - addr < INT32_MAX) {
197
+ /* unused memory region before func_addr. */
198
+ addrs[0] = (void*)addr;
199
+ }
200
+ }
201
+ if ((size_t)func_addr < prev_end) {
202
+ if (prev_end - (size_t)func_addr < INT32_MAX) {
203
+ /* unused memory region after func_addr. */
204
+ addrs[1] = (void*)prev_end;
205
+ }
206
+ funchook_log(funchook, " -- Use address %p or %p for function %p\n",
207
+ addrs[0], addrs[1], func_addr);
208
+ memory_map_close(&mm);
209
+ return 0;
210
+ }
211
+ }
212
+ prev_end = end;
213
+ }
214
+ memory_map_close(&mm);
215
+ funchook_set_error_message(funchook, "Could not find a free region near %p",
216
+ func_addr);
217
+ return FUNCHOOK_ERROR_MEMORY_ALLOCATION;
218
+ }
219
+
220
+ #endif /* CPU_X86_64 */
221
+
222
+ int funchook_page_alloc(funchook_t *funchook, funchook_page_t **page_out, uint8_t *func, rip_displacement_t *disp)
223
+ {
224
+ #ifdef CPU_X86_64
225
+ int loop_cnt;
226
+
227
+ /* Loop three times just to avoid rare cases such as
228
+ * unused memory region is used between 'get_free_address()'
229
+ * and 'mmap()'.
230
+ */
231
+ for (loop_cnt = 0; loop_cnt < 3; loop_cnt++) {
232
+ void *addrs[2];
233
+ int rv = get_free_address(funchook, func, addrs);
234
+ int i;
235
+
236
+ if (rv != 0) {
237
+ return rv;
238
+ }
239
+ for (i = 1; i >= 0; i--) {
240
+ /* Try to use addr[1] (unused memory region after `func`)
241
+ * and then addr[0] (before `func`)
242
+ */
243
+ if (addrs[i] == NULL) {
244
+ continue;
245
+ }
246
+ *page_out = mmap(addrs[i], page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
247
+ if (*page_out == addrs[i]) {
248
+ funchook_log(funchook, " allocate page %p (size=%"SIZE_T_FMT"u)\n", *page_out, page_size);
249
+ return 0;
250
+ }
251
+ if (*page_out == MAP_FAILED) {
252
+ char errbuf[128];
253
+
254
+ funchook_set_error_message(funchook, "mmap failed(addr=%p): %s", addrs[i],
255
+ funchook_strerror(errno, errbuf, sizeof(errbuf)));
256
+ return FUNCHOOK_ERROR_MEMORY_ALLOCATION;
257
+ }
258
+ funchook_log(funchook, " try to allocate %p but %p (size=%"SIZE_T_FMT"u)\n", addrs[i], *page_out, page_size);
259
+ munmap(*page_out, page_size);
260
+ }
261
+ }
262
+ funchook_set_error_message(funchook, "Failed to allocate memory in unused regions");
263
+ return FUNCHOOK_ERROR_MEMORY_ALLOCATION;
264
+ #else
265
+ char errbuf[128];
266
+
267
+ *page_out = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
268
+ if (*page_out != MAP_FAILED) {
269
+ funchook_log(funchook, " allocate page %p (size=%"SIZE_T_FMT"u)\n", *page_out, page_size);
270
+ return 0;
271
+ }
272
+ funchook_set_error_message(funchook, "mmap failed: %s", funchook_strerror(errno, errbuf, sizeof(errbuf)));
273
+ return FUNCHOOK_ERROR_MEMORY_ALLOCATION;
274
+ #endif
275
+ }
276
+
277
+ int funchook_page_free(funchook_t *funchook, funchook_page_t *page)
278
+ {
279
+ char errbuf[128];
280
+ int rv = munmap(page, page_size);
281
+
282
+ if (rv == 0) {
283
+ funchook_log(funchook, " deallocate page %p (size=%"SIZE_T_FMT"u)\n",
284
+ page, page_size);
285
+ return 0;
286
+ }
287
+ funchook_set_error_message(funchook, "Failed to deallocate page %p (size=%"SIZE_T_FMT"u, error=%s)",
288
+ page, page_size,
289
+ funchook_strerror(errno, errbuf, sizeof(errbuf)));
290
+ return FUNCHOOK_ERROR_MEMORY_FUNCTION;
291
+ }
292
+
293
+ int funchook_page_protect(funchook_t *funchook, funchook_page_t *page)
294
+ {
295
+ char errbuf[128];
296
+ int rv = mprotect(page, page_size, PROT_READ | PROT_EXEC);
297
+
298
+ if (rv == 0) {
299
+ funchook_log(funchook, " protect page %p (size=%"SIZE_T_FMT"u)\n",
300
+ page, page_size);
301
+ return 0;
302
+ }
303
+ funchook_set_error_message(funchook, "Failed to protect page %p (size=%"SIZE_T_FMT"u, error=%s)",
304
+ page, page_size,
305
+ funchook_strerror(errno, errbuf, sizeof(errbuf)));
306
+ return FUNCHOOK_ERROR_MEMORY_FUNCTION;
307
+ }
308
+
309
+ int funchook_page_unprotect(funchook_t *funchook, funchook_page_t *page)
310
+ {
311
+ char errbuf[128];
312
+ int rv = mprotect(page, page_size, PROT_READ | PROT_WRITE);
313
+
314
+ if (rv == 0) {
315
+ funchook_log(funchook, " unprotect page %p (size=%"SIZE_T_FMT"u)\n",
316
+ page, page_size);
317
+ return 0;
318
+ }
319
+ funchook_set_error_message(funchook, "Failed to unprotect page %p (size=%"SIZE_T_FMT"u, error=%s)",
320
+ page, page_size,
321
+ funchook_strerror(errno, errbuf, sizeof(errbuf)));
322
+ return FUNCHOOK_ERROR_MEMORY_FUNCTION;
323
+ }
324
+
325
+ int funchook_unprotect_begin(funchook_t *funchook, mem_state_t *mstate, void *start, size_t len)
326
+ {
327
+ static int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
328
+ char errbuf[128];
329
+ size_t saddr = ROUND_DOWN((size_t)start, page_size);
330
+ int rv;
331
+
332
+ mstate->addr = (void*)saddr;
333
+ mstate->size = len + (size_t)start - saddr;
334
+ mstate->size = ROUND_UP(mstate->size, page_size);
335
+ rv = mprotect(mstate->addr, mstate->size, prot);
336
+ if (rv == 0) {
337
+ funchook_log(funchook, " unprotect memory %p (size=%"SIZE_T_FMT"u, prot=read,write%s) <- %p (size=%"SIZE_T_FMT"u)\n",
338
+ mstate->addr, mstate->size, (prot & PROT_EXEC) ? ",exec" : "", start, len);
339
+ return 0;
340
+ }
341
+ if (rv == -1 && errno == EACCES && (prot & PROT_EXEC)) {
342
+ rv = mprotect(mstate->addr, mstate->size, PROT_READ | PROT_WRITE);
343
+ if (rv == 0) {
344
+ prot = PROT_READ | PROT_WRITE;
345
+ funchook_log(funchook, " unprotect memory %p (size=%"SIZE_T_FMT"u, prot=read,write) <- %p (size=%"SIZE_T_FMT"u)\n",
346
+ mstate->addr, mstate->size, start, len);
347
+ return 0;
348
+ }
349
+ }
350
+ funchook_set_error_message(funchook, "Failed to unprotect memory %p (size=%"SIZE_T_FMT"u, prot=read,write%s) <- %p (size=%"SIZE_T_FMT"u, error=%s)",
351
+ mstate->addr, mstate->size, (prot & PROT_EXEC) ? ",exec" : "", start, len,
352
+ funchook_strerror(errno, errbuf, sizeof(errbuf)));
353
+ return FUNCHOOK_ERROR_MEMORY_FUNCTION;
354
+ }
355
+
356
+ int funchook_unprotect_end(funchook_t *funchook, const mem_state_t *mstate)
357
+ {
358
+ char errbuf[128];
359
+ int rv = mprotect(mstate->addr, mstate->size, PROT_READ | PROT_EXEC);
360
+
361
+ if (rv == 0) {
362
+ funchook_log(funchook, " protect memory %p (size=%"SIZE_T_FMT"u, prot=read,exec)\n",
363
+ mstate->addr, mstate->size);
364
+ return 0;
365
+ }
366
+ funchook_set_error_message(funchook, "Failed to protect memory %p (size=%"SIZE_T_FMT"u, prot=read,exec, error=%s)",
367
+ mstate->addr, mstate->size,
368
+ funchook_strerror(errno, errbuf, sizeof(errbuf)));
369
+ return FUNCHOOK_ERROR_MEMORY_FUNCTION;
370
+ }
371
+
372
+ void *funchook_resolve_func(funchook_t *funchook, void *func)
373
+ {
374
+ #ifdef __GLIBC__
375
+ struct link_map *lmap, *lm;
376
+ const ElfW(Ehdr) *ehdr;
377
+ const ElfW(Dyn) *dyn;
378
+ const ElfW(Sym) *symtab = NULL;
379
+ const ElfW(Sym) *symtab_end = NULL;
380
+ const char *strtab = NULL;
381
+ size_t strtab_size = 0;
382
+ int i;
383
+
384
+ lmap = NULL;
385
+ for (lm = _r_debug.r_map; lm != NULL; lm = lm->l_next) {
386
+ if ((void*)lm->l_addr <= func) {
387
+ if (lmap == NULL) {
388
+ lmap = lm;
389
+ } else if (lmap->l_addr > lm->l_addr) {
390
+ lmap = lm;
391
+ }
392
+ }
393
+ }
394
+ if (lmap == NULL) {
395
+ return func;
396
+ }
397
+ if (lmap->l_addr != 0) {
398
+ ehdr = (ElfW(Ehdr) *)lmap->l_addr;
399
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
400
+ funchook_log(funchook, " not a valid ELF module %s.\n", lmap->l_name);
401
+ return func;
402
+ }
403
+ if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
404
+ funchook_log(funchook, " ELF type is neither ET_EXEC nor ET_DYN.\n");
405
+ return func;
406
+ }
407
+ }
408
+ funchook_log(funchook, " link_map addr=%p, name=%s\n", (void*)lmap->l_addr, lmap->l_name);
409
+ dyn = lmap->l_ld;
410
+
411
+ for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
412
+ switch (dyn[i].d_tag) {
413
+ case DT_SYMTAB:
414
+ symtab = (const ElfW(Sym) *)dyn[i].d_un.d_ptr;
415
+ break;
416
+ case DT_STRTAB:
417
+ strtab = (const char *)dyn[i].d_un.d_ptr;
418
+ break;
419
+ case DT_STRSZ:
420
+ strtab_size = dyn[i].d_un.d_val;
421
+ break;
422
+ }
423
+ }
424
+ symtab_end = (const ElfW(Sym) *)strtab;
425
+ while (symtab < symtab_end) {
426
+ if (symtab->st_name >= strtab_size) {
427
+ break;
428
+ }
429
+ if (ELF64_ST_TYPE(symtab->st_info) == STT_FUNC &&
430
+ symtab->st_size == 0 && (void*)symtab->st_value == func) {
431
+ void *fn = dlsym(RTLD_DEFAULT, strtab + symtab->st_name);
432
+ if (fn == func) {
433
+ fn = dlsym(RTLD_NEXT, strtab + symtab->st_name);
434
+ }
435
+ if (fn != NULL) {
436
+ funchook_log(funchook, " change %s address from %p to %p\n",
437
+ strtab + symtab->st_name, func, fn);
438
+ func = fn;
439
+ }
440
+ break;
441
+ }
442
+ symtab++;
443
+ }
444
+ #endif
445
+ return func;
446
+ }
447
+
448
+ #ifndef HAVE_DECL__SYS_NERR
449
+ #define HAVE_DECL__SYS_NERR 0
450
+ #endif
451
+ #ifndef HAVE_DECL__SYS_ERRLIST
452
+ #define HAVE_DECL__SYS_ERRLIST 0
453
+ #endif
454
+ #ifndef HAVE_DECL_SYS_NERR
455
+ #define HAVE_DECL_SYS_NERR 0
456
+ #endif
457
+ #ifndef HAVE_DECL_SYS_ERRLIST
458
+ #define HAVE_DECL_SYS_ERRLIST 0
459
+ #endif
460
+
461
+ const char *funchook_strerror(int errnum, char *buf, size_t buflen)
462
+ {
463
+ #if HAVE_DECL__SYS_NERR && HAVE_DECL__SYS_ERRLIST
464
+ if (0 <= errnum && errnum < _sys_nerr) {
465
+ return _sys_errlist[errnum];
466
+ }
467
+ #elif HAVE_DECL_SYS_NERR && HAVE_DECL_SYS_ERRLIST
468
+ if (0 <= errnum && errnum < sys_nerr) {
469
+ return sys_errlist[errnum];
470
+ }
471
+ #else
472
+ switch (errnum) {
473
+ #undef E
474
+ #define E(err, msg) case err: return msg;
475
+ #include "__strerror.h" /* header file copied from musl libc */
476
+ }
477
+ #endif
478
+ funchook_snprintf(buf, buflen, "Unknown error (%d)", errnum);
479
+ return buf;
480
+ }