rex 1.0.2 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (528) hide show
  1. checksums.yaml +15 -0
  2. data/README.markdown +22 -0
  3. data/examples/smb_example.rb +35 -0
  4. data/lib/rex.rb +108 -3
  5. data/lib/rex/LICENSE +29 -0
  6. data/lib/rex/arch.rb +104 -0
  7. data/lib/rex/arch/sparc.rb +75 -0
  8. data/lib/rex/arch/x86.rb +524 -0
  9. data/lib/rex/assembly/nasm.rb +104 -0
  10. data/lib/rex/codepage.map +104 -0
  11. data/lib/rex/compat.rb +389 -0
  12. data/lib/rex/constants.rb +124 -0
  13. data/lib/rex/elfparsey.rb +9 -0
  14. data/lib/rex/elfparsey/elf.rb +121 -0
  15. data/lib/rex/elfparsey/elfbase.rb +256 -0
  16. data/lib/rex/elfparsey/exceptions.rb +25 -0
  17. data/lib/rex/elfscan.rb +10 -0
  18. data/lib/rex/elfscan/scanner.rb +226 -0
  19. data/lib/rex/elfscan/search.rb +44 -0
  20. data/lib/rex/encoder/alpha2.rb +31 -0
  21. data/lib/rex/encoder/alpha2/alpha_mixed.rb +68 -0
  22. data/lib/rex/encoder/alpha2/alpha_upper.rb +79 -0
  23. data/lib/rex/encoder/alpha2/generic.rb +90 -0
  24. data/lib/rex/encoder/alpha2/unicode_mixed.rb +116 -0
  25. data/lib/rex/encoder/alpha2/unicode_upper.rb +123 -0
  26. data/lib/rex/encoder/bloxor/bloxor.rb +327 -0
  27. data/lib/rex/encoder/ndr.rb +90 -0
  28. data/lib/rex/encoder/nonalpha.rb +61 -0
  29. data/lib/rex/encoder/nonupper.rb +64 -0
  30. data/lib/rex/encoder/xdr.rb +107 -0
  31. data/lib/rex/encoder/xor.rb +69 -0
  32. data/lib/rex/encoder/xor/dword.rb +13 -0
  33. data/lib/rex/encoder/xor/dword_additive.rb +13 -0
  34. data/lib/rex/encoders/xor_dword.rb +35 -0
  35. data/lib/rex/encoders/xor_dword_additive.rb +53 -0
  36. data/lib/rex/encoding/xor.rb +20 -0
  37. data/lib/rex/encoding/xor/byte.rb +15 -0
  38. data/lib/rex/encoding/xor/dword.rb +21 -0
  39. data/lib/rex/encoding/xor/dword_additive.rb +92 -0
  40. data/lib/rex/encoding/xor/exceptions.rb +17 -0
  41. data/lib/rex/encoding/xor/generic.rb +146 -0
  42. data/lib/rex/encoding/xor/qword.rb +15 -0
  43. data/lib/rex/encoding/xor/word.rb +21 -0
  44. data/lib/rex/exceptions.rb +275 -0
  45. data/lib/rex/exploitation/cmdstager.rb +10 -0
  46. data/lib/rex/exploitation/cmdstager/base.rb +190 -0
  47. data/lib/rex/exploitation/cmdstager/bourne.rb +105 -0
  48. data/lib/rex/exploitation/cmdstager/debug_asm.rb +140 -0
  49. data/lib/rex/exploitation/cmdstager/debug_write.rb +134 -0
  50. data/lib/rex/exploitation/cmdstager/echo.rb +164 -0
  51. data/lib/rex/exploitation/cmdstager/printf.rb +122 -0
  52. data/lib/rex/exploitation/cmdstager/tftp.rb +71 -0
  53. data/lib/rex/exploitation/cmdstager/vbs.rb +126 -0
  54. data/lib/rex/exploitation/egghunter.rb +425 -0
  55. data/lib/rex/exploitation/encryptjs.rb +78 -0
  56. data/lib/rex/exploitation/heaplib.js.b64 +331 -0
  57. data/lib/rex/exploitation/heaplib.rb +107 -0
  58. data/lib/rex/exploitation/js.rb +6 -0
  59. data/lib/rex/exploitation/js/detect.rb +69 -0
  60. data/lib/rex/exploitation/js/memory.rb +81 -0
  61. data/lib/rex/exploitation/js/network.rb +84 -0
  62. data/lib/rex/exploitation/js/utils.rb +33 -0
  63. data/lib/rex/exploitation/jsobfu.rb +513 -0
  64. data/lib/rex/exploitation/obfuscatejs.rb +336 -0
  65. data/lib/rex/exploitation/omelet.rb +321 -0
  66. data/lib/rex/exploitation/opcodedb.rb +819 -0
  67. data/lib/rex/exploitation/powershell.rb +62 -0
  68. data/lib/rex/exploitation/powershell/function.rb +63 -0
  69. data/lib/rex/exploitation/powershell/obfu.rb +98 -0
  70. data/lib/rex/exploitation/powershell/output.rb +151 -0
  71. data/lib/rex/exploitation/powershell/param.rb +23 -0
  72. data/lib/rex/exploitation/powershell/parser.rb +183 -0
  73. data/lib/rex/exploitation/powershell/psh_methods.rb +70 -0
  74. data/lib/rex/exploitation/powershell/script.rb +99 -0
  75. data/lib/rex/exploitation/ropdb.rb +190 -0
  76. data/lib/rex/exploitation/seh.rb +93 -0
  77. data/lib/rex/file.rb +160 -0
  78. data/lib/rex/image_source.rb +10 -0
  79. data/lib/rex/image_source/disk.rb +58 -0
  80. data/lib/rex/image_source/image_source.rb +44 -0
  81. data/lib/rex/image_source/memory.rb +35 -0
  82. data/lib/rex/io/bidirectional_pipe.rb +161 -0
  83. data/lib/rex/io/datagram_abstraction.rb +35 -0
  84. data/lib/rex/io/ring_buffer.rb +369 -0
  85. data/lib/rex/io/stream.rb +312 -0
  86. data/lib/rex/io/stream_abstraction.rb +209 -0
  87. data/lib/rex/io/stream_server.rb +221 -0
  88. data/lib/rex/job_container.rb +200 -0
  89. data/lib/rex/logging.rb +4 -0
  90. data/lib/rex/logging/log_dispatcher.rb +180 -0
  91. data/lib/rex/logging/log_sink.rb +43 -0
  92. data/lib/rex/logging/sinks/flatfile.rb +56 -0
  93. data/lib/rex/logging/sinks/stderr.rb +44 -0
  94. data/lib/rex/mac_oui.rb +16581 -0
  95. data/lib/rex/machparsey.rb +9 -0
  96. data/lib/rex/machparsey/exceptions.rb +34 -0
  97. data/lib/rex/machparsey/mach.rb +209 -0
  98. data/lib/rex/machparsey/machbase.rb +408 -0
  99. data/lib/rex/machscan.rb +9 -0
  100. data/lib/rex/machscan/scanner.rb +217 -0
  101. data/lib/rex/mime.rb +10 -0
  102. data/lib/rex/mime/encoding.rb +17 -0
  103. data/lib/rex/mime/header.rb +78 -0
  104. data/lib/rex/mime/message.rb +150 -0
  105. data/lib/rex/mime/part.rb +50 -0
  106. data/lib/rex/nop/opty2.rb +109 -0
  107. data/lib/rex/nop/opty2_tables.rb +301 -0
  108. data/lib/rex/ole.rb +202 -0
  109. data/lib/rex/ole/clsid.rb +44 -0
  110. data/lib/rex/ole/difat.rb +138 -0
  111. data/lib/rex/ole/directory.rb +228 -0
  112. data/lib/rex/ole/direntry.rb +237 -0
  113. data/lib/rex/ole/docs/dependencies.txt +8 -0
  114. data/lib/rex/ole/docs/references.txt +1 -0
  115. data/lib/rex/ole/fat.rb +96 -0
  116. data/lib/rex/ole/header.rb +201 -0
  117. data/lib/rex/ole/minifat.rb +74 -0
  118. data/lib/rex/ole/propset.rb +141 -0
  119. data/lib/rex/ole/samples/create_ole.rb +27 -0
  120. data/lib/rex/ole/samples/dir.rb +35 -0
  121. data/lib/rex/ole/samples/dump_stream.rb +34 -0
  122. data/lib/rex/ole/samples/ole_info.rb +23 -0
  123. data/lib/rex/ole/storage.rb +392 -0
  124. data/lib/rex/ole/stream.rb +50 -0
  125. data/lib/rex/ole/substorage.rb +46 -0
  126. data/lib/rex/ole/util.rb +154 -0
  127. data/lib/rex/parser/acunetix_nokogiri.rb +406 -0
  128. data/lib/rex/parser/apple_backup_manifestdb.rb +132 -0
  129. data/lib/rex/parser/appscan_nokogiri.rb +367 -0
  130. data/lib/rex/parser/arguments.rb +108 -0
  131. data/lib/rex/parser/burp_session_nokogiri.rb +291 -0
  132. data/lib/rex/parser/ci_nokogiri.rb +193 -0
  133. data/lib/rex/parser/foundstone_nokogiri.rb +342 -0
  134. data/lib/rex/parser/fusionvm_nokogiri.rb +109 -0
  135. data/lib/rex/parser/group_policy_preferences.rb +185 -0
  136. data/lib/rex/parser/ini.rb +186 -0
  137. data/lib/rex/parser/ip360_aspl_xml.rb +103 -0
  138. data/lib/rex/parser/ip360_xml.rb +98 -0
  139. data/lib/rex/parser/mbsa_nokogiri.rb +256 -0
  140. data/lib/rex/parser/nessus_xml.rb +121 -0
  141. data/lib/rex/parser/netsparker_xml.rb +109 -0
  142. data/lib/rex/parser/nexpose_raw_nokogiri.rb +686 -0
  143. data/lib/rex/parser/nexpose_simple_nokogiri.rb +330 -0
  144. data/lib/rex/parser/nexpose_xml.rb +172 -0
  145. data/lib/rex/parser/nmap_nokogiri.rb +394 -0
  146. data/lib/rex/parser/nmap_xml.rb +166 -0
  147. data/lib/rex/parser/nokogiri_doc_mixin.rb +233 -0
  148. data/lib/rex/parser/openvas_nokogiri.rb +172 -0
  149. data/lib/rex/parser/outpost24_nokogiri.rb +240 -0
  150. data/lib/rex/parser/retina_xml.rb +110 -0
  151. data/lib/rex/parser/unattend.rb +171 -0
  152. data/lib/rex/parser/wapiti_nokogiri.rb +105 -0
  153. data/lib/rex/payloads.rb +2 -0
  154. data/lib/rex/payloads/win32.rb +3 -0
  155. data/lib/rex/payloads/win32/common.rb +27 -0
  156. data/lib/rex/payloads/win32/kernel.rb +54 -0
  157. data/lib/rex/payloads/win32/kernel/common.rb +55 -0
  158. data/lib/rex/payloads/win32/kernel/migration.rb +13 -0
  159. data/lib/rex/payloads/win32/kernel/recovery.rb +51 -0
  160. data/lib/rex/payloads/win32/kernel/stager.rb +195 -0
  161. data/lib/rex/peparsey.rb +10 -0
  162. data/lib/rex/peparsey/exceptions.rb +30 -0
  163. data/lib/rex/peparsey/pe.rb +210 -0
  164. data/lib/rex/peparsey/pe_memdump.rb +61 -0
  165. data/lib/rex/peparsey/pebase.rb +1662 -0
  166. data/lib/rex/peparsey/section.rb +128 -0
  167. data/lib/rex/pescan.rb +11 -0
  168. data/lib/rex/pescan/analyze.rb +366 -0
  169. data/lib/rex/pescan/scanner.rb +230 -0
  170. data/lib/rex/pescan/search.rb +68 -0
  171. data/lib/rex/platforms.rb +2 -0
  172. data/lib/rex/platforms/windows.rb +52 -0
  173. data/lib/rex/poly.rb +134 -0
  174. data/lib/rex/poly/block.rb +480 -0
  175. data/lib/rex/poly/machine.rb +13 -0
  176. data/lib/rex/poly/machine/machine.rb +830 -0
  177. data/lib/rex/poly/machine/x86.rb +509 -0
  178. data/lib/rex/poly/register.rb +101 -0
  179. data/lib/rex/poly/register/x86.rb +41 -0
  180. data/lib/rex/post.rb +7 -0
  181. data/lib/rex/post/dir.rb +51 -0
  182. data/lib/rex/post/file.rb +172 -0
  183. data/lib/rex/post/file_stat.rb +220 -0
  184. data/lib/rex/post/gen.pl +13 -0
  185. data/lib/rex/post/io.rb +182 -0
  186. data/lib/rex/post/meterpreter.rb +5 -0
  187. data/lib/rex/post/meterpreter/channel.rb +446 -0
  188. data/lib/rex/post/meterpreter/channel_container.rb +54 -0
  189. data/lib/rex/post/meterpreter/channels/pool.rb +160 -0
  190. data/lib/rex/post/meterpreter/channels/pools/file.rb +62 -0
  191. data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +103 -0
  192. data/lib/rex/post/meterpreter/channels/stream.rb +87 -0
  193. data/lib/rex/post/meterpreter/client.rb +483 -0
  194. data/lib/rex/post/meterpreter/client_core.rb +352 -0
  195. data/lib/rex/post/meterpreter/dependencies.rb +3 -0
  196. data/lib/rex/post/meterpreter/extension.rb +32 -0
  197. data/lib/rex/post/meterpreter/extensions/android/android.rb +128 -0
  198. data/lib/rex/post/meterpreter/extensions/android/tlv.rb +40 -0
  199. data/lib/rex/post/meterpreter/extensions/espia/espia.rb +58 -0
  200. data/lib/rex/post/meterpreter/extensions/espia/tlv.rb +17 -0
  201. data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +71 -0
  202. data/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb +169 -0
  203. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +45 -0
  204. data/lib/rex/post/meterpreter/extensions/extapi/service/service.rb +104 -0
  205. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +77 -0
  206. data/lib/rex/post/meterpreter/extensions/extapi/window/window.rb +56 -0
  207. data/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb +75 -0
  208. data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +94 -0
  209. data/lib/rex/post/meterpreter/extensions/incognito/tlv.rb +22 -0
  210. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +361 -0
  211. data/lib/rex/post/meterpreter/extensions/kiwi/tlv.rb +76 -0
  212. data/lib/rex/post/meterpreter/extensions/lanattacks/dhcp/dhcp.rb +78 -0
  213. data/lib/rex/post/meterpreter/extensions/lanattacks/lanattacks.rb +43 -0
  214. data/lib/rex/post/meterpreter/extensions/lanattacks/tftp/tftp.rb +49 -0
  215. data/lib/rex/post/meterpreter/extensions/lanattacks/tlv.rb +17 -0
  216. data/lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb +128 -0
  217. data/lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb +16 -0
  218. data/lib/rex/post/meterpreter/extensions/networkpug/networkpug.rb +57 -0
  219. data/lib/rex/post/meterpreter/extensions/networkpug/tlv.rb +16 -0
  220. data/lib/rex/post/meterpreter/extensions/priv/fs.rb +118 -0
  221. data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +61 -0
  222. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +109 -0
  223. data/lib/rex/post/meterpreter/extensions/priv/tlv.rb +29 -0
  224. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +117 -0
  225. data/lib/rex/post/meterpreter/extensions/sniffer/tlv.rb +27 -0
  226. data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +396 -0
  227. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +284 -0
  228. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +399 -0
  229. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +104 -0
  230. data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +48 -0
  231. data/lib/rex/post/meterpreter/extensions/stdapi/net/arp.rb +59 -0
  232. data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +256 -0
  233. data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +129 -0
  234. data/lib/rex/post/meterpreter/extensions/stdapi/net/netstat.rb +97 -0
  235. data/lib/rex/post/meterpreter/extensions/stdapi/net/resolve.rb +106 -0
  236. data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +67 -0
  237. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +139 -0
  238. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +180 -0
  239. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +168 -0
  240. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +209 -0
  241. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +38146 -0
  242. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +48 -0
  243. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +2102 -0
  244. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_crypt32.rb +32 -0
  245. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_iphlpapi.rb +97 -0
  246. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3852 -0
  247. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +100 -0
  248. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ntdll.rb +168 -0
  249. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_psapi.rb +32 -0
  250. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_shell32.rb +32 -0
  251. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_user32.rb +3170 -0
  252. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_version.rb +41 -0
  253. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wlanapi.rb +87 -0
  254. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb +128 -0
  255. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ws2_32.rb +613 -0
  256. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +388 -0
  257. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +111 -0
  258. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +149 -0
  259. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb +27 -0
  260. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/mock_magic.rb +515 -0
  261. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +319 -0
  262. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb +23 -0
  263. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +301 -0
  264. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb +56 -0
  265. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb +106 -0
  266. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +676 -0
  267. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +96 -0
  268. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +151 -0
  269. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +128 -0
  270. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +192 -0
  271. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +41 -0
  272. data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +60 -0
  273. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +408 -0
  274. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +129 -0
  275. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +55 -0
  276. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +336 -0
  277. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +141 -0
  278. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +328 -0
  279. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +193 -0
  280. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +102 -0
  281. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb +188 -0
  282. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +180 -0
  283. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +236 -0
  284. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +259 -0
  285. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +201 -0
  286. data/lib/rex/post/meterpreter/inbound_packet_handler.rb +30 -0
  287. data/lib/rex/post/meterpreter/object_aliases.rb +83 -0
  288. data/lib/rex/post/meterpreter/packet.rb +709 -0
  289. data/lib/rex/post/meterpreter/packet_dispatcher.rb +543 -0
  290. data/lib/rex/post/meterpreter/packet_parser.rb +94 -0
  291. data/lib/rex/post/meterpreter/packet_response_waiter.rb +83 -0
  292. data/lib/rex/post/meterpreter/ui/console.rb +142 -0
  293. data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +86 -0
  294. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +383 -0
  295. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +939 -0
  296. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +109 -0
  297. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi.rb +65 -0
  298. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +198 -0
  299. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +444 -0
  300. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb +199 -0
  301. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb +118 -0
  302. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb +108 -0
  303. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +242 -0
  304. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +509 -0
  305. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks.rb +60 -0
  306. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +254 -0
  307. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/tftp.rb +159 -0
  308. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +182 -0
  309. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/networkpug.rb +232 -0
  310. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +62 -0
  311. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +97 -0
  312. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +52 -0
  313. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +133 -0
  314. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +204 -0
  315. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +66 -0
  316. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +527 -0
  317. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +448 -0
  318. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +906 -0
  319. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +318 -0
  320. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +343 -0
  321. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +99 -0
  322. data/lib/rex/post/permission.rb +26 -0
  323. data/lib/rex/post/process.rb +57 -0
  324. data/lib/rex/post/thread.rb +57 -0
  325. data/lib/rex/post/ui.rb +52 -0
  326. data/lib/rex/proto.rb +15 -0
  327. data/lib/rex/proto/addp.rb +218 -0
  328. data/lib/rex/proto/dcerpc.rb +7 -0
  329. data/lib/rex/proto/dcerpc/client.rb +362 -0
  330. data/lib/rex/proto/dcerpc/exceptions.rb +151 -0
  331. data/lib/rex/proto/dcerpc/handle.rb +48 -0
  332. data/lib/rex/proto/dcerpc/ndr.rb +73 -0
  333. data/lib/rex/proto/dcerpc/packet.rb +264 -0
  334. data/lib/rex/proto/dcerpc/response.rb +188 -0
  335. data/lib/rex/proto/dcerpc/uuid.rb +85 -0
  336. data/lib/rex/proto/dcerpc/wdscp.rb +3 -0
  337. data/lib/rex/proto/dcerpc/wdscp/constants.rb +89 -0
  338. data/lib/rex/proto/dcerpc/wdscp/packet.rb +94 -0
  339. data/lib/rex/proto/dhcp.rb +7 -0
  340. data/lib/rex/proto/dhcp/constants.rb +34 -0
  341. data/lib/rex/proto/dhcp/server.rb +334 -0
  342. data/lib/rex/proto/drda.rb +6 -0
  343. data/lib/rex/proto/drda/constants.rb +50 -0
  344. data/lib/rex/proto/drda/packet.rb +253 -0
  345. data/lib/rex/proto/drda/utils.rb +124 -0
  346. data/lib/rex/proto/http.rb +7 -0
  347. data/lib/rex/proto/http/client.rb +722 -0
  348. data/lib/rex/proto/http/client_request.rb +472 -0
  349. data/lib/rex/proto/http/handler.rb +47 -0
  350. data/lib/rex/proto/http/handler/erb.rb +129 -0
  351. data/lib/rex/proto/http/handler/proc.rb +61 -0
  352. data/lib/rex/proto/http/header.rb +173 -0
  353. data/lib/rex/proto/http/packet.rb +414 -0
  354. data/lib/rex/proto/http/request.rb +354 -0
  355. data/lib/rex/proto/http/response.rb +151 -0
  356. data/lib/rex/proto/http/server.rb +385 -0
  357. data/lib/rex/proto/iax2.rb +2 -0
  358. data/lib/rex/proto/iax2/call.rb +321 -0
  359. data/lib/rex/proto/iax2/client.rb +218 -0
  360. data/lib/rex/proto/iax2/codecs.rb +5 -0
  361. data/lib/rex/proto/iax2/codecs/alaw.rb +16 -0
  362. data/lib/rex/proto/iax2/codecs/g711.rb +2176 -0
  363. data/lib/rex/proto/iax2/codecs/mulaw.rb +17 -0
  364. data/lib/rex/proto/iax2/constants.rb +262 -0
  365. data/lib/rex/proto/ipmi.rb +57 -0
  366. data/lib/rex/proto/ipmi/channel_auth_reply.rb +89 -0
  367. data/lib/rex/proto/ipmi/open_session_reply.rb +36 -0
  368. data/lib/rex/proto/ipmi/rakp2.rb +36 -0
  369. data/lib/rex/proto/ipmi/utils.rb +125 -0
  370. data/lib/rex/proto/natpmp.rb +7 -0
  371. data/lib/rex/proto/natpmp/constants.rb +19 -0
  372. data/lib/rex/proto/natpmp/packet.rb +45 -0
  373. data/lib/rex/proto/ntlm.rb +8 -0
  374. data/lib/rex/proto/ntlm/base.rb +327 -0
  375. data/lib/rex/proto/ntlm/constants.rb +75 -0
  376. data/lib/rex/proto/ntlm/crypt.rb +412 -0
  377. data/lib/rex/proto/ntlm/exceptions.rb +17 -0
  378. data/lib/rex/proto/ntlm/message.rb +534 -0
  379. data/lib/rex/proto/ntlm/utils.rb +765 -0
  380. data/lib/rex/proto/ntp.rb +3 -0
  381. data/lib/rex/proto/ntp/constants.rb +12 -0
  382. data/lib/rex/proto/ntp/modes.rb +130 -0
  383. data/lib/rex/proto/pjl.rb +31 -0
  384. data/lib/rex/proto/pjl/client.rb +163 -0
  385. data/lib/rex/proto/proxy/socks4a.rb +441 -0
  386. data/lib/rex/proto/rfb.rb +13 -0
  387. data/lib/rex/proto/rfb/cipher.rb +82 -0
  388. data/lib/rex/proto/rfb/client.rb +205 -0
  389. data/lib/rex/proto/rfb/constants.rb +50 -0
  390. data/lib/rex/proto/sip.rb +4 -0
  391. data/lib/rex/proto/sip/response.rb +61 -0
  392. data/lib/rex/proto/smb.rb +8 -0
  393. data/lib/rex/proto/smb/client.rb +2064 -0
  394. data/lib/rex/proto/smb/constants.rb +1064 -0
  395. data/lib/rex/proto/smb/crypt.rb +37 -0
  396. data/lib/rex/proto/smb/evasions.rb +67 -0
  397. data/lib/rex/proto/smb/exceptions.rb +867 -0
  398. data/lib/rex/proto/smb/simpleclient.rb +173 -0
  399. data/lib/rex/proto/smb/simpleclient/open_file.rb +106 -0
  400. data/lib/rex/proto/smb/simpleclient/open_pipe.rb +57 -0
  401. data/lib/rex/proto/smb/utils.rb +104 -0
  402. data/lib/rex/proto/sunrpc.rb +2 -0
  403. data/lib/rex/proto/sunrpc/client.rb +196 -0
  404. data/lib/rex/proto/tftp.rb +13 -0
  405. data/lib/rex/proto/tftp/client.rb +344 -0
  406. data/lib/rex/proto/tftp/constants.rb +39 -0
  407. data/lib/rex/proto/tftp/server.rb +497 -0
  408. data/lib/rex/random_identifier_generator.rb +177 -0
  409. data/lib/rex/registry.rb +14 -0
  410. data/lib/rex/registry/hive.rb +132 -0
  411. data/lib/rex/registry/lfkey.rb +51 -0
  412. data/lib/rex/registry/nodekey.rb +54 -0
  413. data/lib/rex/registry/regf.rb +25 -0
  414. data/lib/rex/registry/valuekey.rb +67 -0
  415. data/lib/rex/registry/valuelist.rb +29 -0
  416. data/lib/rex/ropbuilder.rb +8 -0
  417. data/lib/rex/ropbuilder/rop.rb +271 -0
  418. data/lib/rex/script.rb +42 -0
  419. data/lib/rex/script/base.rb +61 -0
  420. data/lib/rex/script/meterpreter.rb +16 -0
  421. data/lib/rex/script/shell.rb +10 -0
  422. data/lib/rex/service.rb +49 -0
  423. data/lib/rex/service_manager.rb +154 -0
  424. data/lib/rex/services/local_relay.rb +424 -0
  425. data/lib/rex/socket.rb +788 -0
  426. data/lib/rex/socket/comm.rb +120 -0
  427. data/lib/rex/socket/comm/local.rb +526 -0
  428. data/lib/rex/socket/ip.rb +132 -0
  429. data/lib/rex/socket/parameters.rb +363 -0
  430. data/lib/rex/socket/range_walker.rb +470 -0
  431. data/lib/rex/socket/ssl_tcp.rb +345 -0
  432. data/lib/rex/socket/ssl_tcp_server.rb +188 -0
  433. data/lib/rex/socket/subnet_walker.rb +76 -0
  434. data/lib/rex/socket/switch_board.rb +289 -0
  435. data/lib/rex/socket/tcp.rb +79 -0
  436. data/lib/rex/socket/tcp_server.rb +67 -0
  437. data/lib/rex/socket/udp.rb +165 -0
  438. data/lib/rex/sslscan/result.rb +201 -0
  439. data/lib/rex/sslscan/scanner.rb +206 -0
  440. data/lib/rex/struct2.rb +5 -0
  441. data/lib/rex/struct2/c_struct.rb +181 -0
  442. data/lib/rex/struct2/c_struct_template.rb +39 -0
  443. data/lib/rex/struct2/constant.rb +26 -0
  444. data/lib/rex/struct2/element.rb +44 -0
  445. data/lib/rex/struct2/generic.rb +73 -0
  446. data/lib/rex/struct2/restraint.rb +54 -0
  447. data/lib/rex/struct2/s_string.rb +72 -0
  448. data/lib/rex/struct2/s_struct.rb +111 -0
  449. data/lib/rex/sync.rb +6 -0
  450. data/lib/rex/sync/event.rb +85 -0
  451. data/lib/rex/sync/read_write_lock.rb +177 -0
  452. data/lib/rex/sync/ref.rb +58 -0
  453. data/lib/rex/sync/thread_safe.rb +83 -0
  454. data/lib/rex/text.rb +1813 -0
  455. data/lib/rex/thread_factory.rb +43 -0
  456. data/lib/rex/time.rb +66 -0
  457. data/lib/rex/transformer.rb +116 -0
  458. data/lib/rex/ui.rb +22 -0
  459. data/lib/rex/ui/interactive.rb +304 -0
  460. data/lib/rex/ui/output.rb +85 -0
  461. data/lib/rex/ui/output/none.rb +19 -0
  462. data/lib/rex/ui/progress_tracker.rb +97 -0
  463. data/lib/rex/ui/subscriber.rb +160 -0
  464. data/lib/rex/ui/text/color.rb +98 -0
  465. data/lib/rex/ui/text/dispatcher_shell.rb +538 -0
  466. data/lib/rex/ui/text/input.rb +119 -0
  467. data/lib/rex/ui/text/input/buffer.rb +79 -0
  468. data/lib/rex/ui/text/input/readline.rb +129 -0
  469. data/lib/rex/ui/text/input/socket.rb +96 -0
  470. data/lib/rex/ui/text/input/stdio.rb +46 -0
  471. data/lib/rex/ui/text/irb_shell.rb +62 -0
  472. data/lib/rex/ui/text/output.rb +86 -0
  473. data/lib/rex/ui/text/output/buffer.rb +62 -0
  474. data/lib/rex/ui/text/output/buffer/stdout.rb +26 -0
  475. data/lib/rex/ui/text/output/file.rb +44 -0
  476. data/lib/rex/ui/text/output/socket.rb +44 -0
  477. data/lib/rex/ui/text/output/stdio.rb +53 -0
  478. data/lib/rex/ui/text/output/tee.rb +56 -0
  479. data/lib/rex/ui/text/progress_tracker.rb +57 -0
  480. data/lib/rex/ui/text/shell.rb +403 -0
  481. data/lib/rex/ui/text/table.rb +346 -0
  482. data/lib/rex/zip.rb +96 -0
  483. data/lib/rex/zip/archive.rb +130 -0
  484. data/lib/rex/zip/blocks.rb +184 -0
  485. data/lib/rex/zip/entry.rb +122 -0
  486. data/lib/rex/zip/jar.rb +283 -0
  487. data/lib/rex/zip/samples/comment.rb +32 -0
  488. data/lib/rex/zip/samples/mkwar.rb +138 -0
  489. data/lib/rex/zip/samples/mkzip.rb +19 -0
  490. data/lib/rex/zip/samples/recursive.rb +58 -0
  491. data/rex.gemspec +20 -0
  492. metadata +528 -98
  493. data/CHANGELOG.rdoc +0 -7
  494. data/DOCUMENTATION.en.rdoc +0 -215
  495. data/DOCUMENTATION.ja.rdoc +0 -205
  496. data/Manifest.txt +0 -37
  497. data/README.ja +0 -73
  498. data/README.rdoc +0 -53
  499. data/Rakefile +0 -28
  500. data/bin/rex +0 -18
  501. data/lib/rex/generator.rb +0 -523
  502. data/lib/rex/info.rb +0 -16
  503. data/lib/rex/rexcmd.rb +0 -136
  504. data/sample/a.cmd +0 -1
  505. data/sample/b.cmd +0 -1
  506. data/sample/c.cmd +0 -4
  507. data/sample/calc3.racc +0 -47
  508. data/sample/calc3.rex +0 -15
  509. data/sample/calc3.rex.rb +0 -94
  510. data/sample/calc3.tab.rb +0 -188
  511. data/sample/error1.rex +0 -15
  512. data/sample/error2.rex +0 -15
  513. data/sample/sample.html +0 -32
  514. data/sample/sample.rex +0 -15
  515. data/sample/sample.rex.rb +0 -100
  516. data/sample/sample.xhtml +0 -32
  517. data/sample/sample1.c +0 -9
  518. data/sample/sample1.rex +0 -43
  519. data/sample/sample2.bas +0 -4
  520. data/sample/sample2.rex +0 -33
  521. data/sample/simple.html +0 -7
  522. data/sample/simple.xhtml +0 -10
  523. data/sample/xhtmlparser.racc +0 -66
  524. data/sample/xhtmlparser.rex +0 -72
  525. data/test/assets/test.rex +0 -12
  526. data/test/rex-20060125.rb +0 -152
  527. data/test/rex-20060511.rb +0 -143
  528. data/test/test_generator.rb +0 -184
