librex 0.0.68 → 0.0.70

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 (528) hide show
  1. checksums.yaml +15 -0
  2. data/README.markdown +1 -1
  3. data/Rakefile +18 -16
  4. data/lib/rex.rb +14 -10
  5. data/lib/rex/LICENSE +2 -2
  6. data/lib/rex/arch.rb +76 -76
  7. data/lib/rex/arch/sparc.rb +57 -58
  8. data/lib/rex/arch/x86.rb +506 -496
  9. data/lib/rex/assembly/nasm.rb +83 -84
  10. data/lib/rex/compat.rb +228 -173
  11. data/lib/rex/constants.rb +47 -37
  12. data/lib/rex/elfparsey.rb +0 -3
  13. data/lib/rex/elfparsey/elf.rb +107 -110
  14. data/lib/rex/elfparsey/elfbase.rb +244 -247
  15. data/lib/rex/elfparsey/exceptions.rb +0 -3
  16. data/lib/rex/elfscan.rb +0 -3
  17. data/lib/rex/elfscan/scanner.rb +184 -166
  18. data/lib/rex/elfscan/search.rb +35 -38
  19. data/lib/rex/encoder/alpha2.rb +1 -2
  20. data/lib/rex/encoder/alpha2/alpha_mixed.rb +52 -53
  21. data/lib/rex/encoder/alpha2/alpha_upper.rb +62 -63
  22. data/lib/rex/encoder/alpha2/generic.rb +77 -78
  23. data/lib/rex/encoder/alpha2/unicode_mixed.rb +101 -97
  24. data/lib/rex/encoder/alpha2/unicode_upper.rb +106 -107
  25. data/lib/rex/encoder/bloxor/bloxor.rb +326 -0
  26. data/lib/rex/encoder/ndr.rb +68 -68
  27. data/lib/rex/encoder/nonalpha.rb +50 -51
  28. data/lib/rex/encoder/nonupper.rb +50 -51
  29. data/lib/rex/encoder/xdr.rb +78 -78
  30. data/lib/rex/encoder/xor.rb +52 -53
  31. data/lib/rex/encoder/xor/dword.rb +1 -2
  32. data/lib/rex/encoder/xor/dword_additive.rb +1 -2
  33. data/lib/rex/encoders/xor_dword.rb +17 -18
  34. data/lib/rex/encoders/xor_dword_additive.rb +35 -36
  35. data/lib/rex/encoding/xor.rb +0 -1
  36. data/lib/rex/encoding/xor/byte.rb +3 -4
  37. data/lib/rex/encoding/xor/dword.rb +3 -4
  38. data/lib/rex/encoding/xor/dword_additive.rb +72 -73
  39. data/lib/rex/encoding/xor/exceptions.rb +2 -3
  40. data/lib/rex/encoding/xor/generic.rb +129 -130
  41. data/lib/rex/encoding/xor/qword.rb +3 -4
  42. data/lib/rex/encoding/xor/word.rb +3 -4
  43. data/lib/rex/exceptions.rb +100 -101
  44. data/lib/rex/exploitation/cmdstager.rb +3 -3
  45. data/lib/rex/exploitation/cmdstager/base.rb +170 -156
  46. data/lib/rex/exploitation/cmdstager/bourne.rb +105 -0
  47. data/lib/rex/exploitation/cmdstager/debug_asm.rb +110 -113
  48. data/lib/rex/exploitation/cmdstager/debug_write.rb +106 -109
  49. data/lib/rex/exploitation/cmdstager/echo.rb +164 -0
  50. data/lib/rex/exploitation/cmdstager/printf.rb +122 -0
  51. data/lib/rex/exploitation/cmdstager/tftp.rb +34 -27
  52. data/lib/rex/exploitation/cmdstager/vbs.rb +95 -98
  53. data/lib/rex/exploitation/egghunter.rb +359 -346
  54. data/lib/rex/exploitation/encryptjs.rb +60 -60
  55. data/lib/rex/exploitation/heaplib.rb +76 -76
  56. data/lib/rex/exploitation/js.rb +6 -0
  57. data/lib/rex/exploitation/js/detect.rb +69 -0
  58. data/lib/rex/exploitation/js/memory.rb +81 -0
  59. data/lib/rex/exploitation/js/network.rb +84 -0
  60. data/lib/rex/exploitation/js/utils.rb +33 -0
  61. data/lib/rex/exploitation/jsobfu.rb +448 -424
  62. data/lib/rex/exploitation/obfuscatejs.rb +301 -301
  63. data/lib/rex/exploitation/omelet.rb +257 -257
  64. data/lib/rex/exploitation/opcodedb.rb +699 -699
  65. data/lib/rex/exploitation/ropdb.rb +189 -0
  66. data/lib/rex/exploitation/seh.rb +68 -68
  67. data/lib/rex/file.rb +96 -49
  68. data/lib/rex/image_source.rb +0 -3
  69. data/lib/rex/image_source/disk.rb +45 -48
  70. data/lib/rex/image_source/image_source.rb +33 -36
  71. data/lib/rex/image_source/memory.rb +17 -20
  72. data/lib/rex/io/bidirectional_pipe.rb +118 -115
  73. data/lib/rex/io/datagram_abstraction.rb +13 -14
  74. data/lib/rex/io/ring_buffer.rb +273 -273
  75. data/lib/rex/io/stream.rb +284 -284
  76. data/lib/rex/io/stream_abstraction.rb +183 -181
  77. data/lib/rex/io/stream_server.rb +193 -193
  78. data/lib/rex/job_container.rb +167 -167
  79. data/lib/rex/logging.rb +0 -1
  80. data/lib/rex/logging/log_dispatcher.rb +113 -113
  81. data/lib/rex/logging/log_sink.rb +17 -17
  82. data/lib/rex/logging/sinks/flatfile.rb +36 -36
  83. data/lib/rex/logging/sinks/stderr.rb +27 -27
  84. data/lib/rex/mac_oui.rb +16572 -16571
  85. data/lib/rex/machparsey.rb +0 -1
  86. data/lib/rex/machparsey/exceptions.rb +0 -1
  87. data/lib/rex/machparsey/mach.rb +160 -161
  88. data/lib/rex/machparsey/machbase.rb +367 -368
  89. data/lib/rex/machscan.rb +0 -1
  90. data/lib/rex/machscan/scanner.rb +175 -176
  91. data/lib/rex/mime/encoding.rb +17 -0
  92. data/lib/rex/mime/header.rb +58 -58
  93. data/lib/rex/mime/message.rb +140 -137
  94. data/lib/rex/mime/part.rb +41 -12
  95. data/lib/rex/nop/opty2.rb +90 -90
  96. data/lib/rex/nop/opty2_tables.rb +273 -273
  97. data/lib/rex/ole.rb +0 -4
  98. data/lib/rex/ole/clsid.rb +26 -30
  99. data/lib/rex/ole/difat.rb +121 -125
  100. data/lib/rex/ole/directory.rb +205 -209
  101. data/lib/rex/ole/direntry.rb +217 -221
  102. data/lib/rex/ole/fat.rb +79 -83
  103. data/lib/rex/ole/header.rb +178 -182
  104. data/lib/rex/ole/minifat.rb +49 -53
  105. data/lib/rex/ole/propset.rb +113 -117
  106. data/lib/rex/ole/samples/create_ole.rb +8 -9
  107. data/lib/rex/ole/samples/dir.rb +10 -11
  108. data/lib/rex/ole/samples/dump_stream.rb +14 -15
  109. data/lib/rex/ole/samples/ole_info.rb +5 -6
  110. data/lib/rex/ole/storage.rb +372 -376
  111. data/lib/rex/ole/stream.rb +33 -37
  112. data/lib/rex/ole/substorage.rb +20 -24
  113. data/lib/rex/ole/util.rb +137 -141
  114. data/lib/rex/parser/acunetix_nokogiri.rb +398 -398
  115. data/lib/rex/parser/apple_backup_manifestdb.rb +116 -116
  116. data/lib/rex/parser/appscan_nokogiri.rb +359 -359
  117. data/lib/rex/parser/arguments.rb +88 -88
  118. data/lib/rex/parser/burp_session_nokogiri.rb +258 -258
  119. data/lib/rex/parser/ci_nokogiri.rb +184 -184
  120. data/lib/rex/parser/foundstone_nokogiri.rb +334 -333
  121. data/lib/rex/parser/fusionvm_nokogiri.rb +94 -94
  122. data/lib/rex/parser/ini.rb +167 -167
  123. data/lib/rex/parser/ip360_aspl_xml.rb +84 -84
  124. data/lib/rex/parser/ip360_xml.rb +77 -77
  125. data/lib/rex/parser/mbsa_nokogiri.rb +224 -224
  126. data/lib/rex/parser/nessus_xml.rb +100 -100
  127. data/lib/rex/parser/netsparker_xml.rb +89 -75
  128. data/lib/rex/parser/nexpose_raw_nokogiri.rb +677 -677
  129. data/lib/rex/parser/nexpose_simple_nokogiri.rb +322 -322
  130. data/lib/rex/parser/nexpose_xml.rb +105 -105
  131. data/lib/rex/parser/nmap_nokogiri.rb +386 -386
  132. data/lib/rex/parser/nmap_xml.rb +116 -116
  133. data/lib/rex/parser/nokogiri_doc_mixin.rb +223 -221
  134. data/lib/rex/parser/openvas_nokogiri.rb +162 -162
  135. data/lib/rex/parser/outpost24_nokogiri.rb +239 -0
  136. data/lib/rex/parser/retina_xml.rb +90 -90
  137. data/lib/rex/parser/unattend.rb +171 -0
  138. data/lib/rex/parser/wapiti_nokogiri.rb +89 -89
  139. data/lib/rex/payloads/win32/common.rb +14 -14
  140. data/lib/rex/payloads/win32/kernel.rb +36 -36
  141. data/lib/rex/payloads/win32/kernel/common.rb +32 -32
  142. data/lib/rex/payloads/win32/kernel/recovery.rb +27 -27
  143. data/lib/rex/payloads/win32/kernel/stager.rb +170 -170
  144. data/lib/rex/peparsey.rb +0 -3
  145. data/lib/rex/peparsey/exceptions.rb +0 -3
  146. data/lib/rex/peparsey/pe.rb +196 -199
  147. data/lib/rex/peparsey/pe_memdump.rb +35 -38
  148. data/lib/rex/peparsey/pebase.rb +1633 -1652
  149. data/lib/rex/peparsey/section.rb +115 -124
  150. data/lib/rex/pescan.rb +0 -3
  151. data/lib/rex/pescan/analyze.rb +351 -351
  152. data/lib/rex/pescan/scanner.rb +182 -182
  153. data/lib/rex/pescan/search.rb +59 -59
  154. data/lib/rex/platforms/windows.rb +37 -37
  155. data/lib/rex/poly.rb +111 -110
  156. data/lib/rex/poly/block.rb +419 -417
  157. data/lib/rex/poly/machine.rb +12 -0
  158. data/lib/rex/poly/machine/machine.rb +829 -0
  159. data/lib/rex/poly/machine/x86.rb +508 -0
  160. data/lib/rex/poly/register.rb +70 -70
  161. data/lib/rex/poly/register/x86.rb +22 -22
  162. data/lib/rex/post.rb +0 -1
  163. data/lib/rex/post/dir.rb +35 -36
  164. data/lib/rex/post/file.rb +140 -141
  165. data/lib/rex/post/file_stat.rb +198 -199
  166. data/lib/rex/post/io.rb +167 -168
  167. data/lib/rex/post/meterpreter.rb +1 -1
  168. data/lib/rex/post/meterpreter/channel.rb +389 -390
  169. data/lib/rex/post/meterpreter/channel_container.rb +33 -34
  170. data/lib/rex/post/meterpreter/channels/pool.rb +129 -130
  171. data/lib/rex/post/meterpreter/channels/pools/file.rb +35 -36
  172. data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +72 -73
  173. data/lib/rex/post/meterpreter/channels/stream.rb +62 -63
  174. data/lib/rex/post/meterpreter/client.rb +442 -436
  175. data/lib/rex/post/meterpreter/client_core.rb +326 -310
  176. data/lib/rex/post/meterpreter/dependencies.rb +0 -1
  177. data/lib/rex/post/meterpreter/extension.rb +12 -13
  178. data/lib/rex/post/meterpreter/extensions/espia/espia.rb +35 -36
  179. data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +71 -0
  180. data/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb +169 -0
  181. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +45 -0
  182. data/lib/rex/post/meterpreter/extensions/extapi/service/service.rb +104 -0
  183. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +77 -0
  184. data/lib/rex/post/meterpreter/extensions/extapi/window/window.rb +56 -0
  185. data/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb +75 -0
  186. data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +70 -71
  187. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +361 -0
  188. data/lib/rex/post/meterpreter/extensions/kiwi/tlv.rb +76 -0
  189. data/lib/rex/post/meterpreter/extensions/lanattacks/dhcp/dhcp.rb +78 -0
  190. data/lib/rex/post/meterpreter/extensions/lanattacks/lanattacks.rb +22 -78
  191. data/lib/rex/post/meterpreter/extensions/lanattacks/tftp/tftp.rb +49 -0
  192. data/lib/rex/post/meterpreter/extensions/lanattacks/tlv.rb +4 -4
  193. data/lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb +128 -0
  194. data/lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb +16 -0
  195. data/lib/rex/post/meterpreter/extensions/networkpug/networkpug.rb +38 -39
  196. data/lib/rex/post/meterpreter/extensions/networkpug/tlv.rb +1 -1
  197. data/lib/rex/post/meterpreter/extensions/priv/fs.rb +95 -96
  198. data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +39 -40
  199. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +80 -85
  200. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +94 -95
  201. data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +207 -147
  202. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +258 -259
  203. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +366 -301
  204. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +72 -73
  205. data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +24 -25
  206. data/lib/rex/post/meterpreter/extensions/stdapi/net/arp.rb +59 -0
  207. data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +227 -149
  208. data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +107 -108
  209. data/lib/rex/post/meterpreter/extensions/stdapi/net/netstat.rb +97 -0
  210. data/lib/rex/post/meterpreter/extensions/stdapi/net/resolve.rb +106 -0
  211. data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +41 -42
  212. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +102 -101
  213. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +151 -152
  214. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +142 -142
  215. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +185 -185
  216. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +38118 -38117
  217. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +7 -7
  218. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +2086 -2084
  219. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_crypt32.rb +15 -15
  220. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_iphlpapi.rb +80 -80
  221. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3835 -3833
  222. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +84 -28
  223. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ntdll.rb +151 -137
  224. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_shell32.rb +15 -6
  225. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_user32.rb +3155 -3155
  226. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_version.rb +41 -0
  227. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wlanapi.rb +70 -70
  228. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb +128 -0
  229. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ws2_32.rb +596 -596
  230. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +310 -301
  231. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +71 -61
  232. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +100 -100
  233. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb +14 -14
  234. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/mock_magic.rb +488 -488
  235. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +273 -264
  236. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb +5 -5
  237. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +240 -238
  238. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb +17 -15
  239. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb +61 -61
  240. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +654 -635
  241. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +49 -49
  242. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +103 -102
  243. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +98 -68
  244. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +165 -166
  245. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +16 -17
  246. data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +34 -36
  247. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +363 -364
  248. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +102 -103
  249. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +28 -29
  250. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +303 -304
  251. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +113 -114
  252. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +260 -261
  253. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +165 -166
  254. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +69 -70
  255. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb +160 -161
  256. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +143 -144
  257. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +29 -12
  258. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +230 -231
  259. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +181 -44
  260. data/lib/rex/post/meterpreter/inbound_packet_handler.rb +12 -13
  261. data/lib/rex/post/meterpreter/object_aliases.rb +56 -57
  262. data/lib/rex/post/meterpreter/packet.rb +591 -592
  263. data/lib/rex/post/meterpreter/packet_dispatcher.rb +506 -496
  264. data/lib/rex/post/meterpreter/packet_parser.rb +72 -73
  265. data/lib/rex/post/meterpreter/packet_response_waiter.rb +56 -57
  266. data/lib/rex/post/meterpreter/ui/console.rb +112 -112
  267. data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +53 -53
  268. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +911 -854
  269. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +86 -86
  270. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi.rb +65 -0
  271. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +198 -0
  272. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +444 -0
  273. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb +199 -0
  274. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb +118 -0
  275. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb +108 -0
  276. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +220 -220
  277. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +509 -0
  278. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks.rb +60 -0
  279. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +254 -0
  280. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/tftp.rb +159 -0
  281. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +182 -0
  282. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/networkpug.rb +173 -173
  283. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +40 -40
  284. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +75 -77
  285. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +30 -30
  286. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +105 -105
  287. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +182 -182
  288. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +37 -37
  289. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +504 -482
  290. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +401 -330
  291. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +883 -581
  292. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +296 -299
  293. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +320 -153
  294. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +78 -78
  295. data/lib/rex/post/permission.rb +0 -1
  296. data/lib/rex/post/process.rb +39 -40
  297. data/lib/rex/post/thread.rb +41 -42
  298. data/lib/rex/post/ui.rb +35 -36
  299. data/lib/rex/proto/addp.rb +218 -0
  300. data/lib/rex/proto/dcerpc/client.rb +344 -344
  301. data/lib/rex/proto/dcerpc/exceptions.rb +128 -128
  302. data/lib/rex/proto/dcerpc/handle.rb +32 -32
  303. data/lib/rex/proto/dcerpc/ndr.rb +56 -56
  304. data/lib/rex/proto/dcerpc/packet.rb +249 -245
  305. data/lib/rex/proto/dcerpc/response.rb +170 -170
  306. data/lib/rex/proto/dcerpc/uuid.rb +65 -65
  307. data/lib/rex/proto/dcerpc/wdscp.rb +3 -0
  308. data/lib/rex/proto/dcerpc/wdscp/constants.rb +89 -0
  309. data/lib/rex/proto/dcerpc/wdscp/packet.rb +94 -0
  310. data/lib/rex/proto/dhcp.rb +0 -1
  311. data/lib/rex/proto/dhcp/constants.rb +0 -1
  312. data/lib/rex/proto/dhcp/server.rb +303 -304
  313. data/lib/rex/proto/drda/constants.rb +1 -1
  314. data/lib/rex/proto/drda/packet.rb +186 -186
  315. data/lib/rex/proto/drda/utils.rb +104 -104
  316. data/lib/rex/proto/http.rb +1 -0
  317. data/lib/rex/proto/http/client.rb +692 -820
  318. data/lib/rex/proto/http/client_request.rb +472 -0
  319. data/lib/rex/proto/http/handler.rb +25 -25
  320. data/lib/rex/proto/http/handler/erb.rb +104 -104
  321. data/lib/rex/proto/http/handler/proc.rb +37 -37
  322. data/lib/rex/proto/http/header.rb +149 -149
  323. data/lib/rex/proto/http/packet.rb +388 -382
  324. data/lib/rex/proto/http/request.rb +332 -335
  325. data/lib/rex/proto/http/response.rb +132 -72
  326. data/lib/rex/proto/http/server.rb +348 -338
  327. data/lib/rex/proto/iax2/call.rb +310 -310
  328. data/lib/rex/proto/iax2/client.rb +197 -197
  329. data/lib/rex/proto/iax2/codecs/alaw.rb +4 -4
  330. data/lib/rex/proto/iax2/codecs/mulaw.rb +4 -4
  331. data/lib/rex/proto/ipmi.rb +57 -0
  332. data/lib/rex/proto/ipmi/channel_auth_reply.rb +88 -0
  333. data/lib/rex/proto/ipmi/open_session_reply.rb +35 -0
  334. data/lib/rex/proto/ipmi/rakp2.rb +35 -0
  335. data/lib/rex/proto/ipmi/utils.rb +125 -0
  336. data/lib/rex/proto/natpmp.rb +1 -5
  337. data/lib/rex/proto/natpmp/constants.rb +4 -4
  338. data/lib/rex/proto/natpmp/packet.rb +25 -25
  339. data/lib/rex/proto/ntlm/base.rb +271 -271
  340. data/lib/rex/proto/ntlm/constants.rb +61 -61
  341. data/lib/rex/proto/ntlm/crypt.rb +348 -352
  342. data/lib/rex/proto/ntlm/exceptions.rb +3 -3
  343. data/lib/rex/proto/ntlm/message.rb +468 -471
  344. data/lib/rex/proto/ntlm/utils.rb +746 -746
  345. data/lib/rex/proto/pjl.rb +30 -0
  346. data/lib/rex/proto/pjl/client.rb +162 -0
  347. data/lib/rex/proto/proxy/socks4a.rb +440 -440
  348. data/lib/rex/proto/rfb.rb +1 -8
  349. data/lib/rex/proto/rfb/cipher.rb +46 -49
  350. data/lib/rex/proto/rfb/client.rb +179 -182
  351. data/lib/rex/proto/rfb/constants.rb +18 -21
  352. data/lib/rex/proto/smb/client.rb +1954 -1843
  353. data/lib/rex/proto/smb/constants.rb +533 -516
  354. data/lib/rex/proto/smb/crypt.rb +21 -21
  355. data/lib/rex/proto/smb/evasions.rb +43 -43
  356. data/lib/rex/proto/smb/exceptions.rb +791 -791
  357. data/lib/rex/proto/smb/simpleclient.rb +142 -286
  358. data/lib/rex/proto/smb/simpleclient/open_file.rb +106 -0
  359. data/lib/rex/proto/smb/simpleclient/open_pipe.rb +57 -0
  360. data/lib/rex/proto/smb/utils.rb +81 -81
  361. data/lib/rex/proto/sunrpc/client.rb +158 -158
  362. data/lib/rex/proto/tftp.rb +0 -1
  363. data/lib/rex/proto/tftp/client.rb +289 -289
  364. data/lib/rex/proto/tftp/constants.rb +9 -10
  365. data/lib/rex/proto/tftp/server.rb +466 -467
  366. data/lib/rex/random_identifier_generator.rb +176 -0
  367. data/lib/rex/registry.rb +1 -1
  368. data/lib/rex/registry/hive.rb +88 -88
  369. data/lib/rex/registry/lfkey.rb +25 -25
  370. data/lib/rex/registry/nodekey.rb +30 -30
  371. data/lib/rex/registry/regf.rb +10 -10
  372. data/lib/rex/registry/valuekey.rb +43 -43
  373. data/lib/rex/registry/valuelist.rb +13 -13
  374. data/lib/rex/ropbuilder/rop.rb +254 -253
  375. data/lib/rex/script.rb +21 -22
  376. data/lib/rex/script/base.rb +51 -50
  377. data/lib/rex/script/meterpreter.rb +2 -2
  378. data/lib/rex/service.rb +24 -24
  379. data/lib/rex/service_manager.rb +132 -132
  380. data/lib/rex/services/local_relay.rb +398 -398
  381. data/lib/rex/socket.rb +758 -763
  382. data/lib/rex/socket/comm.rb +95 -95
  383. data/lib/rex/socket/comm/local.rb +507 -440
  384. data/lib/rex/socket/ip.rb +118 -118
  385. data/lib/rex/socket/parameters.rb +351 -350
  386. data/lib/rex/socket/range_walker.rb +445 -368
  387. data/lib/rex/socket/ssl_tcp.rb +323 -317
  388. data/lib/rex/socket/ssl_tcp_server.rb +173 -158
  389. data/lib/rex/socket/subnet_walker.rb +48 -48
  390. data/lib/rex/socket/switch_board.rb +259 -259
  391. data/lib/rex/socket/tcp.rb +58 -56
  392. data/lib/rex/socket/tcp_server.rb +42 -42
  393. data/lib/rex/socket/udp.rb +152 -152
  394. data/lib/rex/sslscan/result.rb +200 -0
  395. data/lib/rex/sslscan/scanner.rb +205 -0
  396. data/lib/rex/struct2.rb +0 -1
  397. data/lib/rex/struct2/c_struct.rb +162 -163
  398. data/lib/rex/struct2/c_struct_template.rb +21 -22
  399. data/lib/rex/struct2/constant.rb +6 -7
  400. data/lib/rex/struct2/element.rb +30 -31
  401. data/lib/rex/struct2/generic.rb +60 -61
  402. data/lib/rex/struct2/restraint.rb +40 -41
  403. data/lib/rex/struct2/s_string.rb +60 -61
  404. data/lib/rex/struct2/s_struct.rb +97 -98
  405. data/lib/rex/sync.rb +0 -1
  406. data/lib/rex/sync/event.rb +62 -72
  407. data/lib/rex/sync/read_write_lock.rb +149 -149
  408. data/lib/rex/sync/ref.rb +42 -42
  409. data/lib/rex/sync/thread_safe.rb +59 -59
  410. data/lib/rex/text.rb +1803 -1315
  411. data/lib/rex/thread_factory.rb +25 -25
  412. data/lib/rex/time.rb +44 -44
  413. data/lib/rex/transformer.rb +91 -91
  414. data/lib/rex/ui/interactive.rb +265 -265
  415. data/lib/rex/ui/output.rb +66 -60
  416. data/lib/rex/ui/progress_tracker.rb +79 -79
  417. data/lib/rex/ui/subscriber.rb +144 -134
  418. data/lib/rex/ui/text/color.rb +76 -76
  419. data/lib/rex/ui/text/dispatcher_shell.rb +512 -505
  420. data/lib/rex/ui/text/input.rb +96 -96
  421. data/lib/rex/ui/text/input/buffer.rb +58 -58
  422. data/lib/rex/ui/text/input/readline.rb +114 -114
  423. data/lib/rex/ui/text/input/socket.rb +77 -77
  424. data/lib/rex/ui/text/input/stdio.rb +24 -24
  425. data/lib/rex/ui/text/irb_shell.rb +45 -41
  426. data/lib/rex/ui/text/output.rb +64 -60
  427. data/lib/rex/ui/text/output/buffer.rb +42 -42
  428. data/lib/rex/ui/text/output/buffer/stdout.rb +25 -0
  429. data/lib/rex/ui/text/output/file.rb +24 -24
  430. data/lib/rex/ui/text/output/socket.rb +24 -24
  431. data/lib/rex/ui/text/output/stdio.rb +29 -29
  432. data/lib/rex/ui/text/output/tee.rb +36 -36
  433. data/lib/rex/ui/text/progress_tracker.rb +37 -37
  434. data/lib/rex/ui/text/shell.rb +371 -361
  435. data/lib/rex/ui/text/table.rb +320 -284
  436. data/lib/rex/zip.rb +0 -1
  437. data/lib/rex/zip/archive.rb +115 -94
  438. data/lib/rex/zip/blocks.rb +101 -100
  439. data/lib/rex/zip/entry.rb +108 -99
  440. data/lib/rex/zip/jar.rb +261 -206
  441. data/lib/rex/zip/samples/comment.rb +1 -2
  442. data/lib/rex/zip/samples/mkwar.rb +12 -13
  443. data/lib/rex/zip/samples/mkzip.rb +1 -2
  444. data/lib/rex/zip/samples/recursive.rb +29 -30
  445. metadata +424 -446
  446. data/lib/rex/arch/sparc.rb.ut.rb +0 -19
  447. data/lib/rex/arch/x86.rb.ut.rb +0 -94
  448. data/lib/rex/assembly/nasm.rb.ut.rb +0 -23
  449. data/lib/rex/encoder/ndr.rb.ut.rb +0 -45
  450. data/lib/rex/encoder/xdr.rb.ut.rb +0 -30
  451. data/lib/rex/encoders/xor_dword_additive.rb.ut.rb +0 -13
  452. data/lib/rex/encoding/xor.rb.ts.rb +0 -15
  453. data/lib/rex/encoding/xor/byte.rb.ut.rb +0 -22
  454. data/lib/rex/encoding/xor/dword.rb.ut.rb +0 -16
  455. data/lib/rex/encoding/xor/dword_additive.rb.ut.rb +0 -16
  456. data/lib/rex/encoding/xor/generic.rb.ut.rb +0 -121
  457. data/lib/rex/encoding/xor/word.rb.ut.rb +0 -14
  458. data/lib/rex/exceptions.rb.ut.rb +0 -45
  459. data/lib/rex/exploitation/egghunter.rb.ut.rb +0 -28
  460. data/lib/rex/exploitation/javascriptosdetect.js +0 -1014
  461. data/lib/rex/exploitation/javascriptosdetect.rb +0 -43
  462. data/lib/rex/exploitation/omelet.rb.ut.rb +0 -27
  463. data/lib/rex/exploitation/opcodedb.rb.ut.rb +0 -280
  464. data/lib/rex/exploitation/seh.rb.ut.rb +0 -20
  465. data/lib/rex/file.rb.ut.rb +0 -17
  466. data/lib/rex/io/ring_buffer.rb.ut.rb +0 -135
  467. data/lib/rex/nop/opty2.rb.ut.rb +0 -24
  468. data/lib/rex/parser/arguments.rb.ut.rb +0 -68
  469. data/lib/rex/parser/ini.rb.ut.rb +0 -30
  470. data/lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb +0 -18
  471. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb.ut.rb +0 -39
  472. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb.ut.rb +0 -37
  473. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb.ut.rb +0 -52
  474. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb +0 -43
  475. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb.ut.rb +0 -128
  476. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb.ut.rb +0 -64
  477. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb.ut.rb +0 -29
  478. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb.ut.rb +0 -155
  479. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb.ut.rb +0 -128
  480. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb +0 -124
  481. data/lib/rex/proto.rb.ts.rb +0 -9
  482. data/lib/rex/proto/dcerpc.rb.ts.rb +0 -10
  483. data/lib/rex/proto/dcerpc/client.rb.ut.rb +0 -492
  484. data/lib/rex/proto/dcerpc/handle.rb.ut.rb +0 -86
  485. data/lib/rex/proto/dcerpc/ndr.rb.ut.rb +0 -42
  486. data/lib/rex/proto/dcerpc/packet.rb.ut.rb +0 -57
  487. data/lib/rex/proto/dcerpc/response.rb.ut.rb +0 -16
  488. data/lib/rex/proto/dcerpc/uuid.rb.ut.rb +0 -47
  489. data/lib/rex/proto/drda.rb.ts.rb +0 -18
  490. data/lib/rex/proto/drda/constants.rb.ut.rb +0 -24
  491. data/lib/rex/proto/drda/packet.rb.ut.rb +0 -110
  492. data/lib/rex/proto/drda/utils.rb.ut.rb +0 -85
  493. data/lib/rex/proto/http.rb.ts.rb +0 -13
  494. data/lib/rex/proto/http/client.rb.ut.rb +0 -96
  495. data/lib/rex/proto/http/handler/erb.rb.ut.rb +0 -22
  496. data/lib/rex/proto/http/handler/erb.rb.ut.rb.rhtml +0 -1
  497. data/lib/rex/proto/http/handler/proc.rb.ut.rb +0 -25
  498. data/lib/rex/proto/http/header.rb.ut.rb +0 -47
  499. data/lib/rex/proto/http/packet.rb.ut.rb +0 -166
  500. data/lib/rex/proto/http/request.rb.ut.rb +0 -215
  501. data/lib/rex/proto/http/response.rb.ut.rb +0 -150
  502. data/lib/rex/proto/http/server.rb.ut.rb +0 -80
  503. data/lib/rex/proto/ntlm.rb.ut.rb +0 -181
  504. data/lib/rex/proto/rfb.rb.ut.rb +0 -40
  505. data/lib/rex/proto/smb.rb.ts.rb +0 -9
  506. data/lib/rex/proto/smb/client.rb.ut.rb +0 -224
  507. data/lib/rex/proto/smb/constants.rb.ut.rb +0 -19
  508. data/lib/rex/proto/smb/simpleclient.rb.ut.rb +0 -129
  509. data/lib/rex/proto/smb/utils.rb.ut.rb +0 -21
  510. data/lib/rex/proto/tftp/server.rb.ut.rb +0 -29
  511. data/lib/rex/service_manager.rb.ut.rb +0 -33
  512. data/lib/rex/socket.rb.ut.rb +0 -108
  513. data/lib/rex/socket/comm/local.rb.ut.rb +0 -76
  514. data/lib/rex/socket/parameters.rb.ut.rb +0 -52
  515. data/lib/rex/socket/range_walker.rb.ut.rb +0 -56
  516. data/lib/rex/socket/ssl_tcp.rb.ut.rb +0 -40
  517. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +0 -62
  518. data/lib/rex/socket/subnet_walker.rb.ut.rb +0 -29
  519. data/lib/rex/socket/switch_board.rb.ut.rb +0 -53
  520. data/lib/rex/socket/tcp.rb.ut.rb +0 -65
  521. data/lib/rex/socket/tcp_server.rb.ut.rb +0 -45
  522. data/lib/rex/socket/udp.rb.ut.rb +0 -45
  523. data/lib/rex/test.rb +0 -36
  524. data/lib/rex/text.rb.ut.rb +0 -193
  525. data/lib/rex/transformer.rb.ut.rb +0 -39
  526. data/lib/rex/ui/text/color.rb.ut.rb +0 -19
  527. data/lib/rex/ui/text/progress_tracker.rb.ut.rb +0 -35
  528. data/lib/rex/ui/text/table.rb.ut.rb +0 -56
