librex 0.0.3 → 0.0.4

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 (376) hide show
  1. data/README +0 -0
  2. data/lib/rex.rb +0 -0
  3. data/lib/rex.rb.ts.rb +0 -0
  4. data/lib/rex/LICENSE +0 -0
  5. data/lib/rex/arch.rb +0 -0
  6. data/lib/rex/arch/sparc.rb +0 -0
  7. data/lib/rex/arch/sparc.rb.ut.rb +0 -0
  8. data/lib/rex/arch/x86.rb +0 -0
  9. data/lib/rex/arch/x86.rb.ut.rb +0 -0
  10. data/lib/rex/assembly/nasm.rb +0 -0
  11. data/lib/rex/assembly/nasm.rb.ut.rb +0 -0
  12. data/lib/rex/codepage.map +0 -0
  13. data/lib/rex/compat.rb +0 -0
  14. data/lib/rex/constants.rb +0 -0
  15. data/lib/rex/elfparsey.rb +0 -0
  16. data/lib/rex/elfparsey/elf.rb +0 -0
  17. data/lib/rex/elfparsey/elfbase.rb +0 -0
  18. data/lib/rex/elfparsey/exceptions.rb +0 -0
  19. data/lib/rex/elfscan.rb +0 -0
  20. data/lib/rex/elfscan/scanner.rb +0 -0
  21. data/lib/rex/elfscan/search.rb +0 -0
  22. data/lib/rex/encoder/alpha2.rb +0 -0
  23. data/lib/rex/encoder/alpha2/alpha_mixed.rb +0 -0
  24. data/lib/rex/encoder/alpha2/alpha_upper.rb +0 -0
  25. data/lib/rex/encoder/alpha2/generic.rb +0 -0
  26. data/lib/rex/encoder/alpha2/unicode_mixed.rb +0 -0
  27. data/lib/rex/encoder/alpha2/unicode_upper.rb +0 -0
  28. data/lib/rex/encoder/ndr.rb +0 -0
  29. data/lib/rex/encoder/ndr.rb.ut.rb +0 -0
  30. data/lib/rex/encoder/nonalpha.rb +0 -0
  31. data/lib/rex/encoder/nonupper.rb +0 -0
  32. data/lib/rex/encoder/xdr.rb +0 -0
  33. data/lib/rex/encoder/xdr.rb.ut.rb +0 -0
  34. data/lib/rex/encoder/xor.rb +0 -0
  35. data/lib/rex/encoder/xor/dword.rb +0 -0
  36. data/lib/rex/encoder/xor/dword_additive.rb +0 -0
  37. data/lib/rex/encoders/xor_dword.rb +0 -0
  38. data/lib/rex/encoders/xor_dword_additive.rb +0 -0
  39. data/lib/rex/encoders/xor_dword_additive.rb.ut.rb +0 -0
  40. data/lib/rex/encoding/xor.rb +0 -0
  41. data/lib/rex/encoding/xor.rb.ts.rb +0 -0
  42. data/lib/rex/encoding/xor/byte.rb +0 -0
  43. data/lib/rex/encoding/xor/byte.rb.ut.rb +0 -0
  44. data/lib/rex/encoding/xor/dword.rb +0 -0
  45. data/lib/rex/encoding/xor/dword.rb.ut.rb +0 -0
  46. data/lib/rex/encoding/xor/dword_additive.rb +0 -0
  47. data/lib/rex/encoding/xor/dword_additive.rb.ut.rb +0 -0
  48. data/lib/rex/encoding/xor/exceptions.rb +0 -0
  49. data/lib/rex/encoding/xor/generic.rb +0 -0
  50. data/lib/rex/encoding/xor/generic.rb.ut.rb +0 -0
  51. data/lib/rex/encoding/xor/qword.rb +0 -0
  52. data/lib/rex/encoding/xor/word.rb +0 -0
  53. data/lib/rex/encoding/xor/word.rb.ut.rb +0 -0
  54. data/lib/rex/exceptions.rb +0 -0
  55. data/lib/rex/exceptions.rb.ut.rb +0 -0
  56. data/lib/rex/exploitation/cmdstager.rb +0 -0
  57. data/lib/rex/exploitation/cmdstager/base.rb +0 -0
  58. data/lib/rex/exploitation/cmdstager/debug_asm.rb +0 -0
  59. data/lib/rex/exploitation/cmdstager/debug_write.rb +0 -0
  60. data/lib/rex/exploitation/cmdstager/tftp.rb +0 -0
  61. data/lib/rex/exploitation/cmdstager/vbs.rb +0 -0
  62. data/lib/rex/exploitation/egghunter.rb +0 -0
  63. data/lib/rex/exploitation/egghunter.rb.ut.rb +0 -0
  64. data/lib/rex/exploitation/encryptjs.rb +0 -0
  65. data/lib/rex/exploitation/heaplib.js.b64 +0 -0
  66. data/lib/rex/exploitation/heaplib.rb +0 -0
  67. data/lib/rex/exploitation/javascriptosdetect.rb +2 -2
  68. data/lib/rex/exploitation/obfuscatejs.rb +0 -0
  69. data/lib/rex/exploitation/opcodedb.rb +0 -0
  70. data/lib/rex/exploitation/opcodedb.rb.ut.rb +0 -0
  71. data/lib/rex/exploitation/seh.rb +0 -0
  72. data/lib/rex/exploitation/seh.rb.ut.rb +0 -0
  73. data/lib/rex/file.rb +0 -0
  74. data/lib/rex/file.rb.ut.rb +0 -0
  75. data/lib/rex/image_source.rb +0 -0
  76. data/lib/rex/image_source/disk.rb +0 -0
  77. data/lib/rex/image_source/image_source.rb +0 -0
  78. data/lib/rex/image_source/memory.rb +0 -0
  79. data/lib/rex/io/bidirectional_pipe.rb +0 -0
  80. data/lib/rex/io/datagram_abstraction.rb +0 -0
  81. data/lib/rex/io/stream.rb +13 -15
  82. data/lib/rex/io/stream_abstraction.rb +0 -0
  83. data/lib/rex/io/stream_server.rb +0 -0
  84. data/lib/rex/job_container.rb +10 -25
  85. data/lib/rex/logging.rb +0 -0
  86. data/lib/rex/logging/log_dispatcher.rb +0 -0
  87. data/lib/rex/logging/log_sink.rb +0 -0
  88. data/lib/rex/logging/sinks/flatfile.rb +0 -0
  89. data/lib/rex/logging/sinks/stderr.rb +0 -0
  90. data/lib/rex/machparsey.rb +0 -0
  91. data/lib/rex/machparsey/exceptions.rb +0 -0
  92. data/lib/rex/machparsey/mach.rb +1 -1
  93. data/lib/rex/machparsey/machbase.rb +0 -0
  94. data/lib/rex/machscan.rb +0 -0
  95. data/lib/rex/machscan/scanner.rb +0 -0
  96. data/lib/rex/mime.rb +0 -0
  97. data/lib/rex/mime/header.rb +0 -0
  98. data/lib/rex/mime/message.rb +0 -0
  99. data/lib/rex/mime/part.rb +0 -0
  100. data/lib/rex/nop/opty2.rb +0 -0
  101. data/lib/rex/nop/opty2.rb.ut.rb +0 -0
  102. data/lib/rex/nop/opty2_tables.rb +0 -0
  103. data/lib/rex/ole.rb +0 -0
  104. data/lib/rex/ole/clsid.rb +0 -0
  105. data/lib/rex/ole/difat.rb +0 -0
  106. data/lib/rex/ole/directory.rb +0 -0
  107. data/lib/rex/ole/direntry.rb +0 -0
  108. data/lib/rex/ole/fat.rb +0 -0
  109. data/lib/rex/ole/header.rb +0 -0
  110. data/lib/rex/ole/minifat.rb +0 -0
  111. data/lib/rex/ole/storage.rb +0 -0
  112. data/lib/rex/ole/stream.rb +0 -0
  113. data/lib/rex/ole/substorage.rb +0 -0
  114. data/lib/rex/ole/util.rb +0 -0
  115. data/lib/rex/parser/arguments.rb +0 -0
  116. data/lib/rex/parser/arguments.rb.ut.rb +0 -0
  117. data/lib/rex/parser/ini.rb +0 -0
  118. data/lib/rex/parser/ini.rb.ut.rb +0 -0
  119. data/lib/rex/parser/nexpose_xml.rb +0 -0
  120. data/lib/rex/parser/nmap_xml.rb +0 -0
  121. data/lib/rex/payloads.rb +0 -0
  122. data/lib/rex/payloads/win32.rb +0 -0
  123. data/lib/rex/payloads/win32/common.rb +0 -0
  124. data/lib/rex/payloads/win32/kernel.rb +0 -0
  125. data/lib/rex/payloads/win32/kernel/common.rb +0 -0
  126. data/lib/rex/payloads/win32/kernel/migration.rb +0 -0
  127. data/lib/rex/payloads/win32/kernel/recovery.rb +0 -0
  128. data/lib/rex/payloads/win32/kernel/stager.rb +26 -3
  129. data/lib/rex/peparsey.rb +0 -0
  130. data/lib/rex/peparsey/exceptions.rb +0 -0
  131. data/lib/rex/peparsey/pe.rb +0 -0
  132. data/lib/rex/peparsey/pe_memdump.rb +0 -0
  133. data/lib/rex/peparsey/pebase.rb +0 -0
  134. data/lib/rex/peparsey/section.rb +0 -0
  135. data/lib/rex/pescan.rb +0 -0
  136. data/lib/rex/pescan/analyze.rb +0 -0
  137. data/lib/rex/pescan/scanner.rb +0 -0
  138. data/lib/rex/pescan/search.rb +0 -0
  139. data/lib/rex/platforms.rb +0 -0
  140. data/lib/rex/platforms/windows.rb +0 -0
  141. data/lib/rex/poly.rb +0 -0
  142. data/lib/rex/poly/block.rb +0 -0
  143. data/lib/rex/poly/register.rb +0 -0
  144. data/lib/rex/poly/register/x86.rb +0 -0
  145. data/lib/rex/post.rb +0 -0
  146. data/lib/rex/post/dir.rb +0 -0
  147. data/lib/rex/post/file.rb +0 -0
  148. data/lib/rex/post/file_stat.rb +0 -0
  149. data/lib/rex/post/gen.pl +0 -0
  150. data/lib/rex/post/io.rb +0 -0
  151. data/lib/rex/post/meterpreter.rb +0 -0
  152. data/lib/rex/post/meterpreter/channel.rb +0 -0
  153. data/lib/rex/post/meterpreter/channel_container.rb +0 -0
  154. data/lib/rex/post/meterpreter/channels/pool.rb +0 -0
  155. data/lib/rex/post/meterpreter/channels/pools/file.rb +0 -0
  156. data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +0 -0
  157. data/lib/rex/post/meterpreter/channels/stream.rb +0 -0
  158. data/lib/rex/post/meterpreter/client.rb +0 -0
  159. data/lib/rex/post/meterpreter/client_core.rb +0 -0
  160. data/lib/rex/post/meterpreter/dependencies.rb +0 -0
  161. data/lib/rex/post/meterpreter/extension.rb +0 -0
  162. data/lib/rex/post/meterpreter/extensions/espia/espia.rb +0 -0
  163. data/lib/rex/post/meterpreter/extensions/espia/tlv.rb +0 -0
  164. data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +0 -0
  165. data/lib/rex/post/meterpreter/extensions/incognito/tlv.rb +0 -0
  166. data/lib/rex/post/meterpreter/extensions/priv/fs.rb +0 -0
  167. data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +0 -0
  168. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +0 -0
  169. data/lib/rex/post/meterpreter/extensions/priv/tlv.rb +0 -0
  170. data/lib/rex/post/meterpreter/extensions/railgun/api.rb +9303 -0
  171. data/lib/rex/post/meterpreter/extensions/railgun/api_constants.rb +38105 -0
  172. data/lib/rex/post/meterpreter/extensions/railgun/def_kernel32.rb +3678 -0
  173. data/lib/rex/post/meterpreter/extensions/railgun/railgun.rb +815 -0
  174. data/lib/rex/post/meterpreter/extensions/railgun/tlv.rb +54 -0
  175. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +0 -0
  176. data/lib/rex/post/meterpreter/extensions/sniffer/tlv.rb +0 -0
  177. data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +0 -0
  178. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +0 -0
  179. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +0 -0
  180. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +0 -0
  181. data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +0 -0
  182. data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +0 -0
  183. data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +0 -0
  184. data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +0 -0
  185. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +7 -7
  186. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +21 -8
  187. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +0 -0
  188. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +33 -17
  189. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +0 -0
  190. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +0 -0
  191. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +0 -0
  192. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +0 -0
  193. data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +0 -0
  194. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +0 -0
  195. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +0 -0
  196. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +0 -0
  197. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +0 -0
  198. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +0 -0
  199. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +0 -0
  200. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +0 -0
  201. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +0 -0
  202. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +0 -0
  203. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +0 -0
  204. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +0 -0
  205. data/lib/rex/post/meterpreter/inbound_packet_handler.rb +0 -0
  206. data/lib/rex/post/meterpreter/object_aliases.rb +0 -0
  207. data/lib/rex/post/meterpreter/packet.rb +0 -0
  208. data/lib/rex/post/meterpreter/packet_dispatcher.rb +0 -0
  209. data/lib/rex/post/meterpreter/packet_parser.rb +0 -0
  210. data/lib/rex/post/meterpreter/packet_response_waiter.rb +0 -0
  211. data/lib/rex/post/meterpreter/ui/console.rb +0 -0
  212. data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +0 -0
  213. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +0 -0
  214. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +0 -0
  215. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +0 -0
  216. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +0 -0
  217. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +0 -0
  218. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +0 -0
  219. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +0 -0
  220. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/railgun.rb +57 -0
  221. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +0 -0
  222. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +0 -0
  223. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +0 -0
  224. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +0 -0
  225. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +0 -0
  226. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +0 -0
  227. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +0 -0
  228. data/lib/rex/post/permission.rb +0 -0
  229. data/lib/rex/post/process.rb +0 -0
  230. data/lib/rex/post/thread.rb +0 -0
  231. data/lib/rex/post/ui.rb +0 -0
  232. data/lib/rex/proto.rb +0 -0
  233. data/lib/rex/proto.rb.ts.rb +0 -0
  234. data/lib/rex/proto/dcerpc.rb +0 -0
  235. data/lib/rex/proto/dcerpc.rb.ts.rb +0 -0
  236. data/lib/rex/proto/dcerpc/client.rb +45 -44
  237. data/lib/rex/proto/dcerpc/exceptions.rb +0 -0
  238. data/lib/rex/proto/dcerpc/handle.rb +0 -0
  239. data/lib/rex/proto/dcerpc/handle.rb.ut.rb +0 -0
  240. data/lib/rex/proto/dcerpc/ndr.rb +0 -0
  241. data/lib/rex/proto/dcerpc/ndr.rb.ut.rb +0 -0
  242. data/lib/rex/proto/dcerpc/packet.rb +0 -0
  243. data/lib/rex/proto/dcerpc/packet.rb.ut.rb +0 -0
  244. data/lib/rex/proto/dcerpc/response.rb +32 -31
  245. data/lib/rex/proto/dcerpc/response.rb.ut.rb +0 -0
  246. data/lib/rex/proto/dcerpc/uuid.rb +0 -0
  247. data/lib/rex/proto/dcerpc/uuid.rb.ut.rb +0 -0
  248. data/lib/rex/proto/drda.rb +0 -0
  249. data/lib/rex/proto/drda.rb.ts.rb +0 -0
  250. data/lib/rex/proto/drda/constants.rb +0 -0
  251. data/lib/rex/proto/drda/constants.rb.ut.rb +0 -0
  252. data/lib/rex/proto/drda/packet.rb +0 -0
  253. data/lib/rex/proto/drda/packet.rb.ut.rb +0 -0
  254. data/lib/rex/proto/drda/utils.rb +0 -0
  255. data/lib/rex/proto/drda/utils.rb.ut.rb +0 -0
  256. data/lib/rex/proto/http.rb +0 -0
  257. data/lib/rex/proto/http.rb.ts.rb +0 -0
  258. data/lib/rex/proto/http/client.rb +1 -1
  259. data/lib/rex/proto/http/client.rb.ut.rb +0 -0
  260. data/lib/rex/proto/http/handler.rb +0 -0
  261. data/lib/rex/proto/http/handler/erb.rb +0 -0
  262. data/lib/rex/proto/http/handler/erb.rb.ut.rb +0 -0
  263. data/lib/rex/proto/http/handler/erb.rb.ut.rb.rhtml +0 -0
  264. data/lib/rex/proto/http/handler/proc.rb +0 -0
  265. data/lib/rex/proto/http/handler/proc.rb.ut.rb +0 -0
  266. data/lib/rex/proto/http/header.rb +0 -0
  267. data/lib/rex/proto/http/header.rb.ut.rb +0 -0
  268. data/lib/rex/proto/http/packet.rb +0 -0
  269. data/lib/rex/proto/http/packet.rb.ut.rb +0 -0
  270. data/lib/rex/proto/http/request.rb +0 -0
  271. data/lib/rex/proto/http/request.rb.ut.rb +0 -0
  272. data/lib/rex/proto/http/response.rb +0 -0
  273. data/lib/rex/proto/http/response.rb.ut.rb +0 -0
  274. data/lib/rex/proto/http/server.rb +0 -0
  275. data/lib/rex/proto/http/server.rb.ut.rb +0 -0
  276. data/lib/rex/proto/smb.rb +0 -0
  277. data/lib/rex/proto/smb.rb.ts.rb +0 -0
  278. data/lib/rex/proto/smb/client.rb +1 -1
  279. data/lib/rex/proto/smb/client.rb.ut.rb +0 -0
  280. data/lib/rex/proto/smb/constants.rb +0 -0
  281. data/lib/rex/proto/smb/constants.rb.ut.rb +0 -0
  282. data/lib/rex/proto/smb/crypt.rb +0 -0
  283. data/lib/rex/proto/smb/crypt.rb.ut.rb +0 -0
  284. data/lib/rex/proto/smb/evasions.rb +18 -17
  285. data/lib/rex/proto/smb/exceptions.rb +0 -0
  286. data/lib/rex/proto/smb/simpleclient.rb +0 -0
  287. data/lib/rex/proto/smb/simpleclient.rb.ut.rb +0 -0
  288. data/lib/rex/proto/smb/utils.rb +0 -0
  289. data/lib/rex/proto/smb/utils.rb.ut.rb +0 -0
  290. data/lib/rex/proto/sunrpc.rb +0 -0
  291. data/lib/rex/proto/sunrpc/client.rb +0 -0
  292. data/lib/rex/proto/tftp.rb +0 -0
  293. data/lib/rex/proto/tftp/constants.rb +0 -0
  294. data/lib/rex/proto/tftp/server.rb +212 -37
  295. data/lib/rex/script.rb +0 -0
  296. data/lib/rex/script/base.rb +0 -0
  297. data/lib/rex/script/meterpreter.rb +0 -0
  298. data/lib/rex/script/shell.rb +0 -0
  299. data/lib/rex/service.rb +0 -0
  300. data/lib/rex/service_manager.rb +0 -0
  301. data/lib/rex/service_manager.rb.ut.rb +0 -0
  302. data/lib/rex/services/local_relay.rb +0 -0
  303. data/lib/rex/socket.rb +25 -0
  304. data/lib/rex/socket.rb.ut.rb +0 -0
  305. data/lib/rex/socket/comm.rb +0 -0
  306. data/lib/rex/socket/comm/local.rb +0 -0
  307. data/lib/rex/socket/comm/local.rb.ut.rb +0 -0
  308. data/lib/rex/socket/ip.rb +0 -0
  309. data/lib/rex/socket/parameters.rb +0 -0
  310. data/lib/rex/socket/parameters.rb.ut.rb +0 -0
  311. data/lib/rex/socket/range_walker.rb +0 -0
  312. data/lib/rex/socket/range_walker.rb.ut.rb +0 -0
  313. data/lib/rex/socket/ssl_tcp.rb +0 -0
  314. data/lib/rex/socket/ssl_tcp.rb.ut.rb +0 -0
  315. data/lib/rex/socket/ssl_tcp_server.rb +0 -0
  316. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +0 -0
  317. data/lib/rex/socket/subnet_walker.rb +0 -0
  318. data/lib/rex/socket/subnet_walker.rb.ut.rb +0 -0
  319. data/lib/rex/socket/switch_board.rb +11 -5
  320. data/lib/rex/socket/switch_board.rb.ut.rb +0 -0
  321. data/lib/rex/socket/tcp.rb +0 -0
  322. data/lib/rex/socket/tcp.rb.ut.rb +0 -0
  323. data/lib/rex/socket/tcp_server.rb +0 -0
  324. data/lib/rex/socket/tcp_server.rb.ut.rb +0 -0
  325. data/lib/rex/socket/udp.rb +0 -0
  326. data/lib/rex/socket/udp.rb.ut.rb +0 -0
  327. data/lib/rex/struct2.rb +0 -0
  328. data/lib/rex/struct2/c_struct.rb +0 -0
  329. data/lib/rex/struct2/c_struct_template.rb +0 -0
  330. data/lib/rex/struct2/constant.rb +0 -0
  331. data/lib/rex/struct2/element.rb +0 -0
  332. data/lib/rex/struct2/generic.rb +0 -0
  333. data/lib/rex/struct2/restraint.rb +0 -0
  334. data/lib/rex/struct2/s_string.rb +0 -0
  335. data/lib/rex/struct2/s_struct.rb +0 -0
  336. data/lib/rex/sync.rb +0 -0
  337. data/lib/rex/sync/event.rb +0 -0
  338. data/lib/rex/sync/read_write_lock.rb +0 -0
  339. data/lib/rex/sync/ref.rb +0 -0
  340. data/lib/rex/sync/thread_safe.rb +0 -0
  341. data/lib/rex/test.rb +0 -0
  342. data/lib/rex/text.rb +15 -4
  343. data/lib/rex/text.rb.ut.rb +3 -0
  344. data/lib/rex/time.rb +0 -0
  345. data/lib/rex/transformer.rb +0 -0
  346. data/lib/rex/transformer.rb.ut.rb +0 -0
  347. data/lib/rex/ui.rb +0 -0
  348. data/lib/rex/ui/interactive.rb +0 -0
  349. data/lib/rex/ui/output.rb +0 -0
  350. data/lib/rex/ui/output/none.rb +0 -0
  351. data/lib/rex/ui/progress_tracker.rb +0 -0
  352. data/lib/rex/ui/subscriber.rb +0 -0
  353. data/lib/rex/ui/text/color.rb +0 -0
  354. data/lib/rex/ui/text/color.rb.ut.rb +0 -0
  355. data/lib/rex/ui/text/dispatcher_shell.rb +0 -0
  356. data/lib/rex/ui/text/input.rb +0 -0
  357. data/lib/rex/ui/text/input/buffer.rb +0 -0
  358. data/lib/rex/ui/text/input/readline.rb +0 -0
  359. data/lib/rex/ui/text/input/socket.rb +0 -0
  360. data/lib/rex/ui/text/input/stdio.rb +0 -0
  361. data/lib/rex/ui/text/irb_shell.rb +0 -0
  362. data/lib/rex/ui/text/output.rb +0 -0
  363. data/lib/rex/ui/text/output/buffer.rb +0 -0
  364. data/lib/rex/ui/text/output/file.rb +0 -0
  365. data/lib/rex/ui/text/output/socket.rb +0 -0
  366. data/lib/rex/ui/text/output/stdio.rb +0 -0
  367. data/lib/rex/ui/text/progress_tracker.rb +0 -0
  368. data/lib/rex/ui/text/progress_tracker.rb.ut.rb +0 -0
  369. data/lib/rex/ui/text/shell.rb +0 -0
  370. data/lib/rex/ui/text/table.rb +0 -0
  371. data/lib/rex/ui/text/table.rb.ut.rb +0 -0
  372. data/lib/rex/zip.rb +0 -0
  373. data/lib/rex/zip/archive.rb +0 -0
  374. data/lib/rex/zip/blocks.rb +0 -0
  375. data/lib/rex/zip/entry.rb +0 -0
  376. metadata +414 -347
