ronin-exploits 0.3.1 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (338) hide show
  1. checksums.yaml +7 -0
  2. data/.document +4 -0
  3. data/.editorconfig +11 -0
  4. data/.github/workflows/ruby.yml +31 -0
  5. data/.gitignore +13 -0
  6. data/.mailmap +1 -0
  7. data/.rspec +1 -0
  8. data/.ruby-version +1 -0
  9. data/.yardopts +1 -0
  10. data/COPYING.txt +161 -335
  11. data/{History.txt → ChangeLog.md} +119 -16
  12. data/Gemfile +50 -0
  13. data/README.md +454 -0
  14. data/Rakefile +37 -23
  15. data/bin/ronin-exploits +13 -6
  16. data/data/new/exploit.rb.erb +158 -0
  17. data/gemspec.yml +37 -0
  18. data/lib/ronin/exploits/advisory.rb +84 -0
  19. data/lib/ronin/exploits/cli/command.rb +39 -0
  20. data/lib/ronin/exploits/cli/commands/irb.rb +57 -0
  21. data/lib/ronin/exploits/cli/commands/list.rb +80 -0
  22. data/lib/ronin/exploits/cli/commands/new.rb +332 -0
  23. data/lib/ronin/exploits/cli/commands/run.rb +396 -0
  24. data/lib/ronin/exploits/cli/commands/show.rb +264 -0
  25. data/lib/ronin/exploits/cli/exploit_command.rb +114 -0
  26. data/lib/ronin/exploits/cli/exploit_methods.rb +114 -0
  27. data/lib/ronin/exploits/cli/ruby_shell.rb +51 -0
  28. data/lib/ronin/exploits/cli.rb +46 -0
  29. data/lib/ronin/exploits/client_side_web_vuln.rb +69 -0
  30. data/lib/ronin/exploits/exceptions.rb +27 -17
  31. data/lib/ronin/exploits/exploit.rb +501 -582
  32. data/lib/ronin/exploits/heap_overflow.rb +50 -0
  33. data/lib/ronin/exploits/lfi.rb +141 -0
  34. data/lib/ronin/exploits/loot/file.rb +113 -0
  35. data/lib/ronin/exploits/loot.rb +119 -0
  36. data/lib/ronin/exploits/memory_corruption.rb +53 -0
  37. data/lib/ronin/exploits/metadata/arch.rb +83 -0
  38. data/lib/ronin/exploits/metadata/cookie_param.rb +80 -0
  39. data/lib/ronin/exploits/metadata/default_filename.rb +69 -0
  40. data/lib/ronin/exploits/metadata/default_port.rb +69 -0
  41. data/lib/ronin/exploits/metadata/header_name.rb +80 -0
  42. data/lib/ronin/exploits/metadata/os.rb +117 -0
  43. data/lib/ronin/exploits/metadata/shouts.rb +85 -0
  44. data/lib/ronin/exploits/metadata/url_path.rb +82 -0
  45. data/lib/ronin/exploits/metadata/url_query_param.rb +80 -0
  46. data/lib/ronin/exploits/mixins/binary.rb +106 -0
  47. data/lib/ronin/exploits/mixins/build_dir.rb +61 -0
  48. data/lib/ronin/exploits/mixins/file_builder.rb +102 -0
  49. data/lib/ronin/exploits/mixins/format_string.rb +87 -0
  50. data/lib/ronin/exploits/mixins/has_payload.rb +202 -0
  51. data/lib/ronin/exploits/mixins/has_targets.rb +297 -0
  52. data/lib/ronin/exploits/mixins/html.rb +213 -0
  53. data/lib/ronin/exploits/mixins/http.rb +866 -0
  54. data/lib/ronin/exploits/mixins/loot.rb +84 -0
  55. data/lib/ronin/exploits/mixins/nops.rb +121 -0
  56. data/lib/ronin/exploits/mixins/remote_tcp.rb +272 -0
  57. data/lib/ronin/exploits/mixins/remote_udp.rb +264 -0
  58. data/lib/ronin/exploits/mixins/seh.rb +136 -0
  59. data/lib/ronin/exploits/mixins/stack_overflow.rb +124 -0
  60. data/lib/ronin/exploits/mixins/text.rb +65 -0
  61. data/lib/ronin/exploits/mixins.rb +32 -0
  62. data/lib/ronin/exploits/open_redirect.rb +103 -0
  63. data/lib/ronin/exploits/params/base_url.rb +84 -0
  64. data/lib/ronin/exploits/params/bind_host.rb +53 -0
  65. data/lib/ronin/exploits/params/bind_port.rb +53 -0
  66. data/lib/ronin/exploits/params/filename.rb +71 -0
  67. data/lib/ronin/exploits/params/host.rb +56 -0
  68. data/lib/ronin/exploits/params/port.rb +71 -0
  69. data/lib/ronin/exploits/registry.rb +32 -0
  70. data/lib/ronin/exploits/rfi.rb +106 -0
  71. data/lib/ronin/exploits/root.rb +28 -0
  72. data/lib/ronin/exploits/seh_overflow.rb +90 -0
  73. data/lib/ronin/exploits/sqli.rb +172 -0
  74. data/lib/ronin/exploits/ssti.rb +108 -0
  75. data/lib/ronin/exploits/stack_overflow.rb +90 -0
  76. data/lib/ronin/exploits/target.rb +63 -103
  77. data/lib/ronin/exploits/test_result.rb +80 -0
  78. data/lib/ronin/exploits/use_after_free.rb +50 -0
  79. data/lib/ronin/exploits/version.rb +11 -12
  80. data/lib/ronin/exploits/web.rb +18 -89
  81. data/lib/ronin/exploits/web_vuln.rb +378 -0
  82. data/lib/ronin/exploits/xss.rb +102 -0
  83. data/lib/ronin/exploits.rb +19 -26
  84. data/man/ronin-exploits-irb.1 +31 -0
  85. data/man/ronin-exploits-irb.1.md +22 -0
  86. data/man/ronin-exploits-list.1 +37 -0
  87. data/man/ronin-exploits-list.1.md +27 -0
  88. data/man/ronin-exploits-new.1 +98 -0
  89. data/man/ronin-exploits-new.1.md +73 -0
  90. data/man/ronin-exploits-run.1 +117 -0
  91. data/man/ronin-exploits-run.1.md +87 -0
  92. data/man/ronin-exploits-show.1 +45 -0
  93. data/man/ronin-exploits-show.1.md +33 -0
  94. data/man/ronin-exploits.1 +55 -0
  95. data/man/ronin-exploits.1.md +41 -0
  96. data/ronin-exploits.gemspec +62 -0
  97. data/spec/advisory_spec.rb +71 -0
  98. data/spec/cli/exploit_command_spec.rb +68 -0
  99. data/spec/cli/exploit_methods_spec.rb +208 -0
  100. data/spec/cli/ruby_shell_spec.rb +14 -0
  101. data/spec/client_side_web_vuln_spec.rb +117 -0
  102. data/spec/exploit_spec.rb +538 -0
  103. data/spec/exploits_spec.rb +3 -4
  104. data/spec/heap_overflow_spec.rb +14 -0
  105. data/spec/lfi_spec.rb +162 -0
  106. data/spec/loot/file_spec.rb +131 -0
  107. data/spec/loot_spec.rb +138 -0
  108. data/spec/memory_corruption_spec.rb +22 -0
  109. data/spec/metadata/arch_spec.rb +82 -0
  110. data/spec/metadata/cookie_param_spec.rb +67 -0
  111. data/spec/metadata/default_filename_spec.rb +62 -0
  112. data/spec/metadata/default_port_spec.rb +62 -0
  113. data/spec/metadata/header_name_spec.rb +67 -0
  114. data/spec/metadata/os_spec.rb +164 -0
  115. data/spec/metadata/shouts_spec.rb +100 -0
  116. data/spec/metadata/url_path_spec.rb +67 -0
  117. data/spec/metadata/url_query_param_spec.rb +67 -0
  118. data/spec/mixins/binary_spec.rb +129 -0
  119. data/spec/mixins/build_dir.rb +66 -0
  120. data/spec/mixins/file_builder_spec.rb +67 -0
  121. data/spec/mixins/format_string_spec.rb +44 -0
  122. data/spec/mixins/has_payload_spec.rb +333 -0
  123. data/spec/mixins/has_targets_spec.rb +434 -0
  124. data/spec/mixins/html_spec.rb +772 -0
  125. data/spec/mixins/http_spec.rb +1227 -0
  126. data/spec/mixins/loot_spec.rb +20 -0
  127. data/spec/mixins/nops_spec.rb +165 -0
  128. data/spec/mixins/remote_tcp_spec.rb +217 -0
  129. data/spec/mixins/remote_udp_spec.rb +217 -0
  130. data/spec/mixins/seh_spec.rb +89 -0
  131. data/spec/mixins/stack_overflow_spec.rb +87 -0
  132. data/spec/mixins/text_spec.rb +43 -0
  133. data/spec/open_redirect_spec.rb +71 -0
  134. data/spec/params/base_url_spec.rb +71 -0
  135. data/spec/params/bind_host_spec.rb +34 -0
  136. data/spec/params/bind_port_spec.rb +35 -0
  137. data/spec/params/filename_spec.rb +77 -0
  138. data/spec/params/host_spec.rb +34 -0
  139. data/spec/params/port_spec.rb +77 -0
  140. data/spec/rfi_spec.rb +107 -0
  141. data/spec/seh_overflow_spec.rb +18 -0
  142. data/spec/spec_helper.rb +6 -10
  143. data/spec/sqli_spec.rb +306 -0
  144. data/spec/ssti_spec.rb +121 -0
  145. data/spec/stack_overflow_spec.rb +18 -0
  146. data/spec/target_spec.rb +92 -0
  147. data/spec/test_result_spec.rb +32 -0
  148. data/spec/use_after_free_spec.rb +14 -0
  149. data/spec/web_spec.rb +12 -0
  150. data/spec/web_vuln_spec.rb +854 -0
  151. data/spec/xss_spec.rb +69 -0
  152. metadata +356 -324
  153. data/Manifest.txt +0 -196
  154. data/README.txt +0 -274
  155. data/bin/ronin-exploit +0 -12
  156. data/bin/ronin-gen-binary-payload +0 -12
  157. data/bin/ronin-gen-exploit +0 -12
  158. data/bin/ronin-gen-ftp-exploit +0 -12
  159. data/bin/ronin-gen-http-exploit +0 -12
  160. data/bin/ronin-gen-local-exploit +0 -12
  161. data/bin/ronin-gen-nops +0 -12
  162. data/bin/ronin-gen-payload +0 -12
  163. data/bin/ronin-gen-remote-exploit +0 -12
  164. data/bin/ronin-gen-remote-tcp-exploit +0 -12
  165. data/bin/ronin-gen-remote-udp-exploit +0 -12
  166. data/bin/ronin-gen-shellcode +0 -12
  167. data/bin/ronin-gen-web-exploit +0 -12
  168. data/bin/ronin-payload +0 -12
  169. data/bin/ronin-payloads +0 -12
  170. data/lib/ronin/controls/behaviors.rb +0 -133
  171. data/lib/ronin/controls/exceptions/not_implemented.rb +0 -27
  172. data/lib/ronin/controls/exceptions/program_not_found.rb +0 -27
  173. data/lib/ronin/controls/exceptions.rb +0 -23
  174. data/lib/ronin/controls/file_system.rb +0 -145
  175. data/lib/ronin/controls/helpers/command_exec.rb +0 -143
  176. data/lib/ronin/controls/helpers/dir_create.rb +0 -42
  177. data/lib/ronin/controls/helpers/dir_listing.rb +0 -62
  178. data/lib/ronin/controls/helpers/dir_remove.rb +0 -42
  179. data/lib/ronin/controls/helpers/file_ctime.rb +0 -52
  180. data/lib/ronin/controls/helpers/file_mtime.rb +0 -53
  181. data/lib/ronin/controls/helpers/file_ownership.rb +0 -53
  182. data/lib/ronin/controls/helpers/file_read.rb +0 -62
  183. data/lib/ronin/controls/helpers/file_remove.rb +0 -51
  184. data/lib/ronin/controls/helpers/file_write.rb +0 -62
  185. data/lib/ronin/controls/helpers/memory_read.rb +0 -39
  186. data/lib/ronin/controls/helpers/memory_write.rb +0 -39
  187. data/lib/ronin/controls/helpers.rb +0 -33
  188. data/lib/ronin/controls.rb +0 -23
  189. data/lib/ronin/exploits/control.rb +0 -47
  190. data/lib/ronin/exploits/exceptions/exception.rb +0 -27
  191. data/lib/ronin/exploits/exceptions/exploit_not_built.rb +0 -29
  192. data/lib/ronin/exploits/exceptions/payload_size.rb +0 -29
  193. data/lib/ronin/exploits/exceptions/restricted_char.rb +0 -29
  194. data/lib/ronin/exploits/exceptions/target_data_missing.rb +0 -29
  195. data/lib/ronin/exploits/exceptions/target_unspecified.rb +0 -29
  196. data/lib/ronin/exploits/exceptions/unknown_helper.rb +0 -29
  197. data/lib/ronin/exploits/exploit_author.rb +0 -33
  198. data/lib/ronin/exploits/ftp.rb +0 -42
  199. data/lib/ronin/exploits/helpers/binary.rb +0 -50
  200. data/lib/ronin/exploits/helpers/buffer_overflow.rb +0 -115
  201. data/lib/ronin/exploits/helpers/file_based.rb +0 -112
  202. data/lib/ronin/exploits/helpers/format_string.rb +0 -117
  203. data/lib/ronin/exploits/helpers/padding.rb +0 -101
  204. data/lib/ronin/exploits/helpers.rb +0 -26
  205. data/lib/ronin/exploits/http.rb +0 -49
  206. data/lib/ronin/exploits/local.rb +0 -40
  207. data/lib/ronin/exploits/remote.rb +0 -40
  208. data/lib/ronin/exploits/remote_tcp.rb +0 -87
  209. data/lib/ronin/exploits/remote_udp.rb +0 -87
  210. data/lib/ronin/exploits/targets/buffer_overflow.rb +0 -46
  211. data/lib/ronin/exploits/targets/format_string.rb +0 -43
  212. data/lib/ronin/exploits/targets.rb +0 -27
  213. data/lib/ronin/exploits/verifiers.rb +0 -121
  214. data/lib/ronin/generators/exploits/exploit.rb +0 -70
  215. data/lib/ronin/generators/exploits/ftp.rb +0 -42
  216. data/lib/ronin/generators/exploits/http.rb +0 -42
  217. data/lib/ronin/generators/exploits/local.rb +0 -42
  218. data/lib/ronin/generators/exploits/remote.rb +0 -42
  219. data/lib/ronin/generators/exploits/remote_tcp.rb +0 -44
  220. data/lib/ronin/generators/exploits/remote_udp.rb +0 -44
  221. data/lib/ronin/generators/exploits/static.rb +0 -30
  222. data/lib/ronin/generators/exploits/web.rb +0 -45
  223. data/lib/ronin/generators/exploits.rb +0 -23
  224. data/lib/ronin/generators/payloads/binary_payload.rb +0 -42
  225. data/lib/ronin/generators/payloads/nops.rb +0 -42
  226. data/lib/ronin/generators/payloads/payload.rb +0 -66
  227. data/lib/ronin/generators/payloads/shellcode.rb +0 -42
  228. data/lib/ronin/generators/payloads/static.rb +0 -30
  229. data/lib/ronin/generators/payloads.rb +0 -23
  230. data/lib/ronin/model/has_default_port.rb +0 -54
  231. data/lib/ronin/model/targets_arch.rb +0 -68
  232. data/lib/ronin/model/targets_os.rb +0 -69
  233. data/lib/ronin/model/targets_product.rb +0 -68
  234. data/lib/ronin/payloads/asm_payload.rb +0 -40
  235. data/lib/ronin/payloads/binary_payload.rb +0 -42
  236. data/lib/ronin/payloads/control.rb +0 -47
  237. data/lib/ronin/payloads/encoders/encoder.rb +0 -92
  238. data/lib/ronin/payloads/encoders/xor.rb +0 -79
  239. data/lib/ronin/payloads/encoders.rb +0 -32
  240. data/lib/ronin/payloads/exceptions/exception.rb +0 -27
  241. data/lib/ronin/payloads/exceptions/not_implemented.rb +0 -29
  242. data/lib/ronin/payloads/exceptions/unknown_helper.rb +0 -29
  243. data/lib/ronin/payloads/exceptions.rb +0 -23
  244. data/lib/ronin/payloads/has_payload.rb +0 -111
  245. data/lib/ronin/payloads/helpers/chained.rb +0 -61
  246. data/lib/ronin/payloads/helpers/rpc.rb +0 -93
  247. data/lib/ronin/payloads/helpers.rb +0 -23
  248. data/lib/ronin/payloads/nops.rb +0 -39
  249. data/lib/ronin/payloads/payload.rb +0 -350
  250. data/lib/ronin/payloads/payload_author.rb +0 -33
  251. data/lib/ronin/payloads/shellcode.rb +0 -40
  252. data/lib/ronin/payloads/web_payload.rb +0 -41
  253. data/lib/ronin/payloads.rb +0 -36
  254. data/lib/ronin/ui/command_line/commands/exploit.rb +0 -193
  255. data/lib/ronin/ui/command_line/commands/exploits.rb +0 -154
  256. data/lib/ronin/ui/command_line/commands/gen_binary_payload.rb +0 -34
  257. data/lib/ronin/ui/command_line/commands/gen_exploit.rb +0 -34
  258. data/lib/ronin/ui/command_line/commands/gen_ftp_exploit.rb +0 -34
  259. data/lib/ronin/ui/command_line/commands/gen_http_exploit.rb +0 -34
  260. data/lib/ronin/ui/command_line/commands/gen_local_exploit.rb +0 -34
  261. data/lib/ronin/ui/command_line/commands/gen_nops.rb +0 -34
  262. data/lib/ronin/ui/command_line/commands/gen_payload.rb +0 -34
  263. data/lib/ronin/ui/command_line/commands/gen_remote_exploit.rb +0 -34
  264. data/lib/ronin/ui/command_line/commands/gen_remote_tcp_exploit.rb +0 -34
  265. data/lib/ronin/ui/command_line/commands/gen_remote_udp_exploit.rb +0 -34
  266. data/lib/ronin/ui/command_line/commands/gen_shellcode.rb +0 -34
  267. data/lib/ronin/ui/command_line/commands/gen_web_exploit.rb +0 -34
  268. data/lib/ronin/ui/command_line/commands/payload.rb +0 -129
  269. data/lib/ronin/ui/command_line/commands/payloads.rb +0 -128
  270. data/lib/ronin/vuln/behavior.rb +0 -165
  271. data/spec/controls/behaviors_examples.rb +0 -38
  272. data/spec/exploits/binary_exploit_spec.rb +0 -44
  273. data/spec/exploits/buffer_overflow_exploit_spec.rb +0 -70
  274. data/spec/exploits/exploit_spec.rb +0 -313
  275. data/spec/exploits/file_based_exploit_spec.rb +0 -48
  276. data/spec/exploits/format_string_exploit_spec.rb +0 -32
  277. data/spec/exploits/ftp_spec.rb +0 -13
  278. data/spec/exploits/http_spec.rb +0 -17
  279. data/spec/exploits/padding_exploit_spec.rb +0 -44
  280. data/spec/exploits/remote_tcp_spec.rb +0 -28
  281. data/spec/exploits/remote_udp_spec.rb +0 -28
  282. data/spec/exploits/target_spec.rb +0 -98
  283. data/spec/exploits/targets/buffer_overflow_spec.rb +0 -22
  284. data/spec/exploits/web_spec.rb +0 -35
  285. data/spec/generators/exploits/exploit_examples.rb +0 -24
  286. data/spec/generators/exploits/exploit_spec.rb +0 -42
  287. data/spec/generators/exploits/ftp_spec.rb +0 -42
  288. data/spec/generators/exploits/http_spec.rb +0 -42
  289. data/spec/generators/exploits/local_spec.rb +0 -42
  290. data/spec/generators/exploits/remote_spec.rb +0 -42
  291. data/spec/generators/exploits/remote_tcp_spec.rb +0 -47
  292. data/spec/generators/exploits/remote_udp_spec.rb +0 -47
  293. data/spec/generators/exploits/web_spec.rb +0 -52
  294. data/spec/generators/payloads/binary_payload_spec.rb +0 -31
  295. data/spec/generators/payloads/nops_spec.rb +0 -31
  296. data/spec/generators/payloads/payload_examples.rb +0 -16
  297. data/spec/generators/payloads/payload_spec.rb +0 -31
  298. data/spec/generators/payloads/shellcode_spec.rb +0 -31
  299. data/spec/helpers/database.rb +0 -5
  300. data/spec/helpers/objects.rb +0 -22
  301. data/spec/model/has_default_port_spec.rb +0 -27
  302. data/spec/model/models/default_port_model.rb +0 -13
  303. data/spec/model/models/non_default_port_model.rb +0 -11
  304. data/spec/model/models/targets_arch_model.rb +0 -11
  305. data/spec/model/models/targets_os_model.rb +0 -11
  306. data/spec/model/models/targets_product_model.rb +0 -11
  307. data/spec/model/targets_arch_spec.rb +0 -32
  308. data/spec/model/targets_os_spec.rb +0 -33
  309. data/spec/model/targets_product_spec.rb +0 -35
  310. data/spec/objects/exploits/example.rb +0 -25
  311. data/spec/objects/exploits/simple.rb +0 -24
  312. data/spec/objects/payloads/simple.rb +0 -19
  313. data/spec/payloads/encoders/encoder_spec.rb +0 -30
  314. data/spec/payloads/encoders/xor_spec.rb +0 -20
  315. data/spec/payloads/payload_spec.rb +0 -156
  316. data/spec/vuln/behavior_spec.rb +0 -15
  317. data/static/ronin/generators/exploits/_cache.erb +0 -14
  318. data/static/ronin/generators/exploits/_header.erb +0 -1
  319. data/static/ronin/generators/exploits/_helpers.erb +0 -4
  320. data/static/ronin/generators/exploits/exploit.erb +0 -24
  321. data/static/ronin/generators/exploits/ftp.erb +0 -24
  322. data/static/ronin/generators/exploits/http.erb +0 -26
  323. data/static/ronin/generators/exploits/local.erb +0 -24
  324. data/static/ronin/generators/exploits/remote.erb +0 -24
  325. data/static/ronin/generators/exploits/remote_tcp.erb +0 -26
  326. data/static/ronin/generators/exploits/remote_udp.erb +0 -26
  327. data/static/ronin/generators/exploits/web.erb +0 -28
  328. data/static/ronin/generators/payloads/_cache.erb +0 -10
  329. data/static/ronin/generators/payloads/_header.erb +0 -1
  330. data/static/ronin/generators/payloads/_helpers.erb +0 -2
  331. data/static/ronin/generators/payloads/binary_payload.erb +0 -25
  332. data/static/ronin/generators/payloads/nops.erb +0 -19
  333. data/static/ronin/generators/payloads/payload.erb +0 -25
  334. data/static/ronin/generators/payloads/shellcode.erb +0 -25
  335. data/tasks/spec.rb +0 -10
  336. data/tasks/yard.rb +0 -13
  337. data.tar.gz.sig +0 -0
  338. metadata.gz.sig +0 -0
