pwn 0.5.451 → 0.5.453
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +8 -4
- data/Gemfile +4 -9
- data/README.md +3 -3
- data/etc/pwn.yaml.EXAMPLE +34 -33
- data/find_latest_gem_versions_per_Gemfile.sh +3 -0
- data/lib/pwn/ai/grok.rb +20 -38
- data/lib/pwn/ai/introspection.rb +42 -44
- data/lib/pwn/ai/ollama.rb +21 -38
- data/lib/pwn/ai/open_ai.rb +20 -149
- data/lib/pwn/blockchain/btc.rb +4 -4
- data/lib/pwn/config.rb +56 -54
- data/lib/pwn/plugins/assembly.rb +14 -3
- data/lib/pwn/plugins/repl.rb +8 -67
- data/lib/pwn/plugins/transparent_browser.rb +320 -141
- data/lib/pwn/reports/sast.rb +1 -54
- data/lib/pwn/sast/pom_version.rb +8 -14
- data/lib/pwn/sast/test_case_engine.rb +8 -15
- data/lib/pwn/version.rb +1 -1
- data/third_party/pwn_rdoc.jsonl +29 -25
- metadata +35 -7
@@ -1,13 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'diffy'
|
3
4
|
require 'em/pure_ruby'
|
4
5
|
require 'faye/websocket'
|
5
|
-
|
6
|
+
require 'nokogiri'
|
6
7
|
require 'openssl'
|
7
8
|
require 'rest-client'
|
8
9
|
require 'securerandom'
|
10
|
+
require 'selenium/devtools/v140'
|
9
11
|
require 'selenium/webdriver'
|
10
|
-
require 'selenium/devtools'
|
11
12
|
require 'socksify'
|
12
13
|
require 'timeout'
|
13
14
|
require 'watir'
|
@@ -474,6 +475,8 @@ module PWN
|
|
474
475
|
case js
|
475
476
|
when 'clear', 'clear;', 'clear()', 'clear();'
|
476
477
|
script = 'console.clear()'
|
478
|
+
when 'debugger', 'debugger;', 'debugger()', 'debugger();'
|
479
|
+
script = 'debugger'
|
477
480
|
else
|
478
481
|
case return_to.to_s.downcase.to_sym
|
479
482
|
when :stdout
|
@@ -938,205 +941,387 @@ module PWN
|
|
938
941
|
end
|
939
942
|
|
940
943
|
# Supported Method Parameters::
|
941
|
-
# PWN::Plugins::TransparentBrowser.
|
942
|
-
# browser_obj: 'required - browser_obj returned from #open method)'
|
943
|
-
# action: 'optional - action to take :pause|:resume (Defaults to :pause)',
|
944
|
-
# url: 'optional - URL to navigate to after pausing debugger (Defaults to nil)'
|
944
|
+
# current_dom = PWN::Plugins::TransparentBrowser.dom(
|
945
|
+
# browser_obj: 'required - browser_obj returned from #open method)'
|
945
946
|
# )
|
946
947
|
|
947
|
-
public_class_method def self.
|
948
|
+
public_class_method def self.dom(opts = {})
|
948
949
|
browser_obj = opts[:browser_obj]
|
949
|
-
|
950
|
-
verified = verify_devtools_browser(browser_obj: browser_obj, supported: supported)
|
950
|
+
verified = verify_devtools_browser(browser_obj: browser_obj)
|
951
951
|
puts 'This browser is not supported for DevTools operations.' unless verified
|
952
952
|
return unless verified
|
953
953
|
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
case action.to_s.downcase.to_sym
|
958
|
-
when :pause
|
959
|
-
browser_obj[:devtools].send_cmd(
|
960
|
-
'EventBreakpoints.setInstrumentationBreakpoint',
|
961
|
-
eventName: 'scriptFirstStatement'
|
962
|
-
)
|
963
|
-
# browser_obj[:devtools].send_cmd('Debugger.enable')
|
964
|
-
# browser_obj[:devtools].send_cmd(
|
965
|
-
# 'Debugger.setInstrumentationBreakpoint',
|
966
|
-
# instrumentation: 'beforeScriptExecution'
|
967
|
-
# )
|
968
|
-
|
969
|
-
# browser_obj[:devtools].send_cmd(
|
970
|
-
# 'EventBreakpoints.setInstrumentationBreakpoint',
|
971
|
-
# eventName: 'load'
|
972
|
-
# )
|
973
|
-
|
974
|
-
# browser_obj[:devtools].send_cmd(
|
975
|
-
# 'Debugger.setPauseOnExceptions',
|
976
|
-
# state: 'all'
|
977
|
-
# )
|
954
|
+
dom_str = console(browser_obj: browser_obj, js: 'document.documentElement.outerHTML', return_to: :stdout)
|
955
|
+
raise 'DOM capture failed: returned nil or empty string. Check DevTools connection.' if dom_str.nil? || dom_str.strip.empty?
|
978
956
|
|
979
|
-
|
980
|
-
Timeout.timeout(1) do
|
981
|
-
browser_obj[:browser].refresh if url.nil?
|
982
|
-
browser_obj[:browser].goto(url) unless url.nil?
|
983
|
-
end
|
984
|
-
rescue Timeout::Error
|
985
|
-
url
|
986
|
-
end
|
987
|
-
when :resume
|
988
|
-
browser_obj[:devtools].send_cmd(
|
989
|
-
'EventBreakpoints.removeInstrumentationBreakpoint',
|
990
|
-
eventName: 'scriptFirstStatement'
|
991
|
-
)
|
992
|
-
browser_obj[:devtools].send_cmd('Debugger.resume')
|
993
|
-
else
|
994
|
-
raise 'ERROR: action parameter must be :pause or :resume'
|
995
|
-
end
|
957
|
+
Nokogiri::HTML.parse(dom_str)
|
996
958
|
rescue StandardError => e
|
997
959
|
raise e
|
998
960
|
end
|
999
961
|
|
1000
962
|
# Supported Method Parameters::
|
1001
|
-
#
|
963
|
+
# page_state = PWN::Plugins::TransparentBrowser.get_page_state(
|
1002
964
|
# browser_obj: 'required - browser_obj returned from #open method)'
|
1003
965
|
# )
|
1004
966
|
|
1005
|
-
public_class_method def self.
|
967
|
+
public_class_method def self.get_page_state(opts = {})
|
1006
968
|
browser_obj = opts[:browser_obj]
|
1007
|
-
|
1008
|
-
verified = verify_devtools_browser(browser_obj: browser_obj, supported: supported)
|
969
|
+
verified = verify_devtools_browser(browser_obj: browser_obj)
|
1009
970
|
puts 'This browser is not supported for DevTools operations.' unless verified
|
1010
971
|
return unless verified
|
1011
972
|
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
973
|
+
js = <<~JS.strip
|
974
|
+
(function() {
|
975
|
+
try {
|
976
|
+
let ls = {};
|
977
|
+
for (let i = 0; i < localStorage.length; i++) {
|
978
|
+
let key = localStorage.key(i);
|
979
|
+
ls[key] = localStorage.getItem(key);
|
980
|
+
}
|
981
|
+
let ss = {};
|
982
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
983
|
+
let key = sessionStorage.key(i);
|
984
|
+
ss[key] = sessionStorage.getItem(key);
|
985
|
+
}
|
1020
986
|
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
# )
|
987
|
+
let scripts = Array.from(document.scripts).map(s => ({
|
988
|
+
src: s.src,
|
989
|
+
innerHTML: s.innerHTML
|
990
|
+
})).filter(s => s.src || s.innerHTML);
|
1026
991
|
|
1027
|
-
|
1028
|
-
browser_obj = opts[:browser_obj]
|
1029
|
-
supported = %i[chrome headless_chrome]
|
1030
|
-
verified = verify_devtools_browser(browser_obj: browser_obj, supported: supported)
|
1031
|
-
puts 'This browser is not supported for DevTools operations.' unless verified
|
1032
|
-
return unless verified
|
992
|
+
let stylesheets = Array.from(document.querySelectorAll('link[rel="stylesheet"]')).map(l => l.href).filter(h => h);
|
1033
993
|
|
1034
|
-
|
1035
|
-
steps = 1 if steps.zero? || steps.negative?
|
994
|
+
let inline_styles = Array.from(document.querySelectorAll('style')).map(s => s.innerHTML).filter(c => c);
|
1036
995
|
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
996
|
+
let forms = Array.from(document.forms).map(f => ({
|
997
|
+
action: f.action,
|
998
|
+
method: f.method,
|
999
|
+
elements: Array.from(f.elements).map(e => ({
|
1000
|
+
name: e.name,
|
1001
|
+
type: e.type,
|
1002
|
+
value: e.value
|
1003
|
+
}))
|
1004
|
+
}));
|
1042
1005
|
|
1043
|
-
|
1044
|
-
diff_hash[:dom_before_step] = dom_before
|
1006
|
+
let iframes = Array.from(document.querySelectorAll('iframe')).map(i => i.src).filter(s => s);
|
1045
1007
|
|
1046
|
-
|
1008
|
+
let csp_meta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
|
1009
|
+
let csp = csp_meta ? csp_meta.content : null;
|
1047
1010
|
|
1048
|
-
|
1049
|
-
|
1011
|
+
let feature_policy = [];
|
1012
|
+
if (document.featurePolicy) {
|
1013
|
+
feature_policy = document.featurePolicy.allowedFeatures().sort();
|
1014
|
+
}
|
1050
1015
|
|
1051
|
-
|
1052
|
-
|
1016
|
+
let is_framed = false;
|
1017
|
+
try {
|
1018
|
+
if (window.top !== window.self) {
|
1019
|
+
is_framed = true;
|
1020
|
+
}
|
1021
|
+
} catch (e) {
|
1022
|
+
is_framed = true;
|
1023
|
+
}
|
1053
1024
|
|
1054
|
-
|
1055
|
-
|
1025
|
+
let resources = window.performance.getEntriesByType('resource').map(e => ({
|
1026
|
+
name: e.name,
|
1027
|
+
initiatorType: e.initiatorType
|
1028
|
+
}));
|
1029
|
+
|
1030
|
+
// Enhanced globals capture with values
|
1031
|
+
let globals = {};
|
1032
|
+
let propNames = Object.getOwnPropertyNames(window).sort();
|
1033
|
+
const safeStringify = (value, depth = 0) => {
|
1034
|
+
if (depth > 5) return '[Max depth exceeded]'; // Prevent deep recursion
|
1035
|
+
try {
|
1036
|
+
return JSON.stringify(value, (key, val) => {
|
1037
|
+
if (typeof val === 'function') {
|
1038
|
+
return val.toString(); // Capture function source
|
1039
|
+
} else if (typeof val === 'symbol') {
|
1040
|
+
return val.toString();
|
1041
|
+
} else if (val === window) {
|
1042
|
+
return '[Window reference]'; // Avoid circularity
|
1043
|
+
} else if (val && typeof val === 'object') {
|
1044
|
+
if (depth > 5) return '[Object (depth limit)]';
|
1045
|
+
return val; // Let JSON handle, recurse with depth
|
1046
|
+
}
|
1047
|
+
return val;
|
1048
|
+
});
|
1049
|
+
} catch (e) {
|
1050
|
+
return '[Stringify error: ' + e.message + ']';
|
1051
|
+
}
|
1052
|
+
};
|
1053
|
+
|
1054
|
+
for (let name of propNames) {
|
1055
|
+
try {
|
1056
|
+
let value = window[name];
|
1057
|
+
globals[name] = safeStringify(value);
|
1058
|
+
} catch (e) {
|
1059
|
+
globals[name] = '[Access error: ' + e.message + ']';
|
1060
|
+
}
|
1061
|
+
}
|
1056
1062
|
|
1057
|
-
|
1063
|
+
return JSON.stringify({
|
1064
|
+
cookies: document.cookie,
|
1065
|
+
localStorage: ls,
|
1066
|
+
sessionStorage: ss,
|
1067
|
+
globals: globals, // Now an object with name: stringified_value
|
1068
|
+
scripts: scripts,
|
1069
|
+
stylesheets: stylesheets,
|
1070
|
+
inline_styles: inline_styles,
|
1071
|
+
stack: new Error().stack,
|
1072
|
+
location: {
|
1073
|
+
href: location.href,
|
1074
|
+
origin: location.origin,
|
1075
|
+
pathname: location.pathname,
|
1076
|
+
search: location.search,
|
1077
|
+
hash: location.hash
|
1078
|
+
},
|
1079
|
+
referrer: document.referrer,
|
1080
|
+
userAgent: navigator.userAgent,
|
1081
|
+
html_snapshot: document.documentElement.outerHTML,
|
1082
|
+
forms: forms,
|
1083
|
+
iframes: iframes,
|
1084
|
+
csp: csp,
|
1085
|
+
feature_policy: feature_policy,
|
1086
|
+
is_framed: is_framed,
|
1087
|
+
has_service_worker: 'serviceWorker' in navigator,
|
1088
|
+
resources: resources
|
1089
|
+
});
|
1090
|
+
} catch (e) {
|
1091
|
+
return JSON.stringify({
|
1092
|
+
error: e.message,
|
1093
|
+
stack: e.stack
|
1094
|
+
});
|
1095
|
+
}
|
1096
|
+
})()
|
1097
|
+
JS
|
1098
|
+
|
1099
|
+
browser_obj[:devtools].send_cmd('Console.clearMessages')
|
1100
|
+
browser_obj[:devtools].send_cmd('Log.clear')
|
1101
|
+
console_events = []
|
1102
|
+
browser_obj[:browser].driver.on_log_event(:console) { |event| console_events.push(event) }
|
1103
|
+
|
1104
|
+
# page_state = console(browser_obj: browser_obj, js: js, return_to: :stdout)
|
1105
|
+
console_cmd = { expression: js }
|
1106
|
+
runtime_resp = browser_obj[:devtools].send_cmd('Runtime.evaluate', **console_cmd)
|
1107
|
+
page_state = runtime_resp['result']['result']['value']
|
1108
|
+
JSON.parse(page_state, symbolize_names: true)
|
1109
|
+
rescue JSON::ParserError => e
|
1110
|
+
raise "Failed to parse state JSON: #{e.message}. Raw output: #{state_json.inspect}"
|
1058
1111
|
rescue StandardError => e
|
1059
1112
|
raise e
|
1060
1113
|
end
|
1061
1114
|
|
1062
1115
|
# Supported Method Parameters::
|
1063
|
-
# PWN::Plugins::TransparentBrowser.
|
1064
|
-
# browser_obj: 'required - browser_obj returned from #open method)'
|
1065
|
-
# steps: 'optional - number of steps taken (Defaults to 1)'
|
1116
|
+
# messages = PWN::Plugins::TransparentBrowser.devtools_websocket_messages(
|
1117
|
+
# browser_obj: 'required - browser_obj returned from #open method)'
|
1066
1118
|
# )
|
1067
1119
|
|
1068
|
-
public_class_method def self.
|
1120
|
+
public_class_method def self.devtools_websocket_messages(opts = {})
|
1069
1121
|
browser_obj = opts[:browser_obj]
|
1070
|
-
|
1071
|
-
verified = verify_devtools_browser(browser_obj: browser_obj, supported: supported)
|
1122
|
+
verified = verify_devtools_browser(browser_obj: browser_obj)
|
1072
1123
|
puts 'This browser is not supported for DevTools operations.' unless verified
|
1073
1124
|
return unless verified
|
1074
1125
|
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
step = s + 1
|
1082
|
-
diff_hash[:step] = step
|
1126
|
+
devtools = browser_obj[:devtools]
|
1127
|
+
websocket = devtools.instance_variable_get(:@ws)
|
1128
|
+
websocket.instance_variable_get(:@messages)[nil]
|
1129
|
+
rescue StandardError => e
|
1130
|
+
raise e
|
1131
|
+
end
|
1083
1132
|
|
1084
|
-
|
1085
|
-
|
1133
|
+
# Supported Method Parameters::
|
1134
|
+
# PWN::Plugins::TransparentBrowser.debugger(
|
1135
|
+
# browser_obj: 'required - browser_obj returned from #open method)',
|
1136
|
+
# action: 'optional - action to take :enable|:pause|:resume|:disable (Defaults to :enable)',
|
1137
|
+
# )
|
1086
1138
|
|
1087
|
-
|
1139
|
+
public_class_method def self.debugger(opts = {})
|
1140
|
+
browser_obj = opts[:browser_obj]
|
1141
|
+
verified = verify_devtools_browser(browser_obj: browser_obj)
|
1142
|
+
puts 'This browser is not supported for DevTools operations.' unless verified
|
1143
|
+
return unless verified
|
1088
1144
|
|
1089
|
-
|
1090
|
-
|
1145
|
+
valid_actions = %i[enable pause resume disable]
|
1146
|
+
action = opts[:action] ||= :enable
|
1147
|
+
action = action.to_s.downcase.to_sym
|
1148
|
+
raise 'ERROR: action parameter must be :enable|:pause|:resume|:disable' unless valid_actions.include?(action)
|
1091
1149
|
|
1092
|
-
|
1093
|
-
|
1150
|
+
devtools = browser_obj[:devtools]
|
1151
|
+
debugger_state = devtools.instance_variable_get(:@debugger_state)
|
1094
1152
|
|
1095
|
-
|
1153
|
+
case action
|
1154
|
+
when :enable
|
1155
|
+
if debugger_state.is_a?(Hash)
|
1156
|
+
debugger_state = devtools.instance_variable_get(:@debugger_state)
|
1157
|
+
devtools.remove_instance_variable(:@debugger_state) if debugger_state.is_a?(Hash)
|
1158
|
+
devtools.debugger.disable
|
1159
|
+
end
|
1160
|
+
debugger_state = {}
|
1161
|
+
breakpoint_arr = []
|
1162
|
+
|
1163
|
+
# breakpoint = devtools.debugger.set_instrumentation_breakpoint(instrumentation: 'beforeScriptExecution')
|
1164
|
+
bcmd = 'EventBreakpoints.setInstrumentationBreakpoint'
|
1165
|
+
event = 'load'
|
1166
|
+
breakpoint = devtools.send_cmd(bcmd, eventName: event)
|
1167
|
+
breakpoint['result']['breakpointId'] = "#{bcmd}.#{event}.#{SecureRandom.uuid}"
|
1168
|
+
breakpoint_arr.push(breakpoint)
|
1169
|
+
debugger_state[:breakpoints] = breakpoint_arr
|
1170
|
+
|
1171
|
+
devtools.runtime.disable
|
1172
|
+
devtools.log.disable
|
1173
|
+
devtools.network.disable
|
1174
|
+
devtools.page.disable
|
1175
|
+
devtools.debugger.enable
|
1176
|
+
when :pause
|
1177
|
+
devtools.debugger.pause
|
1178
|
+
Timeout.timeout(5) { browser_obj[:browser].refresh }
|
1179
|
+
when :resume
|
1180
|
+
devtools.debugger.resume
|
1181
|
+
when :disable
|
1182
|
+
debugger_state = devtools.instance_variable_get(:@debugger_state)
|
1183
|
+
devtools.remove_instance_variable(:@debugger_state) if debugger_state.is_a?(Hash)
|
1184
|
+
devtools.debugger.disable
|
1096
1185
|
end
|
1097
1186
|
|
1098
|
-
|
1187
|
+
devtools_websocket_messages = devtools_websocket_messages(browser_obj: browser_obj)
|
1188
|
+
debugger_state[:method] = devtools_websocket_messages['method']
|
1189
|
+
devtools.instance_variable_set(:@debugger_state, debugger_state)
|
1190
|
+
devtools
|
1191
|
+
rescue Timeout::Error
|
1192
|
+
devtools
|
1193
|
+
rescue Selenium::WebDriver::Error::WebDriverError => e
|
1194
|
+
puts e.message
|
1099
1195
|
rescue StandardError => e
|
1100
1196
|
raise e
|
1101
1197
|
end
|
1102
1198
|
|
1103
1199
|
# Supported Method Parameters::
|
1104
|
-
# PWN::Plugins::TransparentBrowser.
|
1200
|
+
# page_state_arr = PWN::Plugins::TransparentBrowser.step(
|
1105
1201
|
# browser_obj: 'required - browser_obj returned from #open method)',
|
1202
|
+
# action: 'optional - action to take :into|:out|:over (Defaults to :into)',
|
1106
1203
|
# steps: 'optional - number of steps taken (Defaults to 1)'
|
1107
1204
|
# )
|
1108
1205
|
|
1109
|
-
public_class_method def self.
|
1206
|
+
public_class_method def self.step(opts = {})
|
1110
1207
|
browser_obj = opts[:browser_obj]
|
1111
1208
|
supported = %i[chrome headless_chrome]
|
1112
1209
|
verified = verify_devtools_browser(browser_obj: browser_obj, supported: supported)
|
1113
1210
|
puts 'This browser is not supported for DevTools operations.' unless verified
|
1114
1211
|
return unless verified
|
1115
1212
|
|
1213
|
+
valid_actions = %i[into out over]
|
1214
|
+
action = opts[:action] ||= :into
|
1215
|
+
action = action.to_s.downcase.to_sym
|
1216
|
+
raise 'ERROR: action parameter must be :into|:out|:over' unless valid_actions.include?(action)
|
1217
|
+
|
1116
1218
|
steps = opts[:steps].to_i
|
1117
1219
|
steps = 1 if steps.zero? || steps.negative?
|
1118
1220
|
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1221
|
+
devtools = browser_obj[:devtools]
|
1222
|
+
debugger_state = devtools.instance_variable_get(:@debugger_state)
|
1223
|
+
method = debugger_state[:method]
|
1224
|
+
if method != 'Debugger.paused'
|
1225
|
+
puts 'The debugger must be paused before stepping. Pausing now...'
|
1226
|
+
return devtools
|
1227
|
+
end
|
1124
1228
|
|
1125
|
-
|
1126
|
-
|
1229
|
+
page_state_arr = []
|
1230
|
+
steps.times do |s|
|
1231
|
+
step_num = s + 1
|
1232
|
+
puts "Stepping #{action} (step #{step_num}/#{steps})..."
|
1233
|
+
|
1234
|
+
# before = get_page_state(browser_obj: browser_obj)
|
1235
|
+
# puts before.inspect
|
1236
|
+
before = devtools_websocket_messages(browser_obj: browser_obj)
|
1237
|
+
method = before['method']
|
1238
|
+
# puts before
|
1239
|
+
puts "\n"
|
1240
|
+
|
1241
|
+
if method == 'Debugger.paused'
|
1242
|
+
before_location = before['params']['callFrames'].first['location']
|
1243
|
+
start_location = before['params']['callFrames'].first['scopeChain'].first['startLocation']
|
1244
|
+
before_script_id = start_location['scriptId']
|
1245
|
+
from_line_num = start_location['lineNumber']
|
1246
|
+
from_column_num = start_location['columnNumber']
|
1247
|
+
|
1248
|
+
end_location = before['params']['callFrames'].first['scopeChain'].first['endLocation']
|
1249
|
+
to_line_num = end_location['lineNumber']
|
1250
|
+
to_column_num = end_location['columnNumber']
|
1251
|
+
|
1252
|
+
source_obj = devtools.debugger.get_script_source(script_id: before_script_id)
|
1253
|
+
source_code = source_obj['result']['scriptSource']
|
1254
|
+
# puts source_code
|
1255
|
+
# gets
|
1256
|
+
|
1257
|
+
source_lines = source_code.split("\n")
|
1258
|
+
source_lines_str = source_lines[from_line_num..to_line_num].join("\n")
|
1259
|
+
source_to_review = source_lines_str[from_column_num..to_column_num]
|
1260
|
+
|
1261
|
+
puts source_to_review
|
1262
|
+
request = source_lines_str[from_column_num..to_column_num]
|
1263
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(request: request)
|
1264
|
+
puts "^^^ #{ai_analysis}" unless ai_analysis.nil?
|
1265
|
+
# gets
|
1266
|
+
end
|
1127
1267
|
|
1128
|
-
|
1268
|
+
case action
|
1269
|
+
when :into
|
1270
|
+
devtools.debugger.step_into
|
1271
|
+
when :out
|
1272
|
+
devtools.debugger.step_out
|
1273
|
+
when :over
|
1274
|
+
devtools.debugger.step_over
|
1275
|
+
end
|
1129
1276
|
|
1130
|
-
|
1131
|
-
|
1277
|
+
puts "\n" * 3
|
1278
|
+
after = devtools_websocket_messages(browser_obj: browser_obj)
|
1279
|
+
method = after['method']
|
1280
|
+
# puts after
|
1281
|
+
puts "\n"
|
1282
|
+
|
1283
|
+
if method == 'Debugger.paused'
|
1284
|
+
after_location = after['params']['callFrames'].first['scopeChain'].first['object']
|
1285
|
+
start_location = after['params']['callFrames'].first['scopeChain'].first['startLocation']
|
1286
|
+
after_script_id = start_location['scriptId']
|
1287
|
+
from_line_num = start_location['lineNumber']
|
1288
|
+
from_column_num = start_location['columnNumber']
|
1289
|
+
|
1290
|
+
end_location = after['params']['callFrames'].first['scopeChain'].first['endLocation']
|
1291
|
+
to_line_num = end_location['lineNumber']
|
1292
|
+
to_column_num = end_location['columnNumber']
|
1293
|
+
|
1294
|
+
source_obj = devtools.debugger.get_script_source(script_id: after_script_id)
|
1295
|
+
source_code = source_obj['result']['scriptSource']
|
1296
|
+
# puts source_code
|
1297
|
+
# gets
|
1298
|
+
|
1299
|
+
source_lines = source_code.split("\n")
|
1300
|
+
source_lines_str = source_lines[from_line_num..to_line_num].join("\n")
|
1301
|
+
source_to_review = source_lines_str[from_column_num..to_column_num]
|
1302
|
+
|
1303
|
+
puts source_to_review
|
1304
|
+
request = source_lines_str[from_column_num..to_column_num]
|
1305
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(request: request)
|
1306
|
+
puts "^^^ #{ai_analysis}" unless ai_analysis.nil?
|
1307
|
+
# gets
|
1308
|
+
end
|
1309
|
+
puts "\n" * 6
|
1132
1310
|
|
1133
|
-
|
1134
|
-
|
1311
|
+
# step_hash = {
|
1312
|
+
# step: step_num,
|
1313
|
+
# action: action,
|
1314
|
+
# before: before,
|
1315
|
+
# after: after,
|
1316
|
+
# diff: diff.to_s(:text)
|
1317
|
+
# }
|
1135
1318
|
|
1136
|
-
|
1319
|
+
# page_state_arr.push(step_hash)
|
1137
1320
|
end
|
1138
1321
|
|
1139
|
-
|
1322
|
+
devtools
|
1323
|
+
rescue Selenium::WebDriver::Error::WebDriverError
|
1324
|
+
devtools
|
1140
1325
|
rescue StandardError => e
|
1141
1326
|
raise e
|
1142
1327
|
end
|
@@ -1399,28 +1584,22 @@ module PWN
|
|
1399
1584
|
keyword: 'optional - keyword in title or url used to close tabs (defaults to closing active tab)'
|
1400
1585
|
)
|
1401
1586
|
|
1402
|
-
#{self}.debugger(
|
1403
|
-
browser_obj: 'required - browser_obj returned from #open method)',
|
1404
|
-
action: 'optional - action to take :pause|:resume (Defaults to :pause)',
|
1405
|
-
url: 'optional - URL to navigate to after pausing debugger (Defaults to nil)'
|
1406
|
-
)
|
1407
|
-
|
1408
1587
|
current_dom = #{self}.dom(
|
1409
1588
|
browser_obj: 'required - browser_obj returned from #open method)'
|
1410
1589
|
)
|
1411
1590
|
|
1412
|
-
#{self}.
|
1413
|
-
browser_obj: 'required - browser_obj returned from #open method)'
|
1414
|
-
steps: 'optional - number of steps taken (Defaults to 1)'
|
1591
|
+
page_state = #{self}.get_page_state(
|
1592
|
+
browser_obj: 'required - browser_obj returned from #open method)'
|
1415
1593
|
)
|
1416
1594
|
|
1417
|
-
#{self}.
|
1595
|
+
#{self}.debugger(
|
1418
1596
|
browser_obj: 'required - browser_obj returned from #open method)',
|
1419
|
-
|
1597
|
+
action: 'optional - action to take :enable|:pause|:resume|:disable (Defaults to :enable)'
|
1420
1598
|
)
|
1421
1599
|
|
1422
|
-
#{self}.
|
1600
|
+
#{self}.step(
|
1423
1601
|
browser_obj: 'required - browser_obj returned from #open method)',
|
1602
|
+
action: 'optional - action to take :into|:out|:over (Defaults to :into)',
|
1424
1603
|
steps: 'optional - number of steps taken (Defaults to 1)'
|
1425
1604
|
)
|
1426
1605
|
|
data/lib/pwn/reports/sast.rb
CHANGED
@@ -22,61 +22,8 @@ module PWN
|
|
22
22
|
report_name: HTMLEntities.new.encode(report_name.to_s.scrub.strip.chomp),
|
23
23
|
data: []
|
24
24
|
}
|
25
|
-
report_name = opts[:report_name] ||= File.basename(Dir.pwd)
|
26
25
|
|
27
|
-
|
28
|
-
# total_entries = results_hash[:data].sum { |entry| entry[:line_no_and_contents].size }
|
29
|
-
# puts "Total entries to analyze: #{total_entries}" if engine
|
30
|
-
|
31
|
-
# percent_complete = 0.0
|
32
|
-
# entry_count = 0
|
33
|
-
# spin = TTY::Spinner.new(
|
34
|
-
# '[:spinner] Report Generation Progress: :percent_complete :entry_count of :total_entries',
|
35
|
-
# format: :dots,
|
36
|
-
# hide_cursor: true
|
37
|
-
# )
|
38
|
-
# spin.auto_spin
|
39
|
-
|
40
|
-
# ai_instrospection = PWN::Env[:ai][:introspection]
|
41
|
-
# puts "Analyzing source code using AI engine: #{engine}\nModel: #{model}\nSystem Role Content: #{system_role_content}\nTemperature: #{temp}" if ai_instrospection
|
42
|
-
|
43
|
-
# results_hash[:data].each do |hash_line|
|
44
|
-
# git_repo_root_uri = hash_line[:filename][:git_repo_root_uri]
|
45
|
-
# filename = hash_line[:filename][:entry]
|
46
|
-
# hash_line[:line_no_and_contents].each do |src_detail|
|
47
|
-
# entry_count += 1
|
48
|
-
# percent_complete = (entry_count.to_f / total_entries * 100).round(2)
|
49
|
-
# line_no = src_detail[:line_no]
|
50
|
-
# source_code_snippet = src_detail[:contents]
|
51
|
-
# author = src_detail[:author].to_s.scrub.chomp.strip
|
52
|
-
# response = nil
|
53
|
-
# if ai_instrospection
|
54
|
-
# request = {
|
55
|
-
# scm_uri: "#{git_repo_root_uri}/#{filename}",
|
56
|
-
# line: line_no,
|
57
|
-
# source_code_snippet: source_code_snippet
|
58
|
-
# }.to_json
|
59
|
-
# response = PWN::AI::Introspection.reflect(request: request)
|
60
|
-
# end
|
61
|
-
# ai_analysis = nil
|
62
|
-
# if response.is_a?(Hash)
|
63
|
-
# ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
|
64
|
-
# ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
|
65
|
-
# puts "AI Analysis Progress: #{percent_complete}% Line: #{line_no} | Author: #{author} | AI Analysis: #{ai_analysis}\n\n\n" if ai_analysis
|
66
|
-
# end
|
67
|
-
# src_detail[:ai_analysis] = ai_analysis.to_s.scrub.chomp.strip
|
68
|
-
# spin.update(
|
69
|
-
# percent_complete: "#{percent_complete}%",
|
70
|
-
# entry_count: entry_count,
|
71
|
-
# total_entries: total_entries
|
72
|
-
# )
|
73
|
-
# end
|
74
|
-
# end
|
75
|
-
|
76
|
-
# JSON object Completion
|
77
|
-
# File.open("#{dir_path}/pwn_scan_git_source.json", 'w') do |f|
|
78
|
-
# f.print(results_hash.to_json)
|
79
|
-
# end
|
26
|
+
report_name = opts[:report_name] ||= File.basename(Dir.pwd)
|
80
27
|
File.write(
|
81
28
|
"#{dir_path}/#{report_name}.json",
|
82
29
|
JSON.pretty_generate(results_hash)
|