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,57 @@
1
+ require 'thread'
2
+
3
+ module Rex
4
+
5
+ ###
6
+ #
7
+ # This module provides a uniform reference counted interface for classes to
8
+ # use.
9
+ #
10
+ ###
11
+ module Ref
12
+
13
+ #
14
+ # Initializes the reference count to one.
15
+ #
16
+ def refinit
17
+ @_references = 1
18
+ @_references_mutex = Mutex.new
19
+
20
+ self
21
+ end
22
+
23
+ #
24
+ # Increments the total number of references.
25
+ #
26
+ def ref
27
+ @_references_mutex.synchronize {
28
+ @_references += 1
29
+ }
30
+
31
+ self
32
+ end
33
+
34
+ #
35
+ # Decrements the total number of references. If the reference count
36
+ # reaches zero, true is returned. Otherwise, false is returned.
37
+ #
38
+ def deref
39
+ @_references_mutex.synchronize {
40
+ if ((@_references -= 1) == 0)
41
+ cleanup
42
+
43
+ true
44
+ else
45
+ false
46
+ end
47
+ }
48
+ end
49
+
50
+ #
51
+ # Called to clean up resources once the ref count drops to zero.
52
+ #
53
+ def cleanup
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,82 @@
1
+ require 'timeout'
2
+
3
+ module Rex
4
+
5
+ ###
6
+ #
7
+ # This module provides a set of methods for performing various blocking
8
+ # operations in a manner that is compatible with ruby style threads.
9
+ #
10
+ ###
11
+ module ThreadSafe
12
+
13
+ DefaultCycle = 0.2
14
+
15
+ #
16
+ # Wraps calls to select with a lower timeout period and does the
17
+ # calculations to walk down to zero timeout. This has a little room for
18
+ # improvement in that it should probably check how much time actually
19
+ # elapsed during the select call considering ruby threading wont be exactly
20
+ # accurate perhaps.
21
+ #
22
+ def self.select(rfd = nil, wfd = nil, efd = nil, t = nil)
23
+ left = t
24
+
25
+ # Immediately raise a StreamClosedError if the socket was closed. This
26
+ # prevents a bad fd from being passed downstream and solves an issue
27
+ # with Ruby on Windows.
28
+ rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
29
+
30
+ begin
31
+ orig_size = rfd.length if (rfd)
32
+
33
+ # Poll the set supplied to us at least once.
34
+ begin
35
+ rv = ::IO.select(rfd, wfd, efd, DefaultCycle)
36
+ rescue ::IOError, ::Errno::EBADF, ::Errno::ENOTSOCK
37
+ # If a stream was detected as being closed, re-raise the error as
38
+ # a StreamClosedError with the specific file descriptor that was
39
+ # detected as being closed. This is to better handle the case of
40
+ # a closed socket being detected so that it can be cleaned up and
41
+ # removed.
42
+ rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
43
+
44
+ # If the original rfd length is not the same as the current
45
+ # length, then the list may have been altered and as such may not
46
+ # contain the socket that caused the IOError. This is a bad way
47
+ # to do this since it's possible that the array length could be
48
+ # back to the size that it was originally and yet have had the
49
+ # socket that caused the IOError to be removed.
50
+ return nil if (rfd and rfd.length != orig_size)
51
+
52
+ # Re-raise the exception since we didn't handle it here.
53
+ raise $!
54
+ # rescue ::Exception => e
55
+ # $stderr.puts "SELECT(#{t}) #{[rfd,wfd,efd].inspect} #{e.class} #{e} #{e.backtrace}"
56
+ end
57
+
58
+ return rv if (rv)
59
+
60
+ # Decrement the amount of time left by the polling cycle
61
+ left -= DefaultCycle if (left)
62
+
63
+ # Keep chugging until we run out of time, if time was supplied.
64
+ end while ((left == nil) or (left > 0))
65
+
66
+ # Nothin.
67
+ nil
68
+ end
69
+
70
+ #
71
+ # Simulates a sleep operation by selecting on nil until a timeout period
72
+ # expires.
73
+ #
74
+ def self.sleep(seconds)
75
+ self.select(nil, nil, nil, seconds)
76
+
77
+ seconds
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+
3
+ # DEFAULTS
4
+ module Rex
5
+ class Test
6
+
7
+ $_REX_TEST_NO_MOCK = nil
8
+ $_REX_TEST_TIMEOUT = 30
9
+ $_REX_TEST_SMB_HOST = '10.4.10.58'
10
+ $_REX_TEXT_SMB_USER = 'SMBTest'
11
+ $_REX_TEXT_SMB_PASS = 'SMBTest'
12
+
13
+ # overwrite test defaults with rex/test-config.rb
14
+ def self.load()
15
+ file = File.join( ENV.fetch('HOME'), '.msf3', 'test')
16
+ begin
17
+ if File.stat(file + '.rb')
18
+ require file
19
+ end
20
+ rescue
21
+ # just ignore the errors
22
+ end
23
+
24
+ end
25
+
26
+ def self.cantmock()
27
+ if (!$_REX_TEST_NO_MOCK)
28
+ raise RuntimeError, "*** $_REX_TEST_NO_MOCK must not be set for this test ***", caller
29
+ end
30
+ end
31
+
32
+ Rex::Test.load()
33
+
34
+ end
35
+ end
@@ -0,0 +1,1029 @@
1
+ require 'digest/md5'
2
+ require 'stringio'
3
+
4
+ begin
5
+ require 'iconv'
6
+ require 'zlib'
7
+ rescue LoadError
8
+ end
9
+
10
+ module Rex
11
+
12
+ ###
13
+ #
14
+ # This class formats text in various fashions and also provides
15
+ # a mechanism for wrapping text at a given column.
16
+ #
17
+ ###
18
+ module Text
19
+ @@codepage_map_cache = nil
20
+
21
+ ##
22
+ #
23
+ # Constants
24
+ #
25
+ ##
26
+
27
+ States = ["AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DE", "FL", "GA", "HI",
28
+ "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN",
29
+ "MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH",
30
+ "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA",
31
+ "WI", "WV", "WY"]
32
+ UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
33
+ LowerAlpha = "abcdefghijklmnopqrstuvwxyz"
34
+ Numerals = "0123456789"
35
+ Alpha = UpperAlpha + LowerAlpha
36
+ AlphaNumeric = Alpha + Numerals
37
+ HighAscii = [*(0x80 .. 0xff)].pack("C*")
38
+ DefaultWrap = 60
39
+ AllChars = [*(0x00 .. 0xff)].pack("C*")
40
+
41
+ DefaultPatternSets = [ Rex::Text::UpperAlpha, Rex::Text::LowerAlpha, Rex::Text::Numerals ]
42
+
43
+ ##
44
+ #
45
+ # Serialization
46
+ #
47
+ ##
48
+
49
+ #
50
+ # Converts a raw string into a ruby buffer
51
+ #
52
+ def self.to_ruby(str, wrap = DefaultWrap, name = "buf")
53
+ return hexify(str, wrap, '"', '" +', "#{name} = \n", '"')
54
+ end
55
+
56
+ #
57
+ # Creates a ruby-style comment
58
+ #
59
+ def self.to_ruby_comment(str, wrap = DefaultWrap)
60
+ return wordwrap(str, 0, wrap, '', '# ')
61
+ end
62
+
63
+ #
64
+ # Converts a raw string into a C buffer
65
+ #
66
+ def self.to_c(str, wrap = DefaultWrap, name = "buf")
67
+ return hexify(str, wrap, '"', '"', "unsigned char #{name}[] = \n", '";')
68
+ end
69
+
70
+ #
71
+ # Creates a c-style comment
72
+ #
73
+ def self.to_c_comment(str, wrap = DefaultWrap)
74
+ return "/*\n" + wordwrap(str, 0, wrap, '', ' * ') + " */\n"
75
+ end
76
+
77
+ #
78
+ # Creates a javascript-style comment
79
+ #
80
+ def self.to_js_comment(str, wrap = DefaultWrap)
81
+ return wordwrap(str, 0, wrap, '', '// ')
82
+ end
83
+
84
+ #
85
+ # Converts a raw string into a perl buffer
86
+ #
87
+ def self.to_perl(str, wrap = DefaultWrap, name = "buf")
88
+ return hexify(str, wrap, '"', '" .', "my $#{name} = \n", '";')
89
+ end
90
+
91
+ #
92
+ # Converts a raw string into a java byte array
93
+ #
94
+ def self.to_java(str, name = "shell")
95
+ buff = "byte #{name}[] = new byte[]\n{\n"
96
+ cnt = 0
97
+ max = 0
98
+ str.unpack('C*').each do |c|
99
+ buff << ", " if max > 0
100
+ buff << "\t" if max == 0
101
+ buff << sprintf('(byte) 0x%.2x', c)
102
+ max +=1
103
+ cnt +=1
104
+
105
+ if (max > 7)
106
+ buff << ",\n" if cnt != str.length
107
+ max = 0
108
+ end
109
+ end
110
+ buff << "\n};\n"
111
+ return buff
112
+ end
113
+
114
+ #
115
+ # Creates a perl-style comment
116
+ #
117
+ def self.to_perl_comment(str, wrap = DefaultWrap)
118
+ return wordwrap(str, 0, wrap, '', '# ')
119
+ end
120
+
121
+ #
122
+ # Returns the raw string
123
+ #
124
+ def self.to_raw(str)
125
+ return str
126
+ end
127
+
128
+ #
129
+ # Converts ISO-8859-1 to UTF-8
130
+ #
131
+ def self.to_utf8(str)
132
+ begin
133
+ Iconv.iconv("utf-8","iso-8859-1", str).join(" ")
134
+ rescue
135
+ raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
136
+ end
137
+ end
138
+
139
+ #
140
+ # Converts ASCII to EBCDIC
141
+ #
142
+ def self.to_ebcdic(str)
143
+ begin
144
+ Iconv.iconv("EBCDIC-US", "ASCII", str).first
145
+ rescue ::Iconv::IllegalSequence => e
146
+ raise e
147
+ rescue
148
+ raise ::RuntimeError, "Your installation does not support iconv (needed for EBCDIC conversion)"
149
+ end
150
+ end
151
+
152
+ #
153
+ # Converts EBCIDC to ASCII
154
+ #
155
+ def self.from_ebcdic(str)
156
+ begin
157
+ Iconv.iconv("ASCII", "EBCDIC-US", str).first
158
+ rescue ::Iconv::IllegalSequence => e
159
+ raise e
160
+ rescue
161
+ raise ::RuntimeError, "Your installation does not support iconv (needed for EBCDIC conversion)"
162
+ end
163
+ end
164
+
165
+ #
166
+ # Returns a unicode escaped string for Javascript
167
+ #
168
+ def self.to_unescape(data, endian=ENDIAN_LITTLE)
169
+ data << "\x41" if (data.length % 2 != 0)
170
+ dptr = 0
171
+ buff = ''
172
+ while (dptr < data.length)
173
+ c1 = data[dptr,1].unpack("C*")[0]
174
+ dptr += 1
175
+ c2 = data[dptr,1].unpack("C*")[0]
176
+ dptr += 1
177
+
178
+ if (endian == ENDIAN_LITTLE)
179
+ buff << sprintf('%%u%.2x%.2x', c2, c1)
180
+ else
181
+ buff << sprintf('%%u%.2x%.2x', c1, c2)
182
+ end
183
+ end
184
+ return buff
185
+ end
186
+
187
+ #
188
+ # Returns the hex version of the supplied string
189
+ #
190
+ def self.to_hex(str, prefix = "\\x", count = 1)
191
+ raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
192
+
193
+ # XXX: Regexp.new is used here since using /.{#{count}}/o would compile
194
+ # the regex the first time it is used and never check again. Since we
195
+ # want to know how many to capture on every instance, we do it this
196
+ # way.
197
+ return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s| prefix + s }
198
+ end
199
+
200
+ #
201
+ # Converts standard ASCII text to a unicode string.
202
+ #
203
+ # Supported unicode types include: utf-16le, utf16-be, utf32-le, utf32-be, utf-7, and utf-8
204
+ #
205
+ # Providing 'mode' provides hints to the actual encoder as to how it should encode the string. Only UTF-7 and UTF-8 use "mode".
206
+ #
207
+ # utf-7 by default does not encode alphanumeric and a few other characters. By specifying the mode of "all", then all of the characters are encoded, not just the non-alphanumeric set.
208
+ # to_unicode(str, 'utf-7', 'all')
209
+ #
210
+ # utf-8 specifies that alphanumeric characters are used directly, eg "a" is just "a". However, there exist 6 different overlong encodings of "a" that are technically not valid, but parse just fine in most utf-8 parsers. (0xC1A1, 0xE081A1, 0xF08081A1, 0xF8808081A1, 0xFC80808081A1, 0xFE8080808081A1). How many bytes to use for the overlong enocding is specified providing 'size'.
211
+ # to_unicode(str, 'utf-8', 'overlong', 2)
212
+ #
213
+ # Many utf-8 parsers also allow invalid overlong encodings, where bits that are unused when encoding a single byte are modified. Many parsers will ignore these bits, rendering simple string matching to be ineffective for dealing with UTF-8 strings. There are many more invalid overlong encodings possible for "a". For example, three encodings are available for an invalid 2 byte encoding of "a". (0xC1E1 0xC161 0xC121). By specifying "invalid", a random invalid encoding is chosen for the given byte size.
214
+ # to_unicode(str, 'utf-8', 'invalid', 2)
215
+ #
216
+ # utf-7 defaults to 'normal' utf-7 encoding
217
+ # utf-8 defaults to 2 byte 'normal' encoding
218
+ #
219
+ def self.to_unicode(str='', type = 'utf-16le', mode = '', size = '')
220
+ return '' if not str
221
+ case type
222
+ when 'utf-16le'
223
+ return str.unpack('C*').pack('v*')
224
+ when 'utf-16be'
225
+ return str.unpack('C*').pack('n*')
226
+ when 'utf-32le'
227
+ return str.unpack('C*').pack('V*')
228
+ when 'utf-32be'
229
+ return str.unpack('C*').pack('N*')
230
+ when 'utf-7'
231
+ case mode
232
+ when 'all'
233
+ return str.gsub(/./){ |a|
234
+ out = ''
235
+ if 'a' != '+'
236
+ out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
237
+ end
238
+ '+' + out + '-'
239
+ }
240
+ else
241
+ return str.gsub(/[^\n\r\t\ A-Za-z0-9\'\(\),-.\/\:\?]/){ |a|
242
+ out = ''
243
+ if a != '+'
244
+ out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
245
+ end
246
+ '+' + out + '-'
247
+ }
248
+ end
249
+ when 'utf-8'
250
+ if size == ''
251
+ size = 2
252
+ end
253
+
254
+ if size >= 2 and size <= 7
255
+ string = ''
256
+ str.each_byte { |a|
257
+ if (a < 21 || a > 0x7f) || mode != ''
258
+ # ugh. turn a single byte into the binary representation of it, in array form
259
+ bin = [a].pack('C').unpack('B8')[0].split(//)
260
+
261
+ # even more ugh.
262
+ bin.collect!{|a_| a_.to_i}
263
+
264
+ out = Array.new(8 * size, 0)
265
+
266
+ 0.upto(size - 1) { |i|
267
+ out[i] = 1
268
+ out[i * 8] = 1
269
+ }
270
+
271
+ i = 0
272
+ byte = 0
273
+ bin.reverse.each { |bit|
274
+ if i < 6
275
+ mod = (((size * 8) - 1) - byte * 8) - i
276
+ out[mod] = bit
277
+ else
278
+ byte = byte + 1
279
+ i = 0
280
+ redo
281
+ end
282
+ i = i + 1
283
+ }
284
+
285
+ if mode != ''
286
+ case mode
287
+ when 'overlong'
288
+ # do nothing, since we already handle this as above...
289
+ when 'invalid'
290
+ done = 0
291
+ while done == 0
292
+ # the ghetto...
293
+ bits = [7, 8, 15, 16, 23, 24, 31, 32, 41]
294
+ bits.each { |bit|
295
+ bit = (size * 8) - bit
296
+ if bit > 1
297
+ set = rand(2)
298
+ if out[bit] != set
299
+ out[bit] = set
300
+ done = 1
301
+ end
302
+ end
303
+ }
304
+ end
305
+ else
306
+ raise TypeError, 'Invalid mode. Only "overlong" and "invalid" are acceptable modes for utf-8'
307
+ end
308
+ end
309
+ string << [out.join('')].pack('B*')
310
+ else
311
+ string << [a].pack('C')
312
+ end
313
+ }
314
+ return string
315
+ else
316
+ raise TypeError, 'invalid utf-8 size'
317
+ end
318
+ when 'uhwtfms' # suggested name from HD :P
319
+ load_codepage()
320
+
321
+ string = ''
322
+ # overloading mode as codepage
323
+ if mode == ''
324
+ mode = 1252 # ANSI - Latan 1, default for US installs of MS products
325
+ else
326
+ mode = mode.to_i
327
+ end
328
+ if @@codepage_map_cache[mode].nil?
329
+ raise TypeError, "Invalid codepage #{mode}"
330
+ end
331
+ str.each_byte {|byte|
332
+ char = [byte].pack('C*')
333
+ possible = @@codepage_map_cache[mode]['data'][char]
334
+ if possible.nil?
335
+ raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
336
+ end
337
+ string << possible[ rand(possible.length) ]
338
+ }
339
+ return string
340
+ when 'uhwtfms-half' # suggested name from HD :P
341
+ load_codepage()
342
+ string = ''
343
+ # overloading mode as codepage
344
+ if mode == ''
345
+ mode = 1252 # ANSI - Latan 1, default for US installs of MS products
346
+ else
347
+ mode = mode.to_i
348
+ end
349
+ if mode != 1252
350
+ raise TypeError, "Invalid codepage #{mode}, only 1252 supported for uhwtfms_half"
351
+ end
352
+ str.each_byte {|byte|
353
+ if ((byte >= 33 && byte <= 63) || (byte >= 96 && byte <= 126))
354
+ string << "\xFF" + [byte ^ 32].pack('C')
355
+ elsif (byte >= 64 && byte <= 95)
356
+ string << "\xFF" + [byte ^ 96].pack('C')
357
+ else
358
+ char = [byte].pack('C')
359
+ possible = @@codepage_map_cache[mode]['data'][char]
360
+ if possible.nil?
361
+ raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
362
+ end
363
+ string << possible[ rand(possible.length) ]
364
+ end
365
+ }
366
+ return string
367
+ else
368
+ raise TypeError, 'invalid utf type'
369
+ end
370
+ end
371
+
372
+ #
373
+ # Encode a string in a manor useful for HTTP URIs and URI Parameters.
374
+ #
375
+ def self.uri_encode(str, mode = 'hex-normal')
376
+ return "" if str == nil
377
+
378
+ return str if mode == 'none' # fast track no encoding
379
+
380
+ all = /[^\/\\]+/
381
+ normal = /[^a-zA-Z0-9\/\\\.\-]+/
382
+ normal_na = /[a-zA-Z0-9\/\\\.\-]/
383
+
384
+ case mode
385
+ when 'hex-normal'
386
+ return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
387
+ when 'hex-all'
388
+ return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
389
+ when 'hex-random'
390
+ res = ''
391
+ str.each_byte do |c|
392
+ b = c.chr
393
+ res << ((rand(2) == 0) ?
394
+ b.gsub(all) { |s| Rex::Text.to_hex(s, '%') } :
395
+ b.gsub(normal){ |s| Rex::Text.to_hex(s, '%') } )
396
+ end
397
+ return res
398
+ when 'u-normal'
399
+ return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
400
+ when 'u-all'
401
+ return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
402
+ when 'u-random'
403
+ res = ''
404
+ str.each_byte do |c|
405
+ b = c.chr
406
+ res << ((rand(2) == 0) ?
407
+ b.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } :
408
+ b.gsub(normal){ |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } )
409
+ end
410
+ return res
411
+ when 'u-half'
412
+ return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms-half'), '%u', 2) }
413
+ else
414
+ raise TypeError, 'invalid mode'
415
+ end
416
+ end
417
+
418
+ #
419
+ # Encode a string in a manner useful for HTTP URIs and URI Parameters.
420
+ #
421
+ def self.html_encode(str, mode = 'hex')
422
+ case mode
423
+ when 'hex'
424
+ return str.unpack('C*').collect{ |i| "&#x" + ("%.2x" % i) + ";"}.join
425
+ when 'int'
426
+ return str.unpack('C*').collect{ |i| "&#" + i.to_s + ";"}.join
427
+ when 'int-wide'
428
+ return str.unpack('C*').collect{ |i| "&#" + ("0" * (7 - i.to_s.length)) + i.to_s + ";" }.join
429
+ else
430
+ raise TypeError, 'invalid mode'
431
+ end
432
+ end
433
+
434
+ #
435
+ # Decode a URI encoded string
436
+ #
437
+ def self.uri_decode(str)
438
+ str.gsub(/(%[a-z0-9]{2})/i){ |c| [c[1,2]].pack("H*") }
439
+ end
440
+
441
+ #
442
+ # Converts a string to random case
443
+ #
444
+ def self.to_rand_case(str)
445
+ buf = str.dup
446
+ 0.upto(str.length) do |i|
447
+ buf[i,1] = rand(2) == 0 ? str[i,1].upcase : str[i,1].downcase
448
+ end
449
+ return buf
450
+ end
451
+
452
+ #
453
+ # Takes a string, and returns an array of all mixed case versions.
454
+ #
455
+ # Example:
456
+ #
457
+ # >> Rex::Text.to_mixed_case_array "abc1"
458
+ # => ["abc1", "abC1", "aBc1", "aBC1", "Abc1", "AbC1", "ABc1", "ABC1"]
459
+ #
460
+ def self.to_mixed_case_array(str)
461
+ letters = []
462
+ str.scan(/./).each { |l| letters << [l.downcase, l.upcase] }
463
+ coords = []
464
+ (1 << str.size).times { |i| coords << ("%0#{str.size}b" % i) }
465
+ mixed = []
466
+ coords.each do |coord|
467
+ c = coord.scan(/./).map {|x| x.to_i}
468
+ this_str = ""
469
+ c.each_with_index { |d,i| this_str << letters[i][d] }
470
+ mixed << this_str
471
+ end
472
+ return mixed.uniq
473
+ end
474
+
475
+ #
476
+ # Converts a string a nicely formatted hex dump
477
+ #
478
+ def self.to_hex_dump(str, width=16)
479
+ buf = ''
480
+ idx = 0
481
+ cnt = 0
482
+ snl = false
483
+ lst = 0
484
+
485
+ while (idx < str.length)
486
+
487
+ chunk = str[idx, width]
488
+ line = chunk.unpack("H*")[0].scan(/../).join(" ")
489
+ buf << line
490
+
491
+ if (lst == 0)
492
+ lst = line.length
493
+ buf << " " * 4
494
+ else
495
+ buf << " " * ((lst - line.length) + 4).abs
496
+ end
497
+
498
+ chunk.unpack("C*").each do |c|
499
+ if (c > 0x1f and c < 0x7f)
500
+ buf << c.chr
501
+ else
502
+ buf << "."
503
+ end
504
+ end
505
+
506
+ buf << "\n"
507
+
508
+ idx += width
509
+ end
510
+
511
+ buf << "\n"
512
+ end
513
+
514
+ #
515
+ # Converts a hex string to a raw string
516
+ #
517
+ def self.hex_to_raw(str)
518
+ [ str.downcase.gsub(/'/,'').gsub(/\\?x([a-f0-9][a-f0-9])/, '\1') ].pack("H*")
519
+ end
520
+
521
+ #
522
+ # Wraps text at a given column using a supplied indention
523
+ #
524
+ def self.wordwrap(str, indent = 0, col = DefaultWrap, append = '', prepend = '')
525
+ return str.gsub(/.{1,#{col - indent}}(?:\s|\Z)/){
526
+ ( (" " * indent) + prepend + $& + append + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
527
+ end
528
+
529
+ #
530
+ # Converts a string to a hex version with wrapping support
531
+ #
532
+ def self.hexify(str, col = DefaultWrap, line_start = '', line_end = '', buf_start = '', buf_end = '')
533
+ output = buf_start
534
+ cur = 0
535
+ count = 0
536
+ new_line = true
537
+
538
+ # Go through each byte in the string
539
+ str.each_byte { |byte|
540
+ count += 1
541
+ append = ''
542
+
543
+ # If this is a new line, prepend with the
544
+ # line start text
545
+ if (new_line == true)
546
+ append << line_start
547
+ new_line = false
548
+ end
549
+
550
+ # Append the hexified version of the byte
551
+ append << sprintf("\\x%.2x", byte)
552
+ cur += append.length
553
+
554
+ # If we're about to hit the column or have gone past it,
555
+ # time to finish up this line
556
+ if ((cur + line_end.length >= col) or (cur + buf_end.length >= col))
557
+ new_line = true
558
+ cur = 0
559
+
560
+ # If this is the last byte, use the buf_end instead of
561
+ # line_end
562
+ if (count == str.length)
563
+ append << buf_end + "\n"
564
+ else
565
+ append << line_end + "\n"
566
+ end
567
+ end
568
+
569
+ output << append
570
+ }
571
+
572
+ # If we were in the middle of a line, finish the buffer at this point
573
+ if (new_line == false)
574
+ output << buf_end + "\n"
575
+ end
576
+
577
+ return output
578
+ end
579
+
580
+ ##
581
+ #
582
+ # Transforms
583
+ #
584
+ ##
585
+
586
+ #
587
+ # Base64 encoder
588
+ #
589
+ def self.encode_base64(str, delim='')
590
+ [str].pack("m").gsub(/\s+/, delim)
591
+ end
592
+
593
+ #
594
+ # Base64 decoder
595
+ #
596
+ def self.decode_base64(str)
597
+ str.unpack("m")[0]
598
+ end
599
+
600
+ #
601
+ # Raw MD5 digest of the supplied string
602
+ #
603
+ def self.md5_raw(str)
604
+ Digest::MD5.digest(str)
605
+ end
606
+
607
+ #
608
+ # Hexidecimal MD5 digest of the supplied string
609
+ #
610
+ def self.md5(str)
611
+ Digest::MD5.hexdigest(str)
612
+ end
613
+
614
+
615
+ ##
616
+ #
617
+ # Generators
618
+ #
619
+ ##
620
+
621
+
622
+ # Generates a random character.
623
+ def self.rand_char(bad, chars = AllChars)
624
+ rand_text(1, bad, chars)
625
+ end
626
+
627
+ # Base text generator method
628
+ def self.rand_base(len, bad, *foo)
629
+ # Remove restricted characters
630
+ (bad || '').split('').each { |c| foo.delete(c) }
631
+
632
+ # Return nil if all bytes are restricted
633
+ return nil if foo.length == 0
634
+
635
+ buff = ""
636
+
637
+ # Generate a buffer from the remaining bytes
638
+ if foo.length >= 256
639
+ len.times { buff << Kernel.rand(256) }
640
+ else
641
+ len.times { buff << foo[ rand(foo.length) ] }
642
+ end
643
+
644
+ return buff
645
+ end
646
+
647
+ # Generate random bytes of data
648
+ def self.rand_text(len, bad='', chars = AllChars)
649
+ foo = chars.split('')
650
+ rand_base(len, bad, *foo)
651
+ end
652
+
653
+ # Generate random bytes of alpha data
654
+ def self.rand_text_alpha(len, bad='')
655
+ foo = []
656
+ foo += ('A' .. 'Z').to_a
657
+ foo += ('a' .. 'z').to_a
658
+ rand_base(len, bad, *foo )
659
+ end
660
+
661
+ # Generate random bytes of lowercase alpha data
662
+ def self.rand_text_alpha_lower(len, bad='')
663
+ rand_base(len, bad, *('a' .. 'z').to_a)
664
+ end
665
+
666
+ # Generate random bytes of uppercase alpha data
667
+ def self.rand_text_alpha_upper(len, bad='')
668
+ rand_base(len, bad, *('A' .. 'Z').to_a)
669
+ end
670
+
671
+ # Generate random bytes of alphanumeric data
672
+ def self.rand_text_alphanumeric(len, bad='')
673
+ foo = []
674
+ foo += ('A' .. 'Z').to_a
675
+ foo += ('a' .. 'z').to_a
676
+ foo += ('0' .. '9').to_a
677
+ rand_base(len, bad, *foo )
678
+ end
679
+
680
+ # Generate random bytes of alphanumeric hex.
681
+ def self.rand_text_hex(len, bad='')
682
+ foo = []
683
+ foo += ('0' .. '9').to_a
684
+ foo += ('a' .. 'f').to_a
685
+ rand_base(len, bad, *foo)
686
+ end
687
+
688
+ # Generate random bytes of numeric data
689
+ def self.rand_text_numeric(len, bad='')
690
+ foo = ('0' .. '9').to_a
691
+ rand_base(len, bad, *foo )
692
+ end
693
+
694
+ # Generate random bytes of english-like data
695
+ def self.rand_text_english(len, bad='')
696
+ foo = []
697
+ foo += (0x21 .. 0x7e).map{ |c| c.chr }
698
+ rand_base(len, bad, *foo )
699
+ end
700
+
701
+ # Generate random bytes of high ascii data
702
+ def self.rand_text_highascii(len, bad='')
703
+ foo = []
704
+ foo += (0x80 .. 0xff).map{ |c| c.chr }
705
+ rand_base(len, bad, *foo )
706
+ end
707
+
708
+ #
709
+ # Creates a pattern that can be used for offset calculation purposes. This
710
+ # routine is capable of generating patterns using a supplied set and a
711
+ # supplied number of identifiable characters (slots). The supplied sets
712
+ # should not contain any duplicate characters or the logic will fail.
713
+ #
714
+ def self.pattern_create(length, sets = [ UpperAlpha, LowerAlpha, Numerals ])
715
+ buf = ''
716
+ idx = 0
717
+ offsets = []
718
+
719
+ sets.length.times { offsets << 0 }
720
+
721
+ until buf.length >= length
722
+ begin
723
+ buf << converge_sets(sets, 0, offsets, length)
724
+ rescue RuntimeError
725
+ break
726
+ end
727
+ end
728
+
729
+ # Maximum permutations reached, but we need more data
730
+ if (buf.length < length)
731
+ buf = buf * (length / buf.length.to_f).ceil
732
+ end
733
+
734
+ buf[0,length]
735
+ end
736
+
737
+ #
738
+ # Calculate the offset to a pattern
739
+ #
740
+ def self.pattern_offset(pattern, value, start=0)
741
+ if (value.kind_of?(String))
742
+ pattern.index(value, start)
743
+ elsif (value.kind_of?(Fixnum) or value.kind_of?(Bignum))
744
+ pattern.index([ value ].pack('V'), start)
745
+ else
746
+ raise ::ArgumentError, "Invalid class for value: #{value.class}"
747
+ end
748
+ end
749
+
750
+ #
751
+ # Compresses a string, eliminating all superfluous whitespace before and
752
+ # after lines and eliminating all lines.
753
+ #
754
+ def self.compress(str)
755
+ str.gsub(/\n/m, ' ').gsub(/\s+/, ' ').gsub(/^\s+/, '').gsub(/\s+$/, '')
756
+ end
757
+
758
+ #
759
+ # Randomize the whitespace in a string
760
+ #
761
+ def self.randomize_space(str)
762
+ str.gsub(/\s+/) { |s|
763
+ len = rand(50)+2
764
+ set = "\x09\x20\x0d\x0a"
765
+ buf = ''
766
+ while (buf.length < len)
767
+ buf << set[rand(set.length),1]
768
+ end
769
+
770
+ buf
771
+ }
772
+ end
773
+
774
+ # Returns true if zlib can be used.
775
+ def self.zlib_present?
776
+ begin
777
+ temp = Zlib
778
+ return true
779
+ rescue
780
+ return false
781
+ end
782
+ end
783
+
784
+ # backwards compat for just a bit...
785
+ def self.gzip_present?
786
+ self.zlib_present?
787
+ end
788
+
789
+ #
790
+ # Compresses a string using zlib
791
+ #
792
+ def self.zlib_deflate(str, level = Zlib::BEST_COMPRESSION)
793
+ if self.zlib_present?
794
+ z = Zlib::Deflate.new(level)
795
+ dst = z.deflate(str, Zlib::FINISH)
796
+ z.close
797
+ return dst
798
+ else
799
+ raise RuntimeError, "Gzip support is not present."
800
+ end
801
+ end
802
+
803
+ #
804
+ # Uncompresses a string using zlib
805
+ #
806
+ def self.zlib_inflate(str)
807
+ if(self.zlib_present?)
808
+ zstream = Zlib::Inflate.new
809
+ buf = zstream.inflate(str)
810
+ zstream.finish
811
+ zstream.close
812
+ return buf
813
+ else
814
+ raise RuntimeError, "Gzip support is not present."
815
+ end
816
+ end
817
+
818
+ #
819
+ # Compresses a string using gzip
820
+ #
821
+ def self.gzip(str, level = 9)
822
+ raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
823
+ raise RuntimeError, "Invalid gzip compression level" if (level < 1 or level > 9)
824
+
825
+ s = ""
826
+ gz = Zlib::GzipWriter.new(StringIO.new(s), level)
827
+ gz << str
828
+ gz.close
829
+ return s
830
+ end
831
+
832
+ #
833
+ # Uncompresses a string using gzip
834
+ #
835
+ def self.ungzip(str)
836
+ raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
837
+
838
+ s = ""
839
+ gz = Zlib::GzipReader.new(StringIO.new(str))
840
+ s << gz.read
841
+ gz.close
842
+ return s
843
+ end
844
+
845
+ #
846
+ # Return the index of the first badchar in data, otherwise return
847
+ # nil if there wasn't any badchar occurences.
848
+ #
849
+ def self.badchar_index(data, badchars = '')
850
+ badchars.unpack("C*").each { |badchar|
851
+ pos = data.index(badchar.chr)
852
+ return pos if pos
853
+ }
854
+ return nil
855
+ end
856
+
857
+ #
858
+ # This method removes bad characters from a string.
859
+ #
860
+ def self.remove_badchars(data, badchars = '')
861
+ data.delete(badchars)
862
+ end
863
+
864
+ #
865
+ # This method returns all chars but the supplied set
866
+ #
867
+ def self.charset_exclude(keepers)
868
+ [*(0..255)].pack('C*').delete(keepers)
869
+ end
870
+
871
+ #
872
+ # Shuffles a byte stream
873
+ #
874
+ def self.shuffle_s(str)
875
+ shuffle_a(str.unpack("C*")).pack("C*")
876
+ end
877
+
878
+ #
879
+ # Performs a Fisher-Yates shuffle on an array
880
+ #
881
+ def self.shuffle_a(arr)
882
+ len = arr.length
883
+ max = len - 1
884
+ cyc = [* (0..max) ]
885
+ for d in cyc
886
+ e = rand(d+1)
887
+ next if e == d
888
+ f = arr[d];
889
+ g = arr[e];
890
+ arr[d] = g;
891
+ arr[e] = f;
892
+ end
893
+ return arr
894
+ end
895
+
896
+ # Permute the case of a word
897
+ def self.permute_case(word, idx=0)
898
+ res = []
899
+
900
+ if( (UpperAlpha+LowerAlpha).index(word[idx,1]))
901
+
902
+ word_ucase = word.dup
903
+ word_ucase[idx, 1] = word[idx, 1].upcase
904
+
905
+ word_lcase = word.dup
906
+ word_lcase[idx, 1] = word[idx, 1].downcase
907
+
908
+ if (idx == word.length)
909
+ return [word]
910
+ else
911
+ res << permute_case(word_ucase, idx+1)
912
+ res << permute_case(word_lcase, idx+1)
913
+ end
914
+ else
915
+ res << permute_case(word, idx+1)
916
+ end
917
+
918
+ res.flatten
919
+ end
920
+
921
+ # Generate a random hostname
922
+ def self.rand_hostname
923
+ host = []
924
+ (rand(5) + 1).times {
925
+ host.push(Rex::Text.rand_text_alphanumeric(rand(10) + 1))
926
+ }
927
+ d = ['com', 'net', 'org', 'gov']
928
+ host.push(d[rand(d.size)])
929
+ host.join('.').downcase
930
+ end
931
+
932
+ # Generate a state
933
+ def self.rand_state()
934
+ States[rand(States.size)]
935
+ end
936
+
937
+
938
+ #
939
+ # Calculate the ROR13 hash of a given string
940
+ #
941
+ def self.ror13_hash(name)
942
+ hash = 0
943
+ name.unpack("C*").each {|c| hash = ror(hash, 13); hash += c }
944
+ hash
945
+ end
946
+
947
+ #
948
+ # Rotate a 32-bit value to the right by cnt bits
949
+ #
950
+ def self.ror(val, cnt)
951
+ bits = [val].pack("N").unpack("B32")[0].split(//)
952
+ 1.upto(cnt) do |c|
953
+ bits.unshift( bits.pop )
954
+ end
955
+ [bits.join].pack("B32").unpack("N")[0]
956
+ end
957
+
958
+ #
959
+ # Rotate a 32-bit value to the left by cnt bits
960
+ #
961
+ def self.rol(val, cnt)
962
+ bits = [val].pack("N").unpack("B32")[0].split(//)
963
+ 1.upto(cnt) do |c|
964
+ bits.push( bits.shift )
965
+ end
966
+ [bits.join].pack("B32").unpack("N")[0]
967
+ end
968
+
969
+
970
+ protected
971
+
972
+ def self.converge_sets(sets, idx, offsets, length) # :nodoc:
973
+ buf = sets[idx][offsets[idx]].chr
974
+
975
+ # If there are more sets after use, converage with them.
976
+ if (sets[idx + 1])
977
+ buf << converge_sets(sets, idx + 1, offsets, length)
978
+ else
979
+ # Increment the current set offset as well as previous ones if we
980
+ # wrap back to zero.
981
+ while (idx >= 0 and ((offsets[idx] = (offsets[idx] + 1) % sets[idx].length)) == 0)
982
+ idx -= 1
983
+ end
984
+
985
+ # If we reached the point where the idx fell below zero, then that
986
+ # means we've reached the maximum threshold for permutations.
987
+ if (idx < 0)
988
+ raise RuntimeError, "Maximum permutations reached"
989
+ end
990
+ end
991
+
992
+ buf
993
+ end
994
+
995
+ def self.load_codepage()
996
+ return if (!@@codepage_map_cache.nil?)
997
+ file = File.join(File.dirname(__FILE__),'codepage.map')
998
+ page = ''
999
+ name = ''
1000
+ map = {}
1001
+ File.open(file).each { |line|
1002
+ next if line =~ /^#/
1003
+ next if line =~ /^\s*$/
1004
+ data = line.split
1005
+ if data[1] =~ /^\(/
1006
+ page = data.shift.to_i
1007
+ name = data.join(' ').sub(/^\(/,'').sub(/\)$/,'')
1008
+ map[page] = {}
1009
+ map[page]['name'] = name
1010
+ map[page]['data'] = {}
1011
+ else
1012
+ data.each { |entry|
1013
+ wide, char = entry.split(':')
1014
+ char = [char].pack('H*')
1015
+ wide = [wide].pack('H*')
1016
+ if map[page]['data'][char].nil?
1017
+ map[page]['data'][char] = [wide]
1018
+ else
1019
+ map[page]['data'][char].push(wide)
1020
+ end
1021
+ }
1022
+ end
1023
+ }
1024
+ @@codepage_map_cache = map
1025
+ end
1026
+
1027
+ end
1028
+ end
1029
+