librex 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. data/README +4 -0
  2. data/lib/rex.rb +101 -0
  3. data/lib/rex.rb.ts.rb +70 -0
  4. data/lib/rex/LICENSE +29 -0
  5. data/lib/rex/arch.rb +103 -0
  6. data/lib/rex/arch/sparc.rb +75 -0
  7. data/lib/rex/arch/sparc.rb.ut.rb +18 -0
  8. data/lib/rex/arch/x86.rb +513 -0
  9. data/lib/rex/arch/x86.rb.ut.rb +93 -0
  10. data/lib/rex/assembly/nasm.rb +100 -0
  11. data/lib/rex/assembly/nasm.rb.ut.rb +22 -0
  12. data/lib/rex/codepage.map +104 -0
  13. data/lib/rex/compat.rb +281 -0
  14. data/lib/rex/constants.rb +113 -0
  15. data/lib/rex/elfparsey.rb +11 -0
  16. data/lib/rex/elfparsey/elf.rb +123 -0
  17. data/lib/rex/elfparsey/elfbase.rb +260 -0
  18. data/lib/rex/elfparsey/exceptions.rb +27 -0
  19. data/lib/rex/elfscan.rb +12 -0
  20. data/lib/rex/elfscan/scanner.rb +207 -0
  21. data/lib/rex/elfscan/search.rb +46 -0
  22. data/lib/rex/encoder/alpha2.rb +31 -0
  23. data/lib/rex/encoder/alpha2/alpha_mixed.rb +68 -0
  24. data/lib/rex/encoder/alpha2/alpha_upper.rb +79 -0
  25. data/lib/rex/encoder/alpha2/generic.rb +113 -0
  26. data/lib/rex/encoder/alpha2/unicode_mixed.rb +117 -0
  27. data/lib/rex/encoder/alpha2/unicode_upper.rb +129 -0
  28. data/lib/rex/encoder/ndr.rb +89 -0
  29. data/lib/rex/encoder/ndr.rb.ut.rb +44 -0
  30. data/lib/rex/encoder/nonalpha.rb +61 -0
  31. data/lib/rex/encoder/nonupper.rb +64 -0
  32. data/lib/rex/encoder/xdr.rb +106 -0
  33. data/lib/rex/encoder/xdr.rb.ut.rb +29 -0
  34. data/lib/rex/encoder/xor.rb +69 -0
  35. data/lib/rex/encoder/xor/dword.rb +13 -0
  36. data/lib/rex/encoder/xor/dword_additive.rb +13 -0
  37. data/lib/rex/encoders/xor_dword.rb +35 -0
  38. data/lib/rex/encoders/xor_dword_additive.rb +53 -0
  39. data/lib/rex/encoders/xor_dword_additive.rb.ut.rb +12 -0
  40. data/lib/rex/encoding/xor.rb +20 -0
  41. data/lib/rex/encoding/xor.rb.ts.rb +14 -0
  42. data/lib/rex/encoding/xor/byte.rb +15 -0
  43. data/lib/rex/encoding/xor/byte.rb.ut.rb +21 -0
  44. data/lib/rex/encoding/xor/dword.rb +21 -0
  45. data/lib/rex/encoding/xor/dword.rb.ut.rb +15 -0
  46. data/lib/rex/encoding/xor/dword_additive.rb +92 -0
  47. data/lib/rex/encoding/xor/dword_additive.rb.ut.rb +15 -0
  48. data/lib/rex/encoding/xor/exceptions.rb +17 -0
  49. data/lib/rex/encoding/xor/generic.rb +146 -0
  50. data/lib/rex/encoding/xor/generic.rb.ut.rb +120 -0
  51. data/lib/rex/encoding/xor/qword.rb +15 -0
  52. data/lib/rex/encoding/xor/word.rb +21 -0
  53. data/lib/rex/encoding/xor/word.rb.ut.rb +13 -0
  54. data/lib/rex/exceptions.rb +275 -0
  55. data/lib/rex/exceptions.rb.ut.rb +44 -0
  56. data/lib/rex/exploitation/cmdstager.rb +133 -0
  57. data/lib/rex/exploitation/egghunter.rb +143 -0
  58. data/lib/rex/exploitation/egghunter.rb.ut.rb +25 -0
  59. data/lib/rex/exploitation/encryptjs.rb +77 -0
  60. data/lib/rex/exploitation/heaplib.js.b64 +331 -0
  61. data/lib/rex/exploitation/heaplib.rb +94 -0
  62. data/lib/rex/exploitation/javascriptosdetect.rb +735 -0
  63. data/lib/rex/exploitation/obfuscatejs.rb +335 -0
  64. data/lib/rex/exploitation/opcodedb.rb +818 -0
  65. data/lib/rex/exploitation/opcodedb.rb.ut.rb +279 -0
  66. data/lib/rex/exploitation/seh.rb +92 -0
  67. data/lib/rex/exploitation/seh.rb.ut.rb +19 -0
  68. data/lib/rex/file.rb +84 -0
  69. data/lib/rex/file.rb.ut.rb +16 -0
  70. data/lib/rex/image_source.rb +12 -0
  71. data/lib/rex/image_source/disk.rb +60 -0
  72. data/lib/rex/image_source/image_source.rb +46 -0
  73. data/lib/rex/image_source/memory.rb +37 -0
  74. data/lib/rex/io/bidirectional_pipe.rb +157 -0
  75. data/lib/rex/io/datagram_abstraction.rb +35 -0
  76. data/lib/rex/io/stream.rb +313 -0
  77. data/lib/rex/io/stream_abstraction.rb +186 -0
  78. data/lib/rex/io/stream_server.rb +211 -0
  79. data/lib/rex/job_container.rb +202 -0
  80. data/lib/rex/logging.rb +4 -0
  81. data/lib/rex/logging/log_dispatcher.rb +179 -0
  82. data/lib/rex/logging/log_sink.rb +42 -0
  83. data/lib/rex/logging/sinks/flatfile.rb +55 -0
  84. data/lib/rex/logging/sinks/stderr.rb +43 -0
  85. data/lib/rex/machparsey.rb +9 -0
  86. data/lib/rex/machparsey/exceptions.rb +34 -0
  87. data/lib/rex/machparsey/mach.rb +209 -0
  88. data/lib/rex/machparsey/machbase.rb +408 -0
  89. data/lib/rex/machscan.rb +9 -0
  90. data/lib/rex/machscan/scanner.rb +217 -0
  91. data/lib/rex/mime.rb +9 -0
  92. data/lib/rex/mime/header.rb +75 -0
  93. data/lib/rex/mime/message.rb +112 -0
  94. data/lib/rex/mime/part.rb +20 -0
  95. data/lib/rex/nop/opty2.rb +108 -0
  96. data/lib/rex/nop/opty2.rb.ut.rb +23 -0
  97. data/lib/rex/nop/opty2_tables.rb +300 -0
  98. data/lib/rex/ole.rb +128 -0
  99. data/lib/rex/ole/clsid.rb +47 -0
  100. data/lib/rex/ole/difat.rb +141 -0
  101. data/lib/rex/ole/directory.rb +230 -0
  102. data/lib/rex/ole/direntry.rb +240 -0
  103. data/lib/rex/ole/fat.rb +99 -0
  104. data/lib/rex/ole/header.rb +204 -0
  105. data/lib/rex/ole/minifat.rb +77 -0
  106. data/lib/rex/ole/samples/create_ole.rb +27 -0
  107. data/lib/rex/ole/samples/dir.rb +35 -0
  108. data/lib/rex/ole/samples/dump_stream.rb +34 -0
  109. data/lib/rex/ole/samples/ole_info.rb +23 -0
  110. data/lib/rex/ole/storage.rb +395 -0
  111. data/lib/rex/ole/stream.rb +53 -0
  112. data/lib/rex/ole/substorage.rb +49 -0
  113. data/lib/rex/ole/util.rb +157 -0
  114. data/lib/rex/parser/arguments.rb +97 -0
  115. data/lib/rex/parser/arguments.rb.ut.rb +67 -0
  116. data/lib/rex/parser/ini.rb +185 -0
  117. data/lib/rex/parser/ini.rb.ut.rb +29 -0
  118. data/lib/rex/parser/nmap_xml.rb +111 -0
  119. data/lib/rex/payloads.rb +1 -0
  120. data/lib/rex/payloads/win32.rb +2 -0
  121. data/lib/rex/payloads/win32/common.rb +26 -0
  122. data/lib/rex/payloads/win32/kernel.rb +53 -0
  123. data/lib/rex/payloads/win32/kernel/common.rb +54 -0
  124. data/lib/rex/payloads/win32/kernel/migration.rb +12 -0
  125. data/lib/rex/payloads/win32/kernel/recovery.rb +50 -0
  126. data/lib/rex/payloads/win32/kernel/stager.rb +171 -0
  127. data/lib/rex/peparsey.rb +12 -0
  128. data/lib/rex/peparsey/exceptions.rb +32 -0
  129. data/lib/rex/peparsey/pe.rb +188 -0
  130. data/lib/rex/peparsey/pe_memdump.rb +63 -0
  131. data/lib/rex/peparsey/pebase.rb +1655 -0
  132. data/lib/rex/peparsey/section.rb +136 -0
  133. data/lib/rex/pescan.rb +13 -0
  134. data/lib/rex/pescan/analyze.rb +309 -0
  135. data/lib/rex/pescan/scanner.rb +206 -0
  136. data/lib/rex/pescan/search.rb +56 -0
  137. data/lib/rex/platforms.rb +1 -0
  138. data/lib/rex/platforms/windows.rb +51 -0
  139. data/lib/rex/poly.rb +132 -0
  140. data/lib/rex/poly/block.rb +468 -0
  141. data/lib/rex/poly/register.rb +100 -0
  142. data/lib/rex/poly/register/x86.rb +40 -0
  143. data/lib/rex/post.rb +8 -0
  144. data/lib/rex/post/dir.rb +51 -0
  145. data/lib/rex/post/file.rb +172 -0
  146. data/lib/rex/post/file_stat.rb +220 -0
  147. data/lib/rex/post/gen.pl +13 -0
  148. data/lib/rex/post/io.rb +182 -0
  149. data/lib/rex/post/meterpreter.rb +4 -0
  150. data/lib/rex/post/meterpreter/channel.rb +438 -0
  151. data/lib/rex/post/meterpreter/channel_container.rb +54 -0
  152. data/lib/rex/post/meterpreter/channels/pool.rb +160 -0
  153. data/lib/rex/post/meterpreter/channels/pools/file.rb +62 -0
  154. data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +103 -0
  155. data/lib/rex/post/meterpreter/channels/stream.rb +87 -0
  156. data/lib/rex/post/meterpreter/client.rb +335 -0
  157. data/lib/rex/post/meterpreter/client_core.rb +274 -0
  158. data/lib/rex/post/meterpreter/dependencies.rb +3 -0
  159. data/lib/rex/post/meterpreter/extension.rb +32 -0
  160. data/lib/rex/post/meterpreter/extensions/espia/espia.rb +58 -0
  161. data/lib/rex/post/meterpreter/extensions/espia/tlv.rb +16 -0
  162. data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +94 -0
  163. data/lib/rex/post/meterpreter/extensions/incognito/tlv.rb +21 -0
  164. data/lib/rex/post/meterpreter/extensions/priv/fs.rb +118 -0
  165. data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +61 -0
  166. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +104 -0
  167. data/lib/rex/post/meterpreter/extensions/priv/tlv.rb +28 -0
  168. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +100 -0
  169. data/lib/rex/post/meterpreter/extensions/sniffer/tlv.rb +24 -0
  170. data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +333 -0
  171. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +273 -0
  172. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +235 -0
  173. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +103 -0
  174. data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +48 -0
  175. data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +144 -0
  176. data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +73 -0
  177. data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +56 -0
  178. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +137 -0
  179. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +167 -0
  180. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +167 -0
  181. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +192 -0
  182. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +139 -0
  183. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +97 -0
  184. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +184 -0
  185. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +41 -0
  186. data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +61 -0
  187. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +361 -0
  188. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +129 -0
  189. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +55 -0
  190. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +336 -0
  191. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +141 -0
  192. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +279 -0
  193. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +182 -0
  194. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +102 -0
  195. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +174 -0
  196. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +185 -0
  197. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +227 -0
  198. data/lib/rex/post/meterpreter/inbound_packet_handler.rb +30 -0
  199. data/lib/rex/post/meterpreter/object_aliases.rb +83 -0
  200. data/lib/rex/post/meterpreter/packet.rb +596 -0
  201. data/lib/rex/post/meterpreter/packet_dispatcher.rb +409 -0
  202. data/lib/rex/post/meterpreter/packet_parser.rb +94 -0
  203. data/lib/rex/post/meterpreter/packet_response_waiter.rb +83 -0
  204. data/lib/rex/post/meterpreter/ui/console.rb +135 -0
  205. data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +62 -0
  206. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +595 -0
  207. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +108 -0
  208. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +241 -0
  209. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +61 -0
  210. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +98 -0
  211. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +51 -0
  212. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +132 -0
  213. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +187 -0
  214. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +63 -0
  215. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +376 -0
  216. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +270 -0
  217. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +484 -0
  218. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +315 -0
  219. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +95 -0
  220. data/lib/rex/post/permission.rb +26 -0
  221. data/lib/rex/post/process.rb +57 -0
  222. data/lib/rex/post/thread.rb +57 -0
  223. data/lib/rex/post/ui.rb +52 -0
  224. data/lib/rex/proto.rb +12 -0
  225. data/lib/rex/proto.rb.ts.rb +8 -0
  226. data/lib/rex/proto/dcerpc.rb +6 -0
  227. data/lib/rex/proto/dcerpc.rb.ts.rb +9 -0
  228. data/lib/rex/proto/dcerpc/client.rb +358 -0
  229. data/lib/rex/proto/dcerpc/client.rb.ut.rb +491 -0
  230. data/lib/rex/proto/dcerpc/exceptions.rb +150 -0
  231. data/lib/rex/proto/dcerpc/handle.rb +47 -0
  232. data/lib/rex/proto/dcerpc/handle.rb.ut.rb +85 -0
  233. data/lib/rex/proto/dcerpc/ndr.rb +72 -0
  234. data/lib/rex/proto/dcerpc/ndr.rb.ut.rb +41 -0
  235. data/lib/rex/proto/dcerpc/packet.rb +253 -0
  236. data/lib/rex/proto/dcerpc/packet.rb.ut.rb +56 -0
  237. data/lib/rex/proto/dcerpc/response.rb +186 -0
  238. data/lib/rex/proto/dcerpc/response.rb.ut.rb +15 -0
  239. data/lib/rex/proto/dcerpc/uuid.rb +84 -0
  240. data/lib/rex/proto/dcerpc/uuid.rb.ut.rb +46 -0
  241. data/lib/rex/proto/drda.rb +5 -0
  242. data/lib/rex/proto/drda.rb.ts.rb +17 -0
  243. data/lib/rex/proto/drda/constants.rb +49 -0
  244. data/lib/rex/proto/drda/constants.rb.ut.rb +23 -0
  245. data/lib/rex/proto/drda/packet.rb +252 -0
  246. data/lib/rex/proto/drda/packet.rb.ut.rb +109 -0
  247. data/lib/rex/proto/drda/utils.rb +123 -0
  248. data/lib/rex/proto/drda/utils.rb.ut.rb +84 -0
  249. data/lib/rex/proto/http.rb +5 -0
  250. data/lib/rex/proto/http.rb.ts.rb +12 -0
  251. data/lib/rex/proto/http/client.rb +817 -0
  252. data/lib/rex/proto/http/client.rb.ut.rb +93 -0
  253. data/lib/rex/proto/http/handler.rb +46 -0
  254. data/lib/rex/proto/http/handler/erb.rb +128 -0
  255. data/lib/rex/proto/http/handler/erb.rb.ut.rb +21 -0
  256. data/lib/rex/proto/http/handler/erb.rb.ut.rb.rhtml +1 -0
  257. data/lib/rex/proto/http/handler/proc.rb +54 -0
  258. data/lib/rex/proto/http/handler/proc.rb.ut.rb +24 -0
  259. data/lib/rex/proto/http/header.rb +161 -0
  260. data/lib/rex/proto/http/header.rb.ut.rb +46 -0
  261. data/lib/rex/proto/http/packet.rb +394 -0
  262. data/lib/rex/proto/http/packet.rb.ut.rb +165 -0
  263. data/lib/rex/proto/http/request.rb +356 -0
  264. data/lib/rex/proto/http/request.rb.ut.rb +214 -0
  265. data/lib/rex/proto/http/response.rb +85 -0
  266. data/lib/rex/proto/http/response.rb.ut.rb +149 -0
  267. data/lib/rex/proto/http/server.rb +367 -0
  268. data/lib/rex/proto/http/server.rb.ut.rb +79 -0
  269. data/lib/rex/proto/smb.rb +7 -0
  270. data/lib/rex/proto/smb.rb.ts.rb +8 -0
  271. data/lib/rex/proto/smb/client.rb +1733 -0
  272. data/lib/rex/proto/smb/client.rb.ut.rb +223 -0
  273. data/lib/rex/proto/smb/constants.rb +1062 -0
  274. data/lib/rex/proto/smb/constants.rb.ut.rb +18 -0
  275. data/lib/rex/proto/smb/crypt.rb +95 -0
  276. data/lib/rex/proto/smb/crypt.rb.ut.rb +20 -0
  277. data/lib/rex/proto/smb/evasions.rb +65 -0
  278. data/lib/rex/proto/smb/exceptions.rb +846 -0
  279. data/lib/rex/proto/smb/simpleclient.rb +292 -0
  280. data/lib/rex/proto/smb/simpleclient.rb.ut.rb +128 -0
  281. data/lib/rex/proto/smb/utils.rb +514 -0
  282. data/lib/rex/proto/smb/utils.rb.ut.rb +20 -0
  283. data/lib/rex/proto/sunrpc.rb +1 -0
  284. data/lib/rex/proto/sunrpc/client.rb +195 -0
  285. data/lib/rex/script.rb +42 -0
  286. data/lib/rex/script/base.rb +59 -0
  287. data/lib/rex/script/meterpreter.rb +9 -0
  288. data/lib/rex/script/shell.rb +9 -0
  289. data/lib/rex/service.rb +48 -0
  290. data/lib/rex/service_manager.rb +141 -0
  291. data/lib/rex/service_manager.rb.ut.rb +32 -0
  292. data/lib/rex/services/local_relay.rb +423 -0
  293. data/lib/rex/socket.rb +586 -0
  294. data/lib/rex/socket.rb.ut.rb +86 -0
  295. data/lib/rex/socket/comm.rb +119 -0
  296. data/lib/rex/socket/comm/local.rb +409 -0
  297. data/lib/rex/socket/comm/local.rb.ut.rb +75 -0
  298. data/lib/rex/socket/ip.rb +129 -0
  299. data/lib/rex/socket/parameters.rb +345 -0
  300. data/lib/rex/socket/parameters.rb.ut.rb +51 -0
  301. data/lib/rex/socket/range_walker.rb +295 -0
  302. data/lib/rex/socket/range_walker.rb.ut.rb +55 -0
  303. data/lib/rex/socket/ssl_tcp.rb +184 -0
  304. data/lib/rex/socket/ssl_tcp.rb.ut.rb +39 -0
  305. data/lib/rex/socket/ssl_tcp_server.rb +122 -0
  306. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +51 -0
  307. data/lib/rex/socket/subnet_walker.rb +75 -0
  308. data/lib/rex/socket/subnet_walker.rb.ut.rb +28 -0
  309. data/lib/rex/socket/switch_board.rb +272 -0
  310. data/lib/rex/socket/switch_board.rb.ut.rb +52 -0
  311. data/lib/rex/socket/tcp.rb +76 -0
  312. data/lib/rex/socket/tcp.rb.ut.rb +64 -0
  313. data/lib/rex/socket/tcp_server.rb +67 -0
  314. data/lib/rex/socket/tcp_server.rb.ut.rb +44 -0
  315. data/lib/rex/socket/udp.rb +157 -0
  316. data/lib/rex/socket/udp.rb.ut.rb +44 -0
  317. data/lib/rex/struct2.rb +5 -0
  318. data/lib/rex/struct2/c_struct.rb +181 -0
  319. data/lib/rex/struct2/c_struct_template.rb +39 -0
  320. data/lib/rex/struct2/constant.rb +26 -0
  321. data/lib/rex/struct2/element.rb +44 -0
  322. data/lib/rex/struct2/generic.rb +73 -0
  323. data/lib/rex/struct2/restraint.rb +54 -0
  324. data/lib/rex/struct2/s_string.rb +72 -0
  325. data/lib/rex/struct2/s_struct.rb +111 -0
  326. data/lib/rex/sync.rb +6 -0
  327. data/lib/rex/sync/event.rb +94 -0
  328. data/lib/rex/sync/read_write_lock.rb +176 -0
  329. data/lib/rex/sync/ref.rb +57 -0
  330. data/lib/rex/sync/thread_safe.rb +82 -0
  331. data/lib/rex/test.rb +35 -0
  332. data/lib/rex/text.rb +1029 -0
  333. data/lib/rex/text.rb.ut.rb +168 -0
  334. data/lib/rex/time.rb +65 -0
  335. data/lib/rex/transformer.rb +115 -0
  336. data/lib/rex/transformer.rb.ut.rb +38 -0
  337. data/lib/rex/ui.rb +21 -0
  338. data/lib/rex/ui/interactive.rb +252 -0
  339. data/lib/rex/ui/output.rb +80 -0
  340. data/lib/rex/ui/output/none.rb +18 -0
  341. data/lib/rex/ui/progress_tracker.rb +96 -0
  342. data/lib/rex/ui/subscriber.rb +149 -0
  343. data/lib/rex/ui/text/color.rb +97 -0
  344. data/lib/rex/ui/text/color.rb.ut.rb +18 -0
  345. data/lib/rex/ui/text/dispatcher_shell.rb +382 -0
  346. data/lib/rex/ui/text/input.rb +117 -0
  347. data/lib/rex/ui/text/input/buffer.rb +75 -0
  348. data/lib/rex/ui/text/input/readline.rb +129 -0
  349. data/lib/rex/ui/text/input/socket.rb +95 -0
  350. data/lib/rex/ui/text/input/stdio.rb +45 -0
  351. data/lib/rex/ui/text/irb_shell.rb +55 -0
  352. data/lib/rex/ui/text/output.rb +80 -0
  353. data/lib/rex/ui/text/output/buffer.rb +65 -0
  354. data/lib/rex/ui/text/output/file.rb +37 -0
  355. data/lib/rex/ui/text/output/socket.rb +43 -0
  356. data/lib/rex/ui/text/output/stdio.rb +40 -0
  357. data/lib/rex/ui/text/progress_tracker.rb +56 -0
  358. data/lib/rex/ui/text/progress_tracker.rb.ut.rb +34 -0
  359. data/lib/rex/ui/text/shell.rb +321 -0
  360. data/lib/rex/ui/text/table.rb +254 -0
  361. data/lib/rex/ui/text/table.rb.ut.rb +55 -0
  362. data/lib/rex/zip.rb +93 -0
  363. data/lib/rex/zip/archive.rb +91 -0
  364. data/lib/rex/zip/blocks.rb +182 -0
  365. data/lib/rex/zip/entry.rb +95 -0
  366. data/lib/rex/zip/samples/comment.rb +32 -0
  367. data/lib/rex/zip/samples/mkwar.rb +138 -0
  368. data/lib/rex/zip/samples/mkzip.rb +19 -0
  369. data/lib/rex/zip/samples/recursive.rb +58 -0
  370. metadata +435 -0