@@ -1,558 +1,561 @@
1
1
  #
2
- # Ronin Exploits - A Ruby library for Ronin that provides exploitation and
2
+ # ronin-exploits - A Ruby library for ronin-rb that provides exploitation and
3
3
  # payload crafting functionality.
4
4
  #
5
- # Copyright (c) 2007-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
5
+ # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
6
  #
7
- # This program is free software; you can redistribute it and/or modify
8
- # it under the terms of the GNU General Public License as published by
9
- # the Free Software Foundation; either version 2 of the License, or
7
+ # ronin-exploits is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
10
  # (at your option) any later version.
11
11
  #
12
- # This program is distributed in the hope that it will be useful,
12
+ # ronin-exploits is distributed in the hope that it will be useful,
13
13
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
14
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # GNU General Public License for more details.
15
+ # GNU Lesser General Public License for more details.
16
16
  #
17
- # You should have received a copy of the GNU General Public License
18
- # along with this program; if not, write to the Free Software
19
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-exploits. If not, see <https://www.gnu.org/licenses/>.
20
19
  #
21
20
 
22
- require 'ronin/exploits/exceptions/unknown_helper'
23
- require 'ronin/exploits/exceptions/target_unspecified'
24
- require 'ronin/exploits/exceptions/target_data_missing'
25
- require 'ronin/exploits/exceptions/restricted_char'
26
- require 'ronin/exploits/exceptions/exploit_not_built'
27
- require 'ronin/exploits/verifiers'
28
- require 'ronin/exploits/exploit_author'
29
- require 'ronin/exploits/target'
30
- require 'ronin/exploits/control'
31
- require 'ronin/payloads/has_payload'
32
- require 'ronin/payloads/payload'
33
- require 'ronin/controls/behaviors'
34
- require 'ronin/cacheable'
35
- require 'ronin/model/has_name'
36
- require 'ronin/model/has_description'
37
- require 'ronin/model/has_version'
38
- require 'ronin/model/has_license'
39
- require 'ronin/ui/output/helpers'
40
- require 'ronin/extensions/kernel'
41
-
42
- require 'parameters'
21
+ require 'ronin/exploits/registry'
22
+ require 'ronin/exploits/advisory'
23
+ require 'ronin/exploits/test_result'
24
+ require 'ronin/exploits/exceptions'
25
+ require 'ronin/core/metadata/id'
26
+ require 'ronin/core/metadata/authors'
27
+ require 'ronin/core/metadata/summary'
28
+ require 'ronin/core/metadata/description'
29
+ require 'ronin/core/metadata/references'
30
+ require 'ronin/core/params/mixin'
31
+ require 'ronin/support/cli/printing'
32
+ require 'ronin/post_ex'
33
+
43
34
  require 'chars/char_set'
