├── .envrc ├── .gitignore ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature-request.yml │ └── bug-report.yml ├── dependabot.yml ├── releaser.sh └── workflows │ ├── build-app.yml │ └── release.yml ├── src ├── commands │ ├── fuzz │ │ ├── mod.rs │ │ └── fuzzer.rs │ ├── rdns │ │ ├── mod.rs │ │ └── rev_dns.rs │ ├── status │ │ ├── mod.rs │ │ └── statuscode.rs │ ├── takeover │ │ ├── mod.rs │ │ └── sub_takeover.rs │ ├── urldencode.rs │ └── mod.rs ├── interface │ ├── mod.rs │ ├── args.rs │ ├── splashes.rs │ └── sub_args.rs ├── main.rs ├── log.rs └── engine.rs ├── tests ├── test_rdns.txt ├── fuzzing.txt ├── test_takeover.txt ├── signatures.json ├── test_fuzzing.txt ├── test-redirect.txt ├── test_status.txt └── signatures_full.json ├── flake.lock ├── LICENSE ├── Cargo.toml ├── flake.nix ├── CHANGELOG.md ├── README.md └── Cargo.lock /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .direnv 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: pwnwriter 2 | -------------------------------------------------------------------------------- /src/commands/fuzz/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod fuzzer; 2 | -------------------------------------------------------------------------------- /src/commands/rdns/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod rev_dns; 2 | -------------------------------------------------------------------------------- /src/commands/status/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod statuscode; 2 | -------------------------------------------------------------------------------- /tests/test_rdns.txt: -------------------------------------------------------------------------------- 1 | 1.1.1.1 2 | 192.30.252.153 3 | 8.8.8.8 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | -------------------------------------------------------------------------------- /tests/fuzzing.txt: -------------------------------------------------------------------------------- 1 | https://FUZZ/hackerone.com 2 | https://metislinux.org/FUZZ 3 | 4 | -------------------------------------------------------------------------------- /src/interface/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod args; 2 | pub mod splashes; 3 | pub mod sub_args; 4 | 5 | pub use sub_args::*; 6 | -------------------------------------------------------------------------------- /tests/test_takeover.txt: -------------------------------------------------------------------------------- 1 | https://checkingifitexists.github.io 2 | https://pwnwriter.xyz 3 | https://letscheckthis.github.io 4 | http://letscheckthisone.s3.amazonaws.com 5 | http://isitpossibleornot.wordpress.com 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # version: 2 2 | # updates: 3 | # # Maintain dependencies for Cargo 4 | # - package-ecosystem: cargo 5 | # directory: "/" 6 | # schedule: 7 | # interval: daily 8 | # open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/releaser.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Trigger release action on new release 4 | 5 | if [ -z "$1" ]; then 6 | echo "Please provide a version number." 7 | echo "Usages: $0 v[X.Y.Z]" 8 | exit 1 9 | fi 10 | 11 | version=$1 12 | 13 | git tag "v$version" 14 | git push origin "v$version" 15 | -------------------------------------------------------------------------------- /tests/signatures.json: -------------------------------------------------------------------------------- 1 | { 2 | "platforms": [ 3 | { 4 | "platform": "GitHub Pages", 5 | "content": [ 6 | "

There isn't a GitHub Pages site here.

