librex 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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