@@ -0,0 +1,815 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2010, patrickHVE@googlemail.com
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright
11
+ # notice, this list of conditions and the following disclaimer in the
12
+ # documentation and/or other materials provided with the distribution.
13
+ # * The names of the author may not be used to endorse or promote products
14
+ # derived from this software without specific prior written permission.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ # DISCLAIMED. IN NO EVENT SHALL patrickHVE@googlemail.com BE LIABLE FOR ANY
20
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+
27
+ require 'rex/post/meterpreter/extensions/railgun/tlv'
28
+ require "pp"
29
+ require 'enumerator'
30
+ require 'rex/post/meterpreter/extensions/railgun/api'
31
+ require 'rex/post/meterpreter/extensions/railgun/api_constants'
32
+
33
+ module Rex
34
+ module Post
35
+ module Meterpreter
36
+ module Extensions
37
+ module Railgun
38
+
39
+ # Manages our library of windows constants
40
+ class WinConstManager
41
+ def initialize()
42
+ @consts = {}
43
+ end
44
+
45
+ def add_const(name, value)
46
+ @consts[name] = value
47
+ end
48
+
49
+ # parses a string constaining constants and returns an integer
50
+ # the string can be either "CONST" or "CONST1 | CONST2"
51
+ #
52
+ # this function will NOT throw an exception but return "nil" if it can't parse a string
53
+ def parse(s)
54
+ if s.class != String
55
+ return nil # it's not even a string'
56
+ end
57
+ return_value = 0
58
+ for one_const in s.split('|')
59
+ one_const = one_const.strip()
60
+ if not @consts.has_key? one_const
61
+ return nil # at least one "Constant" is unknown to us
62
+ end
63
+ return_value |= @consts[one_const]
64
+ end
65
+ return return_value
66
+ end
67
+
68
+ def is_parseable(s)
69
+ return parse(s) != nil
70
+ end
71
+ end
72
+
73
+
74
+ # represents one function, e.g. MessageBoxW
75
+ class DLLFunction
76
+ attr_reader :return_type, :params, :windows_name
77
+
78
+ def initialize(return_type, params, windows_name)
79
+ check_return_type(return_type) # we do error checking as early as possible so the library is easier to use
80
+ check_params(params)
81
+ @return_type = return_type
82
+ @params = params
83
+ @windows_name = windows_name
84
+ end
85
+
86
+ @@directions=["in", "out", "inout", "return"]
87
+ @@allowed_datatypes={
88
+ "VOID" => ["return"],
89
+ "BOOL" => ["in", "return"],
90
+ "DWORD" => ["in", "return"],
91
+ "WORD" => ["in", "return"],
92
+ "BYTE" => ["in", "return"],
93
+ "PDWORD" => ["in", "out", "inout"], # todo: support for functions that return pointers to strings
94
+ "PWCHAR" => ["in", "out", "inout"],
95
+ "PCHAR" => ["in", "out", "inout"],
96
+ "PBLOB" => ["in", "out", "inout"]
97
+ }
98
+ private
99
+ def check_type_exists (type)
100
+ if not @@allowed_datatypes.has_key?(type)
101
+ raise "Type unknown: #{type}. Allowed types: #{PP.pp(@@allowed_datatypes.keys, "")}"
102
+ end
103
+ end
104
+
105
+ def check_return_type (type)
106
+ check_type_exists(type)
107
+ if not @@allowed_datatypes[type].include?("return")
108
+ raise "#{type} is not allowed as a return type"
109
+ end
110
+ end
111
+
112
+ def check_params (params)
113
+ params.each do |param|
114
+ throw "each param must be descriped by a three-tuple [type,name,direction]" unless param.length == 3
115
+ type = param[0]
116
+ direction = param[2]
117
+ check_type_exists(type)
118
+ throw "invalid direction: #{direction}" unless @@directions.include?(direction)
119
+ throw "direction 'return' is only for the return value of the function." unless direction != "return"
120
+ end
121
+ end
122
+ end
123
+
124
+ class BufferItem
125
+ attr_reader :belongs_to_param_n, :addr, :length_in_bytes, :datatype
126
+
127
+ def initialize(belongs_to_param_n, addr, length_in_bytes, datatype)
128
+ @belongs_to_param_n = belongs_to_param_n
129
+ @addr = addr
130
+ @length_in_bytes = length_in_bytes
131
+ @datatype = datatype
132
+ end
133
+ end
134
+
135
+ # shared functions
136
+ module DLLHelper
137
+
138
+ # converts ruby string to zero-terminated ASCII string
139
+ def str_to_ascii_z(str)
140
+ return str+"\x00"
141
+ end
142
+
143
+ # converts 0-terminated ASCII string to ruby string
144
+ def asciiz_to_str(asciiz)
145
+ zero_byte_idx = asciiz.index("\x00")
146
+ if zero_byte_idx != nil
147
+ return asciiz[0, zero_byte_idx]
148
+ else
149
+ return asciiz
150
+ end
151
+ end
152
+
153
+ # converts ruby string to zero-terminated WCHAR string
154
+ def str_to_uni_z(str)
155
+ enc = str.unpack("C*").pack("v*")
156
+ enc += "\x00\x00"
157
+ return enc
158
+ end
159
+
160
+ # converts 0-terminated UTF16 to ruby string
161
+ def uniz_to_str(uniz)
162
+ uniz.unpack("v*").pack("C*").unpack("A*")[0]
163
+ end
164
+
165
+ # parses a DWORD param and returns the value
166
+ # raises an exception if the param cannot be converted to DWORD
167
+ # examples:
168
+ # 3 => 3
169
+ # "MB_OK" => 0
170
+ # "SOME_CONSTANT | OTHER_CONSTANT" => 17
171
+ # "tuna" => !!!!!!!!!!Exception
172
+ def param_to_dword(v)
173
+ if v.class == Fixnum then
174
+ return v # ok, it's already a number
175
+ elsif v.class == Bignum then
176
+ return v # ok, it's already a number
177
+ elsif v.class == String then
178
+ dw = @win_consts.parse(v) # might raise an exception
179
+ if dw != nil
180
+ return dw
181
+ else
182
+ raise "Param #{v} (class #{v.class}) cannot be converted to DWORD. It's a string but matches no constants I know."
183
+ end
184
+ else
185
+ raise "Param #{v} (class #{v.class}) should be a number but isn't"
186
+ end
187
+ end # param_to_dword(v)
188
+
189
+
190
+ # assembles the buffers "in" and "inout"
191
+ def assemble_buffer(direction, function, args)
192
+ layout = {} # paramName => BufferItem
193
+ blob = ""
194
+ #puts " building buffer: #{direction}"
195
+ function.params.each_with_index do |param_desc, param_idx|
196
+ #puts " processing #{param_desc[0]} #{param_desc[1]} #{param_desc[2]}"
197
+ # we care only about inout buffers
198
+ if param_desc[2] == direction
199
+ buffer = nil
200
+
201
+ # Special case:
202
+ # The user can choose to supply a Null pointer instead of a buffer
203
+ # in this case we don't need space in any heap buffer
204
+ if param_desc[0][0,1] == 'P' # type is a pointer
205
+ if args[param_idx] == nil
206
+ next
207
+ end
208
+ end
209
+
210
+ case param_desc[0] # required argument type
211
+ when "PDWORD"
212
+ dw = param_to_dword(args[param_idx])
213
+ buffer = [dw].pack('V')
214
+ when "PWCHAR"
215
+ raise "param #{param_desc[1]}: string expected" unless args[param_idx].class == String
216
+ buffer = str_to_uni_z(args[param_idx])
217
+ when "PCHAR"
218
+ raise "param #{param_desc[1]}: string expected" unless args[param_idx].class == String
219
+ buffer = str_to_ascii_z(args[param_idx])
220
+ when "PBLOB"
221
+ raise "param #{param_desc[1]}: please supply your BLOB as string!" unless args[param_idx].class == String
222
+ buffer = args[param_idx]
223
+ # other types (non-pointers) don't reference buffers
224
+ # and don't need any treatment here
225
+ end
226
+ if buffer != nil
227
+ #puts " adding #{buffer.length} bytes to heap blob"
228
+ layout[param_desc[1]] = BufferItem.new(param_idx, blob.length, buffer.length, param_desc[0])
229
+ blob += buffer
230
+ #puts " heap blob size now #{blob.length}"
231
+ end
232
+ end
233
+ end
234
+ #puts " built buffer: #{direction}"
235
+ return [layout, blob]
236
+ end
237
+ end
238
+
239
+ # represents a DLL, e.g. kernel32.dll
240
+ class DLL
241
+
242
+ include DLLHelper
243
+
244
+ attr_accessor :functions
245
+
246
+ def initialize(dll_path, client, win_consts) #
247
+ @dll_path = dll_path
248
+ @client = client
249
+ @win_consts = win_consts
250
+ self.functions = {}
251
+ end
252
+
253
+ # adds a function to the DLL
254
+ # syntax for params:
255
+ # add_function("MessageBoxW", # name
256
+ # "DWORD", # return value
257
+ # [["DWORD","hWnd","in"], # params
258
+ # ["PWCHAR","lpText","in"],
259
+ # ["PWCHAR","lpCaption","in"],
260
+ # ["DWORD","uType","in"],
261
+ # ])
262
+ #
263
+ # Every function argument is described by a tuple (type,name,direction)
264
+ #
265
+ # windows_name: Use it when the actual windows name is different from the ruby variable
266
+ # for example when the actual func name is myFunc@4
267
+ # or when you want to create an alternative version of an existing function
268
+ #
269
+ # When new function is called it will return a list containing the return value and all inout params
270
+ def add_function(name, return_type, params, windows_name=nil)
271
+ if windows_name == nil
272
+ windows_name = name
273
+ end
274
+ @functions[name] = DLLFunction.new(return_type, params, windows_name)
275
+ end
276
+
277
+ private
278
+
279
+
280
+ # called when a function like "MessageBoxW" is called
281
+ def process_function_call(function, args)
282
+ raise "#{function.params.length} arguments expected. #{args.length} arguments provided." unless args.length == function.params.length
283
+ #puts "process_function_call(function.windows_name,#{PP.pp(args, "")})"
284
+
285
+ # We transmit the immediate stack and three heap-buffers:
286
+ # in, inout and out. The reason behind the separation is bandwidth.
287
+ # We don't want to transmit uninitialized data in or no-longer-needed data out.
288
+
289
+ # out-only-buffers that are ONLY transmitted on the way BACK
290
+ out_only_layout = {} # paramName => BufferItem
291
+ out_only_size_bytes = 0
292
+ #puts " assembling out-only buffer"
293
+ function.params.each_with_index do |param_desc, param_idx|
294
+ #puts " processing #{param_desc[1]}"
295
+
296
+ # Special case:
297
+ # The user can choose to supply a Null pointer instead of a buffer
298
+ # in this case we don't need space in any heap buffer
299
+ if param_desc[0][0,1] == 'P' # type is a pointer
300
+ if args[param_idx] == nil
301
+ next
302
+ end
303
+ end
304
+
305
+ # we care only about out-only buffers
306
+ if param_desc[2] == "out"
307
+ raise "error in param #{param_desc[1]}: Out-only buffers must be described by a number indicating their size in bytes " unless args[param_idx].class == Fixnum
308
+ buffer_size = args[param_idx]
309
+ if param_desc[0] == "PDWORD"
310
+ raise "Please pass 4 for 'out' PDWORDS, since they require a buffer of size 4" unless buffer_size == 4
311
+ end
312
+
313
+ out_only_layout[param_desc[1]] = BufferItem.new(param_idx, out_only_size_bytes, buffer_size, param_desc[0])
314
+ out_only_size_bytes += buffer_size
315
+ end
316
+ end
317
+
318
+ tmp = assemble_buffer("in", function, args)
319
+ in_only_layout = tmp[0]
320
+ in_only_buffer = tmp[1]
321
+
322
+ tmp = assemble_buffer("inout", function, args)
323
+ inout_layout = tmp[0]
324
+ inout_buffer = tmp[1]
325
+
326
+
327
+ # now we build the stack
328
+ # every stack dword will be described by two dwords:
329
+ # first dword describes second dword:
330
+ # 0 - literal,
331
+ # 1 = relative to in-only buffer
332
+ # 2 = relative to out-only buffer
333
+ # 3 = relative to inout buffer
334
+
335
+ # (literal numbers and pointers to buffers we have created)
336
+ literal_pairs_blob = ""
337
+ #puts " assembling literal stack"
338
+ function.params.each_with_index do |param_desc, param_idx|
339
+ #puts " processing (#{param_desc[0]}, #{param_desc[1]}, #{param_desc[2]})"
340
+ buffer = nil
341
+ # is it a pointer to a buffer on our stack
342
+ if ["PDWORD", "PWCHAR", "PCHAR", "PBLOB"].include? param_desc[0]
343
+ #puts " pointer"
344
+ if args[param_idx] == nil # null pointer?
345
+ buffer = [0].pack('V') # type: DWORD (so the dll does not rebase it)
346
+ buffer += [0].pack('V') # value: 0
347
+ elsif param_desc[2] == "in"
348
+ buffer = [1].pack('V')
349
+ buffer += [in_only_layout[param_desc[1]].addr].pack('V')
350
+ elsif param_desc[2] == "out"
351
+ buffer = [2].pack('V')
352
+ buffer += [out_only_layout[param_desc[1]].addr].pack('V')
353
+ elsif param_desc[2] == "inout"
354
+ buffer = [3].pack('V')
355
+ buffer += [inout_layout[param_desc[1]].addr].pack('V')
356
+ else
357
+ raise "unexpected direction"
358
+ end
359
+ else
360
+ #puts " not a pointer"
361
+ # it's not a pointer
362
+ buffer = [0].pack('V')
363
+ case param_desc[0]
364
+ when "DWORD"
365
+ dw = param_to_dword(args[param_idx])
366
+ buffer += [dw].pack('V')
367
+ when "WORD"
368
+ dw = param_to_dword(args[param_idx])
369
+ buffer += [dw % 65536].pack('V')
370
+ when "BYTE"
371
+ dw = param_to_dword(args[param_idx])
372
+ buffer += [dw % 256].pack('V')
373
+ when "BOOL"
374
+ case args[param_idx]
375
+ when true
376
+ buffer += [1].pack('V')
377
+ when false
378
+ buffer += [0].pack('V')
379
+ else
380
+ raise "param #{param_desc[1]}: true or false expected"
381
+ end
382
+ else
383
+ raise "unexpected type for param #{param_desc[1]}"
384
+ end
385
+ end
386
+
387
+ #puts " adding pair to blob"
388
+ literal_pairs_blob += buffer
389
+ #puts " buffer size %X" % buffer.length
390
+ #puts " blob size so far: %X" % literal_pairs_blob.length
391
+ end
392
+
393
+ #puts "\n\nsending Stuff to meterpreter"
394
+ request = Packet.create_request('railgun_api')
395
+ request.add_tlv(TLV_TYPE_RAILGUN_SIZE_OUT, out_only_size_bytes)
396
+
397
+ request.add_tlv(TLV_TYPE_RAILGUN_STACKBLOB, literal_pairs_blob)
398
+ request.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_IN, in_only_buffer)
399
+ request.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT, inout_buffer)
400
+
401
+ request.add_tlv(TLV_TYPE_RAILGUN_DLLNAME, @dll_path )
402
+ request.add_tlv(TLV_TYPE_RAILGUN_FUNCNAME, function.windows_name)
403
+
404
+
405
+ response = @client.send_request(request)
406
+
407
+ #puts "receiving Stuff from meterpreter"
408
+ #puts "out_only_layout:"
409
+ #puts out_only_layout
410
+
411
+ rec_inout_buffers = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT)
412
+ rec_out_only_buffers = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT)
413
+ rec_return_value = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_RET)
414
+ rec_last_error = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_ERR)
415
+
416
+ #puts "received stuff"
417
+ #puts "out_only_layout:"
418
+ #puts out_only_layout
419
+
420
+ # The hash the function returns
421
+ return_hash={"GetLastError" => rec_last_error}
422
+
423
+ #process return value
424
+ case function.return_type
425
+ when "DWORD"
426
+ return_hash["return"] = rec_return_value
427
+ when "WORD"
428
+ return_hash["return"] = rec_return_value % 65536
429
+ when "BYTE"
430
+ return_hash["return"] = rec_return_value % 256
431
+ when "BOOL"
432
+ return_hash["return"] = (rec_return_value != 0)
433
+ when "VOID"
434
+ return_hash["return"] = nil
435
+ else
436
+ raise "unexpected return type: #{function.return_type}"
437
+ end
438
+ #puts return_hash
439
+ #puts "out_only_layout:"
440
+ #puts out_only_layout
441
+
442
+
443
+ # process out-only buffers
444
+ #puts "processing out-only buffers:"
445
+ out_only_layout.each_pair do |param_name, buffer_item|
446
+ #puts " #{param_name}"
447
+ buffer = rec_out_only_buffers[buffer_item.addr, buffer_item.length_in_bytes]
448
+ case buffer_item.datatype
449
+ when "PDWORD"
450
+ return_hash[param_name] = buffer.unpack('V')[0]
451
+ when "PCHAR"
452
+ return_hash[param_name] = asciiz_to_str(buffer)
453
+ when "PWCHAR"
454
+ return_hash[param_name] = uniz_to_str(buffer)
455
+ when "PBLOB"
456
+ return_hash[param_name] = buffer
457
+ else
458
+ raise "unexpected type in out-only buffer of #{param_name}: #{buffer_item.datatype}"
459
+ end
460
+ end
461
+ #puts return_hash
462
+
463
+ # process in-out buffers
464
+ #puts "processing in-out buffers:"
465
+ inout_layout.each_pair do |param_name, buffer_item|
466
+ #puts " #{param_name}"
467
+ buffer = rec_inout_buffers[buffer_item.addr, buffer_item.length_in_bytes]
468
+ case buffer_item.datatype
469
+ when "PDWORD"
470
+ return_hash[param_name] = buffer.unpack('V')[0]
471
+ when "PCHAR"
472
+ return_hash[param_name] = asciiz_to_str(buffer)
473
+ when "PWCHAR"
474
+ return_hash[param_name] = uniz_to_str(buffer)
475
+ when "PBLOB"
476
+ return_hash[param_name] = buffer
477
+ else
478
+ raise "unexpected type in in-out-buffer of #{param_name}: #{buffer_item.datatype}"
479
+ end
480
+ end
481
+ #puts return_hash
482
+ #puts "finished"
483
+
484
+ return return_hash
485
+ end
486
+
487
+ # process_function_call
488
+
489
+
490
+ # we fake having methods like "MessageBoxW" by intercepting "method-not-found"-exceptions
491
+ def method_missing(func_symbol, *args)
492
+ func_name = func_symbol.to_s
493
+ raise "DLL-function #{func_name} not found. Known functions: #{PP.pp(@functions.keys, "")}" unless @functions.has_key? func_name
494
+ function = @functions[func_name]
495
+ return process_function_call(function, args)
496
+ end
497
+ end
498
+
499
+ #
500
+ # This extensions give you access to the full Windows API
501
+ #
502
+ class Railgun < Extension
503
+
504
+ attr_accessor :dll, :client, :multicaller
505
+
506
+ def initialize(client)
507
+ super(client, 'railgun')
508
+ self.client = client
509
+ self.dll = {}
510
+ @win_consts = WinConstManager.new()
511
+
512
+ # Load tons of definitions
513
+ ApiDefinitions.add_imports(self)
514
+ ApiConstants.add_constants(@win_consts)
515
+
516
+ # Load the multi-caller
517
+ self.multicaller = MultiCaller.new(self)
518
+ client.register_extension_aliases(
519
+ [
520
+ {
521
+ 'name' => 'railgun',
522
+ 'ext' => self
523
+ },
524
+ ])
525
+ end
526
+
527
+ # adds a function to an existing DLL-definition
528
+ def add_function(dll_name, function_name, return_type, params, windows_name=nil)
529
+ raise "DLL #{dll_name} not found. Known DLLs: #{PP.pp(@dll.keys, "")}" unless @dll.has_key? dll_name
530
+ @dll[dll_name].add_function(function_name, return_type, params, windows_name)
531
+ end
532
+
533
+ # adds a function to an existing DLL-definition
534
+ # you can override the dll name if you want to include a path or the DLL name contains
535
+ # non-ruby-approved characters
536
+ def add_dll(dll_name, windows_name=nil)
537
+ raise "DLL #{dll_name} already exists. Existing DLLs: #{PP.pp(@dll.keys, "")}" unless not @dll.has_key? dll_name
538
+ if windows_name == nil
539
+ windows_name = dll_name
540
+ end
541
+ @dll[dll_name] = DLL.new(windows_name, @client, @win_consts)
542
+ end
543
+
544
+ # we fake having members like user32 and kernel32.
545
+ # reason is that
546
+ # ...user32.MessageBoxW()
547
+ # is prettier than
548
+ # ...dlls["user32"].functions["MessageBoxW"]()
549
+ def method_missing(dll_symbol, *args)
550
+ dll_name = dll_symbol.to_s
551
+ raise "DLL #{dll_name} not found. Known DLLs: #{PP.pp(@dll.keys, "")}" unless @dll.has_key? dll_name
552
+ return @dll[dll_name]
553
+ end
554
+
555
+ # Give the programmer access to constants
556
+ def const(str)
557
+ return @win_consts.parse(str)
558
+ end
559
+
560
+ # The multi-call shorthand ( ["kernel32", "ExitProcess", [0]] )
561
+ def multi(functions)
562
+ self.multicaller.call(functions)
563
+ end
564
+
565
+ # A easier way to call multiple functions in a single request
566
+ class MultiCaller
567
+
568
+ include DLLHelper
569
+ attr_accessor :parent, :dll, :client
570
+
571
+ def initialize(parent)
572
+ self.parent = parent
573
+ self.dll = parent.dll
574
+ self.client = parent.client
575
+ end
576
+
577
+ def call(functions)
578
+
579
+ request = Packet.create_request('railgun_api_multi')
580
+ function_results = []
581
+ layouts = []
582
+ functions.each do |f|
583
+ dll_name,funcname,args = f
584
+ dll_host = @dll[dll_name]
585
+
586
+ if not dll_host
587
+ raise "DLL #{dll_name} has not been loaded"
588
+ end
589
+
590
+ function = dll_host.functions[funcname]
591
+ if not function
592
+ raise "DLL #{dll_name} function #{funcname} has not been defined"
593
+ end
594
+
595
+ raise "#{function.params.length} arguments expected. #{args.length} arguments provided." unless args.length == function.params.length
596
+ #puts "process_function_call(function.windows_name,#{PP.pp(args, "")})"
597
+
598
+ # We transmit the immediate stack and three heap-buffers:
599
+ # in, inout and out. The reason behind the separation is bandwidth.
600
+ # We don't want to transmit uninitialized data in or no-longer-needed data out.
601
+
602
+ # out-only-buffers that are ONLY transmitted on the way BACK
603
+ out_only_layout = {} # paramName => BufferItem
604
+ out_only_size_bytes = 0
605
+ #puts " assembling out-only buffer"
606
+ function.params.each_with_index do |param_desc, param_idx|
607
+ #puts " processing #{param_desc[1]}"
608
+
609
+ # Special case:
610
+ # The user can choose to supply a Null pointer instead of a buffer
611
+ # in this case we don't need space in any heap buffer
612
+ if param_desc[0][0,1] == 'P' # type is a pointer
613
+ if args[param_idx] == nil
614
+ next
615
+ end
616
+ end
617
+
618
+ # we care only about out-only buffers
619
+ if param_desc[2] == "out"
620
+ raise "error in param #{param_desc[1]}: Out-only buffers must be described by a number indicating their size in bytes " unless args[param_idx].class == Fixnum
621
+ buffer_size = args[param_idx]
622
+ if param_desc[0] == "PDWORD"
623
+ raise "Please pass 4 for 'out' PDWORDS, since they require a buffer of size 4" unless buffer_size == 4
624
+ end
625
+
626
+ out_only_layout[param_desc[1]] = BufferItem.new(param_idx, out_only_size_bytes, buffer_size, param_desc[0])
627
+ out_only_size_bytes += buffer_size
628
+ end
629
+ end
630
+
631
+ tmp = assemble_buffer("in", function, args)
632
+ in_only_layout = tmp[0]
633
+ in_only_buffer = tmp[1]
634
+
635
+ tmp = assemble_buffer("inout", function, args)
636
+ inout_layout = tmp[0]
637
+ inout_buffer = tmp[1]
638
+
639
+
640
+ # now we build the stack
641
+ # every stack dword will be described by two dwords:
642
+ # first dword describes second dword:
643
+ # 0 - literal,
644
+ # 1 = relative to in-only buffer
645
+ # 2 = relative to out-only buffer
646
+ # 3 = relative to inout buffer
647
+
648
+ # (literal numbers and pointers to buffers we have created)
649
+ literal_pairs_blob = ""
650
+ #puts " assembling literal stack"
651
+ function.params.each_with_index do |param_desc, param_idx|
652
+ #puts " processing (#{param_desc[0]}, #{param_desc[1]}, #{param_desc[2]})"
653
+ buffer = nil
654
+ # is it a pointer to a buffer on our stack
655
+ if ["PDWORD", "PWCHAR", "PCHAR", "PBLOB"].include? param_desc[0]
656
+ #puts " pointer"
657
+ if args[param_idx] == nil # null pointer?
658
+ buffer = [0].pack('V') # type: DWORD (so the dll does not rebase it)
659
+ buffer += [0].pack('V') # value: 0
660
+ elsif param_desc[2] == "in"
661
+ buffer = [1].pack('V')
662
+ buffer += [in_only_layout[param_desc[1]].addr].pack('V')
663
+ elsif param_desc[2] == "out"
664
+ buffer = [2].pack('V')
665
+ buffer += [out_only_layout[param_desc[1]].addr].pack('V')
666
+ elsif param_desc[2] == "inout"
667
+ buffer = [3].pack('V')
668
+ buffer += [inout_layout[param_desc[1]].addr].pack('V')
669
+ else
670
+ raise "unexpected direction"
671
+ end
672
+ else
673
+ #puts " not a pointer"
674
+ # it's not a pointer
675
+ buffer = [0].pack('V')
676
+ case param_desc[0]
677
+ when "DWORD"
678
+ dw = param_to_dword(args[param_idx])
679
+ buffer += [dw].pack('V')
680
+ when "WORD"
681
+ dw = param_to_dword(args[param_idx])
682
+ buffer += [dw % 65536].pack('V')
683
+ when "BYTE"
684
+ dw = param_to_dword(args[param_idx])
685
+ buffer += [dw % 256].pack('V')
686
+ when "BOOL"
687
+ case args[param_idx]
688
+ when true
689
+ buffer += [1].pack('V')
690
+ when false
691
+ buffer += [0].pack('V')
692
+ else
693
+ raise "param #{param_desc[1]}: true or false expected"
694
+ end
695
+ else
696
+ raise "unexpected type for param #{param_desc[1]}"
697
+ end
698
+ end
699
+
700
+ #puts " adding pair to blob"
701
+ literal_pairs_blob += buffer
702
+ #puts " buffer size %X" % buffer.length
703
+ #puts " blob size so far: %X" % literal_pairs_blob.length
704
+ end
705
+
706
+ #puts "\n\nsending Stuff to meterpreter"
707
+
708
+ group = Rex::Post::Meterpreter::GroupTlv.new(TLV_TYPE_RAILGUN_MULTI_GROUP)
709
+ group.add_tlv(TLV_TYPE_RAILGUN_SIZE_OUT, out_only_size_bytes)
710
+ group.add_tlv(TLV_TYPE_RAILGUN_STACKBLOB, literal_pairs_blob)
711
+ group.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_IN, in_only_buffer)
712
+ group.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT, inout_buffer)
713
+ group.add_tlv(TLV_TYPE_RAILGUN_DLLNAME, dll_name )
714
+ group.add_tlv(TLV_TYPE_RAILGUN_FUNCNAME, function.windows_name)
715
+ request.tlvs << group
716
+
717
+ layouts << [inout_layout, out_only_layout]
718
+ end
719
+
720
+ call_results = []
721
+ res = @client.send_request(request)
722
+ res.each(TLV_TYPE_RAILGUN_MULTI_GROUP) do |val|
723
+ call_results << val
724
+ end
725
+
726
+ functions.each do |f|
727
+ dll_name,funcname,args = f
728
+ dll_host = @dll[dll_name]
729
+ function = dll_host.functions[funcname]
730
+ response = call_results.shift
731
+ inout_layout, out_only_layout = layouts.shift
732
+
733
+ rec_inout_buffers = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT)
734
+ rec_out_only_buffers = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT)
735
+ rec_return_value = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_RET)
736
+ rec_last_error = response.get_tlv_value(TLV_TYPE_RAILGUN_BACK_ERR)
737
+
738
+ # The hash the function returns
739
+ return_hash={"GetLastError" => rec_last_error}
740
+
741
+ #process return value
742
+ case function.return_type
743
+ when "DWORD"
744
+ return_hash["return"] = rec_return_value
745
+ when "WORD"
746
+ return_hash["return"] = rec_return_value % 65536
747
+ when "BYTE"
748
+ return_hash["return"] = rec_return_value % 256
749
+ when "BOOL"
750
+ return_hash["return"] = (rec_return_value != 0)
751
+ when "VOID"
752
+ return_hash["return"] = nil
753
+ else
754
+ raise "unexpected return type: #{function.return_type}"
755
+ end
756
+ #puts return_hash
757
+ #puts "out_only_layout:"
758
+ #puts out_only_layout
759
+
760
+
761
+ # process out-only buffers
762
+ #puts "processing out-only buffers:"
763
+ out_only_layout.each_pair do |param_name, buffer_item|
764
+ #puts " #{param_name}"
765
+ buffer = rec_out_only_buffers[buffer_item.addr, buffer_item.length_in_bytes]
766
+ case buffer_item.datatype
767
+ when "PDWORD"
768
+ return_hash[param_name] = buffer.unpack('V')[0]
769
+ when "PCHAR"
770
+ return_hash[param_name] = asciiz_to_str(buffer)
771
+ when "PWCHAR"
772
+ return_hash[param_name] = uniz_to_str(buffer)
773
+ when "PBLOB"
774
+ return_hash[param_name] = buffer
775
+ else
776
+ raise "unexpected type in out-only buffer of #{param_name}: #{buffer_item.datatype}"
777
+ end
778
+ end
779
+ #puts return_hash
780
+
781
+ # process in-out buffers
782
+ #puts "processing in-out buffers:"
783
+ inout_layout.each_pair do |param_name, buffer_item|
784
+ #puts " #{param_name}"
785
+ buffer = rec_inout_buffers[buffer_item.addr, buffer_item.length_in_bytes]
786
+ case buffer_item.datatype
787
+ when "PDWORD"
788
+ return_hash[param_name] = buffer.unpack('V')[0]
789
+ when "PCHAR"
790
+ return_hash[param_name] = asciiz_to_str(buffer)
791
+ when "PWCHAR"
792
+ return_hash[param_name] = uniz_to_str(buffer)
793
+ when "PBLOB"
794
+ return_hash[param_name] = buffer
795
+ else
796
+ raise "unexpected type in in-out-buffer of #{param_name}: #{buffer_item.datatype}"
797
+ end
798
+ end
799
+ #puts return_hash
800
+ #puts "finished"
801
+
802
+ function_results << return_hash
803
+ end
804
+ function_results
805
+ end
806
+ # process_multi_function_call
807
+ end # MultiCall
808
+ end
809
+
810
+ end
811
+ end
812
+ end
813
+ end
814
+ end
815
+