Module: PWN::Plugins::MonkeyPatch

Defined in:
lib/pwn/plugins/monkey_patch.rb

Overview

This module provides the abilty to centralize monkey patches used in PWN

Class Method Summary collapse

Class Method Details

.authorsObject

Author(s)

0day Inc. <[email protected]>



147
148
149
150
151
# File 'lib/pwn/plugins/monkey_patch.rb', line 147

public_class_method def self.authors
  "AUTHOR(S):
    0day Inc. <[email protected]>
  "
end

.helpObject

Display Usage for this Module



155
156
157
158
159
160
161
# File 'lib/pwn/plugins/monkey_patch.rb', line 155

public_class_method def self.help
  puts "USAGE:
    #{self}.pry

    #{self}.authors
  "
end

.pryObject



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/pwn/plugins/monkey_patch.rb', line 10

def self.pry
  # Overwrite Pry::History.push method in History class
  # to get duplicate history entries in order to properly
  # replay automation in this prototyping driver
  Pry::History.class_eval do
    def push(line)
      return line if line.empty? || invalid_readline_line?(line)

      begin
        last_line = @history[-1]
      rescue IndexError
        last_line = nil
      end

      @history << line
      @history_line_count += 1
      @saver.call(line) if !should_ignore?(line) &&
                           Pry.config.history_save

      line
    end
    alias << push
  end

  Pry.class_eval do
    def handle_line(line, options)
      if line.nil?
        config.control_d_handler.call(self)
        return
      end

      ensure_correct_encoding!(line)
      Pry.history << line unless options[:generated]

      @suppress_output = false
      inject_sticky_locals!
      begin
        # unless process_command_safely(line)
        unless process_command_safely(line) && (
                 line.empty? || @eval_string.empty?
               )
          # @eval_string += "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
          @eval_string += "#{line.chomp}\n"
        end
      rescue Pry::RescuableException => e
        self.last_exception = e
        result = e

        Pry.critical_section do
          show_result(result)
        end
        return
      end

      # This hook is supposed to be executed after each line of ruby code
      # has been read (regardless of whether eval_string is yet a complete expression)
      exec_hook :after_read, eval_string, self

      begin
        complete_expr = true if config.pwn_ai || config.pwn_asm
        complete_expr = Pry::Code.complete_expression?(@eval_string) unless config.pwn_ai || config.pwn_asm
      rescue SyntaxError => e
        output.puts e.message.gsub(/^.*syntax error, */, 'SyntaxError: ')
        reset_eval_string
      end

      if complete_expr
        @suppress_output = true if @eval_string =~ /;\Z/ ||
                                   @eval_string.empty? ||
                                   @eval_string =~ /\A *#.*\n\z/ ||
                                   config.pwn_ai ||
                                   config.pwn_asm

        # A bug in jruby makes java.lang.Exception not rescued by
        # `rescue Pry::RescuableException` clause.
        #
        # * https://github.com/pry/pry/issues/854
        # * https://jira.codehaus.org/browse/JRUBY-7100
        #
        # Until that gets fixed upstream, treat java.lang.Exception
        # as an additional exception to be rescued explicitly.
        #
        # This workaround has a side effect: java exceptions specified
        # in `Pry.config.unrescued_exceptions` are ignored.
        jruby_exceptions = []
        jruby_exceptions << Java::JavaLang::Exception if Pry::Helpers::Platform.jruby?

        begin
          # Reset eval string, in case we're evaluating Ruby that does something
          # like open a nested REPL on this instance.
          eval_string = @eval_string
          reset_eval_string

          result = evaluate_ruby(eval_string) unless config.pwn_ai ||
                                                     config.pwn_asm

          result = eval_string if config.pwn_ai ||
                                  config.pwn_asm
        rescue Pry::RescuableException, *jruby_exceptions => e
          # Eliminate following warning:
          # warning: singleton on non-persistent Java type X
          # (http://wiki.jruby.org/Persistence)
          e.class.__persistent__ = true if Pry::Helpers::Platform.jruby? && e.class.respond_to?('__persistent__')
          self.last_exception = e
          result = e
        end

        Pry.critical_section do
          show_result(result)
        end
      end

      throw(:breakout) if current_binding.nil?
    end

    # Ensure the return value in pwn_ai mode reflects the input
    def evaluate_ruby(code)
      # if config.pwn_ai || config.pwn_asm
      #   result = message = code.to_s
      #   return
      # end
      inject_sticky_locals!
      exec_hook :before_eval, code, self

      result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
      set_last_result(result, code)
    ensure
      update_input_history(code)
      exec_hook :after_eval, result, self
    end
  end
rescue StandardError => e
  raise e
end