# frozen_string_literal: true # # ronin-post_ex - a Ruby API for Post-Exploitation. # # Copyright (c) 2007-2023 Hal Brodigan (postmodern.mod3 at gmail.com) # # ronin-post_ex is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # ronin-post_ex is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with ronin-post_ex. If not, see . # require 'ronin/post_ex/resource' require 'ronin/post_ex/cli/shell_shell' require 'date' module Ronin module PostEx class System < Resource # # Provides access to a system's shell and executing shell commands. # # ## Supported API Methods # # * `shell_exec(command : String) -> String` # class Shell < Resource # Persistent environment variables for the shell. # # @return {Hash{String => String}] attr_reader :env # # Initializes the Shell resource. # # @param [#shell_exec] session # The {#session} object that defines the `shell_exec` method. # def initialize(session) super(session) @cwd = nil @env = {} end # # Executes a shell command and returns it's output. # # @param [String] command # The shell command to execute. # # @param [Array] arguments # Additional arguments for the shell command. # # @example # system.shell.run 'ls' # # @example with additional arguments: # system.shell.run 'ls', '-l' # # @return [String] # The output of the shell command. # def run(command,*arguments) unless arguments.empty? command = "#{command} #{Shellwords.shelljoin(arguments)}" end unless @env.empty? env_vars = @env.map { |key,value| "#{key}=#{Shellwords.shellescape(value)}" }.join(' ') command = "env #{env_vars} #{command}" end if @cwd command = "cd #{@cwd} && #{command}" end return @session.shell_exec(command) end resource_method :run, [:shell_exec] # # Executes a command and prints the resulting output. # # @param [String] command # The program name or path to execute. # # @param [Array] arguments # Additional arguments for the shell command. # # @return [nil] # def system(command,*arguments) puts(run(command,*arguments)) end resource_method :system, [:shell_exec] # # Changes the current working directory in the shell. # # @param [String] path # The path for the new current working directory. # # @return [String] # Any error messages. # def cd(path) @pwd = File.expand_path(path,pwd) end resource_method :cd, [:shell_exec] # # Gets the current working directory. # # @return [String] # The path of the current working directory. # def pwd @pwd ||= run('pwd').chomp end resource_method :pwd, [:shell_exec] # # Lists the files or directories. # # @param [Array] arguments # Arguments to pass to the `ls` command. # # @return [String] # The full output of the command. # # @see #exec # def ls(*arguments) run('ls',*arguments) end resource_method :ls, [:shell_exec] # # Lists all files or directories. # # @param [Array] arguments # Additional arguments to pass to the `ls -a` command. # # @return [String] # The full output of the command. # # @see #exec # def ls_a(*arguments) run('ls','-a',*arguments) end resource_method :ls_a, [:shell_exec] # # Lists information about files or directories. # # @param [Array] arguments # Additional arguments to pass to the `ls -l` command. # # @return [String] # The full output of the command. # # @see #exec # def ls_l(*arguments) run('ls','-l',*arguments) end resource_method :ls_l, [:shell_exec] # # Lists information about all files or directories. # # @param [Array] arguments # Additional arguments to pass to the `ls -la` command. # # @return [String] # The full output of the command. # # @see #exec # def ls_la(*arguments) run('ls','-la',*arguments) end resource_method :ls_la, [:shell_exec] alias ls_al ls_la # # Searches for files or directories. # # @param [Array] arguments # Additional arguments to pass to the `find` command. # # @yield [path] # If a block is given, it will be passed each path found. # # @yieldparam [String] path # A path found by the `find` command. # # @return [Array, nil] # If no block is given, all found paths will be returned. # def find(*arguments,&block) if block run('find',*arguments).each_line(chomp: true,&block) else enum_for(__method__,*arguments).to_a end end resource_method :find, [:shell_exec] # # Determines the format of a file. # # @param [Array] arguments # Additional arguments to pass to the `file` command. # # @return [String] # The output of the `file` command. # # @example # system.shell.file('data.db') # # => "data.db: SQLite 3.x database" # def file(*arguments) run('file',*arguments) end resource_method :file, [:shell_exec] # # Finds a program available to the shell. # # @param [Array] arguments # Additional arguments to pass to the `which` command. # # @return [String] # The output from the `which` command. # def which(*arguments) run('which',*arguments) end resource_method :which, [:shell_exec] # # Reads the contents of one or more files. # # @param [Array] arguments # Additional arguments to pass to the `cat` command. # # @return [String] # The full output of the command. # # @see #exec # def cat(*arguments) run('cat',*arguments) end resource_method :cat, [:shell_exec] # # Reads the first `n` lines of one or more files. # # @param [Array] arguments # Additional arguments to pass to the `head` command. # # @return [String] # The full output of the command. # # @see #exec # def head(*arguments) run('head',*arguments) end resource_method :head, [:shell_exec] # # Reads the first `n` lines of one or more files. # # @param [Integer] lines # The number of lines to read from one or more files. # # @param [Array] arguments # Additional arguments to pass to the `head` command. # # @return [String] # The full output of the command. # # @see #exec # def head_n(lines,*arguments) head('-n',lines,*arguments) end resource_method :head_n, [:shell_exec] # # Reads the last `n` lines of one or more files. # # @param [Array] arguments # Additional arguments to pass to the `tail` command. # # @return [String] # The full output of the command. # # @see #exec # def tail(*arguments) run('tail',*arguments) end resource_method :tail, [:shell_exec] # # Reads the last `n` lines of one or more files. # # @param [Integer] lines # The number of lines to read from one or more files. # # @param [Array] arguments # Additional arguments to pass to the `tail` command. # # @return [String] # The full output of the command. # # @see #exec # def tail_n(lines,*arguments) tail('-n',lines,*arguments) end resource_method :tail_n, [:shell_exec] # # Searches one or more files for a given pattern. # # @param [Array] arguments # Additional arguments to pass to the `grep` command. # # @yield [path, line] # If a block is given, it will be passed the paths and lines # within files that matched the given pattern. # # @yieldparam [String] path # The path of a file that contains matching lines. # # @yieldparam [String] line # A line that matches the given pattern. # # @return [Array, nil] # If no block is given, all matching paths and lines will be # returned. # def grep(*arguments) if block_given? run('grep',*arguments).each_line(chomp: true) do |line| yield(*line.split(':',2)) end else enum_for(__method__,*arguments).to_a end end resource_method :grep, [:shell_exec] # # Runs `grep -E`. # # @param [Array] arguments # Additional arguments for the `grep` command. # # @return [Array, nil] # If no block is given, all matching paths and lines will be # returned. # # @see #grep # def egrep(*arguments,&block) grep('-E',*arguments,&block) end resource_method :egrep, [:shell_exec] # # Runs `grep -F`. # # @param [Array] arguments # Additional arguments for the `grep` command. # # @return [Array, nil] # If no block is given, all matching paths and lines will be # returned. # # @see #grep # def fgrep(*arguments,&block) grep('-F',*arguments,&block) end resource_method :fgrep, [:shell_exec] # # Touches a file. # # @param [Array] arguments # Additional arguments to pass to the `touch` command. # # @return [String] # Any error messages returned by the `touch` command. # def touch(*arguments) run('touch',*arguments) end resource_method :touch, [:shell_exec] # # Creates a tempfile. # # @param [Array] arguments # Additional arguments to pass to `mktemp`. # # @return [String] # The path of the new tempfile. # def mktemp(*arguments) run('mktemp',*arguments).chomp end resource_method :mktemp, [:shell_exec] # # Creates a tempdir. # # @param [Array] arguments # Additional arguments to pass to `mktemp`. # # @return [String] # The path of the new tempdir. # def mktempdir(*arguments) mktemp('-d',*arguments) end resource_method :mktempdir, [:shell_exec] # # Creates a new directory. # # @param [Array] arguments # Additional arguments to pass to the `mkdir` command. # # @return [String] # Any error messages returned by the `mkdir` command. # def mkdir(*arguments) run('mkdir',*arguments) end resource_method :mkdir, [:shell_exec] # # Copies one or more files or directories. # # @param [Array] arguments # Additional arguments to pass to the `cp` command. # # @return [String] # Any error messages returned by the `cp` command. # def cp(*arguments) run('cp',*arguments) end resource_method :cp, [:shell_exec] # # Runs `cp -r`. # # @param [Array] arguments # Additional arguments for the `cp` command. # # @return [String] # Any error messages returned by the `cp` command. # # @see #cp # def cp_r(*arguments) cp('-r',*arguments) end resource_method :cp_r, [:shell_exec] # # Runs `cp -a`. # # @param [Array] arguments # Additional arguments for the `cp` command. # # @return [String] # Any error messages returned by the `cp` command. # # @see #cp # def cp_a(*arguments) cp('-a',*arguments) end resource_method :cp_a, [:shell_exec] # # Runs `rsync`. # # @param [Array] arguments # Additional arguments to pass to the `rsync` command. # # @return [String] # The full output of the command. # # @see #exec # def rsync(*arguments) run('rsync',*arguments) end resource_method :rsync, [:shell_exec] # # Runs `rsync -a`. # # @param [Array] arguments # Additional arguments for the `rsync` command. # # @return [String] # The full output of the command. # # @see #rsync # def rsync_a(*arguments) rsync('-a',*arguments) end resource_method :rsync_a, [:shell_exec] # # Runs `wget`. # # @param [Array] arguments # Additional arguments to pass to the `rsync` command. # # @return [String] # The full output of the command. # # @see #exec # def wget(*arguments) run('wget','-q',*arguments) end resource_method :wget, [:shell_exec] # # Runs `wget -O`. # # @param [String] path # The path that `wget` will write to. # # @param [Array] arguments # Additional arguments for the `wget` command. # # @return [String] # The full output of the command. # # @see #wget # def wget_out(path,*arguments) wget('-O',path,*arguments) end resource_method :wget_out, [:shell_exec] # # Runs the `curl`. # # @param [Array] arguments # Additional arguments to pass to the `curl` command. # # @return [String] # The full output of the command. # # @see #exec # def curl(*arguments) run('curl','-s',*arguments) end resource_method :curl, [:shell_exec] # # Runs `curl -O`. # # @param [String] path # The path that `curl` will write to. # # @param [Array] arguments # Additional arguments for the `curl` command. # # @return [String] # The full output of the command. # # @see #curl # def curl_out(path,*arguments) curl('-O',path,*arguments) end resource_method :curl_out, [:shell_exec] # # Removes a directory. # # @param [Array] arguments # Additional arguments to pass to the `rmdir` command. # # @return [String] # Any error messages returned by the `rmdir` command. # def rmdir(*arguments) run('rmdir',*arguments) end resource_method :rmdir, [:shell_exec] # # Removes one or more files or directories. # # @param [Array] arguments # Additional arguments to pass to the `rm` command. # # @yield [line] # If a block is given, it will be passed each line of output # from the command. # # @yieldparam [String] line # A line of output from the command. # # @return [String] # The full output of the command. # # @see #exec # def rm(*arguments) run('rm',*arguments) end resource_method :rm, [:shell_exec] # # Runs `rm -r`. # # @param [Array] arguments # Additional arguments for the `rm` command. # # @return [String] # The full output of the command. # # @see #rm # def rm_r(*arguments) rm('-r',*arguments) end resource_method :rm_r, [:shell_exec] # # Runs `rm -rf`. # # @param [Array] arguments # Additional arguments for the `rm` command. # # @return [String] # The full output of the command. # # @see #rm # def rm_rf(*arguments) rm('-rf',*arguments) end resource_method :rm_rf, [:shell_exec] # # Gets the current time from the shell. # # @return [Time] # The current time returned by the shell. # def time Time.parse(run('date').chomp) end resource_method :time, [:shell_exec] # # Gets the current time and date from the shell. # # @return [Date] # The current data returned by the shell. # def date time.to_date end resource_method :date, [:shell_exec] # # The ID information of the current user. # # @return [Hash{Symbol => String}] # The ID information returned by the `id` command. # def id hash = {} run('id').split.each do |name_value| name, value = name_value.split('=',2) hash[name.to_sym] = value end return hash end resource_method :id, [:shell_exec] # # The UID of the current user. # # @return [Integer] # The UID of the current user. # def uid run('id','-u').to_i end resource_method :uid, [:shell_exec] # # The GID of the current user. # # @return [Integer] # The GID of the current user. # def gid run('id','-g').to_i end resource_method :gid, [:shell_exec] # # The name of the current user. # # @param [Array] arguments # Additional arguments to pass to the `whoami` command. # # @return [String] # The name of the current user returned by the `whoami` command. # def whoami(*arguments) run('whoami',*arguments).chomp end resource_method :whoami, [:shell_exec] # # Shows who is currently logged in. # # @param [Array] arguments # Additional arguments to pass to the `who` command. # # @return [String] # The full output of the command. # # @see #exec # def who(*arguments) run('who',*arguments) end resource_method :who, [:shell_exec] # # Similar to {#who} but runs the `w` command. # # @param [Array] arguments # Additional arguments to pass to the `w` command. # # @return [String] # The full output of the command. # # @see #exec # def w(*arguments) run('w',*arguments) end resource_method :w, [:shell_exec] # # Shows when users last logged in. # # @param [Array] arguments # Additional arguments to pass to the `lastlog` command. # # @return [String] # The full output of the command. # # @see #exec # def lastlog(*arguments) run('lastlog',*arguments) end resource_method :lastlog, [:shell_exec] # # Shows login failures. # # @param [Array] arguments # Additional arguments to pass to the `faillog` command. # # @yield [line] # If a block is given, it will be passed each line of output # from the command. # # @yieldparam [String] line # A line of output from the command. # # @return [String] # The full output of the command. # # @see #exec # def faillog(*arguments) run('faillog',*arguments) end resource_method :faillog, [:shell_exec] # # Shows the current running processes. # # @param [Array] arguments # Additional arguments to pass to the `ps` command. # # @return [String] # The full output of the command. # # @see #exec # def ps(*arguments) run('ps',*arguments) end resource_method :ps, [:shell_exec] # # Runs `ps aux`. # # @param [Array] arguments # Additional arguments for the `ps` command. # # @return [String] # The full output of the command. # # @see #ps # def ps_aux(*arguments) ps('aux',*arguments) end resource_method :ps_aux, [:shell_exec] # # Kills a current running process. # # @param [Array] arguments # Additional arguments to pass to the `kill` command. # # @return [String] # Output from the `kill` command. # def kill(*arguments) run('kill',*arguments) end resource_method :kill, [:shell_exec] # # Shows information about network interfaces. # # @param [Array] arguments # Additional arguments to pass to the `ifconfig` command. # # @return [String] # The full output of the command. # # @see #exec # def ifconfig(*arguments) run('ifconfig',*arguments) end resource_method :ifconfig, [:shell_exec] # # Shows network connections. # # @param [Array] arguments # Additional arguments to pass to the `netstat` command. # # @return [String] # The full output of the command. # # @see #exec # def netstat(*arguments) run('netstat',*arguments) end resource_method :netstat, [:shell_exec] # # Runs `netstat -anp`. # # @param [Array] arguments # Additional arguments for the `netstat` command. # # @return [String] # The full output of the command. # # @see #netstat # def netstat_anp(*arguments) netstat('-anp',*arguments) end resource_method :netstat_anp, [:shell_exec] # # Pings an IP address. # # @param [Array] arguments # Additional arguments to pass to the `ping` command. # # @yield [line] # If a block is given, it will be passed each line of output # from the command. # # @yieldparam [String] line # A line of output from the command. # # @return [String] # The full output of the command. # # @see #exec # def ping(*arguments) run('ping',*arguments) end resource_method :ping, [:shell_exec] # # Compiles some C source-code with `gcc`. # # @param [Array] arguments # Additional arguments to pass to the `gcc` command. # # @return [String] # The full output of the command. # # @see #exec # def gcc(*arguments) run('gcc',*arguments) end resource_method :gcc, [:shell_exec] # # Compiles some C source-code with `cc`. # # @param [Array] arguments # Additional arguments to pass to the `cc` command. # # @return [String] # The full output of the command. # # @see #exec # def cc(*arguments) run('cc',*arguments) end resource_method :cc, [:shell_exec] # # Runs a PERL script. # # @param [Array] arguments # Additional arguments to pass to the `perl` command. # # @return [String] # The full output of the command. # # @see #exec # def perl(*arguments) run('perl',*arguments) end resource_method :perl, [:shell_exec] # # Runs a Python script. # # @param [Array] arguments # Additional arguments to pass to the `python` command. # # @return [String] # The full output of the command. # # @see #exec # def python(*arguments) run('python',*arguments) end resource_method :python, [:shell_exec] # # Runs a Ruby script. # # @param [Array] arguments # Additional arguments to pass to the `ruby` command. # # @return [String] # The full output of the command. # # @see #exec # def ruby(*arguments) run('ruby',*arguments) end resource_method :ruby, [:shell_exec] # # Starts an interactive Shell console. # def interact CLI::ShellShell.start(self) end end end end end