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
data/lib/pwn/config.rb
CHANGED
@@ -26,69 +26,71 @@ module PWN
|
|
26
26
|
"
|
27
27
|
env = {
|
28
28
|
ai: {
|
29
|
-
active: 'grok',
|
29
|
+
active: "'grok'",
|
30
30
|
introspection: false,
|
31
31
|
grok: {
|
32
|
-
base_uri: 'optional - Base URI for Grok - Use private base OR defaults to https://api.x.ai/v1',
|
33
|
-
key: 'required - OpenAI API Key',
|
34
|
-
model: 'optional - Grok model to use',
|
35
|
-
system_role_content: 'You are an ethically hacking OpenAI agent.',
|
36
|
-
temp: 'optional - OpenAI temperature'
|
32
|
+
base_uri: "'optional - Base URI for Grok - Use private base OR defaults to https://api.x.ai/v1'",
|
33
|
+
key: "'required - OpenAI API Key'",
|
34
|
+
model: "'optional - Grok model to use'",
|
35
|
+
system_role_content: "'You are an ethically hacking OpenAI agent.'",
|
36
|
+
temp: "'optional - OpenAI temperature'"
|
37
37
|
},
|
38
38
|
openai: {
|
39
|
-
base_uri: 'optional - Base URI for OpenAI - Use private base OR defaults to https://api.openai.com/v1',
|
40
|
-
key: 'required - OpenAI API Key',
|
41
|
-
model: 'optional - OpenAI model to use',
|
42
|
-
system_role_content: 'You are an ethically hacking OpenAI agent.',
|
43
|
-
temp: 'optional - OpenAI temperature'
|
39
|
+
base_uri: "'optional - Base URI for OpenAI - Use private base OR defaults to https://api.openai.com/v1'",
|
40
|
+
key: "'required - OpenAI API Key'",
|
41
|
+
model: "'optional - OpenAI model to use'",
|
42
|
+
system_role_content: "'You are an ethically hacking OpenAI agent.'",
|
43
|
+
temp: "'optional - OpenAI temperature'"
|
44
44
|
},
|
45
45
|
ollama: {
|
46
|
-
base_uri: 'required - Base URI for Open WebUI - e.g. https://ollama.local',
|
47
|
-
key: 'required - Open WebUI API Key Under Settings >> Account >> JWT Token',
|
48
|
-
model: 'required - Ollama model to use',
|
49
|
-
system_role_content: 'You are an ethically hacking Ollama agent.',
|
50
|
-
temp: 'optional - Ollama temperature'
|
46
|
+
base_uri: "'required - Base URI for Open WebUI - e.g. https://ollama.local'",
|
47
|
+
key: "'required - Open WebUI API Key Under Settings >> Account >> JWT Token'",
|
48
|
+
model: "'required - Ollama model to use'",
|
49
|
+
system_role_content: "'You are an ethically hacking Ollama agent.'",
|
50
|
+
temp: "'optional - Ollama temperature'"
|
51
51
|
}
|
52
52
|
},
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
},
|
62
|
-
irc: {
|
63
|
-
ui_nick: '_human_',
|
64
|
-
shared_chan: '#pwn',
|
65
|
-
ai_agent_nicks: {
|
66
|
-
browser: {
|
67
|
-
pwn_rb: '/opt/pwn/lib/pwn/plugins/transparent_browser.rb',
|
68
|
-
system_role_content: 'You are a browser. You are a web browser that can be controlled by a human or AI agent'
|
69
|
-
},
|
70
|
-
nimjeh: {
|
71
|
-
pwn_rb: '',
|
72
|
-
system_role_content: 'You are a sarcastic hacker. You find software zero day vulnerabilities. This involves analyzing source code, race conditions, application binaries, and network protocols from an offensive security perspective.'
|
73
|
-
},
|
74
|
-
nmap: {
|
75
|
-
pwn_rb: '/opt/pwn/lib/pwn/plugins/nmap_it.rb',
|
76
|
-
system_role_content: 'You are a network scanner. You are a network scanner that can be controlled by a human or AI agent'
|
77
|
-
},
|
78
|
-
shodan: {
|
79
|
-
pwn_rb: '/opt/pwn/lib/pwn/plugins/shodan.rb',
|
80
|
-
system_role_content: 'You are a passive reconnaissance agent. You are a passive reconnaissance agent that can be controlled by a human or AI agent'
|
53
|
+
plugins: {
|
54
|
+
asm: { arch: "'#{PWN::Plugins::DetectOS.arch}'", endian: "'#{PWN::Plugins::DetectOS.endian}'" },
|
55
|
+
blockchain: {
|
56
|
+
bitcoin: {
|
57
|
+
rpc_host: "'localhost'",
|
58
|
+
rpc_port: 8332,
|
59
|
+
rpc_user: "'bitcoin RPC Username'",
|
60
|
+
rpc_pass: "'bitcoin RPC Password'"
|
81
61
|
}
|
82
|
-
}
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
62
|
+
},
|
63
|
+
irc: {
|
64
|
+
ui_nick: '_human_',
|
65
|
+
shared_chan: '#pwn',
|
66
|
+
ai_agent_nicks: {
|
67
|
+
browser: {
|
68
|
+
pwn_rb: '/opt/pwn/lib/pwn/plugins/transparent_browser.rb',
|
69
|
+
system_role_content: 'You are a browser. You are a web browser that can be controlled by a human or AI agent'
|
70
|
+
},
|
71
|
+
nimjeh: {
|
72
|
+
pwn_rb: '',
|
73
|
+
system_role_content: 'You are a sarcastic hacker. You find software zero day vulnerabilities. This involves analyzing source code, race conditions, application binaries, and network protocols from an offensive security perspective.'
|
74
|
+
},
|
75
|
+
nmap: {
|
76
|
+
pwn_rb: '/opt/pwn/lib/pwn/plugins/nmap_it.rb',
|
77
|
+
system_role_content: 'You are a network scanner. You are a network scanner that can be controlled by a human or AI agent'
|
78
|
+
},
|
79
|
+
shodan: {
|
80
|
+
pwn_rb: '/opt/pwn/lib/pwn/plugins/shodan.rb',
|
81
|
+
system_role_content: 'You are a passive reconnaissance agent. You are a passive reconnaissance agent that can be controlled by a human or AI agent'
|
82
|
+
}
|
83
|
+
}
|
84
|
+
},
|
85
|
+
hunter: { api_key: 'hunter.how API Key' },
|
86
|
+
meshtastic: {
|
87
|
+
psks: {
|
88
|
+
LongFast: 'AQ==',
|
89
|
+
PWN: 'required - PSK for pwn channel'
|
90
|
+
}
|
91
|
+
},
|
92
|
+
shodan: { api_key: 'SHODAN API Key' }
|
93
|
+
}
|
92
94
|
}
|
93
95
|
# Remove beginning colon from key names
|
94
96
|
yaml_env = YAML.dump(env).gsub(/^(\s*):/, '\1')
|
data/lib/pwn/plugins/assembly.rb
CHANGED
@@ -25,6 +25,12 @@ module PWN
|
|
25
25
|
|
26
26
|
raise 'ERROR: opcodes parameter is required.' if opcodes.nil?
|
27
27
|
|
28
|
+
system_role_content = "Analyze the #{endian} endian #{arch} assembly opcodes below and provide a concise summary of their functionality."
|
29
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(
|
30
|
+
request: opcodes,
|
31
|
+
system_role_content: system_role_content
|
32
|
+
)
|
33
|
+
|
28
34
|
case arch.to_s.downcase
|
29
35
|
when 'i386', 'i686', 'x86'
|
30
36
|
arch_obj = Metasm::Ia32.new(endian)
|
@@ -109,7 +115,7 @@ module PWN
|
|
109
115
|
opcodes = [opcodes].pack('H*')
|
110
116
|
# puts opcodes.inspect
|
111
117
|
|
112
|
-
Metasm::Shellcode.disassemble(arch_obj, opcodes).to_s.squeeze("\n")
|
118
|
+
"#{ai_analysis}\n\n* Assembly Instructions >>>#{Metasm::Shellcode.disassemble(arch_obj, opcodes).to_s.squeeze("\n")}\n"
|
113
119
|
rescue StandardError => e
|
114
120
|
raise e
|
115
121
|
end
|
@@ -131,6 +137,12 @@ module PWN
|
|
131
137
|
|
132
138
|
raise 'ERROR: asm parameter is required.' if asm.nil?
|
133
139
|
|
140
|
+
system_role_content = "Analyze the #{endian} endian #{arch} assembly instructions below and provide a concise summary of their functionality."
|
141
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(
|
142
|
+
request: asm,
|
143
|
+
system_role_content: system_role_content
|
144
|
+
)
|
145
|
+
|
134
146
|
case arch.to_s.downcase
|
135
147
|
when 'i386', 'i686', 'x86'
|
136
148
|
arch_obj = Metasm::Ia32.new(endian)
|
@@ -175,9 +187,8 @@ module PWN
|
|
175
187
|
end
|
176
188
|
|
177
189
|
opcodes = Metasm::Shellcode.assemble(arch_obj, asm).encode_string
|
178
|
-
hex_encoded_opcodes = opcodes.bytes.map { |b| format('\x%02x', b) }.join
|
179
190
|
|
180
|
-
"\n#{
|
191
|
+
"#{ai_analysis}\n\n* Hex-Escaped Opcodes >>>\n#{opcodes.bytes.map { |b| format('\x%02x', b) }.join}\n"
|
181
192
|
rescue Metasm::ParseError
|
182
193
|
puts "Invalid assembly instruction(s) provided:\n#{asm}"
|
183
194
|
# Should we try to call opcode_to_asm here or just raise the error?
|
data/lib/pwn/plugins/repl.rb
CHANGED
@@ -34,8 +34,8 @@ module PWN
|
|
34
34
|
dchars = "\001\e[33m\002***\001\e[0m\002" if mode == :splat
|
35
35
|
|
36
36
|
if pi.config.pwn_asm
|
37
|
-
arch = PWN::Env[:asm][:arch] ||= PWN::Plugins::DetectOS.arch
|
38
|
-
endian = PWN::Env[:asm][:endian] ||= PWN::Plugins::DetectOS.endian
|
37
|
+
arch = PWN::Env[:plugins][:asm][:arch] ||= PWN::Plugins::DetectOS.arch
|
38
|
+
endian = PWN::Env[:plugins][:asm][:endian] ||= PWN::Plugins::DetectOS.endian
|
39
39
|
|
40
40
|
pi.config.prompt_name = "pwn.asm:#{arch}/#{endian}"
|
41
41
|
name = "\001\e[1m\002\001\e[37m\002#{pi.config.prompt_name}\001\e[0m\002"
|
@@ -173,10 +173,10 @@ module PWN
|
|
173
173
|
|
174
174
|
reply = nil
|
175
175
|
response_history = nil
|
176
|
-
shared_chan = PWN::Env[:irc][:shared_chan]
|
176
|
+
shared_chan = PWN::Env[:plugins][:irc][:shared_chan]
|
177
177
|
mem_chan = '#mem'
|
178
|
-
ai_agents = PWN::Env[:irc][:ai_agent_nicks]
|
179
|
-
ai_agents_arr = PWN::Env[:irc][:ai_agent_nicks].keys
|
178
|
+
ai_agents = PWN::Env[:plugins][:irc][:ai_agent_nicks]
|
179
|
+
ai_agents_arr = PWN::Env[:plugins][:irc][:ai_agent_nicks].keys
|
180
180
|
total_ai_agents = ai_agents_arr.length
|
181
181
|
mutex = Mutex.new
|
182
182
|
PWN::Plugins::ThreadPool.fill(
|
@@ -303,11 +303,6 @@ module PWN
|
|
303
303
|
|
304
304
|
response_history = ai_agents[dm_agent.to_sym][:response_history]
|
305
305
|
engine = PWN::Env[:ai][:active].to_s.downcase.to_sym
|
306
|
-
base_uri = PWN::Env[:ai][engine][:base_uri]
|
307
|
-
key = PWN::Env[:ai][engine][:key] ||= ''
|
308
|
-
temp = PWN::Env[:ai][engine][:temp]
|
309
|
-
model = PWN::Env[:ai][engine][:model]
|
310
|
-
system_role_content = PWN::Env[:ai][engine][:system_role_content]
|
311
306
|
|
312
307
|
users_in_chan = PWN::Plugins::IRC.names(
|
313
308
|
irc_obj: irc_obj,
|
@@ -319,55 +314,21 @@ module PWN
|
|
319
314
|
chan: shared_chan
|
320
315
|
)
|
321
316
|
|
322
|
-
system_role_content = "
|
323
|
-
#{system_role_content}
|
324
|
-
You joined the IRC channel #{shared_chan}
|
325
|
-
with the following users: #{users_in_shared_chan}
|
326
|
-
"
|
327
|
-
|
328
|
-
system_role_content = "
|
329
|
-
#{system_role_content}
|
330
|
-
You also joined your own IRC channel #{chan}
|
331
|
-
with the following users: #{users_in_chan}
|
332
|
-
"
|
333
|
-
|
334
|
-
system_role_content = "
|
335
|
-
#{system_role_content}
|
336
|
-
You can dm/collaborate/speak with users to
|
337
|
-
achieve your goals using '@<nick>' in your
|
338
|
-
message.
|
339
|
-
"
|
340
|
-
|
341
317
|
case engine
|
342
318
|
when :grok
|
343
319
|
response = PWN::AI::Grok.chat(
|
344
|
-
base_uri: base_uri,
|
345
|
-
token: key,
|
346
|
-
model: model,
|
347
|
-
temp: temp,
|
348
|
-
system_role_content: system_role_content,
|
349
320
|
request: request,
|
350
321
|
response_history: response_history,
|
351
322
|
spinner: false
|
352
323
|
)
|
353
324
|
when :ollama
|
354
325
|
response = PWN::AI::Ollama.chat(
|
355
|
-
base_uri: base_uri,
|
356
|
-
token: key,
|
357
|
-
model: model,
|
358
|
-
temp: temp,
|
359
|
-
system_role_content: system_role_content,
|
360
326
|
request: request,
|
361
327
|
response_history: response_history,
|
362
328
|
spinner: false
|
363
329
|
)
|
364
330
|
when :openai
|
365
331
|
response = PWN::AI::OpenAI.chat(
|
366
|
-
base_uri: base_uri,
|
367
|
-
token: key,
|
368
|
-
model: model,
|
369
|
-
temp: temp,
|
370
|
-
system_role_content: system_role_content,
|
371
332
|
request: request,
|
372
333
|
response_history: response_history,
|
373
334
|
spinner: false
|
@@ -431,7 +392,7 @@ module PWN
|
|
431
392
|
|
432
393
|
# TODO: Use TLS for IRC Connections
|
433
394
|
# Use an IRC nCurses CLI Client
|
434
|
-
ui_nick = PWN::Env[:irc][:ui_nick]
|
395
|
+
ui_nick = PWN::Env[:plugins][:irc][:ui_nick]
|
435
396
|
join_channels = ai_agents_arr.map { |ai_chan| "##{ai_chan}" }.join(',')
|
436
397
|
|
437
398
|
cmd0 = "/server add pwn #{host}/#{port} -notls"
|
@@ -535,8 +496,8 @@ module PWN
|
|
535
496
|
if pi.config.pwn_asm && !request.chomp.empty?
|
536
497
|
request = pi.input.line_buffer
|
537
498
|
|
538
|
-
arch = PWN::Env[:asm][:arch]
|
539
|
-
endian = PWN::Env[:asm][:endian]
|
499
|
+
arch = PWN::Env[:plugins][:asm][:arch]
|
500
|
+
endian = PWN::Env[:plugins][:asm][:endian]
|
540
501
|
|
541
502
|
# Analyze request to determine if it should be processed as opcodes or asm.
|
542
503
|
straight_hex = /^[a-fA-F0-9\s]+$/
|
@@ -573,22 +534,12 @@ module PWN
|
|
573
534
|
request = pi.input.line_buffer.to_s
|
574
535
|
debug = pi.config.pwn_ai_debug
|
575
536
|
engine = PWN::Env[:ai][:active].to_s.downcase.to_sym
|
576
|
-
base_uri = PWN::Env[:ai][engine][:base_uri]
|
577
|
-
key = PWN::Env[:ai][engine][:key] ||= ''
|
578
537
|
response_history = PWN::Env[:ai][engine][:response_history]
|
579
538
|
speak_answer = pi.config.pwn_ai_speak
|
580
|
-
model = PWN::Env[:ai][engine][:model]
|
581
|
-
system_role_content = PWN::Env[:ai][engine][:system_role_content]
|
582
|
-
temp = PWN::Env[:ai][engine][:temp]
|
583
539
|
|
584
540
|
case engine
|
585
541
|
when :grok
|
586
542
|
response = PWN::AI::Grok.chat(
|
587
|
-
base_uri: base_uri,
|
588
|
-
token: key,
|
589
|
-
model: model,
|
590
|
-
system_role_content: system_role_content,
|
591
|
-
temp: temp,
|
592
543
|
request: request.chomp,
|
593
544
|
response_history: response_history,
|
594
545
|
speak_answer: speak_answer,
|
@@ -596,11 +547,6 @@ module PWN
|
|
596
547
|
)
|
597
548
|
when :ollama
|
598
549
|
response = PWN::AI::Ollama.chat(
|
599
|
-
base_uri: base_uri,
|
600
|
-
token: key,
|
601
|
-
model: model,
|
602
|
-
system_role_content: system_role_content,
|
603
|
-
temp: temp,
|
604
550
|
request: request.chomp,
|
605
551
|
response_history: response_history,
|
606
552
|
speak_answer: speak_answer,
|
@@ -608,11 +554,6 @@ module PWN
|
|
608
554
|
)
|
609
555
|
when :openai
|
610
556
|
response = PWN::AI::OpenAI.chat(
|
611
|
-
base_uri: base_uri,
|
612
|
-
token: key,
|
613
|
-
model: model,
|
614
|
-
system_role_content: system_role_content,
|
615
|
-
temp: temp,
|
616
557
|
request: request.chomp,
|
617
558
|
response_history: response_history,
|
618
559
|
speak_answer: speak_answer,
|