Module: Msf::Post::File

Instance Method Summary collapse

Instance Method Details

#append_file(file_name, data) ⇒ Object

Platform-agnostic file append. Appends given object content to a remote file. Returns Boolean true if successful

NOTE: *This is not binary-safe on Windows shell sessions!*


267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/msf/core/post/file.rb', line 267

def append_file(file_name, data)
  if session.type == "meterpreter"
    fd = session.fs.file.new(file_name, "ab")
    fd.write(data)
    fd.close
  elsif session.respond_to? :shell_command_token
    if session.platform =~ /win/
      session.shell_command_token("<nul set /p=\"#{data}\" >> \"#{file_name}\"")
    else
      _write_file_unix_shell(file_name, data, true)
    end
  end
  return true
end

#cd(path) ⇒ Object

Change directory in the remote session to path


8
9
10
11
12
13
14
15
# File 'lib/msf/core/post/file.rb', line 8

def cd(path)
  if session.type == "meterpreter"
    e_path = session.fs.file.expand_path(path) rescue path
    session.fs.dir.chdir(e_path)
  else
    session.shell_command_token("cd '#{path}'")
  end
end

#directory?(path) ⇒ Boolean

See if path exists on the remote system and is a directory

Returns:

  • (Boolean)

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/msf/core/post/file.rb', line 37

def directory?(path)
  if session.type == "meterpreter"
    stat = session.fs.file.stat(path) rescue nil
    return false unless stat
    return stat.directory?
  else
    if session.platform =~ /win/
      f = cmd_exec("cmd.exe /C IF exist \"#{path}\\*\" ( echo true )")
    else
      f = session.shell_command_token("test -d '#{path}' && echo true")
    end

    return false if f.nil? or f.empty?
    return false unless f =~ /true/
    return true
  end
end

#exist?(path) ⇒ Boolean

Check for existence of path on the remote file system

Returns:

  • (Boolean)

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/msf/core/post/file.rb', line 95

def exist?(path)
  if session.type == "meterpreter"
    stat = session.fs.file.stat(path) rescue nil
    return !!(stat)
  else
    if session.platform =~ /win/
       f = cmd_exec("cmd.exe /C IF exist \"#{path}\" ( echo true )")
    else
      f = session.shell_command_token("test -e '#{path}' && echo true")
    end

    return false if f.nil? or f.empty?
    return false unless f =~ /true/
    return true
  end
end

#expand_path(path) ⇒ Object

Expand any environment variables to return the full path specified by path.


58
59
60
61
62
63
64
# File 'lib/msf/core/post/file.rb', line 58

def expand_path(path)
  if session.type == "meterpreter"
    return session.fs.file.expand_path(path)
  else
    return cmd_exec("echo #{path}")
  end
end

#file?(path) ⇒ Boolean Also known as: file_exist?

See if path exists on the remote system and is a regular file

Returns:

  • (Boolean)

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/msf/core/post/file.rb', line 69

def file?(path)
  if session.type == "meterpreter"
    stat = session.fs.file.stat(path) rescue nil
    return false unless stat
    return stat.file?
  else
    if session.platform =~ /win/
      f = cmd_exec("cmd.exe /C IF exist \"#{path}\" ( echo true )")
      if f =~ /true/
        f = cmd_exec("cmd.exe /C IF exist \"#{path}\\\\\" ( echo false ) ELSE ( echo true )")
      end
    else
      f = session.shell_command_token("test -f '#{path}' && echo true")
    end

    return false if f.nil? or f.empty?
    return false unless f =~ /true/
    return true
  end
end

#file_local_digestmd5(file2md5) ⇒ Object

Returns a MD5 checksum of a given local file


145
146
147
148
149
150
151
152
153
154
# File 'lib/msf/core/post/file.rb', line 145

def file_local_digestmd5(file2md5)
  if not ::File.exists?(file2md5)
    raise "File #{file2md5} does not exists!"
  else
    require 'digest/md5'
    chksum = nil
    chksum = Digest::MD5.hexdigest(::File.open(file2md5, "rb") { |f| f.read})
    return chksum
  end
end

#file_local_digestsha1(file2sha1) ⇒ Object

Returns a SHA1 checksum of a given local file


171
172
173
174
175
176
177
178
179
180
# File 'lib/msf/core/post/file.rb', line 171

def file_local_digestsha1(file2sha1)
  if not ::File.exists?(file2sha1)
    raise "File #{file2sha1} does not exists!"
  else
    require 'digest/sha1'
    chksum = nil
    chksum = Digest::SHA1.hexdigest(::File.open(file2sha1, "rb") { |f| f.read})
    return chksum
  end
end

#file_local_digestsha2(file2sha2) ⇒ Object

Returns a SHA256 checksum of a given local file


197
198
199
200
201
202
203
204
205
206
# File 'lib/msf/core/post/file.rb', line 197

def file_local_digestsha2(file2sha2)
  if not ::File.exists?(file2sha2)
    raise "File #{file2sha2} does not exists!"
  else
    require 'digest/sha2'
    chksum = nil
    chksum = Digest::SHA256.hexdigest(::File.open(file2sha2, "rb") { |f| f.read})
    return chksum
  end