", 7 | "For root URLs (like http://example.com/) you must provide an index.html file" 8 | ] 9 | } 10 | 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod commands; 2 | mod engine; 3 | mod interface; 4 | mod log; 5 | 6 | //  asynchronous entry point where the magic happens :dizzy:  7 | #[tokio::main] 8 | #[allow(clippy::needless_return)] 9 | async fn main() { 10 | // Simply await the engine's start method 11 | engine::start().await; 12 | } 13 | -------------------------------------------------------------------------------- /tests/test_fuzzing.txt: -------------------------------------------------------------------------------- 1 | .npm 2 | .npmignore 3 | .npmrc 4 | .nra.cache 5 | .nrepl-port 6 | .nsconfig 7 | .nsf 8 | .ntvs_analysis.dat 9 | .nuget/ 10 | .nuget/packages.config 11 | .nyc_output 12 | .old 13 | .old.env 14 | .oldsnippets 15 | .oldstatic 16 | .org-id-locations 17 | .ost 18 | .packages 19 | .paket/ 20 | .pass 21 | .passes 22 | .passwd 23 | .password 24 | .env 25 | projects 26 | guestbook 27 | blog 28 | guestbook 29 | dist 30 | -------------------------------------------------------------------------------- /.github/workflows/build-app.yml: -------------------------------------------------------------------------------- 1 | name: Run on Changes 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'src/*' 7 | - 'flake.*' 8 | - 'Cargo.*' 9 | pull_request: 10 | paths: 11 | - 'src/*' 12 | - 'flake.*' 13 | - 'Cargo.*' 14 | 15 | jobs: 16 | run-tests: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v2 22 | 23 | - name: Nix build 24 | run: | 25 | nix build 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Describe a feature you want to see 3 | labels: [feature-request] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: "Description" 8 | description: "A clear and concise description of the feature you are requesting" 9 | validations: 10 | required: true 11 | - type: input 12 | attributes: 13 | label: "Related Documentation or Links" 14 | description: "Provide any supporting documents, links, or references that can help in understanding or implementing the feature." 15 | validations: 16 | required: false 17 | -------------------------------------------------------------------------------- /src/commands/takeover/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod sub_takeover; 2 | 3 | pub mod takeover_helper { 4 | 5 | use crate::log::abort; 6 | 7 | const JSON_URL: &str = "https://raw.githubusercontent.com/Pentester-Nepal/Subdomain-Takeover-Signatures/main/signatures.json"; 8 | 9 | pub async fn get_signatures_from_repo() -> Result { 10 | let response = reqwest::get(JSON_URL).await?; 11 | 12 | if response.status().is_success() { 13 | let json_text = response.text().await?; 14 | Ok(json_text) 15 | } else { 16 | abort("Couldn't fetch default json, parse manualy"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1725816686, 6 | "narHash": "sha256-0Kq2MkQ/sQX1rhWJ/ySBBQlBJBUK8mPMDcuDhhdBkSU=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "add0443ee587a0c44f22793b8c8649a0dbc3bb00", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "ref": "nixpkgs-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /src/log.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | use colored::{Color, Colorize}; 4 | 5 | /// Prints the given message to the console and aborts the process. 6 | pub fn abort(msg: &str) -> ! { 7 | error(msg); 8 | std::process::exit(1); 9 | } 10 | 11 | pub fn info(msg: &str, color: Color) { 12 | println!("{}: {}", "Info".bold().color(color), msg); 13 | } 14 | 15 | pub fn message(msg: &str, color: Color) { 16 | println!("Message: {}", msg.bold().color(color)); 17 | } 18 | 19 | pub fn error(msg: &str) { 20 | println!("{}: {}", "Error".bold().color(Color::Red), msg); 21 | } 22 | 23 | pub fn success(msg: &str) { 24 | println!("{}: {}", "Success".bold().color(Color::Green), msg); 25 | } 26 | 27 | pub fn warn(msg: &str) { 28 | println!("{}: {}", "Warning".bold().color(Color::Yellow), msg); 29 | } 30 | -------------------------------------------------------------------------------- /src/engine.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | commands::{ 3 | fuzz::fuzzer::fuzz_url, rdns::rev_dns::reverse_dns_lookup, 4 | status::statuscode::handle_status_command, takeover::sub_takeover::subdomain_takeover, 5 | urldencode::dencode_urls, 6 | }, 7 | interface::args::{Cli, CommandChoice}, 8 | log::abort, 9 | }; 10 | use clap::Parser; 11 | 12 | pub async fn start() { 13 | let cli = Cli::parse(); 14 | 15 | let result = match cli.command { 16 | CommandChoice::Status(status_args) => handle_status_command(status_args).await, 17 | CommandChoice::Fuzzer(fuzz_args) => fuzz_url(fuzz_args).await, 18 | CommandChoice::Rdns(rdns_args) => reverse_dns_lookup(rdns_args).await, 19 | CommandChoice::Takeover(takeover_args) => subdomain_takeover(takeover_args).await, 20 | CommandChoice::Dencode(dencode_args) => dencode_urls(dencode_args).await, 21 | }; 22 | 23 | if let Err(err) = result { 24 | abort(&format!("{}", err)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 PwnWriter < pwnwriter.xyz > 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/interface/args.rs: -------------------------------------------------------------------------------- 1 | use crate::interface::{splashes::show_splashes, sub_args::*}; 2 | use clap::{Parser, Subcommand}; 3 | 4 | /// The KANHA CLI. 5 | #[derive(Parser)] 6 | #[command(author, version, about = show_splashes(), long_about = show_splashes())] 7 | #[command(propagate_version = true)] 8 | #[command(arg_required_else_help = true)] 9 | pub struct Cli { 10 | /// The command to execute. 11 | #[clap(subcommand)] 12 | pub command: CommandChoice, 13 | } 14 | 15 | #[derive(Subcommand)] 16 | pub enum CommandChoice { 17 | /// Just return the HTTP response code of urls 18 | #[command(arg_required_else_help = true)] 19 | #[clap(name = "status")] 20 | Status(StatusArgs), 21 | 22 | /// Fuzz urls and return the response codes 23 | #[command(arg_required_else_help = true)] 24 | #[clap(name = "fuzz")] 25 | Fuzzer(FuzzerArgs), 26 | 27 | /// Reverse dns lookup 28 | #[command(arg_required_else_help = true)] 29 | #[clap(name = "rdns")] 30 | Rdns(RdnsArgs), 31 | 32 | /// Check possible subdomain takeover vulnerability 33 | #[command(arg_required_else_help = true)] 34 | #[clap(name = "takeover")] 35 | Takeover(TakeoverArgs), 36 | 37 | /// (De|En) code urls 38 | #[command(arg_required_else_help = true)] 39 | #[clap(name = "urldencode")] 40 | Dencode(DencodeArgs), 41 | } 42 | -------------------------------------------------------------------------------- /src/commands/rdns/rev_dns.rs: -------------------------------------------------------------------------------- 1 | use crate::commands::kanha_helpers::{read_lines, read_urls_from_stdin}; 2 | use crate::interface::RdnsArgs; 3 | use dns_lookup::lookup_addr; 4 | 5 | #[allow(non_snake_case)] 6 | pub fn Rdns(ip_addr: std::net::IpAddr) -> Result> { 7 | let host = lookup_addr(&ip_addr)?; 8 | 9 | Ok(host.to_string()) 10 | } 11 | 12 | pub async fn reverse_dns_lookup(rdns_args: RdnsArgs) -> Result<(), Box> { 13 | // Type Result, Box> 14 | let ip_addresses = if rdns_args.stdin { 15 | read_urls_from_stdin() 16 | } else if let Some(filename) = rdns_args.filename { 17 | let lines_result: Result, _> = read_lines(&filename).await?.collect(); 18 | Ok(lines_result?) 19 | } else { 20 | Err("Either stdin or filename must be provided")? 21 | }; 22 | 23 | let ip_addresses = ip_addresses?; 24 | 25 | for line in ip_addresses { 26 | match line.parse() { 27 | Ok(ip_addr) => match Rdns(ip_addr) { 28 | Ok(hostname) => println!("{} => {}", line, hostname), 29 | Err(e) => eprintln!("Error looking up {}: {}", line, e), 30 | }, 31 | Err(e) => eprintln!("Error parsing IP address {}: {}", line, e), 32 | } 33 | } 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "kanha" 3 | version = "0.1.2" 4 | edition = "2021" 5 | authors = [ "PwnWriter < hey@pwnwriter.xyz >" ] 6 | description = "🦚 Compile once, Hack forever" 7 | readme = "README.md" 8 | repository = "https://github.com/pwnwriter/kanha" 9 | homepage = "https://github.com/pwnwriter/kanha.git" 10 | license = "MIT" 11 | keywords = ["recon", "red_teaming", "pentesting", "osint"] 12 | categories = ["accessibility", "web-programming", "command-line" ] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | clap = { version = "4.4.11", features = ["derive", "string"] } 18 | reqwest = { version = "0.11.20", default-features = false, features = ["json", "rustls-tls"] } 19 | tokio = { version = "1.33.0", features = ["full"] } 20 | serde = { version = "1.0.193", features = ["derive"] } 21 | colored = "2.0.4" 22 | futures = "0.3.30" 23 | lazy_static = "1.4.0" 24 | dns-lookup = "2.0.4" 25 | serde_json = "1.0.108" 26 | urlencoding = "2.1.3" 27 | anyhow = "1.0.75" 28 | 29 | [profile.dev] 30 | opt-level = 0 31 | debug = true 32 | panic = "abort" 33 | 34 | [profile.test] 35 | opt-level = 0 36 | debug = true 37 | 38 | [profile.release] 39 | opt-level = 3 40 | debug = false 41 | panic = "unwind" 42 | lto = true 43 | codegen-units = 1 44 | 45 | [profile.bench] 46 | opt-level = 3 47 | debug = false 48 | 49 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report a problem 3 | labels: [bug] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: "Description" 8 | description: "A brief summary of the issue" 9 | validations: 10 | required: true 11 | - type: input 12 | attributes: 13 | label: "Software Version" 14 | description: "Please provide the version number, e.g., `0.1.1`" 15 | validations: 16 | required: true 17 | - type: textarea 18 | attributes: 19 | label: "Steps to Reproduce" 20 | description: "Detailed steps to reproduce the issue. If possible, please provide a sample command or actions taken." 21 | validations: 22 | required: true 23 | - type: textarea 24 | attributes: 25 | label: "Expected Behavior" 26 | description: "A clear description of what you expected to happen" 27 | validations: 28 | required: true 29 | - type: textarea 30 | attributes: 31 | label: "Actual Behavior" 32 | description: "A description of the behavior you observed. Feel free to include images, gifs, or any other supporting materials." 33 | validations: 34 | required: true 35 | - type: textarea 36 | attributes: 37 | label: "Additional Information" 38 | description: "Any additional information that might be helpful in understanding the context or environment in which the issue occurred" 39 | validations: 40 | required: false 41 | -------------------------------------------------------------------------------- /src/commands/urldencode.rs: -------------------------------------------------------------------------------- 1 | use crate::{commands::kanha_helpers::read_lines, interface::DencodeArgs, log::abort}; 2 | use urlencoding::{decode, encode}; 3 | 4 | pub async fn dencode_urls(dencode_args: DencodeArgs) -> Result<(), Box> { 5 | match (dencode_args.encode.as_ref(), dencode_args.decode.as_ref()) { 6 | (Some(filename), None) => { 7 | let urls = read_lines(filename).await?; 8 | for line_result in urls { 9 | let url = line_result?; 10 | let encoded_url = encode(&url); 11 | println!("{}", encoded_url); 12 | } 13 | } 14 | (None, Some(filename)) => { 15 | let urls = read_lines(filename).await?; 16 | for line_result in urls { 17 | let url = line_result?; 18 | let decoded_url = decode(&url); 19 | println!( 20 | "{}", 21 | decoded_url.unwrap_or_else(|err| { 22 | println!("error decoding URL: {:?}", err); 23 | abort("something went wrong while decoding URLs"); 24 | }) 25 | ); 26 | } 27 | } 28 | (Some(_), Some(_)) => { 29 | println!("Both encode and decode options provided. Please provide only one."); 30 | } 31 | (None, None) => { 32 | println!("No encode or decode option provided."); 33 | } 34 | } 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /src/interface/splashes.rs: -------------------------------------------------------------------------------- 1 | // LICENSE: https://en.wikipedia.org/wiki/Creative_Commons_license 2 | 3 | use colored::Colorize; 4 | 5 | pub static SPLASHES: &[&str] = &[ 6 | "There are reasons to use rust. - PwnWriter", 7 | "whatsoever a man soweth, that shall he also reap. - Dylanaraps", 8 | "Bounty plss, this time - Knight_yagami", 9 | "Hacking in a nutshell", 10 | "In the world of programming, curiosity is the compass. - Ashokcpg", 11 | "Compile once, Hack forever - PwnWriter", 12 | "I want my system to hack!! wOoO", 13 | "Hello everyone, this is your daily dose for Bounty - PwnWriter", 14 | "Why no work?, Bro RTFM :/", 15 | ]; 16 | 17 | // Not using rand crate anymore 18 | // https://users.rust-lang.org/t/cheap-random-number-generator-with-std/90589/6 19 | 20 | fn generate_random_number() -> usize { 21 | let current_time = std::time::SystemTime::now() 22 | .duration_since(std::time::SystemTime::UNIX_EPOCH) 23 | .expect("Time went backwards") 24 | .as_micros(); 25 | 26 | (current_time % SPLASHES.len() as u128) as usize 27 | } 28 | 29 | pub fn show_splashes() -> String { 30 | let rng = generate_random_number(); 31 | 32 | let kanha_version = env!("CARGO_PKG_VERSION"); 33 | 34 | let logo = format!( 35 | r#" 36 | ┓┏┓ ┓ 37 | ┃┫ ┏┓┏┓┣┓┏┓ 38 | ┛┗┛┗┻┛┗┛┗┗┻ v{} 39 | "#, 40 | kanha_version, 41 | ) 42 | .bold() 43 | .purple(); 44 | let splash = SPLASHES[rng].italic(); 45 | format!("{logo} {splash}") 46 | } 47 | -------------------------------------------------------------------------------- /src/commands/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod fuzz; 2 | pub mod rdns; 3 | pub mod status; 4 | pub mod takeover; 5 | pub mod urldencode; 6 | pub use status::*; 7 | 8 | #[allow(dead_code)] 9 | pub mod kanha_helpers { 10 | use crate::interface::splashes::show_splashes; 11 | use crate::log::abort; 12 | use std::fs::File; 13 | use std::io::{self, BufRead}; 14 | 15 | /// https://doc.rust-lang.org/rust-by-example/std_misc/rile/read_lines.html 16 | /// Reads a file line by line and returns an iterator for reading those lines, or aborts with a message if the file doesn't exist. 17 | #[inline] 18 | pub async fn read_lines(filename: &str) -> anyhow::Result>> { 19 | match File::open(filename) { 20 | Ok(file) => Ok(io::BufReader::new(file).lines()), 21 | Err(_) => { 22 | abort("No such file in this location"); 23 | } 24 | } 25 | } 26 | 27 | /// https://www.youtube.com/watch?v=K_wnB9ibCMg&t=1078s 28 | /// Reads lines from the standard input, collects them into a Vec using the collect method, and returns the result 29 | #[inline] 30 | pub fn read_urls_from_stdin() -> anyhow::Result> { 31 | Ok(io::read_to_string(io::stdin().lock())? 32 | .lines() 33 | .map(|url| url.trim().to_owned()) 34 | .collect()) 35 | } 36 | 37 | #[inline] 38 | pub fn print_info() { 39 | let banner = show_splashes(); 40 | println!("{}", banner); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/test-redirect.txt: -------------------------------------------------------------------------------- 1 | /%09/example.com 2 | /%2f%2fexample.com 3 | /%2f%5c%2f%67%6f%6f%67%6c%65%2e%63%6f%6d/ 4 | /%5cexample.com 5 | /%68%74%74%70%3a%2f%2f%67%6f%6f%67%6c%65%2e%63%6f%6d 6 | /.example.com 7 | //%09/example.com 8 | //%5cexample.com 9 | ///%09/example.com 10 | ///%5cexample.com 11 | ////%09/example.com 12 | ////%5cexample.com 13 | /////example.com 14 | /////example.com/ 15 | ////\;@example.com 16 | ////example.com/ 17 | ////example.com/%2e%2e 18 | ////example.com/%2e%2e%2f 19 | ////example.com/%2f%2e%2e 20 | ////example.com/%2f.. 21 | ////example.com// 22 | ///\;@example.com 23 | ///example.com 24 | ///example.com/ 25 | ///example.com/%2e%2e 26 | ///example.com/%2e%2e%2f 27 | ///example.com/%2f%2e%2e 28 | ///example.com/%2f.. 29 | ///example.com// 30 | //example.com 31 | //example.com/ 32 | //example.com/%2e%2e 33 | //example.com/%2e%2e%2f 34 | //example.com/%2f%2e%2e 35 | //example.com/%2f.. 36 | //example.com// 37 | //google%00.com 38 | //google%E3%80%82com 39 | //https:///example.com/%2e%2e 40 | //https://example.com/%2e%2e%2f 41 | //https://example.com// 42 | /<>//example.com 43 | /?url=//example.com&next=//example.com&redirect=//example.com&redir=//example.com&rurl=//example.com&redirect_uri=//example.com 44 | /?url=/\/example.com&next=/\/example.com&redirect=/\/example.com&redirect_uri=/\/example.com 45 | /?url=Https://example.com&next=Https://example.com&redirect=Https://example.com&redir=Https://example.com&rurl=Https://example.com&redirect_uri=Https://example.com 46 | /\/\/example.com/ 47 | /\/example.com/ 48 | /example.com/%2f%2e%2e 49 | /http://%67%6f%6f%67%6c%65%2e%63%6f%6d 50 | /http://example.com 51 | /http:/example.com 52 | /https:/%5cexample.com/ 53 | /https://%09/example.com 54 | /https://%5cexample.com 55 | /https:///example.com/%2e%2e 56 | /https:///example.com/%2f%2e%2e 57 | /https://example.com 58 | /https://example.com/ 59 | /https://example.com/%2e%2e 60 | /https://example.com/%2e%2e%2f 61 | /https://example.com/%2f%2e%2e 62 | /https://example.com/%2f.. 63 | /https://example.com// 64 | /https:example.com 65 | /redirect?url=//example.com&next=//example.com&redirect=//example.com&redir=//example.com&rurl=//example.com&redirect_uri=//example.com 66 | /redirect?url=/\/example.com&next=/\/example.com&redirect=/\/example.com&redir=/\/example.com&rurl=/\/example.com&redirect_uri=/\/example.com 67 | /redirect?url=Https://example.com&next=Https://example.com&redirect=Https://example.com&redir=Https://example.com&rurl=Https://example.com&redirect_uri=Http 68 | 69 | -------------------------------------------------------------------------------- /src/interface/sub_args.rs: -------------------------------------------------------------------------------- 1 | use clap::Args; 2 | 3 | #[derive(Debug, Args, Clone)] 4 | #[group(required = false, multiple = false, conflicts_with = "stdin")] 5 | pub struct Input { 6 | /// A single url 7 | #[arg(short, long)] 8 | pub url: Option, 9 | 10 | /// Path of the file containing multiple urls 11 | #[arg(short, long)] 12 | pub file_path: Option, 13 | } 14 | 15 | #[derive(Args, Clone)] 16 | pub struct StatusArgs { 17 | /// A file containing multiple urls 18 | #[arg(short, long)] 19 | #[arg(required = false, conflicts_with = "stdin")] 20 | pub filename: Option, 21 | 22 | /// Define the maximum concurrent tasks 23 | #[arg(short, long, default_value = "20")] 24 | pub tasks: usize, 25 | 26 | /// Reads input from the standard in 27 | #[arg(long)] 28 | pub stdin: bool, 29 | 30 | /// Define your status code for selective exclusion. 31 | #[arg(long)] 32 | pub exclude: Option, 33 | } 34 | 35 | #[derive(Args)] 36 | pub struct FuzzerArgs { 37 | /// A file containing a list of payloads 38 | #[arg(required = true, short, long)] 39 | pub payloads: String, 40 | 41 | #[command(flatten)] 42 | pub input: Input, 43 | 44 | /// Define the maximum concurrent tasks. 45 | #[arg(short, long, default_value = "20")] 46 | pub tasks: usize, 47 | 48 | /// Define your status code for selective exclusion. 49 | #[arg(long)] 50 | pub exclude: Option, 51 | 52 | /// Reads input from the standard in 53 | #[arg(long)] 54 | pub stdin: bool, 55 | } 56 | 57 | #[derive(Args, Clone)] 58 | pub struct TakeoverArgs { 59 | #[command(flatten)] 60 | pub input: Input, 61 | 62 | /// A json file containing signature values of different services (if you don't provide it uses default one) 63 | #[arg(required = false, short, long)] 64 | pub json_file: Option, 65 | 66 | /// Reads input from the standard in 67 | #[arg(long)] 68 | pub stdin: bool, 69 | } 70 | 71 | #[derive(Args)] 72 | pub struct RdnsArgs { 73 | /// a file containing a list of possible wordlists 74 | #[arg(required = true, conflicts_with = "stdin", short, long)] 75 | pub filename: Option, 76 | 77 | /// Reads input from the standard in 78 | #[arg(long)] 79 | pub stdin: bool, 80 | } 81 | 82 | #[derive(Args)] 83 | pub struct DencodeArgs { 84 | /// Provide a url to encode 85 | #[arg(required = false, conflicts_with = "decode", long)] 86 | pub encode: Option, 87 | 88 | /// Provide a url to dencode 89 | #[arg(required = false, long)] 90 | pub decode: Option, 91 | } 92 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "kanha"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 6 | }; 7 | 8 | outputs = 9 | { self, nixpkgs, ... }: 10 | let 11 | forAllSystems = 12 | function: 13 | nixpkgs.lib.genAttrs [ 14 | "x86_64-linux" 15 | "aarch64-linux" 16 | "x86_64-darwin" 17 | "aarch64-darwin" 18 | ] (system: function nixpkgs.legacyPackages.${system}); 19 | 20 | darwinDeps = 21 | pkgs: with pkgs; [ 22 | darwin.apple_sdk.frameworks.SystemConfiguration 23 | libiconv 24 | ]; 25 | in 26 | { 27 | devShells = forAllSystems (pkgs: { 28 | default = pkgs.mkShell { 29 | name = "bwatch"; 30 | packages = 31 | (with pkgs; [ 32 | # cargo 33 | # cargo-edit 34 | # clippy 35 | # rustc 36 | ]) 37 | ++ (pkgs.lib.optional pkgs.stdenvNoCC.isDarwin (darwinDeps pkgs)); 38 | }; 39 | }); 40 | formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style); 41 | packages = forAllSystems (pkgs: { 42 | bwatch = 43 | with pkgs; 44 | let 45 | fs = lib.fileset; 46 | sourceFiles = fs.unions [ 47 | ./Cargo.lock 48 | ./Cargo.toml 49 | ./src 50 | ]; 51 | 52 | cargoToml = with builtins; (fromTOML (readFile ./Cargo.toml)); 53 | pname = cargoToml.package.name; 54 | version = cargoToml.package.version; 55 | cargoLock.lockFile = ./Cargo.lock; 56 | darwinBuildInputs = (darwinDeps pkgs); 57 | in 58 | pkgs.rustPlatform.buildRustPackage { 59 | inherit pname version cargoLock; 60 | src = fs.toSource { 61 | root = ./.; 62 | fileset = sourceFiles; 63 | }; 64 | nativeBuildInputs = [ 65 | clippy 66 | rustfmt 67 | openssl 68 | ]; 69 | buildInputs = [ ] ++ lib.optionals stdenv.isDarwin darwinBuildInputs; 70 | preBuildPhases = [ "cargoFmt" ]; 71 | cargoFmt = '' 72 | cargo fmt --manifest-path ./Cargo.toml --all --check 73 | ''; 74 | # right after checkPhase (tests) 75 | preInstallPhases = [ "clippy" ]; 76 | clippy = '' 77 | cargo clippy -- --deny warnings 78 | ''; 79 | }; 80 | default = self.packages.${pkgs.system}.bwatch; 81 | }); 82 | apps = forAllSystems (pkgs: { 83 | default = { 84 | type = "app"; 85 | program = "${self.packages.${pkgs.system}.bwatch}/bin/bwatch"; 86 | }; 87 | }); 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## [0.1.2] - 2023-10-17 6 | 7 | ### Features 8 | 9 | - Use default json if the end user don't provide one 10 | 11 | ### Miscellaneous Tasks 12 | 13 | - Prepare changelog notes for the new release 14 | - Showcase images for the docx // subcommands 15 | - Bug-report,feature req templates 16 | - Removed redundant client calls 17 | - Show docx from main path 18 | 19 | ### Refactor 20 | 21 | - Show docx inside main instead of .github 22 | 23 | ## [0.1.1] - 2023-10-13 24 | 25 | ### Bug Fixes 26 | 27 | - Fix error handling that triggers a panic 28 | 29 | ### Feat 30 | 31 | - Test stdin // exclude args 32 | 33 | ### Features 34 | 35 | - Use dependabot for automatic v. updates 36 | - Exclude args for fuzzing #1 // check possible openredirect vuln 37 | - Read urls from standard input while fuzzing 38 | 39 | ### Miscellaneous Tasks 40 | 41 | - Use new img for logo :P 42 | - Removed white spaces 43 | - Option for single url //multiple urls via file 44 | - Allow dead code for commands module 45 | - Use colored lines instead of aqua 46 | - Fix emojies for contrib // license 47 | - Show help if no args are provided 48 | - Applied clippy suggestions 49 | - Updated test scripts to new flag conf 50 | 51 | ### Refactor 52 | 53 | - Add references for similar projects 54 | - Use same return types 55 | - Use iterators over loops 56 | - Use confliction method to handle file // stdin 57 | - Show not vulnerable urls as well 58 | 59 | ### Update 60 | 61 | - Docx 62 | 63 | ### Cleanup 64 | 65 | - Removed redundant files 66 | 67 | ## [0.1.0] - 2023-09-08 68 | 69 | ### Bug Fixes 70 | 71 | - Readme file path 72 | 73 | ### Documentation 74 | 75 | - Init 76 | - Update 77 | 78 | ### Features 79 | 80 | - Check status code of url/urls 81 | - Example urls for status code testing 82 | - Skeleton for fuzzer subcommand 83 | - Use lazy static // args for max conc task 84 | - Read urls from standard input 85 | - Fuzz urls with fuzz subcommand 86 | - Reverse dns lookup // skel: for subdomain takeover 87 | - Working code // check possible s-tcs 88 | - Test subcommands via ci/cd 89 | - Read urls from standard input 90 | - Add splashes // (cc) license 91 | - Installation guide // subcommands helps 92 | - Fuzzing test files 93 | - Use changelogs for release notes 94 | 95 | ### Miscellaneous Tasks 96 | 97 | - Use appr colors for warn/success and others 98 | - Test kanha via ci/cd 99 | - Use seprate modules for helper functions 100 | - Desc for the app 101 | - Use caps instead 102 | - Update dependencies // update: skel for takeover 103 | - Provide lockfile for locked installation 104 | - Improved code organization and readability 105 | - Allow formating logs via clippy 106 | - 💭 updated deps specs // removed redundant files 107 | 108 | ### Refactor 109 | 110 | - Testout kanha with ci // handle errors with logs 111 | - Use match to for subcmds // applied clippy suggestions 112 | - Indented code // removed redundant files 113 | - Just print the status code 114 | - Use iterators over loops 115 | - Use distinct strings instead of option 116 | - Check multiple contents 117 | - Cargo-fmt all the way 118 | - Cargo-fmt all the way 119 | - Fix readme path 120 | - Readme path 121 | 122 | ### Testing 123 | 124 | - Testing takeover skel 125 | 126 | ### Update 127 | 128 | - Docx 129 | - Docx 130 | - Docx 131 | 132 | 133 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Deployment 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*.*.*" 7 | 8 | jobs: 9 | publish-github: 10 | name: Publish on GitHub 11 | runs-on: ${{ matrix.config.OS }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | config: 16 | - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-gnu" } 17 | - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-musl" } 18 | - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-gnu" } 19 | - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-musl" } 20 | - { OS: ubuntu-latest, TARGET: "armv5te-unknown-linux-gnueabi" } 21 | - { OS: ubuntu-latest, TARGET: "armv7-unknown-linux-gnueabihf" } 22 | - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-gnu" } 23 | - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-musl" } 24 | - { OS: macos-latest, TARGET: "x86_64-apple-darwin" } 25 | - { OS: macos-latest, TARGET: "aarch64-apple-darwin" } 26 | - { OS: windows-latest, TARGET: "x86_64-pc-windows-msvc" } 27 | - { OS: windows-latest, TARGET: "i686-pc-windows-msvc" } 28 | 29 | steps: 30 | - name: Checkout the repository 31 | uses: actions/checkout@v3 32 | 33 | - name: Set the release version 34 | shell: bash 35 | run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV 36 | 37 | - name: Install Rust 38 | uses: actions-rs/toolchain@v1 39 | with: 40 | toolchain: stable 41 | target: ${{ matrix.config.TARGET }} 42 | override: true 43 | 44 | - name: Build 45 | uses: actions-rs/cargo@v1 46 | with: 47 | use-cross: true 48 | command: build 49 | args: --release --locked --target ${{ matrix.config.TARGET }} 50 | 51 | - name: Prepare release assets 52 | shell: bash 53 | run: | 54 | mkdir release/ 55 | cp {LICENSE,README.md} release/ 56 | cp target/${{ matrix.config.TARGET }}/release/kanha release/ 57 | mv release/ kanha-${{ env.RELEASE_VERSION }}/ 58 | 59 | - name: Create release artifacts 60 | shell: bash 61 | run: | 62 | if [ "${{ matrix.config.OS }}" = "windows-latest" ]; then 63 | 7z a -tzip "kanha-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip" \ 64 | kanha-${{ env.RELEASE_VERSION }} 65 | else 66 | tar -czvf kanha-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \ 67 | kanha-${{ env.RELEASE_VERSION }}/ 68 | shasum -a 512 kanha-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \ 69 | > kanha-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz.sha512 70 | fi 71 | 72 | - name: Upload the release 73 | uses: svenstaro/upload-release-action@v2 74 | with: 75 | repo_token: ${{ secrets.GITHUB_TOKEN }} 76 | file: kanha-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.* 77 | file_glob: true 78 | overwrite: true 79 | tag: ${{ github.ref }} 80 | 81 | publish-crates-io: 82 | name: Publish on crates.io 83 | needs: publish-github 84 | runs-on: ubuntu-latest 85 | steps: 86 | - name: Checkout the repository 87 | uses: actions/checkout@v3 88 | 89 | - name: Publish 90 | uses: actions-rs/cargo@v1 91 | with: 92 | command: publish 93 | args: --locked --token ${{ secrets.CARGO_TOKEN }} 94 | -------------------------------------------------------------------------------- /src/commands/fuzz/fuzzer.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | commands::{ 3 | kanha_helpers::{read_lines, read_urls_from_stdin}, 4 | statuscode::{fetch_and_print_status_codes, ArgsWithTasks}, 5 | }, 6 | interface::FuzzerArgs, 7 | log::abort, 8 | }; 9 | use anyhow::{Context, Result}; 10 | use futures::stream::iter; 11 | use futures::StreamExt; 12 | 13 | impl ArgsWithTasks for FuzzerArgs { 14 | fn tasks(&self) -> usize { 15 | self.tasks 16 | } 17 | } 18 | 19 | pub async fn fuzz_url(fuzzer_args: FuzzerArgs) -> Result<(), Box> { 20 | let urls_to_fuzz: Vec = match fuzzer_args.stdin { 21 | true => read_urls_from_stdin()?, 22 | false => match (&fuzzer_args.input.url, &fuzzer_args.input.file_path) { 23 | (Some(url), None) => vec![url.clone()], 24 | (None, Some(file_path)) => read_lines(file_path) 25 | .await 26 | .context(format!("Error reading URLs from file: {:?}", file_path))? 27 | .map_while(Result::ok) 28 | .collect(), 29 | _ => unreachable!(), 30 | }, 31 | }; 32 | 33 | if urls_to_fuzz.is_empty() { 34 | abort("No URLs to fuzz."); 35 | } 36 | 37 | let payloads = read_lines(&fuzzer_args.payloads) 38 | .await 39 | .context("Error reading payloads from wordlist file")?; 40 | 41 | let formatted_urls: Vec = payloads 42 | .map_while(Result::ok) 43 | .flat_map(|line| { 44 | urls_to_fuzz 45 | .iter() 46 | .map(move |url| url.replace("FUZZ", &line)) 47 | }) 48 | .collect(); 49 | 50 | if let Some(exclude_str) = fuzzer_args.exclude.clone() { 51 | let exclude_codes: Vec = exclude_str 52 | .split(',') 53 | .filter_map(|s| s.trim().parse().ok()) 54 | .collect(); 55 | 56 | fetch_and_print_status_codes_with_exclude( 57 | formatted_urls.clone(), 58 | fuzzer_args, 59 | exclude_codes, 60 | ) 61 | .await 62 | } else { 63 | fetch_and_print_status_codes(formatted_urls.clone(), fuzzer_args).await 64 | } 65 | 66 | Ok(()) 67 | } 68 | 69 | pub async fn fetch_and_print_status_codes_with_exclude( 70 | urls: Vec, 71 | fuzzer_args: FuzzerArgs, 72 | exclude: Vec, 73 | ) { 74 | let tasks = fuzzer_args.tasks(); 75 | 76 | let client = reqwest::Client::new(); 77 | 78 | let responses = iter(urls.into_iter()) 79 | .map(|url| { 80 | let client = &client; 81 | async move { 82 | let response = client.get(&url).send().await; 83 | (url, response) 84 | } 85 | }) 86 | .buffer_unordered(tasks) 87 | .collect::)>>() 88 | .await; 89 | 90 | for (url, response_result) in responses { 91 | match response_result { 92 | Ok(response) => { 93 | let status_code = response.status(); 94 | let status_code_usize: usize = status_code.as_u16().into(); 95 | if !exclude.contains(&status_code_usize) { 96 | println!("URL: {}, Status Code: {}", url, status_code_usize); 97 | } 98 | } 99 | Err(err) => { 100 | eprintln!("Error fetching URL {}: {}", url, err); 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /tests/test_status.txt: -------------------------------------------------------------------------------- 1 | https://pwnwriter.xyz 2 | https://pwnwriter.xyz/pw 3 | https://kisslinux.org 4 | https://ok.l 5 | http://0.0.0.0:8000 6 | https://a27a12ringutrecht.nl 7 | https://a27houtenhooipolder.nl 8 | https://a28a1knooppunthoevelaken.nl 9 | https://a4burgerveen-n14.nl 10 | https://a4haaglanden-n14.nl 11 | https://a58tilburgbreda.nl 12 | https://a6zonlelystaddronten.nl 13 | https://a7a8.nl 14 | https://aanbiedersmedicijnen.nl 15 | https://aandachtvoorelkaar.nl 16 | https://aandeslagmetdeomgevingswet.nl 17 | https://aaninhetdonker.nl 18 | https://aanmelder.nl 19 | https://aanpaklerarentekort.nl 20 | https://aanpakringzuid.nl 21 | https://aanpakstikstof.nl 22 | https://geobasisregistraties.nl 23 | https://geoforum.nl 24 | https://gerechtelijkebrief.nl 25 | https://ger-ned380kv.nl 26 | https://gerned380kv.nl 27 | https://gerned380.nl 28 | https://geschilleninstantieszorg.nl 29 | https://gezondekinderopvang.nl 30 | https://gezondeleefomgeving.nl 31 | https://gezondeschool.nl 32 | https://gezondheidsraad.nl 33 | https://ggo-vergunningverlening.nl 34 | https://ggo-vergunningverlening-zoeken.nl 35 | https://gipdatabank.nl 36 | https://gipinfo.nl 37 | https://globemission.eu 38 | https://globio.info 39 | https://gobiernodireino.nl 40 | https://gobiernudireino.nl 41 | https://gov4nano.eu 42 | https://government.nl 43 | https://gov.nl 44 | https://gratisvog.nl 45 | https://greendeals.nl 46 | https://grensdata.eu 47 | https://grensinfo.nl 48 | https://groenalliantiemiddenholland.nl 49 | https://grondstoffenscanner.nl 50 | https://guaranteeforum.eu 51 | https://haaglandenveilig.nl 52 | https://halt.nl 53 | https://handelingenbank.info 54 | https://hansken.nl 55 | https://hansken.org 56 | https://hcaict.nl 57 | https://healthcouncil.nl 58 | https://helpdeskbouwregels.nl 59 | https://helpdesk-efactureren.nl 60 | https://helpdeskwater.nl 61 | https://hepatitis-and-u.nl 62 | https://hepatitisonderzoek.nl 63 | https://herkomstgezocht.nl 64 | https://hetcak.nl 65 | https://heyhetisoke.nl 66 | https://higherlevel.nl 67 | https://hiswa.nl 68 | https://hoepakjijdataan.nl 69 | https://hoewerktnederland.nl 70 | https://hogeraad.nl 71 | https://hogeraadvanadel.nl 72 | https://holandaevoce.nl 73 | https://holandanomundo.nl 74 | https://holandawaanta.nl 75 | https://hollandavesen.nl 76 | https://hollandnationalparks.com 77 | https://hollands-hout.com 78 | https://hoogspanningsverbindingen.nl 79 | https://hoogspanningsverbinding.nl 80 | https://horizonscangeneesmiddelen.nl 81 | https://houseofrepresentatives.nl 82 | https://huiselijkgeweld.nl 83 | https://huisvoorklokkenluiders.nl 84 | https://hulpbijprivacy.nl 85 | https://hulpmiddelenwijzer.nl 86 | https://hulpmiddelenzorg.nl 87 | https://huurcommissie.nl 88 | https://hwbp.nl 89 | https://iamcdocumentation.eu 90 | https://ibki.nl 91 | https://icov.nl 92 | https://ictu.nl 93 | https://ideasfrom.eu 94 | https://identiteitsdocumenten.nl 95 | https://iedereendoetwat.nl 96 | https://iedereenondereendak.nl 97 | https://ienc-kennisportaal.nl 98 | https://ienw-datadagen.nl 99 | https://ifv.nl 100 | https://igjacademie.nl 101 | https://igj.nl 102 | https://ihw.nl 103 | https://iinterimrijk.nl 104 | https://ikbenhandelaar.nl 105 | https://ikpasophetwad.nl 106 | https://ikvermoedhuiselijkgeweld.nl 107 | https://ikz.nl 108 | https://ilent.nl 109 | https://immissietoets.nl 110 | https://impact-project.eu 111 | https://inburgeren.nl 112 | https://incca.org 113 | https://incidentmanagement.nl 114 | https://indjaarverslag.nl 115 | https://ind.nl 116 | https://infomil.nl 117 | https://informatieberaadzorg.nl 118 | https://informatiehuishouding.nl 119 | https://informatiehuismarien.nl 120 | https://informatiepuntdigitaleoverheid.n 121 | -------------------------------------------------------------------------------- /src/commands/takeover/sub_takeover.rs: -------------------------------------------------------------------------------- 1 | // Guide: https://www.hackerone.com/application-security/guide-subdomain-takeovers 2 | 3 | use crate::{ 4 | commands::kanha_helpers::{read_lines, read_urls_from_stdin}, 5 | interface::TakeoverArgs, 6 | log::message, 7 | }; 8 | use colored::*; 9 | use reqwest; 10 | use serde::{Deserialize, Serialize}; 11 | 12 | use super::takeover_helper::get_signatures_from_repo; 13 | 14 | #[derive(Debug, Deserialize, Serialize)] 15 | struct PlatformInfo { 16 | platforms: Vec, 17 | } 18 | 19 | #[derive(Debug, Deserialize, Serialize)] 20 | struct Platform { 21 | platform: String, 22 | content: Content, 23 | } 24 | 25 | #[derive(Debug, Deserialize, Serialize)] 26 | #[serde(untagged)] 27 | enum Content { 28 | Single(String), 29 | Multiple(Vec), 30 | } 31 | 32 | pub async fn subdomain_takeover( 33 | takeover_args: TakeoverArgs, 34 | ) -> Result<(), Box> { 35 | let platform_info = load_platform_info(&takeover_args.json_file).await?; 36 | 37 | if takeover_args.stdin { 38 | let urls = read_urls_from_stdin()?; 39 | process_takeover_urls(&urls, &platform_info).await; 40 | } 41 | match (&takeover_args.input.file_path, &takeover_args.input.url) { 42 | (Some(file_path), None) => { 43 | let lines = read_lines(file_path).await?; 44 | let urls: Vec = lines.map_while(Result::ok).collect(); 45 | process_takeover_urls(&urls, &platform_info).await; 46 | } 47 | (None, Some(url)) => { 48 | let urls = vec![url.clone()]; 49 | process_takeover_urls(&urls, &platform_info).await; 50 | } 51 | _ => {} 52 | } 53 | Ok(()) 54 | } 55 | 56 | async fn load_platform_info( 57 | json_file: &Option, 58 | ) -> Result> { 59 | let json_file_contents = match json_file { 60 | Some(file) => tokio::fs::read_to_string(file).await?, 61 | None => { 62 | message( 63 | "Seems like you didn't pass the JSON, fetching and using default JSON", 64 | Color::Blue, 65 | ); 66 | get_signatures_from_repo().await? 67 | } 68 | }; 69 | let platform_info: PlatformInfo = serde_json::from_str(&json_file_contents)?; 70 | Ok(platform_info) 71 | } 72 | 73 | async fn process_takeover_urls(urls: &[String], platform_info: &PlatformInfo) { 74 | for url_str in urls { 75 | let url = match reqwest::Url::parse(url_str) { 76 | Ok(url) => url, 77 | Err(_) => { 78 | println!("{} -> [{}]", "Invalid URL".red().bold(), url_str); 79 | continue; 80 | } 81 | }; 82 | 83 | let body = reqwest::get(url.clone()) 84 | .await 85 | .unwrap() 86 | .text() 87 | .await 88 | .unwrap(); 89 | 90 | if let Some(vulnerable_platform) = check_vulnerability(&body, platform_info).await { 91 | println!( 92 | "{} [{}] -> [{}]", 93 | "vulnerable".red().bold(), 94 | vulnerable_platform.red().bold(), 95 | url 96 | ); 97 | } else { 98 | println!("{} -> [{}]", "Not vulnerable".green().bold(), url); 99 | } 100 | } 101 | } 102 | 103 | async fn check_vulnerability(body: &str, platform_info: &PlatformInfo) -> Option { 104 | for platform in &platform_info.platforms { 105 | let platform_name = &platform.platform; 106 | 107 | match &platform.content { 108 | Content::Single(content) => { 109 | if body.contains(content) { 110 | return Some(platform_name.clone()); 111 | } 112 | } 113 | Content::Multiple(contents) => { 114 | if contents.iter().any(|content| body.contains(content)) { 115 | return Some(platform_name.clone()); 116 | } 117 | } 118 | } 119 | } 120 | None 121 | } 122 | -------------------------------------------------------------------------------- /src/commands/status/statuscode.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | commands::kanha_helpers::{read_lines, read_urls_from_stdin}, 3 | interface::StatusArgs, 4 | }; 5 | use futures::stream::iter; 6 | use futures::StreamExt; 7 | use {reqwest::Client, std::sync::Arc, tokio::sync::Semaphore}; 8 | 9 | // Reuse the reqwest client instance 10 | lazy_static::lazy_static! { 11 | static ref HTTP_CLIENT: Client = Client::builder() 12 | .redirect(reqwest::redirect::Policy::none()) 13 | .build() 14 | .expect("Failed to create reqwest client"); 15 | } 16 | 17 | pub async fn fetch_and_print_status_codes(urls: Vec, args: T) 18 | where 19 | T: ArgsWithTasks, 20 | { 21 | let client = &HTTP_CLIENT; 22 | let semaphore = Arc::new(Semaphore::new(args.tasks())); 23 | 24 | let tasks = urls.into_iter().map(|url| { 25 | let semaphore = semaphore.clone(); 26 | async move { 27 | let _permit = semaphore.acquire().await.expect("Semaphore error"); 28 | if let Ok(response) = client.get(&url).send().await { 29 | println!("{} [{}]", url, response.status().as_u16()); 30 | } 31 | } 32 | }); 33 | 34 | futures::future::join_all(tasks).await; 35 | } 36 | 37 | pub trait ArgsWithTasks { 38 | fn tasks(&self) -> usize; 39 | } 40 | 41 | impl ArgsWithTasks for StatusArgs { 42 | fn tasks(&self) -> usize { 43 | self.tasks 44 | } 45 | } 46 | 47 | pub async fn handle_status_command( 48 | status_args: StatusArgs, 49 | ) -> anyhow::Result<(), Box> { 50 | match status_args.stdin { 51 | true => { 52 | let urls = read_urls_from_stdin()?; 53 | 54 | if let Some(exclude_str) = status_args.exclude.clone() { 55 | let exclude_codes: Vec = exclude_str 56 | .split(',') 57 | .filter_map(|s| s.trim().parse().ok()) 58 | .collect(); 59 | 60 | fetch_and_print_status_codes_with_exclude(urls, status_args, exclude_codes).await; 61 | } else { 62 | fetch_and_print_status_codes(urls, status_args).await; 63 | } 64 | } 65 | false => { 66 | if let Some(filename) = &status_args.filename { 67 | if let Ok(lines) = read_lines(filename).await { 68 | let urls: Vec = lines 69 | .map_while(Result::ok) // Filter out lines with read errors 70 | .collect(); 71 | 72 | if let Some(exclude_str) = status_args.exclude.clone() { 73 | let exclude_codes: Vec = exclude_str 74 | .split(',') 75 | .filter_map(|s| s.trim().parse().ok()) 76 | .collect(); 77 | 78 | fetch_and_print_status_codes_with_exclude(urls, status_args, exclude_codes) 79 | .await; 80 | } else { 81 | fetch_and_print_status_codes(urls, status_args).await; 82 | } 83 | } 84 | } 85 | } 86 | } 87 | 88 | Ok(()) 89 | } 90 | 91 | pub async fn fetch_and_print_status_codes_with_exclude( 92 | urls: Vec, 93 | status_args: StatusArgs, 94 | exclude: Vec, 95 | ) { 96 | let tasks = status_args.tasks(); 97 | 98 | let client = reqwest::Client::new(); 99 | 100 | let responses = iter(urls.into_iter()) 101 | .map(|url| { 102 | let client = &client; 103 | async move { 104 | let response = client.get(&url).send().await; 105 | (url, response) 106 | } 107 | }) 108 | .buffer_unordered(tasks) 109 | .collect::)>>() 110 | .await; 111 | 112 | for (url, response_result) in responses { 113 | match response_result { 114 | Ok(response) => { 115 | let status_code = response.status(); 116 | let status_code_usize: usize = status_code.as_u16().into(); // Use into() for infallible conversion 117 | 118 | if !exclude.contains(&status_code_usize) { 119 | println!("URL: {}, Status Code: {}", url, status_code_usize); 120 | } 121 | } 122 | Err(err) => { 123 | eprintln!("Error fetching URL {}: {}", url, err); 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /tests/signatures_full.json: -------------------------------------------------------------------------------- 1 | { 2 | "platforms": [ 3 | { 4 | "platform": "GitHub Pages", 5 | "content": [ 6 | "

There isn't a GitHub Pages site here.

", 7 | "For root URLs (like http://example.com/) you must provide an index.html file" 8 | ] 9 | }, 10 | { 11 | "platform": "WordPress.com", 12 | "content": [ 13 | "Do you want to register ", 14 | "Error: Domain mapping upgrade for this domain not found", 15 | "It looks like it doesn't have an active domain connection upgrade to link the requested domain name to the WordPress.com site." 16 | ] 17 | }, 18 | { 19 | "platform": "Amazon S3", 20 | "content": [ 21 | "NoSuchBucket", 22 | "The specified bucket does not exist" 23 | ] 24 | }, 25 | { 26 | "platform": "Agile CRM", 27 | "content": "Sorry, this page is no longer available." 28 | }, 29 | { 30 | "platform": "Anima", 31 | "content": "If this is your website and you've just created it, try refreshing in a minute" 32 | }, 33 | { 34 | "platform": "Bitbucket", 35 | "content": [ 36 | "Repository not found", 37 | "The page you have requested does not exist" 38 | ] 39 | }, 40 | { 41 | "platform": "Campaign Monitor", 42 | "content": [ 43 | "Trying to access your account?", 44 | "Double check the URL" 45 | ] 46 | }, 47 | { 48 | "platform": "DigitalOcean", 49 | "content": "Domain uses DO name serves with no records in DO." 50 | }, 51 | { 52 | "platform": "Fastly", 53 | "content": [ 54 | "Fastly error: unknown domain:", 55 | "Please check that this domain has been added to a service" 56 | ] 57 | }, 58 | { 59 | "platform": "Ghost", 60 | "content": [ 61 | "The thing you were looking for is no longer here", 62 | "The thing you were looking for is no longer here, or never was", 63 | "

Failed to resolve DNS path for this host

" 64 | ] 65 | }, 66 | { 67 | "platform": "HatenaBlog", 68 | "content": "404 Blog is not found" 69 | }, 70 | { 71 | "platform": "Help Juice", 72 | "content": "We could not find what you're looking for." 73 | }, 74 | { 75 | "platform": "HelpScout", 76 | "content": "No settings were found for this company:" 77 | }, 78 | { 79 | "platform": "Heroku", 80 | "content": [ 81 | "No such app", 82 | "There's nothing here, yet.", 83 | "herokucdn.com/error-pages/no-such-app.html" 84 | ] 85 | }, 86 | { 87 | "platform": "Intercom", 88 | "content": [ 89 | "Uh oh. That page doesn't exist.", 90 | "This page is reserved for artistic dogs." 91 | ] 92 | }, 93 | { 94 | "platform": "JetBrains YouTrack", 95 | "content": "is not a registered InCloud YouTrack" 96 | }, 97 | { 98 | "platform": "Kinsta", 99 | "content": "You have successfully pointed this domain to Kinsta servers but you haven't added it to any of your sites." 100 | }, 101 | { 102 | "platform": "LaunchRock", 103 | "content": "It looks like you may have taken a wrong turn somewhere. Don't worry...it happens to all of us." 104 | }, 105 | { 106 | "platform": "Ngrok", 107 | "content": "Tunnel *.ngrok.io not found" 108 | }, 109 | { 110 | "platform": "Pantheon", 111 | "content": [ 112 | "404 error unknown site!", 113 | "The gods are wise", 114 | "The gods are wise, but do not know of the site which you seek." 115 | ] 116 | }, 117 | { 118 | "platform": "Pingdom", 119 | "content": [ 120 | "This public report page has not been activated by the user", 121 | "pingdom" 122 | ] 123 | }, 124 | { 125 | "platform": "Readme.io", 126 | "content": "

Project doesnt exist... yet!

" 127 | }, 128 | { 129 | "platform": "Shopify", 130 | "content": [ 131 | "

Sorry, this shop is currently unavailable.

", 132 | "Only one step left!
To finish setting up your new web address, go to" 133 | ] 134 | }, 135 | { 136 | "platform": "SmartJobBoard", 137 | "content": "This job board website is either expired or its domain name is invalid." 138 | }, 139 | { 140 | "platform": "Strikingly", 141 | "content": "Page not found - Strikingly" 142 | }, 143 | { 144 | "platform": "Surge.sh", 145 | "content": "

project not found

" 146 | }, 147 | { 148 | "platform": "Tumblr", 149 | "content": [ 150 | "Whatever you were looking for doesn't currently exist at this address. Unless you were looking for this error page, in which case: Congrats! You totally found it.", 151 | "There's nothing here." 152 | ] 153 | }, 154 | { 155 | "platform": "Uberflip", 156 | "content": "Non-hub domain, The URL you've accessed does not provide a hub." 157 | }, 158 | { 159 | "platform": "Unbounce", 160 | "content": [ 161 | "The requested URL was not found on this server.", 162 | "The requested URL / was not found on this server." 163 | ] 164 | }, 165 | { 166 | "platform": "UserVoice", 167 | "content": "This UserVoice subdomain is currently available!" 168 | }, 169 | { 170 | "platform": "Webflow", 171 | "content": [ 172 | "

The page you are looking for doesn't exist or has been moved.

", 173 | "

The URL you've accessed does not provide a hub. Please check the URL and try again.

", 174 | "

The page you are looking for doesn't exist or has been moved.

" 175 | ] 176 | }, 177 | { 178 | "platform": "Worksites", 179 | "content": "

Hello! Sorry, but the website you’re looking for doesn’t exist.

" 180 | }, 181 | { 182 | "platform": "UptimeRobot.com", 183 | "content": "page not found" 184 | }, 185 | { 186 | "platform": "Instapage", 187 | "content": "You've Discovered A Missing Link. Our Apologies!" 188 | }, 189 | { 190 | "platform": "Desk", 191 | "content": [ 192 | "Please try again or try Desk.com free for 14 days.", 193 | "Sorry, We Couldn't Find That Page" 194 | ] 195 | }, 196 | { 197 | "platform": "Tictail", 198 | "content": [ 199 | "Building a brand of your own?", 200 | "to target URL: redirected" 212 | ] 213 | }, 214 | { 215 | "platform": "Cloudfront", 216 | "content": [ 217 | "The request could not be satisfied", 218 | "ERROR: The request could not be satisfied" 219 | ] 220 | }, 221 | { 222 | "platform": "Smartling", 223 | "content": "Domain is not configured" 224 | }, 225 | { 226 | "platform": "Acquia", 227 | "content": [ 228 | "If you are an Acquia Cloud customer and expect to see your site at this address", 229 | "The site you are looking for could not be found." 230 | ] 231 | }, 232 | { 233 | "platform": "Zendesk", 234 | "content": [ 235 | "Help Center Closed | Zendesk", 236 | "Help Center Closed" 237 | ] 238 | }, 239 | { 240 | "platform": "Tilda", 241 | "content": "Domain has been assigned" 242 | }, 243 | { 244 | "platform": "Teamwork", 245 | "content": "Oops - We didn't find your site." 246 | }, 247 | { 248 | "platform": "Helpjuice", 249 | "content": "We could not find what you're looking for." 250 | }, 251 | { 252 | "platform": "Feedpress", 253 | "content": "The feed has not been found." 254 | }, 255 | { 256 | "platform": "Surge", 257 | "content": "project not found" 258 | }, 259 | { 260 | "platform": "Surveygizmo", 261 | "content": "data-html-name" 262 | }, 263 | { 264 | "platform": "Mashery", 265 | "content": "Unrecognized domain " 266 | }, 267 | { 268 | "platform": "Kajabi", 269 | "content": "

The page you were looking for doesn't exist.

" 270 | }, 271 | { 272 | "platform": "Thinkific", 273 | "content": "You may have mistyped the address or the page may have moved." 274 | }, 275 | { 276 | "platform": "Wishpond", 277 | "content": "https://www.wishpond.com/404?campaign=true" 278 | }, 279 | { 280 | "platform": "Aftership", 281 | "content": "Oops.

The page you're looking for doesn't exist." 282 | }, 283 | { 284 | "platform": "Aha", 285 | "content": "There is no portal here ... sending you back to Aha!" 286 | }, 287 | { 288 | "platform": "Brightcove", 289 | "content": "

" 290 | }, 291 | { 292 | "platform": "Bigcartel", 293 | "content": "

Oops! We couldn’t find that page.

" 294 | }, 295 | { 296 | "platform": "activecompaign", 297 | "content": "alt=\"LIGHTTPD - fly light.\"" 298 | }, 299 | { 300 | "platform": "compaignmonitor", 301 | "content": "Double check the URL or
2 |

Kanha - A web-app pentesting suite written in rust 🦀

3 | 4 |
5 | Installation 6 | ⦾ 7 | Subcommands 8 | ⦾ 9 | Contribute 10 |
11 |

12 | Crate Release 13 | 14 | MIT LICENSE 15 | Ko-fi 16 | 17 | ![-----------------------------------------------------][line] 18 | 19 | img

20 | 21 | [**`Kanha`**](/) is a tool that can help you perform, a variety of attacks based on the target domain . With just `kanha` you can do, [***`Fuzzing`***][wiki-fuzzing], [***`Reverse dns lookup`***][wiki-dns-lookup], [***`common http response`***][wiki-http], [***`subdomain takeover detection`***][wiki-subdomain] and many [**`more`**][commands]. 22 | 23 | The project is inspird by [`mini.nvim`][mini], basically helping you to be productive with less numbers of *tools(plugins)* installed on your system and be unobtrusive and function as a standalone **`single binary`** out of the box. 24 | 25 | Built from the ground up with performance, ease of use, and portability in mind in your favourite programming lang [**`rust`**][rust] 💝 26 | 27 | ## Philosophy 28 | 29 | - **KISS** - Keep things simple and stupid. 30 | - **Ease** - Write code that can be used elsewhere as well. 31 | - **Efficiency** - Optimize for performance without sacrificing readability. 32 | 33 | ## Installation 34 | 35 |
Binary 36 |   37 | 38 | - *Manual* : You can directly download the binary of your arch from [**releases**][releases] and run it. 39 | - *One liner* : Run this script, requires `jq`,`curl`, `tar` & `wget` 40 | ```bash 41 | wget -qO- "$(curl -qfsSL "https://api.github.com/repos/pwnwriter/kanha/releases/latest" | jq -r '.assets[].browser_download_url' | grep -Ei "$(uname -m).*$(uname -s).*musl" | grep -v "\.sha")" | tar -xzf - --strip-components=1 42 | ./kanha -h 43 | ``` 44 |
45 | 46 | > [!IMPORTANT] 47 | > *_For upstream updates, it's recommended to build `kanha` from source !_* 48 | 49 |
Source 50 |   51 | 52 | 53 | ```bash 54 | git clone --depth=1 https://github.com/pwnwriter/kanha --branch=main 55 | cd kanha 56 | cargo build --release 57 | ``` 58 | 59 |
60 | 61 |
Cargo 62 | 63 | - Using [crates.io][crate] 64 | ```bash 65 | cargo install kanha 66 | ``` 67 | - Using [binstall][binstall] 68 | ```bash 69 | cargo binstall kanha 70 | ``` 71 | 72 | > **Note** ⚠️ 73 | > This requires a working setup of rust/cargo & binstall. 74 |
75 | 76 |
METIS Linux 77 |   78 | 79 | ```bash 80 | sudo/doas pacman -Syyy kanha 81 | ``` 82 | 83 |
84 | 85 |
Arch user repository 86 |   87 | 88 | ```bash 89 | paru/yay -S kanha-git 90 | ``` 91 | 92 |
93 | 94 | 95 |
On Nix 96 |   97 | 98 | ```bash 99 | # Build from source and run 100 | nix run github:pwnwriter/kanha 101 | # without flakes: 102 | nix-env -iA nixpkgs.kanha 103 | # with flakes: 104 | nix profile install nixpkgs#kanha 105 | ``` 106 | 107 |
108 | 109 | 110 | ## Subcommands 111 | - ➊ `Status` :- Just return the HTTP response code of URLs 112 | 113 |
114 | Help 115 |   116 | 117 | ```bash 118 | $ kanha status -h 119 | Just return the HTTP response code of URLs 120 | 121 | Usage: kanha status [OPTIONS] 122 | 123 | Options: 124 | -f, --filename A file containing multiple urls 125 | -t, --tasks Define the maximum concurrent tasks [default: 20] 126 | --stdin Reads input from the standard in 127 | --exclude Define your status code for selective exclusion 128 | -h, --help Print help 129 | -V, --version Print version 130 | 131 | ``` 132 | 133 |
134 | 135 | - ➋ `fuzz` :- Fuzz URLs and return the response codes 136 | 137 |
138 | Help 139 |   140 | 141 | ```bash 142 | $ kanha fuzz -h 143 | Fuzz a URL and return the response codes 144 | 145 | Usage: kanha fuzz [OPTIONS] --payloads 146 | 147 | Options: 148 | -p, --payloads A file containing a list of payloads 149 | -u, --url A single url 150 | -f, --file-path Path of the file containing multiple urls 151 | -t, --tasks Define the maximum concurrent tasks [default: 20] 152 | --exclude Define your status code for selective exclusion 153 | --stdin Reads input from the standard in 154 | -h, --help Print help 155 | -V, --version Print version 156 | 157 | ``` 158 |
159 | 160 | - ➌ `rdns` :- Reverse dns lookup 161 |
162 | Help 163 |   164 | 165 | ```bash 166 | 167 | $ kanha rdns -h 168 | Reverse dns lookup 169 | 170 | Usage: kanha rdns [OPTIONS] --filename 171 | 172 | Options: 173 | -f, --filename a file containing a list of possible wordlists 174 | --stdin Reads input from the standard in 175 | -h, --help Print help 176 | -V, --version Print version 177 | ``` 178 |
179 | 180 | - ➍ `Takeover` :- Check possible subdomain takeover 181 |
182 | Help 183 |   184 | 185 | ```bash 186 | $ kanha takeover -h 187 | Check possible subdomain takeover vulnerability 188 | 189 | Usage: kanha takeover [OPTIONS] 190 | 191 | Options: 192 | -u, --url A single url 193 | -f, --file-path Path of the file containing multiple urls 194 | -j, --json-file A json file containing signature values of different services 195 | --stdin Reads input from the standard in 196 | -h, --help Print help 197 | -V, --version Print version 198 | 199 | ``` 200 |
201 | 202 | 203 | - ➎ `urldencode` :- (De|En) code urls 204 |
205 | Help 206 |   207 | 208 | ```bash 209 | $ kanha urldencode -h 210 | (De|En) code urls 211 | 212 | Usage: kanha urldencode [OPTIONS] 213 | 214 | Options: 215 | --encode Provide a url to encode 216 | --decode Provide a url to dencode 217 | -h, --help Print help 218 | -V, --version Print version 219 | 220 | ``` 221 |
222 | 223 | 224 | 225 | 226 | 227 | ## Contributing 228 | - Recommend a new feature 229 | - Give the project a star 230 | - Add new [subcommand][commands]. 231 | - Fix docx and improve code quality 232 | 233 | ## Also see 234 | - [`haylxon`][haylxon] :- Blazingly fast tool to grab screenshots of your domain list right from terminal written in rust 🦀 235 | - [`httpx`][httpx] :- httpx is a fast and multi-purpose HTTP toolkit. 236 | - [`ffuf`][ffuf] :- Fast web fuzzer written in Go 237 | 238 | ## FAQ 239 | 240 | - **Development:** 241 | - Progress may be gradual, but I assure you of delivering quality code! 242 | - **Why this?** 243 | - This is a way for me to continually expand my knowledge in cybersecurity and Rust! 244 | - **I want my quote in Kanha.** 245 | - Please feel free to add it [here][splash]. 246 | 247 | ## Support 248 | I am a student, i like working for open-source during my free time. If you appreciate my work, kindly consider supporting me through [Ko-fi][Ko-Fi]. 249 | 250 | ## Copying 251 | `Kanha` is licensed under the [**`MIT LICENSE`**][license], Feel free to consider Kanha as your own! 252 | 253 | 254 | 255 | 256 | [license]:/LICENSE 257 | [splash]:/src/interface/splashes.rs 258 | [commands]:/src/commands 259 | [releases]:https://github.com/pwnwriter/kanha/releases 260 | 261 | [line]:https://github.com/pwnwriter/haylxon/blob/readme-assets/colored.png 262 | 263 | [Ko-Fi]:https://ko-fi.com/pwnwriter 264 | [haylxon]:https://github.com/pwnwriter/haylxon 265 | 266 | [ffuf]:https://github.com/ffuf/ffuf 267 | [httpx]:https://github.com/projectdiscovery/httpx 268 | 269 | [crate]:https://crates.io/crates/kanha 270 | [binstall]:https://github.com/cargo-bins/cargo-binstall 271 | [mini]:https://github.com/echasnovski/mini.nvim 272 | [rust]:https://www.rust-lang.org 273 | 274 | [wiki-fuzzing]:https://en.wikipedia.org/wiki/Fuzzing 275 | [wiki-dns-lookup]:https://en.wikipedia.org/wiki/Reverse_DNS_lookup 276 | [wiki-http]:https://en.wikipedia.org/wiki/List_of_HTTP_status_codes 277 | [wiki-subdomain]:https://en.wikipedia.org/wiki/Domain_hijacking 278 | 279 | 280 | 281 |

282 |

Copyright © 2023 - present pwnwriter xyz ☘️

283 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "anstream" 22 | version = "0.6.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" 25 | dependencies = [ 26 | "anstyle", 27 | "anstyle-parse", 28 | "anstyle-query", 29 | "anstyle-wincon", 30 | "colorchoice", 31 | "utf8parse", 32 | ] 33 | 34 | [[package]] 35 | name = "anstyle" 36 | version = "1.0.2" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" 39 | 40 | [[package]] 41 | name = "anstyle-parse" 42 | version = "0.2.1" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" 45 | dependencies = [ 46 | "utf8parse", 47 | ] 48 | 49 | [[package]] 50 | name = "anstyle-query" 51 | version = "1.0.0" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 54 | dependencies = [ 55 | "windows-sys", 56 | ] 57 | 58 | [[package]] 59 | name = "anstyle-wincon" 60 | version = "3.0.1" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" 63 | dependencies = [ 64 | "anstyle", 65 | "windows-sys", 66 | ] 67 | 68 | [[package]] 69 | name = "anyhow" 70 | version = "1.0.75" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" 73 | 74 | [[package]] 75 | name = "autocfg" 76 | version = "1.1.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 79 | 80 | [[package]] 81 | name = "backtrace" 82 | version = "0.3.69" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 85 | dependencies = [ 86 | "addr2line", 87 | "cc", 88 | "cfg-if", 89 | "libc", 90 | "miniz_oxide", 91 | "object", 92 | "rustc-demangle", 93 | ] 94 | 95 | [[package]] 96 | name = "base64" 97 | version = "0.21.3" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" 100 | 101 | [[package]] 102 | name = "bitflags" 103 | version = "1.3.2" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 106 | 107 | [[package]] 108 | name = "bitflags" 109 | version = "2.4.0" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" 112 | 113 | [[package]] 114 | name = "bumpalo" 115 | version = "3.13.0" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 118 | 119 | [[package]] 120 | name = "bytes" 121 | version = "1.4.0" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 124 | 125 | [[package]] 126 | name = "cc" 127 | version = "1.0.83" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 130 | dependencies = [ 131 | "libc", 132 | ] 133 | 134 | [[package]] 135 | name = "cfg-if" 136 | version = "1.0.0" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 139 | 140 | [[package]] 141 | name = "clap" 142 | version = "4.4.11" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" 145 | dependencies = [ 146 | "clap_builder", 147 | "clap_derive", 148 | ] 149 | 150 | [[package]] 151 | name = "clap_builder" 152 | version = "4.4.11" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" 155 | dependencies = [ 156 | "anstream", 157 | "anstyle", 158 | "clap_lex", 159 | "strsim", 160 | ] 161 | 162 | [[package]] 163 | name = "clap_derive" 164 | version = "4.4.7" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" 167 | dependencies = [ 168 | "heck", 169 | "proc-macro2", 170 | "quote", 171 | "syn", 172 | ] 173 | 174 | [[package]] 175 | name = "clap_lex" 176 | version = "0.6.0" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" 179 | 180 | [[package]] 181 | name = "colorchoice" 182 | version = "1.0.0" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 185 | 186 | [[package]] 187 | name = "colored" 188 | version = "2.0.4" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" 191 | dependencies = [ 192 | "is-terminal", 193 | "lazy_static", 194 | "windows-sys", 195 | ] 196 | 197 | [[package]] 198 | name = "core-foundation" 199 | version = "0.9.3" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 202 | dependencies = [ 203 | "core-foundation-sys", 204 | "libc", 205 | ] 206 | 207 | [[package]] 208 | name = "core-foundation-sys" 209 | version = "0.8.4" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" 212 | 213 | [[package]] 214 | name = "dns-lookup" 215 | version = "2.0.4" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "e5766087c2235fec47fafa4cfecc81e494ee679d0fd4a59887ea0919bfb0e4fc" 218 | dependencies = [ 219 | "cfg-if", 220 | "libc", 221 | "socket2 0.5.3", 222 | "windows-sys", 223 | ] 224 | 225 | [[package]] 226 | name = "encoding_rs" 227 | version = "0.8.33" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" 230 | dependencies = [ 231 | "cfg-if", 232 | ] 233 | 234 | [[package]] 235 | name = "errno" 236 | version = "0.3.3" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" 239 | dependencies = [ 240 | "errno-dragonfly", 241 | "libc", 242 | "windows-sys", 243 | ] 244 | 245 | [[package]] 246 | name = "errno-dragonfly" 247 | version = "0.1.2" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 250 | dependencies = [ 251 | "cc", 252 | "libc", 253 | ] 254 | 255 | [[package]] 256 | name = "fnv" 257 | version = "1.0.7" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 260 | 261 | [[package]] 262 | name = "form_urlencoded" 263 | version = "1.2.0" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" 266 | dependencies = [ 267 | "percent-encoding", 268 | ] 269 | 270 | [[package]] 271 | name = "futures" 272 | version = "0.3.30" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" 275 | dependencies = [ 276 | "futures-channel", 277 | "futures-core", 278 | "futures-executor", 279 | "futures-io", 280 | "futures-sink", 281 | "futures-task", 282 | "futures-util", 283 | ] 284 | 285 | [[package]] 286 | name = "futures-channel" 287 | version = "0.3.30" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 290 | dependencies = [ 291 | "futures-core", 292 | "futures-sink", 293 | ] 294 | 295 | [[package]] 296 | name = "futures-core" 297 | version = "0.3.30" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 300 | 301 | [[package]] 302 | name = "futures-executor" 303 | version = "0.3.30" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 306 | dependencies = [ 307 | "futures-core", 308 | "futures-task", 309 | "futures-util", 310 | ] 311 | 312 | [[package]] 313 | name = "futures-io" 314 | version = "0.3.30" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 317 | 318 | [[package]] 319 | name = "futures-macro" 320 | version = "0.3.30" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 323 | dependencies = [ 324 | "proc-macro2", 325 | "quote", 326 | "syn", 327 | ] 328 | 329 | [[package]] 330 | name = "futures-sink" 331 | version = "0.3.30" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 334 | 335 | [[package]] 336 | name = "futures-task" 337 | version = "0.3.30" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 340 | 341 | [[package]] 342 | name = "futures-util" 343 | version = "0.3.30" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 346 | dependencies = [ 347 | "futures-channel", 348 | "futures-core", 349 | "futures-io", 350 | "futures-macro", 351 | "futures-sink", 352 | "futures-task", 353 | "memchr", 354 | "pin-project-lite", 355 | "pin-utils", 356 | "slab", 357 | ] 358 | 359 | [[package]] 360 | name = "gimli" 361 | version = "0.28.0" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" 364 | 365 | [[package]] 366 | name = "h2" 367 | version = "0.3.21" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" 370 | dependencies = [ 371 | "bytes", 372 | "fnv", 373 | "futures-core", 374 | "futures-sink", 375 | "futures-util", 376 | "http", 377 | "indexmap", 378 | "slab", 379 | "tokio", 380 | "tokio-util", 381 | "tracing", 382 | ] 383 | 384 | [[package]] 385 | name = "hashbrown" 386 | version = "0.12.3" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 389 | 390 | [[package]] 391 | name = "heck" 392 | version = "0.4.1" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 395 | 396 | [[package]] 397 | name = "hermit-abi" 398 | version = "0.3.2" 399 | source = "registry+https://github.com/rust-lang/crates.io-index" 400 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" 401 | 402 | [[package]] 403 | name = "http" 404 | version = "0.2.9" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" 407 | dependencies = [ 408 | "bytes", 409 | "fnv", 410 | "itoa", 411 | ] 412 | 413 | [[package]] 414 | name = "http-body" 415 | version = "0.4.5" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 418 | dependencies = [ 419 | "bytes", 420 | "http", 421 | "pin-project-lite", 422 | ] 423 | 424 | [[package]] 425 | name = "httparse" 426 | version = "1.8.0" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 429 | 430 | [[package]] 431 | name = "httpdate" 432 | version = "1.0.3" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 435 | 436 | [[package]] 437 | name = "hyper" 438 | version = "0.14.27" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" 441 | dependencies = [ 442 | "bytes", 443 | "futures-channel", 444 | "futures-core", 445 | "futures-util", 446 | "h2", 447 | "http", 448 | "http-body", 449 | "httparse", 450 | "httpdate", 451 | "itoa", 452 | "pin-project-lite", 453 | "socket2 0.4.9", 454 | "tokio", 455 | "tower-service", 456 | "tracing", 457 | "want", 458 | ] 459 | 460 | [[package]] 461 | name = "hyper-rustls" 462 | version = "0.24.1" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" 465 | dependencies = [ 466 | "futures-util", 467 | "http", 468 | "hyper", 469 | "rustls", 470 | "tokio", 471 | "tokio-rustls", 472 | ] 473 | 474 | [[package]] 475 | name = "idna" 476 | version = "0.4.0" 477 | source = "registry+https://github.com/rust-lang/crates.io-index" 478 | checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" 479 | dependencies = [ 480 | "unicode-bidi", 481 | "unicode-normalization", 482 | ] 483 | 484 | [[package]] 485 | name = "indexmap" 486 | version = "1.9.3" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 489 | dependencies = [ 490 | "autocfg", 491 | "hashbrown", 492 | ] 493 | 494 | [[package]] 495 | name = "ipnet" 496 | version = "2.8.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" 499 | 500 | [[package]] 501 | name = "is-terminal" 502 | version = "0.4.9" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" 505 | dependencies = [ 506 | "hermit-abi", 507 | "rustix", 508 | "windows-sys", 509 | ] 510 | 511 | [[package]] 512 | name = "itoa" 513 | version = "1.0.9" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" 516 | 517 | [[package]] 518 | name = "js-sys" 519 | version = "0.3.64" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 522 | dependencies = [ 523 | "wasm-bindgen", 524 | ] 525 | 526 | [[package]] 527 | name = "kanha" 528 | version = "0.1.2" 529 | dependencies = [ 530 | "anyhow", 531 | "clap", 532 | "colored", 533 | "dns-lookup", 534 | "futures", 535 | "lazy_static", 536 | "reqwest", 537 | "serde", 538 | "serde_json", 539 | "tokio", 540 | "urlencoding", 541 | ] 542 | 543 | [[package]] 544 | name = "lazy_static" 545 | version = "1.4.0" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 548 | 549 | [[package]] 550 | name = "libc" 551 | version = "0.2.147" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 554 | 555 | [[package]] 556 | name = "linux-raw-sys" 557 | version = "0.4.5" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" 560 | 561 | [[package]] 562 | name = "lock_api" 563 | version = "0.4.10" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 566 | dependencies = [ 567 | "autocfg", 568 | "scopeguard", 569 | ] 570 | 571 | [[package]] 572 | name = "log" 573 | version = "0.4.20" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 576 | 577 | [[package]] 578 | name = "memchr" 579 | version = "2.6.3" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" 582 | 583 | [[package]] 584 | name = "mime" 585 | version = "0.3.17" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 588 | 589 | [[package]] 590 | name = "miniz_oxide" 591 | version = "0.7.1" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 594 | dependencies = [ 595 | "adler", 596 | ] 597 | 598 | [[package]] 599 | name = "mio" 600 | version = "0.8.8" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 603 | dependencies = [ 604 | "libc", 605 | "wasi", 606 | "windows-sys", 607 | ] 608 | 609 | [[package]] 610 | name = "num_cpus" 611 | version = "1.16.0" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 614 | dependencies = [ 615 | "hermit-abi", 616 | "libc", 617 | ] 618 | 619 | [[package]] 620 | name = "object" 621 | version = "0.32.1" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" 624 | dependencies = [ 625 | "memchr", 626 | ] 627 | 628 | [[package]] 629 | name = "once_cell" 630 | version = "1.18.0" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 633 | 634 | [[package]] 635 | name = "parking_lot" 636 | version = "0.12.1" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 639 | dependencies = [ 640 | "lock_api", 641 | "parking_lot_core", 642 | ] 643 | 644 | [[package]] 645 | name = "parking_lot_core" 646 | version = "0.9.8" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 649 | dependencies = [ 650 | "cfg-if", 651 | "libc", 652 | "redox_syscall", 653 | "smallvec", 654 | "windows-targets", 655 | ] 656 | 657 | [[package]] 658 | name = "percent-encoding" 659 | version = "2.3.0" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" 662 | 663 | [[package]] 664 | name = "pin-project-lite" 665 | version = "0.2.13" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" 668 | 669 | [[package]] 670 | name = "pin-utils" 671 | version = "0.1.0" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 674 | 675 | [[package]] 676 | name = "proc-macro2" 677 | version = "1.0.66" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" 680 | dependencies = [ 681 | "unicode-ident", 682 | ] 683 | 684 | [[package]] 685 | name = "quote" 686 | version = "1.0.33" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 689 | dependencies = [ 690 | "proc-macro2", 691 | ] 692 | 693 | [[package]] 694 | name = "redox_syscall" 695 | version = "0.3.5" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 698 | dependencies = [ 699 | "bitflags 1.3.2", 700 | ] 701 | 702 | [[package]] 703 | name = "reqwest" 704 | version = "0.11.22" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" 707 | dependencies = [ 708 | "base64", 709 | "bytes", 710 | "encoding_rs", 711 | "futures-core", 712 | "futures-util", 713 | "h2", 714 | "http", 715 | "http-body", 716 | "hyper", 717 | "hyper-rustls", 718 | "ipnet", 719 | "js-sys", 720 | "log", 721 | "mime", 722 | "once_cell", 723 | "percent-encoding", 724 | "pin-project-lite", 725 | "rustls", 726 | "rustls-pemfile", 727 | "serde", 728 | "serde_json", 729 | "serde_urlencoded", 730 | "system-configuration", 731 | "tokio", 732 | "tokio-rustls", 733 | "tower-service", 734 | "url", 735 | "wasm-bindgen", 736 | "wasm-bindgen-futures", 737 | "web-sys", 738 | "webpki-roots", 739 | "winreg", 740 | ] 741 | 742 | [[package]] 743 | name = "ring" 744 | version = "0.16.20" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 747 | dependencies = [ 748 | "cc", 749 | "libc", 750 | "once_cell", 751 | "spin", 752 | "untrusted", 753 | "web-sys", 754 | "winapi", 755 | ] 756 | 757 | [[package]] 758 | name = "rustc-demangle" 759 | version = "0.1.23" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 762 | 763 | [[package]] 764 | name = "rustix" 765 | version = "0.38.11" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" 768 | dependencies = [ 769 | "bitflags 2.4.0", 770 | "errno", 771 | "libc", 772 | "linux-raw-sys", 773 | "windows-sys", 774 | ] 775 | 776 | [[package]] 777 | name = "rustls" 778 | version = "0.21.7" 779 | source = "registry+https://github.com/rust-lang/crates.io-index" 780 | checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" 781 | dependencies = [ 782 | "log", 783 | "ring", 784 | "rustls-webpki", 785 | "sct", 786 | ] 787 | 788 | [[package]] 789 | name = "rustls-pemfile" 790 | version = "1.0.3" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" 793 | dependencies = [ 794 | "base64", 795 | ] 796 | 797 | [[package]] 798 | name = "rustls-webpki" 799 | version = "0.101.4" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" 802 | dependencies = [ 803 | "ring", 804 | "untrusted", 805 | ] 806 | 807 | [[package]] 808 | name = "ryu" 809 | version = "1.0.15" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" 812 | 813 | [[package]] 814 | name = "scopeguard" 815 | version = "1.2.0" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 818 | 819 | [[package]] 820 | name = "sct" 821 | version = "0.7.0" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" 824 | dependencies = [ 825 | "ring", 826 | "untrusted", 827 | ] 828 | 829 | [[package]] 830 | name = "serde" 831 | version = "1.0.193" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" 834 | dependencies = [ 835 | "serde_derive", 836 | ] 837 | 838 | [[package]] 839 | name = "serde_derive" 840 | version = "1.0.193" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" 843 | dependencies = [ 844 | "proc-macro2", 845 | "quote", 846 | "syn", 847 | ] 848 | 849 | [[package]] 850 | name = "serde_json" 851 | version = "1.0.108" 852 | source = "registry+https://github.com/rust-lang/crates.io-index" 853 | checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" 854 | dependencies = [ 855 | "itoa", 856 | "ryu", 857 | "serde", 858 | ] 859 | 860 | [[package]] 861 | name = "serde_urlencoded" 862 | version = "0.7.1" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 865 | dependencies = [ 866 | "form_urlencoded", 867 | "itoa", 868 | "ryu", 869 | "serde", 870 | ] 871 | 872 | [[package]] 873 | name = "signal-hook-registry" 874 | version = "1.4.1" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 877 | dependencies = [ 878 | "libc", 879 | ] 880 | 881 | [[package]] 882 | name = "slab" 883 | version = "0.4.9" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 886 | dependencies = [ 887 | "autocfg", 888 | ] 889 | 890 | [[package]] 891 | name = "smallvec" 892 | version = "1.11.0" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" 895 | 896 | [[package]] 897 | name = "socket2" 898 | version = "0.4.9" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" 901 | dependencies = [ 902 | "libc", 903 | "winapi", 904 | ] 905 | 906 | [[package]] 907 | name = "socket2" 908 | version = "0.5.3" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" 911 | dependencies = [ 912 | "libc", 913 | "windows-sys", 914 | ] 915 | 916 | [[package]] 917 | name = "spin" 918 | version = "0.5.2" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 921 | 922 | [[package]] 923 | name = "strsim" 924 | version = "0.10.0" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 927 | 928 | [[package]] 929 | name = "syn" 930 | version = "2.0.31" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" 933 | dependencies = [ 934 | "proc-macro2", 935 | "quote", 936 | "unicode-ident", 937 | ] 938 | 939 | [[package]] 940 | name = "system-configuration" 941 | version = "0.5.1" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" 944 | dependencies = [ 945 | "bitflags 1.3.2", 946 | "core-foundation", 947 | "system-configuration-sys", 948 | ] 949 | 950 | [[package]] 951 | name = "system-configuration-sys" 952 | version = "0.5.0" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" 955 | dependencies = [ 956 | "core-foundation-sys", 957 | "libc", 958 | ] 959 | 960 | [[package]] 961 | name = "tinyvec" 962 | version = "1.6.0" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 965 | dependencies = [ 966 | "tinyvec_macros", 967 | ] 968 | 969 | [[package]] 970 | name = "tinyvec_macros" 971 | version = "0.1.1" 972 | source = "registry+https://github.com/rust-lang/crates.io-index" 973 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 974 | 975 | [[package]] 976 | name = "tokio" 977 | version = "1.33.0" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" 980 | dependencies = [ 981 | "backtrace", 982 | "bytes", 983 | "libc", 984 | "mio", 985 | "num_cpus", 986 | "parking_lot", 987 | "pin-project-lite", 988 | "signal-hook-registry", 989 | "socket2 0.5.3", 990 | "tokio-macros", 991 | "windows-sys", 992 | ] 993 | 994 | [[package]] 995 | name = "tokio-macros" 996 | version = "2.1.0" 997 | source = "registry+https://github.com/rust-lang/crates.io-index" 998 | checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" 999 | dependencies = [ 1000 | "proc-macro2", 1001 | "quote", 1002 | "syn", 1003 | ] 1004 | 1005 | [[package]] 1006 | name = "tokio-rustls" 1007 | version = "0.24.1" 1008 | source = "registry+https://github.com/rust-lang/crates.io-index" 1009 | checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" 1010 | dependencies = [ 1011 | "rustls", 1012 | "tokio", 1013 | ] 1014 | 1015 | [[package]] 1016 | name = "tokio-util" 1017 | version = "0.7.8" 1018 | source = "registry+https://github.com/rust-lang/crates.io-index" 1019 | checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" 1020 | dependencies = [ 1021 | "bytes", 1022 | "futures-core", 1023 | "futures-sink", 1024 | "pin-project-lite", 1025 | "tokio", 1026 | "tracing", 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "tower-service" 1031 | version = "0.3.2" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1034 | 1035 | [[package]] 1036 | name = "tracing" 1037 | version = "0.1.37" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1040 | dependencies = [ 1041 | "cfg-if", 1042 | "pin-project-lite", 1043 | "tracing-core", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "tracing-core" 1048 | version = "0.1.31" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" 1051 | dependencies = [ 1052 | "once_cell", 1053 | ] 1054 | 1055 | [[package]] 1056 | name = "try-lock" 1057 | version = "0.2.4" 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" 1059 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 1060 | 1061 | [[package]] 1062 | name = "unicode-bidi" 1063 | version = "0.3.13" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" 1066 | 1067 | [[package]] 1068 | name = "unicode-ident" 1069 | version = "1.0.11" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" 1072 | 1073 | [[package]] 1074 | name = "unicode-normalization" 1075 | version = "0.1.22" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1078 | dependencies = [ 1079 | "tinyvec", 1080 | ] 1081 | 1082 | [[package]] 1083 | name = "untrusted" 1084 | version = "0.7.1" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 1087 | 1088 | [[package]] 1089 | name = "url" 1090 | version = "2.4.1" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" 1093 | dependencies = [ 1094 | "form_urlencoded", 1095 | "idna", 1096 | "percent-encoding", 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "urlencoding" 1101 | version = "2.1.3" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" 1104 | 1105 | [[package]] 1106 | name = "utf8parse" 1107 | version = "0.2.1" 1108 | source = "registry+https://github.com/rust-lang/crates.io-index" 1109 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 1110 | 1111 | [[package]] 1112 | name = "want" 1113 | version = "0.3.1" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1116 | dependencies = [ 1117 | "try-lock", 1118 | ] 1119 | 1120 | [[package]] 1121 | name = "wasi" 1122 | version = "0.11.0+wasi-snapshot-preview1" 1123 | source = "registry+https://github.com/rust-lang/crates.io-index" 1124 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1125 | 1126 | [[package]] 1127 | name = "wasm-bindgen" 1128 | version = "0.2.87" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 1131 | dependencies = [ 1132 | "cfg-if", 1133 | "wasm-bindgen-macro", 1134 | ] 1135 | 1136 | [[package]] 1137 | name = "wasm-bindgen-backend" 1138 | version = "0.2.87" 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" 1140 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 1141 | dependencies = [ 1142 | "bumpalo", 1143 | "log", 1144 | "once_cell", 1145 | "proc-macro2", 1146 | "quote", 1147 | "syn", 1148 | "wasm-bindgen-shared", 1149 | ] 1150 | 1151 | [[package]] 1152 | name = "wasm-bindgen-futures" 1153 | version = "0.4.37" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" 1156 | dependencies = [ 1157 | "cfg-if", 1158 | "js-sys", 1159 | "wasm-bindgen", 1160 | "web-sys", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "wasm-bindgen-macro" 1165 | version = "0.2.87" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 1168 | dependencies = [ 1169 | "quote", 1170 | "wasm-bindgen-macro-support", 1171 | ] 1172 | 1173 | [[package]] 1174 | name = "wasm-bindgen-macro-support" 1175 | version = "0.2.87" 1176 | source = "registry+https://github.com/rust-lang/crates.io-index" 1177 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 1178 | dependencies = [ 1179 | "proc-macro2", 1180 | "quote", 1181 | "syn", 1182 | "wasm-bindgen-backend", 1183 | "wasm-bindgen-shared", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "wasm-bindgen-shared" 1188 | version = "0.2.87" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 1191 | 1192 | [[package]] 1193 | name = "web-sys" 1194 | version = "0.3.64" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" 1197 | dependencies = [ 1198 | "js-sys", 1199 | "wasm-bindgen", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "webpki-roots" 1204 | version = "0.25.2" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" 1207 | 1208 | [[package]] 1209 | name = "winapi" 1210 | version = "0.3.9" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1213 | dependencies = [ 1214 | "winapi-i686-pc-windows-gnu", 1215 | "winapi-x86_64-pc-windows-gnu", 1216 | ] 1217 | 1218 | [[package]] 1219 | name = "winapi-i686-pc-windows-gnu" 1220 | version = "0.4.0" 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" 1222 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1223 | 1224 | [[package]] 1225 | name = "winapi-x86_64-pc-windows-gnu" 1226 | version = "0.4.0" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1229 | 1230 | [[package]] 1231 | name = "windows-sys" 1232 | version = "0.48.0" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1235 | dependencies = [ 1236 | "windows-targets", 1237 | ] 1238 | 1239 | [[package]] 1240 | name = "windows-targets" 1241 | version = "0.48.5" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1244 | dependencies = [ 1245 | "windows_aarch64_gnullvm", 1246 | "windows_aarch64_msvc", 1247 | "windows_i686_gnu", 1248 | "windows_i686_msvc", 1249 | "windows_x86_64_gnu", 1250 | "windows_x86_64_gnullvm", 1251 | "windows_x86_64_msvc", 1252 | ] 1253 | 1254 | [[package]] 1255 | name = "windows_aarch64_gnullvm" 1256 | version = "0.48.5" 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" 1258 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1259 | 1260 | [[package]] 1261 | name = "windows_aarch64_msvc" 1262 | version = "0.48.5" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1265 | 1266 | [[package]] 1267 | name = "windows_i686_gnu" 1268 | version = "0.48.5" 1269 | source = "registry+https://github.com/rust-lang/crates.io-index" 1270 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1271 | 1272 | [[package]] 1273 | name = "windows_i686_msvc" 1274 | version = "0.48.5" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1277 | 1278 | [[package]] 1279 | name = "windows_x86_64_gnu" 1280 | version = "0.48.5" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1283 | 1284 | [[package]] 1285 | name = "windows_x86_64_gnullvm" 1286 | version = "0.48.5" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1289 | 1290 | [[package]] 1291 | name = "windows_x86_64_msvc" 1292 | version = "0.48.5" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1295 | 1296 | [[package]] 1297 | name = "winreg" 1298 | version = "0.50.0" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" 1301 | dependencies = [ 1302 | "cfg-if", 1303 | "windows-sys", 1304 | ] 1305 | --------------------------------------------------------------------------------