@@ -0,0 +1,13 @@
1
+ # -*- coding: binary -*-
2
+ #
3
+ # RFB protocol support
4
+ #
5
+ # @author Joshua J. Drake <jduck>
6
+ #
7
+ # Based on:
8
+ # vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
9
+ # vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
10
+
11
+ require 'rex/proto/rfb/constants'
12
+ require 'rex/proto/rfb/cipher'
13
+ require 'rex/proto/rfb/client'
@@ -0,0 +1,82 @@
1
+ # -*- coding: binary -*-
2
+
3
+ ##
4
+ #
5
+ # RFB protocol support
6
+ #
7
+ # by Joshua J. Drake <jduck>
8
+ #
9
+ # Based on:
10
+ # vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
11
+ # vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
12
+ #
13
+ ##
14
+
15
+ # Required for VNC authentication
16
+ require 'openssl'
17
+
18
+ module Rex
19
+ module Proto
20
+ module RFB
21
+
22
+ ##
23
+ # A bit of information about the DES algorithm was found here:
24
+ # http://www.vidarholen.net/contents/junk/vnc.html
25
+ #
26
+ # In addition, VNC uses two individual 8 byte block encryptions rather than
27
+ # using any block mode (like cbc, ecb, etc).
28
+ ##
29
+
30
+ class Cipher
31
+
32
+ def self.mangle_password(password)
33
+ key = ''
34
+ key = password.dup if password
35
+ key.slice!(8,key.length) if key.length > 8
36
+ key << "\x00" * (8 - key.length) if key.length < 8
37
+
38
+ # We have to mangle the key so the LSB are kept vs the MSB
39
+ [key.unpack('B*').first.scan(/.{8}/).map! { |e| e.reverse }.join].pack('B*')
40
+ end
41
+
42
+ def self.encrypt(plain, password)
43
+ key = self.mangle_password(password)
44
+
45
+ # pad the plain to 16 chars
46
+ plain << ("\x00" * (16 - plain.length)) if plain.length < 16
47
+
48
+ # VNC auth does two 8-byte blocks individually instead supporting some block mode
49
+ cipher = ''
50
+ 2.times { |x|
51
+ c = OpenSSL::Cipher::Cipher.new('des')
52
+ c.encrypt
53
+ c.key = key
54
+ cipher << c.update(plain[x*8, 8])
55
+ }
56
+
57
+ cipher
58
+ end
59
+
60
+ #
61
+ # NOTE: The default password is that of winvnc/etc which is used for
62
+ # encrypting the password(s) on disk/in registry.
63
+ #
64
+ def self.decrypt(cipher, password = "\x17\x52\x6b\x06\x23\x4e\x58\x07")
65
+ key = self.mangle_password(password)
66
+
67
+ # pad the cipher text to 9 bytes
68
+ cipher << ("\x00" * (9 - cipher.length)) if cipher.length < 9
69
+
70
+ # NOTE: This only does one 8 byte block
71
+ plain = ''
72
+ c = OpenSSL::Cipher::Cipher.new('des')
73
+ c.decrypt
74
+ c.key = key
75
+ c.update(cipher)
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,205 @@
1
+ # -*- coding: binary -*-
2
+
3
+ ##
4
+ #
5
+ # RFB protocol support
6
+ #
7
+ # by Joshua J. Drake <jduck>
8
+ #
9
+ # Based on:
10
+ # vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
11
+ # vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
12
+ #
13
+ # TODO: determine how to detect a view-only session.
14
+ ##
15
+
16
+ module Rex
17
+ module Proto
18
+ module RFB
19
+
20
+ class Client
21
+
22
+ def initialize(sock, opts = {})
23
+ @sock = sock
24
+ @opts = opts
25
+
26
+ @banner = nil
27
+ @majver = MajorVersion
28
+ @minver = -1
29
+ @auth_types = []
30
+ end
31
+
32
+ def read_error_message
33
+ len = @sock.get_once(4)
34
+ return 'Unknown error' if not len or len.length != 4
35
+
36
+ len = len.unpack("N").first
37
+ @sock.get_once(len)
38
+ end
39
+
40
+ def handshake
41
+ @banner = @sock.get_once(12)
42
+ if not @banner
43
+ @error = "Unable to obtain banner from server"
44
+ return false
45
+ end
46
+
47
+ # RFB Protocol Version 3.3 (1998-01)
48
+ # RFB Protocol Version 3.7 (2003-08)
49
+ # RFB Protocol Version 3.8 (2007-06)
50
+
51
+ if @banner =~ /RFB ([0-9]{3})\.([0-9]{3})/
52
+ maj = $1.to_i
53
+ if maj != MajorVersion
54
+ @error = "Invalid major version number: #{maj}"
55
+ return false
56
+ end
57
+ else
58
+ @error = "Invalid RFB banner: #{@banner}"
59
+ return false
60
+ end
61
+
62
+ @minver = $2.to_i
63
+
64
+ our_ver = "RFB %03d.%03d\n" % [MajorVersion, @minver]
65
+ @sock.put(our_ver)
66
+
67
+ true
68
+ end
69
+
70
+ def connect(password = nil)
71
+ return false if not handshake
72
+ return false if not authenticate(password)
73
+ return false if not send_client_init
74
+ true
75
+ end
76
+
77
+ def send_client_init
78
+ if @opts[:exclusive]
79
+ @sock.put("\x00") # do share.
80
+ else
81
+ @sock.put("\x01") # do share.
82
+ end
83
+ end
84
+
85
+ def authenticate(password = nil)
86
+ type = negotiate_authentication
87
+ return false if not type
88
+
89
+ # Authenticate.
90
+ case type
91
+ when AuthType::None
92
+ # Nothing here.
93
+
94
+ when AuthType::VNC
95
+ return false if not negotiate_vnc_auth(password)
96
+
97
+ end
98
+
99
+ # Handle reading the security result message
100
+ result = @sock.get_once(4)
101
+ if not result
102
+ @error = "Unable to read auth result"
103
+ return false
104
+ end
105
+
106
+ result = result.unpack('N').first
107
+ case result
108
+ when 0
109
+ return true
110
+
111
+ when 1
112
+ if @minver >= 8
113
+ msg = read_error_message
114
+ @error = "Authentication failed: #{msg}"
115
+ else
116
+ @error = "Authentication failed"
117
+ end
118
+ when 2
119
+ @error = "Too many authentication attempts"
120
+ else
121
+ @error = "Unknown authentication result: #{result}"
122
+ end
123
+
124
+ false
125
+ end
126
+
127
+ def negotiate_authentication
128
+ # Authentication type negotiation is protocol version specific.
129
+ if @minver < 7
130
+ buf = @sock.get_once(4)
131
+ if not buf
132
+ @error = "Unable to obtain requested authentication method"
133
+ return nil
134
+ end
135
+ @auth_types = buf.unpack('N')
136
+ if not @auth_types or @auth_types.first == 0
137
+ msg = read_error_message
138
+ @error = "No authentication types available: #{msg}"
139
+ return nil
140
+ end
141
+ else
142
+ buf = @sock.get_once(1)
143
+ if not buf
144
+ @error = "Unable to obtain supported authentication method count"
145
+ return nil
146
+ end
147
+
148
+ # first byte is number of security types
149
+ num_types = buf.unpack("C").first
150
+ if (num_types == 0)
151
+ msg = read_error_message
152
+ @error = "No authentication types available: #{msg}"
153
+ return nil
154
+ end
155
+
156
+ buf = @sock.get_once(num_types)
157
+ if not buf or buf.length != num_types
158
+ @error = "Unable to read authentication types"
159
+ return nil
160
+ end
161
+
162
+ @auth_types = buf.unpack("C*")
163
+ end
164
+
165
+ if not @auth_types or @auth_types.length < 1
166
+ @error = "No authentication types found"
167
+ return nil
168
+ end
169
+
170
+ # Select the one we prefer
171
+ selected = nil
172
+ selected ||= AuthType::None if @opts[:allow_none] and @auth_types.include? AuthType::None
173
+ selected ||= AuthType::VNC if @auth_types.include? AuthType::VNC
174
+
175
+ if not selected
176
+ @error = "No supported authentication method found."
177
+ return nil
178
+ end
179
+
180
+ # For 3.7 and later, clients must state which security-type to use
181
+ @sock.put([selected].pack('C')) if @minver >= 7
182
+
183
+ selected
184
+ end
185
+
186
+ def negotiate_vnc_auth(password = nil)
187
+ challenge = @sock.get_once(16)
188
+ if not challenge or challenge.length != 16
189
+ @error = "Unable to obtain VNC challenge"
190
+ return false
191
+ end
192
+
193
+ response = Cipher.encrypt(challenge, password)
194
+ @sock.put(response)
195
+
196
+ true
197
+ end
198
+
199
+ attr_reader :error, :majver, :minver, :auth_types
200
+ attr_reader :view_only
201
+ end
202
+
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,50 @@
1
+ # -*- coding: binary -*-
2
+
3
+ ##
4
+ #
5
+ # RFB protocol support
6
+ #
7
+ # by Joshua J. Drake <jduck>
8
+ #
9
+ # Based on:
10
+ # vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
11
+ # vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
12
+ #
13
+ ##
14
+
15
+ module Rex
16
+ module Proto
17
+ module RFB
18
+
19
+ DefaultPort = 5900
20
+
21
+ # Version information
22
+ MajorVersion = 3
23
+ # NOTE: We will emulate whatever minor version the server reports.
24
+
25
+ # Security types
26
+ class AuthType
27
+ Invalid = 0
28
+ None = 1
29
+ VNC = 2
30
+ RA2 = 5
31
+ RA2ne = 6
32
+ Tight = 16
33
+ Ultra = 17
34
+ TLS = 18
35
+ VeNCrypt = 19
36
+ GtkVncSasl = 20
37
+ MD5Hash = 21
38
+ ColinDeanXVP = 22
39
+
40
+ def self.to_s(num)
41
+ self.constants.each { |c|
42
+ return c.to_s if self.const_get(c) == num
43
+ }
44
+ 'Unknown'
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: binary
2
+
3
+ # SIP protocol support
4
+ require 'rex/proto/sip/response'
@@ -0,0 +1,61 @@
1
+ # encoding: binary
2
+
3
+ module Rex
4
+ module Proto
5
+ # SIP protocol support
6
+ module SIP
7
+ SIP_STATUS_REGEX = /^SIP\/(\d\.\d) (\d{3})\s*(.*)$/
8
+
9
+ # Represents a generic SIP message
10
+ class Message
11
+ attr_accessor :headers
12
+
13
+ def initialize
14
+ @headers = {}
15
+ end
16
+
17
+ # Returns a list of all values from all +name+ headers, regardless of case,
18
+ # or nil if no matching header is found
19
+ def header(name)
20
+ matches = @headers.select { |k, _| k.downcase == name.downcase }
21
+ return nil if matches.empty?
22
+ matches.values.flatten
23
+ end
24
+
25
+ # Returns a hash of header name to values mapping
26
+ # from the provided message, or nil if no headers
27
+ # are found
28
+ def self.extract_headers(message)
29
+ pairs = message.scan(/^([^\s:]+):\s*(.*)$/)
30
+ return nil if pairs.empty?
31
+ headers = {}
32
+ pairs.each do |pair|
33
+ headers[pair.first] ||= []
34
+ headers[pair.first] << pair.last.strip
35
+ end
36
+ headers
37
+ end
38
+ end
39
+
40
+ # Represents a SIP response message
41
+ class Response < Message
42
+ attr_accessor :code, :message, :status_line, :version
43
+
44
+ # Parses +data+, constructs and returns a Response
45
+ def self.parse(data)
46
+ response = Response.new
47
+ # do some basic sanity checking on this response to ensure that it is SIP
48
+ response.status_line = data.split(/\r\n/)[0]
49
+ unless response.status_line && response.status_line =~ SIP_STATUS_REGEX
50
+ fail(ArgumentError, "Invalid SIP status line: #{response.status_line}")
51
+ end
52
+ response.version = Regexp.last_match(1)
53
+ response.code = Regexp.last_match(2)
54
+ response.message = Regexp.last_match(3)
55
+ response.headers = extract_headers(data)
56
+ response
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,8 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/proto/smb/constants'
3
+ require 'rex/proto/smb/exceptions'
4
+ require 'rex/proto/smb/evasions'
5
+ require 'rex/proto/smb/crypt'
6
+ require 'rex/proto/smb/utils'
7
+ require 'rex/proto/smb/client'
8
+ require 'rex/proto/smb/simpleclient'
@@ -0,0 +1,2064 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Proto
4
+ module SMB
5
+ class Client
6
+
7
+ require 'rex/text'
8
+ require 'rex/struct2'
9
+ require 'rex/proto/smb/constants'
10
+ require 'rex/proto/smb/exceptions'
11
+ require 'rex/proto/smb/evasions'
12
+ require 'rex/proto/smb/utils'
13
+ require 'rex/proto/smb/crypt'
14
+ require 'rex/proto/ntlm/crypt'
15
+ require 'rex/proto/ntlm/constants'
16
+ require 'rex/proto/ntlm/utils'
17
+
18
+
19
+ # Some short-hand class aliases
20
+ CONST = Rex::Proto::SMB::Constants
21
+ CRYPT = Rex::Proto::SMB::Crypt
22
+ UTILS = Rex::Proto::SMB::Utils
23
+ XCEPT = Rex::Proto::SMB::Exceptions
24
+ EVADE = Rex::Proto::SMB::Evasions
25
+ NTLM_CRYPT = Rex::Proto::NTLM::Crypt
26
+ NTLM_CONST = Rex::Proto::NTLM::Constants
27
+ NTLM_UTILS = Rex::Proto::NTLM::Utils
28
+
29
+ def initialize(socket)
30
+ self.socket = socket
31
+ self.native_os = 'Windows 2000 2195'
32
+ self.native_lm = 'Windows 2000 5.0'
33
+ self.encrypt_passwords = true
34
+ self.extended_security = false
35
+ self.multiplex_id = rand(0xffff)
36
+ self.process_id = rand(0xffff)
37
+ self.read_timeout = 10
38
+ self.evasion_opts = {
39
+
40
+ # Padding is performed between packet headers and data
41
+ 'pad_data' => EVADE::EVASION_NONE,
42
+
43
+ # File path padding is performed on all open/create calls
44
+ 'pad_file' => EVADE::EVASION_NONE,
45
+
46
+ # Modify the \PIPE\ string in trans_named_pipe calls
47
+ 'obscure_trans_pipe' => EVADE::EVASION_NONE,
48
+ }
49
+
50
+ self.verify_signature = false
51
+ self.use_ntlmv2 = false
52
+ self.usentlm2_session = true
53
+ self.send_lm = true
54
+ self.use_lanman_key = false
55
+ self.send_ntlm = true
56
+
57
+ # Signing
58
+ self.sequence_counter = 0
59
+ self.signing_key = ''
60
+ self.require_signing = false
61
+
62
+ #Misc
63
+ self.spnopt = {}
64
+
65
+ end
66
+
67
+ # Read a SMB packet from the socket
68
+ def smb_recv
69
+
70
+ data = socket.timed_read(4, self.read_timeout)
71
+ if (data.nil? or data.length < 4)
72
+ raise XCEPT::NoReply
73
+ end
74
+
75
+ recv_len = data[2,2].unpack('n')[0]
76
+ if (recv_len == 0)
77
+ return data
78
+ end
79
+
80
+ recv_len += 4
81
+
82
+ while (data.length != recv_len)
83
+ buff = ''
84
+
85
+ begin
86
+ buff << self.socket.timed_read(recv_len - data.length, self.read_timeout)
87
+ rescue Timeout::Error
88
+ rescue
89
+ raise XCEPT::ReadPacket
90
+ end
91
+
92
+ if (buff.nil? or buff.length == 0)
93
+ raise XCEPT::ReadPacket
94
+ end
95
+
96
+ data << buff
97
+ end
98
+
99
+ #signing
100
+ if self.require_signing && self.signing_key != ''
101
+ if self.verify_signature
102
+ raise XCEPT::IncorrectSigningError if not CRYPT::is_signature_correct?(self.signing_key,self.sequence_counter,data)
103
+ end
104
+ self.sequence_counter += 1
105
+ end
106
+
107
+ return data
108
+
109
+
110
+ end
111
+
112
+ # Send a SMB packet down the socket
113
+ def smb_send(data, evasion_level=0)
114
+
115
+ # evasion_level is ignored, since real evasion happens
116
+ # in the actual socket layer
117
+
118
+ size = 0
119
+ wait = 0
120
+
121
+ #signing
122
+ if self.require_signing && self.signing_key != ''
123
+ data = CRYPT::sign_smb_packet(self.signing_key, self.sequence_counter, data)
124
+ self.sequence_counter += 1
125
+ end
126
+
127
+ begin
128
+ # Just send the packet and return
129
+ if (size == 0 or size >= data.length)
130
+ return self.socket.put(data)
131
+ end
132
+
133
+ # Break the packet up into chunks and wait between them
134
+ ret = 0
135
+ while ( (chunk = data.slice!(0, size)).length > 0 )
136
+ ret = self.socket.put(chunk)
137
+ if (wait > 0)
138
+ ::IO.select(nil, nil, nil, wait)
139
+ end
140
+ end
141
+ return ret
142
+ end
143
+ end
144
+
145
+ # Set the SMB parameters to some reasonable defaults
146
+ def smb_defaults(packet)
147
+ packet.v['MultiplexID'] = self.multiplex_id.to_i
148
+ packet.v['TreeID'] = self.last_tree_id.to_i
149
+ packet.v['UserID'] = self.auth_user_id.to_i
150
+ packet.v['ProcessID'] = self.process_id.to_i
151
+ end
152
+
153
+ # Receive a full SMB reply and cache the parsed packet
154
+ def smb_recv_and_cache
155
+ @smb_recv_cache ||= []
156
+
157
+ # This will throw an exception if it fails to read the whole packet
158
+ data = self.smb_recv
159
+
160
+ pkt = CONST::SMB_BASE_PKT.make_struct
161
+ pkt.from_s(data)
162
+
163
+ # Store the received packet into the cache
164
+ @smb_recv_cache << [ pkt, data, Time.now ]
165
+ end
166
+
167
+ # Scan the packet receive cache for a matching response
168
+ def smb_recv_cache_find_match(expected_type)
169
+
170
+ clean = []
171
+ found = nil
172
+
173
+ @smb_recv_cache.each do |cent|
174
+ pkt, data, tstamp = cent
175
+
176
+ # Return matching packets and mark for removal
177
+ if pkt['Payload']['SMB'].v['Command'] == expected_type
178
+ found = [pkt,data]
179
+ clean << cent
180
+ end
181
+
182
+ # Purge any packets older than 5 minutes
183
+ if Time.now.to_i - tstamp.to_i > 300
184
+ clean << cent
185
+ end
186
+
187
+ break if found
188
+ end
189
+
190
+ clean.each do |cent|
191
+ @smb_recv_cache.delete(cent)
192
+ end
193
+
194
+ found
195
+ end
196
+
197
+ # The main dispatcher for all incoming SMB packets
198
+ def smb_recv_parse(expected_type, ignore_errors = false)
199
+
200
+ pkt = nil
201
+ data = nil
202
+
203
+ # This allows for some leeway when a previous response has not
204
+ # been processed but a new request was sent. The old response
205
+ # will eventually be timed out of the cache.
206
+ 1.upto(3) do |attempt|
207
+ smb_recv_and_cache
208
+ pkt,data = smb_recv_cache_find_match(expected_type)
209
+ break if pkt
210
+ end
211
+
212
+ begin
213
+ case pkt['Payload']['SMB'].v['Command']
214
+
215
+ when CONST::SMB_COM_NEGOTIATE
216
+ res = smb_parse_negotiate(pkt, data)
217
+
218
+ when CONST::SMB_COM_SESSION_SETUP_ANDX
219
+ res = smb_parse_session_setup(pkt, data)
220
+
221
+ when CONST::SMB_COM_TREE_CONNECT_ANDX
222
+ res = smb_parse_tree_connect(pkt, data)
223
+
224
+ when CONST::SMB_COM_TREE_DISCONNECT
225
+ res = smb_parse_tree_disconnect(pkt, data)
226
+
227
+ when CONST::SMB_COM_NT_CREATE_ANDX
228
+ res = smb_parse_create(pkt, data)
229
+
230
+ when CONST::SMB_COM_TRANSACTION, CONST::SMB_COM_TRANSACTION2
231
+ res = smb_parse_trans(pkt, data)
232
+
233
+ when CONST::SMB_COM_NT_TRANSACT
234
+ res = smb_parse_nttrans(pkt, data)
235
+
236
+ when CONST::SMB_COM_NT_TRANSACT_SECONDARY
237
+ res = smb_parse_nttrans(pkt, data)
238
+
239
+ when CONST::SMB_COM_OPEN_ANDX
240
+ res = smb_parse_open(pkt, data)
241
+
242
+ when CONST::SMB_COM_WRITE_ANDX
243
+ res = smb_parse_write(pkt, data)
244
+
245
+ when CONST::SMB_COM_READ_ANDX
246
+ res = smb_parse_read(pkt, data)
247
+
248
+ when CONST::SMB_COM_CLOSE
249
+ res = smb_parse_close(pkt, data)
250
+
251
+ when CONST::SMB_COM_DELETE
252
+ res = smb_parse_delete(pkt, data)
253
+
254
+ else
255
+ raise XCEPT::InvalidCommand
256
+ end
257
+
258
+ if (ignore_errors == false and pkt['Payload']['SMB'].v['ErrorClass'] != 0)
259
+ raise XCEPT::ErrorCode
260
+ end
261
+
262
+ rescue XCEPT::InvalidWordCount, XCEPT::InvalidCommand, XCEPT::ErrorCode
263
+ $!.word_count = pkt['Payload']['SMB'].v['WordCount']
264
+ $!.command = pkt['Payload']['SMB'].v['Command']
265
+ $!.error_code = pkt['Payload']['SMB'].v['ErrorClass']
266
+ raise $!
267
+ end
268
+
269
+ return res
270
+ end
271
+
272
+ # Process incoming SMB_COM_NEGOTIATE packets
273
+ def smb_parse_negotiate(pkt, data)
274
+ #Process NTLM negotiate responses
275
+ if (pkt['Payload']['SMB'].v['WordCount'] == 17)
276
+ res = CONST::SMB_NEG_RES_NT_PKT.make_struct
277
+ res.from_s(data)
278
+ return res
279
+ end
280
+
281
+ # Process LANMAN negotiate responses
282
+ if (pkt['Payload']['SMB'].v['WordCount'] == 13)
283
+ res = CONST::SMB_NEG_RES_LM_PKT.make_struct
284
+ res.from_s(data)
285
+ return res
286
+ end
287
+
288
+ # Process ERROR negotiate responses
289
+ if (pkt['Payload']['SMB'].v['WordCount'] == 1)
290
+ res = CONST::SMB_NEG_RES_ERR_PKT.make_struct
291
+ res.from_s(data)
292
+ return res
293
+ end
294
+
295
+ # Process SMB error responses
296
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
297
+ return pkt
298
+ end
299
+
300
+ raise XCEPT::InvalidWordCount
301
+ end
302
+
303
+ # Process incoming SMB_COM_SESSION_SETUP_ANDX packets
304
+ def smb_parse_session_setup(pkt, data)
305
+ # Process NTLMSSP negotiate responses
306
+ if (pkt['Payload']['SMB'].v['WordCount'] == 4)
307
+ res = CONST::SMB_SETUP_NTLMV2_RES_PKT.make_struct
308
+ res.from_s(data)
309
+ return res
310
+ end
311
+
312
+ # Process LANMAN responses
313
+ if (pkt['Payload']['SMB'].v['WordCount'] == 3)
314
+ res = CONST::SMB_SETUP_RES_PKT.make_struct
315
+ res.from_s(data)
316
+ return res
317
+ end
318
+
319
+ # Process SMB error responses
320
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
321
+ return pkt
322
+ end
323
+
324
+ raise XCEPT::InvalidWordCount
325
+ end
326
+
327
+ # Process incoming SMB_COM_TREE_CONNECT_ANDX packets
328
+ def smb_parse_tree_connect(pkt, data)
329
+
330
+ if (pkt['Payload']['SMB'].v['WordCount'] == 3)
331
+ res = CONST::SMB_TREE_CONN_RES_PKT.make_struct
332
+ res.from_s(data)
333
+ return res
334
+ end
335
+
336
+ # Process SMB error responses
337
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
338
+ return pkt
339
+ end
340
+
341
+ raise XCEPT::InvalidWordCount
342
+ end
343
+
344
+ # Process incoming SMB_COM_TREE_DISCONNECT packets
345
+ def smb_parse_tree_disconnect(pkt, data)
346
+
347
+ # Process SMB responses
348
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
349
+ res = CONST::SMB_TREE_DISCONN_RES_PKT.make_struct
350
+ res.from_s(data)
351
+ return res
352
+ end
353
+
354
+ raise XCEPT::InvalidWordCount
355
+ end
356
+
357
+ # Process incoming SMB_COM_NT_CREATE_ANDX packets
358
+ def smb_parse_create(pkt, data)
359
+
360
+ # Windows says 42, but Samba says 34, same structure :-/
361
+ if (pkt['Payload']['SMB'].v['WordCount'] == 42)
362
+ res = CONST::SMB_CREATE_RES_PKT.make_struct
363
+ res.from_s(data)
364
+ return res
365
+ end
366
+
367
+ if (pkt['Payload']['SMB'].v['WordCount'] == 34)
368
+ res = CONST::SMB_CREATE_RES_PKT.make_struct
369
+ res.from_s(data)
370
+ return res
371
+ end
372
+
373
+ # Process SMB error responses
374
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
375
+ return pkt
376
+ end
377
+
378
+ raise XCEPT::InvalidWordCount
379
+ end
380
+
381
+ # Process incoming SMB_COM_TRANSACTION packets
382
+ def smb_parse_trans(pkt, data)
383
+
384
+ if (pkt['Payload']['SMB'].v['WordCount'] == 10)
385
+ res = CONST::SMB_TRANS_RES_PKT.make_struct
386
+ res.from_s(data)
387
+ return res
388
+ end
389
+
390
+ # Process SMB error responses
391
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
392
+ return pkt
393
+ end
394
+
395
+ raise XCEPT::InvalidWordCount
396
+ end
397
+
398
+ # Process incoming SMB_COM_NT_TRANSACT packets
399
+ def smb_parse_nttrans(pkt, data)
400
+
401
+ # Process SMB error responses
402
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
403
+ return pkt
404
+ end
405
+
406
+ if (pkt['Payload']['SMB'].v['WordCount'] >= 18)
407
+ res = CONST::SMB_NTTRANS_RES_PKT.make_struct
408
+ res.from_s(data)
409
+ return res
410
+ end
411
+
412
+ raise XCEPT::InvalidWordCount
413
+ end
414
+
415
+ # Process incoming SMB_COM_OPEN_ANDX packets
416
+ def smb_parse_open(pkt, data)
417
+ # Process open responses
418
+ if (pkt['Payload']['SMB'].v['WordCount'] == 15)
419
+ res = CONST::SMB_OPEN_RES_PKT.make_struct
420
+ res.from_s(data)
421
+ return res
422
+ end
423
+
424
+ # Process SMB error responses
425
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
426
+ return pkt
427
+ end
428
+
429
+ raise XCEPT::InvalidWordCount
430
+ end
431
+
432
+ # Process incoming SMB_COM_WRITE_ANDX packets
433
+ def smb_parse_write(pkt, data)
434
+
435
+ # Process write responses
436
+ if (pkt['Payload']['SMB'].v['WordCount'] == 6)
437
+ res = CONST::SMB_WRITE_RES_PKT.make_struct
438
+ res.from_s(data)
439
+ return res
440
+ end
441
+
442
+ # Process SMB error responses
443
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
444
+ return pkt
445
+ end
446
+
447
+ raise XCEPT::InvalidWordCount
448
+ end
449
+
450
+ # Process incoming SMB_COM_READ_ANDX packets
451
+ def smb_parse_read(pkt, data)
452
+
453
+ # Process read responses
454
+ if (pkt['Payload']['SMB'].v['WordCount'] == 12)
455
+ res = CONST::SMB_READ_RES_PKT.make_struct
456
+ res.from_s(data)
457
+ return res
458
+ end
459
+
460
+ # Process SMB error responses
461
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
462
+ return pkt
463
+ end
464
+
465
+ raise XCEPT::InvalidWordCount
466
+ end
467
+
468
+ # Process incoming SMB_COM_CLOSE packets
469
+ def smb_parse_close(pkt, data)
470
+
471
+ # Process SMB error responses
472
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
473
+ return pkt
474
+ end
475
+
476
+ raise XCEPT::InvalidWordCount
477
+ end
478
+
479
+ # Process incoming SMB_COM_DELETE packets
480
+ def smb_parse_delete(pkt, data)
481
+
482
+ # Process SMB error responses
483
+ if (pkt['Payload']['SMB'].v['WordCount'] == 0)
484
+ res = CONST::SMB_DELETE_RES_PKT.make_struct
485
+ res.from_s(data)
486
+ return res
487
+ end
488
+
489
+ raise XCEPT::InvalidWordCount
490
+ end
491
+
492
+ # Request a SMB session over NetBIOS
493
+ def session_request(name = '*SMBSERVER', do_recv = true)
494
+
495
+ name ||= '*SMBSERVER'
496
+
497
+ data = ''
498
+ data << "\x20" + UTILS.nbname_encode(name) + "\x00"
499
+ data << "\x20" + CONST::NETBIOS_REDIR + "\x00"
500
+
501
+ pkt = CONST::NBRAW_PKT.make_struct
502
+ pkt.v['Type'] = 0x81
503
+ pkt['Payload'].v['Payload'] = data
504
+
505
+ # Most SMB implementations can't handle this being fragmented
506
+ ret = self.smb_send(pkt.to_s, EVADE::EVASION_NONE)
507
+ return ret if not do_recv
508
+
509
+ res = self.smb_recv
510
+
511
+ ack = CONST::NBRAW_PKT.make_struct
512
+ ack.from_s(res)
513
+
514
+ if (ack.v['Type'] != 130)
515
+ raise XCEPT::NetbiosSessionFailed
516
+ end
517
+
518
+ return ack
519
+ end
520
+
521
+ # Negotiate a SMB dialect
522
+ def negotiate(smb_extended_security=true, do_recv = true)
523
+
524
+ dialects = ['LANMAN1.0', 'LM1.2X002' ]
525
+
526
+ if (self.encrypt_passwords)
527
+ dialects.push('NT LANMAN 1.0', 'NT LM 0.12')
528
+ end
529
+
530
+ data = dialects.collect { |dialect| "\x02" + dialect + "\x00" }.join('')
531
+
532
+ pkt = CONST::SMB_NEG_PKT.make_struct
533
+ self.smb_defaults(pkt['Payload']['SMB'])
534
+
535
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NEGOTIATE
536
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
537
+
538
+ if(smb_extended_security)
539
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
540
+ else
541
+ pkt['Payload']['SMB'].v['Flags2'] = 0xc001
542
+ end
543
+
544
+ pkt['Payload'].v['Payload'] = data
545
+
546
+ ret = self.smb_send(pkt.to_s, EVADE::EVASION_NONE)
547
+ return ret if not do_recv
548
+
549
+ ack = self.smb_recv_parse(CONST::SMB_COM_NEGOTIATE)
550
+
551
+ idx = ack['Payload'].v['Dialect']
552
+
553
+ # Check for failed dialect selection
554
+ if (idx < 0 or idx >= dialects.length)
555
+ return nil
556
+ end
557
+
558
+ # Set the selected dialect
559
+ self.dialect = dialects[idx]
560
+
561
+ # Does the server support extended security negotiation?
562
+ if (ack['Payload'].v['Capabilities'] & 0x80000000 != 0)
563
+ self.extended_security = true
564
+ end
565
+
566
+ # Set the security mode
567
+ self.security_mode = ack['Payload'].v['SecurityMode']
568
+
569
+ #set require_signing
570
+ if (ack['Payload'].v['SecurityMode'] & 0x08 != 0)
571
+ self.require_signing = true
572
+ end
573
+
574
+ # Set the challenge key
575
+ if (ack['Payload'].v['EncryptionKey'] != nil)
576
+ self.challenge_key = ack['Payload'].v['EncryptionKey']
577
+ else
578
+ # Handle Windows NT 4.0 responses
579
+ if (ack['Payload'].v['KeyLength'] > 0)
580
+ self.challenge_key = ack['Payload'].v['Payload'][0, ack['Payload'].v['KeyLength']]
581
+ end
582
+ end
583
+
584
+ # Set the session identifier
585
+ if (ack['Payload'].v['SessionKey'] != nil)
586
+ self.session_id = ack['Payload'].v['SessionKey']
587
+ end
588
+
589
+ # Extract the payload (GUID/SecurityBlob)
590
+ buf = ack['Payload'].v['Payload'] || ''
591
+
592
+ # Set the server GUID
593
+ if (self.extended_security and buf.length >= 16)
594
+ self.server_guid = buf[0,16]
595
+ end
596
+
597
+ # Set the server SecurityBlob
598
+ if (self.extended_security and buf.length > 16)
599
+ # buf[16, buf.length - 16]
600
+ end
601
+
602
+ # The number of 100-nanosecond intervals that have elapsed since January 1, 1601, in
603
+ # Coordinated Universal Time (UTC) format.
604
+ # We convert it to a friendly Time object here
605
+ self.system_time = UTILS.time_smb_to_unix(ack['Payload'].v['SystemTimeHigh'],ack['Payload'].v['SystemTimeLow'])
606
+ self.system_time = ::Time.at( self.system_time )
607
+
608
+ # A signed 16-bit signed integer that represents the server's time zone, in minutes,
609
+ # from UTC. The time zone of the server MUST be expressed in minutes, plus or minus,
610
+ # from UTC.
611
+ # NOTE: althought the spec says +/- it doesn't say that it should be inverted :-/
612
+ system_zone = ack['Payload'].v['ServerTimeZone']
613
+ # Convert the ServerTimeZone to _seconds_ and back into a signed integer :-/
614
+ if (system_zone & 0x8000) == 0x8000
615
+ system_zone = (( (~system_zone) & 0x0FFF ) + 1 )
616
+ else
617
+ system_zone *= -1
618
+ end
619
+ self.system_zone = system_zone * 60
620
+
621
+ return ack
622
+ end
623
+
624
+
625
+ # Authenticate and establish a session
626
+ def session_setup(*args)
627
+
628
+ if (self.dialect =~ /^(NT LANMAN 1.0|NT LM 0.12)$/)
629
+
630
+ if (self.challenge_key)
631
+ return self.session_setup_no_ntlmssp(*args)
632
+ end
633
+
634
+ if ( self.extended_security )
635
+ return self.session_setup_with_ntlmssp(*args)
636
+ end
637
+
638
+ end
639
+
640
+ return self.session_setup_clear(*args)
641
+ end
642
+
643
+ # Authenticate using clear-text passwords
644
+ def session_setup_clear(user = '', pass = '', domain = '', do_recv = true)
645
+
646
+ data = [ pass, user, domain, self.native_os, self.native_lm ].collect{ |a| a + "\x00" }.join('');
647
+
648
+ pkt = CONST::SMB_SETUP_LANMAN_PKT.make_struct
649
+ self.smb_defaults(pkt['Payload']['SMB'])
650
+
651
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
652
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
653
+ if self.require_signing
654
+ #ascii
655
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
656
+ else
657
+ #ascii
658
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
659
+ end
660
+
661
+ pkt['Payload']['SMB'].v['WordCount'] = 10
662
+ pkt['Payload'].v['AndX'] = 255
663
+ pkt['Payload'].v['MaxBuff'] = 0xffdf
664
+ pkt['Payload'].v['MaxMPX'] = 2
665
+ pkt['Payload'].v['VCNum'] = 1
666
+ pkt['Payload'].v['PasswordLen'] = pass.length + 1
667
+ pkt['Payload'].v['Capabilities'] = 64
668
+ pkt['Payload'].v['SessionKey'] = self.session_id
669
+ pkt['Payload'].v['Payload'] = data
670
+
671
+ ret = self.smb_send(pkt.to_s)
672
+ return ret if not do_recv
673
+
674
+ ack = self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX)
675
+
676
+ if (ack['Payload'].v['Action'] != 1 and user.length > 0)
677
+ self.auth_user = user
678
+ end
679
+
680
+ self.auth_user_id = ack['Payload']['SMB'].v['UserID']
681
+
682
+ info = ack['Payload'].v['Payload'].split(/\x00/n)
683
+ self.peer_native_os = info[0]
684
+ self.peer_native_lm = info[1]
685
+ self.default_domain = info[2]
686
+
687
+ return ack
688
+ end
689
+
690
+ # Authenticate without NTLMSSP
691
+ def session_setup_no_ntlmssp(user = '', pass = '', domain = '', do_recv = true)
692
+
693
+ # Requires a challenge key to have been seen during negotiation
694
+ raise XCEPT::NTLM1MissingChallenge if not self.challenge_key
695
+
696
+ #
697
+ # We can not yet handle signing in this situation
698
+ # But instead of throwing an exception,we will disable signing, continue and hope for the best.
699
+ #
700
+
701
+ #raise XCEPT::SigningError if self.require_signing
702
+ self.require_signing = false if self.require_signing
703
+
704
+
705
+ if NTLM_UTILS.is_pass_ntlm_hash?(pass)
706
+ arglm = {
707
+ :lm_hash => [ pass.upcase()[0,32] ].pack('H32'),
708
+ :challenge => self.challenge_key
709
+ }
710
+ hash_lm = NTLM_CRYPT::lm_response(arglm)
711
+
712
+ argntlm = {
713
+ :ntlm_hash => [ pass.upcase()[33,65] ].pack('H32'),
714
+ :challenge => self.challenge_key
715
+ }
716
+ hash_nt = NTLM_CRYPT::ntlm_response(argntlm)
717
+ else
718
+ hash_lm = pass.length > 0 ? NTLM_CRYPT.lanman_des(pass, self.challenge_key) : ''
719
+ hash_nt = pass.length > 0 ? NTLM_CRYPT.ntlm_md4(pass, self.challenge_key) : ''
720
+ end
721
+
722
+ data = ''
723
+ data << hash_lm
724
+ data << hash_nt
725
+ data << user + "\x00"
726
+ data << domain + "\x00"
727
+ data << self.native_os + "\x00"
728
+ data << self.native_lm + "\x00"
729
+
730
+ pkt = CONST::SMB_SETUP_NTLMV1_PKT.make_struct
731
+ self.smb_defaults(pkt['Payload']['SMB'])
732
+
733
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
734
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
735
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2001
736
+ pkt['Payload']['SMB'].v['WordCount'] = 13
737
+ pkt['Payload'].v['AndX'] = 255
738
+ pkt['Payload'].v['MaxBuff'] = 0xffdf
739
+ pkt['Payload'].v['MaxMPX'] = 2
740
+ pkt['Payload'].v['VCNum'] = 1
741
+ pkt['Payload'].v['PasswordLenLM'] = hash_lm.length
742
+ pkt['Payload'].v['PasswordLenNT'] = hash_nt.length
743
+ pkt['Payload'].v['Capabilities'] = 64
744
+ pkt['Payload'].v['SessionKey'] = self.session_id
745
+ pkt['Payload'].v['Payload'] = data
746
+
747
+ ret = self.smb_send(pkt.to_s)
748
+ return ret if not do_recv
749
+
750
+ ack = self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX)
751
+
752
+ if (ack['Payload'].v['Action'] != 1 and user.length > 0)
753
+ self.auth_user = user
754
+ end
755
+
756
+ self.auth_user_id = ack['Payload']['SMB'].v['UserID']
757
+
758
+ info = ack['Payload'].v['Payload'].split(/\x00/n)
759
+
760
+ self.peer_native_os = info[0]
761
+ self.peer_native_lm = info[1]
762
+ self.default_domain = info[2]
763
+
764
+ return ack
765
+ end
766
+
767
+
768
+ # Authenticate without ntlmssp with a precomputed hash pair
769
+ def session_setup_no_ntlmssp_prehash(user, domain, hash_lm, hash_nt, do_recv = true)
770
+
771
+ data = ''
772
+ data << hash_lm
773
+ data << hash_nt
774
+ data << user + "\x00"
775
+ data << domain + "\x00"
776
+ data << self.native_os + "\x00"
777
+ data << self.native_lm + "\x00"
778
+
779
+ pkt = CONST::SMB_SETUP_NTLMV1_PKT.make_struct
780
+ self.smb_defaults(pkt['Payload']['SMB'])
781
+
782
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
783
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
784
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2001
785
+ pkt['Payload']['SMB'].v['WordCount'] = 13
786
+ pkt['Payload'].v['AndX'] = 255
787
+ pkt['Payload'].v['MaxBuff'] = 0xffdf
788
+ pkt['Payload'].v['MaxMPX'] = 2
789
+ pkt['Payload'].v['VCNum'] = 1
790
+ pkt['Payload'].v['PasswordLenLM'] = hash_lm.length
791
+ pkt['Payload'].v['PasswordLenNT'] = hash_nt.length
792
+ pkt['Payload'].v['Capabilities'] = 64
793
+ pkt['Payload'].v['SessionKey'] = self.session_id
794
+ pkt['Payload'].v['Payload'] = data
795
+
796
+ ret = self.smb_send(pkt.to_s)
797
+ return ret if not do_recv
798
+
799
+ ack = self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX)
800
+
801
+ if (ack['Payload'].v['Action'] != 1 and user.length > 0)
802
+ self.auth_user = user
803
+ end
804
+
805
+ self.auth_user_id = ack['Payload']['SMB'].v['UserID']
806
+
807
+ info = ack['Payload'].v['Payload'].split(/\x00/n)
808
+
809
+ self.peer_native_os = info[0]
810
+ self.peer_native_lm = info[1]
811
+ self.default_domain = info[2]
812
+
813
+ return ack
814
+ end
815
+
816
+ # Authenticate using extended security negotiation
817
+ def session_setup_with_ntlmssp(user = '', pass = '', domain = '', name = nil, do_recv = true)
818
+
819
+ ntlm_options = {
820
+ :signing => self.require_signing,
821
+ :usentlm2_session => self.usentlm2_session,
822
+ :use_ntlmv2 => self.use_ntlmv2,
823
+ :send_lm => self.send_lm,
824
+ :send_ntlm => self.send_ntlm,
825
+ :use_lanman_key => self.use_lanman_key
826
+ }
827
+
828
+ ntlmssp_flags = NTLM_UTILS.make_ntlm_flags(ntlm_options)
829
+
830
+ if (name == nil)
831
+ name = Rex::Text.rand_text_alphanumeric(16)
832
+ end
833
+
834
+ blob = NTLM_UTILS.make_ntlmssp_secblob_init(domain, name, ntlmssp_flags)
835
+
836
+ native_data = ''
837
+ native_data << self.native_os + "\x00"
838
+ native_data << self.native_lm + "\x00"
839
+
840
+ pkt = CONST::SMB_SETUP_NTLMV2_PKT.make_struct
841
+ self.smb_defaults(pkt['Payload']['SMB'])
842
+
843
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
844
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
845
+ if require_signing
846
+ #ascii
847
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
848
+ else
849
+ #ascii
850
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
851
+ end
852
+ pkt['Payload']['SMB'].v['WordCount'] = 12
853
+ pkt['Payload'].v['AndX'] = 255
854
+ pkt['Payload'].v['MaxBuff'] = 0xffdf
855
+ pkt['Payload'].v['MaxMPX'] = 2
856
+ pkt['Payload'].v['VCNum'] = 1
857
+ pkt['Payload'].v['SecurityBlobLen'] = blob.length
858
+ pkt['Payload'].v['Capabilities'] = 0x800000d4
859
+ pkt['Payload'].v['SessionKey'] = self.session_id
860
+ pkt['Payload'].v['Payload'] = blob + native_data
861
+
862
+ ret = self.smb_send(pkt.to_s)
863
+
864
+ return ret if not do_recv
865
+
866
+ ack = self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX, true)
867
+
868
+
869
+ # The server doesn't know about NTLM_NEGOTIATE
870
+ if (ack['Payload']['SMB'].v['ErrorClass'] == 0x00020002)
871
+ return session_setup_no_ntlmssp(user, pass, domain)
872
+ end
873
+
874
+ # Make sure the error code tells us to continue processing
875
+ if (ack['Payload']['SMB'].v['ErrorClass'] != 0xc0000016)
876
+ failure = XCEPT::ErrorCode.new
877
+ failure.word_count = ack['Payload']['SMB'].v['WordCount']
878
+ failure.command = ack['Payload']['SMB'].v['Command']
879
+ failure.error_code = ack['Payload']['SMB'].v['ErrorClass']
880
+ raise failure
881
+ end
882
+
883
+ # Extract the SecurityBlob from the response
884
+ data = ack['Payload'].v['Payload']
885
+ blob = data.slice!(0, ack['Payload'].v['SecurityBlobLen'])
886
+
887
+ # Extract the native lanman and os strings
888
+ info = data.split(/\x00/n)
889
+ self.peer_native_os = info[0]
890
+ self.peer_native_lm = info[1]
891
+
892
+ # Save the temporary UserID for use in the next request
893
+ temp_user_id = ack['Payload']['SMB'].v['UserID']
894
+
895
+ # Get default data
896
+ blob_data = NTLM_UTILS.parse_ntlm_type_2_blob(blob)
897
+ self.challenge_key = blob_data[:challenge_key]
898
+ server_ntlmssp_flags = blob_data[:server_ntlmssp_flags] #else should raise an error
899
+ #netbios name
900
+ self.default_name = blob_data[:default_name] || ''
901
+ #netbios domain
902
+ self.default_domain = blob_data[:default_domain] || ''
903
+ #dns name
904
+ self.dns_host_name = blob_data[:dns_host_name] || ''
905
+ #dns domain
906
+ self.dns_domain_name = blob_data[:dns_domain_name] || ''
907
+ #Client time
908
+ chall_MsvAvTimestamp = blob_data[:chall_MsvAvTimestamp] || ''
909
+
910
+
911
+ resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge = NTLM_UTILS.create_lm_ntlm_responses(user, pass, self.challenge_key, domain,
912
+ default_name, default_domain, dns_host_name,
913
+ dns_domain_name, chall_MsvAvTimestamp ,
914
+ self.spnopt, ntlm_options)
915
+ enc_session_key = ''
916
+ self.sequence_counter = 0
917
+
918
+ if self.require_signing
919
+ self.signing_key, enc_session_key, ntlmssp_flags = NTLM_UTILS.create_session_key(ntlmssp_flags, server_ntlmssp_flags, user, pass, domain,
920
+ self.challenge_key, client_challenge, ntlm_cli_challenge,
921
+ ntlm_options)
922
+ end
923
+
924
+ # Create the security blob data
925
+ blob = NTLM_UTILS.make_ntlmssp_secblob_auth(domain, name, user, resp_lm, resp_ntlm, enc_session_key, ntlmssp_flags)
926
+
927
+ pkt = CONST::SMB_SETUP_NTLMV2_PKT.make_struct
928
+ self.smb_defaults(pkt['Payload']['SMB'])
929
+
930
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
931
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
932
+ if self.require_signing
933
+ #ascii
934
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
935
+ else
936
+ #ascii
937
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
938
+ end
939
+ pkt['Payload']['SMB'].v['WordCount'] = 12
940
+ pkt['Payload']['SMB'].v['UserID'] = temp_user_id
941
+ pkt['Payload'].v['AndX'] = 255
942
+ pkt['Payload'].v['MaxBuff'] = 0xffdf
943
+ pkt['Payload'].v['MaxMPX'] = 2
944
+ pkt['Payload'].v['VCNum'] = 1
945
+ pkt['Payload'].v['Capabilities'] = 0x8000d05c
946
+ pkt['Payload'].v['SessionKey'] = self.session_id
947
+ pkt['Payload'].v['SecurityBlobLen'] = blob.length
948
+ pkt['Payload'].v['Payload'] = blob + native_data
949
+
950
+ # NOTE: if do_recv is set to false, we cant reach here...
951
+ self.smb_send(pkt.to_s)
952
+
953
+ ack = self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX, true)
954
+
955
+ # Make sure that authentication succeeded
956
+ if (ack['Payload']['SMB'].v['ErrorClass'] != 0)
957
+
958
+ if (user.length == 0)
959
+ # Ensure that signing is disabled when we hit this corner case
960
+ self.require_signing = false
961
+
962
+ # Fall back to the non-ntlmssp authentication method
963
+ return self.session_setup_no_ntlmssp(user, pass, domain)
964
+ end
965
+
966
+ failure = XCEPT::ErrorCode.new
967
+ failure.word_count = ack['Payload']['SMB'].v['WordCount']
968
+ failure.command = ack['Payload']['SMB'].v['Command']
969
+ failure.error_code = ack['Payload']['SMB'].v['ErrorClass']
970
+ raise failure
971
+ end
972
+
973
+ self.auth_user_id = ack['Payload']['SMB'].v['UserID']
974
+
975
+ if (ack['Payload'].v['Action'] != 1 and user.length > 0)
976
+ self.auth_user = user
977
+ end
978
+
979
+ return ack
980
+ end
981
+
982
+
983
+ # An exploit helper function for sending arbitrary SPNEGO blobs
984
+ def session_setup_with_ntlmssp_blob(blob = '', do_recv = true, userid = 0)
985
+ native_data = ''
986
+ native_data << self.native_os + "\x00"
987
+ native_data << self.native_lm + "\x00"
988
+
989
+ pkt = CONST::SMB_SETUP_NTLMV2_PKT.make_struct
990
+ self.smb_defaults(pkt['Payload']['SMB'])
991
+
992
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
993
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
994
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
995
+ pkt['Payload']['SMB'].v['WordCount'] = 12
996
+ pkt['Payload']['SMB'].v['UserID'] = userid
997
+ pkt['Payload'].v['AndX'] = 255
998
+ pkt['Payload'].v['MaxBuff'] = 0xffdf
999
+ pkt['Payload'].v['MaxMPX'] = 2
1000
+ pkt['Payload'].v['VCNum'] = 1
1001
+ pkt['Payload'].v['SecurityBlobLen'] = blob.length
1002
+ pkt['Payload'].v['Capabilities'] = 0x8000d05c
1003
+ pkt['Payload'].v['SessionKey'] = self.session_id
1004
+ pkt['Payload'].v['Payload'] = blob + native_data
1005
+
1006
+ ret = self.smb_send(pkt.to_s)
1007
+ return ret if not do_recv
1008
+
1009
+ self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX, false)
1010
+ end
1011
+
1012
+
1013
+ # Authenticate using extended security negotiation (NTLMSSP), but stop half-way, using the temporary ID
1014
+ def session_setup_with_ntlmssp_temp(domain = '', name = nil, do_recv = true)
1015
+
1016
+ if (name == nil)
1017
+ name = Rex::Text.rand_text_alphanumeric(16)
1018
+ end
1019
+
1020
+ blob = NTLM_UTILS.make_ntlmssp_secblob_init(domain, name)
1021
+
1022
+ native_data = ''
1023
+ native_data << self.native_os + "\x00"
1024
+ native_data << self.native_lm + "\x00"
1025
+
1026
+ pkt = CONST::SMB_SETUP_NTLMV2_PKT.make_struct
1027
+ self.smb_defaults(pkt['Payload']['SMB'])
1028
+
1029
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
1030
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1031
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1032
+ pkt['Payload']['SMB'].v['WordCount'] = 12
1033
+ pkt['Payload'].v['AndX'] = 255
1034
+ pkt['Payload'].v['MaxBuff'] = 0xffdf
1035
+ pkt['Payload'].v['MaxMPX'] = 2
1036
+ pkt['Payload'].v['VCNum'] = 1
1037
+ pkt['Payload'].v['SecurityBlobLen'] = blob.length
1038
+ pkt['Payload'].v['Capabilities'] = 0x8000d05c
1039
+ pkt['Payload'].v['SessionKey'] = self.session_id
1040
+ pkt['Payload'].v['Payload'] = blob + native_data
1041
+
1042
+ ret = self.smb_send(pkt.to_s)
1043
+ return ret if not do_recv
1044
+
1045
+ ack = self.smb_recv_parse(CONST::SMB_COM_SESSION_SETUP_ANDX, true)
1046
+
1047
+ # The server doesn't know about NTLM_NEGOTIATE, try ntlmv1
1048
+ if (ack['Payload']['SMB'].v['ErrorClass'] == 0x00020002)
1049
+ return session_setup_no_ntlmssp(user, pass, domain)
1050
+ end
1051
+
1052
+ # Make sure the error code tells us to continue processing
1053
+ if (ack['Payload']['SMB'].v['ErrorClass'] != 0xc0000016)
1054
+ failure = XCEPT::ErrorCode.new
1055
+ failure.word_count = ack['Payload']['SMB'].v['WordCount']
1056
+ failure.command = ack['Payload']['SMB'].v['Command']
1057
+ failure.error_code = ack['Payload']['SMB'].v['ErrorClass']
1058
+ raise failure
1059
+ end
1060
+
1061
+ # Extract the SecurityBlob from the response
1062
+ data = ack['Payload'].v['Payload']
1063
+ blob = data.slice!(0, ack['Payload'].v['SecurityBlobLen'])
1064
+
1065
+ # Extract the native lanman and os strings
1066
+ info = data.split(/\x00/n)
1067
+ self.peer_native_os = info[0]
1068
+ self.peer_native_lm = info[1]
1069
+
1070
+ # Save the temporary UserID for use in the next request
1071
+ self.auth_user_id = ack['Payload']['SMB'].v['UserID']
1072
+
1073
+ # Extract the NTLM challenge key the lazy way
1074
+ cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")
1075
+
1076
+ if (cidx == -1)
1077
+ raise XCEPT::NTLM2MissingChallenge
1078
+ end
1079
+
1080
+ # Store the challenge key
1081
+ self.challenge_key = blob[cidx + 24, 8]
1082
+
1083
+ return ack
1084
+ end
1085
+
1086
+ # Connect to a specified share with an optional password
1087
+ def tree_connect(share = 'IPC$', pass = '', do_recv = true)
1088
+
1089
+ data = [ pass, share, '?????' ].collect{ |a| a + "\x00" }.join('');
1090
+
1091
+ pkt = CONST::SMB_TREE_CONN_PKT.make_struct
1092
+ self.smb_defaults(pkt['Payload']['SMB'])
1093
+ pkt['Payload']['SMB'].v['TreeID'] = 0
1094
+
1095
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TREE_CONNECT_ANDX
1096
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1097
+ if self.require_signing
1098
+ #ascii
1099
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1100
+ else
1101
+ #ascii
1102
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1103
+ end
1104
+
1105
+ pkt['Payload']['SMB'].v['WordCount'] = 4
1106
+ pkt['Payload'].v['AndX'] = 255
1107
+ pkt['Payload'].v['PasswordLen'] = pass.length + 1
1108
+ pkt['Payload'].v['Capabilities'] = 64
1109
+ pkt['Payload'].v['Payload'] = data
1110
+
1111
+ ret = self.smb_send(pkt.to_s)
1112
+ return ret if not do_recv
1113
+
1114
+ ack = self.smb_recv_parse(CONST::SMB_COM_TREE_CONNECT_ANDX)
1115
+
1116
+ self.last_tree_id = ack['Payload']['SMB'].v['TreeID']
1117
+ # why bother?
1118
+ # info = ack['Payload'].v['Payload'].split(/\x00/)
1119
+
1120
+ return ack
1121
+ end
1122
+
1123
+ # Disconnect from the current tree
1124
+ def tree_disconnect(tree_id = self.last_tree_id, do_recv = true)
1125
+
1126
+ pkt = CONST::SMB_TREE_DISCONN_PKT.make_struct
1127
+ self.smb_defaults(pkt['Payload']['SMB'])
1128
+
1129
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TREE_DISCONNECT
1130
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1131
+ if self.require_signing
1132
+ #ascii
1133
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1134
+ else
1135
+ #ascii
1136
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1137
+ end
1138
+
1139
+ pkt['Payload']['SMB'].v['WordCount'] = 0
1140
+ pkt['Payload']['SMB'].v['TreeID'] = tree_id
1141
+
1142
+ ret = self.smb_send(pkt.to_s)
1143
+ return ret if not do_recv
1144
+
1145
+ ack = self.smb_recv_parse(CONST::SMB_COM_TREE_DISCONNECT)
1146
+
1147
+ if (tree_id == self.last_tree_id)
1148
+ self.last_tree_id = 0
1149
+ end
1150
+
1151
+ return ack
1152
+ end
1153
+
1154
+ # Returns a SMB_CREATE_RES response for a given named pipe
1155
+ def create_pipe(filename, disposition = 1, impersonation = 2)
1156
+ self.create(filename)
1157
+ end
1158
+
1159
+ # Creates a file or opens an existing pipe
1160
+ def create(filename, disposition = 1, impersonation = 2, do_recv = true)
1161
+
1162
+ pkt = CONST::SMB_CREATE_PKT.make_struct
1163
+ self.smb_defaults(pkt['Payload']['SMB'])
1164
+
1165
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
1166
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1167
+ if self.require_signing
1168
+ #ascii
1169
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1170
+ else
1171
+ #ascii
1172
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1173
+ end
1174
+
1175
+ pkt['Payload']['SMB'].v['WordCount'] = 24
1176
+
1177
+ pkt['Payload'].v['AndX'] = 255
1178
+ pkt['Payload'].v['FileNameLen'] = filename.length
1179
+ pkt['Payload'].v['CreateFlags'] = 0x16
1180
+ pkt['Payload'].v['AccessMask'] = 0x02000000 # Maximum Allowed
1181
+ pkt['Payload'].v['ShareAccess'] = 7
1182
+ pkt['Payload'].v['CreateOptions'] = 0
1183
+ pkt['Payload'].v['Impersonation'] = impersonation
1184
+ pkt['Payload'].v['Disposition'] = disposition
1185
+ pkt['Payload'].v['Payload'] = filename + "\x00"
1186
+
1187
+ ret = self.smb_send(pkt.to_s)
1188
+ return ret if not do_recv
1189
+
1190
+ ack = self.smb_recv_parse(CONST::SMB_COM_NT_CREATE_ANDX)
1191
+
1192
+ # Save off the FileID
1193
+ if (ack['Payload'].v['FileID'] > 0)
1194
+ self.last_file_id = ack['Payload'].v['FileID']
1195
+ end
1196
+
1197
+ return ack
1198
+ end
1199
+
1200
+ # Deletes a file from a share
1201
+ def delete(filename, tree_id = self.last_tree_id, do_recv = true)
1202
+
1203
+ pkt = CONST::SMB_DELETE_PKT.make_struct
1204
+ self.smb_defaults(pkt['Payload']['SMB'])
1205
+
1206
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_DELETE
1207
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1208
+ if self.require_signing
1209
+ #ascii
1210
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1211
+ else
1212
+ #ascii
1213
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1214
+ end
1215
+
1216
+ pkt['Payload']['SMB'].v['TreeID'] = tree_id
1217
+ pkt['Payload']['SMB'].v['WordCount'] = 1
1218
+
1219
+ pkt['Payload'].v['SearchAttributes'] = 0x06
1220
+ pkt['Payload'].v['BufferFormat'] = 4
1221
+ pkt['Payload'].v['Payload'] = filename + "\x00"
1222
+
1223
+ ret = self.smb_send(pkt.to_s)
1224
+ return ret if not do_recv
1225
+
1226
+ ack = self.smb_recv_parse(CONST::SMB_COM_DELETE)
1227
+
1228
+ return ack
1229
+ end
1230
+
1231
+ # Opens an existing file or creates a new one
1232
+ def open(filename, mode = 0x12, access = 0x42, do_recv = true)
1233
+
1234
+ pkt = CONST::SMB_OPEN_PKT.make_struct
1235
+ self.smb_defaults(pkt['Payload']['SMB'])
1236
+
1237
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_OPEN_ANDX
1238
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1239
+ if self.require_signing
1240
+ #ascii
1241
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1242
+ else
1243
+ #ascii
1244
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1245
+ end
1246
+
1247
+ pkt['Payload']['SMB'].v['WordCount'] = 15
1248
+
1249
+ pkt['Payload'].v['AndX'] = 255
1250
+ pkt['Payload'].v['Access'] = access
1251
+ pkt['Payload'].v['SearchAttributes'] = 0x06
1252
+ pkt['Payload'].v['OpenFunction'] = mode
1253
+ pkt['Payload'].v['Payload'] = filename + "\x00"
1254
+
1255
+ ret = self.smb_send(pkt.to_s)
1256
+ return ret if not do_recv
1257
+
1258
+ ack = self.smb_recv_parse(CONST::SMB_COM_OPEN_ANDX)
1259
+
1260
+ # Save off the FileID
1261
+ if (ack['Payload'].v['FileID'] > 0)
1262
+ self.last_file_id = ack['Payload'].v['FileID']
1263
+ end
1264
+
1265
+ return ack
1266
+ end
1267
+
1268
+ # Closes an open file handle
1269
+ def close(file_id = self.last_file_id, tree_id = self.last_tree_id, do_recv = true)
1270
+
1271
+ pkt = CONST::SMB_CLOSE_PKT.make_struct
1272
+ self.smb_defaults(pkt['Payload']['SMB'])
1273
+
1274
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_CLOSE
1275
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1276
+ if self.require_signing
1277
+ #ascii
1278
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1279
+ else
1280
+ #ascii
1281
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1282
+ end
1283
+
1284
+ pkt['Payload']['SMB'].v['TreeID'] = tree_id
1285
+ pkt['Payload']['SMB'].v['WordCount'] = 3
1286
+
1287
+ pkt['Payload'].v['FileID'] = file_id
1288
+ pkt['Payload'].v['LastWrite'] = -1
1289
+
1290
+ ret = self.smb_send(pkt.to_s)
1291
+ return ret if not do_recv
1292
+
1293
+ ack = self.smb_recv_parse(CONST::SMB_COM_CLOSE)
1294
+
1295
+ return ack
1296
+ end
1297
+
1298
+ # Writes data to an open file handle
1299
+ def write(file_id = self.last_file_id, offset = 0, data = '', do_recv = true)
1300
+ pkt = CONST::SMB_WRITE_PKT.make_struct
1301
+ self.smb_defaults(pkt['Payload']['SMB'])
1302
+
1303
+ data_offset = pkt.to_s.length - 4
1304
+
1305
+ filler = EVADE.make_offset_filler(evasion_opts['pad_data'], 4096 - data.length - data_offset)
1306
+
1307
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_WRITE_ANDX
1308
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1309
+ if self.require_signing
1310
+ #ascii
1311
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2805
1312
+ else
1313
+ #ascii
1314
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1315
+ end
1316
+
1317
+ pkt['Payload']['SMB'].v['WordCount'] = 14
1318
+
1319
+ pkt['Payload'].v['AndX'] = 255
1320
+ pkt['Payload'].v['FileID'] = file_id
1321
+ pkt['Payload'].v['Offset'] = offset
1322
+ pkt['Payload'].v['Reserved2'] = -1
1323
+ pkt['Payload'].v['WriteMode'] = 8
1324
+ pkt['Payload'].v['Remaining'] = data.length
1325
+ # pkt['Payload'].v['DataLenHigh'] = (data.length / 65536).to_i
1326
+ pkt['Payload'].v['DataLenLow'] = (data.length % 65536).to_i
1327
+ pkt['Payload'].v['DataOffset'] = data_offset + filler.length
1328
+ pkt['Payload'].v['Payload'] = filler + data
1329
+
1330
+ ret = self.smb_send(pkt.to_s)
1331
+ return ret if not do_recv
1332
+
1333
+ ack = self.smb_recv_parse(CONST::SMB_COM_WRITE_ANDX)
1334
+
1335
+ return ack
1336
+ end
1337
+
1338
+
1339
+ # Reads data from an open file handle
1340
+ def read(file_id = self.last_file_id, offset = 0, data_length = 64000, do_recv = true)
1341
+
1342
+ pkt = CONST::SMB_READ_PKT.make_struct
1343
+ self.smb_defaults(pkt['Payload']['SMB'])
1344
+
1345
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_READ_ANDX
1346
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1347
+ if self.require_signing
1348
+ #ascii
1349
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1350
+ else
1351
+ #ascii
1352
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1353
+ end
1354
+
1355
+ pkt['Payload']['SMB'].v['WordCount'] = 10
1356
+
1357
+ pkt['Payload'].v['AndX'] = 255
1358
+ pkt['Payload'].v['FileID'] = file_id
1359
+ pkt['Payload'].v['Offset'] = offset
1360
+ # pkt['Payload'].v['MaxCountHigh'] = (data_length / 65536).to_i
1361
+ pkt['Payload'].v['MaxCountLow'] = (data_length % 65536).to_i
1362
+ pkt['Payload'].v['MinCount'] = data_length
1363
+ pkt['Payload'].v['Reserved2'] = -1
1364
+
1365
+ ret = self.smb_send(pkt.to_s)
1366
+ return ret if not do_recv
1367
+
1368
+ ack = self.smb_recv_parse(CONST::SMB_COM_READ_ANDX, true)
1369
+
1370
+ err = ack['Payload']['SMB'].v['ErrorClass']
1371
+
1372
+ # Catch some non-fatal error codes
1373
+ if (err != 0 && err != CONST::SMB_ERROR_BUFFER_OVERFLOW)
1374
+ failure = XCEPT::ErrorCode.new
1375
+ failure.word_count = ack['Payload']['SMB'].v['WordCount']
1376
+ failure.command = ack['Payload']['SMB'].v['Command']
1377
+ failure.error_code = ack['Payload']['SMB'].v['ErrorClass']
1378
+ raise failure
1379
+ end
1380
+
1381
+ return ack
1382
+ end
1383
+
1384
+
1385
+ # Perform a transaction against a named pipe
1386
+ def trans_named_pipe(file_id, data = '', no_response = nil)
1387
+ pipe = EVADE.make_trans_named_pipe_name(evasion_opts['pad_file'])
1388
+ self.trans(pipe, '', data, 2, [0x26, file_id].pack('vv'), no_response)
1389
+ end
1390
+
1391
+ # Perform a mailslot write over SMB
1392
+ # Warning: This can kill srv.sys unless MS06-035 is applied
1393
+ def trans_mailslot (name, data = '')
1394
+ # Setup data must be:
1395
+ # Operation: 1 (write)
1396
+ # Priority: 0
1397
+ # Class: Reliable
1398
+ self.trans_maxzero(name, '', data, 3, [1, 0, 1].pack('vvv'), true )
1399
+ end
1400
+
1401
+ # Perform a transaction against a given pipe name
1402
+ def trans(pipe, param = '', body = '', setup_count = 0, setup_data = '', no_response = false, do_recv = true)
1403
+
1404
+ # Null-terminate the pipe parameter if needed
1405
+ if (pipe[-1,1] != "\x00")
1406
+ pipe << "\x00"
1407
+ end
1408
+
1409
+ pkt = CONST::SMB_TRANS_PKT.make_struct
1410
+ self.smb_defaults(pkt['Payload']['SMB'])
1411
+
1412
+ # Packets larger than mlen will cause XP SP2 to disconnect us ;-(
1413
+ mlen = 4200
1414
+
1415
+ # Figure out how much space is taken up by our current arguments
1416
+ xlen = pipe.length + param.length + body.length
1417
+
1418
+ filler1 = ''
1419
+ filler2 = ''
1420
+
1421
+ # Fill any available space depending on the evasion settings
1422
+ if (xlen < mlen)
1423
+ filler1 = EVADE.make_offset_filler(evasion_opts['pad_data'], (mlen-xlen)/2)
1424
+ filler2 = EVADE.make_offset_filler(evasion_opts['pad_data'], (mlen-xlen)/2)
1425
+ end
1426
+
1427
+ # Squish the whole thing together
1428
+ data = pipe + filler1 + param + filler2 + body
1429
+
1430
+ # Throw some form of a warning out?
1431
+ if (data.length > mlen)
1432
+ # XXX This call will more than likely fail :-(
1433
+ end
1434
+
1435
+ # Calculate all of the offsets
1436
+ base_offset = pkt.to_s.length + (setup_count * 2) - 4
1437
+ param_offset = base_offset + pipe.length + filler1.length
1438
+ data_offset = param_offset + filler2.length + param.length
1439
+
1440
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION
1441
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1442
+ if self.require_signing
1443
+ #ascii
1444
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1445
+ else
1446
+ #ascii
1447
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1448
+ end
1449
+
1450
+ pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1451
+
1452
+ pkt['Payload'].v['ParamCountTotal'] = param.length
1453
+ pkt['Payload'].v['DataCountTotal'] = body.length
1454
+ pkt['Payload'].v['ParamCountMax'] = 1024
1455
+ pkt['Payload'].v['DataCountMax'] = 65000
1456
+ pkt['Payload'].v['ParamCount'] = param.length
1457
+ pkt['Payload'].v['ParamOffset'] = param_offset
1458
+ pkt['Payload'].v['DataCount'] = body.length
1459
+ pkt['Payload'].v['DataOffset'] = data_offset
1460
+ pkt['Payload'].v['SetupCount'] = setup_count
1461
+ pkt['Payload'].v['SetupData'] = setup_data
1462
+
1463
+ pkt['Payload'].v['Payload'] = data
1464
+
1465
+ if no_response
1466
+ pkt['Payload'].v['Flags'] = 2
1467
+ end
1468
+
1469
+ ret = self.smb_send(pkt.to_s)
1470
+ return ret if no_response or not do_recv
1471
+
1472
+ self.smb_recv_parse(CONST::SMB_COM_TRANSACTION)
1473
+ end
1474
+
1475
+
1476
+
1477
+ # Perform a transaction against a given pipe name
1478
+ # Difference from trans: sets MaxParam/MaxData to zero
1479
+ # This is required to trigger mailslot bug :-(
1480
+ def trans_maxzero(pipe, param = '', body = '', setup_count = 0, setup_data = '', no_response = false, do_recv = true)
1481
+
1482
+ # Null-terminate the pipe parameter if needed
1483
+ if (pipe[-1] != 0)
1484
+ pipe << "\x00"
1485
+ end
1486
+
1487
+ pkt = CONST::SMB_TRANS_PKT.make_struct
1488
+ self.smb_defaults(pkt['Payload']['SMB'])
1489
+
1490
+ # Packets larger than mlen will cause XP SP2 to disconnect us ;-(
1491
+ mlen = 4200
1492
+
1493
+ # Figure out how much space is taken up by our current arguments
1494
+ xlen = pipe.length + param.length + body.length
1495
+
1496
+ filler1 = ''
1497
+ filler2 = ''
1498
+
1499
+ # Fill any available space depending on the evasion settings
1500
+ if (xlen < mlen)
1501
+ filler1 = EVADE.make_offset_filler(evasion_opts['pad_data'], (mlen-xlen)/2)
1502
+ filler2 = EVADE.make_offset_filler(evasion_opts['pad_data'], (mlen-xlen)/2)
1503
+ end
1504
+
1505
+ # Squish the whole thing together
1506
+ data = pipe + filler1 + param + filler2 + body
1507
+
1508
+ # Throw some form of a warning out?
1509
+ if (data.length > mlen)
1510
+ # XXX This call will more than likely fail :-(
1511
+ end
1512
+
1513
+ # Calculate all of the offsets
1514
+ base_offset = pkt.to_s.length + (setup_count * 2) - 4
1515
+ param_offset = base_offset + pipe.length + filler1.length
1516
+ data_offset = param_offset + filler2.length + param.length
1517
+
1518
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION
1519
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1520
+ if self.require_signing
1521
+ #ascii
1522
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1523
+ else
1524
+ #ascii
1525
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1526
+ end
1527
+
1528
+ pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1529
+
1530
+ pkt['Payload'].v['ParamCountTotal'] = param.length
1531
+ pkt['Payload'].v['DataCountTotal'] = body.length
1532
+ pkt['Payload'].v['ParamCountMax'] = 0
1533
+ pkt['Payload'].v['DataCountMax'] = 0
1534
+ pkt['Payload'].v['ParamCount'] = param.length
1535
+ pkt['Payload'].v['ParamOffset'] = param_offset
1536
+ pkt['Payload'].v['DataCount'] = body.length
1537
+ pkt['Payload'].v['DataOffset'] = data_offset
1538
+ pkt['Payload'].v['SetupCount'] = setup_count
1539
+ pkt['Payload'].v['SetupData'] = setup_data
1540
+
1541
+ pkt['Payload'].v['Payload'] = data
1542
+
1543
+ if no_response
1544
+ pkt['Payload'].v['Flags'] = 2
1545
+ end
1546
+
1547
+ ret = self.smb_send(pkt.to_s)
1548
+ return ret if no_response or not do_recv
1549
+
1550
+ self.smb_recv_parse(CONST::SMB_COM_TRANSACTION)
1551
+ end
1552
+
1553
+
1554
+ # Perform a transaction against a given pipe name (no null terminator)
1555
+ def trans_nonull(pipe, param = '', body = '', setup_count = 0, setup_data = '', no_response = false, do_recv = true)
1556
+
1557
+ pkt = CONST::SMB_TRANS_PKT.make_struct
1558
+ self.smb_defaults(pkt['Payload']['SMB'])
1559
+
1560
+ # Packets larger than mlen will cause XP SP2 to disconnect us ;-(
1561
+ mlen = 4200
1562
+
1563
+ # Figure out how much space is taken up by our current arguments
1564
+ xlen = pipe.length + param.length + body.length
1565
+
1566
+ filler1 = ''
1567
+ filler2 = ''
1568
+
1569
+ # Fill any available space depending on the evasion settings
1570
+ if (xlen < mlen)
1571
+ filler1 = EVADE.make_offset_filler(evasion_opts['pad_data'], (mlen-xlen)/2)
1572
+ filler2 = EVADE.make_offset_filler(evasion_opts['pad_data'], (mlen-xlen)/2)
1573
+ end
1574
+
1575
+ # Squish the whole thing together
1576
+ data = pipe + filler1 + param + filler2 + body
1577
+
1578
+ # Throw some form of a warning out?
1579
+ if (data.length > mlen)
1580
+ # XXX This call will more than likely fail :-(
1581
+ end
1582
+
1583
+ # Calculate all of the offsets
1584
+ base_offset = pkt.to_s.length + (setup_count * 2) - 4
1585
+ param_offset = base_offset + pipe.length + filler1.length
1586
+ data_offset = param_offset + filler2.length + param.length
1587
+
1588
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION
1589
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1590
+ if self.require_signing
1591
+ #ascii
1592
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1593
+ else
1594
+ #ascii
1595
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1596
+ end
1597
+
1598
+ pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1599
+
1600
+ pkt['Payload'].v['ParamCountTotal'] = param.length
1601
+ pkt['Payload'].v['DataCountTotal'] = body.length
1602
+ pkt['Payload'].v['ParamCountMax'] = 0
1603
+ pkt['Payload'].v['DataCountMax'] = 0
1604
+ pkt['Payload'].v['ParamCount'] = param.length
1605
+ pkt['Payload'].v['ParamOffset'] = param_offset
1606
+ pkt['Payload'].v['DataCount'] = body.length
1607
+ pkt['Payload'].v['DataOffset'] = data_offset
1608
+ pkt['Payload'].v['SetupCount'] = setup_count
1609
+ pkt['Payload'].v['SetupData'] = setup_data
1610
+
1611
+ pkt['Payload'].v['Payload'] = data
1612
+
1613
+ if no_response
1614
+ pkt['Payload'].v['Flags'] = 2
1615
+ end
1616
+
1617
+ ret = self.smb_send(pkt.to_s)
1618
+ return ret if no_response or not do_recv
1619
+
1620
+ self.smb_recv_parse(CONST::SMB_COM_TRANSACTION)
1621
+ end
1622
+
1623
+ # Perform a transaction2 request using the specified subcommand, parameters, and data
1624
+ def trans2(subcommand, param = '', body = '', do_recv = true)
1625
+
1626
+ setup_count = 1
1627
+ setup_data = [subcommand].pack('v')
1628
+
1629
+ data = param + body
1630
+
1631
+ pkt = CONST::SMB_TRANS2_PKT.make_struct
1632
+ self.smb_defaults(pkt['Payload']['SMB'])
1633
+
1634
+ base_offset = pkt.to_s.length + (setup_count * 2) - 4
1635
+ param_offset = base_offset
1636
+ data_offset = param_offset + param.length
1637
+
1638
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION2
1639
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1640
+ if self.require_signing
1641
+ #ascii
1642
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1643
+ else
1644
+ #ascii
1645
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1646
+ end
1647
+
1648
+ pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
1649
+
1650
+ pkt['Payload'].v['ParamCountTotal'] = param.length
1651
+ pkt['Payload'].v['DataCountTotal'] = body.length
1652
+ pkt['Payload'].v['ParamCountMax'] = 1024
1653
+ pkt['Payload'].v['DataCountMax'] = 65000
1654
+ pkt['Payload'].v['ParamCount'] = param.length
1655
+ pkt['Payload'].v['ParamOffset'] = param_offset
1656
+ pkt['Payload'].v['DataCount'] = body.length
1657
+ pkt['Payload'].v['DataOffset'] = data_offset
1658
+ pkt['Payload'].v['SetupCount'] = setup_count
1659
+ pkt['Payload'].v['SetupData'] = setup_data
1660
+
1661
+ pkt['Payload'].v['Payload'] = data
1662
+
1663
+ ret = self.smb_send(pkt.to_s)
1664
+ return ret if not do_recv
1665
+
1666
+ ack = self.smb_recv_parse(CONST::SMB_COM_TRANSACTION2)
1667
+
1668
+ return ack
1669
+ end
1670
+
1671
+
1672
+ # Perform a nttransaction request using the specified subcommand, parameters, and data
1673
+ def nttrans(subcommand, param = '', body = '', setup_count = 0, setup_data = '', do_recv = true)
1674
+
1675
+ data = param + body
1676
+
1677
+ pkt = CONST::SMB_NTTRANS_PKT.make_struct
1678
+ self.smb_defaults(pkt['Payload']['SMB'])
1679
+
1680
+ base_offset = pkt.to_s.length + (setup_count * 2) - 4
1681
+ param_offset = base_offset
1682
+ data_offset = param_offset + param.length
1683
+
1684
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_TRANSACT
1685
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1686
+ if self.require_signing
1687
+ #ascii
1688
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1689
+ else
1690
+ #ascii
1691
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1692
+ end
1693
+
1694
+ pkt['Payload']['SMB'].v['WordCount'] = 19 + setup_count
1695
+
1696
+ pkt['Payload'].v['ParamCountTotal'] = param.length
1697
+ pkt['Payload'].v['DataCountTotal'] = body.length
1698
+ pkt['Payload'].v['ParamCountMax'] = 1024
1699
+ pkt['Payload'].v['DataCountMax'] = 65000
1700
+ pkt['Payload'].v['ParamCount'] = param.length
1701
+ pkt['Payload'].v['ParamOffset'] = param_offset
1702
+ pkt['Payload'].v['DataCount'] = body.length
1703
+ pkt['Payload'].v['DataOffset'] = data_offset
1704
+ pkt['Payload'].v['SetupCount'] = setup_count
1705
+ pkt['Payload'].v['SetupData'] = setup_data
1706
+ pkt['Payload'].v['Subcommand'] = subcommand
1707
+
1708
+ pkt['Payload'].v['Payload'] = data
1709
+
1710
+ ret = self.smb_send(pkt.to_s)
1711
+ return ret if not do_recv
1712
+
1713
+ ack = self.smb_recv_parse(CONST::SMB_COM_NT_TRANSACT)
1714
+ return ack
1715
+ end
1716
+
1717
+ # Perform a nttransaction request using the specified subcommand, parameters, and data
1718
+ def nttrans_secondary(param = '', body = '', do_recv = true)
1719
+
1720
+ data = param + body
1721
+
1722
+ pkt = CONST::SMB_NTTRANS_SECONDARY_PKT.make_struct
1723
+ self.smb_defaults(pkt['Payload']['SMB'])
1724
+
1725
+ base_offset = pkt.to_s.length - 4
1726
+ param_offset = base_offset
1727
+ data_offset = param_offset + param.length
1728
+
1729
+ pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_TRANSACT_SECONDARY
1730
+ pkt['Payload']['SMB'].v['Flags1'] = 0x18
1731
+ if self.require_signing
1732
+ #ascii
1733
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2807
1734
+ else
1735
+ #ascii
1736
+ pkt['Payload']['SMB'].v['Flags2'] = 0x2801
1737
+ end
1738
+
1739
+ pkt['Payload']['SMB'].v['WordCount'] = 18
1740
+
1741
+ pkt['Payload'].v['ParamCountTotal'] = param.length
1742
+ pkt['Payload'].v['DataCountTotal'] = body.length
1743
+ pkt['Payload'].v['ParamCount'] = param.length
1744
+ pkt['Payload'].v['ParamOffset'] = param_offset
1745
+ pkt['Payload'].v['DataCount'] = body.length
1746
+ pkt['Payload'].v['DataOffset'] = data_offset
1747
+
1748
+ pkt['Payload'].v['Payload'] = data
1749
+
1750
+ ret = self.smb_send(pkt.to_s)
1751
+ return ret if not do_recv
1752
+
1753
+ ack = self.smb_recv_parse(CONST::SMB_COM_NT_TRANSACT_SECONDARY)
1754
+ return ack
1755
+ end
1756
+
1757
+ def queryfs(level)
1758
+ parm = [level].pack('v')
1759
+
1760
+ begin
1761
+ resp = trans2(CONST::TRANS2_QUERY_FS_INFO, parm, '')
1762
+
1763
+ pcnt = resp['Payload'].v['ParamCount']
1764
+ dcnt = resp['Payload'].v['DataCount']
1765
+ poff = resp['Payload'].v['ParamOffset']
1766
+ doff = resp['Payload'].v['DataOffset']
1767
+
1768
+ # Get the raw packet bytes
1769
+ resp_rpkt = resp.to_s
1770
+
1771
+ # Remove the NetBIOS header
1772
+ resp_rpkt.slice!(0, 4)
1773
+
1774
+ resp_parm = resp_rpkt[poff, pcnt]
1775
+ resp_data = resp_rpkt[doff, dcnt]
1776
+ return resp_data
1777
+
1778
+ rescue ::Exception
1779
+ raise $!
1780
+ end
1781
+ end
1782
+
1783
+ def symlink(src,dst)
1784
+ parm = [513, 0x00000000].pack('vV') + src + "\x00"
1785
+
1786
+ begin
1787
+ resp = trans2(CONST::TRANS2_SET_PATH_INFO, parm, dst + "\x00")
1788
+
1789
+ pcnt = resp['Payload'].v['ParamCount']
1790
+ dcnt = resp['Payload'].v['DataCount']
1791
+ poff = resp['Payload'].v['ParamOffset']
1792
+ doff = resp['Payload'].v['DataOffset']
1793
+
1794
+ # Get the raw packet bytes
1795
+ resp_rpkt = resp.to_s
1796
+
1797
+ # Remove the NetBIOS header
1798
+ resp_rpkt.slice!(0, 4)
1799
+
1800
+ resp_parm = resp_rpkt[poff, pcnt]
1801
+ resp_data = resp_rpkt[doff, dcnt]
1802
+ return resp_data
1803
+
1804
+ rescue ::Exception
1805
+ raise $!
1806
+ end
1807
+ end
1808
+
1809
+ # Obtains allocation information on the mounted tree
1810
+ def queryfs_info_allocation
1811
+ data = queryfs(CONST::SMB_INFO_ALLOCATION)
1812
+ head = %w{fs_id sectors_per_unit unit_total units_available bytes_per_sector}
1813
+ vals = data.unpack('VVVVv')
1814
+ info = { }
1815
+ head.each_index {|i| info[head[i]]=vals[i]}
1816
+ return info
1817
+ end
1818
+
1819
+ # Obtains volume information on the mounted tree
1820
+ def queryfs_info_volume
1821
+ data = queryfs(CONST::SMB_INFO_VOLUME)
1822
+ vals = data.unpack('VCA*')
1823
+ return {
1824
+ 'serial' => vals[0],
1825
+ 'label' => vals[2][0,vals[1]].gsub("\x00", '')
1826
+ }
1827
+ end
1828
+
1829
+ # Obtains file system volume information on the mounted tree
1830
+ def queryfs_fs_volume
1831
+ data = queryfs(CONST::SMB_QUERY_FS_VOLUME_INFO)
1832
+ vals = data.unpack('VVVVCCA*')
1833
+ return {
1834
+ 'create_time' => (vals[1] << 32) + vals[0],
1835
+ 'serial' => vals[2],
1836
+ 'label' => vals[6][0,vals[3]].gsub("\x00", '')
1837
+ }
1838
+ end
1839
+
1840
+ # Obtains file system size information on the mounted tree
1841
+ def queryfs_fs_size
1842
+ data = queryfs(CONST::SMB_QUERY_FS_SIZE_INFO)
1843
+ vals = data.unpack('VVVVVV')
1844
+ return {
1845
+ 'total_alloc_units' => (vals[1] << 32) + vals[0],
1846
+ 'total_free_units' => (vals[3] << 32) + vals[2],
1847
+ 'sectors_per_unit' => vals[4],
1848
+ 'bytes_per_sector' => vals[5]
1849
+ }
1850
+ end
1851
+
1852
+ # Obtains file system device information on the mounted tree
1853
+ def queryfs_fs_device
1854
+ data = queryfs(CONST::SMB_QUERY_FS_DEVICE_INFO)
1855
+ vals = data.unpack('VV')
1856
+ return {
1857
+ 'device_type' => vals[0],
1858
+ 'device_chars' => vals[1],
1859
+ }
1860
+ end
1861
+
1862
+ # Obtains file system attribute information on the mounted tree
1863
+ def queryfs_fs_attribute
1864
+ data = queryfs(CONST::SMB_QUERY_FS_ATTRIBUTE_INFO)
1865
+ vals = data.unpack('VVVA*')
1866
+ return {
1867
+ 'fs_attributes' => vals[0],
1868
+ 'max_file_name' => vals[1],
1869
+ 'fs_name' => vals[3][0, vals[2]].gsub("\x00", '')
1870
+ }
1871
+ end
1872
+
1873
+ # Enumerates a specific path on the mounted tree
1874
+ def find_first(path)
1875
+ files = { }
1876
+ parm = [
1877
+ 26, # Search for ALL files
1878
+ 20, # Maximum search count
1879
+ 6, # Resume and Close on End of Search
1880
+ 260, # Level of interest
1881
+ 0, # Storage type is zero
1882
+ ].pack('vvvvV') + path + "\x00"
1883
+
1884
+ resp = trans2(CONST::TRANS2_FIND_FIRST2, parm, '')
1885
+ search_next = 0
1886
+
1887
+ # Loop until we run out of results
1888
+ loop do
1889
+ pcnt = resp['Payload'].v['ParamCount']
1890
+ dcnt = resp['Payload'].v['DataCount']
1891
+ poff = resp['Payload'].v['ParamOffset']
1892
+ doff = resp['Payload'].v['DataOffset']
1893
+
1894
+ # Get the raw packet bytes
1895
+ resp_rpkt = resp.to_s
1896
+
1897
+ # Remove the NetBIOS header
1898
+ resp_rpkt.slice!(0, 4)
1899
+
1900
+ resp_parm = resp_rpkt[poff, pcnt]
1901
+ resp_data = resp_rpkt[doff, dcnt]
1902
+
1903
+ if search_next == 0
1904
+ # search id, search count, end of search, error offset, last name offset
1905
+ sid, scnt, eos, eoff, loff = resp_parm.unpack('v5')
1906
+ else
1907
+ # FIND_NEXT doesn't return a SID
1908
+ scnt, eos, eoff, loff = resp_parm.unpack('v4')
1909
+ end
1910
+
1911
+ didx = 0
1912
+ while (didx < resp_data.length)
1913
+ info_buff = resp_data[didx, 70]
1914
+ break if info_buff.length != 70
1915
+
1916
+ info = info_buff.unpack(
1917
+ 'V'+ # Next Entry Offset
1918
+ 'V'+ # File Index
1919
+ 'VV'+ # Time Create
1920
+ 'VV'+ # Time Last Access
1921
+ 'VV'+ # Time Last Write
1922
+ 'VV'+ # Time Change
1923
+ 'VV'+ # End of File
1924
+ 'VV'+ # Allocation Size
1925
+ 'V'+ # File Attributes
1926
+ 'V'+ # File Name Length
1927
+ 'V'+ # Extended Attr List Length
1928
+ 'C'+ # Short File Name Length
1929
+ 'C' # Reserved
1930
+ )
1931
+
1932
+ name = resp_data[didx + 70 + 24, info[15]]
1933
+
1934
+ # Verify that the filename was actually present
1935
+ break unless name
1936
+
1937
+ # Key the file list minus any trailing nulls
1938
+ files[name.sub(/\x00+$/n, '')] =
1939
+ {
1940
+ 'type' => ( info[14] & CONST::SMB_EXT_FILE_ATTR_DIRECTORY == 0 ) ? 'F' : 'D',
1941
+ 'attr' => info[14],
1942
+ 'info' => info
1943
+ }
1944
+
1945
+ break if info[0] == 0
1946
+ didx += info[0]
1947
+ end
1948
+
1949
+ last_search_id = sid
1950
+ last_offset = loff
1951
+ last_filename = name
1952
+
1953
+ # Exit the search if we reached the end of our results
1954
+ break if (eos != 0 or last_search_id.nil? or last_offset.to_i == 0)
1955
+
1956
+ # If we aren't at the end of the search, run find_next
1957
+ resp = find_next(last_search_id, last_offset, last_filename)
1958
+
1959
+ # Flip bit so response params will parse correctly
1960
+ search_next = 1
1961
+ end
1962
+
1963
+ files
1964
+ end
1965
+
1966
+ # Supplements find_first if file/dir count exceeds max search count
1967
+ def find_next(sid, resume_key, last_filename)
1968
+
1969
+ parm = [
1970
+ sid, # Search ID
1971
+ 20, # Maximum search count (Size of 20 keeps response to 1 packet)
1972
+ 260, # Level of interest
1973
+ resume_key, # Resume key from previous (Last name offset)
1974
+ 6, # Close search if end of search
1975
+ ].pack('vvvVv') +
1976
+ last_filename.to_s + # Last filename returned from find_first or find_next
1977
+ "\x00" # Terminate the file name
1978
+
1979
+ # Returns the FIND_NEXT2 response packet for parsing by the find_first function
1980
+ trans2(CONST::TRANS2_FIND_NEXT2, parm, '')
1981
+ end
1982
+
1983
+ # Recursively search for files matching a regular expression
1984
+ def file_search(current_path, regex, depth)
1985
+ depth -= 1
1986
+ return [] if depth < 0
1987
+
1988
+ results = find_first(current_path + "*")
1989
+ files = []
1990
+
1991
+ results.each_pair do |fname, finfo|
1992
+
1993
+ # Skip current and parent directory results
1994
+ next if %W{. ..}.include?(fname)
1995
+
1996
+ # Verify the results contain an attribute
1997
+ next unless finfo and finfo['attr']
1998
+
1999
+ if finfo['attr'] & CONST::SMB_EXT_FILE_ATTR_DIRECTORY == 0
2000
+ # Add any matching files to our result set
2001
+ files << "#{current_path}#{fname}" if fname =~ regex
2002
+ else
2003
+ # Recurse into the discovery subdirectory for more files
2004
+ begin
2005
+ search_path = "#{current_path}#{fname}\\"
2006
+ file_search(search_path, regex, depth).each {|fn| files << fn }
2007
+ rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
2008
+
2009
+ # Ignore common errors related to permissions and non-files
2010
+ if %W{
2011
+ STATUS_ACCESS_DENIED
2012
+ STATUS_NO_SUCH_FILE
2013
+ STATUS_OBJECT_NAME_NOT_FOUND
2014
+ STATUS_OBJECT_PATH_NOT_FOUND
2015
+ }.include? e.get_error(e.error_code)
2016
+ next
2017
+ end
2018
+
2019
+ $stderr.puts [e, e.get_error(e.error_code), search_path]
2020
+
2021
+ raise e
2022
+ end
2023
+ end
2024
+
2025
+ end
2026
+
2027
+ files.uniq
2028
+ end
2029
+
2030
+ # Creates a new directory on the mounted tree
2031
+ def create_directory(name)
2032
+ files = { }
2033
+ parm = [0].pack('V') + name + "\x00"
2034
+ resp = trans2(CONST::TRANS2_CREATE_DIRECTORY, parm, '')
2035
+ end
2036
+
2037
+ # public read/write methods
2038
+ attr_accessor :native_os, :native_lm, :encrypt_passwords, :extended_security, :read_timeout, :evasion_opts
2039
+ attr_accessor :verify_signature, :use_ntlmv2, :usentlm2_session, :send_lm, :use_lanman_key, :send_ntlm
2040
+ attr_accessor :system_time, :system_zone
2041
+ attr_accessor :spnopt
2042
+
2043
+ # public read methods
2044
+ attr_reader :dialect, :session_id, :challenge_key, :peer_native_lm, :peer_native_os
2045
+ attr_reader :default_domain, :default_name, :auth_user, :auth_user_id
2046
+ attr_reader :multiplex_id, :last_tree_id, :last_file_id, :process_id, :last_search_id
2047
+ attr_reader :dns_host_name, :dns_domain_name
2048
+ attr_reader :security_mode, :server_guid
2049
+ attr_reader :sequence_counter,:signing_key, :require_signing
2050
+
2051
+ # private write methods
2052
+ attr_writer :dialect, :session_id, :challenge_key, :peer_native_lm, :peer_native_os
2053
+ attr_writer :default_domain, :default_name, :auth_user, :auth_user_id
2054
+ attr_writer :dns_host_name, :dns_domain_name
2055
+ attr_writer :multiplex_id, :last_tree_id, :last_file_id, :process_id, :last_search_id
2056
+ attr_writer :security_mode, :server_guid
2057
+ attr_writer :sequence_counter,:signing_key, :require_signing
2058
+
2059
+ attr_accessor :socket
2060
+
2061
+ end
2062
+ end
2063
+ end
2064
+ end