end

#file_local_write(file2wrt, data2wrt) ⇒ Object

Writes a given string to a given local file


130
131
132
133
134
135
136
137
138
139
140
# File 'lib/msf/core/post/file.rb', line 130

def file_local_write(file2wrt, data2wrt)
  if not ::File.exists?(file2wrt)
    ::FileUtils.touch(file2wrt)
  end

  output = ::File.open(file2wrt, "a")
  data2wrt.each_line do |d|
    output.puts(d)
  end
  output.close
end

#file_remote_digestmd5(file2md5) ⇒ Object

Returns a MD5 checksum of a given remote file


159
160
161
162
163
164
165
166
# File 'lib/msf/core/post/file.rb', line 159

def file_remote_digestmd5(file2md5)
  data = read_file(file2md5)
  chksum = nil
  if data
    chksum = Digest::MD5.hexdigest(data)
  end
  return chksum
end

#file_remote_digestsha1(file2sha1) ⇒ Object

Returns a SHA1 checksum of a given remote file


185
186
187
188
189
190
191
192
# File 'lib/msf/core/post/file.rb', line 185

def file_remote_digestsha1(file2sha1)
  data = read_file(file2sha1)
  chksum = nil
  if data
    chksum = Digest::SHA1.hexdigest(data)
  end
  return chksum
end

#file_remote_digestsha2(file2sha2) ⇒ Object

Returns a SHA2 checksum of a given remote file


211
212
213
214
215
216
217
218
# File 'lib/msf/core/post/file.rb', line 211

def file_remote_digestsha2(file2sha2)
  data = read_file(file2sha2)
  chksum = nil
  if data
    chksum = Digest::SHA256.hexdigest(data)
  end
  return chksum
end

#file_rm(file) ⇒ Object

Remove a remote file


115
116
117
118
119
120
121
122
123
124
125
# File 'lib/msf/core/post/file.rb', line 115

def file_rm(file)
  if session.type == "meterpreter"
    session.fs.file.rm(file)
  else
    if session.platform =~ /win/
      session.shell_command_token("del \"#{file}\"")
    else
      session.shell_command_token("rm -f '#{file}'")
    end
  end
end

#pwdObject

Returns the current working directory in the remote session


20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/msf/core/post/file.rb', line 20

def pwd
  if session.type == "meterpreter"
    return session.fs.dir.getwd
  else
    if session.platform =~ /win/
      # XXX: %CD% only exists on XP and newer, figure something out for NT4
      # and 2k
      return session.shell_command_token("echo %CD%")
    else
      return session.shell_command_token("pwd")
    end
  end
end

#read_file(file_name) ⇒ Object

Platform-agnostic file read. Returns contents of remote file file_name as a String.


224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/msf/core/post/file.rb', line 224

def read_file(file_name)
  data = nil
  if session.type == "meterpreter"
    data = _read_file_meterpreter(file_name)
  elsif session.type == "shell"
    if session.platform =~ /win/
      data = session.shell_command_token("type \"#{file_name}\"")
    else
      data = session.shell_command_token("cat \'#{file_name}\'")
    end

  end
  data
end

#rename_file(old_file, new_file) ⇒ Object Also known as: move_file, mv_file

Rename a remote file.


310
311
312
313
314
315
316
317
318
319
320
# File 'lib/msf/core/post/file.rb', line 310

def rename_file(old_file, new_file)
  if session.respond_to? :commands and session.commands.include?("stdapi_fs_file_move")
    session.fs.file.mv(old_file, new_file)
  else
      if session.platform =~ /win/
        cmd_exec(%Q|move /y "#{old_file}" "#{new_file}"|)
      else
        cmd_exec(%Q|mv -f "#{old_file}" "#{new_file}"|)
      end
  end
end

#rm_f(*remote_files) ⇒ Object

Delete remote files


293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/msf/core/post/file.rb', line 293

def rm_f(*remote_files)
  remote_files.each do |remote|
    if session.type == "meterpreter"
      session.fs.file.delete(remote)
    else
      if session.platform =~ /win/
        cmd_exec("del /q /f #{remote}")
      else
        cmd_exec("rm -f #{remote}")
      end
    end
  end
end

#upload_file(remote, local) ⇒ Object

Read a local file local and write it as remote on the remote file system


286
287
288
# File 'lib/msf/core/post/file.rb', line 286

def upload_file(remote, local)
  write_file(remote, ::File.read(local))
end

#write_file(file_name, data) ⇒ Object

Platform-agnostic file write. Writes given object content to a remote file. Returns Boolean true if successful

NOTE: *This is not binary-safe on Windows shell sessions!*


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/msf/core/post/file.rb', line 245

def write_file(file_name, data)
  if session.type == "meterpreter"
    fd = session.fs.file.new(file_name, "wb")
    fd.write(data)
    fd.close
  elsif session.respond_to? :shell_command_token
    if session.platform =~ /win/
      session.shell_command_token("echo #{data} > \"#{file_name}\"")
    else
      _write_file_unix_shell(file_name, data)
    end

  end
  return true
end