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,335 @@
1
+ require 'rex/text'
2
+ module Rex
3
+ module Exploitation
4
+
5
+ #
6
+ # Obfuscates javascript in various ways
7
+ #
8
+ class ObfuscateJS
9
+ attr_reader :opts
10
+
11
+ #
12
+ # Obfuscates a javascript string.
13
+ #
14
+ # Options are 'Symbols', described below, and 'Strings', a boolean
15
+ # which specifies whether strings within the javascript should be
16
+ # mucked with (defaults to false).
17
+ #
18
+ # The 'Symbols' argument should have the following format:
19
+ #
20
+ # {
21
+ # 'Variables' => [ 'var1', ... ],
22
+ # 'Methods' => [ 'method1', ... ],
23
+ # 'Namespaces' => [ 'n', ... ],
24
+ # 'Classes' => [ { 'Namespace' => 'n', 'Class' => 'y'}, ... ]
25
+ # }
26
+ #
27
+ # Make sure you order your methods, classes, and namespaces by most
28
+ # specific to least specific to prevent partial substitution. For
29
+ # instance, if you have two methods (joe and joeBob), you should place
30
+ # joeBob before joe because it is more specific and will be globally
31
+ # replaced before joe is replaced.
32
+ #
33
+ # A simple example follows:
34
+ #
35
+ # <code>
36
+ # js = ObfuscateJS.new <<ENDJS
37
+ # function say_hi() {
38
+ # var foo = "Hello, world";
39
+ # document.writeln(foo);
40
+ # }
41
+ # ENDJS
42
+ # js.obfuscate(
43
+ # 'Symbols' => {
44
+ # 'Variables' => [ 'foo' ],
45
+ # 'Methods' => [ 'say_hi' ]
46
+ # }
47
+ # 'Strings' => true
48
+ # )
49
+ # </code>
50
+ #
51
+ # which should generate something like the following:
52
+ #
53
+ # <code>
54
+ # function oJaDYRzFOyJVQCOHk() { var cLprVG = "\x48\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64"; document.writeln(cLprVG); }
55
+ # </code>
56
+ #
57
+ # String obfuscation tries to deal with escaped quotes within strings but
58
+ # won't catch things like
59
+ # "\\"
60
+ # so be careful.
61
+ #
62
+ def self.obfuscate(js, opts = {})
63
+ ObfuscateJS.new(js).obfuscate(opts)
64
+ end
65
+
66
+ #
67
+ # Initialize an instance of the obfuscator
68
+ #
69
+ def initialize(js = "", opts = {})
70
+ @js = js
71
+ @dynsym = {}
72
+ @opts = {
73
+ 'Symbols' => {
74
+ 'Variables'=>[],
75
+ 'Methods'=>[],
76
+ 'Namespaces'=>[],
77
+ 'Classes'=>[]
78
+ },
79
+ 'Strings'=>false
80
+ }
81
+ @done = false
82
+ update_opts(opts) if (opts.length > 0)
83
+ end
84
+
85
+ def update_opts(opts)
86
+ if (opts.nil? or opts.length < 1)
87
+ return
88
+ end
89
+ if (@opts['Symbols'] && opts['Symbols'])
90
+ ['Variables', 'Methods', 'Namespaces', 'Classes'].each { |k|
91
+ if (@opts['Symbols'][k] && opts['Symbols'][k])
92
+ opts['Symbols'][k].each { |s|
93
+ if (not @opts['Symbols'][k].include? s)
94
+ @opts['Symbols'][k].push(s)
95
+ end
96
+ }
97
+ elsif (opts['Symbols'][k])
98
+ @opts['Symbols'][k] = opts['Symbols'][k]
99
+ end
100
+ }
101
+ elsif opts['Symbols']
102
+ @opts['Symbols'] = opts['Symbols']
103
+ end
104
+ @opts['Strings'] ||= opts['Strings']
105
+ end
106
+
107
+ #
108
+ # Returns the dynamic symbol associated with the supplied symbol name
109
+ #
110
+ # If obfuscation has not yet been performed (i.e. obfuscate() has not been
111
+ # called), then this method simply returns its argument
112
+ #
113
+ def sym(name)
114
+ @dynsym[name] || name
115
+ end
116
+
117
+ #
118
+ # Obfuscates the javascript string passed to the constructor
119
+ #
120
+ def obfuscate(opts = {})
121
+ #return @js if (@done)
122
+ @done = true
123
+
124
+ update_opts(opts)
125
+
126
+ if (@opts['Strings'])
127
+ obfuscate_strings()
128
+
129
+ # Full space randomization does not work for javascript -- despite
130
+ # claims that space is irrelavent, newlines break things. Instead,
131
+ # use only space (0x20) and tab (0x09).
132
+
133
+ #@js.gsub!(/[\x09\x20]+/) { |s|
134
+ # len = rand(50)+2
135
+ # set = "\x09\x20"
136
+ # buf = ''
137
+ # while (buf.length < len)
138
+ # buf << set[rand(set.length)].chr
139
+ # end
140
+ #
141
+ # buf
142
+ #}
143
+ end
144
+
145
+ # Remove our comments
146
+ remove_comments
147
+
148
+ # Globally replace symbols
149
+ replace_symbols(@opts['Symbols']) if @opts['Symbols']
150
+
151
+ return @js
152
+ end
153
+
154
+ #
155
+ # Returns the replaced javascript string
156
+ #
157
+ def to_s
158
+ @js
159
+ end
160
+ alias :to_str :to_s
161
+
162
+ def <<(str)
163
+ @js << str
164
+ end
165
+ def +(str)
166
+ @js + str
167
+ end
168
+
169
+ protected
170
+ attr_accessor :done
171
+
172
+ #
173
+ # Get rid of both single-line C++ style comments and multiline C style comments.
174
+ #
175
+ # Note: embedded comments (e.g.: "/*/**/*/") will break this,
176
+ # but they also break real javascript engines so I don't care.
177
+ #
178
+ def remove_comments
179
+ @js.gsub!(%r{\s+//.*$}, '')
180
+ @js.gsub!(%r{/\*.*?\*/}m, '')
181
+ end
182
+
183
+ # Replace method, class, and namespace symbols found in the javascript
184
+ # string
185
+ def replace_symbols(symbols)
186
+ taken = { }
187
+
188
+ # Generate random symbol names
189
+ [ 'Variables', 'Methods', 'Classes', 'Namespaces' ].each { |symtype|
190
+ next if symbols[symtype].nil?
191
+ symbols[symtype].each { |sym|
192
+ dyn = Rex::Text.rand_text_alpha(rand(32)+1) until dyn and not taken.key?(dyn)
193
+
194
+ taken[dyn] = true
195
+
196
+ if symtype == 'Classes'
197
+ full_sym = sym['Namespace'] + "." + sym['Class']
198
+ @dynsym[full_sym] = dyn
199
+
200
+ @js.gsub!(/#{full_sym}/) { |m|
201
+ sym['Namespace'] + "." + dyn
202
+ }
203
+ else
204
+ @dynsym[sym] = dyn
205
+
206
+ @js.gsub!(/#{sym}/, dyn)
207
+ end
208
+ }
209
+ }
210
+ end
211
+
212
+ #
213
+ # Change each string into some javascript that will generate that string
214
+ #
215
+ # There are a couple of caveats to using string obfuscation:
216
+ # * it tries to deal with escaped quotes within strings but won't catch
217
+ # things like: "\\"
218
+ # * depending on the random choices, this can easily balloon a short
219
+ # string up to hundreds of kilobytes if called multiple times.
220
+ # so be careful.
221
+ #
222
+ def obfuscate_strings()
223
+ @js.gsub!(/".*?[^\\]"|'.*?[^\\]'/) { |str|
224
+ buf = ''
225
+ quote = str[0,1]
226
+ # Pull the quotes off either end
227
+ str = str[1, str.length-2]
228
+ case (rand(2))
229
+ # Disable hex encoding for now. It's just too big a hassle.
230
+ #when 0
231
+ # # This is where we can run into trouble with generating
232
+ # # incorrect code. If we hex encode a string twice, the second
233
+ # # encoding will generate the first instead of the original
234
+ # # string.
235
+ # if str =~ /\\x/
236
+ # # Always have to remove spaces from strings so the space
237
+ # # randomization doesn't mess with them.
238
+ # buf = quote + str.gsub(/ /, '\x20') + quote
239
+ # else
240
+ # buf = '"' + Rex::Text.to_hex(str) + '"'
241
+ # end
242
+ when 0
243
+ #
244
+ # Escape sequences when naively encoded for unescape become a
245
+ # literal backslash instead of the intended meaning. To avoid
246
+ # that problem, we scan the string for escapes and leave them
247
+ # unmolested.
248
+ #
249
+ buf << 'unescape("'
250
+ bytes = str.unpack("C*")
251
+ c = 0
252
+ while bytes[c]
253
+ if bytes[c].chr == "\\"
254
+ # XXX This is pretty slow.
255
+ esc_len = parse_escape(bytes, c)
256
+ buf << bytes[c, esc_len].map{|a| a.chr}.join
257
+ c += esc_len
258
+ next
259
+ end
260
+ buf << "%%%0.2x"%(bytes[c])
261
+ # Break the string into smaller strings
262
+ if bytes[c+1] and rand(10) == 0
263
+ buf << '" + "'
264
+ end
265
+ c += 1
266
+ end
267
+ buf << '")'
268
+ when 1
269
+ buf = "String.fromCharCode( "
270
+ bytes = str.unpack("C*")
271
+ c = 0
272
+ while bytes[c]
273
+ if bytes[c].chr == "\\"
274
+ case bytes[c+1].chr
275
+ # For chars that contain their non-escaped selves, step
276
+ # past the backslash and let the rand() below decide
277
+ # how to represent the character.
278
+ when '"'; c += 1
279
+ when "'"; c += 1
280
+ when "\\"; c += 1
281
+ # For others, just take the hex representation out of
282
+ # laziness.
283
+ when "n"; buf << "0x0a"; c += 2; next
284
+ when "t"; buf << "0x09"; c += 2; next
285
+ # Lastly, if it's a hex, unicode, or octal escape,
286
+ # leave it, and anything after it, alone. At some
287
+ # point we may want to parse up to the end of the
288
+ # escapes and encode subsequent non-escape characters.
289
+ # Since this is the lazy way to do it, spaces after an
290
+ # escape sequence will get away unmodified. To prevent
291
+ # the space randomizer from hosing the string, convert
292
+ # spaces specifically.
293
+ else
294
+ buf = buf[0,buf.length-1] + " )"
295
+ buf << ' + ("' + bytes[c, bytes.length].map{|a| a==0x20 ? '\x20' : a.chr}.join + '" '
296
+ break
297
+ end
298
+ end
299
+ case (rand(3))
300
+ when 0
301
+ buf << " %i,"%(bytes[c])
302
+ when 1
303
+ buf << " 0%o,"%(bytes[c])
304
+ when 2
305
+ buf << " 0x%0.2x,"%(bytes[c])
306
+ end
307
+ c += 1
308
+ end
309
+ # Strip off the last comma
310
+ buf = buf[0,buf.length-1] + " )"
311
+ end
312
+ buf
313
+ }
314
+ @js
315
+ end
316
+
317
+ def parse_escape(bytes, offset)
318
+ esc_len = 0
319
+ if bytes[offset].chr == "\\"
320
+ case bytes[offset+1].chr
321
+ when "u"; esc_len = 6 # unicode \u1234
322
+ when "x"; esc_len = 4 # hex, \x41
323
+ when /[0-9]/ # octal, \123, \0
324
+ oct = bytes[offset+1, 4].map{|a|a.chr}.join
325
+ oct =~ /([0-9]+)/
326
+ esc_len = 1 + $1.length
327
+ else; esc_len = 2 # \" \n, etc.
328
+ end
329
+ end
330
+ esc_len
331
+ end
332
+ end
333
+
334
+ end
335
+ end
@@ -0,0 +1,818 @@
1
+ require 'rexml/rexml'
2
+ require 'rexml/source'
3
+ require 'rexml/document'
4
+ require 'rexml/parsers/treeparser'
5
+ require 'rex/proto/http'
6
+ require 'uri'
7
+
8
+ module Rex
9
+ module Exploitation
10
+ module OpcodeDb
11
+
12
+ module OpcodeResult # :nodoc:
13
+ def initialize(hash)
14
+ @hash = hash
15
+ end
16
+ attr_reader :hash
17
+ end
18
+
19
+ ###
20
+ #
21
+ # A cachable entry.
22
+ #
23
+ ###
24
+ module Cachable
25
+
26
+ def create(hash) # :nodoc:
27
+ @Cache = {} unless (@Cache)
28
+ if (hash_key(hash) and @Cache[hash_key(hash)])
29
+ @Cache[hash_key(hash)]
30
+ else
31
+ @Cache[hash_key(hash)] = self.new(hash)
32
+ end
33
+ end
34
+
35
+ def hash_key(hash) # :nodoc:
36
+ hash['id'] || nil
37
+ end
38
+
39
+ def flush_cache # :nodoc:
40
+ @Cache.clear
41
+ end
42
+
43
+ end
44
+
45
+ ###
46
+ #
47
+ # This class provides a general interface to items that come from that opcode
48
+ # database that have a symbolic entry identifier and name.
49
+ #
50
+ ###
51
+ module DbEntry
52
+ include OpcodeResult
53
+
54
+ def initialize(hash)
55
+ super
56
+
57
+ @id = hash['id'].to_i
58
+ @name = hash['name']
59
+ end
60
+
61
+ #
62
+ # Fields that could possibly be filtered on for this database entry.
63
+ #
64
+ def filter_hash
65
+ {
66
+ "id" => id,
67
+ "name" => name
68
+ }
69
+ end
70
+
71
+ #
72
+ # The unique server identifier.
73
+ #
74
+ attr_reader :id
75
+ #
76
+ # The unique name for this entry.
77
+ #
78
+ attr_reader :name
79
+ end
80
+
81
+ ###
82
+ #
83
+ # This class represents a particular image module including its name,
84
+ # segments, imports, exports, base address, and so on.
85
+ #
86
+ ###
87
+ class ImageModule
88
+ include DbEntry
89
+
90
+ ###
91
+ #
92
+ # This class contains information about a module-associated segment.
93
+ #
94
+ ###
95
+ class Segment
96
+ def initialize(hash)
97
+ @type = hash['type']
98
+ @base_address = hash['base_address'].to_i
99
+ @size = hash['segment_size'].to_i
100
+ @writable = hash['writable'] == "true" ? true : false
101
+ @readable = hash['readable'] == "true" ? true : false
102
+ @executable = hash['executable'] == "true" ? true : false
103
+ end
104
+
105
+ #
106
+ # The type of the segment, such as ".text".
107
+ #
108
+ attr_reader :type
109
+ #
110
+ # The base address of the segment.
111
+ #
112
+ attr_reader :base_address
113
+ #
114
+ # The size of the segment in bytes.
115
+ #
116
+ attr_reader :size
117
+ #
118
+ # Boolean that indicates whether or not the segment is writable.
119
+ #
120
+ attr_reader :writable
121
+ #
122
+ # Boolean that indicates whether or not the segment is readable.
123
+ #
124
+ attr_reader :readable
125
+ #
126
+ # Boolean that indicates whether or not the segment is executable.
127
+ #
128
+ attr_reader :executable
129
+ end
130
+
131
+ ###
132
+ #
133
+ # This class contains information about a module-associated import.
134
+ #
135
+ ###
136
+ class Import
137
+ def initialize(hash)
138
+ @name = hash['name']
139
+ @address = hash['address'].to_i
140
+ @ordinal = hash['ordinal'].to_i
141
+ end
142
+
143
+ #
144
+ # The name of the imported function.
145
+ #
146
+ attr_reader :name
147
+ #
148
+ # The address of the function pointer in the IAT.
149
+ #
150
+ attr_reader :address
151
+ #
152
+ # The ordinal of the imported symbol.
153
+ #
154
+ attr_reader :ordinal
155
+ end
156
+
157
+ ###
158
+ #
159
+ # This class contains information about a module-associated export.
160
+ #
161
+ ###
162
+ class Export
163
+ def initialize(hash)
164
+ @name = hash['name']
165
+ @address = hash['address'].to_i
166
+ @ordinal = hash['ordinal'].to_i
167
+ end
168
+
169
+ #
170
+ # The name of the exported function.
171
+ #
172
+ attr_reader :name
173
+ #
174
+ # The address of the exported function.
175
+ #
176
+ attr_reader :address
177
+ #
178
+ # The ordinal of the exported symbol.
179
+ #
180
+ attr_reader :ordinal
181
+ end
182
+
183
+ class <<self
184
+ include Cachable
185
+ def hash_key(hash) # :nodoc:
186
+ (hash['id'] || '') +
187
+ (hash['segments'] || '').to_s +
188
+ (hash['exports'] || '').to_s +
189
+ (hash['imports'] || '').to_s
190
+ end
191
+ end
192
+
193
+ def initialize(hash)
194
+ super
195
+
196
+ @locale = Locale.create(hash['locale'])
197
+ @maj_maj_ver = hash['maj_maj_ver'].to_i
198
+ @maj_min_ver = hash['maj_min_ver'].to_i
199
+ @min_maj_ver = hash['min_maj_ver'].to_i
200
+ @min_min_ver = hash['min_min_ver'].to_i
201
+ @timestamp = Time.at(hash['timestamp'].to_i)
202
+ @vendor = hash['vendor']
203
+ @base_address = hash['base_address'].to_i
204
+ @image_size = hash['image_size'].to_i
205
+
206
+ @segments = hash['segments'].map { |ent|
207
+ Segment.new(ent)
208
+ } if (hash['segments'])
209
+ @imports = hash['imports'].map { |ent|
210
+ Import.new(ent)
211
+ } if (hash['imports'])
212
+ @exports = hash['exports'].map { |ent|
213
+ Export.new(ent)
214
+ } if (hash['exports'])
215
+ @platforms = hash['platforms'].map { |ent|
216
+ OsVersion.create(ent)
217
+ } if (hash['platforms'])
218
+
219
+ @segments = [] unless(@segments)
220
+ @imports = [] unless(@imports)
221
+ @exports = [] unless(@exports)
222
+ @platforms = [] unless(@platforms)
223
+ end
224
+
225
+ #
226
+ # An instance of a Locale class that is associated with this module.
227
+ #
228
+ attr_reader :locale
229
+ #
230
+ # The module's major major version number (X.x.x.x).
231
+ #
232
+ attr_reader :maj_maj_ver
233
+ #
234
+ # The module's major minor version number (x.X.x.x).
235
+ #
236
+ attr_reader :maj_min_ver
237
+ #
238
+ # The module's minor major version number (x.x.X.x).
239
+ #
240
+ attr_reader :min_maj_ver
241
+ #
242
+ # The module's minor minor version number (x.x.x.X).
243
+ #
244
+ attr_reader :min_min_ver
245
+ #
246
+ # The timestamp that the image was compiled (as a Time instance).
247
+ #
248
+ attr_reader :timestamp
249
+ #
250
+ # The vendor that created the module.
251
+ #
252
+ attr_reader :vendor
253
+ #
254
+ # The preferred base address at which the module will load.
255
+ #
256
+ attr_reader :base_address
257
+ #
258
+ # The size of the image mapping associated with the module in bytes.
259
+ #
260
+ attr_reader :image_size
261
+ #
262
+ # An array of Segment instances.
263
+ #
264
+ attr_reader :segments
265
+ #
266
+ # An array of Import instances.
267
+ #
268
+ attr_reader :imports
269
+ #
270
+ # An array of Export instances.
271
+ #
272
+ attr_reader :exports
273
+ #
274
+ # An array of OsVersion instances.
275
+ #
276
+ attr_reader :platforms
277
+ end
278
+
279
+ ###
280
+ #
281
+ # This class contains information about a specific locale, such as English.
282
+ #
283
+ ###
284
+ class Locale
285
+ include DbEntry
286
+ class <<self
287
+ include Cachable
288
+ end
289
+ end
290
+
291
+ ###
292
+ #
293
+ # This class contains information about a platform (operating system) version.
294
+ #
295
+ ###
296
+ class OsVersion
297
+ include DbEntry
298
+
299
+ class <<self
300
+ include Cachable
301
+ def hash_key(hash)
302
+ hash['id'] + (hash['modules'] || '')
303
+ end
304
+ end
305
+
306
+ def initialize(hash)
307
+ super
308
+
309
+ @modules = (hash['modules']) ? hash['modules'].to_i : 0
310
+ @desc = hash['desc']
311
+ @arch = hash['arch']
312
+ @maj_ver = hash['maj_ver'].to_i
313
+ @min_ver = hash['min_ver'].to_i
314
+ @maj_patch_level = hash['maj_patch_level'].to_i
315
+ @min_patch_level = hash['min_patch_level'].to_i
316
+ end
317
+
318
+ #
319
+ # The number of modules that exist in this operating system version.
320
+ #
321
+ attr_reader :modules
322
+ #
323
+ # The operating system version description, such as Windows XP 5.2.0.0
324
+ # (IA32).
325
+ #
326
+ attr_reader :desc
327
+ #
328
+ # The architecture that the operating system version runs on, such as IA32.
329
+ #
330
+ attr_reader :arch
331
+ #
332
+ # The major version of the operating system version.
333
+ #
334
+ attr_reader :maj_ver
335
+ #
336
+ # The minor version of the operating system version.
337
+ #
338
+ attr_reader :min_ver
339
+ #
340
+ # The major patch level of the operating system version, such as a service
341
+ # pack.
342
+ #
343
+ attr_reader :maj_patch_level
344
+ #
345
+ # The minor patch level of the operating system version.
346
+ #
347
+ attr_reader :min_patch_level
348
+ end
349
+
350
+ ###
351
+ #
352
+ # An opcode group (esp => eip).
353
+ #
354
+ ###
355
+ class Group
356
+ include DbEntry
357
+ class <<self
358
+ include Cachable
359
+ end
360
+ end
361
+
362
+ ###
363
+ #
364
+ # An opcode type (jmp esp).
365
+ #
366
+ ###
367
+ class Type
368
+ include DbEntry
369
+
370
+ class <<self
371
+ include Cachable
372
+ end
373
+
374
+ def initialize(hash)
375
+ super
376
+
377
+ @opcodes = (hash['opcodes']) ? hash['opcodes'].to_i : 0
378
+ @meta_type = MetaType.create(hash['meta_type']) if (hash['meta_type'])
379
+ @group = Group.create(hash['group']) if (hash['group'])
380
+ @arch = hash['arch']
381
+ end
382
+
383
+ #
384
+ # The number of opcodes associated with this type, or 0 if this information
385
+ # is not available.
386
+ #
387
+ attr_reader :opcodes
388
+ #
389
+ # An instance of the MetaType to which this opcode type belongs, or nil.
390
+ #
391
+ attr_reader :meta_type
392
+ #
393
+ # An instance of the Group to which this opcode type belongs, or nil.
394
+ #
395
+ attr_reader :group
396
+ #
397
+ # The architecture that this opcode type is associated with.
398
+ #
399
+ attr_reader :arch
400
+ end
401
+
402
+ ###
403
+ #
404
+ # An opcode meta type (jmp reg).
405
+ #
406
+ ###
407
+ class MetaType
408
+ include DbEntry
409
+ class <<self
410
+ include Cachable
411
+ end
412
+ end
413
+
414
+ ###
415
+ #
416
+ # An opcode that has a specific address and is associated with one or more
417
+ # modules.
418
+ #
419
+ ###
420
+ class Opcode
421
+ include DbEntry
422
+
423
+ def initialize(hash)
424
+ super
425
+
426
+ @address = hash['address'].to_i
427
+ @type = Type.create(hash['type'])
428
+ @group = @type.group
429
+ @modules = hash['modules'].map { |ent|
430
+ ImageModule.create(ent)
431
+ } if (hash['modules'])
432
+
433
+ @modules = [] unless(@modules)
434
+ end
435
+
436
+ #
437
+ # The address of the opcode.
438
+ #
439
+ attr_reader :address
440
+ #
441
+ # The type of the opcode indicating which instruction is found at the
442
+ # address. This is an instance of the Type class.
443
+ #
444
+ attr_reader :type
445
+ #
446
+ # A Group instance that reflects the group to which the opcode type found
447
+ # at the instance's address belongs.
448
+ #
449
+ attr_reader :group
450
+ #
451
+ # An array of ImageModule instances that show the modules that contain this
452
+ # address.
453
+ #
454
+ attr_reader :modules
455
+ end
456
+
457
+ ###
458
+ #
459
+ # Current statistics of the opcode database.
460
+ #
461
+ ###
462
+ class Statistics
463
+ def initialize(hash)
464
+ @modules = hash['modules'].to_i
465
+ @opcodes = hash['opcodes'].to_i
466
+ @opcode_types = hash['opcode_types'].to_i
467
+ @platforms = hash['platforms'].to_i
468
+ @architectures = hash['architectures'].to_i
469
+ @module_segments = hash['module_segments'].to_i
470
+ @module_imports = hash['module_imports'].to_i
471
+ @module_exports = hash['module_exports'].to_i
472
+ @last_update = Time.at(hash['last_update'].to_i)
473
+ end
474
+
475
+ #
476
+ # The number of modules found within the opcode database.
477
+ #
478
+ attr_reader :modules
479
+ #
480
+ # The number of opcodes supported by the opcode database.
481
+ #
482
+ attr_reader :opcodes
483
+ #
484
+ # The number of opcode types supported by the database.
485
+ #
486
+ attr_reader :opcode_types
487
+ #
488
+ # The number of platforms supported by the database.
489
+ #
490
+ attr_reader :platforms
491
+ #
492
+ # The number of architectures supported by the database.
493
+ #
494
+ attr_reader :architectures
495
+ #
496
+ # The number of module segments supported by the database.
497
+ #
498
+ attr_reader :module_segments
499
+ #
500
+ # The number of module imports supported by the database.
501
+ #
502
+ attr_reader :module_imports
503
+ #
504
+ # The number of module exports supported by the database.
505
+ #
506
+ attr_reader :module_exports
507
+ #
508
+ # The time at which the last database update occurred.
509
+ #
510
+ attr_reader :last_update
511
+ end
512
+
513
+ ###
514
+ #
515
+ # This class implements a client interface to the Metasploit Opcode Database.
516
+ # It is intended to be used as a method of locating reliable return addresses
517
+ # given a set of executable files and a set of usable opcodes.
518
+ #
519
+ ###
520
+ class Client
521
+
522
+ DefaultServerHost = "www.metasploit.com"
523
+ DefaultServerPort = 80
524
+ DefaultServerUri = "/users/opcode/msfopcode_server.cgi"
525
+
526
+ #
527
+ # Returns an instance of an initialized client that will use the supplied
528
+ # server values.
529
+ #
530
+ def initialize(host = DefaultServerHost, port = DefaultServerPort, uri = DefaultServerUri)
531
+ self.server_host = host
532
+ self.server_port = port
533
+ self.server_uri = uri
534
+ end
535
+
536
+ #
537
+ # Disables response parsing.
538
+ #
539
+ def disable_parse
540
+ @disable_parse = true
541
+ end
542
+
543
+ #
544
+ # Enables response parsing.
545
+ #
546
+ def enable_parse
547
+ @disable_parse = false
548
+ end
549
+
550
+ #
551
+ # Returns an array of MetaType instances.
552
+ #
553
+ def meta_types
554
+ request('meta_types').map { |ent| MetaType.create(ent) }
555
+ end
556
+
557
+ #
558
+ # Returns an array of Group instances.
559
+ #
560
+ def groups
561
+ request('groups').map { |ent| Group.create(ent) }
562
+ end
563
+
564
+ #
565
+ # Returns an array of Type instances. Opcode types are specific opcodes,
566
+ # such as a jmp esp. Optionally, a filter hash can be passed to include
567
+ # extra information in the results.
568
+ #
569
+ # Statistics (Bool)
570
+ #
571
+ # If this hash element is set to true, the number of opcodes currently in
572
+ # the database of this type will be returned.
573
+ #
574
+ def types(filter = {})
575
+ request('types', filter).map { |ent| Type.create(ent) }
576
+ end
577
+
578
+ #
579
+ # Returns an array of OsVersion instances. OS versions are associated with
580
+ # a particular operating system release (including service packs).
581
+ # Optionally, a filter hash can be passed to limit the number of results
582
+ # returned. If no filter hash is supplied, all results are returned.
583
+ #
584
+ # Names (Array)
585
+ #
586
+ # If this hash element is specified, only the operating systems that
587
+ # contain one or more of the names specified will be returned.
588
+ #
589
+ # Statistics (Bool)
590
+ #
591
+ # If this hash element is set to true, the number of modules associated
592
+ # with this matched operating system versions will be returned.
593
+ #
594
+ def platforms(filter = {})
595
+ request('platforms', filter).map { |ent| OsVersion.create(ent) }
596
+ end
597
+
598
+ #
599
+ # Returns an array of ImageModule instances. Image modules are
600
+ # version-specific, locale-specific, and operating system version specific
601
+ # image files. Modules have opcodes, segments, imports and exports
602
+ # associated with them. Optionally, a filter hash can be specified to
603
+ # limit the number of results returned from the database. If no filter
604
+ # hash is supplied, all modules will be returned.
605
+ #
606
+ # LocaleNames (Array)
607
+ #
608
+ # This hash element limits results to one or more specific locale by name.
609
+ #
610
+ # PlatformNames (Array)
611
+ #
612
+ # This hash element limits results to one or more specific platform by
613
+ # name.
614
+ #
615
+ # ModuleNames (Array)
616
+ #
617
+ # This hash element limits results to one or more specific module by name.
618
+ #
619
+ # Segments (Bool)
620
+ #
621
+ # If this hash element is set to true, the segments associated with each
622
+ # resulting module will be returned by the server.
623
+ #
624
+ # Imports (Bool)
625
+ #
626
+ # If this hash element is set to true, the imports associated with each
627
+ # resulting module will be returned by the server.
628
+ #
629
+ # Exports (Bool)
630
+ #
631
+ # If this hash element is set to true, the exports associated with each
632
+ # resulting module will be returned by the server.
633
+ #
634
+ def modules(filter = {})
635
+ request('modules', filter).map { |ent| ImageModule.create(ent) }
636
+ end
637
+
638
+ #
639
+ # Returns an array of Locale instances that are supported by the server.
640
+ #
641
+ def locales
642
+ request('locales').map { |ent| Locale.create(ent) }
643
+ end
644
+
645
+ #
646
+ # Returns an array of Opcode instances that match the filter limitations
647
+ # specified in the supplied filter hash. If no filter hash is specified,
648
+ # all opcodes will be returned (but are most likely going to be limited by
649
+ # the server). The filter hash limiters that can be specified are:
650
+ #
651
+ # ModuleNames (Array)
652
+ #
653
+ # This hash element limits results to one or more specific modules by
654
+ # name.
655
+ #
656
+ # GroupNames (Array)
657
+ #
658
+ # This hash element limits results to one or more specific opcode group by
659
+ # name.
660
+ #
661
+ # TypeNames (Array)
662
+ #
663
+ # This hash element limits results to one or more specific opcode type by
664
+ # name.
665
+ #
666
+ # MetaTypeNames (Array)
667
+ #
668
+ # This hash element limits results to one or more specific opcode meta
669
+ # type by name.
670
+ #
671
+ # LocaleNames (Array)
672
+ #
673
+ # Limits results to one or more specific locale by name.
674
+ #
675
+ # PlatformNames (Array)
676
+ #
677
+ # Limits reslts to one or more specific operating system version by name.
678
+ #
679
+ # Addresses (Array)
680
+ #
681
+ # Limits results to a specific set of addresses.
682
+ #
683
+ # Portable (Bool)
684
+ #
685
+ # If this hash element is true, opcode results will be limited to ones
686
+ # that span more than one operating system version.
687
+ #
688
+ def search(filter = {})
689
+ request('search', filter).map { |ent| Opcode.new(ent) }
690
+ end
691
+
692
+ #
693
+ # Returns an instance of the Statistics class that holds information about
694
+ # the server's database stats.
695
+ #
696
+ def statistics
697
+ Statistics.new(request('statistics'))
698
+ end
699
+
700
+ #
701
+ # These attributes convey information about the remote server and can be
702
+ # changed in order to point it to a locate copy as necessary.
703
+ #
704
+ attr_accessor :server_host, :server_port, :server_uri
705
+
706
+ #
707
+ # Retrieves the last raw XML response to be processed.
708
+ #
709
+ attr_reader :last_xml
710
+
711
+ protected
712
+
713
+ #
714
+ # Transmits a request to the Opcode database server and translates the
715
+ # response into a native general ruby datatype.
716
+ #
717
+ def request(method, opts = {})
718
+ client = Rex::Proto::Http::Client.new(server_host, server_port)
719
+
720
+ begin
721
+
722
+ # Create the CGI parameter list
723
+ vars = { 'method' => method }
724
+
725
+ opts.each_pair do |k, v|
726
+ vars[k] = xlate_param(v)
727
+ end
728
+
729
+ client.set_config('uri_encode_mode' => 'none')
730
+
731
+ # Initialize the request with the POST body.
732
+ request = client.request_cgi(
733
+ 'method' => 'POST',
734
+ 'uri' => server_uri,
735
+ 'vars_post' => vars
736
+ )
737
+
738
+ # Send the request and grab the response.
739
+ response = client.send_recv(request, 300)
740
+
741
+ # Non-200 return code?
742
+ if (response.code != 200)
743
+ raise RuntimeError, "Invalid response received from server."
744
+ end
745
+
746
+ # Convert the return value to the native type.
747
+ parse_response(response.body)
748
+ rescue ::SocketError
749
+ raise RuntimeError, "Could not communicate with the opcode service: #{$!.class} #{$!}"
750
+ ensure
751
+ client.close
752
+ end
753
+ end
754
+
755
+ #
756
+ # Translates a parameter into a flat CGI parameter string.
757
+ #
758
+ def xlate_param(v)
759
+ if (v.kind_of?(Array))
760
+ v.map { |ent|
761
+ xlate_param(ent)
762
+ }.join(',,')
763
+ elsif (v.kind_of?(Hash))
764
+ v.map { |k,v|
765
+ "#{URI.escape(k)}:#{xlate_param(v)}" if (v)
766
+ }.join(',,')
767
+ else
768
+ URI.escape(v.to_s)
769
+ end
770
+ end
771
+
772
+ #
773
+ # Translate the data type from a flat string to a ruby native type.
774
+ #
775
+ def parse_response(xml)
776
+ @last_xml = xml
777
+
778
+ if (!@disable_parse)
779
+ source = REXML::Source.new(xml)
780
+ doc = REXML::Document.new
781
+
782
+ REXML::Parsers::TreeParser.new(source, doc).parse
783
+
784
+ translate_element(doc.root)
785
+ end
786
+ end
787
+
788
+ #
789
+ # Translate elements conveyed as data types.
790
+ #
791
+ def translate_element(element)
792
+ case element.name
793
+ when "Array"
794
+ return element.elements.map { |child| translate_element(child) }
795
+ when "Hash"
796
+ hsh = {}
797
+
798
+ element.each_element { |child|
799
+ if (e = child.elements[1])
800
+ v = translate_element(e)
801
+ else
802
+ v = child.text
803
+ end
804
+
805
+ hsh[child.attributes['name']] = v
806
+ }
807
+
808
+ return hsh
809
+ else
810
+ return element.text
811
+ end
812
+ end
813
+
814
+ end
815
+
816
+ end
817
+ end
818
+ end