44
35
 
45
36
  module Ronin
46
37
  module Exploits
38
+ #
39
+ # The {Exploit} class allows for describing exploits for security
40
+ # vulnerabilities, purely in Ruby. Exploits contain metadata about the
41
+ # exploit/vulnerability and methods which defines the functionality
42
+ # of the exploit. Exploits may also include additional
43
+ # {Mixins mixin modules} to add additional functionality, such as defining
44
+ # targets or loading in a payload.
45
+ #
46
+ # ## Philosophy
47
+ #
48
+ # Exploits are just programs with steps to build and launch the exploit.
49
+ # Exploits also typically contain metadata that describes the exploit's
50
+ # author(s), release date, what the exploit does, etc.
51
+ #
52
+ # The {Exploit} class defines six key parts:
53
+ #
54
+ # 1. Metadata - defines information about the exploit.
55
+ # 2. Params - user configurable parameters.
56
+ # 3. {Exploit#test test} - optional method that tests whether the target is
57
+ # vulnerable or not.
58
+ # 4. {Exploit#build build} - method which builds the exploit.
59
+ # 5. {Exploit#launch launch} - method which launches the exploit.
60
+ # 6. {Exploit#cleanup cleanup} - optional Method which performs additional
61
+ # cleanup steps.
62
+ #
63
+ # ## Example
64
+ #
65
+ # require 'ronin/exploits/exploit'
66
+ # require 'ronin/exploits/mixins/remote_tcp'
67
+ #
68
+ # module Ronin
69
+ # module Exploits
70
+ # class MyExploit < Exploit
71
+ #
72
+ # include Mixins::RemoteTCP
73
+ #
74
+ # register 'my_exploit'
75
+ #
76
+ # summary 'My first exploit'
77
+ # description <<~EOS
78
+ # This is my first exploit.
79
+ # Bla bla bla bla.
80
+ # EOS
81
+ #
82
+ # author '...'
83
+ # author '...', email: '...', twitter: '...'
84
+ #
85
+ # disclosure_date 'YYY-MM-DD'
86
+ # release_date 'YYYY-MM-DD'
87
+ #
88
+ # advisory 'CVE-YYYY-NNNN'
89
+ # advisory 'GHSA-XXXXXX'
90
+ # software 'TestHTTP'
91
+ # software_versions '1.0.0'..'1.5.4'
92
+ #
93
+ # param :cmd, desc: 'The command to run'
94
+ #
95
+ # def test
96
+ # # ...
97
+ # end
98
+ #
99
+ # def build
100
+ # # ...
101
+ # end
102
+ #
103
+ # def launch
104
+ # # ...
105
+ # end
106
+ #
107
+ # def cleanup
108
+ # # ...
109
+ # end
110
+ #
111
+ # end
112
+ # end
113
+ # end
114
+ #
115
+ # ### register
116
+ #
117
+ # Registers the exploit with `Exploits`.
118
+ #
119
+ # register 'my_exploit'
120
+ #
121
+ # ### quality
122
+ #
123
+ # Defines the quality level of the exploit. Accepted values are:
124
+ #
125
+ # * `:testing`
126
+ # * `:poc`
127
+ # * `:weaponized`
128
+ #
129
+ # quality :poc
130
+ #
131
+ # ### summary
132
+ #
133
+ # Defines a short one-sentence description of the exploit.
134
+ #
135
+ # summary 'My first exploit'
136
+ #
137
+ # ### description
138
+ #
139
+ # Defines a longer multi-paragraph escription of the exploit.
140
+ #
141
+ # description <<~EOS
142
+ # This is my first exploit.
143
+ # Bla bla bla bla.
144
+ # EOS
145
+ #
146
+ # **Note:** that `<<~` heredoc, unlike the regular `<<` heredoc, removes
147
+ # leading whitespace.
148
+ #
149
+ # ### author
150
+ #
151
+ # Add an author's name and additional information to the exploit.
152
+ #
153
+ # author 'John Smith'
154
+ #
155
+ # author 'doctor_doom', email: '...', twitter: '...'
156
+ #
157
+ # ### software
158
+ #
159
+ # Defines the software which the exploit targets.
160
+ #
161
+ # software 'TestApp'
162
+ #
163
+ # ### software_versions
164
+ #
165
+ # Defines the software versions which the exploit targets:
166
+ #
167
+ # software_versions %w[
168
+ # 1.0.0
169
+ # 1.0.1
170
+ # 1.0.2
171
+ # 1.1.0
172
+ # ]
173
+ #
174
+ # software_versions '1.0.0'..'1.5.4'
175
+ #
176
+ # ### param
177
+ #
178
+ # Defines a user configurable param. Params may have a type class, but
179
+ # default to `String`. Params must have a one-line description.
180
+ #
181
+ # param :str, desc: 'A basic string param'
182
+ #
183
+ # param :feature_flag, Boolean, desc: 'A boolean param'
184
+ #
185
+ # param :enum, Enum[:one, :two, :three],
186
+ # desc: 'An enum param'
187
+ #
188
+ # param :num1, Integer, desc: 'An integer param'
189
+ #
190
+ # param :num2, Integer, default: 42,
191
+ # desc: 'A param with a default value'
192
+ #
193
+ # param :num3, Integer, default: ->{ rand(42) },
194
+ # desc: 'A param with a dynamic default value'
195
+ #
196
+ # param :float, Float, 'Floating point param'
197
+ #
198
+ # param :url, URI, desc: 'URL param'
199
+ #
200
+ # param :pattern, Regexp, desc: 'Regular Expression param'
201
+ #
202
+ # Params may then be accessed in instance methods using `params` Hash.
203
+ #
204
+ # param :padding, Integer, desc: 'Amount of additional padding'
205
+ #
206
+ # def build
207
+ # # ...
208
+ #
209
+ # if params[:padding]
210
+ # @buffer << 'A' * params[:padding]
211
+ # end
212
+ # end
213
+ #
214
+ # ### test
215
+ #
216
+ # The method which may define tests which confirm whether the target is
217
+ # vulnerable. The method must return a {Exploit#Vulnerable Vulnerable},
218
+ # {Exploit#NotVulnerable NotVulnerable}, or an {Exploit#Unknown} object.
219
+ #
220
+ # def test
221
+ # case http.get_body('/')
222
+ # when /Powered by Foo 4\.19\./
223
+ # Vulnerable('host is vulnerable')
224
+ # when /Powered by Foo 4\.2[0-9]\./
225
+ # NotVulnerable('host is patched')
226
+ # else
227
+ # Unknown('cannot determine whether the host is vulnerable or not')
228
+ # end
229
+ # end
230
+ #
231
+ # ### build
232
+ #
233
+ # The method which defines the logic that builds the exploit before
234
+ # launching it.
235
+ #
236
+ # def build
237
+ # @buffer = "..."
238
+ # @buffer << "..."
239
+ # end
240
+ #
241
+ # ### launch
242
+ #
243
+ # The method which launches the built exploit against the target.
244
+ #
245
+ # def launch
246
+ # @socket = tcp_connect do |socket|
247
+ # socket.write(@buffer)
248
+ # end
249
+ # end
250
+ #
251
+ # ### cleanup
252
+ #
253
+ # The method which defines additional cleanup tasks after the exploit has
254
+ # successfully launched and any post-exploitation tasks have been completed.
255
+ #
256
+ # def cleanup
257
+ # @socket.close
258
+ # end
259
+ #
47
260
  class Exploit
