librex 0.0.1

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 (370) hide show
  1. data/README +4 -0
  2. data/lib/rex.rb +101 -0
  3. data/lib/rex.rb.ts.rb +70 -0
  4. data/lib/rex/LICENSE +29 -0
  5. data/lib/rex/arch.rb +103 -0
  6. data/lib/rex/arch/sparc.rb +75 -0
  7. data/lib/rex/arch/sparc.rb.ut.rb +18 -0
  8. data/lib/rex/arch/x86.rb +513 -0
  9. data/lib/rex/arch/x86.rb.ut.rb +93 -0
  10. data/lib/rex/assembly/nasm.rb +100 -0
  11. data/lib/rex/assembly/nasm.rb.ut.rb +22 -0
  12. data/lib/rex/codepage.map +104 -0
  13. data/lib/rex/compat.rb +281 -0
  14. data/lib/rex/constants.rb +113 -0
  15. data/lib/rex/elfparsey.rb +11 -0
  16. data/lib/rex/elfparsey/elf.rb +123 -0
  17. data/lib/rex/elfparsey/elfbase.rb +260 -0
  18. data/lib/rex/elfparsey/exceptions.rb +27 -0
  19. data/lib/rex/elfscan.rb +12 -0
  20. data/lib/rex/elfscan/scanner.rb +207 -0
  21. data/lib/rex/elfscan/search.rb +46 -0
  22. data/lib/rex/encoder/alpha2.rb +31 -0
  23. data/lib/rex/encoder/alpha2/alpha_mixed.rb +68 -0
  24. data/lib/rex/encoder/alpha2/alpha_upper.rb +79 -0
  25. data/lib/rex/encoder/alpha2/generic.rb +113 -0
  26. data/lib/rex/encoder/alpha2/unicode_mixed.rb +117 -0
  27. data/lib/rex/encoder/alpha2/unicode_upper.rb +129 -0
  28. data/lib/rex/encoder/ndr.rb +89 -0
  29. data/lib/rex/encoder/ndr.rb.ut.rb +44 -0
  30. data/lib/rex/encoder/nonalpha.rb +61 -0
  31. data/lib/rex/encoder/nonupper.rb +64 -0
  32. data/lib/rex/encoder/xdr.rb +106 -0
  33. data/lib/rex/encoder/xdr.rb.ut.rb +29 -0
  34. data/lib/rex/encoder/xor.rb +69 -0
  35. data/lib/rex/encoder/xor/dword.rb +13 -0
  36. data/lib/rex/encoder/xor/dword_additive.rb +13 -0
  37. data/lib/rex/encoders/xor_dword.rb +35 -0
  38. data/lib/rex/encoders/xor_dword_additive.rb +53 -0
  39. data/lib/rex/encoders/xor_dword_additive.rb.ut.rb +12 -0
  40. data/lib/rex/encoding/xor.rb +20 -0
  41. data/lib/rex/encoding/xor.rb.ts.rb +14 -0
  42. data/lib/rex/encoding/xor/byte.rb +15 -0
  43. data/lib/rex/encoding/xor/byte.rb.ut.rb +21 -0
  44. data/lib/rex/encoding/xor/dword.rb +21 -0
  45. data/lib/rex/encoding/xor/dword.rb.ut.rb +15 -0
  46. data/lib/rex/encoding/xor/dword_additive.rb +92 -0
  47. data/lib/rex/encoding/xor/dword_additive.rb.ut.rb +15 -0
  48. data/lib/rex/encoding/xor/exceptions.rb +17 -0
  49. data/lib/rex/encoding/xor/generic.rb +146 -0
  50. data/lib/rex/encoding/xor/generic.rb.ut.rb +120 -0
  51. data/lib/rex/encoding/xor/qword.rb +15 -0
  52. data/lib/rex/encoding/xor/word.rb +21 -0
  53. data/lib/rex/encoding/xor/word.rb.ut.rb +13 -0
  54. data/lib/rex/exceptions.rb +275 -0
  55. data/lib/rex/exceptions.rb.ut.rb +44 -0
  56. data/lib/rex/exploitation/cmdstager.rb +133 -0
  57. data/lib/rex/exploitation/egghunter.rb +143 -0
  58. data/lib/rex/exploitation/egghunter.rb.ut.rb +25 -0
  59. data/lib/rex/exploitation/encryptjs.rb +77 -0
  60. data/lib/rex/exploitation/heaplib.js.b64 +331 -0
  61. data/lib/rex/exploitation/heaplib.rb +94 -0
  62. data/lib/rex/exploitation/javascriptosdetect.rb +735 -0
  63. data/lib/rex/exploitation/obfuscatejs.rb +335 -0
  64. data/lib/rex/exploitation/opcodedb.rb +818 -0
  65. data/lib/rex/exploitation/opcodedb.rb.ut.rb +279 -0
  66. data/lib/rex/exploitation/seh.rb +92 -0
  67. data/lib/rex/exploitation/seh.rb.ut.rb +19 -0
  68. data/lib/rex/file.rb +84 -0
  69. data/lib/rex/file.rb.ut.rb +16 -0
  70. data/lib/rex/image_source.rb +12 -0
  71. data/lib/rex/image_source/disk.rb +60 -0
  72. data/lib/rex/image_source/image_source.rb +46 -0
  73. data/lib/rex/image_source/memory.rb +37 -0
  74. data/lib/rex/io/bidirectional_pipe.rb +157 -0
  75. data/lib/rex/io/datagram_abstraction.rb +35 -0
  76. data/lib/rex/io/stream.rb +313 -0
  77. data/lib/rex/io/stream_abstraction.rb +186 -0
  78. data/lib/rex/io/stream_server.rb +211 -0
  79. data/lib/rex/job_container.rb +202 -0
  80. data/lib/rex/logging.rb +4 -0
  81. data/lib/rex/logging/log_dispatcher.rb +179 -0
  82. data/lib/rex/logging/log_sink.rb +42 -0
  83. data/lib/rex/logging/sinks/flatfile.rb +55 -0
  84. data/lib/rex/logging/sinks/stderr.rb +43 -0
  85. data/lib/rex/machparsey.rb +9 -0
  86. data/lib/rex/machparsey/exceptions.rb +34 -0
  87. data/lib/rex/machparsey/mach.rb +209 -0
  88. data/lib/rex/machparsey/machbase.rb +408 -0
  89. data/lib/rex/machscan.rb +9 -0
  90. data/lib/rex/machscan/scanner.rb +217 -0
  91. data/lib/rex/mime.rb +9 -0
  92. data/lib/rex/mime/header.rb +75 -0
  93. data/lib/rex/mime/message.rb +112 -0
  94. data/lib/rex/mime/part.rb +20 -0
  95. data/lib/rex/nop/opty2.rb +108 -0
  96. data/lib/rex/nop/opty2.rb.ut.rb +23 -0
  97. data/lib/rex/nop/opty2_tables.rb +300 -0
  98. data/lib/rex/ole.rb +128 -0
  99. data/lib/rex/ole/clsid.rb +47 -0
  100. data/lib/rex/ole/difat.rb +141 -0
  101. data/lib/rex/ole/directory.rb +230 -0
  102. data/lib/rex/ole/direntry.rb +240 -0
  103. data/lib/rex/ole/fat.rb +99 -0
  104. data/lib/rex/ole/header.rb +204 -0
  105. data/lib/rex/ole/minifat.rb +77 -0
  106. data/lib/rex/ole/samples/create_ole.rb +27 -0
  107. data/lib/rex/ole/samples/dir.rb +35 -0
  108. data/lib/rex/ole/samples/dump_stream.rb +34 -0
  109. data/lib/rex/ole/samples/ole_info.rb +23 -0
  110. data/lib/rex/ole/storage.rb +395 -0
  111. data/lib/rex/ole/stream.rb +53 -0
  112. data/lib/rex/ole/substorage.rb +49 -0
  113. data/lib/rex/ole/util.rb +157 -0
  114. data/lib/rex/parser/arguments.rb +97 -0
  115. data/lib/rex/parser/arguments.rb.ut.rb +67 -0
  116. data/lib/rex/parser/ini.rb +185 -0
  117. data/lib/rex/parser/ini.rb.ut.rb +29 -0
  118. data/lib/rex/parser/nmap_xml.rb +111 -0
  119. data/lib/rex/payloads.rb +1 -0
  120. data/lib/rex/payloads/win32.rb +2 -0
  121. data/lib/rex/payloads/win32/common.rb +26 -0
  122. data/lib/rex/payloads/win32/kernel.rb +53 -0
  123. data/lib/rex/payloads/win32/kernel/common.rb +54 -0
  124. data/lib/rex/payloads/win32/kernel/migration.rb +12 -0
  125. data/lib/rex/payloads/win32/kernel/recovery.rb +50 -0
  126. data/lib/rex/payloads/win32/kernel/stager.rb +171 -0
  127. data/lib/rex/peparsey.rb +12 -0
  128. data/lib/rex/peparsey/exceptions.rb +32 -0
  129. data/lib/rex/peparsey/pe.rb +188 -0
  130. data/lib/rex/peparsey/pe_memdump.rb +63 -0
  131. data/lib/rex/peparsey/pebase.rb +1655 -0
  132. data/lib/rex/peparsey/section.rb +136 -0
  133. data/lib/rex/pescan.rb +13 -0
  134. data/lib/rex/pescan/analyze.rb +309 -0
  135. data/lib/rex/pescan/scanner.rb +206 -0
  136. data/lib/rex/pescan/search.rb +56 -0
  137. data/lib/rex/platforms.rb +1 -0
  138. data/lib/rex/platforms/windows.rb +51 -0
  139. data/lib/rex/poly.rb +132 -0
  140. data/lib/rex/poly/block.rb +468 -0
  141. data/lib/rex/poly/register.rb +100 -0
  142. data/lib/rex/poly/register/x86.rb +40 -0
  143. data/lib/rex/post.rb +8 -0
  144. data/lib/rex/post/dir.rb +51 -0
  145. data/lib/rex/post/file.rb +172 -0
  146. data/lib/rex/post/file_stat.rb +220 -0
  147. data/lib/rex/post/gen.pl +13 -0
  148. data/lib/rex/post/io.rb +182 -0
  149. data/lib/rex/post/meterpreter.rb +4 -0
  150. data/lib/rex/post/meterpreter/channel.rb +438 -0
  151. data/lib/rex/post/meterpreter/channel_container.rb +54 -0
  152. data/lib/rex/post/meterpreter/channels/pool.rb +160 -0
  153. data/lib/rex/post/meterpreter/channels/pools/file.rb +62 -0
  154. data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +103 -0
  155. data/lib/rex/post/meterpreter/channels/stream.rb +87 -0
  156. data/lib/rex/post/meterpreter/client.rb +335 -0
  157. data/lib/rex/post/meterpreter/client_core.rb +274 -0
  158. data/lib/rex/post/meterpreter/dependencies.rb +3 -0
  159. data/lib/rex/post/meterpreter/extension.rb +32 -0
  160. data/lib/rex/post/meterpreter/extensions/espia/espia.rb +58 -0
  161. data/lib/rex/post/meterpreter/extensions/espia/tlv.rb +16 -0
  162. data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +94 -0
  163. data/lib/rex/post/meterpreter/extensions/incognito/tlv.rb +21 -0
  164. data/lib/rex/post/meterpreter/extensions/priv/fs.rb +118 -0
  165. data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +61 -0
  166. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +104 -0
  167. data/lib/rex/post/meterpreter/extensions/priv/tlv.rb +28 -0
  168. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +100 -0
  169. data/lib/rex/post/meterpreter/extensions/sniffer/tlv.rb +24 -0
  170. data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +333 -0
  171. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +273 -0
  172. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +235 -0
  173. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +103 -0
  174. data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +48 -0
  175. data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +144 -0
  176. data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +73 -0
  177. data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +56 -0
  178. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +137 -0
  179. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +167 -0
  180. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +167 -0
  181. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +192 -0
  182. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +139 -0
  183. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +97 -0
  184. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +184 -0
  185. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +41 -0
  186. data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +61 -0
  187. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +361 -0
  188. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +129 -0
  189. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +55 -0
  190. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +336 -0
  191. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +141 -0
  192. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +279 -0
  193. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +182 -0
  194. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +102 -0
  195. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +174 -0
  196. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +185 -0
  197. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +227 -0
  198. data/lib/rex/post/meterpreter/inbound_packet_handler.rb +30 -0
  199. data/lib/rex/post/meterpreter/object_aliases.rb +83 -0
  200. data/lib/rex/post/meterpreter/packet.rb +596 -0
  201. data/lib/rex/post/meterpreter/packet_dispatcher.rb +409 -0
  202. data/lib/rex/post/meterpreter/packet_parser.rb +94 -0
  203. data/lib/rex/post/meterpreter/packet_response_waiter.rb +83 -0
  204. data/lib/rex/post/meterpreter/ui/console.rb +135 -0
  205. data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +62 -0
  206. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +595 -0
  207. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +108 -0
  208. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +241 -0
  209. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +61 -0
  210. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +98 -0
  211. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +51 -0
  212. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +132 -0
  213. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +187 -0
  214. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +63 -0
  215. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +376 -0
  216. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +270 -0
  217. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +484 -0
  218. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +315 -0
  219. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +95 -0
  220. data/lib/rex/post/permission.rb +26 -0
  221. data/lib/rex/post/process.rb +57 -0
  222. data/lib/rex/post/thread.rb +57 -0
  223. data/lib/rex/post/ui.rb +52 -0
  224. data/lib/rex/proto.rb +12 -0
  225. data/lib/rex/proto.rb.ts.rb +8 -0
  226. data/lib/rex/proto/dcerpc.rb +6 -0
  227. data/lib/rex/proto/dcerpc.rb.ts.rb +9 -0
  228. data/lib/rex/proto/dcerpc/client.rb +358 -0
  229. data/lib/rex/proto/dcerpc/client.rb.ut.rb +491 -0
  230. data/lib/rex/proto/dcerpc/exceptions.rb +150 -0
  231. data/lib/rex/proto/dcerpc/handle.rb +47 -0
  232. data/lib/rex/proto/dcerpc/handle.rb.ut.rb +85 -0
  233. data/lib/rex/proto/dcerpc/ndr.rb +72 -0
  234. data/lib/rex/proto/dcerpc/ndr.rb.ut.rb +41 -0
  235. data/lib/rex/proto/dcerpc/packet.rb +253 -0
  236. data/lib/rex/proto/dcerpc/packet.rb.ut.rb +56 -0
  237. data/lib/rex/proto/dcerpc/response.rb +186 -0
  238. data/lib/rex/proto/dcerpc/response.rb.ut.rb +15 -0
  239. data/lib/rex/proto/dcerpc/uuid.rb +84 -0
  240. data/lib/rex/proto/dcerpc/uuid.rb.ut.rb +46 -0
  241. data/lib/rex/proto/drda.rb +5 -0
  242. data/lib/rex/proto/drda.rb.ts.rb +17 -0
  243. data/lib/rex/proto/drda/constants.rb +49 -0
  244. data/lib/rex/proto/drda/constants.rb.ut.rb +23 -0
  245. data/lib/rex/proto/drda/packet.rb +252 -0
  246. data/lib/rex/proto/drda/packet.rb.ut.rb +109 -0
  247. data/lib/rex/proto/drda/utils.rb +123 -0
  248. data/lib/rex/proto/drda/utils.rb.ut.rb +84 -0
  249. data/lib/rex/proto/http.rb +5 -0
  250. data/lib/rex/proto/http.rb.ts.rb +12 -0
  251. data/lib/rex/proto/http/client.rb +817 -0
  252. data/lib/rex/proto/http/client.rb.ut.rb +93 -0
  253. data/lib/rex/proto/http/handler.rb +46 -0
  254. data/lib/rex/proto/http/handler/erb.rb +128 -0
  255. data/lib/rex/proto/http/handler/erb.rb.ut.rb +21 -0
  256. data/lib/rex/proto/http/handler/erb.rb.ut.rb.rhtml +1 -0
  257. data/lib/rex/proto/http/handler/proc.rb +54 -0
  258. data/lib/rex/proto/http/handler/proc.rb.ut.rb +24 -0
  259. data/lib/rex/proto/http/header.rb +161 -0
  260. data/lib/rex/proto/http/header.rb.ut.rb +46 -0
  261. data/lib/rex/proto/http/packet.rb +394 -0
  262. data/lib/rex/proto/http/packet.rb.ut.rb +165 -0
  263. data/lib/rex/proto/http/request.rb +356 -0
  264. data/lib/rex/proto/http/request.rb.ut.rb +214 -0
  265. data/lib/rex/proto/http/response.rb +85 -0
  266. data/lib/rex/proto/http/response.rb.ut.rb +149 -0
  267. data/lib/rex/proto/http/server.rb +367 -0
  268. data/lib/rex/proto/http/server.rb.ut.rb +79 -0
  269. data/lib/rex/proto/smb.rb +7 -0
  270. data/lib/rex/proto/smb.rb.ts.rb +8 -0
  271. data/lib/rex/proto/smb/client.rb +1733 -0
  272. data/lib/rex/proto/smb/client.rb.ut.rb +223 -0
  273. data/lib/rex/proto/smb/constants.rb +1062 -0
  274. data/lib/rex/proto/smb/constants.rb.ut.rb +18 -0
  275. data/lib/rex/proto/smb/crypt.rb +95 -0
  276. data/lib/rex/proto/smb/crypt.rb.ut.rb +20 -0
  277. data/lib/rex/proto/smb/evasions.rb +65 -0
  278. data/lib/rex/proto/smb/exceptions.rb +846 -0
  279. data/lib/rex/proto/smb/simpleclient.rb +292 -0
  280. data/lib/rex/proto/smb/simpleclient.rb.ut.rb +128 -0
  281. data/lib/rex/proto/smb/utils.rb +514 -0
  282. data/lib/rex/proto/smb/utils.rb.ut.rb +20 -0
  283. data/lib/rex/proto/sunrpc.rb +1 -0
  284. data/lib/rex/proto/sunrpc/client.rb +195 -0
  285. data/lib/rex/script.rb +42 -0
  286. data/lib/rex/script/base.rb +59 -0
  287. data/lib/rex/script/meterpreter.rb +9 -0
  288. data/lib/rex/script/shell.rb +9 -0
  289. data/lib/rex/service.rb +48 -0
  290. data/lib/rex/service_manager.rb +141 -0
  291. data/lib/rex/service_manager.rb.ut.rb +32 -0
  292. data/lib/rex/services/local_relay.rb +423 -0
  293. data/lib/rex/socket.rb +586 -0
  294. data/lib/rex/socket.rb.ut.rb +86 -0
  295. data/lib/rex/socket/comm.rb +119 -0
  296. data/lib/rex/socket/comm/local.rb +409 -0
  297. data/lib/rex/socket/comm/local.rb.ut.rb +75 -0
  298. data/lib/rex/socket/ip.rb +129 -0
  299. data/lib/rex/socket/parameters.rb +345 -0
  300. data/lib/rex/socket/parameters.rb.ut.rb +51 -0
  301. data/lib/rex/socket/range_walker.rb +295 -0
  302. data/lib/rex/socket/range_walker.rb.ut.rb +55 -0
  303. data/lib/rex/socket/ssl_tcp.rb +184 -0
  304. data/lib/rex/socket/ssl_tcp.rb.ut.rb +39 -0
  305. data/lib/rex/socket/ssl_tcp_server.rb +122 -0
  306. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +51 -0
  307. data/lib/rex/socket/subnet_walker.rb +75 -0
  308. data/lib/rex/socket/subnet_walker.rb.ut.rb +28 -0
  309. data/lib/rex/socket/switch_board.rb +272 -0
  310. data/lib/rex/socket/switch_board.rb.ut.rb +52 -0
  311. data/lib/rex/socket/tcp.rb +76 -0
  312. data/lib/rex/socket/tcp.rb.ut.rb +64 -0
  313. data/lib/rex/socket/tcp_server.rb +67 -0
  314. data/lib/rex/socket/tcp_server.rb.ut.rb +44 -0
  315. data/lib/rex/socket/udp.rb +157 -0
  316. data/lib/rex/socket/udp.rb.ut.rb +44 -0
  317. data/lib/rex/struct2.rb +5 -0
  318. data/lib/rex/struct2/c_struct.rb +181 -0
  319. data/lib/rex/struct2/c_struct_template.rb +39 -0
  320. data/lib/rex/struct2/constant.rb +26 -0
  321. data/lib/rex/struct2/element.rb +44 -0
  322. data/lib/rex/struct2/generic.rb +73 -0
  323. data/lib/rex/struct2/restraint.rb +54 -0
  324. data/lib/rex/struct2/s_string.rb +72 -0
  325. data/lib/rex/struct2/s_struct.rb +111 -0
  326. data/lib/rex/sync.rb +6 -0
  327. data/lib/rex/sync/event.rb +94 -0
  328. data/lib/rex/sync/read_write_lock.rb +176 -0
  329. data/lib/rex/sync/ref.rb +57 -0
  330. data/lib/rex/sync/thread_safe.rb +82 -0
  331. data/lib/rex/test.rb +35 -0
  332. data/lib/rex/text.rb +1029 -0
  333. data/lib/rex/text.rb.ut.rb +168 -0
  334. data/lib/rex/time.rb +65 -0
  335. data/lib/rex/transformer.rb +115 -0
  336. data/lib/rex/transformer.rb.ut.rb +38 -0
  337. data/lib/rex/ui.rb +21 -0
  338. data/lib/rex/ui/interactive.rb +252 -0
  339. data/lib/rex/ui/output.rb +80 -0
  340. data/lib/rex/ui/output/none.rb +18 -0
  341. data/lib/rex/ui/progress_tracker.rb +96 -0
  342. data/lib/rex/ui/subscriber.rb +149 -0
  343. data/lib/rex/ui/text/color.rb +97 -0
  344. data/lib/rex/ui/text/color.rb.ut.rb +18 -0
  345. data/lib/rex/ui/text/dispatcher_shell.rb +382 -0
  346. data/lib/rex/ui/text/input.rb +117 -0
  347. data/lib/rex/ui/text/input/buffer.rb +75 -0
  348. data/lib/rex/ui/text/input/readline.rb +129 -0
  349. data/lib/rex/ui/text/input/socket.rb +95 -0
  350. data/lib/rex/ui/text/input/stdio.rb +45 -0
  351. data/lib/rex/ui/text/irb_shell.rb +55 -0
  352. data/lib/rex/ui/text/output.rb +80 -0
  353. data/lib/rex/ui/text/output/buffer.rb +65 -0
  354. data/lib/rex/ui/text/output/file.rb +37 -0
  355. data/lib/rex/ui/text/output/socket.rb +43 -0
  356. data/lib/rex/ui/text/output/stdio.rb +40 -0
  357. data/lib/rex/ui/text/progress_tracker.rb +56 -0
  358. data/lib/rex/ui/text/progress_tracker.rb.ut.rb +34 -0
  359. data/lib/rex/ui/text/shell.rb +321 -0
  360. data/lib/rex/ui/text/table.rb +254 -0
  361. data/lib/rex/ui/text/table.rb.ut.rb +55 -0
  362. data/lib/rex/zip.rb +93 -0
  363. data/lib/rex/zip/archive.rb +91 -0
  364. data/lib/rex/zip/blocks.rb +182 -0
  365. data/lib/rex/zip/entry.rb +95 -0
  366. data/lib/rex/zip/samples/comment.rb +32 -0
  367. data/lib/rex/zip/samples/mkwar.rb +138 -0
  368. data/lib/rex/zip/samples/mkzip.rb +19 -0
  369. data/lib/rex/zip/samples/recursive.rb +58 -0
  370. metadata +435 -0
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..'))
4
+
5
+ require 'test/unit'
6
+ require 'rex/proto/http'
7
+
8
+ class Rex::Proto::Http::Packet::Header::UnitTest < Test::Unit::TestCase
9
+
10
+ Klass = Rex::Proto::Http::Packet::Header
11
+
12
+ def test_to_s
13
+ h = Klass.new
14
+
15
+ h['Foo'] = 'Fishing'
16
+ h['Chicken'] = 47
17
+
18
+ assert_equal(
19
+ "Foo: Fishing\r\n" +
20
+ "Chicken: 47\r\n\r\n", h.to_s)
21
+ end
22
+
23
+ def test_from_s
24
+ h = Klass.new
25
+
26
+ h.from_s(
27
+ "POST /foo HTTP/1.0\r\n" +
28
+ "Lucifer: Beast\r\n" +
29
+ "HoHo: Satan\r\n" +
30
+ "Eat: Babies\r\n" +
31
+ "\r\n")
32
+
33
+ assert_equal('Babies', h['Eat'], 'header')
34
+ assert_equal('Satan', h['HoHo'], 'header')
35
+ assert_equal('Satan', h['hOhO'], 'header')
36
+
37
+ assert_equal("POST /foo HTTP/1.0\r\n", h.cmd_string, 'cmd_string')
38
+ end
39
+
40
+ def test_just_cmdstring
41
+ h = Klass.new
42
+
43
+ h.from_s("POST /foo HTTP/1.0")
44
+ assert_equal("POST /foo HTTP/1.0\r\n", h.cmd_string, 'just cmd_string')
45
+ end
46
+ end
@@ -0,0 +1,394 @@
1
+ require 'rex/proto/http'
2
+
3
+ module Rex
4
+ module Proto
5
+ module Http
6
+
7
+ DefaultProtocol = '1.1'
8
+
9
+ ###
10
+ #
11
+ # This class represents an HTTP packet.
12
+ #
13
+ ###
14
+ class Packet
15
+
16
+ #
17
+ # Parser processing codes
18
+ #
19
+ module ParseCode
20
+ Completed = 1
21
+ Partial = 2
22
+ Error = 3
23
+ end
24
+
25
+ #
26
+ # Parser states
27
+ #
28
+ module ParseState
29
+ ProcessingHeader = 1
30
+ ProcessingBody = 2
31
+ Completed = 3
32
+ end
33
+
34
+ require 'rex/proto/http/header'
35
+
36
+ #
37
+ # Initializes an instance of an HTTP packet.
38
+ #
39
+ def initialize()
40
+ self.headers = Header.new
41
+ self.auto_cl = true
42
+
43
+ reset
44
+ end
45
+
46
+ #
47
+ # Return the associated header value, if any.
48
+ #
49
+ def [](key)
50
+ if (self.headers.include?(key))
51
+ return self.headers[key]
52
+ end
53
+
54
+ self.headers.each_pair do |k,v|
55
+ if (k.downcase == key.downcase)
56
+ return v
57
+ end
58
+ end
59
+
60
+ return nil
61
+ end
62
+
63
+ #
64
+ # Set the associated header value.
65
+ #
66
+ def []=(key, value)
67
+ self.headers[key] = value
68
+ end
69
+
70
+ #
71
+ # Parses the supplied buffer. Returns one of the two parser processing
72
+ # codes (Completed, Partial, or Error).
73
+ #
74
+ def parse(buf)
75
+
76
+ # Append the incoming buffer to the buffer queue.
77
+ self.bufq += buf.to_s
78
+
79
+ begin
80
+
81
+ # Process the header
82
+ if(self.state == ParseState::ProcessingHeader)
83
+ parse_header
84
+ end
85
+
86
+ # Continue on to the body if the header was processed
87
+ if(self.state == ParseState::ProcessingBody)
88
+ if (self.body_bytes_left == 0)
89
+ self.state = ParseState::Completed
90
+ else
91
+ parse_body
92
+ end
93
+ end
94
+ rescue
95
+ self.error = $!
96
+ return ParseCode::Error
97
+ end
98
+
99
+ # Return completed or partial to the parsing status to the caller
100
+ (self.state == ParseState::Completed) ? ParseCode::Completed : ParseCode::Partial
101
+ end
102
+
103
+ #
104
+ # Reset the parsing state and buffers.
105
+ #
106
+ def reset
107
+ self.state = ParseState::ProcessingHeader
108
+ self.transfer_chunked = false
109
+ self.inside_chunk = false
110
+ self.headers.reset
111
+ self.bufq = ''
112
+ self.body = ''
113
+ end
114
+
115
+ #
116
+ # Reset the parsing state but leave the buffers.
117
+ #
118
+ def reset_except_queue
119
+ self.state = ParseState::ProcessingHeader
120
+ self.transfer_chunked = false
121
+ self.inside_chunk = false
122
+ self.headers.reset
123
+ self.body = ''
124
+ end
125
+
126
+ #
127
+ # Returns whether or not parsing has completed.
128
+ #
129
+ def completed?
130
+
131
+ return true if self.state == ParseState::Completed
132
+
133
+ # If the parser state is processing the body and there are an
134
+ # undetermined number of bytes left to read, we just need to say that
135
+ # things are completed as it's hard to tell whether or not they really
136
+ # are.
137
+ if (self.state == ParseState::ProcessingBody and self.body_bytes_left < 0)
138
+ return true
139
+ end
140
+
141
+ false
142
+ end
143
+
144
+ #
145
+ # Build a 'Transfer-Encoding: chunked' payload with random chunk sizes
146
+ #
147
+ def chunk(str, min_size = 1, max_size = 1000)
148
+ chunked = ''
149
+
150
+ # min chunk size is 1 byte
151
+ if (min_size < 1); min_size = 1; end
152
+
153
+ # don't be dumb
154
+ if (max_size < min_size); max_size = min_size; end
155
+
156
+ while (str.size > 0)
157
+ chunk = str.slice!(0, rand(max_size - min_size) + min_size)
158
+ chunked += sprintf("%x", chunk.size) + "\r\n" + chunk + "\r\n"
159
+ end
160
+ chunked += "0\r\n\r\n"
161
+ end
162
+
163
+ #
164
+ # Converts the packet to a string.
165
+ #
166
+ def to_s
167
+ content = self.body.dup
168
+ # Update the content length field in the header with the body length.
169
+ if (content)
170
+ if !self.compress.nil?
171
+ case self.compress
172
+ when 'gzip'
173
+ self.headers['Content-Encoding'] = 'gzip'
174
+ content = Rex::Text.gzip(content)
175
+ when 'deflate'
176
+ self.headers['Content-Encoding'] = 'deflate'
177
+ content = Rex::Text.zlib_deflate(content)
178
+ when 'none'
179
+ # this one is fine...
180
+ # when 'compress'
181
+ else
182
+ raise RuntimeError, 'Invalid Content-Encoding'
183
+ end
184
+ end
185
+
186
+ if (self.auto_cl == true && self.transfer_chunked == true)
187
+ raise RuntimeError, "'Content-Length' and 'Transfer-Encoding: chunked' are incompatible"
188
+ elsif self.auto_cl == true
189
+ self.headers['Content-Length'] = content.length
190
+ elsif self.transfer_chunked == true
191
+ if self.proto != '1.1'
192
+ raise RuntimeError, 'Chunked encoding is only available via 1.1'
193
+ end
194
+ self.headers['Transfer-Encoding'] = 'chunked'
195
+ content = self.chunk(content, self.chunk_min_size, self.chunk_max_size)
196
+ end
197
+ end
198
+
199
+ str = self.headers.to_s(cmd_string)
200
+ str += content || ''
201
+ end
202
+
203
+ #
204
+ # Converts the packet from a string.
205
+ #
206
+ def from_s(str)
207
+ reset
208
+ parse(str)
209
+ end
210
+
211
+ #
212
+ # Returns the command string, such as:
213
+ #
214
+ # HTTP/1.0 200 OK for a response
215
+ #
216
+ # or
217
+ #
218
+ # GET /foo HTTP/1.0 for a request
219
+ #
220
+ def cmd_string
221
+ self.headers.cmd_string
222
+ end
223
+
224
+ attr_accessor :headers
225
+ attr_accessor :error
226
+ attr_accessor :state
227
+ attr_accessor :bufq
228
+ attr_accessor :body
229
+ attr_accessor :auto_cl
230
+ attr_accessor :max_data
231
+ attr_accessor :transfer_chunked
232
+ attr_accessor :compress
233
+ attr_reader :incomplete
234
+
235
+ attr_accessor :chunk_min_size
236
+ attr_accessor :chunk_max_size
237
+
238
+ protected
239
+
240
+ attr_writer :incomplete
241
+ attr_accessor :body_bytes_left
242
+ attr_accessor :inside_chunk
243
+ attr_accessor :keepalive
244
+
245
+ ##
246
+ #
247
+ # Overridable methods
248
+ #
249
+ ##
250
+
251
+ #
252
+ # Allows derived classes to split apart the command string.
253
+ #
254
+ def update_cmd_parts(str)
255
+ end
256
+
257
+ ##
258
+ #
259
+ # Parsing
260
+ #
261
+ ##
262
+
263
+ def parse_header
264
+
265
+ head,data = self.bufq.split(/\r?\n\r?\n/, 2)
266
+ return if not data
267
+
268
+ self.headers.from_s(head)
269
+ self.bufq = data || ""
270
+
271
+ # Set the content-length to -1 as a placeholder (read until EOF)
272
+ self.body_bytes_left = -1
273
+
274
+ # Extract the content length if it was specified
275
+ if (self.headers['Content-Length'])
276
+ self.body_bytes_left = self.headers['Content-Length'].to_i
277
+ end
278
+
279
+ # Look for a chunked transfer header
280
+ if (self.headers['Transfer-Encoding'].to_s.downcase == 'chunked')
281
+ self.transfer_chunked = true
282
+ self.auto_cl = false
283
+ end
284
+
285
+ # Determine how to handle data when there is no length header
286
+ if(self.body_bytes_left == -1 and self.transfer_chunked != true)
287
+ if(self.headers['Connection'].to_s.downcase.include?('keep-alive'))
288
+ # If we are using keep-alive, but have no content-length and
289
+ # no chunked transfer header, pretend this is the entire
290
+ # buffer and call it done
291
+ self.body_bytes_left = self.bufq.length
292
+ elsif(not self.transfer_chunked and not self.headers['Content-Length'])
293
+ # RFC 2616 says: "The presence of a message-body in a request
294
+ # is signaled by the inclusion of a Content-Length or
295
+ # Transfer-Encoding header field in the request's
296
+ # message-headers."
297
+ #
298
+ # So if we haven't seen either a Content-Length or a
299
+ # Transfer-Encoding header, there shouldn't be a message body.
300
+ self.body_bytes_left = 0
301
+ else
302
+ # Otherwise we need to keep reading until EOF
303
+ self.body_bytes_left = -1
304
+ end
305
+ end
306
+
307
+ # Throw an error if we didnt parse the header properly
308
+ if !self.headers.cmd_string
309
+ raise RuntimeError, "Invalid command string", caller
310
+ end
311
+
312
+ # Move the state into body processing
313
+ self.state = ParseState::ProcessingBody
314
+
315
+ # Allow derived classes to update the parts of the command string
316
+ self.update_cmd_parts(self.headers.cmd_string)
317
+ end
318
+
319
+ #
320
+ # Parses the body portion of the request.
321
+ #
322
+ def parse_body
323
+ # Just return if the buffer is empty
324
+ if (self.bufq.length == 0)
325
+ return
326
+ end
327
+
328
+ # Handle chunked transfer-encoding responses
329
+ if (self.transfer_chunked and self.inside_chunk != 1 and self.bufq.length)
330
+
331
+ # Remove any leading newlines or spaces
332
+ self.bufq.lstrip!
333
+
334
+ # Extract the actual hexadecimal length value
335
+ clen = self.bufq.slice!(/^[a-zA-Z0-9]*\r?\n/)
336
+
337
+ clen.rstrip! if (clen)
338
+
339
+ # if we happen to fall upon the end of the buffer for the next chunk len and have no data left, go get some more...
340
+ if clen.nil? and self.bufq.length == 0
341
+ return
342
+ end
343
+
344
+ # Invalid chunk length, exit out early
345
+ if clen.nil?
346
+ self.state = ParseState::Completed
347
+ return
348
+ end
349
+
350
+ self.body_bytes_left = clen.hex
351
+
352
+ if (self.body_bytes_left == 0)
353
+ self.bufq.sub!(/^\r?\n/s,'')
354
+ self.state = ParseState::Completed
355
+ return
356
+ end
357
+
358
+ self.inside_chunk = 1
359
+ end
360
+
361
+ # If there are bytes remaining, slice as many as we can and append them
362
+ # to our body state.
363
+ if (self.body_bytes_left > 0)
364
+ part = self.bufq.slice!(0, self.body_bytes_left)
365
+
366
+ self.body += part
367
+ self.body_bytes_left -= part.length
368
+ # Otherwise, just read it all.
369
+ else
370
+ self.body += self.bufq
371
+ self.bufq = ''
372
+ end
373
+
374
+ # Finish this chunk and move on to the next one
375
+ if (self.transfer_chunked and self.body_bytes_left == 0)
376
+ self.inside_chunk = 0
377
+ self.parse_body
378
+ return
379
+ end
380
+
381
+ # If there are no more bytes left, then parsing has completed and we're
382
+ # ready to go.
383
+ if (self.transfer_chunked != 1 and self.body_bytes_left <= 0)
384
+ self.state = ParseState::Completed
385
+ return
386
+ end
387
+ end
388
+
389
+ end
390
+
391
+ end
392
+ end
393
+ end
394
+
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..'))
4
+
5
+ require 'test/unit'
6
+ require 'rex/proto/http'
7
+
8
+ class Rex::Proto::Http::Packet::UnitTest < Test::Unit::TestCase
9
+
10
+ Klass = Rex::Proto::Http::Packet
11
+
12
+ def test_junk_headers
13
+ srand(0)
14
+ h = Klass.new
15
+ h.headers.cmd_string = "GET / HTTP/1.0\r\n"
16
+ h.headers['TestMe'] = 'bob'
17
+ h.headers.junk_headers = 1
18
+ expected = "GET / HTTP/1.0\r\nX-v1AD7DnJTVykXGYYM: BmnXuYRlZNIJUzQzFPvASjYxzdTTOngBJ5gfK0XjLy3ciAAk1Fmo0RPEpq6f4BBnp5jm3LuSbAOj1M5qULEGEv0DMk0oOPUj6XPN1VwxFpjAfFeAxykiwdDiqNwnVJAKyr6X7C5ije7DSujURybOp6BkKWroLCzQg2AmTuqz48oNeY9CDeirNwoITfIaC40Ds9OgEDtL8WN5tL4QYdVuZQ85219Thogk775GVfNH4YPpSo2PLmvd5Bf2sY9YDSvDqMmjW9FXrgLoUK2rl9cvoCbTZX1zuU1dDjnJJpXDuaysDfJKbtHn9VhsiiY\r\nX-FokALi: 1QI9BRwj4bo0kwZDn8jyedxhSRdU9CFlMs19CvbVnnLWeRGHScrTxpduVJZygbJcrRp6AWQqkeY0DzI4bd7uXgTIHXN6R403ALckZgqOWcUSEWj6THI9NFAIPP1LEnctaK0uxbzjpS1ize16r388StXBGq1we7Qa8j6xqJsN5GmnIN4HQ4W4PZIjGRHUZC8Q4ytXYE\r\nX-sxXe2ZUhl: Xbdhz13zW2HpxJ2AT4kRU1wDqBUkEQwvKtoebrfUGJ8bvjTMSxKihrDMk6BxAnY6kjFGDi5o8hcEag4tzJ1FhH9eI2UHDVbsDmUHTfAFbreJTHVlcIruAozmZKzi7XgTaOgzGhs75ytpE5dbRjCUt5P3kpExyNetXijJa3a2WMPiazmuQ98v6oAKLNHeGt1ePpm1rSHcBpCycOlb2kfdy8udyhMgpQCIz9Kwab44BAFYiPD8ulrTYGUGczGCccml7FtJk2NV7fRjtz6IZVtlWQZu3lBFGMaK72OIHtFv7qDKy5bZD9OSF6ERFeYDFok6x3YhShOxH1ruw0hRdM2u2gizX8Zuyr0puAM2JSEHDwMl0twtSzxHaxudDKUqB3UQqycaX0wCmJC0spZ81kaEpKMohlng6hajZyYSUecISZYnq7cYSDsTt2AKDGbj5GTiyymUr2AktpChMP2hXMFmBKG9GmmLyVyyzCMdJzIF01rBrPMvMV4SZNecspVGkwoaeFPll7xfgwQgKMdAdanWTFkTkFcMaxTMmH0QdAXPK8D9DQwJU0l44wR15JsPmOhEQkHXbuH9Wie2QbvvyLXOneai2RjHt7wlE1NlTrIgRF8kB9dFQm4oWeTEUqK7DW8l6dpo8Rzo7qedheulYQjnd8BXIAXlvaZZGY3PlpRQwruF2TvWtLLhH3awHv\r\nX-gkSXVCIKFmmkB17kFFmjYxPUyJ3: xYeCTDNLNkRaGviVUq65RlZ0V3kEviLihuTwLhZhftGZYtmzQXaDau6dCF5HPOj0n2Hzm5zd3xLDN63Y784E1zW5dmLOSZsDlHdOLJLQ87n7BS1cAVYJISLc1zR3PDqYVc6VO\r\nX-BMLZnLatiBQBQhhsmoIN: TygXEfWAlfPTPz5MtK0pQGVeDQABygr7SS5WPPcHbY56YMNSOOUH3sr1bsP9XLNdfuSEcBxxX5QpawCvRUmAGsWPKiom2Vi1gqsjp5nb7wK\r\nX-RDleXdm7e: Cd8Hz0JXAwRozVeaPwRKRDnJdDHQiE9akGgR321l3bzO7WfI4dcfi6RcvQI73sHMgUrLdoAUtcNlv9nyEuM53lwEpkQSle1ujwAx5JyhwxMG8zkjmkeyTmsjOdz84RDdbDh1z2bk4VnqKdxd96YyQAki7NB7CCT06MenVNxazMxABkKqgc6CcBNTvRkH1GJPSd18qSCdRj4T\r\nX-XMjt4CUDRsmqKlqovbEzW: jeHYYvPKTNn4lnSH8Ygsn0ov0kqQ0aoQugeUXPsT33ibtiRXbNwXeF5nhxic0BEVI8yh2jwjZFBjHBBHZkNsybgrTitkQwq5rDITuA0UgirFVYC99HsLzc2fBQySOVvvFhqCbo3TPHsdjhwxQ4Y6Fz69qTRtgWhmJFM9q3Q7RE8ZOt91RdGcKFkkU3yyW1Kr7e7Ozw494BoHFP3p0gXOidzZ1EA7aUF6YRE4gxRIJkfeJswjgO9Xg4crhyusIl4CRPDVwydl4WSH3xa4EtZa8zvTOS5gbkmUsDSNzxfhSMvbniHetQBYQtblyYwMEwzuoOxKbOmNEWPdOqZLfbWurU39CZ94Af4uGSWu7ZNMlTf3c74Too5Zvdc0qKURAnmiBwWt6xWncBVCgyGmj1kXz6SmZuPxbVBJzRLA3D592kUTvFU9EpQQ5FgWDIcpKmcfsLibxHnm36FJYMoh7OtPEW0CHtIFnPPpZWZZTdJL9janSIBjyxu3KKYfrbNO3FXqnxlmL14rYRVeSZdlxoxqfnL41OgB51Bk6ZMIyMYTDKH0cOIujjRX911MtH6vuneTqtyBrSO7Zl44IyiaLsLokxMRfKwKLdiKMxnwKC5vLuz0p6bDQANmEDTRQHYLW8bCIIZm0hYVEfzLlHW8q7f2JzzSXTZ5FZtvYz7sa4\r\nX-r5geOHg9B2v8t2raPEKVnqreWA: 6Mbr29vWf0iiqE6kTsRwvGGwJcN4JVCJu4kc0AK8NrClHXeRDviQzSy9qScj1axnquFcrTKKJbjLgmfzWb5Vh9spzrjp6X9o0X6Ipt8vPkBelqATGdDfdQDa9GplLR39rDUb3cOOQj1mrbmXU7XigBWV5EtonYWR0aIFhW6SKdLeH6eqVHZs22TZt5qD0UxT5lh8sZH8lU6iQtonhhBJXEYGhy8Y90735Kdv4cYDSVGUV3baZAuD1lH4QLLsC2FR69OFORpuseiDAdsssz9ARdbiyzk7Ve4lRmPBPpWtRs1WNyvCLJyo2zvEKxG2sIIIslSCFd5lkqdbR6LxIYDwL5yP5D2k8nVd1D4L3PtaPhL3Fe6E7glr98td6bnbdILhOmLK2ZgyoGeW7LjUEEx0d9bvToaaJyfeRH4zjJcvw3H1D7HIlFh3cumxI6BCQ9CLfKUkO40HdFOyuPzgX5bGJ4BLX8Go8kMjF6MSABUNawrVONoDpRFabrtpNtw46RWfZcNHaRErve9c5I6bGH134a7LldxUd3493cX5JAmTHymD8el4pF7Qa9fGZLRffUan1yKmE7nPNjm7LnLw2k\r\nX-Lzi6QcJlIRwscZe7l77e576: MBbKD9Qb8GAHZD740ksVx2IvmqhkEbNNpIGeMiDoQFo3d1WlX76kr7iGGYMRfwlAKxsEf8KdhpwNTpMszrQ4ylOkyEyvAxlLsFouQQKFXvDmwSeQfqvVh3KsfTCTfyTnn9hs0s2e6nMQQGEtU6eM71haSG4CauZNb5ltVr4F5xZM0Gv9JKIaQfelmw8GwG3BvB9VuAWkaUUnixu9ebkJI0UXwn7rqN4v5JbaliGptlG6VDLqLdOTarQj0RQK58JjZazPbEmVnx1XsmrrWcu\r\nX-GNNRo9eESwCbIrPz: veNcuOyuthE0K0SkI36JuNMdOoNJu8MldtLspxY7IP2gsQyzsyxLPZVWRc6bsIbcnrnje0p2J20rRyQAaH2S6L56MNIoSRqsiLXGOu2yrBOlG5vsJDJ707ieBmOQeyNWujXldtqaSWGKrBJawPRTTBbzkjJpN1GYK5rlFo0POVAjhOGY2DElofbypDipNxRqotKmqDb8PyikqnysU0ZLsRFT\r\nX-EfdqybgrpSdN: sJ2IZhRxvQxHeQW7lJuMY91W4OthEF9MpMAFWphxzBKG6QHbmrUpSzqGmixKnoobe7ki7Zb46fwrDAl3nMULM4ybv5VsMvRnfvd3BlAXNIU1SQNIGbljoaeM5tQ6XyqI32Q19SKPm9YkvADaUvvhYSoJIHcvpTWD3O3CXrYUj6ugiqclkS3qjnjBdUljuibx7OqebzEEGppDnskbNsAKdOAAg0LdFF5eSqQ3RLJJaMAnc2NX65wbrZUvMYFiM7rP7VkxsMwiFU8fiXTVv6GEJYvgKabQiW9ccxOlZFCjLzNj4feFdb51B9oacnnhpvtg5E2ALzjEaPxcqQ0G4fC8RyBghmEeE7PV5zmKQCu9uugnX9BkZIvbAjav0qWfBdDDi0kquUpFYT2lDTXweeZHqMEwbMvK8r1uKzrGHAzigXAHeSgCmMA8IDNaDmGGU6CVv06uSQ5rhqFdPZt1Yk85A9NMGxxDgzxjNLREXvKm01mwkdZjHAAIDGl8HzNS4RDIvr9DsL1xyKrPbmjS91jVc7hZKB6VZK4pNzCSUHo4VluTa3GAI8V7vlDuopc53knBz9tF6bfoJ14HjvFpc26VLDSjupRvb2vJTHHlrsuuihK3FcugTnefvvBgox3t3u2AlVWbFtjtj8oDcb7JrDrLzWqqEd8sCeFvMRP4pYVoD8uwfGzhvLnID3r2np2ZtGHodFmDHyrXYydzR4rhwOqqQv1Bq1Az4PQIpU92rZA7xnCGDeNU0LLFwQNIbGs2qEopP8AnlGzd6vZMA0yxc6HBswyHoao9wuWOfV0HkQGqUmEQiv47vOvnPYOK2EUpo0L81dD0sa8bC8C9Xtc51Sv7BEkRYZrMiV4yJkrpGRf6yvsGyQecLgmZmdCTMSApWRqEESFOKydTiDIaSEHqdjPutD6DGClY37jDHbyCwHKt7w5F0oW0rBGcFoKHdkSv87Cpdgx80ZkTg1ba44ctXSFBViBdtiOqeJ2bHMdkmcxVXlUNtoyp2BI\r\nContent-Length: 0\r\nTestMe: bob\r\n\r\n"
19
+ assert_equal(expected, h.to_s, 'junk headers')
20
+ h.headers.cmd_string = "HTTP/1.0 OK\r\n"
21
+ h.headers.fold = 1
22
+ expected = "HTTP/1.0 OK\r\nX-nsJxRxZX5o5zKaNf8VhtBgr3Gieuamk:\r\n\twM0v0nww3ZA8mepvkmcqXPmmWwHlyCNUudg03Tss4WWsl8i92mVcwi9B2tuR0irNRfVitBFvymfcm6ywElHD2VV5aCcvglhj6gnRJjsWFWJ2B9rFqEH2Tyzm13NLXm21Lo1fD39CHCZuFQyIR4ycO4GN4cDs7mvEALmGzU4GQAD7Fv9n7QZ5ebLoAhZ0Owi0oyyr3mTqimVUajbDZ8HEE1JEhxKX5wgNVcXwF9CAJHdVQOTlaMPTSqCQ4LjJ5JeWqUpTEuPhAvPNJxqKxninwssqBIALaerqTVvB68ScL7x0nJYEa0r2VOdBOAPhg9zlFe2pvy6J1HeVepIBtVI5tx0AbywZdHafO5TIndXNoBZYepQ8LnHmVYlr7kgJxoQj3Dnl6Do6jBDLDu7MgnyA22vXH7BiN4eVRXjhGYi3o5mJYdFwwZEumA7OJkvycPCkHRfrpPc202q4fW5yX8EARGELgQC6Knm28n93AJLs0RkpvFpwmkE7xLndrtLqgBsviqqsKq8ounPtaposwQrcAs9CW8YsTeNHTj11dUIKpiu9L9I13V0EvH44VWGTrGg7lWpV0LrDgdVRFvbBhorn5rzleS2P8ztodE4w4qUQ1VCUt4YrUtPhYYob9DTMysKJc1ufXNFtoHpuQynjqc\r\nX-RlBRei0DhrZBi4xnoSp2VvcBpm:\r\n\tPcZ7y1WbNhO1IEu2VtcWOAyl2yJh0oozHady5RKrhBm9TdGFEC3ooQHoYX06WpG4OznYfUSjgUYgbs6kSWifyS8OHLK56mpWAiRq0GDo7bMnVZAri9BwrlurZXqzE0HdBXXYZFWxQfwAyDhfG0AIYGLE1lH3ZzqFlE8q5MQ5FNLWqnAYwb3eYcYe50ug9ujWvIDk0O8k7R7TYYjyBMUHWs4PghNBDn4kmb6itmvZQwyJZAP1Qq9kHXxomtlxlEiW86xe7hbHNZlfk6xv1nISUZndCoyRonhDa1vYxez5BqSHrF6olTiVkYeBAYtv4EAk8y3UEF9OWPTM9ng5eUU6FKYLV8GB0NPvrVDdJ2Y3k8634xUl19uToDlDUmehZps3WlC5buzl64c8j\r\nX-hZ2KnIRZHzdnpUhx48KM:\r\n\tCgY1FTARXuU6kkMskPl2Yt0U68HuXUFHkvJFZhUAhTJCQX96yZ6qQRo8R69xlpmMGvYhOFJlmLZQT96Xy5wJqppna32qLHbg9eWdgCWvovY2zOCDhqkAYym3M9PaX4dQSth2D6mH5UwYC8KziYAGNmZbvFt9pXz2YNVNC4pB6t0A58OkHwJsxEQQ5QDo2Cg5GVcWb5xEEfCZeLKCLMUJ6jzGfbKwIZlPaFSAkglSNTCv5opAmAJxDFR8StLA1mspRsSGP28nAlkHtLEGm8oGQiQg4ckgxwIVyYQVKgI7lGaqb6tZUUNiEwOYBnrNkhMQ5Fh7fIh2AgfCqbQXCHltUAHZYBjeiciVXRFDZV7G9TWXVMW8KOs5pFn1zK9aaTu0QBTOJs8jjIa4zotN9Zs0OwN6Gr8ImzOucdfeIrC4P44cilqmlYFO4iLQfyM67A9i5A45QEkDFe7yqUwtPlp1cb377t39hLbiYNHYBjSuo3BqbPPpNG6gc40GOfGh66uazg87ufHxnBFlbmtXMJddNXYJEl4LW8Yloo01iuh6NhHMJudM\r\nX-w2ji68BRrw3J359QDpWvUYh76UVk:\r\n\tMaC66WuT5SifDAbwuW0D8gLwYcoJCO70KEJtar9Ilois2mbw66x1Tjk8KxSEYPxeNzQ3otL9iRGYddCL6uoRnJraU5EqC0nT0HfgE0bYq3Is1ambirMvIo4tgAvRMQ14LPczAuck8SRZoZEKhWhuSjwUF6jvNoneLI5aofaylT38fGzlLPs1EjyRsZ26MAgGjpoT7jdqXZU7sImWny1PELaLaMcAF5mNW77Y9aFSsucDXJzFahBgU59vbqMftb6DzUKzJFN8oR6tZDA2O0OXGPF2AnH9Rg6dfPLrfSrmWH0jTFxArBy186O05SpGkrxgLX7YyI1TCycm4urh0NthKzX9NzueArHDuAfIDLXUBGu8Eqj8vWemL0i3DxqAGhdVO0WbDxenuXYrNggy2xZJlsRXj75jiUFUGIA9sZmHJ6GdFkdnTvWDH4dUISWWVun4i8iQNc47Nh6aN59K6XVbt38VfmSb9aXHNUejKjFlWhSAfsetCVSQjMI8a8jJfsxrvAt82Ucmkehjp2auSYYOcypTCqx6dBV2R3ZO5WPySL2YFrG9p8rvMMtlSJI1oIAgM0U571yPX2sRXJtigpG3bjTmBhlhhDWl6yhDNiPrhepcJLZw85J8gVkLj45sCgck4Kjd9rpXldh9jqQUhDftkIYZZlKgDVoNgqFVoNbiA35snwvz7Rg4gLqGShz0FR2KMpRfDoiqeGAEEsAzjWendWXxa24LCVMQCbM155pjA9NlS\r\nX-KTsbJwm6:\r\n\tvmxmFWMC7AxYqdcgEIStcHIQWqPUwVXhCwaLYPvZFW2zidMs68UuhLueu4LGfipVKbRm5GL9wdNuT5H5QGoPCKpqodKKfR7jkk9RxVbZv2Ih6vJLwvcQwCIh7wOoBufWtAMo4Acf8c845Tzgqr3EyRdmaZSzUv5pHicgxmMYuuHJ8nthej8inCd4nWj1AaE1rvJGdFB8WadFQasaOYITd37LuVC95a1wrE5WSmBE9nTbHw1diY5MFsNwmPAxzEtWe9g3ftkD8jTiRsD8IBPpI40WKsMDWMZ1aopA37m0bokVVGMHD4Kb5xxYxuJsskIJjBmUtZsZFAn6GGnyRLRle5yxJMRkgD52M1vl0Hu9FRSSRhKxJaEoZylHhR8vnwRmIm6X3ilbECtxZGKTtPU1P2jvHo8kxcsuJkXjcSOnUkIwnN3roV7v9ggeJb9c4rXc4CUWgH4VUTZvlYT3qNsbWbD5hdVCmYRNJpZlOdvH6bcWEDYna6J7p03HULGctCn56bfjMAXF3AjKdRwoS70v9KTlN5DkDjH2KUcIIRR8Ffd7Q50WjyjQ1bgvCLSYYAt8IXB7dvmmsyyRT9ZF7uVihmybplx8ETzhVEzZ9zH4kzf99vC5ZM0959Fje00JxzR4dL9ir46rh6cWZbRhh0ZU7HAMxHsXmC7JeyaMSnxd6um3GC8xN4zQfIpnfZSTcB5azeV0Lji92A5Yugo6Edz240S0lnCzhZbtWqxG1dgnXlKJBADZ9oMDibxBImhrfdw88tNOcQjYtGS4h\r\nX-IOSp7nYMJwhxhyYPunG9RIvBHUoI0A3pC:\r\n\tW8KeIV35tDFbaMAD9rgoUOYDgJGD6cDPg\r\nX-sc1yFBRvIJ0:\r\n\twpYEHFnUDBJaBowmuVMGgqUMWUthgJ7kDpIczNXHzMCktNXn752JnPLJBaLfw6LB5IZ4ehsXUxIAiemUlW9qwWpUrHB4teMF4VFQrXolvwnomr6wAJ8P0s1EcxjUGpfZQEuNhRvBZvWqWRDTud2EUtesPh8ETl0ARRxnoSFiD6A3jZUdBOsmEGRd94BQCOqxYF5VIIhFg1ArzGOlcQ1d0Sd46lDqKpnggcOfi9ljDNSR9iiTyELVDxiTaIpOjMRqXRgxLoCwWEpqP78RnNfj8xD6tZzcSsfXuKNNNTBDMIzK9G0f3rfVNHtcSd9ayPuBtzZS1nwtWbLsmxAJWF9XGWXB33afT9ZoHL753R2oALkjN8ImKZpJ2UE7nQSuOXu0j7weDKgVp6uhShzM0CZqezcpRO78NhW09YeKDfxgNxnAuYUrpabXaJhapvfofIxkReB6d1QUI3kd7rsPNZlQyLuChcapBaITb5jWZYsUk1YeM03q4cyEBFsV6xYI4s6w6egVD51URRLS5j6VtrizhJbXpz7kwhLtIrudhvOeufXrVCakuJB4DRBweihvwK5GFqGpmF8e7IR3WDPmu0eGdWKcHbwTCzHMzTzeebPvX6eTINmmCqzEmF71uyhYscV9sOy0EpRPZkMm7deiTqTfpkpLHFNiuggcMdzKq3Jzx7TWXe80Nyf68QSBPgOJGzvDG2PdVzK6NbaapE7dwc98Pu5bogtxOEZgMsp7q0N0y4yxFXl0ec2VTY5vXtKegVo2eGZF3fvubZhbQQPei7FIQmzncFATX8e0umoiRPKSobz8qmOvR83psDw1ZYsfX9PV8dWYDJmAPspOFR6pDwTSrxxBHIf8OOUSvjsonfBa5Ympf4Lw7jLxvxxyvytdky5Kqa8L5pH90gbH3U\r\nContent-Length:\r\n\t0\r\nTestMe:\r\n\tbob\r\n\r\n"
23
+ assert_equal(expected, h.to_s, 'junk headers')
24
+ end
25
+
26
+ def test_pipeline
27
+ req_normalized =
28
+ "GET / HTTP/1.0\r\n" +
29
+ "Foo: Bar\r\n" +
30
+ "Content-Length: 10\r\n" +
31
+ "\r\n" +
32
+ "Super body"
33
+
34
+ req = req_normalized + req_normalized
35
+
36
+ req_base = req.dup
37
+ req_fold = req.gsub(/:/, ':' + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t") + "\r\n" + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t"))
38
+ req_nocr = req.gsub(/\r\n/, "\n")
39
+ req_junk = req + "junk"
40
+
41
+ { 'base' => req_base, 'fold' => req_fold, 'no cr' => req_nocr, 'extra junk' => req_junk }.each_pair { |name, test|
42
+ h = Klass.new
43
+ h.auto_cl = false
44
+ assert_equal(Klass::ParseCode::Completed, h.parse(test), "parse #{name}")
45
+ assert_equal(req_normalized, h.to_s, "to string #{name}")
46
+ assert_equal(true, h.completed?, "completed parsing #{name}")
47
+ assert_equal('Bar', h.headers['Foo'], "first header #{name}")
48
+ assert_equal('10', h.headers['Content-Length'], "second header #{name}")
49
+ assert_equal("Super body", h.body, "body #{name}")
50
+ }
51
+ end
52
+
53
+
54
+ def test_chunked
55
+ req_start =
56
+ "GET / HTTP/1.0\r\n" +
57
+ "Transfer-Encoding: chunked\r\n" +
58
+ "Foo: Bar\r\n" +
59
+ "\r\n"
60
+
61
+ req_normalized = req_start + "Super body"
62
+
63
+ req = req_start + "1\r\nS\r\n1\r\nu\r\n1\r\np\r\n1\r\ne\r\n1\r\nr\r\n1\r\n \r\n1\r\nb\r\n1\r\no\r\n1\r\nd\r\n1\r\ny\r\n0\r\n\r\n"
64
+
65
+ req_base = req.dup
66
+ req_fold = req.gsub(/:/, ':' + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t") + "\r\n" + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t"))
67
+ req_nocr = req.gsub(/\r\n/, "\n")
68
+ req_junk = req + "junk"
69
+
70
+ { 'base' => req_base, 'fold' => req_fold, 'no cr' => req_nocr, 'extra junk' => req_junk }.each_pair { |name, test|
71
+ h = Klass.new
72
+ h.auto_cl = false
73
+ assert_equal(Klass::ParseCode::Completed, h.parse(test), "parse #{name}")
74
+ assert_equal(req_normalized, h.to_s, "to string #{name}")
75
+ assert_equal(true, h.completed?, "completed parsing #{name}")
76
+ assert_equal('Bar', h.headers['Foo'], "first header #{name}")
77
+ assert_equal('chunked', h.headers['Transfer-Encoding'], "second header #{name}")
78
+ assert_equal("Super body", h.body, "body #{name}")
79
+ }
80
+ end
81
+
82
+ def test_content_length
83
+ req =
84
+ "GET / HTTP/1.0\r\n" +
85
+ "Foo: Bar\r\n" +
86
+ "Content-Length: 10\r\n" +
87
+ "\r\n" +
88
+ "Super body"
89
+
90
+ req_base = req.dup
91
+ req_fold = req.gsub(/:/, ':' + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t") + "\r\n" + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t"))
92
+ req_nocr = req.gsub(/\r\n/, "\n")
93
+ req_junk = req + "junk"
94
+
95
+ { 'base' => req_base, 'fold' => req_fold, 'no cr' => req_nocr, 'extra junk' => req_junk }.each_pair { |name, test|
96
+ h = Klass.new
97
+ h.auto_cl = false
98
+ assert_equal(Klass::ParseCode::Completed, h.parse(test), "parse #{name}")
99
+ assert_equal(req, h.to_s, "to string #{name}")
100
+ assert_equal(true, h.completed?, "completed parsing #{name}")
101
+ assert_equal('Bar', h.headers['Foo'], "first header #{name}")
102
+ assert_equal('10', h.headers['Content-Length'], "second header #{name}")
103
+ assert_equal("Super body", h.body, "body #{name}")
104
+ }
105
+ end
106
+
107
+ def test_parse_connection_close
108
+ req =
109
+ "GET / HTTP/1.0\r\n" +
110
+ "Foo: Bar\r\n" +
111
+ "Connection: close\r\n" +
112
+ "\r\n" +
113
+ "Super body"
114
+
115
+ req_base = req.dup
116
+ req_fold = req.gsub(/:/, ':' + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t") + "\r\n" + Rex::Text.rand_base(rand(10) + 1,'',"\s","\t"))
117
+ req_nocr = req.gsub(/\r\n/, "\n")
118
+
119
+ { 'base' => req_base, 'fold' => req_fold, 'no cr' => req_nocr }.each_pair { |name, test|
120
+ h = Klass.new
121
+ h.auto_cl = false
122
+ assert_equal(Klass::ParseCode::Completed, h.parse(test), "parse #{name}")
123
+ assert_equal(req, h.to_s, "to string #{name}")
124
+ assert_equal(true, h.completed?, "completed parsing #{name}")
125
+ assert_equal('Bar', h.headers['Foo'], "first header #{name}")
126
+ assert_equal('close', h.headers['Connection'], "second header #{name}")
127
+ assert_equal("Super body", h.body, "body #{name}")
128
+ }
129
+ end
130
+
131
+ def test_to_s
132
+ h = Klass.new
133
+
134
+ h.headers['Foo'] = 'Fishing'
135
+ h.headers['Chicken'] = 47
136
+
137
+ assert_equal(
138
+ "Foo: Fishing\r\n" +
139
+ "Content-Length: 0\r\n" +
140
+ "Chicken: 47\r\n\r\n", h.to_s)
141
+ end
142
+
143
+ def test_from_s
144
+ h = Klass.new
145
+
146
+ h.from_s(
147
+ "HTTP/1.0 200 OK\r\n" +
148
+ "Lucifer: Beast\r\n" +
149
+ "HoHo: Satan\r\n" +
150
+ "Eat: Babies\r\n" +
151
+ "\r\n")
152
+
153
+ assert_equal('Babies', h['Eat'])
154
+ h['Eat'] = "fish"
155
+ assert_equal('fish', h['Eat'])
156
+ end
157
+
158
+ # XXX
159
+ def test_no_headers
160
+ h = Klass.new
161
+ h.from_s("GET / HTTP/1.0\r\n\r\n")
162
+ assert_equal("GET / HTTP/1.0\r\n", h.headers.cmd_string, 'cmd string')
163
+ end
164
+
165
+ end