@@ -0,0 +1,292 @@
1
+ module Rex
2
+ module Proto
3
+ module SMB
4
+ class SimpleClient
5
+
6
+ require 'rex/text'
7
+ require 'rex/struct2'
8
+ require 'rex/proto/smb/constants'
9
+ require 'rex/proto/smb/exceptions'
10
+ require 'rex/proto/smb/evasions'
11
+ require 'rex/proto/smb/crypt'
12
+ require 'rex/proto/smb/utils'
13
+ require 'rex/proto/smb/client'
14
+
15
+ # Some short-hand class aliases
16
+ CONST = Rex::Proto::SMB::Constants
17
+ CRYPT = Rex::Proto::SMB::Crypt
18
+ UTILS = Rex::Proto::SMB::Utils
19
+ XCEPT = Rex::Proto::SMB::Exceptions
20
+ EVADE = Rex::Proto::SMB::Evasions
21
+
22
+
23
+ class OpenFile
24
+ attr_accessor :name, :tree_id, :file_id, :mode, :client, :chunk_size
25
+
26
+ def initialize(client, name, tree_id, file_id)
27
+ self.client = client
28
+ self.name = name
29
+ self.tree_id = tree_id
30
+ self.file_id = file_id
31
+ self.chunk_size = 48000
32
+ end
33
+
34
+ def delete
35
+ begin
36
+ self.close
37
+ rescue
38
+ end
39
+ self.client.delete(self.name, self.tree_id)
40
+ end
41
+
42
+ # Close this open file
43
+ def close
44
+ self.client.close(self.file_id, self.tree_id)
45
+ end
46
+
47
+ # Read data from the file
48
+ def read(length = nil, offset = 0)
49
+ if (length == nil)
50
+ data = ''
51
+ fptr = offset
52
+ ok = self.client.read(self.file_id, fptr, self.chunk_size)
53
+ while (ok and ok['Payload'].v['DataLenLow'] > 0)
54
+ buff = ok.to_s.slice(
55
+ ok['Payload'].v['DataOffset'] + 4,
56
+ ok['Payload'].v['DataLenLow']
57
+ )
58
+ data << buff
59
+ if ok['Payload'].v['Remaining'] == 0
60
+ break
61
+ end
62
+ fptr += ok['Payload'].v['DataLenLow']
63
+
64
+ begin
65
+ ok = self.client.read(self.file_id, fptr, self.chunk_size)
66
+ rescue XCEPT::ErrorCode => e
67
+ case e.error_code
68
+ when 0x00050001
69
+ # Novell fires off an access denied error on EOF
70
+ ok = nil
71
+ else
72
+ raise e
73
+ end
74
+ end
75
+ end
76
+
77
+ return data
78
+ else
79
+ ok = self.client.read(self.file_id, offset, length)
80
+ data = ok.to_s.slice(
81
+ ok['Payload'].v['DataOffset'] + 4,
82
+ ok['Payload'].v['DataLenLow']
83
+ )
84
+ return data
85
+ end
86
+ end
87
+
88
+ def << (data)
89
+ self.write(data)
90
+ end
91
+
92
+ # Write data to the file
93
+ def write(data, offset = 0)
94
+ # Track our offset into the remote file
95
+ fptr = offset
96
+
97
+ # Duplicate the data so we can use slice!
98
+ data = data.dup
99
+
100
+ # Take our first chunk of bytes
101
+ chunk = data.slice!(0, self.chunk_size)
102
+
103
+ # Keep writing data until we run out
104
+ while (chunk.length > 0)
105
+ ok = self.client.write(self.file_id, fptr, chunk)
106
+ cl = ok['Payload'].v['CountLow']
107
+
108
+ # Partial write, push the failed data back into the queue
109
+ if (cl != chunk.length)
110
+ data = chunk.slice(cl - 1, chunk.length - cl) + data
111
+ end
112
+
113
+ # Increment our painter and grab the next chunk
114
+ fptr += cl
115
+ chunk = data.slice!(0, self.chunk_size)
116
+ end
117
+ end
118
+ end
119
+
120
+ class OpenPipe < OpenFile
121
+
122
+ # Valid modes are: 'trans' and 'rw'
123
+ attr_accessor :mode
124
+
125
+ def initialize(*args)
126
+ super(*args)
127
+ self.mode = 'rw'
128
+ @buff = ''
129
+ end
130
+
131
+ def read_buffer(length, offset=0)
132
+ length ||= @buff.length
133
+ @buff.slice!(0, length)
134
+ end
135
+
136
+ def read(length = nil, offset = 0)
137
+ case self.mode
138
+ when 'trans'
139
+ read_buffer(length, offset)
140
+ when 'rw'
141
+ super(length, offset)
142
+ else
143
+ raise ArgumentError
144
+ end
145
+ end
146
+
147
+ def write(data, offset = 0)
148
+ case self.mode
149
+
150
+ when 'trans'
151
+ write_trans(data, offset)
152
+ when 'rw'
153
+ super(data, offset)
154
+ else
155
+ raise ArgumentError
156
+ end
157
+ end
158
+
159
+ def write_trans(data, offset=0)
160
+ ack = self.client.trans_named_pipe(self.file_id, data)
161
+ doff = ack['Payload'].v['DataOffset']
162
+ dlen = ack['Payload'].v['DataCount']
163
+ @buff << ack.to_s[4+doff, dlen]
164
+ end
165
+ end
166
+
167
+
168
+ # Public accessors
169
+ attr_accessor :last_error
170
+
171
+ # Private accessors
172
+ attr_accessor :socket, :client, :direct, :shares, :last_share
173
+
174
+ # Pass the socket object and a boolean indicating whether the socket is netbios or cifs
175
+ def initialize(socket, direct = false)
176
+ self.socket = socket
177
+ self.direct = direct
178
+ self.client = Rex::Proto::SMB::Client.new(socket)
179
+ self.shares = { }
180
+ end
181
+
182
+ def login(name = '', user = '', pass = '', domain = '')
183
+
184
+ begin
185
+
186
+ if (self.direct != true)
187
+ self.client.session_request(name)
188
+ end
189
+
190
+ self.client.negotiate
191
+ ok = self.client.session_setup(user, pass, domain)
192
+ rescue ::Interrupt
193
+ raise $!
194
+ rescue ::Exception => e
195
+ n = XCEPT::LoginError.new
196
+ n.source = e
197
+ if(e.respond_to?('error_code'))
198
+ n.error_code = e.error_code
199
+ n.error_reason = e.get_error(e.error_code)
200
+ end
201
+ raise n
202
+ end
203
+
204
+ return true
205
+ end
206
+
207
+
208
+ def login_split_start_ntlm1(name = '')
209
+
210
+ begin
211
+
212
+ if (self.direct != true)
213
+ self.client.session_request(name)
214
+ end
215
+
216
+ # Disable extended security
217
+ self.client.negotiate(false)
218
+ rescue ::Interrupt
219
+ raise $!
220
+ rescue ::Exception => e
221
+ n = XCEPT::LoginError.new
222
+ n.source = e
223
+ if(e.respond_to?('error_code'))
224
+ n.error_code = e.error_code
225
+ n.error_reason = e.get_error(e.error_code)
226
+ end
227
+ raise n
228
+ end
229
+
230
+ return true
231
+ end
232
+
233
+
234
+ def login_split_next_ntlm1(user, domain, hash_lm, hash_nt)
235
+ begin
236
+ ok = self.client.session_setup_ntlmv1_prehash(user, domain, hash_lm, hash_nt)
237
+ rescue ::Interrupt
238
+ raise $!
239
+ rescue ::Exception => e
240
+ n = XCEPT::LoginError.new
241
+ n.source = e
242
+ if(e.respond_to?('error_code'))
243
+ n.error_code = e.error_code
244
+ n.error_reason = e.get_error(e.error_code)
245
+ end
246
+ raise n
247
+ end
248
+
249
+ return true
250
+ end
251
+
252
+ def connect(share)
253
+ ok = self.client.tree_connect(share)
254
+ tree_id = ok['Payload']['SMB'].v['TreeID']
255
+ self.shares[share] = tree_id
256
+ self.last_share = share
257
+ end
258
+
259
+ def disconnect(share)
260
+ ok = self.client.tree_disconnect(self.shares[share])
261
+ self.shares.delete(share)
262
+ end
263
+
264
+ def open(path, perm)
265
+ mode = UTILS.open_mode_to_mode(perm)
266
+ access = UTILS.open_mode_to_access(perm)
267
+
268
+ ok = self.client.open(path, mode, access)
269
+ file_id = ok['Payload'].v['FileID']
270
+
271
+ fh = OpenFile.new(self.client, path, self.client.last_tree_id, file_id)
272
+ end
273
+
274
+ def delete(*args)
275
+ self.client.delete(*args)
276
+ end
277
+
278
+ def create_pipe(path, perm = 'c')
279
+ disposition = UTILS.create_mode_to_disposition(perm)
280
+ ok = self.client.create_pipe(path, disposition)
281
+ file_id = ok['Payload'].v['FileID']
282
+ fh = OpenPipe.new(self.client, path, self.client.last_tree_id, file_id)
283
+ end
284
+
285
+ def trans_pipe(fid, data, no_response = nil)
286
+ client.trans_named_pipe(fid, data, no_response)
287
+ end
288
+
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..'))
4
+
5
+ require 'rex/test'
6
+ require 'rex/proto/smb'
7
+ require 'rex/proto/dcerpc'
8
+ require 'rex/socket'
9
+
10
+ class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
11
+
12
+ Klass = Rex::Proto::SMB::SimpleClient
13
+
14
+ # Alias over the Rex DCERPC protocol modules
15
+ DCERPCPacket = Rex::Proto::DCERPC::Packet
16
+ DCERPCClient = Rex::Proto::DCERPC::Client
17
+ DCERPCResponse = Rex::Proto::DCERPC::Response
18
+ DCERPCUUID = Rex::Proto::DCERPC::UUID
19
+ XCEPT = Rex::Proto::SMB::Exceptions
20
+
21
+ FILE_CREATE = 0x10
22
+ FILE_TRUNC = 0x02
23
+ FILE_OPEN = 0x01
24
+
25
+
26
+ def test_smb_open_share
27
+ user = 'SMBTest'
28
+ pass = 'SMBTest'
29
+ share = 'C$'
30
+
31
+ write_data = ('A' * (1024 * 8))
32
+ filename = 'smb_tester.txt'
33
+ begin
34
+ Timeout.timeout($_REX_TEST_TIMEOUT) {
35
+ s = Rex::Socket.create_tcp(
36
+ 'PeerHost' => $_REX_TEST_SMB_HOST,
37
+ 'PeerPort' => 445
38
+ )
39
+
40
+ c = Klass.new(s, true)
41
+
42
+ begin
43
+ c.login('*SMBSERVER', user, pass)
44
+ rescue XCEPT::LoginError
45
+ flunk('login failure')
46
+ end
47
+
48
+ c.connect(share)
49
+
50
+ f = c.open(filename, 'rwct')
51
+ f << write_data
52
+ f.close
53
+
54
+ f = c.open(filename, 'ro')
55
+ d = f.read()
56
+ f.close
57
+
58
+ c.delete(filename)
59
+ c.disconnect(share)
60
+
61
+ s.close
62
+ }
63
+ rescue Timeout::Error
64
+ flunk('timeout')
65
+ end
66
+ end
67
+
68
+ def test_smb_dcerpc
69
+ begin
70
+ Timeout.timeout($_REX_TEST_TIMEOUT) {
71
+ s = Rex::Socket.create_tcp(
72
+ 'PeerHost' => $_REX_TEST_SMB_HOST,
73
+ 'PeerPort' => 445
74
+ )
75
+
76
+ c = Klass.new(s, true)
77
+
78
+ user = ''
79
+ pass = ''
80
+
81
+ begin
82
+ c.login('*SMBSERVER', user, pass)
83
+ rescue XCEPT::LoginError
84
+ flunk('login failure')
85
+ end
86
+
87
+ c.connect('IPC$')
88
+ f = c.create_pipe('\BROWSER')
89
+
90
+ bind, ctx = DCERPCPacket.make_bind_fake_multi(
91
+ '4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0',
92
+ 10,
93
+ 4
94
+ )
95
+
96
+ # Evasion techniques:
97
+ # 1) Write the bind out a few bytes at a time with a random offset
98
+ # 2) Read the response back a few bytes at a time with a random offset
99
+
100
+ # Write the bind request out in random chunk sizes
101
+ while (bind.length > 0)
102
+ f.write( bind.slice!(0, (rand(20)+5)), rand(1024)+1 )
103
+ end
104
+
105
+ d = ''
106
+ # Read the response back a few bytes a time
107
+ begin
108
+ while(true)
109
+ t = (f.read((rand(20)+5), rand(1024)+1))
110
+ last if ! t.length
111
+ d << t
112
+ end
113
+ rescue XCEPT::NoReply
114
+ end
115
+
116
+ r = DCERPCResponse.new(d)
117
+ assert_equal(r.type, 12)
118
+ assert_equal(r.ack_result[ctx-0], 0)
119
+ assert_equal(r.ack_result[ctx-1], 2)
120
+
121
+ s.close
122
+ }
123
+ rescue Timeout::Error
124
+ flunk('timeout')
125
+ end
126
+ end
127
+ end
128
+
@@ -0,0 +1,514 @@
1
+ require 'rex/text'
2
+ require 'rex/proto/smb/constants'
3
+
4
+ module Rex
5
+ module Proto
6
+ module SMB
7
+ class Utils
8
+
9
+ CONST = Rex::Proto::SMB::Constants
10
+
11
+ # Creates an access mask for use with the CLIENT.open() call based on a string
12
+ def self.open_mode_to_access(str)
13
+ access = CONST::OPEN_ACCESS_READ | CONST::OPEN_SHARE_DENY_NONE
14
+ str.each_byte { |c|
15
+ case [c].pack('C').downcase
16
+ when 'w'
17
+ access |= CONST::OPEN_ACCESS_READWRITE
18
+ end
19
+ }
20
+ return access
21
+ end
22
+
23
+ # Creates a mode mask for use with the CLIENT.open() call based on a string
24
+ def self.open_mode_to_mode(str)
25
+ mode = 0
26
+
27
+ str.each_byte { |c|
28
+ case [c].pack('C').downcase
29
+ when 'x' # Fail if the file already exists
30
+ mode |= CONST::OPEN_MODE_EXCL
31
+ when 't' # Truncate the file if it already exists
32
+ mode |= CONST::OPEN_MODE_TRUNC
33
+ when 'c' # Create the file if it does not exist
34
+ mode |= CONST::OPEN_MODE_CREAT
35
+ when 'o' # Just open the file, clashes with x
36
+ mode |= CONST::OPEN_MODE_OPEN
37
+ end
38
+ }
39
+
40
+ return mode
41
+ end
42
+
43
+ # Returns a disposition value for smb.create based on permission string
44
+ def self.create_mode_to_disposition(str)
45
+ str.each_byte { |c|
46
+ case [c].pack('C').downcase
47
+ when 'c' # Create the file if it does not exist
48
+ return CONST::CREATE_ACCESS_OPENCREATE
49
+ when 'o' # Just open the file and fail if it does not exist
50
+ return CONST::CREATE_ACCESS_EXIST
51
+ end
52
+ }
53
+
54
+ return CONST::CREATE_ACCESS_OPENCREATE
55
+ end
56
+
57
+ # Convert a 64-bit signed SMB time to a unix timestamp
58
+ def self.time_smb_to_unix(thi, tlo)
59
+ (((thi << 32) + tlo) / 10000000) - 11644473600
60
+ end
61
+
62
+ # Convert a unix timestamp to a 64-bit signed server time
63
+ def self.time_unix_to_smb(unix_time)
64
+ t64 = (unix_time + 11644473600) * 10000000
65
+ thi = (t64 & 0xffffffff00000000) >> 32
66
+ tlo = (t64 & 0x00000000ffffffff)
67
+ return [thi, tlo]
68
+ end
69
+
70
+ # Convert a name to its NetBIOS equivalent
71
+ def self.nbname_encode(str)
72
+ encoded = ''
73
+ for x in (0..15)
74
+ if (x >= str.length)
75
+ encoded << 'CA'
76
+ else
77
+ c = str[x, 1].upcase[0,1].unpack('C*')[0]
78
+ encoded << [ (c / 16) + 0x41, (c % 16) + 0x41 ].pack('CC')
79
+ end
80
+ end
81
+ return encoded
82
+ end
83
+
84
+ # Convert a name from its NetBIOS equivalent
85
+ def self.nbname_decode(str)
86
+ decoded = ''
87
+ str << 'A' if str.length % 2 != 0
88
+ while (str.length > 0)
89
+ two = str.slice!(0, 2).unpack('C*')
90
+ if (two.length == 2)
91
+ decoded << [ ((two[0] - 0x41) * 16) + two[1] - 0x41 ].pack('C')
92
+ end
93
+ end
94
+ return decoded
95
+ end
96
+
97
+ #
98
+ # Prepends an ASN1 formatted length field to a piece of data
99
+ #
100
+ def self.asn1encode(str = '')
101
+ res = ''
102
+
103
+ # If the high bit of the first byte is 1, it contains the number of
104
+ # length bytes that follow
105
+
106
+ case str.length
107
+ when 0 .. 0x7F
108
+ res = [str.length].pack('C') + str
109
+ when 0x80 .. 0xFF
110
+ res = [0x81, str.length].pack('CC') + str
111
+ when 0x100 .. 0xFFFF
112
+ res = [0x82, str.length].pack('Cn') + str
113
+ when 0x10000 .. 0xffffff
114
+ res = [0x83, str.length >> 16, str.length & 0xFFFF].pack('CCn') + str
115
+ when 0x1000000 .. 0xffffffff
116
+ res = [0x84, str.length].pack('CN') + str
117
+ else
118
+ raise "ASN1 str too long"
119
+ end
120
+ return res
121
+ end
122
+
123
+ def self.make_ntlmv2_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
124
+ blob =
125
+ "\x60" + self.asn1encode(
126
+ "\x06" + self.asn1encode(
127
+ "\x2b\x06\x01\x05\x05\x02"
128
+ ) +
129
+ "\xa0" + self.asn1encode(
130
+ "\x30" + self.asn1encode(
131
+ "\xa0" + self.asn1encode(
132
+ "\x30" + self.asn1encode(
133
+ "\x06" + self.asn1encode(
134
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
135
+ )
136
+ )
137
+ ) +
138
+ "\xa2" + self.asn1encode(
139
+ "\x04" + self.asn1encode(
140
+ "NTLMSSP\x00" +
141
+ [1, flags].pack('VV') +
142
+
143
+ [
144
+ domain.length, #length
145
+ domain.length, #max length
146
+ 32
147
+ ].pack('vvV') +
148
+
149
+ [
150
+ name.length, #length
151
+ name.length, #max length
152
+ domain.length + 32
153
+ ].pack('vvV') +
154
+
155
+ domain + name
156
+ )
157
+ )
158
+ )
159
+ )
160
+ )
161
+
162
+ return blob
163
+ end
164
+
165
+ def self.make_ntlmv2_secblob_auth(domain, name, user, lmv2, ntlm, flags = 0x080201)
166
+
167
+ lmv2 ||= "\x00" * 24
168
+ ntlm ||= "\x00" * 24
169
+
170
+ domain_uni = Rex::Text.to_unicode(domain)
171
+ user_uni = Rex::Text.to_unicode(user)
172
+ name_uni = Rex::Text.to_unicode(name)
173
+ session = ''
174
+
175
+ ptr = 64
176
+ blob =
177
+ "\xa1" + self.asn1encode(
178
+ "\x30" + self.asn1encode(
179
+ "\xa2" + self.asn1encode(
180
+ "\x04" + self.asn1encode(
181
+
182
+ "NTLMSSP\x00" +
183
+ [ 3 ].pack('V') +
184
+
185
+ [ # Lan Manager Response
186
+ lmv2.length,
187
+ lmv2.length,
188
+ (ptr)
189
+ ].pack('vvV') +
190
+
191
+ [ # NTLM Manager Response
192
+ ntlm.length,
193
+ ntlm.length,
194
+ (ptr += lmv2.length)
195
+ ].pack('vvV') +
196
+
197
+ [ # Domain Name
198
+ domain_uni.length,
199
+ domain_uni.length,
200
+ (ptr += ntlm.length)
201
+ ].pack('vvV') +
202
+
203
+ [ # Username
204
+ user_uni.length,
205
+ user_uni.length,
206
+ (ptr += domain_uni.length)
207
+ ].pack('vvV') +
208
+
209
+ [ # Hostname
210
+ name_uni.length,
211
+ name_uni.length,
212
+ (ptr += user_uni.length)
213
+ ].pack('vvV') +
214
+
215
+ [ # Session Key (none)
216
+ session.length,
217
+ session.length,
218
+ (ptr += name_uni.length)
219
+ ].pack('vvV') +
220
+
221
+ [ flags ].pack('V') +
222
+
223
+ lmv2 +
224
+ ntlm +
225
+ domain_uni +
226
+ user_uni +
227
+ name_uni +
228
+ session + "\x00"
229
+ )
230
+ )
231
+ )
232
+ )
233
+ return blob
234
+ end
235
+
236
+
237
+ def self.make_negotiate_secblob_resp(account, domain)
238
+ blob =
239
+ "\x60" + self.asn1encode(
240
+ "\x06" + self.asn1encode(
241
+ "\x2b\x06\x01\x05\x05\x02"
242
+ ) +
243
+ "\xa0" + self.asn1encode(
244
+ "\x30" + self.asn1encode(
245
+ "\xa0" + self.asn1encode(
246
+ "\x30" + self.asn1encode(
247
+ "\x06" + self.asn1encode(
248
+ "\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"
249
+ ) +
250
+ "\x06" + self.asn1encode(
251
+ "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
252
+ ) +
253
+ "\x06" + self.asn1encode(
254
+ "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x03"
255
+ ) +
256
+ "\x06" + self.asn1encode(
257
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
258
+ )
259
+ )
260
+ ) +
261
+ "\xa3" + self.asn1encode(
262
+ "\x30" + self.asn1encode(
263
+ "\xa0" + self.asn1encode(
264
+ "\x1b" + self.asn1encode(
265
+ account + '@' + domain
266
+ )
267
+ )
268
+ )
269
+ )
270
+ )
271
+ )
272
+ )
273
+
274
+ return blob
275
+ end
276
+
277
+ def self.make_ntlmv2_secblob_chall(win_domain, dns_domain, win_name, dns_name, chall, flags)
278
+
279
+ win_domain = Rex::Text.to_unicode(win_domain)
280
+ dns_domain = Rex::Text.to_unicode(dns_domain)
281
+ win_name = Rex::Text.to_unicode(win_name)
282
+ dns_name = Rex::Text.to_unicode(dns_name)
283
+
284
+ addr_list = ''
285
+ addr_list << [2, win_domain.length].pack('vv') + win_domain
286
+ addr_list << [1, win_name.length].pack('vv') + win_name
287
+ addr_list << [4, dns_domain.length].pack('vv') + dns_domain
288
+ addr_list << [3, dns_name.length].pack('vv') + dns_name
289
+ addr_list << [5, dns_domain.length].pack('vv') + dns_domain
290
+ addr_list << [0, 0].pack('vv')
291
+
292
+ ptr = 0
293
+ blob =
294
+ "\xa1" + self.asn1encode(
295
+ "\x30" + self.asn1encode(
296
+ "\xa0" + self.asn1encode(
297
+ "\x0a" + self.asn1encode(
298
+ "\x01"
299
+ )
300
+ ) +
301
+ "\xa1" + self.asn1encode(
302
+ "\x06" + self.asn1encode(
303
+ "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
304
+ )
305
+ ) +
306
+ "\xa2" + self.asn1encode(
307
+ "\x04" + self.asn1encode(
308
+ "NTLMSSP\x00" +
309
+ [2].pack('V') +
310
+ [
311
+ win_domain.length, # length
312
+ win_domain.length, # max length
313
+ (ptr += 48)
314
+ ].pack('vvV') +
315
+ [ flags ].pack('V') +
316
+ chall +
317
+ "\x00\x00\x00\x00\x00\x00\x00\x00" +
318
+ [
319
+ addr_list.length, # length
320
+ addr_list.length, # max length
321
+ (ptr += win_domain.length)
322
+ ].pack('vvV') +
323
+ win_domain +
324
+ addr_list
325
+ )
326
+ )
327
+ )
328
+ )
329
+
330
+ return blob
331
+ end
332
+
333
+ def self.make_ntlmv2_secblob_success
334
+ blob =
335
+ "\xa1" + self.asn1encode(
336
+ "\x30" + self.asn1encode(
337
+ "\xa0" + self.asn1encode(
338
+ "\x0a" + self.asn1encode(
339
+ "\x00"
340
+ )
341
+ )
342
+ )
343
+ )
344
+ return blob
345
+ end
346
+
347
+ #
348
+ # Process Type 3 NTLM Message (in Base64)
349
+ #
350
+ def self.process_type3_message(message)
351
+ decode = Rex::Text.decode_base64(message.strip)
352
+ type = decode[8]
353
+ if (type == 3)
354
+ domoff = decode[32] # domain offset
355
+ domlen = decode[28] # domain length
356
+ useroff = decode[40] # username offset
357
+ userlen = decode[36] # username length
358
+ hostoff = decode[48] # hostname offset
359
+ hostlen = decode[44] # hostname length
360
+ lmoff = decode[16] # LM hash offset
361
+ lmlen = decode[12] # LM hash length
362
+ ntoff = decode[24] # NT hash offset
363
+ ntlen = decode[20] # NT hash length
364
+
365
+ domain = decode[domoff..domoff+domlen-1]
366
+ user = decode[useroff..useroff+userlen-1]
367
+ host = decode[hostoff..hostoff+hostlen-1]
368
+ lm = decode[lmoff..lmoff+lmlen-1].unpack("H*")
369
+ nt = decode[ntoff..ntoff+ntlen-1].unpack("H*")
370
+
371
+ return domain, user, host, lm, nt
372
+ else
373
+ return "", "", "", "", ""
374
+ end
375
+ end
376
+
377
+ #
378
+ # Process Type 1 NTLM Messages, return a Base64 Type 2 Message
379
+ #
380
+ def self.process_type1_message(message, nonce = "\x11\x22\x33\x44\x55\x66\x77\x88", win_domain = 'DOMAIN',
381
+ win_name = 'SERVER', dns_name = 'server', dns_domain = 'example.com', downgrade = true)
382
+
383
+ dns_name = Rex::Text.to_unicode(dns_name + "." + dns_domain)
384
+ win_domain = Rex::Text.to_unicode(win_domain)
385
+ dns_domain = Rex::Text.to_unicode(dns_domain)
386
+ win_name = Rex::Text.to_unicode(win_name)
387
+ decode = Rex::Text.decode_base64(message.strip)
388
+
389
+ type = decode[8]
390
+
391
+ if (type == 1)
392
+ # A type 1 message has been received, lets build a type 2 message response
393
+
394
+ reqflags = decode[12..15]
395
+ reqflags = Integer("0x" + reqflags.unpack("h8").to_s.reverse)
396
+
397
+ if (reqflags & CONST::REQUEST_TARGET) == CONST::REQUEST_TARGET
398
+
399
+ if (downgrade)
400
+ # At this time NTLMv2 and signing requirements are not supported
401
+ if (reqflags & CONST::NEGOTIATE_NTLM2_KEY) == CONST::NEGOTIATE_NTLM2_KEY
402
+ reqflags = reqflags - CONST::NEGOTIATE_NTLM2_KEY
403
+ end
404
+ if (reqflags & CONST::NEGOTIATE_ALWAYS_SIGN) == CONST::NEGOTIATE_ALWAYS_SIGN
405
+ reqflags = reqflags - CONST::NEGOTIATE_ALWAYS_SIGN
406
+ end
407
+ end
408
+
409
+ flags = reqflags + CONST::TARGET_TYPE_DOMAIN + CONST::TARGET_TYPE_SERVER
410
+ tid = true
411
+
412
+ tidoffset = 48 + win_domain.length
413
+ tidbuff =
414
+ [2].pack('v') + # tid type, win domain
415
+ [win_domain.length].pack('v') +
416
+ win_domain +
417
+ [1].pack('v') + # tid type, server name
418
+ [win_name.length].pack('v') +
419
+ win_name +
420
+ [4].pack('v') + # tid type, domain name
421
+ [dns_domain.length].pack('v') +
422
+ dns_domain +
423
+ [3].pack('v') + # tid type, dns_name
424
+ [dns_name.length].pack('v') +
425
+ dns_name
426
+ else
427
+ flags = CONST::NEGOTIATE_UNICODE + CONST::NEGOTIATE_NTLM
428
+ tid = false
429
+ end
430
+
431
+ type2msg = "NTLMSSP\0" + # protocol, 8 bytes
432
+ "\x02\x00\x00\x00" # type, 4 bytes
433
+
434
+ if (tid)
435
+ type2msg += # Target security info, 8 bytes. Filled if REQUEST_TARGET
436
+ [win_domain.length].pack('v') + # Length, 2 bytes
437
+ [win_domain.length].pack('v') # Allocated space, 2 bytes
438
+ end
439
+
440
+ type2msg +="\x30\x00\x00\x00" + # Offset, 4 bytes
441
+ [flags].pack('V') + # flags, 4 bytes
442
+ nonce + # the nonce, 8 bytes
443
+ "\x00" * 8 # Context (all 0s), 8 bytes
444
+
445
+ if (tid)
446
+ type2msg += # Target information security buffer. Filled if REQUEST_TARGET
447
+ [tidbuff.length].pack('v') + # Length, 2 bytes
448
+ [tidbuff.length].pack('v') + # Allocated space, 2 bytes
449
+ [tidoffset].pack('V') + # Offset, 4 bytes (usually \x48 + length of win_domain)
450
+ win_domain + # Target name data (domain in unicode if REQUEST_UNICODE)
451
+ # Target information data
452
+ tidbuff + # Type, 2 bytes
453
+ # Length, 2 bytes
454
+ # Data (in unicode if REQUEST_UNICODE)
455
+ "\x00\x00\x00\x00" # Terminator, 4 bytes, all \x00
456
+ end
457
+
458
+ type2msg = Rex::Text.encode_base64(type2msg).delete("\n") # base64 encode and remove the returns
459
+ else
460
+ # This is not a Type2 message
461
+ type2msg = ""
462
+ end
463
+
464
+ return type2msg
465
+ end
466
+
467
+ #
468
+ # Downgrading Type messages to LMv1/NTLMv1 and removing signing
469
+ #
470
+ def self.downgrade_type_message(message)
471
+ decode = Rex::Text.decode_base64(message.strip)
472
+
473
+ type = decode[8]
474
+
475
+ if (type > 0 and type < 4)
476
+ reqflags = decode[12..15] if (type == 1 or type == 3)
477
+ reqflags = decode[20..23] if (type == 2)
478
+ reqflags = Integer("0x" + reqflags.unpack("h8").to_s.reverse)
479
+
480
+ # Remove NEGOTIATE_NTLMV2_KEY and NEGOTIATE_ALWAYS_SIGN, this lowers the negotiation
481
+ # down to LMv1/NTLMv1.
482
+ if (reqflags & CONST::NEGOTIATE_NTLM2_KEY) == CONST::NEGOTIATE_NTLM2_KEY
483
+ reqflags = reqflags - CONST::NEGOTIATE_NTLM2_KEY
484
+ end
485
+ if (reqflags & CONST::NEGOTIATE_ALWAYS_SIGN) == CONST::NEGOTIATE_ALWAYS_SIGN
486
+ reqflags = reqflags - CONST::NEGOTIATE_ALWAYS_SIGN
487
+ end
488
+
489
+ # Return the flags back to the decode so we can base64 it again
490
+ flags = reqflags.to_s(16)
491
+ 0.upto(8) do |idx|
492
+ if (idx > flags.length)
493
+ flags.insert(0, "0")
494
+ end
495
+ end
496
+
497
+ idx = 0
498
+ 0.upto(3) do |cnt|
499
+ if (type == 2)
500
+ decode[23-cnt] = Integer("0x" + flags[idx .. idx + 1])
501
+ else
502
+ decode[15-cnt] = Integer("0x" + flags[idx .. idx + 1])
503
+ end
504
+ idx += 2
505
+ end
506
+
507
+ end
508
+ return Rex::Text.encode_base64(decode).delete("\n") # base64 encode and remove the returns
509
+ end
510
+
511
+ end
512
+ end
513
+ end
514
+ end