48
261
 
49
- include Parameters
50
- include Cacheable
51
- include Model::HasName
52
- include Model::HasDescription
53
- include Model::HasVersion
54
- include Model::HasLicense
55
- include Payloads::HasPayload
56
- include Controls::Behaviors
57
- include UI::Output::Helpers
58
- include Verifiers
262
+ include Core::Metadata::ID
263
+ include Core::Metadata::Authors
264
+ include Core::Metadata::Summary
265
+ include Core::Metadata::Description
266
+ include Core::Metadata::References
267
+ include Core::Params::Mixin
268
+ include Support::CLI::Printing
59
269
 
60
270
  #
61
- # Creates a new Ronin::Exploits::Exploit object using the given
62
- # _block_.
271
+ # Registers the exploit with the given name.
63
272
  #
64
- # ronin_exploit do
65
- # ...
66
- # end
273
+ # @param [String] exploit_id
274
+ # The exploit's `id`.
67
275
  #
68
- contextify :ronin_exploit
69
-
70
- # Primary key of the exploit
71
- property :id, Serial
72
-
73
- # The status of the exploit (either, :potential, :proven or
74
- # :weaponized)
75
- property :status, Enum[
76
- :potential,
77
- :proven,
78
- :weaponized
79
- ], :default => :potential
80
-
81
- # The disclosure status of the exploit (any of, :private,
82
- # :vendor_aware, :in_wild and :public)
83
- property :disclosure, Flag[
84
- :private,
85
- :in_wild,
86
- :vendor_aware,
87
- :public
88
- ]
89
-
90
- # Author(s) of the exploit
91
- has n, :authors, :model => 'Ronin::Exploits::ExploitAuthor'
92
-
93
- # Behaviors that the exploit allows
94
- has n, :controls, :model => 'Ronin::Exploits::Control'
95
-
96
- # Targets for the exploit
97
- has n, :targets
98
-
99
- # Validations
100
- validates_present :name
101
- validates_is_unique :version, :scope => [:name]
102
-
103
- # Exploit target
104
- attr_writer :target
105
-
106
- # Characters to restrict
107
- attr_reader :restricted_chars
108
-
109
- # Encoders to run on the payload
110
- attr_reader :encoders
111
-
112
- # The raw unencoded payload
113
- attr_reader :raw_payload
114
-
115
- # The encoded payload
116
- attr_reader :encoded_payload
117
-
118
- #
119
- # Creates a new Exploit object.
276
+ # @api public
120
277
  #
