pwn 0.5.708 → 0.5.710
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/Gemfile +2 -2
- data/documentation/Installation.md +1 -0
- data/etc/default_skills/exploitdev/SKILL.md +38 -0
- data/etc/default_skills/pwn/ai/agent/extrospection/osint/bridges/SKILL.md +30 -8
- data/etc/default_skills/pwn/ai/agent/extrospection/osint/social/SKILL.md +30 -8
- data/etc/default_skills/pwn/ai/agent/extrospection/osint/social/references/urls.md +1 -1
- data/etc/default_skills/pwn/ai/agent/extrospection/references/urls.md +0 -1
- data/etc/default_skills/pwn/memory_index/SKILL.md +0 -4
- data/etc/default_skills/pwn/plugins/aflplusplus/SKILL.md +49 -0
- data/etc/default_skills/pwn/plugins/android/SKILL.md +1 -0
- data/etc/default_skills/pwn/plugins/artifact_registry/SKILL.md +49 -0
- data/etc/default_skills/pwn/plugins/binary_parser/SKILL.md +54 -0
- data/etc/default_skills/pwn/plugins/credential_attack/SKILL.md +58 -0
- data/etc/default_skills/pwn/plugins/credential_attack/references/urls.md +3 -0
- data/etc/default_skills/pwn/plugins/exploit_db/SKILL.md +49 -0
- data/etc/default_skills/pwn/plugins/exploit_dev/SKILL.md +63 -0
- data/etc/default_skills/pwn/plugins/frida/SKILL.md +51 -0
- data/etc/default_skills/pwn/plugins/fuzz/SKILL.md +2 -0
- data/etc/default_skills/pwn/plugins/gdb/SKILL.md +53 -0
- data/etc/default_skills/pwn/plugins/jobs/SKILL.md +51 -0
- data/etc/default_skills/pwn/plugins/k8s/SKILL.md +51 -0
- data/etc/default_skills/pwn/plugins/nuclei/SKILL.md +50 -0
- data/etc/default_skills/pwn/plugins/preflight_checker/SKILL.md +59 -0
- data/etc/default_skills/pwn/plugins/process_tube/SKILL.md +53 -0
- data/etc/default_skills/pwn/plugins/radare2/SKILL.md +59 -0
- data/etc/default_skills/pwn/plugins/recon/SKILL.md +57 -0
- data/etc/default_skills/pwn/plugins/recon/references/urls.md +6 -0
- data/etc/default_skills/pwn/plugins/semgrep/SKILL.md +48 -0
- data/etc/default_skills/pwn/plugins/sqlmap/SKILL.md +48 -0
- data/etc/default_skills/pwn/plugins/transparent_browser/SKILL.md +0 -4
- data/etc/default_skills/pwn/plugins/volatility/SKILL.md +49 -0
- data/lib/pwn/ai/agent/assembly.rb +4 -1
- data/lib/pwn/ai/agent/btc.rb +4 -1
- data/lib/pwn/ai/agent/burp_suite.rb +5 -2
- data/lib/pwn/ai/agent/curriculum.rb +89 -30
- data/lib/pwn/ai/agent/dispatch.rb +27 -16
- data/lib/pwn/ai/agent/extrospection/osint/bridges.rb +9 -18
- data/lib/pwn/ai/agent/extrospection/osint/social.rb +9 -18
- data/lib/pwn/ai/agent/extrospection.rb +185 -60
- data/lib/pwn/ai/agent/gqrx.rb +4 -1
- data/lib/pwn/ai/agent/hacker_one.rb +5 -2
- data/lib/pwn/ai/agent/learning.rb +142 -25
- data/lib/pwn/ai/agent/loop.rb +53 -46
- data/lib/pwn/ai/agent/metrics.rb +133 -23
- data/lib/pwn/ai/agent/mistakes.rb +126 -17
- data/lib/pwn/ai/agent/open_goal.rb +25 -9
- data/lib/pwn/ai/agent/policy.rb +158 -18
- data/lib/pwn/ai/agent/prompt_builder.rb +21 -11
- data/lib/pwn/ai/agent/prompt_cache.rb +44 -13
- data/lib/pwn/ai/agent/reflect.rb +9 -5
- data/lib/pwn/ai/agent/registry.rb +65 -12
- data/lib/pwn/ai/agent/result.rb +19 -10
- data/lib/pwn/ai/agent/reward.rb +150 -32
- data/lib/pwn/ai/agent/sast.rb +4 -1
- data/lib/pwn/ai/agent/swarm.rb +72 -36
- data/lib/pwn/ai/agent/task_summarizer.rb +165 -36
- data/lib/pwn/ai/agent/tool_guard.rb +105 -6
- data/lib/pwn/ai/agent/tools/sessions.rb +8 -1
- data/lib/pwn/ai/agent/transparent_browser.rb +4 -1
- data/lib/pwn/ai/agent/turn_finalizer.rb +41 -21
- data/lib/pwn/ai/agent/vuln_gen.rb +6 -3
- data/lib/pwn/ai/agent.rb +4 -0
- data/lib/pwn/ai/anthropic.rb +41 -7
- data/lib/pwn/ai/gemini.rb +21 -11
- data/lib/pwn/ai/grok.rb +44 -6
- data/lib/pwn/ai/http_retry.rb +40 -12
- data/lib/pwn/ai/ollama.rb +19 -10
- data/lib/pwn/ai/open_ai.rb +81 -30
- data/lib/pwn/ai/open_web_ui.rb +20 -14
- data/lib/pwn/ai/red_team/agent_protocol_abuse.rb +7 -1
- data/lib/pwn/ai/red_team/data_and_model_poisoning.rb +7 -1
- data/lib/pwn/ai/red_team/excessive_agency.rb +7 -1
- data/lib/pwn/ai/red_team/hidden_context_exposure.rb +7 -1
- data/lib/pwn/ai/red_team/insecure_output_handling.rb +7 -1
- data/lib/pwn/ai/red_team/jailbreak.rb +7 -1
- data/lib/pwn/ai/red_team/memory_poisoning.rb +7 -1
- data/lib/pwn/ai/red_team/multimodal_injection.rb +7 -1
- data/lib/pwn/ai/red_team/overreliance.rb +7 -1
- data/lib/pwn/ai/red_team/payload_splitting.rb +7 -1
- data/lib/pwn/ai/red_team/prompt_injection.rb +7 -1
- data/lib/pwn/ai/red_team/rag_poisoning.rb +7 -1
- data/lib/pwn/ai/red_team/sensitive_information_disclosure.rb +7 -1
- data/lib/pwn/ai/red_team/supply_chain.rb +7 -1
- data/lib/pwn/ai/red_team/system_prompt_extraction.rb +7 -1
- data/lib/pwn/ai/red_team/test_case_engine.rb +12 -9
- data/lib/pwn/ai/red_team/token_smuggling.rb +7 -1
- data/lib/pwn/ai/red_team/unbounded_consumption.rb +7 -1
- data/lib/pwn/ai/red_team/vector_and_embedding_weaknesses.rb +7 -1
- data/lib/pwn/ai/red_team.rb +4 -0
- data/lib/pwn/ai.rb +4 -0
- data/lib/pwn/aws/acm.rb +5 -2
- data/lib/pwn/aws/api_gateway.rb +10 -7
- data/lib/pwn/aws/app_stream.rb +5 -2
- data/lib/pwn/aws/application_auto_scaling.rb +5 -2
- data/lib/pwn/aws/application_discovery_service.rb +5 -2
- data/lib/pwn/aws/auto_scaling.rb +5 -2
- data/lib/pwn/aws/batch.rb +5 -2
- data/lib/pwn/aws/budgets.rb +5 -2
- data/lib/pwn/aws/cloud_formation.rb +5 -2
- data/lib/pwn/aws/cloud_front.rb +7 -4
- data/lib/pwn/aws/cloud_hsm.rb +5 -2
- data/lib/pwn/aws/cloud_search.rb +5 -2
- data/lib/pwn/aws/cloud_search_domain.rb +5 -2
- data/lib/pwn/aws/cloud_trail.rb +5 -2
- data/lib/pwn/aws/cloud_watch.rb +5 -2
- data/lib/pwn/aws/cloud_watch_events.rb +5 -2
- data/lib/pwn/aws/cloud_watch_logs.rb +5 -2
- data/lib/pwn/aws/code_build.rb +5 -2
- data/lib/pwn/aws/code_commit.rb +5 -2
- data/lib/pwn/aws/code_deploy.rb +5 -2
- data/lib/pwn/aws/code_pipeline.rb +5 -2
- data/lib/pwn/aws/cognito_identity.rb +5 -2
- data/lib/pwn/aws/cognito_identity_provider.rb +5 -2
- data/lib/pwn/aws/cognito_sync.rb +5 -2
- data/lib/pwn/aws/config_service.rb +5 -2
- data/lib/pwn/aws/data_pipleline.rb +5 -2
- data/lib/pwn/aws/database_migration_service.rb +5 -2
- data/lib/pwn/aws/device_farm.rb +5 -2
- data/lib/pwn/aws/direct_connect.rb +5 -2
- data/lib/pwn/aws/directory_service.rb +5 -2
- data/lib/pwn/aws/dynamo_db.rb +5 -2
- data/lib/pwn/aws/dynamo_db_streams.rb +5 -2
- data/lib/pwn/aws/ec2.rb +5 -2
- data/lib/pwn/aws/ecr.rb +5 -2
- data/lib/pwn/aws/ecs.rb +5 -2
- data/lib/pwn/aws/efs.rb +5 -2
- data/lib/pwn/aws/elasti_cache.rb +5 -2
- data/lib/pwn/aws/elastic_beanstalk.rb +8 -5
- data/lib/pwn/aws/elastic_load_balancing.rb +5 -2
- data/lib/pwn/aws/elastic_load_balancing_v2.rb +6 -3
- data/lib/pwn/aws/elastic_transcoder.rb +5 -2
- data/lib/pwn/aws/elasticsearch_service.rb +5 -2
- data/lib/pwn/aws/emr.rb +5 -2
- data/lib/pwn/aws/firehose.rb +5 -2
- data/lib/pwn/aws/game_lift.rb +5 -2
- data/lib/pwn/aws/glacier.rb +6 -3
- data/lib/pwn/aws/health.rb +5 -2
- data/lib/pwn/aws/iam.rb +10 -4
- data/lib/pwn/aws/import_export.rb +5 -2
- data/lib/pwn/aws/inspector.rb +5 -2
- data/lib/pwn/aws/iot.rb +5 -2
- data/lib/pwn/aws/iot_data_plane.rb +5 -2
- data/lib/pwn/aws/kinesis.rb +5 -2
- data/lib/pwn/aws/kinesis_analytics.rb +5 -2
- data/lib/pwn/aws/kms.rb +5 -2
- data/lib/pwn/aws/lambda.rb +5 -2
- data/lib/pwn/aws/lambda_preview.rb +5 -2
- data/lib/pwn/aws/lex.rb +5 -2
- data/lib/pwn/aws/lightsail.rb +5 -2
- data/lib/pwn/aws/machine_learning.rb +5 -2
- data/lib/pwn/aws/marketplace_commerce_analytics.rb +5 -2
- data/lib/pwn/aws/marketplace_metering.rb +5 -2
- data/lib/pwn/aws/ops_works.rb +5 -2
- data/lib/pwn/aws/ops_works_cm.rb +5 -2
- data/lib/pwn/aws/pinpoint.rb +5 -2
- data/lib/pwn/aws/polly.rb +5 -2
- data/lib/pwn/aws/rds.rb +5 -2
- data/lib/pwn/aws/redshift.rb +5 -2
- data/lib/pwn/aws/rekognition.rb +5 -2
- data/lib/pwn/aws/route53.rb +5 -2
- data/lib/pwn/aws/route53_domains.rb +5 -2
- data/lib/pwn/aws/s3.rb +5 -2
- data/lib/pwn/aws/service_catalog.rb +5 -2
- data/lib/pwn/aws/ses.rb +5 -2
- data/lib/pwn/aws/shield.rb +5 -2
- data/lib/pwn/aws/simple_db.rb +5 -2
- data/lib/pwn/aws/sms.rb +5 -2
- data/lib/pwn/aws/snowball.rb +5 -2
- data/lib/pwn/aws/sns.rb +5 -2
- data/lib/pwn/aws/sqs.rb +5 -2
- data/lib/pwn/aws/ssm.rb +5 -2
- data/lib/pwn/aws/states.rb +5 -2
- data/lib/pwn/aws/storage_gateway.rb +5 -2
- data/lib/pwn/aws/sts.rb +4 -1
- data/lib/pwn/aws/support.rb +5 -2
- data/lib/pwn/aws/swf.rb +5 -2
- data/lib/pwn/aws/waf.rb +5 -2
- data/lib/pwn/aws/waf_regional.rb +5 -2
- data/lib/pwn/aws/workspaces.rb +5 -2
- data/lib/pwn/aws/x_ray.rb +5 -2
- data/lib/pwn/aws.rb +4 -0
- data/lib/pwn/banner/anon.rb +3 -0
- data/lib/pwn/banner/bubble.rb +3 -0
- data/lib/pwn/banner/cheshire.rb +3 -0
- data/lib/pwn/banner/code_cave.rb +3 -0
- data/lib/pwn/banner/dont_panic.rb +3 -0
- data/lib/pwn/banner/f_society.rb +3 -0
- data/lib/pwn/banner/fork_bomb.rb +3 -0
- data/lib/pwn/banner/jmp_esp.rb +3 -0
- data/lib/pwn/banner/matrix.rb +5 -1
- data/lib/pwn/banner/ninja.rb +3 -0
- data/lib/pwn/banner/off_the_air.rb +3 -0
- data/lib/pwn/banner/pirate.rb +3 -0
- data/lib/pwn/banner/radare2.rb +3 -0
- data/lib/pwn/banner/radare2_ai.rb +3 -0
- data/lib/pwn/banner/white_rabbit.rb +3 -0
- data/lib/pwn/banner.rb +6 -2
- data/lib/pwn/blockchain/btc.rb +8 -3
- data/lib/pwn/blockchain/eth.rb +10 -3
- data/lib/pwn/blockchain.rb +4 -0
- data/lib/pwn/bounty/lifecycle_authz_replay.rb +46 -27
- data/lib/pwn/bounty.rb +4 -0
- data/lib/pwn/config.rb +79 -13
- data/lib/pwn/cron.rb +297 -20
- data/lib/pwn/driver.rb +2 -18
- data/lib/pwn/ffi/adalm_pluto.rb +65 -11
- data/lib/pwn/ffi/fftw.rb +31 -6
- data/lib/pwn/ffi/hack_rf.rb +59 -8
- data/lib/pwn/ffi/liquid.rb +63 -10
- data/lib/pwn/ffi/rtl_sdr.rb +35 -5
- data/lib/pwn/ffi/soapy_sdr.rb +60 -10
- data/lib/pwn/ffi/stdio.rb +7 -8
- data/lib/pwn/ffi/volk.rb +36 -7
- data/lib/pwn/ffi.rb +12 -0
- data/lib/pwn/memory.rb +136 -16
- data/lib/pwn/memory_index.rb +34 -19
- data/lib/pwn/migrate.rb +34 -24
- data/lib/pwn/module_skills.rb +39 -8
- data/lib/pwn/plugins/aflplusplus.rb +72 -0
- data/lib/pwn/plugins/android.rb +71 -245
- data/lib/pwn/plugins/artifact_registry.rb +71 -0
- data/lib/pwn/plugins/assembly.rb +9 -4
- data/lib/pwn/plugins/authentication_helper.rb +8 -5
- data/lib/pwn/plugins/baresip.rb +59 -12
- data/lib/pwn/plugins/basic_auth.rb +9 -3
- data/lib/pwn/plugins/beef.rb +28 -18
- data/lib/pwn/plugins/binary_parser.rb +133 -0
- data/lib/pwn/plugins/black_duck_binary_analysis.rb +63 -39
- data/lib/pwn/plugins/burp_suite.rb +98 -68
- data/lib/pwn/plugins/bus_pirate.rb +15 -8
- data/lib/pwn/plugins/char.rb +33 -3
- data/lib/pwn/plugins/credential_attack.rb +158 -0
- data/lib/pwn/plugins/credit_card.rb +6 -1
- data/lib/pwn/plugins/dao_ldap.rb +19 -13
- data/lib/pwn/plugins/dao_mongo.rb +11 -5
- data/lib/pwn/plugins/dao_postgres.rb +28 -19
- data/lib/pwn/plugins/dao_sqlite3.rb +15 -6
- data/lib/pwn/plugins/defect_dojo.rb +38 -22
- data/lib/pwn/plugins/detect_os.rb +5 -0
- data/lib/pwn/plugins/ein.rb +3 -0
- data/lib/pwn/plugins/exploit_db.rb +69 -0
- data/lib/pwn/plugins/exploit_dev.rb +330 -0
- data/lib/pwn/plugins/file_fu.rb +11 -8
- data/lib/pwn/plugins/frida.rb +112 -0
- data/lib/pwn/plugins/fuzz.rb +42 -6
- data/lib/pwn/plugins/gdb.rb +115 -0
- data/lib/pwn/plugins/git.rb +19 -14
- data/lib/pwn/plugins/github.rb +38 -15
- data/lib/pwn/plugins/google_workspace.rb +188 -45
- data/lib/pwn/plugins/hacker_one.rb +159 -35
- data/lib/pwn/plugins/hunter.rb +6 -3
- data/lib/pwn/plugins/ip_info.rb +9 -4
- data/lib/pwn/plugins/irc.rb +28 -15
- data/lib/pwn/plugins/jenkins.rb +65 -57
- data/lib/pwn/plugins/jira_data_center.rb +30 -22
- data/lib/pwn/plugins/jobs.rb +110 -0
- data/lib/pwn/plugins/json_pathify.rb +9 -5
- data/lib/pwn/plugins/k8s.rb +73 -0
- data/lib/pwn/plugins/log.rb +113 -13
- data/lib/pwn/plugins/mail_agent.rb +87 -79
- data/lib/pwn/plugins/metasploit.rb +11 -6
- data/lib/pwn/plugins/monkey_patch.rb +3 -0
- data/lib/pwn/plugins/msr206.rb +42 -28
- data/lib/pwn/plugins/nessus_cloud.rb +44 -4
- data/lib/pwn/plugins/nexpose_vuln_scan.rb +40 -24
- data/lib/pwn/plugins/nmap_it.rb +14 -34
- data/lib/pwn/plugins/nuclei.rb +90 -0
- data/lib/pwn/plugins/oauth2.rb +11 -5
- data/lib/pwn/plugins/ocr.rb +3 -0
- data/lib/pwn/plugins/open_api.rb +5 -2
- data/lib/pwn/plugins/openvas.rb +33 -25
- data/lib/pwn/plugins/packet.rb +152 -31
- data/lib/pwn/plugins/pdf_parse.rb +5 -2
- data/lib/pwn/plugins/pony.rb +86 -1
- data/lib/pwn/plugins/preflight_checker.rb +166 -0
- data/lib/pwn/plugins/process_tube.rb +139 -0
- data/lib/pwn/plugins/ps.rb +7 -1
- data/lib/pwn/plugins/pwn_logger.rb +6 -2
- data/lib/pwn/plugins/rabbit_mq.rb +12 -7
- data/lib/pwn/plugins/radare2.rb +253 -0
- data/lib/pwn/plugins/recon.rb +196 -0
- data/lib/pwn/plugins/repl.rb +122 -1
- data/lib/pwn/plugins/scannable_codes.rb +5 -1
- data/lib/pwn/plugins/semgrep.rb +61 -0
- data/lib/pwn/plugins/serial.rb +24 -14
- data/lib/pwn/plugins/shodan.rb +54 -35
- data/lib/pwn/plugins/slack_client.rb +11 -6
- data/lib/pwn/plugins/sock.rb +17 -8
- data/lib/pwn/plugins/spider.rb +5 -2
- data/lib/pwn/plugins/sqlmap.rb +49 -0
- data/lib/pwn/plugins/ssn.rb +3 -0
- data/lib/pwn/plugins/thread_pool.rb +6 -9
- data/lib/pwn/plugins/tor.rb +9 -4
- data/lib/pwn/plugins/transparent_browser.rb +62 -107
- data/lib/pwn/plugins/tty_spinner.rb +16 -2
- data/lib/pwn/plugins/twitter_api.rb +6 -2
- data/lib/pwn/plugins/uri_scheme.rb +4 -1
- data/lib/pwn/plugins/vault.rb +12 -3
- data/lib/pwn/plugins/vin.rb +24 -12
- data/lib/pwn/plugins/voice.rb +7 -2
- data/lib/pwn/plugins/volatility.rb +67 -0
- data/lib/pwn/plugins/vsphere.rb +9 -5
- data/lib/pwn/plugins/xxd.rb +12 -43
- data/lib/pwn/plugins/zaproxy.rb +30 -16
- data/lib/pwn/plugins.rb +22 -0
- data/lib/pwn/reports/ai_red_team.rb +6 -2
- data/lib/pwn/reports/csv.rb +8 -1
- data/lib/pwn/reports/fuzz.rb +5 -2
- data/lib/pwn/reports/html.rb +8 -1
- data/lib/pwn/reports/html_footer.rb +4 -3
- data/lib/pwn/reports/html_header.rb +6 -2
- data/lib/pwn/reports/json.rb +8 -1
- data/lib/pwn/reports/markdown.rb +8 -1
- data/lib/pwn/reports/pdf.rb +8 -1
- data/lib/pwn/reports/phone.rb +5 -2
- data/lib/pwn/reports/sast.rb +6 -2
- data/lib/pwn/reports/uri_buster.rb +5 -2
- data/lib/pwn/reports/xml.rb +8 -1
- data/lib/pwn/reports.rb +19 -0
- data/lib/pwn/sast/amqp_connect_as_guest.rb +9 -3
- data/lib/pwn/sast/apache_file_system_util_api.rb +9 -3
- data/lib/pwn/sast/aws.rb +9 -3
- data/lib/pwn/sast/banned_function_calls_c.rb +9 -3
- data/lib/pwn/sast/base64.rb +9 -3
- data/lib/pwn/sast/beef_hook.rb +9 -3
- data/lib/pwn/sast/cmd_execution_go_lang.rb +9 -3
- data/lib/pwn/sast/cmd_execution_java.rb +9 -3
- data/lib/pwn/sast/cmd_execution_python.rb +9 -3
- data/lib/pwn/sast/cmd_execution_ruby.rb +9 -3
- data/lib/pwn/sast/cmd_execution_scala.rb +9 -3
- data/lib/pwn/sast/csrf.rb +9 -3
- data/lib/pwn/sast/deserial_java.rb +9 -3
- data/lib/pwn/sast/emoticon.rb +9 -3
- data/lib/pwn/sast/eval.rb +9 -3
- data/lib/pwn/sast/factory.rb +9 -3
- data/lib/pwn/sast/http_authorization_header.rb +9 -3
- data/lib/pwn/sast/inner_html.rb +9 -3
- data/lib/pwn/sast/keystore.rb +9 -3
- data/lib/pwn/sast/local_storage.rb +9 -3
- data/lib/pwn/sast/location_hash.rb +9 -3
- data/lib/pwn/sast/log4j.rb +9 -3
- data/lib/pwn/sast/logger.rb +9 -3
- data/lib/pwn/sast/md5.rb +9 -3
- data/lib/pwn/sast/outer_html.rb +9 -3
- data/lib/pwn/sast/padding_oracle.rb +9 -3
- data/lib/pwn/sast/password.rb +9 -3
- data/lib/pwn/sast/php_input_mechanisms.rb +9 -3
- data/lib/pwn/sast/php_type_juggling.rb +9 -3
- data/lib/pwn/sast/pom_version.rb +9 -3
- data/lib/pwn/sast/port.rb +9 -3
- data/lib/pwn/sast/post_message.rb +9 -3
- data/lib/pwn/sast/private_key.rb +9 -3
- data/lib/pwn/sast/redirect.rb +9 -3
- data/lib/pwn/sast/redos.rb +9 -3
- data/lib/pwn/sast/shell.rb +9 -3
- data/lib/pwn/sast/signature.rb +9 -3
- data/lib/pwn/sast/sql.rb +9 -3
- data/lib/pwn/sast/ssl.rb +9 -3
- data/lib/pwn/sast/sudo.rb +9 -3
- data/lib/pwn/sast/task_tag.rb +9 -3
- data/lib/pwn/sast/test_case_engine.rb +11 -7
- data/lib/pwn/sast/throw_errors.rb +9 -3
- data/lib/pwn/sast/token.rb +9 -3
- data/lib/pwn/sast/type_script_type_juggling.rb +9 -3
- data/lib/pwn/sast/use_after_free.rb +9 -3
- data/lib/pwn/sast/version.rb +9 -3
- data/lib/pwn/sast/window_location_hash.rb +9 -3
- data/lib/pwn/sast.rb +4 -0
- data/lib/pwn/sdr/decoder/adsb.rb +36 -5
- data/lib/pwn/sdr/decoder/apt.rb +9 -6
- data/lib/pwn/sdr/decoder/base.rb +74 -22
- data/lib/pwn/sdr/decoder/bluetooth.rb +17 -5
- data/lib/pwn/sdr/decoder/dect.rb +12 -3
- data/lib/pwn/sdr/decoder/dsp.rb +229 -39
- data/lib/pwn/sdr/decoder/flex.rb +59 -11
- data/lib/pwn/sdr/decoder/gps.rb +12 -3
- data/lib/pwn/sdr/decoder/gsm.rb +24 -4
- data/lib/pwn/sdr/decoder/iridium.rb +12 -3
- data/lib/pwn/sdr/decoder/lora.rb +13 -4
- data/lib/pwn/sdr/decoder/lte.rb +27 -3
- data/lib/pwn/sdr/decoder/morse.rb +12 -3
- data/lib/pwn/sdr/decoder/p25.rb +12 -3
- data/lib/pwn/sdr/decoder/pager.rb +8 -5
- data/lib/pwn/sdr/decoder/pocsag.rb +29 -9
- data/lib/pwn/sdr/decoder/rds.rb +14 -8
- data/lib/pwn/sdr/decoder/rfid.rb +12 -3
- data/lib/pwn/sdr/decoder/rtl433.rb +12 -3
- data/lib/pwn/sdr/decoder/rtty.rb +8 -5
- data/lib/pwn/sdr/decoder/wifi.rb +12 -3
- data/lib/pwn/sdr/decoder/zigbee.rb +12 -3
- data/lib/pwn/sdr/decoder.rb +9 -0
- data/lib/pwn/sdr/flipper_zero.rb +17 -10
- data/lib/pwn/sdr/frequency_allocation.rb +4 -1
- data/lib/pwn/sdr/gqrx.rb +178 -119
- data/lib/pwn/sdr/rfidler.rb +4 -1
- data/lib/pwn/sdr/son_micro_rfid.rb +37 -24
- data/lib/pwn/sdr.rb +14 -0
- data/lib/pwn/sessions.rb +86 -16
- data/lib/pwn/setup.rb +106 -37
- data/lib/pwn/version.rb +1 -1
- data/lib/pwn/www/app_cobalt_io.rb +11 -5
- data/lib/pwn/www/bing.rb +10 -5
- data/lib/pwn/www/bug_crowd.rb +11 -5
- data/lib/pwn/www/checkip.rb +8 -4
- data/lib/pwn/www/coinbase_pro.rb +11 -5
- data/lib/pwn/www/duckduckgo.rb +12 -6
- data/lib/pwn/www/facebook.rb +11 -5
- data/lib/pwn/www/github.rb +11 -5
- data/lib/pwn/www/google.rb +11 -5
- data/lib/pwn/www/hacker_one.rb +20 -9
- data/lib/pwn/www/linkedin.rb +11 -5
- data/lib/pwn/www/pandora.rb +11 -5
- data/lib/pwn/www/pastebin.rb +9 -4
- data/lib/pwn/www/paypal.rb +19 -11
- data/lib/pwn/www/synack.rb +11 -5
- data/lib/pwn/www/torch.rb +13 -8
- data/lib/pwn/www/trading_view.rb +11 -5
- data/lib/pwn/www/twitter.rb +11 -5
- data/lib/pwn/www/uber.rb +11 -5
- data/lib/pwn/www/upwork.rb +11 -5
- data/lib/pwn/www/wayback_machine.rb +12 -6
- data/lib/pwn/www/youtube.rb +10 -5
- data/lib/pwn/www.rb +4 -0
- data/spec/conventions_spec.rb +118 -2
- data/spec/integration/help_contract_spec.rb +2 -0
- data/spec/lib/pwn/ai/agent/reward_spec.rb +9 -0
- data/spec/lib/pwn/plugins/aflplusplus_spec.rb +13 -0
- data/spec/lib/pwn/plugins/artifact_registry_spec.rb +13 -0
- data/spec/lib/pwn/plugins/binary_parser_spec.rb +21 -0
- data/spec/lib/pwn/plugins/credential_attack_spec.rb +13 -0
- data/spec/lib/pwn/plugins/exploit_db_spec.rb +13 -0
- data/spec/lib/pwn/plugins/exploit_dev_spec.rb +23 -0
- data/spec/lib/pwn/plugins/frida_spec.rb +13 -0
- data/spec/lib/pwn/plugins/gdb_spec.rb +13 -0
- data/spec/lib/pwn/plugins/jobs_spec.rb +13 -0
- data/spec/lib/pwn/plugins/k8s_spec.rb +13 -0
- data/spec/lib/pwn/plugins/nuclei_spec.rb +13 -0
- data/spec/lib/pwn/plugins/preflight_checker_spec.rb +23 -0
- data/spec/lib/pwn/plugins/process_tube_spec.rb +13 -0
- data/spec/lib/pwn/plugins/radare2_spec.rb +13 -0
- data/spec/lib/pwn/plugins/recon_spec.rb +26 -0
- data/spec/lib/pwn/plugins/semgrep_spec.rb +13 -0
- data/spec/lib/pwn/plugins/sqlmap_spec.rb +13 -0
- data/spec/lib/pwn/plugins/volatility_spec.rb +13 -0
- data/spec/lib/pwn/req_queue_spec.rb +168 -0
- data/third_party/pwn_rdoc.jsonl +160 -5
- metadata +63 -7
- data/etc/default_skills/pwn/memory_index/references/urls.md +0 -4
- data/etc/default_skills/pwn/plugins/transparent_browser/references/urls.md +0 -3
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pty'
|
|
4
|
+
require 'timeout'
|
|
5
|
+
require 'socket'
|
|
6
|
+
|
|
7
|
+
module PWN
|
|
8
|
+
module Plugins
|
|
9
|
+
# PTY.spawn tube: sendline/recvuntil/recvline, persisted across pwn_eval.
|
|
10
|
+
module ProcessTube
|
|
11
|
+
@tubes = {}
|
|
12
|
+
|
|
13
|
+
public_class_method def self.required_bins
|
|
14
|
+
[]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
public_class_method def self.spawn(opts = {})
|
|
18
|
+
cmd = opts[:cmd] || opts[:command]
|
|
19
|
+
raise 'ERROR: cmd is required' if cmd.to_s.empty?
|
|
20
|
+
|
|
21
|
+
argv = cmd.is_a?(Array) ? cmd.map(&:to_s) : ['bash', '-lc', cmd.to_s]
|
|
22
|
+
r, w, pid = PTY.spawn(*argv)
|
|
23
|
+
id = "tube_#{pid}"
|
|
24
|
+
@tubes[id] = { r: r, w: w, pid: pid, buf: +'' }
|
|
25
|
+
{ id: id, pid: pid }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
public_class_method def self.connect(opts = {})
|
|
29
|
+
host = (opts[:host] || opts[:target]).to_s
|
|
30
|
+
port = opts[:port].to_i
|
|
31
|
+
raise 'ERROR: host and port are required' if host.empty? || port <= 0
|
|
32
|
+
|
|
33
|
+
sock = TCPSocket.new(host, port)
|
|
34
|
+
id = "sock_#{sock.object_id}"
|
|
35
|
+
@tubes[id] = { r: sock, w: sock, pid: nil, buf: +'' }
|
|
36
|
+
{ id: id, host: host, port: port }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
public_class_method def self.write_line(opts = {})
|
|
40
|
+
t = tube!(opts)
|
|
41
|
+
line = opts[:line] || opts[:data] || ''
|
|
42
|
+
t[:w].write("#{line}\n")
|
|
43
|
+
t[:w].flush
|
|
44
|
+
line.to_s
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
public_class_method def self.recvuntil(opts = {})
|
|
48
|
+
t = tube!(opts)
|
|
49
|
+
needle = opts[:until].to_s
|
|
50
|
+
raise 'ERROR: until is required' if needle.empty?
|
|
51
|
+
|
|
52
|
+
timeout = (opts[:timeout] || 5).to_f
|
|
53
|
+
Timeout.timeout(timeout) do
|
|
54
|
+
loop do
|
|
55
|
+
return t[:buf] if t[:buf].include?(needle)
|
|
56
|
+
|
|
57
|
+
ch = t[:r].read_nonblock(4_096)
|
|
58
|
+
t[:buf] << ch
|
|
59
|
+
rescue IO::WaitReadable
|
|
60
|
+
t[:r].wait_readable(0.2)
|
|
61
|
+
retry
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
public_class_method def self.recvline(opts = {})
|
|
67
|
+
recvuntil(opts.merge(until: "\n"))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
public_class_method def self.close(opts = {})
|
|
71
|
+
t = tube!(opts)
|
|
72
|
+
t[:w].close
|
|
73
|
+
t[:r].close
|
|
74
|
+
Process.kill('TERM', t[:pid]) if t[:pid]
|
|
75
|
+
@tubes.delete(opts[:id].to_s)
|
|
76
|
+
true
|
|
77
|
+
rescue StandardError
|
|
78
|
+
@tubes.delete(opts[:id].to_s)
|
|
79
|
+
false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
public_class_method def self.authors
|
|
83
|
+
"AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
public_class_method def self.help
|
|
87
|
+
puts "USAGE:
|
|
88
|
+
# List host binaries this module expects to be installed.
|
|
89
|
+
#{self}.required_bins
|
|
90
|
+
|
|
91
|
+
# Run spawn and return its result
|
|
92
|
+
#{self}.spawn(
|
|
93
|
+
cmd: 'required - command string to run (defaults to opts[:command])',
|
|
94
|
+
command: 'optional - command value consumed by #spawn'
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Connect a TCP tube with the same write_line/recvuntil API as spawn.
|
|
98
|
+
#{self}.connect(
|
|
99
|
+
host: 'required - hostname or IP address (defaults to opts[:target])',
|
|
100
|
+
target: 'optional - hostname, IP, or CIDR to scan',
|
|
101
|
+
port: 'required - TCP/UDP port number'
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Run write line and return its result
|
|
105
|
+
#{self}.write_line(
|
|
106
|
+
line: 'optional - line value consumed by #write_line',
|
|
107
|
+
data: 'optional - data value consumed by #write_line'
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Run recvuntil and return its result
|
|
111
|
+
#{self}.recvuntil(
|
|
112
|
+
until: 'required - until value consumed by #recvuntil',
|
|
113
|
+
timeout: 'optional - seconds to wait before giving up'
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Run recvline and return its result
|
|
117
|
+
#{self}.recvline
|
|
118
|
+
|
|
119
|
+
# Close a session previously returned by #open.
|
|
120
|
+
#{self}.close(
|
|
121
|
+
id: 'optional - id value consumed by #close'
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Print the AUTHOR(S) string for this module.
|
|
125
|
+
#{self}.authors
|
|
126
|
+
"
|
|
127
|
+
constants.sort
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private_class_method def self.tube!(opts = {})
|
|
131
|
+
id = opts[:id].to_s
|
|
132
|
+
t = @tubes[id]
|
|
133
|
+
raise 'ERROR: id is required / unknown tube' unless t
|
|
134
|
+
|
|
135
|
+
t
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
data/lib/pwn/plugins/ps.rb
CHANGED
|
@@ -76,14 +76,20 @@ module PWN
|
|
|
76
76
|
|
|
77
77
|
public_class_method def self.help
|
|
78
78
|
puts "USAGE:
|
|
79
|
-
|
|
79
|
+
# Run list and return its result
|
|
80
|
+
#{self}.list(
|
|
81
|
+
pid: 'optional - pid value consumed by #list'
|
|
82
|
+
)
|
|
80
83
|
|
|
84
|
+
# Run cleanup pids and return its result
|
|
81
85
|
#{self}.cleanup_pids(
|
|
82
86
|
pids_arr: 'required - array of pids to kill'
|
|
83
87
|
)
|
|
84
88
|
|
|
89
|
+
# Print the AUTHOR(S) string for this module.
|
|
85
90
|
#{self}.authors
|
|
86
91
|
"
|
|
92
|
+
constants.sort
|
|
87
93
|
end
|
|
88
94
|
end
|
|
89
95
|
end
|
|
@@ -53,11 +53,15 @@ module PWN
|
|
|
53
53
|
|
|
54
54
|
public_class_method def self.help
|
|
55
55
|
puts "USAGE:
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
# Run create and return its result
|
|
57
|
+
#{self}.create(
|
|
58
|
+
level: 'optional - level value consumed by #create'
|
|
58
59
|
)
|
|
60
|
+
|
|
61
|
+
# Print the AUTHOR(S) string for this module.
|
|
59
62
|
#{self}.authors
|
|
60
63
|
"
|
|
64
|
+
constants.sort
|
|
61
65
|
end
|
|
62
66
|
end
|
|
63
67
|
end
|
|
@@ -50,20 +50,25 @@ module PWN
|
|
|
50
50
|
# Display Usage for this Module
|
|
51
51
|
|
|
52
52
|
public_class_method def self.help
|
|
53
|
-
puts
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
puts "USAGE:
|
|
54
|
+
# Open a session or connection and return a handle.
|
|
55
|
+
#{self}.open(
|
|
56
|
+
hostname: 'required - hostname value consumed by #open',
|
|
56
57
|
port: 'optional - defaults to 5672',
|
|
57
|
-
username: 'optional',
|
|
58
|
-
password: 'optional'
|
|
58
|
+
username: 'optional - username value consumed by #open',
|
|
59
|
+
password: 'optional - password value consumed by #open'
|
|
59
60
|
)
|
|
60
61
|
|
|
62
|
+
# Close a session previously returned by #open.
|
|
61
63
|
#{self}.close(
|
|
62
|
-
amqp_oject:
|
|
64
|
+
amqp_oject: 'optional - amqp oject value consumed by #close',
|
|
65
|
+
amqp_obj: 'optional - amqp obj value consumed by #close'
|
|
63
66
|
)
|
|
64
67
|
|
|
68
|
+
# Print the AUTHOR(S) string for this module.
|
|
65
69
|
#{self}.authors
|
|
66
|
-
|
|
70
|
+
"
|
|
71
|
+
constants.sort
|
|
67
72
|
end
|
|
68
73
|
end
|
|
69
74
|
end
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'securerandom'
|
|
6
|
+
|
|
7
|
+
module PWN
|
|
8
|
+
module Plugins
|
|
9
|
+
# Persistent r2pipe-style session: open/cmd/cmdj/close plus helpers.
|
|
10
|
+
module Radare2
|
|
11
|
+
@sessions = {}
|
|
12
|
+
|
|
13
|
+
public_class_method def self.required_bins
|
|
14
|
+
%w[r2]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Supported Method Parameters::
|
|
18
|
+
# session = PWN::Plugins::Radare2.open(
|
|
19
|
+
# path: 'required - filesystem path to the binary r2 should open'
|
|
20
|
+
# )
|
|
21
|
+
public_class_method def self.open(opts = {})
|
|
22
|
+
PWN::Plugins::PreflightChecker.require_bin!(name: 'r2')
|
|
23
|
+
path = opts[:path].to_s
|
|
24
|
+
raise 'ERROR: path is required' if path.empty?
|
|
25
|
+
raise "ERROR: binary not found: #{path}" unless File.file?(path)
|
|
26
|
+
|
|
27
|
+
stdin, stdout, waiter = Open3.popen2('r2', '-q0', '-e', 'scr.color=0', path)
|
|
28
|
+
sid = SecureRandom.hex(8)
|
|
29
|
+
@sessions[sid] = { stdin: stdin, stdout: stdout, waiter: waiter, path: path }
|
|
30
|
+
read_until_null(io: stdout)
|
|
31
|
+
sid
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Supported Method Parameters::
|
|
35
|
+
# text = PWN::Plugins::Radare2.cmd(
|
|
36
|
+
# session: 'required - session id returned by #open',
|
|
37
|
+
# cmd: 'required - r2 command to run; returns raw text (e.g. pdf @ main)'
|
|
38
|
+
# )
|
|
39
|
+
public_class_method def self.cmd(opts = {})
|
|
40
|
+
sess = session!(opts)
|
|
41
|
+
line = opts[:cmd].to_s
|
|
42
|
+
raise 'ERROR: cmd is required' if line.empty?
|
|
43
|
+
|
|
44
|
+
sess[:stdin].write("#{line}\n")
|
|
45
|
+
sess[:stdin].flush
|
|
46
|
+
read_until_null(io: sess[:stdout])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Supported Method Parameters::
|
|
50
|
+
# json = PWN::Plugins::Radare2.cmdj(
|
|
51
|
+
# session: 'required - session id returned by #open',
|
|
52
|
+
# cmd: 'required - r2 command; trailing j is added if missing and stdout is JSON.parse (e.g. afl or aflj)'
|
|
53
|
+
# )
|
|
54
|
+
public_class_method def self.cmdj(opts = {})
|
|
55
|
+
raw = cmd(opts.merge(cmd: opts[:cmd].to_s.sub(/j?\z/, 'j')))
|
|
56
|
+
JSON.parse(raw)
|
|
57
|
+
rescue JSON::ParserError
|
|
58
|
+
raw
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Supported Method Parameters::
|
|
62
|
+
# PWN::Plugins::Radare2.close(
|
|
63
|
+
# session: 'required - session id returned by #open'
|
|
64
|
+
# )
|
|
65
|
+
public_class_method def self.close(opts = {})
|
|
66
|
+
sess = session!(opts)
|
|
67
|
+
sess[:stdin].write("q\n")
|
|
68
|
+
sess[:stdin].close
|
|
69
|
+
sess[:stdout].close
|
|
70
|
+
@sessions.delete(opts[:session].to_s)
|
|
71
|
+
true
|
|
72
|
+
rescue StandardError
|
|
73
|
+
@sessions.delete(opts[:session].to_s)
|
|
74
|
+
false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Supported Method Parameters::
|
|
78
|
+
# PWN::Plugins::Radare2.functions(
|
|
79
|
+
# session: 'required - session id returned by #open'
|
|
80
|
+
# )
|
|
81
|
+
public_class_method def self.functions(opts = {})
|
|
82
|
+
cmdj(opts.merge(cmd: 'aflj'))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Supported Method Parameters::
|
|
86
|
+
# PWN::Plugins::Radare2.xrefs_to(
|
|
87
|
+
# session: 'required - session id returned by #open',
|
|
88
|
+
# addr: 'required - address or flag to list xrefs to (e.g. main or 0x401000)'
|
|
89
|
+
# )
|
|
90
|
+
public_class_method def self.xrefs_to(opts = {})
|
|
91
|
+
addr = opts[:addr].to_s
|
|
92
|
+
cmdj(opts.merge(cmd: "axtj #{addr}"))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Supported Method Parameters::
|
|
96
|
+
# PWN::Plugins::Radare2.disasm(
|
|
97
|
+
# session: 'required - session id returned by #open',
|
|
98
|
+
# addr: 'required - address or flag to disassemble from',
|
|
99
|
+
# n: 'optional - instruction count (defaults to 32)'
|
|
100
|
+
# )
|
|
101
|
+
public_class_method def self.disasm(opts = {})
|
|
102
|
+
addr = opts[:addr].to_s
|
|
103
|
+
n = (opts[:n] || 32).to_i
|
|
104
|
+
cmd(opts.merge(cmd: "pd #{n} @ #{addr}"))
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Supported Method Parameters::
|
|
108
|
+
# PWN::Plugins::Radare2.strings(
|
|
109
|
+
# session: 'required - session id returned by #open'
|
|
110
|
+
# )
|
|
111
|
+
public_class_method def self.strings(opts = {})
|
|
112
|
+
cmdj(opts.merge(cmd: 'izj'))
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Supported Method Parameters::
|
|
116
|
+
# PWN::Plugins::Radare2.imports(
|
|
117
|
+
# session: 'required - session id returned by #open'
|
|
118
|
+
# )
|
|
119
|
+
public_class_method def self.imports(opts = {})
|
|
120
|
+
cmdj(opts.merge(cmd: 'iij'))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Supported Method Parameters::
|
|
124
|
+
# PWN::Plugins::Radare2.sections(
|
|
125
|
+
# session: 'required - session id returned by #open'
|
|
126
|
+
# )
|
|
127
|
+
public_class_method def self.sections(opts = {})
|
|
128
|
+
cmdj(opts.merge(cmd: 'iSj'))
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Supported Method Parameters::
|
|
132
|
+
# PWN::Plugins::Radare2.binary_info(
|
|
133
|
+
# session: 'required - session id returned by #open'
|
|
134
|
+
# )
|
|
135
|
+
public_class_method def self.binary_info(opts = {})
|
|
136
|
+
cmdj(opts.merge(cmd: 'iIj'))
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Supported Method Parameters::
|
|
140
|
+
# PWN::Plugins::Radare2.decompile(
|
|
141
|
+
# session: 'required - session id returned by #open',
|
|
142
|
+
# addr: 'required - address or flag to decompile (needs r2ghidra)'
|
|
143
|
+
# )
|
|
144
|
+
public_class_method def self.decompile(opts = {})
|
|
145
|
+
addr = opts[:addr].to_s
|
|
146
|
+
cmd(opts.merge(cmd: "pdg @ #{addr}"))
|
|
147
|
+
rescue StandardError => e
|
|
148
|
+
{ error: "#{e.class}: #{e.message}", hint: 'r2ghidra plugin may be absent' }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
public_class_method def self.authors
|
|
152
|
+
"AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
public_class_method def self.help
|
|
156
|
+
puts "USAGE:
|
|
157
|
+
# List host binaries this module expects to be installed.
|
|
158
|
+
#{self}.required_bins
|
|
159
|
+
|
|
160
|
+
# Open the binary in r2 (-q0) and return a session id.
|
|
161
|
+
#{self}.open(
|
|
162
|
+
path: 'required - filesystem path to the binary r2 should open'
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Run a command and return raw text output.
|
|
166
|
+
#{self}.cmd(
|
|
167
|
+
session: 'required - session id returned by #open',
|
|
168
|
+
cmd: 'required - r2 command to run; returns raw text (e.g. pdf @ main)'
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Run a command, request JSON, and parse the result.
|
|
172
|
+
#{self}.cmdj(
|
|
173
|
+
session: 'required - session id returned by #open',
|
|
174
|
+
cmd: 'required - r2 command; trailing j is added if missing and stdout is JSON.parse (e.g. afl or aflj)'
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Close a session previously returned by #open.
|
|
178
|
+
#{self}.close(
|
|
179
|
+
session: 'required - session id returned by #open'
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# List functions after analysis (aflj JSON).
|
|
183
|
+
#{self}.functions(
|
|
184
|
+
session: 'required - session id returned by #open'
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# List xrefs to an address or flag (axtj JSON).
|
|
188
|
+
#{self}.xrefs_to(
|
|
189
|
+
session: 'required - session id returned by #open',
|
|
190
|
+
addr: 'required - address or flag to list xrefs to (e.g. main or 0x401000)'
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Disassemble n instructions at addr (pd text).
|
|
194
|
+
#{self}.disasm(
|
|
195
|
+
session: 'required - session id returned by #open',
|
|
196
|
+
addr: 'required - address or flag to disassemble from',
|
|
197
|
+
n: 'optional - instruction count (defaults to 32)'
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# List strings in the binary (izj JSON).
|
|
201
|
+
#{self}.strings(
|
|
202
|
+
session: 'required - session id returned by #open'
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# List imported symbols (iij JSON).
|
|
206
|
+
#{self}.imports(
|
|
207
|
+
session: 'required - session id returned by #open'
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# List sections / segments (iSj JSON).
|
|
211
|
+
#{self}.sections(
|
|
212
|
+
session: 'required - session id returned by #open'
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Print binary header info (iIj JSON).
|
|
216
|
+
#{self}.binary_info(
|
|
217
|
+
session: 'required - session id returned by #open'
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Decompile a function at addr via r2ghidra (pdg text).
|
|
221
|
+
#{self}.decompile(
|
|
222
|
+
session: 'required - session id returned by #open',
|
|
223
|
+
addr: 'required - address or flag to decompile (needs r2ghidra)'
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Print the AUTHOR(S) string for this module.
|
|
227
|
+
#{self}.authors
|
|
228
|
+
"
|
|
229
|
+
constants.sort
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private_class_method def self.session!(opts = {})
|
|
233
|
+
sid = opts[:session].to_s
|
|
234
|
+
sess = @sessions[sid]
|
|
235
|
+
raise 'ERROR: session is required / unknown' unless sess
|
|
236
|
+
|
|
237
|
+
sess
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
private_class_method def self.read_until_null(opts = {})
|
|
241
|
+
io = opts[:io]
|
|
242
|
+
buf = +''
|
|
243
|
+
loop do
|
|
244
|
+
ch = io.read(1)
|
|
245
|
+
break if ch.nil? || ch == "\x00"
|
|
246
|
+
|
|
247
|
+
buf << ch
|
|
248
|
+
end
|
|
249
|
+
buf
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'net/http'
|
|
6
|
+
require 'uri'
|
|
7
|
+
require 'timeout'
|
|
8
|
+
|
|
9
|
+
module PWN
|
|
10
|
+
module Plugins
|
|
11
|
+
# subfinder/httpx/masscan wrappers + cert-transparency (crt.sh, certspotter).
|
|
12
|
+
module Recon
|
|
13
|
+
UA = 'pwn-recon/1.0'
|
|
14
|
+
|
|
15
|
+
public_class_method def self.required_bins
|
|
16
|
+
[]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
public_class_method def self.subdomains(opts = {})
|
|
20
|
+
domain = opts[:domain].to_s.downcase.strip
|
|
21
|
+
raise 'ERROR: domain is required' if domain.empty?
|
|
22
|
+
|
|
23
|
+
names = []
|
|
24
|
+
if PWN::Plugins::PreflightChecker.bin?(name: 'subfinder')
|
|
25
|
+
stdout, = Open3.capture3('subfinder', '-silent', '-d', domain)
|
|
26
|
+
names.concat(stdout.lines.map(&:strip).reject(&:empty?))
|
|
27
|
+
end
|
|
28
|
+
if PWN::Plugins::PreflightChecker.bin?(name: 'amass')
|
|
29
|
+
stdout, = Open3.capture3('amass', 'enum', '-passive', '-d', domain, '-nocolor')
|
|
30
|
+
names.concat(stdout.lines.map(&:strip).reject(&:empty?))
|
|
31
|
+
end
|
|
32
|
+
names.concat(Array(crt_sh(domain: domain)))
|
|
33
|
+
normalize_names(names: names, domain: domain)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
public_class_method def self.httpx(opts = {})
|
|
37
|
+
PWN::Plugins::PreflightChecker.require_bin!(name: 'httpx')
|
|
38
|
+
hosts = Array(opts[:hosts] || opts[:urls])
|
|
39
|
+
stdout, = Open3.capture3('httpx', '-silent', '-json', stdin_data: "#{hosts.join("\n")}\n")
|
|
40
|
+
stdout.each_line.filter_map do |ln|
|
|
41
|
+
JSON.parse(ln)
|
|
42
|
+
rescue JSON::ParserError
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
public_class_method def self.masscan(opts = {})
|
|
48
|
+
bin = %w[masscan naabu].find { |b| PWN::Plugins::PreflightChecker.bin?(name: b) }
|
|
49
|
+
raise PWN::Plugins::PreflightChecker::MissingBinary, 'ERROR: masscan/naabu missing' unless bin
|
|
50
|
+
|
|
51
|
+
target = opts[:target].to_s
|
|
52
|
+
ports = (opts[:ports] || '1-1024').to_s
|
|
53
|
+
stdout, = Open3.capture3(bin, '-p', ports, target)
|
|
54
|
+
stdout
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
public_class_method def self.crt_sh(opts = {})
|
|
58
|
+
domain = opts[:domain].to_s.downcase.strip
|
|
59
|
+
raise 'ERROR: domain is required' if domain.empty?
|
|
60
|
+
|
|
61
|
+
errors = []
|
|
62
|
+
names = []
|
|
63
|
+
sources = [
|
|
64
|
+
"https://api.certspotter.com/v1/issuances?domain=#{URI.encode_www_form_component(domain)}&include_subdomains=true&expand=dns_names",
|
|
65
|
+
"https://crt.sh/?q=#{URI.encode_www_form_component(domain)}&output=json",
|
|
66
|
+
"https://crt.sh/?q=#{URI.encode_www_form_component("%.#{domain}")}&output=json"
|
|
67
|
+
]
|
|
68
|
+
sources.each do |url|
|
|
69
|
+
next if !names.empty? && url.include?('crt.sh')
|
|
70
|
+
|
|
71
|
+
rows = http_json(url: url, timeout: url.include?('crt.sh') ? 8 : (opts[:timeout] || 15))
|
|
72
|
+
names.concat(extract_dns_names(rows: rows))
|
|
73
|
+
rescue StandardError => e
|
|
74
|
+
errors << "#{URI(url).host}: #{e.class}: #{e.message}"
|
|
75
|
+
end
|
|
76
|
+
out = normalize_names(names: names, domain: domain)
|
|
77
|
+
return out unless out.empty?
|
|
78
|
+
|
|
79
|
+
raise "ERROR: cert-transparency lookup failed for #{domain} (#{errors.join('; ')})"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
public_class_method def self.amass(opts = {})
|
|
83
|
+
PWN::Plugins::PreflightChecker.require_bin!(name: 'amass')
|
|
84
|
+
domain = opts[:domain].to_s
|
|
85
|
+
raise 'ERROR: domain is required' if domain.empty?
|
|
86
|
+
|
|
87
|
+
stdout, = Open3.capture3('amass', 'enum', '-passive', '-d', domain, '-nocolor')
|
|
88
|
+
stdout.lines.map(&:strip).reject(&:empty?)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
public_class_method def self.passive_dns(opts = {})
|
|
92
|
+
domain = opts[:domain].to_s.downcase.strip
|
|
93
|
+
raise 'ERROR: domain is required' if domain.empty?
|
|
94
|
+
|
|
95
|
+
uri = URI("https://api.hackertarget.com/hostsearch/?q=#{URI.encode_www_form_component(domain)}")
|
|
96
|
+
rows = http_json(url: uri.to_s, timeout: opts[:timeout] || 8)
|
|
97
|
+
Array(rows)
|
|
98
|
+
rescue StandardError => e
|
|
99
|
+
{ error: "#{e.class}: #{e.message}", domain: domain }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
public_class_method def self.authors
|
|
103
|
+
"AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
public_class_method def self.help
|
|
107
|
+
puts "USAGE:
|
|
108
|
+
# List host binaries this module expects to be installed.
|
|
109
|
+
#{self}.required_bins
|
|
110
|
+
|
|
111
|
+
# Run subdomains and return its result
|
|
112
|
+
#{self}.subdomains(
|
|
113
|
+
domain: 'required - FQDN to query (e.g. example.com)'
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Run httpx and return its result
|
|
117
|
+
#{self}.httpx(
|
|
118
|
+
hosts: 'optional - Array of hostnames or URLs to probe',
|
|
119
|
+
urls: 'optional - Array of HTTP(S) URLs'
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Run masscan and return its result
|
|
123
|
+
#{self}.masscan(
|
|
124
|
+
target: 'optional - hostname, IP, or CIDR to scan',
|
|
125
|
+
ports: 'optional - port, list, or range (e.g. 22,80,443 or 1-1024)'
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Run crt sh and return its result
|
|
129
|
+
#{self}.crt_sh(
|
|
130
|
+
domain: 'required - FQDN to query (e.g. example.com)',
|
|
131
|
+
timeout: 'optional - seconds to wait before giving up'
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Passive amass enum (requires amass).
|
|
135
|
+
#{self}.amass(
|
|
136
|
+
domain: 'required - FQDN to query (e.g. example.com)'
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Passive DNS hostsearch for a domain (hackertarget).
|
|
140
|
+
#{self}.passive_dns(
|
|
141
|
+
domain: 'required - FQDN to query (e.g. example.com)',
|
|
142
|
+
timeout: 'optional - seconds to wait before giving up'
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Print the AUTHOR(S) string for this module.
|
|
146
|
+
#{self}.authors
|
|
147
|
+
"
|
|
148
|
+
constants.sort
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
private_class_method def self.http_json(opts = {})
|
|
152
|
+
uri = URI(opts[:url].to_s)
|
|
153
|
+
timeout = (opts[:timeout] || 15).to_i
|
|
154
|
+
req = Net::HTTP::Get.new(uri)
|
|
155
|
+
req['User-Agent'] = UA
|
|
156
|
+
req['Accept'] = 'application/json'
|
|
157
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
158
|
+
http.use_ssl = (uri.scheme == 'https')
|
|
159
|
+
http.open_timeout = [timeout, 8].min
|
|
160
|
+
http.read_timeout = timeout
|
|
161
|
+
http.max_retries = 0
|
|
162
|
+
res = Timeout.timeout(timeout + 2) { http.request(req) }
|
|
163
|
+
raise "HTTP #{res.code}" unless res.is_a?(Net::HTTPSuccess)
|
|
164
|
+
|
|
165
|
+
body = res.body.to_s
|
|
166
|
+
raise JSON::ParserError, body[0, 120] unless body.lstrip.start_with?('[', '{')
|
|
167
|
+
|
|
168
|
+
JSON.parse(body)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
private_class_method def self.extract_dns_names(opts = {})
|
|
172
|
+
rows = opts[:rows]
|
|
173
|
+
return [] if rows.nil?
|
|
174
|
+
|
|
175
|
+
Array(rows).flat_map do |row|
|
|
176
|
+
next [] unless row.is_a?(Hash)
|
|
177
|
+
|
|
178
|
+
vals = []
|
|
179
|
+
vals.concat(Array(row['dns_names'] || row[:dns_names]))
|
|
180
|
+
vals.concat(row['name_value'].to_s.split(/[\s,]+/))
|
|
181
|
+
vals.concat(row['common_name'].to_s.split(/[\s,]+/))
|
|
182
|
+
vals
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
private_class_method def self.normalize_names(opts = {})
|
|
187
|
+
domain = opts[:domain].to_s.downcase
|
|
188
|
+
Array(opts[:names]).map { |n| n.to_s.strip.downcase.delete_prefix('*.') }
|
|
189
|
+
.reject(&:empty?)
|
|
190
|
+
.select { |n| n == domain || n.end_with?(".#{domain}") }
|
|
191
|
+
.uniq
|
|
192
|
+
.sort
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|