Module: PWN::Plugins::Log
- Defined in:
- lib/pwn/plugins/log.rb
Overview
This plugin is used to instantiate a PWN logger with a custom message format
Constant Summary collapse
- TRACE_SKIP_METHODS =
%i[ authors help to_s inspect class object_id hash eql? == equal? ! method public_send send __send__ instance_eval class_eval public_class_method private_class_method ].freeze
- TRACE_SKIP_PREFIXES =
%w[ PWN::Plugins::Log PWN::Plugins::REPL PWN::Banner ].freeze
- DEFAULT_TRACE_PREFIXES =
%w[ PWN::AI PWN::Memory PWN::Sessions PWN::Config PWN::Cron PWN::Plugins ].freeze
- SECRET_KEY_RX =
/password|passwd|secret|token|api[_-]?key|authorization|bearer|cookie|session[_-]?id|private[_-]?key|decryptor|credential|ssh[_-]?key|client[_-]?secret|refresh[_-]?token|access[_-]?token|id[_-]?token|vault|csrf/i- SECRET_VALUE_RX =
%r{ -----BEGIN\ [A-Z ]*PRIVATE\ KEY----- | Bearer\s+[A-Za-z0-9\-._~+/]+=* | \beyJ[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+ | \b(?:sk|rk|pk|xai|xox[baprs]|ghp|gho|ghu|ghs|ghr|glpat|AKIA|ASIA|ya29)[-_][A-Za-z0-9\-_]{16,} | \b(?:api[_-]?key|token|secret|password|passwd)\s*[:=]\s*\S+ }ix- DEBUG_VALUE_MAX =
240- DEBUG_ARGS_MAX =
1_800- DEBUG_LOG_MAX =
Open /tmp/pwn-ai-DEBUG-TIMESTAMP.log, tee the same lines to the TUI (opts), and TracePoint PWN modules that process a pwn-ai request.
1_024_000
Class Method Summary collapse
-
.append(opts = {}) ⇒ Object
- Supported Method Parameters
PWN::Log.create( ).
-
.authors ⇒ Object
- Author(s)
0day Inc.
- .debug_enabled?(opts = {}) ⇒ Boolean
- .debug_log_path(opts = {}) ⇒ Object
-
.help ⇒ Object
Display Usage for this Module.
- .loud_tui!(opts = {}) ⇒ Object
-
.progress(opts = {}) ⇒ Object
One progress line to the debug file and the TUI tee (same payload).
- .quiet_tui!(opts = {}) ⇒ Object
- .start_debug(opts = {}) ⇒ Object
- .start_trace!(opts = {}) ⇒ Object
- .stop_debug(opts = {}) ⇒ Object
- .stop_trace!(opts = {}) ⇒ Object
Class Method Details
.append(opts = {}) ⇒ Object
- Supported Method Parameters
PWN::Log.create( )
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 |
# File 'lib/pwn/plugins/log.rb', line 44 public_class_method def self.append(opts = {}) level = opts[:level].to_s.downcase.to_sym msg = opts[:msg] which_self = opts[:which_self].to_s driver_name = File.basename($PROGRAM_NAME) # Only attempt to exit gracefully if level == :error exit_gracefully = false # Define Date / Time Format datetime_str = '%Y-%m-%d %H:%M:%S.%N%z' # Always append to log file if level == :learning session = SecureRandom.hex log_file_path = "/tmp/pwn-ai-#{session}.json" if level == :learning log_file = File.open(log_file_path, 'w') else log_file_path = '/tmp/pwn.log' log_file = File.open(log_file_path, 'a') end # Leave 10 "old" log files where # each file is ~ 1,024,000 bytes logger = Logger.new( log_file, 10, 1_024_000 ) logger.datetime_format = datetime_str case level when :debug logger.level = Logger::DEBUG when :error logger.level = Logger::ERROR exit_gracefully = true unless driver_name == 'pwn' puts "\nERROR: See #{log_file_path} for more details." if driver_name == 'pwn' when :fatal logger.level = Logger::FATAL puts "\n FATAL ERROR: See #{log_file_path} for more details." if driver_name == 'pwn' when :info, :learning logger.level = Logger::INFO when :unknown logger.level = Logger::UNKNOWN when :warn logger.level = Logger::WARN else level_error = "ERROR: Invalid log level. Valid options are:\n" level_error += ":debug\n:error\n:fatal\n:info\n:learning\n:unknown\n:warn\n" raise level_error end if level == :learning log_event = msg logger.formatter = proc do |_severity, _datetime, _progname, learning_arr| JSON.pretty_generate( learning_data: learning_arr ) end else log_event = "driver: #{driver_name}" if msg.instance_of?(Interrupt) logger.level = Logger::WARN if driver_name == 'pwn' log_event += ' => CTRL+C Detected.' else log_event += ' => CTRL+C Detected...Exiting Session.' exit_gracefully = true unless driver_name == 'pwn' end else log_event += " => #{msg}" if msg.respond_to?('backtrace') && !msg.instance_of?(Errno::ECONNRESET) log_event += " => \n\t#{msg.backtrace.join("\n\t")}" log_event += "\n\n\n" end end end logger.add(logger.level, log_event, which_self) rescue Interrupt puts "\n#{self}.#{__method__} => Goodbye." rescue StandardError => e raise e end |
.authors ⇒ Object
- Author(s)
0day Inc. support@0dayinc.com
399 400 401 402 403 |
# File 'lib/pwn/plugins/log.rb', line 399 public_class_method def self. "AUTHOR(S): 0day Inc. <support@0dayinc.com> " end |
.debug_enabled?(opts = {}) ⇒ Boolean
132 133 134 135 136 |
# File 'lib/pwn/plugins/log.rb', line 132 public_class_method def self.debug_enabled?(opts = {}) return @debug_enabled == true if opts.is_a?(Hash) @debug_enabled == true end |
.debug_log_path(opts = {}) ⇒ Object
138 139 140 141 142 |
# File 'lib/pwn/plugins/log.rb', line 138 public_class_method def self.debug_log_path(opts = {}) return @debug_path if opts.is_a?(Hash) @debug_path end |
.help ⇒ Object
Display Usage for this Module
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 |
# File 'lib/pwn/plugins/log.rb', line 407 public_class_method def self.help puts "USAGE: logger = #{self}.append( level: 'required - log verbosity :debug|:error|:fatal|:info|:learning|:unknown|:warn', msg: 'required - message to log', which_self: 'required - pass in self object from module calling #{self}' ) path = #{self}.start_debug( tee: $stdout, path: 'optional - defaults to /tmp/pwn-ai-DEBUG-TIMESTAMP.log' ) #{self}.progress(msg: 'stage', which_self: self) #{self}.stop_debug " end |
.loud_tui!(opts = {}) ⇒ Object
222 223 224 225 226 |
# File 'lib/pwn/plugins/log.rb', line 222 public_class_method def self.loud_tui!(opts = {}) return if opts[:skip] @debug_tui_quiet = false end |
.progress(opts = {}) ⇒ Object
One progress line to the debug file and the TUI tee (same payload).
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/pwn/plugins/log.rb', line 229 public_class_method def self.progress(opts = {}) return false unless debug_enabled? return false if Thread.current[:pwn_log_progress] Thread.current[:pwn_log_progress] = true msg = sanitize_debug_text(text: opts[:msg].to_s) which = opts[:which_self] || self line = format_progress(msg: msg, which_self: which) begin @debug_file&.puts(line) @debug_file&.flush roll_debug_log! rescue StandardError nil end tee = opts.key?(:tee) ? opts[:tee] : @debug_tee if !@debug_tui_quiet && tee.respond_to?(:puts) begin tee.puts(color_progress(line: line)) rescue StandardError nil end end true ensure Thread.current[:pwn_log_progress] = false end |
.quiet_tui!(opts = {}) ⇒ Object
216 217 218 219 220 |
# File 'lib/pwn/plugins/log.rb', line 216 public_class_method def self.quiet_tui!(opts = {}) return if opts[:skip] @debug_tui_quiet = true end |
.start_debug(opts = {}) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/pwn/plugins/log.rb', line 148 public_class_method def self.start_debug(opts = {}) return @debug_path if debug_enabled? && opts.is_a?(Hash) ts = Time.now.strftime('%Y%m%d-%H%M%S') path = opts[:path].to_s path = "/tmp/pwn-ai-DEBUG-#{ts}.1.log" if path.empty? stem, idx = debug_path_parts(path: path) path = "#{stem}.#{idx}.log" FileUtils.mkdir_p(File.dirname(path)) io = File.open(path, 'a') io.sync = true @debug_file = io @debug_path = path @debug_stem = stem @debug_index = idx @debug_tee = opts[:tee] @debug_tui_quiet = false @debug_enabled = true start_trace!(prefixes: opts[:prefixes]) unless opts[:trace] == false progress(msg: "debug session start path=#{path}", which_self: self) path end |
.start_trace!(opts = {}) ⇒ Object
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
# File 'lib/pwn/plugins/log.rb', line 370 public_class_method def self.start_trace!(opts = {}) return @debug_tp if @debug_tp && opts.is_a?(Hash) prefixes = Array(opts[:prefixes] || DEFAULT_TRACE_PREFIXES).map(&:to_s) prefixes = DEFAULT_TRACE_PREFIXES if prefixes.empty? @debug_tp = TracePoint.new(:call) do |tp| next unless debug_enabled? next unless traceable?(tp: tp, prefixes: prefixes) progress( msg: format_trace_call(tp: tp), which_self: '' ) rescue StandardError nil end @debug_tp.enable @debug_tp end |
.stop_debug(opts = {}) ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/pwn/plugins/log.rb', line 171 public_class_method def self.stop_debug(opts = {}) reason = opts[:reason].to_s if opts.is_a?(Hash) if debug_enabled? tail = reason.to_s.empty? ? 'debug session stop' : "debug session stop reason=#{reason}" progress(msg: tail, which_self: self) end stop_trace! begin @debug_file&.close unless @debug_file.nil? || @debug_file.closed? rescue StandardError nil end path = @debug_path @debug_file = nil @debug_path = nil @debug_stem = nil @debug_index = nil @debug_tee = nil @debug_tui_quiet = false @debug_enabled = false path end |
.stop_trace!(opts = {}) ⇒ Object
390 391 392 393 394 395 |
# File 'lib/pwn/plugins/log.rb', line 390 public_class_method def self.stop_trace!(opts = {}) return if opts[:skip] @debug_tp&.disable @debug_tp = nil end |