121
- # @param [Hash] attributes
122
- # Additional attributes used to initialize the exploit's model
123
- # attributes and parameters.
124
- #
125
- # @yield []
126
- # If a block is given, it will be evaluated in the newly created
127
- # Exploit object.
128
- #
129
- def initialize(attributes={},&block)
130
- super(attributes)
131
-
132
- initialize_params(attributes)
133
-
134
- @target = nil
135
- @built = false
136
- @deployed = false
137
-
138
- @restricted_chars = Chars::CharSet.new
139
- @encoders = []
140
-
141
- instance_eval(&block) if block
278
+ def self.register(exploit_id)
279
+ id(exploit_id)
280
+ Exploits.register(exploit_id,self)
142
281
  end
143
282
 
144
283
  #
145
- # Finds all exploits written by a specific author.
284
+ # Gets or sets the quality of the exploit.
146
285
  #
147
- # @param [String] name
148
- # The name of the author.
286
+ # @param [:testing, :poc, :weaponized, nil] new_quality
287
+ # The optional new quality to set.
149
288
  #
150
- # @return [Array<Exploit>]
151
- # The exploits written by the author.
289
+ # @return [:testing, :poc, :weaponized, nil]
290
+ # The exploit's quality.
152
291
  #
153
- def self.written_by(name)
154
- all(self.authors.name.like => "%#{name}%")
292
+ # @api public
293
+ #
294
+ def self.quality(new_quality=nil)
295
+ if new_quality then @new_quality = new_quality
296
+ else @new_quality
297
+ end
155
298
  end
156
299
 
157
300
  #
158
- # Finds all exploits written for a specific organization.
301
+ # Gets or sets the release date for the exploit.
159
302
  #
160
- # @param [String] name
161
- # The name of the organization.
303
+ # @param [String, nil] new_date
304
+ # The optional new release date to set.
162
305
  #
163
- # @return [Array<Exploit>]
164
- # The exploits written for the organization.
306
+ # @return [Date, nil]
307
+ # The exploit's release date.
165
308
  #
166
- def self.written_for(name)
167
- all(self.authors.organization.like => "%#{name}%")
309
+ def self.release_date(new_date=nil)
310
+ if new_date then @release_date = Date.parse(new_date)
311
+ else @release_date
312
+ end
168
313
  end
169
314
 
170
315
  #
171
- # Finds all exploits which target a given architecture.
172
- #
173
- # @param [String, Symbol] name
174
- # The name of the architecture.
316
+ # Determines whether the exploit has been publically released yet.
175
317
  #
176
- # @return [Array<Exploit>]
177
- # The exploits targeting the architecture.
318
+ # @return [Boolean]
178
319
  #
179
- def self.targeting_arch(name)
180
- all(self.targets.arch.name => name.to_s)
320
+ def self.released?
321
+ !release_date.nil?
181
322
  end
182
323
 
183
324
  #
184
- # Finds all exploits which target a given OS.
325
+ # Gets or sets the disclosure date for the exploit.
185
326
  #
186
- # @param [String, Symbol] name
187
- # The name of the OS.
327
+ # @param [String, nil] new_date
328
+ # The optional new disclosure date to set.
188
329
  #
189
- # @return [Array<Exploit>]
190
- # The exploits targeting the OS.
330
+ # @return [Date, nil]
331
+ # The exploit's disclosure date.
191
332
  #
192
- def self.targeting_os(name)
193
- all(self.targets.os.name => name.to_s)
333
+ # @example
334
+ # disclosure_date '2022-04-20'
335
+ #
336
+ def self.disclosure_date(new_date=nil)
337
+ if new_date then @disclosure_date = Date.parse(new_date)
338
+ else @disclosure_date
339
+ end
194
340
  end
195
341
 
196
342
  #