@@ -4,3 +4,4 @@ require 'rex/proto/http/request'
4
4
  require 'rex/proto/http/response'
5
5
  require 'rex/proto/http/client'
6
6
  require 'rex/proto/http/server'
7
+ require 'rex/proto/http/client_request'
@@ -2,6 +2,13 @@
2
2
  require 'rex/socket'
3
3
  require 'rex/proto/http'
4
4
  require 'rex/text'
5
+ require 'digest'
6
+ require 'rex/proto/ntlm/crypt'
7
+ require 'rex/proto/ntlm/constants'
8
+ require 'rex/proto/ntlm/utils'
9
+ require 'rex/proto/ntlm/exceptions'
10
+
11
+ require 'rex/proto/http/client_request'
5
12
 
6
13
  module Rex
7
14
  module Proto
@@ -16,830 +23,695 @@ module Http
16
23
  ###
17
24
  class Client
18
25
 
19
- DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
20
-
21
- #
22
- # Creates a new client instance
23
- #
24
- def initialize(host, port = 80, context = {}, ssl = nil, ssl_version = nil, proxies = nil)
25
- self.hostname = host
26
- self.port = port.to_i
27
- self.context = context
28
- self.ssl = ssl
29
- self.ssl_version = ssl_version
30
- self.proxies = proxies
31
- self.config = {
32
- 'read_max_data' => (1024*1024*1),
33
- 'vhost' => self.hostname,
34
- 'version' => '1.1',
35
- 'agent' => DefaultUserAgent,
36
- #
37
- # Evasion options
38
- #
39
- 'uri_encode_mode' => 'hex-normal', # hex-all, hex-random, u-normal, u-random, u-all
40
- 'uri_encode_count' => 1, # integer
41
- 'uri_full_url' => false, # bool
42
- 'pad_method_uri_count' => 1, # integer
43
- 'pad_uri_version_count' => 1, # integer
44
- 'pad_method_uri_type' => 'space', # space, tab, apache
45
- 'pad_uri_version_type' => 'space', # space, tab, apache
46
- 'method_random_valid' => false, # bool
47
- 'method_random_invalid' => false, # bool
48
- 'method_random_case' => false, # bool
49
- 'version_random_valid' => false, # bool
50
- 'version_random_invalid' => false, # bool
51
- 'version_random_case' => false, # bool
52
- 'uri_dir_self_reference' => false, # bool
53
- 'uri_dir_fake_relative' => false, # bool
54
- 'uri_use_backslashes' => false, # bool
55
- 'pad_fake_headers' => false, # bool
56
- 'pad_fake_headers_count' => 16, # integer
57
- 'pad_get_params' => false, # bool
58
- 'pad_get_params_count' => 8, # integer
59
- 'pad_post_params' => false, # bool
60
- 'pad_post_params_count' => 8, # integer
61
- 'uri_fake_end' => false, # bool
62
- 'uri_fake_params_start' => false, # bool
63
- 'header_folding' => false, # bool
64
- 'chunked_size' => 0 # integer
65
- }
66
-
67
- # This is not used right now...
68
- self.config_types = {
69
- 'uri_encode_mode' => ['hex-normal', 'hex-all', 'hex-random', 'u-normal', 'u-random', 'u-all'],
70
- 'uri_encode_count' => 'integer',
71
- 'uri_full_url' => 'bool',
72
- 'pad_method_uri_count' => 'integer',
73
- 'pad_uri_version_count' => 'integer',
74
- 'pad_method_uri_type' => ['space', 'tab', 'apache'],
75
- 'pad_uri_version_type' => ['space', 'tab', 'apache'],
76
- 'method_random_valid' => 'bool',
77
- 'method_random_invalid' => 'bool',
78
- 'method_random_case' => 'bool',
79
- 'version_random_valid' => 'bool',
80
- 'version_random_invalid' => 'bool',
81
- 'version_random_case' => 'bool',
82
- 'uri_dir_self_reference' => 'bool',
83
- 'uri_dir_fake_relative' => 'bool',
84
- 'uri_use_backslashes' => 'bool',
85
- 'pad_fake_headers' => 'bool',
86
- 'pad_fake_headers_count' => 'integer',
87
- 'pad_get_params' => 'bool',
88
- 'pad_get_params_count' => 'integer',
89
- 'pad_post_params' => 'bool',
90
- 'pad_post_params_count' => 'integer',
91
- 'uri_fake_end' => 'bool',
92
- 'uri_fake_params_start' => 'bool',
93
- 'header_folding' => 'bool',
94
- 'chunked_size' => 'integer'
95
- }
96
- end
97
-
98
- #
99
- # Set configuration options
100
- #
101
- def set_config(opts = {})
102
- opts.each_pair do |var,val|
103
- # Default type is string
104
- typ = self.config_types[var] || 'string'
105
-
106
- # These are enum types
107
- if(typ.class.to_s == 'Array')
108
- if not typ.include?(val)
109
- raise RuntimeError, "The specified value for #{var} is not one of the valid choices"
110
- end
111
- end
112
-
113
- # The caller should have converted these to proper ruby types, but
114
- # take care of the case where they didn't before setting the
115
- # config.
116
-
117
- if(typ == 'bool')
118
- val = (val =~ /^(t|y|1)$/i ? true : false || val === true)
119
- end
120
-
121
- if(typ == 'integer')
122
- val = val.to_i
123
- end
124
-
125
- self.config[var]=val
126
- end
127
-
128
- end
129
-
130
- #
131
- # Create an arbitrary HTTP request
132
- #
133
- def request_raw(opts={})
134
- c_enc = opts['encode'] || false
135
- c_uri = opts['uri'] || '/'
136
- c_body = opts['data'] || ''
137
- c_meth = opts['method'] || 'GET'
138
- c_prot = opts['proto'] || 'HTTP'
139
- c_vers = opts['version'] || config['version'] || '1.1'
140
- c_qs = opts['query']
141
- c_ag = opts['agent'] || config['agent']
142
- c_cook = opts['cookie'] || config['cookie']
143
- c_host = opts['vhost'] || config['vhost'] || self.hostname
144
- c_head = opts['headers'] || config['headers'] || {}
145
- c_rawh = opts['raw_headers']|| config['raw_headers'] || ''
146
- c_conn = opts['connection']
147
- c_auth = opts['basic_auth'] || config['basic_auth'] || ''
148
-
149
- # An agent parameter was specified, but so was a header, prefer the header
150
- if c_ag and c_head.keys.map{|x| x.downcase }.include?('user-agent')
151
- c_ag = nil
152
- end
153
-
154
- uri = set_uri(c_uri)
155
-
156
- req = ''
157
- req << set_method(c_meth)
158
- req << set_method_uri_spacer()
159
- req << set_uri_prepend()
160
- req << (c_enc ? set_encode_uri(uri) : uri)
161
-
162
- if (c_qs)
163
- req << '?'
164
- req << (c_enc ? set_encode_qs(c_qs) : c_qs)
165
- end
166
-
167
- req << set_uri_append()
168
- req << set_uri_version_spacer()
169
- req << set_version(c_prot, c_vers)
170
- req << set_host_header(c_host)
171
- req << set_agent_header(c_ag)
172
-
173
-
174
- if (c_auth.length > 0)
175
- req << set_basic_auth_header(c_auth)
176
- end
177
-
178
- req << set_cookie_header(c_cook)
179
- req << set_connection_header(c_conn)
180
- req << set_extra_headers(c_head)
181
- req << set_raw_headers(c_rawh)
182
- req << set_body(c_body)
183
-
184
- req
185
- end
186
-
187
-
188
- #
189
- # Create a CGI compatible request
190
- #
191
- # Options:
192
- # - agent: User-Agent header value
193
- # - basic_auth: Basic-Auth header value
194
- # - connection: Connection header value
195
- # - cookie: Cookie header value
196
- # - ctype: Content-Type header value, default: +application/x-www-form-urlencoded+
197
- # - data: HTTP data (only useful with some methods, see rfc2616)
198
- # - encode: URI encode the supplied URI
199
- # - headers: HTTP headers as a hash, e.g. <code>{ "X-MyHeader" => "value" }</code>
200
- # - method: HTTP method to use in the request, not limited to standard methods defined by rfc2616, default: GET
201
- # - proto: protocol, default: HTTP
202
- # - query: raw query string
203
- # - raw_headers: HTTP headers as a hash
204
- # - uri: the URI to request
205
- # - vars_get: GET variables as a hash to be translated into a query string
206
- # - vars_post: POST variables as a hash to be translated into POST data
207
- # - version: version of the protocol, default: 1.1
208
- # - vhost: Host header value
209
- #
210
- def request_cgi(opts={})
211
- c_enc = opts['encode'] || false
212
- c_cgi = opts['uri'] || '/'
213
- c_body = opts['data'] || ''
214
- c_meth = opts['method'] || 'GET'
215
- c_prot = opts['proto'] || 'HTTP'
216
- c_vers = opts['version'] || config['version'] || '1.1'
217
- c_qs = opts['query'] || ''
218
- c_varg = opts['vars_get'] || {}
219
- c_varp = opts['vars_post'] || {}
220
- c_head = opts['headers'] || config['headers'] || {}
221
- c_rawh = opts['raw_headers']|| config['raw_headers'] || ''
222
- c_type = opts['ctype'] || 'application/x-www-form-urlencoded'
223
- c_ag = opts['agent'] || config['agent']
224
- c_cook = opts['cookie'] || config['cookie']
225
- c_host = opts['vhost'] || config['vhost']
226
- c_conn = opts['connection']
227
- c_path = opts['path_info']
228
- c_auth = opts['basic_auth'] || config['basic_auth'] || ''
229
-
230
- uri = set_cgi(c_cgi)
231
- qstr = c_qs
232
- pstr = c_body
233
-
234
- if (config['pad_get_params'])
235
- 1.upto(config['pad_get_params_count'].to_i) do |i|
236
- qstr << '&' if qstr.length > 0
237
- qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
238
- qstr << '='
239
- qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
240
- end
241
- end
242
-
243
- c_varg.each_pair do |var,val|
244
- qstr << '&' if qstr.length > 0
245
- qstr << set_encode_uri(var)
246
- qstr << '='
247
- qstr << set_encode_uri(val)
248
- end
249
-
250
- if (config['pad_post_params'])
251
- 1.upto(config['pad_post_params_count'].to_i) do |i|
252
- pstr << '&' if qstr.length > 0
253
- pstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
254
- pstr << '='
255
- pstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
256
- end
257
- end
258
-
259
- c_varp.each_pair do |var,val|
260
- pstr << '&' if pstr.length > 0
261
- pstr << set_encode_uri(var)
262
- pstr << '='
263
- pstr << set_encode_uri(val)
264
- end
265
-
266
- req = ''
267
- req << set_method(c_meth)
268
- req << set_method_uri_spacer()
269
- req << set_uri_prepend()
270
- req << (c_enc ? set_encode_uri(uri):uri)
271
-
272
- if (qstr.length > 0)
273
- req << '?'
274
- req << qstr
275
- end
276
-
277
- req << set_path_info(c_path)
278
- req << set_uri_append()
279
- req << set_uri_version_spacer()
280
- req << set_version(c_prot, c_vers)
281
- req << set_host_header(c_host)
282
- req << set_agent_header(c_ag)
283
-
284
- if (c_auth.length > 0)
285
- req << set_basic_auth_header(c_auth)
286
- end
287
-
288
- req << set_cookie_header(c_cook)
289
- req << set_connection_header(c_conn)
290
- req << set_extra_headers(c_head)
291
-
292
- req << set_content_type_header(c_type)
293
- req << set_content_len_header(pstr.length)
294
- req << set_chunked_header()
295
- req << set_raw_headers(c_rawh)
296
- req << set_body(pstr)
297
-
298
- req
299
- end
300
-
301
- #
302
- # Connects to the remote server if possible.
303
- #
304
- def connect(t = -1)
305
- # If we already have a connection and we aren't pipelining, close it.
306
- if (self.conn)
307
- if !pipelining?
308
- close
309
- else
310
- return self.conn
311
- end
312
- end
313
-
314
- timeout = (t.nil? or t == -1) ? 0 : t
315
-
316
- self.conn = Rex::Socket::Tcp.create(
317
- 'PeerHost' => self.hostname,
318
- 'PeerPort' => self.port.to_i,
319
- 'LocalHost' => self.local_host,
320
- 'LocalPort' => self.local_port,
321
- 'Context' => self.context,
322
- 'SSL' => self.ssl,
323
- 'SSLVersion'=> self.ssl_version,
324
- 'Proxies' => self.proxies,
325
- 'Timeout' => timeout
326
- )
327
- end
328
-
329
- #
330
- # Closes the connection to the remote server.
331
- #
332
- def close
333
- if (self.conn)
334
- self.conn.shutdown
335
- self.conn.close
336
- end
337
-
338
- self.conn = nil
339
- end
340
-
341
- #
342
- # Transmit an HTTP request and receive the response
343
- # If persist is set, then the request will attempt
344
- # to reuse an existing connection.
345
- #
346
- def send_recv(req, t = -1, persist=false)
347
- @pipeline = persist
348
- send_request(req, t)
349
- res = read_response(t)
350
- res.request = req.to_s if res
351
- res
352
- end
353
-
354
- #
355
- # Send an HTTP request to the server
356
- #
357
- def send_request(req, t = -1)
358
- connect(t)
359
- conn.put(req.to_s)
360
- end
361
-
362
- #
363
- # Read a response from the server
364
- #
365
- def read_response(t = -1)
366
-
367
- resp = Response.new
368
- resp.max_data = config['read_max_data']
369
-
370
- # Wait at most t seconds for the full response to be read in. We only
371
- # do this if t was specified as a negative value indicating an infinite
372
- # wait cycle. If t were specified as nil it would indicate that no
373
- # response parsing is required.
374
-
375
- return resp if not t
376
-
377
- Timeout.timeout((t < 0) ? nil : t) do
378
-
379
- rv = nil
380
- while (
381
- rv != Packet::ParseCode::Completed and
382
- rv != Packet::ParseCode::Error
383
- )
384
-
385
- begin
386
-
387
- buff = conn.get_once(-1, 1)
388
- rv = resp.parse( buff || '' )
389
-
390
- ##########################################################################
391
- # XXX: NOTE: BUG: get_once currently (as of r10042) rescues "Exception"
392
- # As such, the following rescue block will ever be reached. -jjd
393
- ##########################################################################
394
-
395
- # Handle unexpected disconnects
396
- rescue ::Errno::EPIPE, ::EOFError, ::IOError
397
- case resp.state
398
- when Packet::ParseState::ProcessingHeader
399
- resp = nil
400
- when Packet::ParseState::ProcessingBody
401
- # truncated request, good enough
402
- resp.error = :truncated
403
- end
404
- break
405
- end
406
-
407
- # This is a dirty hack for broken HTTP servers
408
- if rv == Packet::ParseCode::Completed
409
- rbody = resp.body
410
- rbufq = resp.bufq
411
-
412
- rblob = rbody.to_s + rbufq.to_s
413
- tries = 0
414
- begin
415
- # XXX: This doesn't deal with chunked encoding or "Content-type: text/html; charset=..."
416
- while tries < 1000 and resp.headers["Content-Type"]== "text/html" and rblob !~ /<\/html>/i
417
- buff = conn.get_once(-1, 0.05)
418
- break if not buff
419
- rblob += buff
420
- tries += 1
421
- end
422
- rescue ::Errno::EPIPE, ::EOFError, ::IOError
423
- end
424
-
425
- resp.bufq = ""
426
- resp.body = rblob
427
- end
428
- end
429
- end
430
-
431
- return resp if not resp
432
-
433
- # As a last minute hack, we check to see if we're dealing with a 100 Continue here.
434
- if resp.proto == '1.1' and resp.code == 100
435
- # If so, our real response becaome the body, so we re-parse it.
436
- body = resp.body
437
- resp = Response.new
438
- resp.max_data = config['read_max_data']
439
- rv = resp.parse(body)
440
- # XXX: At some point, this may benefit from processing post-completion code
441
- # as seen above.
442
- end
443
-
444
- resp
445
- end
446
-
447
- #
448
- # Cleans up any outstanding connections and other resources.
449
- #
450
- def stop
451
- close
452
- end
453
-
454
- #
455
- # Returns whether or not the conn is valid.
456
- #
457
- def conn?
458
- conn != nil
459
- end
460
-
461
- #
462
- # Whether or not connections should be pipelined.
463
- #
464
- def pipelining?
465
- pipeline
466
- end
467
-
468
- #
469
- # Return the encoded URI
470
- # ['none','hex-normal', 'hex-all', 'u-normal', 'u-all']
471
- def set_encode_uri(uri)
472
- a = uri
473
- self.config['uri_encode_count'].times {
474
- a = Rex::Text.uri_encode(a, self.config['uri_encode_mode'])
475
- }
476
- return a
477
- end
478
-
479
- #
480
- # Return the encoded query string
481
- #
482
- def set_encode_qs(qs)
483
- a = qs
484
- self.config['uri_encode_count'].times {
485
- a = Rex::Text.uri_encode(a, self.config['uri_encode_mode'])
486
- }
487
- return a
488
- end
489
-
490
- #
491
- # Return the uri
492
- #
493
- def set_uri(uri)
494
-
495
- if (self.config['uri_dir_self_reference'])
496
- uri.gsub!('/', '/./')
497
- end
498
-
499
- if (self.config['uri_dir_fake_relative'])
500
- buf = ""
501
- uri.split('/').each do |part|
502
- cnt = rand(8)+2
503
- 1.upto(cnt) { |idx|
504
- buf << "/" + Rex::Text.rand_text_alphanumeric(rand(32)+1)
505
- }
506
- buf << ("/.." * cnt)
507
- buf << "/" + part
508
- end
509
- uri = buf
510
- end
511
-
512
- if (self.config['uri_full_url'])
513
- url = self.ssl ? "https" : "http"
514
- url << self.config['vhost']
515
- url << ((self.port == 80) ? "" : ":#{self.port}")
516
- url << uri
517
- url
518
- else
519
- uri
520
- end
521
- end
522
-
523
- #
524
- # Return the cgi
525
- #
526
- def set_cgi(uri)
527
-
528
- if (self.config['uri_dir_self_reference'])
529
- uri.gsub!('/', '/./')
530
- end
531
-
532
- if (self.config['uri_dir_fake_relative'])
533
- buf = ""
534
- uri.split('/').each do |part|
535
- cnt = rand(8)+2
536
- 1.upto(cnt) { |idx|
537
- buf << "/" + Rex::Text.rand_text_alphanumeric(rand(32)+1)
538
- }
539
- buf << ("/.." * cnt)
540
- buf << "/" + part
541
- end
542
- uri = buf
543
- end
544
-
545
- url = uri
546
-
547
- if (self.config['uri_full_url'])
548
- url = self.ssl ? "https" : "http"
549
- url << self.config['vhost']
550
- url << (self.port == 80) ? "" : ":#{self.port}"
551
- url << uri
552
- end
553
-
554
- url
555
- end
556
-
557
- #
558
- # Return the HTTP method string
559
- #
560
- def set_method(method)
561
- ret = method
562
-
563
- if (self.config['method_random_valid'])
564
- ret = ['GET', 'POST', 'HEAD'][rand(3)]
565
- end
566
-
567
- if (self.config['method_random_invalid'])
568
- ret = Rex::Text.rand_text_alpha(rand(20)+1)
569
- end
570
-
571
- if (self.config['method_random_case'])
572
- ret = Rex::Text.to_rand_case(ret)
573
- end
574
-
575
- ret
576
- end
577
-
578
- #
579
- # Return the HTTP version string
580
- #
581
- def set_version(protocol, version)
582
- ret = protocol + "/" + version
583
-
584
- if (self.config['version_random_valid'])
585
- ret = protocol + "/" + ['1.0', '1.1'][rand(2)]
586
- end
587
-
588
- if (self.config['version_random_invalid'])
589
- ret = Rex::Text.rand_text_alphanumeric(rand(20)+1)
590
- end
591
-
592
- if (self.config['version_random_case'])
593
- ret = Rex::Text.to_rand_case(ret)
594
- end
595
-
596
- ret << "\r\n"
597
- end
598
-
599
- #
600
- # Return the HTTP seperator and body string
601
- #
602
- def set_body(data)
603
- return "\r\n" + data if self.config['chunked_size'] == 0
604
- str = data.dup
605
- chunked = ''
606
- while str.size > 0
607
- chunk = str.slice!(0,rand(self.config['chunked_size']) + 1)
608
- chunked << sprintf("%x", chunk.size) + "\r\n" + chunk + "\r\n"
609
- end
610
- "\r\n" + chunked + "0\r\n\r\n"
611
- end
612
-
613
- #
614
- # Return the HTTP path info
615
- # TODO:
616
- # * Encode path information
617
- def set_path_info(path)
618
- path ? path : ''
619
- end
620
-
621
- #
622
- # Return the spacing between the method and uri
623
- #
624
- def set_method_uri_spacer
625
- len = self.config['pad_method_uri_count'].to_i
626
- set = " "
627
- buf = ""
628
-
629
- case self.config['pad_method_uri_type']
630
- when 'tab'
631
- set = "\t"
632
- when 'apache'
633
- set = "\t \x0b\x0c\x0d"
634
- end
635
-
636
- while(buf.length < len)
637
- buf << set[ rand(set.length) ]
638
- end
639
-
640
- return buf
641
- end
642
-
643
- #
644
- # Return the spacing between the uri and the version
645
- #
646
- def set_uri_version_spacer
647
- len = self.config['pad_uri_version_count'].to_i
648
- set = " "
649
- buf = ""
650
-
651
- case self.config['pad_uri_version_type']
652
- when 'tab'
653
- set = "\t"
654
- when 'apache'
655
- set = "\t \x0b\x0c\x0d"
656
- end
657
-
658
- while(buf.length < len)
659
- buf << set[ rand(set.length) ]
660
- end
661
-
662
- return buf
663
- end
664
-
665
- #
666
- # Return the padding to place before the uri
667
- #
668
- def set_uri_prepend
669
- prefix = ""
670
-
671
- if (self.config['uri_fake_params_start'])
672
- prefix << '/%3fa=b/../'
673
- end
674
-
675
- if (self.config['uri_fake_end'])
676
- prefix << '/%20HTTP/1.0/../../'
677
- end
678
-
679
- prefix
680
- end
681
-
682
- #
683
- # Return the padding to place before the uri
684
- #
685
- def set_uri_append
686
- # TODO:
687
- # * Support different padding types
688
- ""
689
- end
690
-
691
- #
692
- # Return the HTTP Host header
693
- #
694
- def set_host_header(host=nil)
695
- return "" if self.config['uri_full_url']
696
- host ||= self.config['vhost']
697
-
698
- # IPv6 addresses must be placed in brackets
699
- if Rex::Socket.is_ipv6?(host)
700
- host = "[#{host}]"
701
- end
702
-
703
- # The port should be appended if non-standard
704
- if not [80,443].include?(self.port)
705
- host = host + ":#{port}"
706
- end
707
-
708
- set_formatted_header("Host", host)
709
- end
710
-
711
- #
712
- # Return the HTTP agent header
713
- #
714
- def set_agent_header(agent)
715
- agent ? set_formatted_header("User-Agent", agent) : ""
716
- end
717
-
718
- #
719
- # Return the HTTP cookie header
720
- #
721
- def set_cookie_header(cookie)
722
- cookie ? set_formatted_header("Cookie", cookie) : ""
723
- end
724
-
725
- #
726
- # Return the HTTP connection header
727
- #
728
- def set_connection_header(conn)
729
- conn ? set_formatted_header("Connection", conn) : ""
730
- end
731
-
732
- #
733
- # Return the content type header
734
- #
735
- def set_content_type_header(ctype)
736
- set_formatted_header("Content-Type", ctype)
737
- end
738
-
739
- #
740
- # Return the content length header
741
- def set_content_len_header(clen)
742
- return "" if self.config['chunked_size'] > 0
743
- set_formatted_header("Content-Length", clen)
744
- end
745
-
746
- #
747
- # Return the Authorization basic-auth header
748
- #
749
- def set_basic_auth_header(auth)
750
- auth ? set_formatted_header("Authorization", "Basic " + Rex::Text.encode_base64(auth)) : ""
751
- end
752
-
753
- #
754
- # Return a string of formatted extra headers
755
- #
756
- def set_extra_headers(headers)
757
- buf = ''
758
-
759
- if (self.config['pad_fake_headers'])
760
- 1.upto(self.config['pad_fake_headers_count'].to_i) do |i|
761
- buf << set_formatted_header(
762
- Rex::Text.rand_text_alphanumeric(rand(32)+1),
763
- Rex::Text.rand_text_alphanumeric(rand(32)+1)
764
- )
765
- end
766
- end
767
-
768
- headers.each_pair do |var,val|
769
- buf << set_formatted_header(var, val)
770
- end
771
-
772
- buf
773
- end
774
-
775
- def set_chunked_header()
776
- return "" if self.config['chunked_size'] == 0
777
- set_formatted_header('Transfer-Encoding', 'chunked')
778
- end
779
-
780
- #
781
- # Return a string of raw header data
782
- #
783
- def set_raw_headers(data)
784
- data
785
- end
786
-
787
- #
788
- # Return a formatted header string
789
- #
790
- def set_formatted_header(var, val)
791
- if (self.config['header_folding'])
792
- "#{var}:\r\n\t#{val}\r\n"
793
- else
794
- "#{var}: #{val}\r\n"
795
- end
796
- end
797
-
798
-
799
-
800
- #
801
- # The client request configuration
802
- #
803
- attr_accessor :config
804
- #
805
- # The client request configuration classes
806
- #
807
- attr_accessor :config_types
808
- #
809
- # Whether or not pipelining is in use.
810
- #
811
- attr_accessor :pipeline
812
- #
813
- # The local host of the client.
814
- #
815
- attr_accessor :local_host
816
- #
817
- # The local port of the client.
818
- #
819
- attr_accessor :local_port
820
- #
821
- # The underlying connection.
822
- #
823
- attr_accessor :conn
824
- #
825
- # The calling context to pass to the socket
826
- #
827
- attr_accessor :context
828
- #
829
- # The proxy list
830
- #
831
- attr_accessor :proxies
832
-
833
-
834
- # When parsing the request, thunk off the first response from the server, since junk
835
- attr_accessor :junk_pipeline
26
+ DefaultUserAgent = ClientRequest::DefaultUserAgent
27
+
28
+ #
29
+ # Creates a new client instance
30
+ #
31
+ def initialize(host, port = 80, context = {}, ssl = nil, ssl_version = nil, proxies = nil, username = '', password = '')
32
+ self.hostname = host
33
+ self.port = port.to_i
34
+ self.context = context
35
+ self.ssl = ssl
36
+ self.ssl_version = ssl_version
37
+ self.proxies = proxies
38
+ self.username = username
39
+ self.password = password
40
+
41
+ # Take ClientRequest's defaults, but override with our own
42
+ self.config = Http::ClientRequest::DefaultConfig.merge({
43
+ 'read_max_data' => (1024*1024*1),
44
+ 'vhost' => self.hostname,
45
+ })
46
+
47
+ # XXX: This info should all be controlled by ClientRequest
48
+ self.config_types = {
49
+ 'uri_encode_mode' => ['hex-normal', 'hex-all', 'hex-random', 'u-normal', 'u-random', 'u-all'],
50
+ 'uri_encode_count' => 'integer',
51
+ 'uri_full_url' => 'bool',
52
+ 'pad_method_uri_count' => 'integer',
53
+ 'pad_uri_version_count' => 'integer',
54
+ 'pad_method_uri_type' => ['space', 'tab', 'apache'],
55
+ 'pad_uri_version_type' => ['space', 'tab', 'apache'],
56
+ 'method_random_valid' => 'bool',
57
+ 'method_random_invalid' => 'bool',
58
+ 'method_random_case' => 'bool',
59
+ 'version_random_valid' => 'bool',
60
+ 'version_random_invalid' => 'bool',
61
+ 'version_random_case' => 'bool',
62
+ 'uri_dir_self_reference' => 'bool',
63
+ 'uri_dir_fake_relative' => 'bool',
64
+ 'uri_use_backslashes' => 'bool',
65
+ 'pad_fake_headers' => 'bool',
66
+ 'pad_fake_headers_count' => 'integer',
67
+ 'pad_get_params' => 'bool',
68
+ 'pad_get_params_count' => 'integer',
69
+ 'pad_post_params' => 'bool',
70
+ 'pad_post_params_count' => 'integer',
71
+ 'uri_fake_end' => 'bool',
72
+ 'uri_fake_params_start' => 'bool',
73
+ 'header_folding' => 'bool',
74
+ 'chunked_size' => 'integer'
75
+ }
76
+
77
+
78
+ end
79
+
80
+ #
81
+ # Set configuration options
82
+ #
83
+ def set_config(opts = {})
84
+ opts.each_pair do |var,val|
85
+ # Default type is string
86
+ typ = self.config_types[var] || 'string'
87
+
88
+ # These are enum types
89
+ if(typ.class.to_s == 'Array')
90
+ if not typ.include?(val)
91
+ raise RuntimeError, "The specified value for #{var} is not one of the valid choices"
92
+ end
93
+ end
94
+
95
+ # The caller should have converted these to proper ruby types, but
96
+ # take care of the case where they didn't before setting the
97
+ # config.
98
+
99
+ if(typ == 'bool')
100
+ val = (val =~ /^(t|y|1)$/i ? true : false || val === true)
101
+ end
102
+
103
+ if(typ == 'integer')
104
+ val = val.to_i
105
+ end
106
+
107
+ self.config[var]=val
108
+ end
109
+ end
110
+
111
+ #
112
+ # Create an arbitrary HTTP request
113
+ #
114
+ # @param opts [Hash]
115
+ # @option opts 'agent' [String] User-Agent header value
116
+ # @option opts 'connection' [String] Connection header value
117
+ # @option opts 'cookie' [String] Cookie header value
118
+ # @option opts 'data' [String] HTTP data (only useful with some methods, see rfc2616)
119
+ # @option opts 'encode' [Bool] URI encode the supplied URI, default: false
120
+ # @option opts 'headers' [Hash] HTTP headers, e.g. <code>{ "X-MyHeader" => "value" }</code>
121
+ # @option opts 'method' [String] HTTP method to use in the request, not limited to standard methods defined by rfc2616, default: GET
122
+ # @option opts 'proto' [String] protocol, default: HTTP
123
+ # @option opts 'query' [String] raw query string
124
+ # @option opts 'raw_headers' [Hash] HTTP headers
125
+ # @option opts 'uri' [String] the URI to request
126
+ # @option opts 'version' [String] version of the protocol, default: 1.1
127
+ # @option opts 'vhost' [String] Host header value
128
+ #
129
+ # @return [ClientRequest]
130
+ def request_raw(opts={})
131
+ opts = self.config.merge(opts)
132
+
133
+ opts['ssl'] = self.ssl
134
+ opts['cgi'] = false
135
+ opts['port'] = self.port
136
+
137
+ req = ClientRequest.new(opts)
138
+ end
139
+
140
+
141
+ #
142
+ # Create a CGI compatible request
143
+ #
144
+ # @param (see #request_raw)
145
+ # @option opts (see #request_raw)
146
+ # @option opts 'ctype' [String] Content-Type header value, default: +application/x-www-form-urlencoded+
147
+ # @option opts 'encode_params' [Bool] URI encode the GET or POST variables (names and values), default: true
148
+ # @option opts 'vars_get' [Hash] GET variables as a hash to be translated into a query string
149
+ # @option opts 'vars_post' [Hash] POST variables as a hash to be translated into POST data
150
+ #
151
+ # @return [ClientRequest]
152
+ def request_cgi(opts={})
153
+ opts = self.config.merge(opts)
154
+
155
+ opts['ctype'] ||= 'application/x-www-form-urlencoded'
156
+ opts['ssl'] = self.ssl
157
+ opts['cgi'] = true
158
+ opts['port'] = self.port
159
+
160
+ req = ClientRequest.new(opts)
161
+ req
162
+ end
163
+
164
+ #
165
+ # Connects to the remote server if possible.
166
+ #
167
+ # @param t [Fixnum] Timeout
168
+ # @see Rex::Socket::Tcp.create
169
+ # @return [Rex::Socket::Tcp]
170
+ def connect(t = -1)
171
+ # If we already have a connection and we aren't pipelining, close it.
172
+ if (self.conn)
173
+ if !pipelining?
174
+ close
175
+ else
176
+ return self.conn
177
+ end
178
+ end
179
+
180
+ timeout = (t.nil? or t == -1) ? 0 : t
181
+
182
+ self.conn = Rex::Socket::Tcp.create(
183
+ 'PeerHost' => self.hostname,
184
+ 'PeerPort' => self.port.to_i,
185
+ 'LocalHost' => self.local_host,
186
+ 'LocalPort' => self.local_port,
187
+ 'Context' => self.context,
188
+ 'SSL' => self.ssl,
189
+ 'SSLVersion' => self.ssl_version,
190
+ 'Proxies' => self.proxies,
191
+ 'Timeout' => timeout
192
+ )
193
+ end
194
+
195
+ #
196
+ # Closes the connection to the remote server.
197
+ #
198
+ def close
199
+ if (self.conn)
200
+ self.conn.shutdown
201
+ self.conn.close unless self.conn.closed?
202
+ end
203
+
204
+ self.conn = nil
205
+ end
206
+
207
+ #
208
+ # Sends a request and gets a response back
209
+ #
210
+ # If the request is a 401, and we have creds, it will attempt to complete
211
+ # authentication and return the final response
212
+ #
213
+ # @return (see #_send_recv)
214
+ def send_recv(req, t = -1, persist=false)
215
+ res = _send_recv(req,t,persist)
216
+ if res and res.code == 401 and res.headers['WWW-Authenticate']
217
+ res = send_auth(res, req.opts, t, persist)
218
+ end
219
+ res
220
+ end
221
+
222
+ #
223
+ # Transmit an HTTP request and receive the response
224
+ #
225
+ # If persist is set, then the request will attempt to reuse an existing
226
+ # connection.
227
+ #
228
+ # Call this directly instead of {#send_recv} if you don't want automatic
229
+ # authentication handling.
230
+ #
231
+ # @return (see #read_response)
232
+ def _send_recv(req, t = -1, persist=false)
233
+ @pipeline = persist
234
+ send_request(req, t)
235
+ res = read_response(t)
236
+ res.request = req.to_s if res
237
+ res
238
+ end
239
+
240
+ #
241
+ # Send an HTTP request to the server
242
+ #
243
+ # @param req [Request,ClientRequest,#to_s] The request to send
244
+ # @param t (see #connect)
245
+ #
246
+ # @return [void]
247
+ def send_request(req, t = -1)
248
+ connect(t)
249
+ conn.put(req.to_s)
250
+ end
251
+
252
+ # Resends an HTTP Request with the propper authentcation headers
253
+ # set. If we do not support the authentication type the server requires
254
+ # we return the original response object
255
+ #
256
+ # @param res [Response] the HTTP Response object
257
+ # @param opts [Hash] the options used to generate the original HTTP request
258
+ # @param t [Fixnum] the timeout for the request in seconds
259
+ # @param persist [Boolean] whether or not to persist the TCP connection (pipelining)
260
+ #
261
+ # @return [Response] the last valid HTTP response object we received
262
+ def send_auth(res, opts, t, persist)
263
+ if opts['username'].nil? or opts['username'] == ''
264
+ if self.username and not (self.username == '')
265
+ opts['username'] = self.username
266
+ opts['password'] = self.password
267
+ else
268
+ opts['username'] = nil
269
+ opts['password'] = nil
270
+ end
271
+ end
272
+
273
+ return res if opts['username'].nil? or opts['username'] == ''
274
+ supported_auths = res.headers['WWW-Authenticate']
275
+ if supported_auths.include? 'Basic'
276
+ opts['headers'] ||= {}
277
+ opts['headers']['Authorization'] = basic_auth_header(opts['username'],opts['password'] )
278
+ req = request_cgi(opts)
279
+ res = _send_recv(req,t,persist)
280
+ return res
281
+ elsif supported_auths.include? "Digest"
282
+ temp_response = digest_auth(opts)
283
+ if temp_response.kind_of? Rex::Proto::Http::Response
284
+ res = temp_response
285
+ end
286
+ return res
287
+ elsif supported_auths.include? "NTLM"
288
+ opts['provider'] = 'NTLM'
289
+ temp_response = negotiate_auth(opts)
290
+ if temp_response.kind_of? Rex::Proto::Http::Response
291
+ res = temp_response
292
+ end
293
+ return res
294
+ elsif supported_auths.include? "Negotiate"
295
+ opts['provider'] = 'Negotiate'
296
+ temp_response = negotiate_auth(opts)
297
+ if temp_response.kind_of? Rex::Proto::Http::Response
298
+ res = temp_response
299
+ end
300
+ return res
301
+ end
302
+ return res
303
+ end
304
+
305
+ # Converts username and password into the HTTP Basic authorization
306
+ # string.
307
+ #
308
+ # @return [String] A value suitable for use as an Authorization header
309
+ def basic_auth_header(username,password)
310
+ auth_str = username.to_s + ":" + password.to_s
311
+ auth_str = "Basic " + Rex::Text.encode_base64(auth_str)
312
+ end
313
+
314
+ # Send a series of requests to complete Digest Authentication
315
+ #
316
+ # @param opts [Hash] the options used to build an HTTP request
317
+ #
318
+ # @return [Response] the last valid HTTP response we received
319
+ def digest_auth(opts={})
320
+ @nonce_count = 0
321
+
322
+ to = opts['timeout'] || 20
323
+
324
+ digest_user = opts['username'] || ""
325
+ digest_password = opts['password'] || ""
326
+
327
+ method = opts['method']
328
+ path = opts['uri']
329
+ iis = true
330
+ if (opts['DigestAuthIIS'] == false or self.config['DigestAuthIIS'] == false)
331
+ iis = false
332
+ end
333
+
334
+ begin
335
+ @nonce_count += 1
336
+
337
+ resp = opts['response']
338
+
339
+ if not resp
340
+ # Get authentication-challenge from server, and read out parameters required
341
+ r = request_cgi(opts.merge({
342
+ 'uri' => path,
343
+ 'method' => method }))
344
+ resp = _send_recv(r, to)
345
+ unless resp.kind_of? Rex::Proto::Http::Response
346
+ return nil
347
+ end
348
+
349
+ if resp.code != 401
350
+ return resp
351
+ end
352
+ return resp unless resp.headers['WWW-Authenticate']
353
+ end
354
+
355
+ # Don't anchor this regex to the beginning of string because header
356
+ # folding makes it appear later when the server presents multiple
357
+ # WWW-Authentication options (such as is the case with IIS configured
358
+ # for Digest or NTLM).
359
+ resp['www-authenticate'] =~ /Digest (.*)/
360
+
361
+ parameters = {}
362
+ $1.split(/,[[:space:]]*/).each do |p|
363
+ k, v = p.split("=", 2)
364
+ parameters[k] = v.gsub('"', '')
365
+ end
366
+
367
+ qop = parameters['qop']
368
+
369
+ if parameters['algorithm'] =~ /(.*?)(-sess)?$/
370
+ algorithm = case $1
371
+ when 'MD5' then Digest::MD5
372
+ when 'SHA1' then Digest::SHA1
373
+ when 'SHA2' then Digest::SHA2
374
+ when 'SHA256' then Digest::SHA256
375
+ when 'SHA384' then Digest::SHA384
376
+ when 'SHA512' then Digest::SHA512
377
+ when 'RMD160' then Digest::RMD160
378
+ else raise Error, "unknown algorithm \"#{$1}\""
379
+ end
380
+ algstr = parameters["algorithm"]
381
+ sess = $2
382
+ else
383
+ algorithm = Digest::MD5
384
+ algstr = "MD5"
385
+ sess = false
386
+ end
387
+
388
+ a1 = if sess then
389
+ [
390
+ algorithm.hexdigest("#{digest_user}:#{parameters['realm']}:#{digest_password}"),
391
+ parameters['nonce'],
392
+ @cnonce
393
+ ].join ':'
394
+ else
395
+ "#{digest_user}:#{parameters['realm']}:#{digest_password}"
396
+ end
397
+
398
+ ha1 = algorithm.hexdigest(a1)
399
+ ha2 = algorithm.hexdigest("#{method}:#{path}")
400
+
401
+ request_digest = [ha1, parameters['nonce']]
402
+ request_digest.push(('%08x' % @nonce_count), @cnonce, qop) if qop
403
+ request_digest << ha2
404
+ request_digest = request_digest.join ':'
405
+
406
+ # Same order as IE7
407
+ auth = [
408
+ "Digest username=\"#{digest_user}\"",
409
+ "realm=\"#{parameters['realm']}\"",
410
+ "nonce=\"#{parameters['nonce']}\"",
411
+ "uri=\"#{path}\"",
412
+ "cnonce=\"#{@cnonce}\"",
413
+ "nc=#{'%08x' % @nonce_count}",
414
+ "algorithm=#{algstr}",
415
+ "response=\"#{algorithm.hexdigest(request_digest)[0, 32]}\"",
416
+ # The spec says the qop value shouldn't be enclosed in quotes, but
417
+ # some versions of IIS require it and Apache accepts it. Chrome
418
+ # and Firefox both send it without quotes but IE does it this way.
419
+ # Use the non-compliant-but-everybody-does-it to be as compatible
420
+ # as possible by default. The user can override if they don't like
421
+ # it.
422
+ if qop.nil? then
423
+ elsif iis then
424
+ "qop=\"#{qop}\""
425
+ else
426
+ "qop=#{qop}"
427
+ end,
428
+ if parameters.key? 'opaque' then
429
+ "opaque=\"#{parameters['opaque']}\""
430
+ end
431
+ ].compact
432
+
433
+ headers ={ 'Authorization' => auth.join(', ') }
434
+ headers.merge!(opts['headers']) if opts['headers']
435
+
436
+ # Send main request with authentication
437
+ r = request_cgi(opts.merge({
438
+ 'uri' => path,
439
+ 'method' => method,
440
+ 'headers' => headers }))
441
+ resp = _send_recv(r, to, true)
442
+ unless resp.kind_of? Rex::Proto::Http::Response
443
+ return nil
444
+ end
445
+
446
+ return resp
447
+
448
+ rescue ::Errno::EPIPE, ::Timeout::Error
449
+ end
450
+ end
451
+
452
+ #
453
+ # Builds a series of requests to complete Negotiate Auth. Works essentially
454
+ # the same way as Digest auth. Same pipelining concerns exist.
455
+ #
456
+ # @option opts (see #send_request_cgi)
457
+ # @option opts provider ["Negotiate","NTLM"] What Negotiate provider to use
458
+ #
459
+ # @return [Response] the last valid HTTP response we received
460
+ def negotiate_auth(opts={})
461
+ ntlm_options = {
462
+ :signing => false,
463
+ :usentlm2_session => self.config['usentlm2_session'],
464
+ :use_ntlmv2 => self.config['use_ntlmv2'],
465
+ :send_lm => self.config['send_lm'],
466
+ :send_ntlm => self.config['send_ntlm']
467
+ }
468
+
469
+ to = opts['timeout'] || 20
470
+ opts['username'] ||= ''
471
+ opts['password'] ||= ''
472
+
473
+ if opts['provider'] and opts['provider'].include? 'Negotiate'
474
+ provider = "Negotiate "
475
+ else
476
+ provider = 'NTLM '
477
+ end
478
+
479
+ opts['method']||= 'GET'
480
+ opts['headers']||= {}
481
+
482
+ ntlmssp_flags = ::Rex::Proto::NTLM::Utils.make_ntlm_flags(ntlm_options)
483
+ workstation_name = Rex::Text.rand_text_alpha(rand(8)+6)
484
+ domain_name = self.config['domain']
485
+
486
+ b64_blob = Rex::Text::encode_base64(
487
+ ::Rex::Proto::NTLM::Utils::make_ntlmssp_blob_init(
488
+ domain_name,
489
+ workstation_name,
490
+ ntlmssp_flags
491
+ ))
492
+
493
+ ntlm_message_1 = provider + b64_blob
494
+
495
+ begin
496
+ # First request to get the challenge
497
+ opts['headers']['Authorization'] = ntlm_message_1
498
+ r = request_cgi(opts)
499
+ resp = _send_recv(r, to)
500
+ unless resp.kind_of? Rex::Proto::Http::Response
501
+ return nil
502
+ end
503
+
504
+ return resp unless resp.code == 401 && resp.headers['WWW-Authenticate']
505
+
506
+ # Get the challenge and craft the response
507
+ ntlm_challenge = resp.headers['WWW-Authenticate'].scan(/#{provider}([A-Z0-9\x2b\x2f=]+)/ni).flatten[0]
508
+ return resp unless ntlm_challenge
509
+
510
+ ntlm_message_2 = Rex::Text::decode_base64(ntlm_challenge)
511
+ blob_data = ::Rex::Proto::NTLM::Utils.parse_ntlm_type_2_blob(ntlm_message_2)
512
+
513
+ challenge_key = blob_data[:challenge_key]
514
+ server_ntlmssp_flags = blob_data[:server_ntlmssp_flags] #else should raise an error
515
+ default_name = blob_data[:default_name] || '' #netbios name
516
+ default_domain = blob_data[:default_domain] || '' #netbios domain
517
+ dns_host_name = blob_data[:dns_host_name] || '' #dns name
518
+ dns_domain_name = blob_data[:dns_domain_name] || '' #dns domain
519
+ chall_MsvAvTimestamp = blob_data[:chall_MsvAvTimestamp] || '' #Client time
520
+
521
+ spnopt = {:use_spn => self.config['SendSPN'], :name => self.hostname}
522
+
523
+ resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge = ::Rex::Proto::NTLM::Utils.create_lm_ntlm_responses(
524
+ opts['username'],
525
+ opts['password'],
526
+ challenge_key,
527
+ domain_name,
528
+ default_name,
529
+ default_domain,
530
+ dns_host_name,
531
+ dns_domain_name,
532
+ chall_MsvAvTimestamp,
533
+ spnopt,
534
+ ntlm_options
535
+ )
536
+
537
+ ntlm_message_3 = ::Rex::Proto::NTLM::Utils.make_ntlmssp_blob_auth(
538
+ domain_name,
539
+ workstation_name,
540
+ opts['username'],
541
+ resp_lm,
542
+ resp_ntlm,
543
+ '',
544
+ ntlmssp_flags
545
+ )
546
+
547
+ ntlm_message_3 = Rex::Text::encode_base64(ntlm_message_3)
548
+
549
+ # Send the response
550
+ opts['headers']['Authorization'] = "#{provider}#{ntlm_message_3}"
551
+ r = request_cgi(opts)
552
+ resp = _send_recv(r, to, true)
553
+ unless resp.kind_of? Rex::Proto::Http::Response
554
+ return nil
555
+ end
556
+ return resp
557
+
558
+ rescue ::Errno::EPIPE, ::Timeout::Error
559
+ return nil
560
+ end
561
+ end
562
+ #
563
+ # Read a response from the server
564
+ #
565
+ # @return [Response]
566
+ def read_response(t = -1, opts = {})
567
+
568
+ resp = Response.new
569
+ resp.max_data = config['read_max_data']
570
+
571
+ # Wait at most t seconds for the full response to be read in. We only
572
+ # do this if t was specified as a negative value indicating an infinite
573
+ # wait cycle. If t were specified as nil it would indicate that no
574
+ # response parsing is required.
575
+
576
+ return resp if not t
577
+
578
+ Timeout.timeout((t < 0) ? nil : t) do
579
+
580
+ rv = nil
581
+ while (
582
+ rv != Packet::ParseCode::Completed and
583
+ rv != Packet::ParseCode::Error
584
+ )
585
+
586
+ begin
587
+
588
+ buff = conn.get_once(-1, 1)
589
+ rv = resp.parse( buff || '' )
590
+
591
+ # Handle unexpected disconnects
592
+ rescue ::Errno::EPIPE, ::EOFError, ::IOError
593
+ case resp.state
594
+ when Packet::ParseState::ProcessingHeader
595
+ resp = nil
596
+ when Packet::ParseState::ProcessingBody
597
+ # truncated request, good enough
598
+ resp.error = :truncated
599
+ end
600
+ break
601
+ end
602
+
603
+ # This is a dirty hack for broken HTTP servers
604
+ if rv == Packet::ParseCode::Completed
605
+ rbody = resp.body
606
+ rbufq = resp.bufq
607
+
608
+ rblob = rbody.to_s + rbufq.to_s
609
+ tries = 0
610
+ begin
611
+ # XXX: This doesn't deal with chunked encoding or "Content-type: text/html; charset=..."
612
+ while tries < 1000 and resp.headers["Content-Type"]== "text/html" and rblob !~ /<\/html>/i
613
+ buff = conn.get_once(-1, 0.05)
614
+ break if not buff
615
+ rblob += buff
616
+ tries += 1
617
+ end
618
+ rescue ::Errno::EPIPE, ::EOFError, ::IOError
619
+ end
620
+
621
+ resp.bufq = ""
622
+ resp.body = rblob
623
+ end
624
+ end
625
+ end
626
+
627
+ return resp if not resp
628
+
629
+ # As a last minute hack, we check to see if we're dealing with a 100 Continue here.
630
+ # Most of the time this is handled by the parser via check_100()
631
+ if resp.proto == '1.1' and resp.code == 100 and not opts[:skip_100]
632
+ # Read the real response from the body if we found one
633
+ # If so, our real response became the body, so we re-parse it.
634
+ if resp.body.to_s =~ /^HTTP/
635
+ body = resp.body
636
+ resp = Response.new
637
+ resp.max_data = config['read_max_data']
638
+ rv = resp.parse(body)
639
+ # We found a 100 Continue but didn't read the real reply yet
640
+ # Otherwise reread the reply, but don't try this hack again
641
+ else
642
+ resp = read_response(t, :skip_100 => true)
643
+ end
644
+ end
645
+
646
+ resp
647
+ end
648
+
649
+ #
650
+ # Cleans up any outstanding connections and other resources.
651
+ #
652
+ def stop
653
+ close
654
+ end
655
+
656
+ #
657
+ # Returns whether or not the conn is valid.
658
+ #
659
+ def conn?
660
+ conn != nil
661
+ end
662
+
663
+ #
664
+ # Whether or not connections should be pipelined.
665
+ #
666
+ def pipelining?
667
+ pipeline
668
+ end
669
+
670
+ #
671
+ # The client request configuration
672
+ #
673
+ attr_accessor :config
674
+ #
675
+ # The client request configuration classes
676
+ #
677
+ attr_accessor :config_types
678
+ #
679
+ # Whether or not pipelining is in use.
680
+ #
681
+ attr_accessor :pipeline
682
+ #
683
+ # The local host of the client.
684
+ #
685
+ attr_accessor :local_host
686
+ #
687
+ # The local port of the client.
688
+ #
689
+ attr_accessor :local_port
690
+ #
691
+ # The underlying connection.
692
+ #
693
+ attr_accessor :conn
694
+ #
695
+ # The calling context to pass to the socket
696
+ #
697
+ attr_accessor :context
698
+ #
699
+ # The proxy list
700
+ #
701
+ attr_accessor :proxies
702
+
703
+ # Auth
704
+ attr_accessor :username, :password
705
+
706
+ # When parsing the request, thunk off the first response from the server, since junk
707
+ attr_accessor :junk_pipeline
836
708
 
837
709
  protected
838
710
 
839
- # https
840
- attr_accessor :ssl, :ssl_version # :nodoc:
711
+ # https
712
+ attr_accessor :ssl, :ssl_version # :nodoc:
841
713
 
842
- attr_accessor :hostname, :port # :nodoc:
714
+ attr_accessor :hostname, :port # :nodoc:
843
715
 
844
716
 
845
717
  end