197
- # Finds all exploits which target a given product.
343
+ # Determines whether the exploit has been disclosed yet.
198
344
  #
199
- # @param [String, Symbol] name
200
- # The name of the product.
201
- #
202
- # @return [Array<Exploit>]
203
- # The exploits targeting the product.
345
+ # @return [Boolean]
204
346
  #
205
- def self.targeting_product(name)
206
- all(self.targets.product.name => "%#{name}%")
347
+ def self.disclosed?
348
+ !disclosure_date.nil?
207
349
  end
208
350
 
209
351
  #
210
- # Adds a new author to the exploit.
211
- #
212
- # @param [Hash] attributes
213
- # Additional attributes to create the ExploitAuthor object with.
352
+ # The advisory IDs for the exploit.
214
353
  #
215
- # @yield [author]
216
- # If a block is given, it will be passed the newly created author
217
- # object.
354
+ # @return [Set<Advisory>]
355
+ # The set of advisories for the exploit.
218
356
  #
219
- # @yieldparam [ExploitAuthor] author
220
- # The author object tied to the exploit.
221
- #
222
- # @example
223
- # author :name => 'Anonymous',
224
- # :email => 'anon@example.com',
225
- # :organization => 'Anonymous LLC'
357
+ # @api semipublic
226
358
  #
227
- def author(attributes={},&block)
228
- self.authors << ExploitAuthor.new(attributes,&block)
359
+ def self.advisories
360
+ @advisories ||= Set.new
229
361
  end
230
362
 
231
363
  #
232
- # Adds a new target to the exploit.
364
+ # Adds an advisory for the exploit.
233
365
  #
234
- # @param [Hash] attributes
235
- # Additional attributes to create the target with.
366
+ # @param [String] id
367
+ # The advisory ID.
236
368
  #
237
- # @yield [target]
238
- # If a block is given, it will be passed the newly created target.
369
+ # @param [String] url
370
+ # The optional advisory URL. If the advisory `id` begins with `CVE-`
371
+ # or `GHSA-`, then the URL will automatically be derived from the `id`.
239
372
  #
240
- # @yieldparam [Target] target
241
- # The newly created target.
373
+ # @api public
242
374
  #
243
- # @example
244
- # targeting do |target|
245
- # target.arch :i686
246
- # target.os :name => 'Linux'
247
- # end
248
- #
249
- def targeting(attributes={},&block)
250
- self.targets << Target.new(attributes,&block)
375
+ def self.advisory(id,url=Advisory.url_for(id))
376
+ advisories << Advisory.new(id,url)
251
377
  end
252
378
 
253
379
  #
254
- # Adds new characters to the list of restricted characters.
380
+ # Gets or sets the software which the exploit targets.
255
381
  #
256
- # @param [Array<String>] chars
257
- # The character to restrict.
382
+ # @param [String, nil] new_software
383
+ # the optional new software name to set.
258
384
  #
259
- # @return [Array<String>]
260
- # The new list of restricted characters.
385
+ # @return [String, nil]
386
+ # The name of the software which the exploit targets.
261
387
  #
262
- # @example
263
- # restrict 0x00, "\n"
264
- # # => #<Chars::CharSet: {"\0", "\n"}>
388
+ # @api public
265
389
  #
266
- def restrict(*chars)
267
- @restricted_chars += chars
390
+ def self.software(new_software=nil)
391
+ if new_software
392
+ @software = new_software
393
+ else
394
+ @software ||= if superclass < Exploit
395
+ superclass.software
396
+ end
397
+ end
268
398
  end
269
399
 
270
400
  #
271
- # Adds a new encoder to the list of encoders to use for encoding the
272
- # payload.
273
- #
274
- # @param [#encode] encoder
275
- # The payload encoder object to use.
276
- # Must provide an encode method.
277
- #
278
- # @yield [payload]
279
- # If a block is given, and an encoder object is not, the block will
280
- # be used to encode the payload.
281
- #
282
- # @yieldparam [String] payload
283
- # The payload to be encoded.
284
- #
285
- # @return [Array]
286
- # The new list of encoders to use to encode the payload.
401
+ # Gets or sets the software version(s) which the exploit targets.
287
402
  #
288
- # @raise [RuntimeError]
289
- # The payload encoder object does not provide an encode method.
403
+ # @param [Array<String>, Range<String,String>, nil] new_software_versions
404
+ # the optional new software version(s) to set.
290
405
  #
291
- # @raise [ArgumentError]
292
- # Either a payload encoder object or a block can be given.
406
+ # @return [Array<String>, Range<String,String>, nil]
407
+ # The name of the software version which the exploit targets.
293
408
  #
294
- # @example
295
- # exploit.encode_payload(some_encoder)
296
- #
297
- # @example
298
- # exploit.encode_payload do |payload|
299
- # # ...
300
- # end
409
+ # @api public
301
410
  #
302
- def encode_payload(encoder=nil,&block)
303
- if encoder
304
- unless encoder.respond_to?(:encode)
305
- raise(RuntimeError,"The payload encoder must provide an encode method",caller)
306
- end
307
-
308
- @encoders << encoder
309
- elsif (encoder.nil? && block)
310
- @encoders << block
411
+ def self.software_versions(new_software_versions=nil)
412
+ if new_software_versions
413
+ @software_versions = new_software_versions
311
414
  else
312
- raise(ArgumentError,"either a payload encoder or a block can be given",caller)
415
+ @software_versions ||= if superclass < Exploit
416
+ superclass.software_versions
417
+ end
313
418
  end
314
419
  end
315
420
 
316
421
  #
317
- # Lists the behaviors controlled by the exploit and the payload, if
318
- # one is being used.
422
+ # Returns the type or kind of exploit.
319
423
  #
320
- # @return [Array<Symbol>]
321
- # The combined behaviors controlled by the exploit.
424
+ # @return [Symbol]
322
425
  #
323
- def behaviors
324
- total_behaviors = super
325
-
326
- if @payload
327
- total_behaviors = (total_behaviors + @payload.behaviors).uniq
328
- end
329
-
330
- return total_behaviors
331
- end
332
-
426
+ # @note
427
+ # This is used internally to map an exploit class to a printable type.
333
428
  #
334
- # @return [Array<Arch>]
335
- # The targeted architectures.
429
+ # @api private
336
430
  #
337
- def targeted_archs
338
- self.targets.map { |target| target.arch }.compact
431
+ def self.exploit_type
432
+ :exploit
339
433
  end
340
434
 
341
435
  #
342
- # @return [Array<OS>]
343
- # The targeted OSes.
436
+ # Initializes the exploit.
344
437
  #
345
- def targeted_oses
346
- self.targets.map { |target| target.os }.compact
347
- end
348
-
349
- #
350
- # @return [Array<Product>]
351
- # The targeted Products.
438
+ # @param [Hash{Symbol => Object}] kwargs
439
+ # Additional keyword arguments.
352
440
  #
353
- def targeted_products
354
- self.targets.map { |target| target.product }.compact
441
+ def initialize(**kwargs)
442
+ super(**kwargs)
355
443
  end
356
444
 
357
445
  #
358
- # Selects a target to use in exploitation.
446
+ # Initializes and runs the exploit.
359
447
  #
360
- # @param [Integer, Hash] index_or_query
361
- # The index within #targets or a query to select the target.
448
+ # @param [Hash{Symbol => Object}] kwargs
449
+ # Additional keyword arguments for {#initialize}.
362
450
  #
363
- # @yield [target]
364
- # If a block is given, it will be used to select the desired
365
- # target from #targets.
451
+ # @yield [exploit]
452
+ # If a block is given, it will be yielded the exploit after it has been
453
+ # launched. Once the block has returned, {#cleanup} will automatically
454
+ # be called.
366
455
  #
367
- # @yieldparam [Target] target
368
- # The potential target to review.
456
+ # @yieldparam [Exploit] exploit
457
+ # The launched exploit.
369
458
  #
370
- # @example
371
- # use_target!(2)
459
+ # @return [Exploit]
460
+ # The launched exploit.
372
461
  #
373
- # @example
374
- # use_target!(Target.arch.name => 'i686')
462
+ # @since 1.0.0
375
463
  #
376
- # @example
377
- # use_target! { |target| target.arch == Arch.i686 }
378
- #
379
- # @since 0.3.0
380
- #
381
- def use_target!(index_or_query=0,&block)
382
- @target = if block
383
- self.targets.find(&block)
384
- elsif index_or_query.kind_of?(Hash)
385
- self.targets.first(index_or_query)
386
- elsif index_or_query.kind_of?(Integer)
387
- self.targets[index_or_query]
388
- end
464
+ def self.exploit(**kwargs,&block)
465
+ new(**kwargs).exploit(&block)
389
466
  end
390
467
 
391
468
  #
392
- # @return [Target]
393
- # The current target to use in exploitation.
469
+ # Validates that the exploit is ready to be used.
394
470
  #
395
- def target
396
- @target ||= self.targets.first
397
- end
398
-
471
+ # @raise [Ronin::Core::Params::RequiredParam]
472
+ # One of the required params was not set.
399
473
  #
400
- # @return [Arch]
401
- # The current targeted architecture.
474
+ # @raise [ValidationError]
475
+ # Another kind of validation error occurred.
402
476
  #
403
- def arch
404
- target.arch if target
477
+ # @api semipublic
478
+ #
479
+ def perform_validate
480
+ validate_params
481
+ validate
405
482
  end
406
483
 
407
484
  #
408
- # @return [OS]
409
- # The current targeted OS.
485
+ # Tests whether the target is vulnerable or not.
410
486
  #
411
- def os
412
- target.os if target
413
- end
414
-
487
+ # @api semipublic
415
488
  #
416
- # @return [Product]
417
- # The current targeted product.
489
+ # @since 1.0.0
418
490
  #
419
- def product
420
- target.product if target
491
+ def perform_test
492
+ test
421
493
  end
422
494
 
423
495
  #
424
- # Associates a payload with the exploit, and the exploit with the
425
- # payload.
496
+ # Builds the exploit.
426
497
  #
427
- # @param [Payload] new_payload
428
- # The new payload to associate with the exploit.
498
+ # @api semipublic
429
499
  #
430
- # @return [Payload]
431
- # The new payload.
500
+ # @since 1.0.0
432
501
  #
433
- # @since 0.3.0
434
- #
435
- def payload=(new_payload)
436
- if (@payload && new_payload.nil?)
437
- @payload.exploit = nil
438
- end
439
-
440
- super(new_payload)
441
-
442
- if @payload
443
- print_info "Using payload: #{new_payload}"
444
-
445
- @payload.exploit = self
446
- end
447
-
448
- return @payload
502
+ def perform_build
503
+ build
449
504
  end
450
505
 
451
506
  #
452
- # Sets the raw payload to use with the exploit.
507
+ # Launches the exploit.
453
508
  #
454
- # @param [String, #to_s] new_raw_payload
455
- # The new raw payload to use with the exploit.
509
+ # @api semipublic
456
510
  #
457
- # @return [String]
458
- # The new raw payload of the exploit.
511
+ # @since 1.0.0
459
512
  #
460
- def raw_payload=(new_raw_payload)
461
- new_raw_payload = new_raw_payload.to_s
462
-
463
- print_debug "Using raw payload: #{new_raw_payload.dump}"
464
-
465
- @raw_payload = new_raw_payload
513
+ def perform_launch
514
+ launch
466
515
  end
467
516
 
468
517
  #
469
- # Builds the current payload, saving the result to the +@raw_payload+
470
- # instance variable.
471
- #
472
- # @param [Hash] options
473
- # Additional options to build the paylod with.
518
+ # Cleans up the exploit.
474
519
  #
475
- # @return [String]
476
- # The built payload.
520
+ # @api semipublic
477
521
  #
478
- # @see Payload#build!
479
- # @since 0.3.0
522
+ # @since 1.0.0
480
523
  #
481
- def build_payload!(options={})
482
- if @payload
483
- @raw_payload = ''
484
-
485
- @payload.build!(options)
486
- @raw_payload = @payload.raw_payload
487
- else
488
- @raw_payload ||= ''
489
- end
490
-
491
- return @raw_payload
524
+ def perform_cleanup
525
+ cleanup
492
526
  end
493
527
 
494
528
  #
495
- # Encodes the current payload and saves the result in the
496
- # +@encoded_payload+ instance variable.
529
+ # Builds the exploit and then launchs the exploit.
497
530
  #
498
- # @return [String]
499
- # The encoded payload.
531
+ # @param [Boolean] dry_run
532
+ # If `true` performs a dry-run by only calling {#build} and **not**
533
+ # launching the exploit.
500
534
  #
501
- def encode_payload!
502
- @encoded_payload = @raw_payload.to_s
503
-
504
- @encoders.each do |encoder|
505
- print_debug "Encoding payload: #{@encoded_payload.dump}"
506
-
507
- new_payload = if encoder.respond_to?(:encode)
508
- encoder.encode(@encoded_payload)
509
- elsif encoder.respond_to?(:call)
510
- encoder.call(@encoded_payload)
511
- end
512
-
513
- @encoded_payload = (new_payload || @encoded_payload).to_s
514
- end
515
-
516
- return @encoded_payload
517
- end
518
-
535
+ # @yield [exploit]
536
+ # If a block is given, it will be yielded the exploit after it has been
537
+ # launched. Once the block has returned, {#cleanup} will automatically
538
+ # be called.
519
539
  #
520
- # @return [Boolean]
521
- # Specifies whether the exploit is built.
540
+ # @yieldparam [Exploit] exploit
541
+ # The launched exploit.
522
542
  #
523
- def built?
524
- @built == true
525
- end
526
-
543
+ # @return [Exploit]
544
+ # The launched exploit.
527
545
  #
528
- # Builds the exploit and checks for restricted characters or patterns.
546
+ # @api public
529
547
  #
530
- # @param [Hash] options
531
- # Additional options to also use as parameters.
548
+ # @since 1.0.0
532
549
  #
533
- def build!(options={},&block)
534
- self.params = options
535
-
536
- print_debug "Exploit parameters: #{self.params.inspect}"
537
-
538
- @built = false
550
+ def exploit(dry_run: false)
551
+ perform_build
539
552
 
540
- build_payload!(options)
541
- encode_payload!
553
+ unless dry_run
554
+ perform_launch
542
555
 
543
- print_info "Building exploit ..."
544
-
545
- build
546
-
547
- print_info "Exploit built!"
548
-
549
- @built = true
550
-
551
- if block
552
- if block.arity == 1
553
- block.call(self)
554
- else
555
- block.call()
556
+ if block_given?
557
+ yield self
558
+ perform_cleanup
556
559
  end
557
560
  end
558
561
 
@@ -560,230 +563,146 @@ module Ronin
560
563
  end
561
564
 
562
565
  #
563
- # Verifies the exploit is built, properly configured, built and
564
- # ready deployment.
566
+ # @group Exploit API Methods
565
567
  #
566
- # @return [true]
567
- # The exploit is built and ready for deployment.
568
+
568
569
  #
569
- # @raise [ExploitNotBuilt]
570
- # The exploit has not been built, and cannot be deployed.
570
+ # Place holder methods for additional validation logic.
571
571
  #
572
- def verify!
573
- unless built?
574
- raise(ExploitNotBuilt,"cannot deploy an unbuilt exploit",caller)
575
- end
576
-
577
- print_info "Verifying exploit ..."
578
-
579
- verify
580
-
581
- print_info "Exploit verified!"
582
- return true
583
- end
584
-
572
+ # @abstract
585
573
  #
586
- # @return [Boolean]
587
- # Specifies whether the exploit has previously been deployed.
574
+ # @api public
575
+ #
576
+ # @since 1.0.0
588
577
  #
589
- def deployed?
590
- @deployed == true
578
+ def validate
591
579
  end
592
580
 
593
581
  #
594
- # Verifies then deploys the exploit. If a payload has been set,
595
- # the payload will also be deployed.
596
- #
597
- # @yield [exploit]
598
- # If a block is given, it will be passed the deployed exploit.
582
+ # Returns a vulnerable test result for the {#test} method.
599
583
  #
600
- # @yieldparam [Exploit] exploit
601
- # The deployed exploit.
584
+ # @return [TestResult::Vulnerable]
602
585
  #
603
- # @return [Exploit]
604
- # The deployed exploit.
586
+ # @example
587
+ # def test
588
+ # # ...
589
+ # return Vulnerable("the host is vulnerable")
590
+ # # ...
591
+ # end
605
592
  #
606
- # @raise [ExploitNotBuilt]
607
- # The exploit has not been built, and cannot be deployed.
593
+ # @since 1.0.0
608
594
  #
609
- def deploy!(&block)
610
- verify!
611
-
612
- print_info "Deploying exploit ..."
613
- @deployed = false
614
-
615
- deploy()
616
-
617
- print_info "Exploit deployed!"
618
- @deployed = true
619
-
620
- @payload.deploy!() if @payload
621
-
622
- if block
623
- if block.arity == 1
624
- block.call(self)
625
- else
626
- block.call()
627
- end
628
- end
629
-
630
- return self
595
+ def Vulnerable(message)
596
+ TestResult::Vulnerable.new(message)
631
597
  end
632
598
 
633
599
  #
634
- # Builds, verified and then deploys the exploit.
600
+ # Returns a not vulnerable test result for the {#test} method.
601
+ #
602
+ # @return [TestResult::NotVulnerable]
603
+ #
604
+ # @example
605
+ # def test
606
+ # # ...
607
+ # return NotVulnerable("the host is not vulnerable")
608
+ # # ...
609
+ # end
635
610
  #
636
- # @param [Hash] options
637
- # Additional options to build the exploit with.
611
+ # @since 1.0.0
638
612
  #
639
- # @option options [Boolean] :dry_run (false)
640
- # Specifies whether to do a dry-run of the exploit, where the
641
- # exploit will be built, verified but *not* deployed.
613
+ def NotVulnerable(message)
614
+ TestResult::NotVulnerable.new(message)
615
+ end
616
+
642
617
  #
643
- # @yieldparam [Exploit] exploit
644
- # The deployed exploit.
618
+ # Returns an unknown test result for the {#test} method.
645
619
  #
646
- # @return [Exploit]
647
- # The deployed exploit.
620
+ # @return [TestResult::Unknown]
648
621
  #
649
- # @return [Exploit]
650
- # The deployed exploit.
622
+ # @example
623
+ # def test
624
+ # # ...
625
+ # return Unknown("cannot determine whether the host is vulnerable")
626
+ # # ...
627
+ # end
651
628
  #
652
- # @since 0.3.0
629
+ # @since 1.0.0
653
630
  #
654
- def exploit!(options={},&block)
655
- build!(options)
656
-
657
- unless options[:dry_run]
658
- deploy!(&block)
659
- end
660
-
661
- return self
631
+ def Unknown(message)
632
+ TestResult::Unknown.new(message)
662
633
  end
663
634
 
664
635
  #
665
- # Converts the exploit to a String.
636
+ # Place holder method for testing whether the targeet is vulnerable.
666
637
  #
667
- # @return [String]
668
- # The name and version of the exploit.
638
+ # @return [Test::Vulnerable, Test::NotVulnerable, Test::Unknown]
669
639
  #
670
- def to_s
671
- if (self.name && self.version)
672
- "#{self.name} #{self.version}"
673
- elsif self.name
674
- self.name
675
- elsif self.version
676
- self.version
677
- end
678
- end
679
-
640
+ # @example
641
+ # def test
642
+ # case http.get_body('/')
643
+ # when /Powered by Foo 4\.19\./
644
+ # Vulnerable('host is vulnerable')
645
+ # when /Powered by Foo 4\.2[0-9]\./
646
+ # NotVulnerable('host is patched')
647
+ # else
648
+ # Unknown('cannot determine whether the host is vulnerable or not')
649
+ # end
650
+ # end
680
651
  #
681
- # Inspects the contents of the exploit.
652
+ # @abstract
682
653
  #
683
- # @return [String]
684
- # The inspected exploit.
654
+ # @since 1.0.0
685
655
  #
686
- def inspect
687
- str = "#{self.class}: #{self}"
688
- str << " #{self.params.inspect}" unless self.params.empty?
689
-
690
- return "#<#{str}>"
656
+ def test
657
+ Unknown("no vulnerability testing logic defined")
691
658
  end
692
659
 
693
- protected
694
-
695
660
  #
696
- # Extends the exploit with the helper module defined in
697
- # Ronin::Exploits::Helpers that has the similar name.
661
+ # Place holder method that builds the exploit.
698
662
  #
699
- # @param [Symbol, String] name
700
- # The snake-case name of the exploit helper to load and extend the
701
- # exploit with.
663
+ # @abstract
702
664
  #
703
- # @return [true]
704
- # The exploit helper was successfully loaded.
665
+ # @api public
705
666
  #
706
- # @raise [UnknownHelper]
707
- # No valid helper module could be found or loaded with the similar
708
- # name.
667
+ # @since 1.0.0
709
668
  #
710
- # @example
711
- # helper :buffer_overflow
712
- #
713
- def helper(name)
714
- name = name.to_s
715
- module_name = name.to_const_string
716
-
717
- begin
718
- require_within File.join('ronin','exploits','helpers'), name
719
- rescue Gem::LoadError => e
720
- raise(e)
721
- rescue ::LoadError
722
- raise(UnknownHelper,"unknown helper #{name.dump}",caller)
723
- end
724
-
725
- unless Ronin::Exploits::Helpers.const_defined?(module_name)
726
- raise(UnknownHelper,"unknown helper #{name.dump}",caller)
727
- end
728
-
729
- helper_module = Ronin::Exploits::Helpers.const_get(module_name)
730
-
731
- unless helper_module.kind_of?(Module)
732
- raise(UnknownHelper,"unknown helper #{name.dump}",caller)
733
- end
734
-
735
- extend helper_module
736
- return true
669
+ def build
737
670
  end
738
671
 
739
672
  #
740
- # Reviews the text for restricted characters.
673
+ # Place holder method that launches the exploit.
741
674
  #
742
- # @param [String] text
743
- # The text to check for restricted characters within.
744
- #
745
- # @return [Boolean]
746
- # Specifies whether the text contains any restricted characters.
675
+ # @abstract
747
676
  #
748
- def is_restricted?(text)
749
- text.each_byte do |b|
750
- return true if @restricted_chars.include?(b)
751
- end
752
-
753
- return false
754
- end
755
-
677
+ # @api public
756
678
  #
757
- # Default build method.
679
+ # @since 1.0.0
758
680
  #
759
- def build
681
+ def launch
760
682
  end
761
683
 
762
684
  #
763
- # Default exploit verify method.
685
+ # Place holder method that cleans up after the exploit.
764
686
  #
765
- def verify
766
- end
767
-
687
+ # @abstract
688
+ #
689
+ # @api public
768
690
  #
769
- # Default exploit deploy method.
691
+ # @since 1.0.0
770
692
  #
771
- def deploy(&block)
772
- block.call(self) if block
693
+ def cleanup
773
694
  end
774
695
 
775
696
  #
776
- # Relays method calls to the payload, if the payload is a kind of
777
- # Ronin::Payloads::Payload.
697
+ # Indicates that the exploit has failed.
778
698
  #
779
- # @since 0.3.0
699
+ # @param [String] message
700
+ # The failure message.
780
701
  #
781
- def method_missing(name,*arguments,&block)
782
- if @payload.kind_of?(Ronin::Payloads::Payload)
783
- return @payload.send(name,*arguments,&block)
784
- end
785
-
786
- super(name,*arguments,&block)
702
+ # @raise [ExploitFailed]
703
+ #
704
+ def fail(message)
705
+ raise(ExploitFailed,message)
787
706
  end
788
707
 
789
708
  end