Compare commits

..
115 Commits
Author SHA1 Message Date
Autumn (Bee)andbee b9d5cee67a Auto merge dependabot PRs (#755)
This pr:
1. checks if the user == dependabot[bot]
2. if all CI passes, auto approve and merge the PR

Co-authored-by: bee <[email protected]>
2025-02-23 14:40:04 +00:00
fabianbees cbd0369dbd remove generated.rs file from git (#750) 2025-02-21 19:51:47 +00:00
Roger G. Coram f1ef3be688 feat: preserve IP address order (#749)
as part of #651, IP addresses are deduplicated; as this uses a
`BTreeSet`, the original order is not necessarily retained.

use
[`retain()`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.retain)
to remove duplicated and/or excluded IPs, mutating the original list of
IPs but preserving the original order.
2025-02-15 15:34:56 +00:00
Roger G. Coram 71091bfe86 Merge pull request #746 from fabianbees/fix/nmap-payloads-hex-conversion-error
fix: Statically generated payloads (nmap-payloads) for UDP scanning
2025-02-12 11:40:06 +00:00
Fabian Bees e797458f43 fix: Statically generated payloads (nmap-payloads) for UDP scanning 2025-02-12 12:36:05 +01:00
Roger G. Coram 2b409c9d33 Merge pull request #748 from RustScan/dependabot/cargo/hickory-proto-0.24.3
build(deps): bump hickory-proto from 0.24.1 to 0.24.3
2025-02-12 09:10:41 +00:00
Roger G. Coram ef8852aeff Merge pull request #747 from RustScan/dependabot/cargo/hickory-resolver-0.24.3
build(deps): bump hickory-resolver from 0.24.2 to 0.24.3
2025-02-12 09:10:11 +00:00
dependabot[bot] 98794d8187 build(deps): bump hickory-proto from 0.24.1 to 0.24.3
Bumps [hickory-proto](https://github.com/hickory-dns/hickory-dns) from 0.24.1 to 0.24.3.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.3/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.1...v0.24.3)

---
updated-dependencies:
- dependency-name: hickory-proto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-02-10 17:59:30 +00:00
dependabot[bot] 9221567d25 build(deps): bump hickory-resolver from 0.24.2 to 0.24.3
Bumps [hickory-resolver](https://github.com/hickory-dns/hickory-dns) from 0.24.2 to 0.24.3.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.3/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.2...v0.24.3)

---
updated-dependencies:
- dependency-name: hickory-resolver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-02-10 09:27:17 +00:00
fabianbees c5e518889e fix issue 663: UDP scan returns port as OPEN, when timed-out (#737) 2025-02-08 07:50:30 +00:00
Roger G. Coram 981c1741fe Merge pull request #744 from RustScan/dependabot/cargo/once_cell-1.20.3
build(deps): bump once_cell from 1.20.2 to 1.20.3
2025-02-07 11:22:56 +00:00
Roger G. Coram a88d311ecf Merge pull request #743 from RustScan/dependabot/cargo/toml-0.8.20
build(deps): bump toml from 0.8.19 to 0.8.20
2025-02-07 11:21:52 +00:00
Roger G. Coram c782b07041 Merge pull request #742 from RustScan/dependabot/cargo/wait-timeout-0.2.1
build(deps): bump wait-timeout from 0.2.0 to 0.2.1
2025-02-07 11:21:25 +00:00
dependabot[bot] 971f2523f5 build(deps): bump once_cell from 1.20.2 to 1.20.3
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.20.2 to 1.20.3.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.2...v1.20.3)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-02-07 09:08:57 +00:00
dependabot[bot] d1cd45ec29 build(deps): bump toml from 0.8.19 to 0.8.20
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.19 to 0.8.20.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.19...toml-v0.8.20)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-02-06 09:18:01 +00:00
dependabot[bot] a6213bc1a3 build(deps): bump wait-timeout from 0.2.0 to 0.2.1
Bumps [wait-timeout](https://github.com/alexcrichton/wait-timeout) from 0.2.0 to 0.2.1.
- [Commits](https://github.com/alexcrichton/wait-timeout/compare/0.2.0...0.2.1)

---
updated-dependencies:
- dependency-name: wait-timeout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-02-04 09:19:05 +00:00
Roger G. Coram e1689e506c Merge pull request #739 from RustScan/dependabot/cargo/rand-0.9.0
build(deps): bump rand from 0.8.5 to 0.9.0
2025-02-03 17:49:54 +00:00
PsypherPunk 85f4eb5a30 fix: update as per rand from 0.9.0
- `thread_rng` is now `rng`
- `gen_range` is now `random_range`
- `SliceRandom` is now `IndexedRandom`
2025-02-03 17:44:16 +00:00
dependabot[bot] 34744424d7 build(deps): bump rand from 0.8.5 to 0.9.0
Bumps [rand](https://github.com/rust-random/rand) from 0.8.5 to 0.9.0.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.8.5...0.9.0)

---
updated-dependencies:
- dependency-name: rand
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-02-03 17:44:16 +00:00
Roger G. Coram ba5d51788a fix: correct clippy warnings (#734) 2025-01-29 21:18:40 +00:00
Roger G. Coram b17b733580 docs: update link to build status badge (#730)
update the link as per the
[docs.](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/adding-a-workflow-status-badge#using-the-branch-parameter).
2025-01-23 19:25:16 +00:00
Roger G. Coram 3b06a34885 Merge pull request #719 from thannaske/feature-exclude-addresses
feat: add address exclusion flag (#718)
2025-01-20 13:09:27 +00:00
Roger G. Coram e3f129e6d1 Merge pull request #720 from sdushantha/no-banner
Added --no-banner option
2025-01-20 11:32:55 +00:00
Roger G. Coram 604ff2acf0 Merge pull request #732 from RustScan/dependabot/cargo/log-0.4.25
build(deps): bump log from 0.4.22 to 0.4.25
2025-01-19 09:27:43 +00:00
dependabot[bot] a8c52917c3 build(deps): bump log from 0.4.22 to 0.4.25
Bumps [log](https://github.com/rust-lang/log) from 0.4.22 to 0.4.25.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.22...0.4.25)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-15 09:20:48 +00:00
Roger G. Coram cbf0f94ca1 Merge pull request #729 from RustScan/dependabot/cargo/dirs-6.0.0
build(deps): bump dirs from 5.0.1 to 6.0.0
2025-01-13 10:18:31 +00:00
Roger G. Coram 4a7101b2f5 Merge pull request #727 from RustScan/dependabot/cargo/colored-3.0.0
build(deps): bump colored from 2.2.0 to 3.0.0
2025-01-13 10:12:16 +00:00
dependabot[bot] 07e7b30f51 build(deps): bump dirs from 5.0.1 to 6.0.0
Bumps [dirs](https://github.com/soc/dirs-rs) from 5.0.1 to 6.0.0.
- [Commits](https://github.com/soc/dirs-rs/commits)

---
updated-dependencies:
- dependency-name: dirs
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-13 09:29:40 +00:00
dependabot[bot] 43c43ae91d build(deps): bump colored from 2.2.0 to 3.0.0
Bumps [colored](https://github.com/mackwic/colored) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/mackwic/colored/releases)
- [Changelog](https://github.com/colored-rs/colored/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mackwic/colored/compare/v2.2.0...v3.0.0)

---
updated-dependencies:
- dependency-name: colored
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-08 09:37:03 +00:00
伊诺 4f19e42ebb Update input.rs (#726)
Updated a TOML syntax error  
scan_order = "Serial"
2025-01-03 10:27:03 +00:00
Roger G. Coram f1810702ab Merge pull request #725 from RustScan/dependabot/cargo/itertools-0.14.0
build(deps): bump itertools from 0.13.0 to 0.14.0
2025-01-02 14:07:07 +00:00
dependabot[bot] 0c0433d628 build(deps): bump itertools from 0.13.0 to 0.14.0
Bumps [itertools](https://github.com/rust-itertools/itertools) from 0.13.0 to 0.14.0.
- [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-itertools/itertools/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: itertools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-01 09:59:53 +00:00
Roger G. Coram de98d0044e Merge pull request #721 from RustScan/dependabot/cargo/env_logger-0.11.6
build(deps): bump env_logger from 0.11.5 to 0.11.6
2024-12-23 14:50:53 +00:00
dependabot[bot] 55e388241e build(deps): bump env_logger from 0.11.5 to 0.11.6
Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.11.5 to 0.11.6.
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.5...v0.11.6)

---
updated-dependencies:
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-12-23 10:01:33 +00:00
Siddharth Dushantha d969699fff Added --no-banner option 2024-12-22 13:04:36 +01:00
Roger G. Coram 4542798c7b build: remove Dockerfile (#712)
no longer explicitly supported.
2024-12-22 10:55:21 +00:00
Roger G. Coram 69629c4fc3 chore: fix clippy lists in tests/benchmarks (#717)
* chore: fix clippy lists in tests/benchmarks

* build: extend clippy checks to tests
2024-12-22 10:54:59 +00:00
t.hannaske 8676de1c19 Adding address exclusion option with test coverage 2024-12-22 09:51:14 +01:00
Roger G. Coram 90708aec1d Merge pull request #716 from RustScan/dependabot/cargo/colored-2.2.0
build(deps): bump colored from 2.1.0 to 2.2.0
2024-12-17 08:24:22 +00:00
Roger G. Coram 094a6f00e7 docs: remove attribution in comments (#714)
contributors are tracked within the repository and attribution remains
within the project's Git history.
2024-12-16 17:54:33 +00:00
dependabot[bot] 840daac9d2 build(deps): bump colored from 2.1.0 to 2.2.0
Bumps [colored](https://github.com/mackwic/colored) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/mackwic/colored/releases)
- [Changelog](https://github.com/colored-rs/colored/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mackwic/colored/compare/v2.1.0...v2.2.0)

---
updated-dependencies:
- dependency-name: colored
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-12-16 09:11:35 +00:00
Roger G. Coram b171ed7c88 Merge pull request #715 from RustScan/dependabot/cargo/hickory-resolver-0.24.2
build(deps): bump hickory-resolver from 0.24.1 to 0.24.2
2024-12-11 13:22:51 +00:00
dependabot[bot] 5a9cfeeb40 build(deps): bump hickory-resolver from 0.24.1 to 0.24.2
Bumps [hickory-resolver](https://github.com/hickory-dns/hickory-dns) from 0.24.1 to 0.24.2.
- [Release notes](https://github.com/hickory-dns/hickory-dns/releases)
- [Changelog](https://github.com/hickory-dns/hickory-dns/blob/v0.24.2/CHANGELOG.md)
- [Commits](https://github.com/hickory-dns/hickory-dns/compare/v0.24.1...v0.24.2)

---
updated-dependencies:
- dependency-name: hickory-resolver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-12-11 10:02:17 +00:00
Roger G. Coram 6a25fb1d98 Merge pull request #709 from Integral-Tech/replace-format
refactor: replace format! with concat! for string literals
2024-12-08 14:39:08 +00:00
Integral bddda4d2c8 refactor: skip using format! macro 2024-12-07 23:24:42 +08:00
Integral 75c7d6215b Fix CI 2024-12-07 23:17:00 +08:00
d9dec00197 benchmark code for rustscan (#705)
* benchmark

* Change duration of each individual port scan to 10ms

* test: extend UDP benchmark measurement time

* benching helper funcs

* Broken benchmarking code

* Add complete benchmarking for most functions

---------

Co-authored-by: bee <[email protected]>
Co-authored-by: PsypherPunk <[email protected]>
2024-11-26 12:57:52 +00:00
Roger G. Coram 1634bab1b4 Merge pull request #703 from RustScan/bee-add-benches
Add benchmarks for UDP and TCP
2024-11-25 20:21:39 +00:00
PsypherPunk c58c389b1e Merge branch 'master' into bee-add-benches 2024-11-25 20:16:11 +00:00
Roger G. Coram d150802c04 Merge pull request #702 from RustScan/bee-update-lib
Add documentation to RustScan library
2024-11-25 20:14:34 +00:00
PsypherPunk dd9e075e56 Merge branch 'master' into bee-update-lib 2024-11-25 20:10:34 +00:00
Roger G. Coram d3229ff9a9 Merge pull request #701 from RustScan/bee-fix-tests
Fix tests
2024-11-25 17:51:19 +00:00
bee aae43ef47e Add benchmarks for UDP and TCP
This CI will fail initially due to an issue fixed in another PR.

This runs the udp scan and tcp scan 100 times and gets an average measure.

Currently these are:

```
portscan tcp            time:   [38.941 ms 39.659 ms 40.397 ms]
                        change: [+62486512% +64310488% +66078003%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

Benchmarking portscan udp: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 5.9s, or reduce sample count to 80.
portscan udp            time:   [58.419 ms 59.596 ms 60.775 ms]
                        change: [+93198493% +96139097% +98913211%] (p = 0.00 < 0.05)
                        Performance has regressed.
```

Notes:
* TCP scan takes 40ms on average
* UDP scan does not complete all 100 samples, as it's a bit slow. Takes 60ms on average.
* I ran these previously for testing so "performance has regressed" can be ignored
* We scan 1k ports because 64k ports over 100 samples is way too many.
2024-11-25 10:51:43 +00:00
Autumn (Bee) 387edc7b05 Add port strat 2024-11-25 10:05:43 +00:00
Autumn (Bee) bb01c3b5ee Add documentation to RustScan library
Our library is sorely lacking docs. I read this https://docs.rs/rustscan/latest/rustscan/ and had no idea what the arguments are. These comments should hopefully show up :)
2024-11-25 10:03:38 +00:00
bee 89541eddfe Fix tests 2024-11-25 09:56:13 +00:00
bee 45537cf6cd Update readme 2024-11-25 09:51:41 +00:00
Integral b039db77f0 refactor: replace subprocess crate with std::process (#697) 2024-11-25 09:25:57 +00:00
Roger G. Coram 8350947caf build: clippy deny warnings (#698)
elevate all warnings to errors for `clippy`.
2024-11-25 07:38:51 +00:00
Autumn (Bee)andbee c7776873bb renamed testing and added CI for packaging (#688)
* renamed testing and added CI for packaging

* fix comments;

---------

Co-authored-by: bee <[email protected]>
2024-11-20 16:58:17 +00:00
Autumn (Bee) 306df13861 Update README.md 2024-11-20 06:56:51 +00:00
Roger G. Coram 88c58f3170 fix: avoid stderr in test output (#692)
as per discussions on the
[`subprocess`](https://github.com/hniksic/rust-subprocess/issues/62)
GitHub.
2024-11-19 08:57:52 +00:00
drawdropandbee 4e3c2a5649 chore: fix some comments (#644)
Signed-off-by: drawdrop <[email protected]>
Co-authored-by: bee <[email protected]>
2024-11-12 17:02:55 +00:00
Autumn (Bee)andbee d6fa72ae34 updated readme (#687)
Co-authored-by: bee <[email protected]>
2024-11-12 16:56:44 +00:00
Roger G. Coram 9ce001f60f Merge pull request #620 from israelrg/ipv6nmapfix
BugFix: Allow IPV6 addresses to be parsed into NMAP
2024-11-10 13:01:03 +00:00
Roger G. Coram f81312d63b Merge pull request #685 from RustScan/dependabot/cargo/anstream-0.6.18
build(deps): bump anstream from 0.6.17 to 0.6.18
2024-11-05 16:25:59 +00:00
Roger G. Coram 04224b6a72 Merge pull request #684 from RustScan/dependabot/github_actions/extractions/setup-just-2
build(deps): bump extractions/setup-just from 1 to 2
2024-11-05 16:25:24 +00:00
dependabot[bot] 086812f2a2 build(deps): bump anstream from 0.6.17 to 0.6.18
Bumps [anstream](https://github.com/rust-cli/anstyle) from 0.6.17 to 0.6.18.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.17...anstream-v0.6.18)

---
updated-dependencies:
- dependency-name: anstream
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-05 09:50:46 +00:00
dependabot[bot] 85959b8c13 build(deps): bump extractions/setup-just from 1 to 2
Bumps [extractions/setup-just](https://github.com/extractions/setup-just) from 1 to 2.
- [Release notes](https://github.com/extractions/setup-just/releases)
- [Commits](https://github.com/extractions/setup-just/compare/v1...v2)

---
updated-dependencies:
- dependency-name: extractions/setup-just
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-05 09:30:18 +00:00
Autumn (Bee)andbee e29aa7747c Bee release justfile (#682)
* added release and fix for justfile

* Ran just fix

---------

Co-authored-by: bee <[email protected]>
2024-11-04 16:29:39 +00:00
Autumn (Bee)andbee 640003f22c Remove builds from CI and change to just (#681)
* Remove builds from CI and change to `just`

Per discussion in Discord, we are:
* Removing all official distributions to focus solely on RustScan itself
* Moving to `just` so developers can run 1 command to run all of our test suites. In some PRs it has turned into a cat and mouse game where they are not running all of our testsl

* make CI run

* update readme

* update readme

* try to fix just

* typo

* fixing just

* install nextest

---------

Co-authored-by: bee <[email protected]>
2024-11-04 14:29:33 +00:00
Roger G. Coram 66de4e7ee0 Merge pull request #669 from RustScan/dependabot/github_actions/actions/upload-artifact-4.4.3
Bump actions/upload-artifact from 4.3.4 to 4.4.3
2024-11-04 10:20:26 +00:00
dependabot[bot] 7edff6d767 Bump actions/upload-artifact from 4.3.4 to 4.4.3
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.4 to 4.4.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.3.4...v4.4.3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 10:18:25 +00:00
Roger G. Coram 5198994cbd Merge pull request #665 from RustScan/dependabot/cargo/once_cell-1.20.2
Bump once_cell from 1.19.0 to 1.20.2
2024-11-04 10:17:11 +00:00
dependabot[bot] cabeb6b1cb Bump once_cell from 1.19.0 to 1.20.2
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.19.0 to 1.20.2.
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.19.0...v1.20.2)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 10:09:31 +00:00
Roger G. Coram 2956073d0d Merge pull request #657 from RustScan/dependabot/docker/alpine-3.20.3
Bump alpine from 3.20.2 to 3.20.3
2024-11-04 10:04:54 +00:00
dependabot[bot] 2c55f1ae58 Bump alpine from 3.20.2 to 3.20.3
Bumps alpine from 3.20.2 to 3.20.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 09:59:57 +00:00
Roger G. Coram e3bd50c922 Merge pull request #656 from RustScan/dependabot/cargo/async-std-1.13.0
Bump async-std from 1.12.0 to 1.13.0
2024-11-04 09:59:13 +00:00
dependabot[bot] d5ed38ef60 Bump async-std from 1.12.0 to 1.13.0
Bumps [async-std](https://github.com/async-rs/async-std) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/async-rs/async-std/releases)
- [Changelog](https://github.com/async-rs/async-std/blob/main/CHANGELOG.md)
- [Commits](https://github.com/async-rs/async-std/commits)

---
updated-dependencies:
- dependency-name: async-std
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 09:54:27 +00:00
Roger G. Coram e4937567b8 Merge pull request #654 from RustScan/dependabot/cargo/rlimit-0.10.2
Bump rlimit from 0.10.1 to 0.10.2
2024-11-04 09:53:38 +00:00
dependabot[bot] f90d56f02b Bump rlimit from 0.10.1 to 0.10.2
Bumps [rlimit](https://github.com/Nugine/rlimit) from 0.10.1 to 0.10.2.
- [Changelog](https://github.com/Nugine/rlimit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Nugine/rlimit/compare/v0.10.1...v0.10.2)

---
updated-dependencies:
- dependency-name: rlimit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 09:38:34 +00:00
Roger G. Coram fdd74c9dab Merge pull request #640 from RustScan/dependabot/cargo/clap-4.5.13
Bump clap from 4.5.9 to 4.5.13
2024-11-04 09:37:46 +00:00
dependabot[bot] 8b253edaed Bump clap from 4.5.9 to 4.5.13
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.9 to 4.5.13.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.9...v4.5.13)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 09:28:23 +00:00
Roger G. Coram 9ebc04cece Merge pull request #639 from RustScan/dependabot/cargo/toml-0.8.19
Bump toml from 0.8.14 to 0.8.19
2024-11-04 09:27:26 +00:00
dependabot[bot] 26f387adc0 Bump toml from 0.8.14 to 0.8.19
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.14 to 0.8.19.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.14...toml-v0.8.19)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 09:24:27 +00:00
Roger G. Coram a46096dab5 Merge pull request #638 from RustScan/dependabot/cargo/colorful-0.3.2
Bump colorful from 0.2.2 to 0.3.2
2024-11-04 09:23:34 +00:00
dependabot[bot] 9c0992dcd0 Bump colorful from 0.2.2 to 0.3.2
Bumps [colorful](https://github.com/mellite/colorful) from 0.2.2 to 0.3.2.
- [Commits](https://github.com/mellite/colorful/commits)

---
updated-dependencies:
- dependency-name: colorful
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 09:20:19 +00:00
Roger G. Coram 347985ea52 Merge pull request #679 from RustScan/dependabot/cargo/anstream-0.6.17
Bump anstream from 0.6.14 to 0.6.17
2024-11-04 09:19:15 +00:00
dependabot[bot] cafcc10b2e Bump anstream from 0.6.14 to 0.6.17
Bumps [anstream](https://github.com/rust-cli/anstyle) from 0.6.14 to 0.6.17.
- [Commits](https://github.com/rust-cli/anstyle/compare/anstream-v0.6.14...anstream-v0.6.17)

---
updated-dependencies:
- dependency-name: anstream
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 09:13:50 +00:00
mugiseyebrows 371ef81c7b fix colors in terminal on windows (#678) 2024-11-04 08:54:48 +00:00
Roger G. Coram 54bc6bf191 build: remove release on pull-request (#673)
- prevent running of the release workflow on pull-request: releases should
  only happen on explicit tagging.
- tests etc. still run as part of the build workflow.
2024-11-04 08:54:40 +00:00
Autumn (Bee)andbee 042a1c7b6c Added justfile for tests (#680)
Co-authored-by: bee <[email protected]>
2024-11-04 08:54:21 +00:00
Roger G. Coram aed0d71de8 Merge pull request #675 from mcamou/add-arm64-docker-build
Fixes #645: Add arm64 Docker image build
2024-10-26 11:52:07 +01:00
mcamou ea428a1a22 Add arm64 Docker image build 2024-10-26 12:19:04 +02:00
Roger G. Coram da41cb062d fix: avoid duplicate IP addresses (#660)
avoid scanning duplicated IPs for overlapping CIDRs.

fixes #651
2024-09-21 19:06:14 +01:00
Roger G. Coram 0a40d1539a Merge pull request #653 from socketz/patch-1
Update README.md
2024-09-19 14:13:43 +01:00
Roger G. Coram c3d24feebe Merge pull request #632 from RustScan/dependabot/cargo/env_logger-0.11.5
Bump env_logger from 0.11.3 to 0.11.5
2024-09-18 16:45:03 +01:00
BrendanGlancy 45fa80acd4 Statically generated payloads (#643)
* update the master branch to use nmap-payloads file

* code generation

* statically generate payloads, workingish

* actually puts the map in memory at compile time

* I am not sure this needs to be in the repo since its built on compilation

* actually ignores

* converting this in networking class counts as paying attention to the lecture right?

* see if if works on windows

* see

* I think i fixed CI

* fixes clippy

* ugh

* formats the gen code automagically

* UDP Service Probing

* UDP Service Probing

* Better comments

* fixes clippy

* fixes cargo fmt
2024-09-13 17:49:30 +01:00
Roger G. Coram a6f04c5c4a Merge pull request #618 from Arvmor/master
Using references in `init_scripts()` to avoid unnecessary `.clone()`s
2024-08-28 09:14:41 +01:00
socketz 0a09da40aa Update README.md
Fixed Build badge
2024-08-27 13:00:33 +02:00
dependabot[bot] 6ffd5f741e Bump env_logger from 0.11.3 to 0.11.5
Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.11.3 to 0.11.5.
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.3...v0.11.5)

---
updated-dependencies:
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-21 18:49:48 +00:00
Roger G. Coram efc42af2aa build: allow cargo-tarpaulin config (#647) 2024-08-21 14:10:10 +01:00
Israel Rodriguez Gallego 4f964b7d47 Clean comments 2024-08-17 23:17:48 +02:00
Israel Rodriguez Gallego 3887dbb93f Remove module that is not used 2024-08-17 23:16:32 +02:00
Israel Rodriguez Gallego 9c2c03f68c Move IP version check match inside the enum declaration 2024-08-17 23:09:48 +02:00
Rui Chen d6cd9392d6 docs: fix homebrew formula link (#636) 2024-08-07 08:58:26 +01:00
dependabot[bot] 12dfefaf4d Bump alpine from 3.20.1 to 3.20.2 (#628)
Bumps alpine from 3.20.1 to 3.20.2.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-26 11:56:04 +01:00
Paul Pfeister 663a3df7ed Match crate license to source (#616) 2024-07-26 11:55:19 +01:00
Israel Rodriguez Gallego 7d8b36aaef BugFix: Allow IPV6 addresses to be parsed into NMAP 2024-07-15 23:05:57 +02:00
Arvin Morawej 4564036218 Fix Lint errors, unused imports 2024-07-11 09:39:49 -04:00
Arvin Morawej 5b87f96451 Fix Lint errors 2024-07-11 09:36:24 -04:00
Arvin Morawej 033e2810f2 Using references in init_scripts()to avoid unnecessary .clone()s 2024-07-11 09:29:40 -04:00
Roger G. Coram 9f35cd43bc Merge pull request #617 from RustScan/dependabot/cargo/clap-4.5.9
Bump clap from 4.5.8 to 4.5.9
2024-07-09 10:46:11 +01:00
dependabot[bot] 68e26cc0fc Bump clap from 4.5.8 to 4.5.9
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.8 to 4.5.9.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.5.8...v4.5.9)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-07-09 09:11:22 +00:00
Autumn (Bee)andbee-san 9c63b56142 2.4.0 (#613)
Co-authored-by: bee-san <[email protected]>
2024-07-08 14:48:22 +01:00
26 changed files with 2129 additions and 1083 deletions

No files matched your search

+4
View File
@@ -7,6 +7,10 @@ assignees: ''
---
IMPORTANT: If you do not fill this out, your issue will be automatically closed.
As of November 2024, RustScan no longer offiically supports any packages other than `cargo`. If you have an issue with Docker or a `.deb`, please bring it up with whoever created it :)
**Describe the bug**
A clear and concise description of what the bug is.
+169 -86
View File
@@ -1,96 +1,179 @@
name: Build
on:
pull_request:
paths-ignore:
- '.github/**'
push:
branches:
- master
paths-ignore:
- '.github/**'
schedule:
- cron: '00 01 * * *'
name: CD Pipeline
on: [push]
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: Swatinem/rust-cache@v2
- name: Run cargo check
uses: actions-rs/cargo@v1
with:
command: check
test:
name: Test Suite
build-nix:
env:
IN_PIPELINE: true
runs-on: ${{ matrix.os }}
if: github.ref == 'refs/heads/master'
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
rust: [stable]
runs-on: ${{ matrix.os }}
type: [ubuntu-x64, ubuntu-x86, armv7, aarch64]
include:
- type: ubuntu-x64
os: ubuntu-latest
target: x86_64-unknown-linux-musl
name: x86_64-linux-rustscan
path: target/x86_64-unknown-linux-musl/release/rustscan
pkg_config_path: /usr/lib/x86_64-linux-gnu/pkgconfig
- type: ubuntu-x86
os: ubuntu-latest
target: i686-unknown-linux-musl
name: x86-linux-rustscan
path: target/i686-unknown-linux-musl/release/rustscan
pkg_config_path: /usr/lib/i686-linux-gnu/pkgconfig
- type: armv7
os: ubuntu-latest
target: armv7-unknown-linux-gnueabihf
name: armv7-linux-rustscan
path: target/armv7-unknown-linux-gnueabihf/release/rustscan
pkg_config_path: /usr/lib/x86_64-linux-gnu/pkgconfig
- type: aarch64
os: ubuntu-latest
target: aarch64-unknown-linux-gnu
name: aarch64-linux-rustscan
path: target/aarch64-unknown-linux-gnu/release/rustscan
pkg_config_path: /usr/lib/x86_64-linux-gnu/pkgconfig
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
- uses: actions/checkout@v4
- name: Cache cargo & target directories
uses: Swatinem/rust-cache@v2
- name: Build binary
uses: houseabsolute/actions-rust-cross@v0
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- uses: Swatinem/rust-cache@v2
- name: Run cargo test
uses: actions-rs/cargo@v1
with:
command: test
lints:
name: Lints
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
submodules: true
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
command: build
target: ${{ matrix.target }}
args: "--locked --release"
strip: true
toolchain: stable
override: true
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Run cargo fmt
uses: actions-rs/cargo@v1
- name: Build tar.gz for homebrew installs
if: matrix.type == 'ubuntu-x64'
run: |
tar czf ${{ matrix.name }}.tar.gz -C target/x86_64-unknown-linux-musl/release rustscan
- uses: actions/upload-artifact@v4
with:
command: fmt
args: --all -- --check
- name: Run cargo clippy
uses: actions-rs/cargo@v1
name: ${{ matrix.name }}
path: ${{ matrix.path }}
- uses: actions/upload-artifact@v4
if: matrix.type == 'ubuntu-x64'
with:
command: clippy
args: -- -D warnings
- name: Run rustdoc lints
uses: actions-rs/cargo@v1
name: ${{ matrix.name }}.tar.gz
path: ${{ matrix.name }}.tar.gz
build-deb:
needs: [build-nix]
runs-on: ubuntu-latest
env:
IN_PIPELINE: true
steps:
- uses: actions/checkout@v4
- name: Install cargo-deb
run: cargo install -f cargo-deb
- uses: awalsh128/cache-apt-pkgs-action@v1
with:
command: doc
args: --workspace --all-features --no-deps --document-private-items
packages: musl-tools # provides musl-gcc
version: 1.0
- name: Install musl toolchain
run: rustup target add x86_64-unknown-linux-musl
- name: Deb Build
run: cargo deb --target=x86_64-unknown-linux-musl
- name: Upload Deb Artifact
uses: actions/upload-artifact@v4
with:
name: rustscan.deb
path: ./target/x86_64-unknown-linux-musl/debian/*
build-macos:
env:
IN_PIPELINE: true
runs-on: macos-latest
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v4
- name: Cache cargo & target directories
uses: Swatinem/rust-cache@v2
- name: Build binary
uses: houseabsolute/actions-rust-cross@v0
with:
command: build
target: x86_64-apple-darwin
args: "--locked --release"
strip: true
toolchain: stable
- name: Build tar.gz for homebrew installs
run: |
tar czf x86_64-macos-rustscan.tar.gz -C target/x86_64-apple-darwin/release rustscan
- uses: actions/upload-artifact@v4
with:
name: x86_64-macos-rustscan
path: target/x86_64-apple-darwin/release/rustscan
- uses: actions/upload-artifact@v4
with:
name: x86_64-macos-rustscan.tar.gz
path: x86_64-macos-rustscan.tar.gz
build-macos-aarch64:
env:
IN_PIPELINE: true
runs-on: macos-latest
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v4
- name: Cache cargo & target directories
uses: Swatinem/rust-cache@v2
- name: Build binary
uses: houseabsolute/actions-rust-cross@v0
with:
command: build
target: aarch64-apple-darwin
args: "--locked --release"
strip: true
toolchain: stable
- name: Build tar.gz for homebrew installs
run: |
tar czf aarch64-macos-rustscan.tar.gz -C target/aarch64-apple-darwin/release rustscan
- uses: actions/upload-artifact@v4
with:
name: aarch64-macos-rustscan
path: target/aarch64-apple-darwin/release/rustscan
- uses: actions/upload-artifact@v4
with:
name: aarch64-macos-rustscan.tar.gz
path: aarch64-macos-rustscan.tar.gz
build-windows:
env:
IN_PIPELINE: true
runs-on: ${{ matrix.os }}
if: github.ref == 'refs/heads/master'
strategy:
matrix:
type: [windows-x64, windows-x86]
include:
- type: windows-x64
os: windows-latest
target: x86_64-pc-windows-msvc
name: x86_64-windows-rustscan.exe
path: target\x86_64-pc-windows-msvc\release\rustscan.exe
- type: windows-x86
os: windows-latest
target: i686-pc-windows-msvc
name: x86-windows-rustscan.exe
path: target\i686-pc-windows-msvc\release\rustscan.exe
steps:
- uses: actions/checkout@v4
- name: Cache cargo & target directories
uses: Swatinem/rust-cache@v2
- name: Build binary
uses: houseabsolute/actions-rust-cross@v0
with:
command: build
target: ${{ matrix.target }}
args: "--locked --release"
strip: true
toolchain: stable
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: ${{ matrix.path }}
+19
View File
@@ -0,0 +1,19 @@
name: Dependabot Auto-Merge
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- name: Enable auto-merge for Dependabot PRs
run: |
gh pr review --approve "$PR_URL"
gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-38
View File
@@ -1,38 +0,0 @@
name: Release - Distribute Docker image
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
# release:
# types: [published]
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Log in to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
password: ${{ secrets.DOCKERHUB_USERNAME }}
username: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: rustscan/rustscan
flavor: latest=true
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: ${{ contains(fromJson('["push", "release"]'), github.event_name) }} # Publish to docker registry only on push event or new release.
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
-216
View File
@@ -1,216 +0,0 @@
name: Release - Distribute binaries
on:
# If we want to make release using github interface.
# release:
# types: [published]
# If we want to make release by pushing new tag.
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
pull_request:
branches:
- master
paths:
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/release.yml'
env:
BIN_NAME: rustscan
PROJECT_NAME: rustscan
REPO_NAME: RustScan/RustScan
BREW_TAP: RustScan/homebrew-tap
jobs:
build:
name: Build
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false # don't fail other jobs if one fails
matrix:
# aarch64-linux is failing due to python3 missing issues during tests. I'm removing it for now.
# build: [x86_64-linux, aarch64-linux, x86_64-macos, aarch64-macos, x86_64-windows, x86_64-win-gnu]
build: [x86_64-linux, x86_64-macos, aarch64-macos, x86_64-windows, x86_64-win-gnu]
include:
- build: aarch64-macos
os: macos-latest
rust: stable
target: aarch64-apple-darwin
cross: true
# - build: aarch64-linux
# os: ubuntu-20.04
# rust: stable
# target: aarch64-unknown-linux-gnu
# cross: true
- build: x86_64-linux
os: ubuntu-20.04
rust: stable
target: x86_64-unknown-linux-gnu
cross: false
- build: x86_64-macos
os: macos-latest
rust: stable
target: x86_64-apple-darwin
cross: false
- build: x86_64-windows
os: windows-2019
rust: stable
target: x86_64-pc-windows-msvc
cross: false
- build: x86_64-win-gnu
os: windows-2019
rust: stable-x86_64-gnu
target: x86_64-pc-windows-gnu
cross: false
steps:
- name: Set Git config (windows only)
if: contains(matrix.os, 'windows') # Windows is missing some dependencies
run: |
git config --global pack.windowMemory "100m"
git config --global pack.packSizeLimit "100m"
git config --global pack.threads "1"
git config --global pack.deltaCacheSize "512m"
- name: Install dependencies
if: contains(matrix.build, 'aarch64-linux') # Windows is missing some dependencies
run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu python3
- name: Install python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Checkout sources
uses: actions/checkout@v4
with:
submodules: true
- name: Install ${{ matrix.rust }} toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
override: true
- name: Run cargo test
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.cross }}
command: test
args: --release --locked --target ${{ matrix.target }}
- name: Build release binary
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.cross }}
command: build
args: --release --locked --target ${{ matrix.target }}
- name: Calculate tag name
# if: contains(matrix.build, 'linux')
shell: bash
run: |
name=dev
if [[ ${GITHUB_REF} =~ refs/tags/[0-9]+.[0-9]+.[0-9]+ ]]; then
name=${GITHUB_REF#refs/tags/}
fi
echo "TAG=$name" >> $GITHUB_ENV
id: tagname
- name: Build and package artifacts
shell: bash
run: |
mkdir dist
if [[ "${{ matrix.build }}" =~ "windows" ]]; then
cp "target/${{ matrix.target }}/release/$BIN_NAME.exe" "dist/"
else
cp "target/${{ matrix.target }}/release/$BIN_NAME" "dist/"
fi
if [[ "${{ matrix.build }}" =~ "linux" ]]; then
cargo install cargo-deb
cargo deb --target ${{ matrix.target }} --deb-version ${TAG}
cp "target/${{ matrix.target }}/debian/rustscan_${TAG}_amd64.deb" "dist/" || true
fi
- uses: actions/[email protected]
with:
name: bins-${{ matrix.build }}
path: dist
package:
name: Package
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
with:
submodules: false
- uses: actions/download-artifact@v4
with:
path: dist
- name: Calculate tag name
# if: contains(matrix.build, 'linux')
shell: bash
run: |
name=dev
if [[ ${GITHUB_REF} =~ refs/tags/[0-9]+.[0-9]+.[0-9]+ ]]; then
name=${GITHUB_REF#refs/tags/}
fi
echo "TAG=$name" >> $GITHUB_ENV
id: tagname
- name: Build archive
shell: bash
run: |
set -ex
rm -rf tmp
mkdir tmp
for dir in dist/bins-* ; do
platform=${dir#"dist/bins-"}
unset exe
if [[ $platform =~ "win" ]]; then
exe=".exe"
fi
pkgname=$PROJECT_NAME-$TAG-$platform
mkdir tmp/$pkgname
cp $dir/$BIN_NAME$exe dist/ || true
mv $dir/$BIN_NAME$exe tmp/$pkgname
chmod +x tmp/$pkgname/$BIN_NAME$exe
if [[ $platform =~ "linux" ]]; then
mv "$dir/rustscan_${TAG}_amd64.deb" dist/ || true
fi
tar cJf dist/$pkgname.tar.xz -C tmp $pkgname
7z a dist/$pkgname.zip tmp/$pkgname
done
- name: Upload binaries to release
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'release'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/*
file_glob: true
tag: ${{ github.ref }}
overwrite: true
# - uses: mislav/bump-homebrew-formula-action@v3
# with:
# formula-path: ${{env.PROJECT_NAME}}.rb
# homebrew-tap: ${{ env.BREW_TAP }}
# download-url: 'https://github.com/${{ env.REPO_NAME }}/releases/download/${{ github.ref }}/${{env.PROJECT_NAME}}-${{ github.ref }}-x86_64-macos.tar.xz'
# commit-message: updating formula for ${{ env.PROJECT_NAME }}
# env:
# COMMITTER_TOKEN: ${{ secrets.COMMITTER_TOKEN }}
- run: cargo publish --token ${CRATES_TOKEN}
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'release'
env:
CRATES_TOKEN: ${{ secrets.CRATES_TOKEN }}
+34
View File
@@ -0,0 +1,34 @@
name: Test
on:
pull_request:
branches: [master]
push:
branches:
- master
jobs:
test:
name: Test Suite
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
rust: [stable]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- uses: taiki-e/install-action@nextest
- uses: Swatinem/rust-cache@v2
- name: Install Just
uses: extractions/setup-just@v2
- name: Run just
run: just test
+3 -1
View File
@@ -1,6 +1,8 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# generated file by build.rs for mapping nmap-payloads to rust
src/generated.rs
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
@@ -121,4 +123,4 @@ fabric.properties
.idea
.idea*
settings.json
settings.json
Generated
+700 -251
View File
File diff suppressed because it is too large. Load diff
+23 -15
View File
@@ -6,7 +6,7 @@ edition = "2018"
description = "Faster Nmap Scanning with Rust"
homepage = "https://github.com/rustscan/rustscan"
repository = "https://github.com/rustscan/rustscan"
license = "MIT"
license = "GPL-3.0-only"
keywords = ["port", "scanning", "nmap"]
categories = ["command-line-utilities"]
readme = "README.md"
@@ -17,32 +17,33 @@ exclude = [
]
[dependencies]
clap = { version = "4.5.8", features = ["derive", "wrap_help"] }
colored = "2.1.0"
async-std = "1.7.0"
clap = { version = "4.5.13", features = ["derive", "wrap_help"] }
colored = "3.0.0"
async-std = "1.13.0"
futures = "0.3"
rlimit = "0.10.1"
log = "0.4.22"
env_logger = "0.11.3"
anstream = "=0.6.14"
dirs = "5.0.1"
rlimit = "0.10.2"
log = "0.4.25"
env_logger = "0.11.6"
anstream = "=0.6.18"
dirs = "6.0.0"
gcd = "2.0.1"
rand = "0.8.5"
colorful = "0.2.1"
rand = "0.9.0"
colorful = "0.3.2"
ansi_term = "0.12.1"
toml = "0.8.14"
toml = "0.8.20"
serde = "1.0.124"
serde_derive = "1.0.116"
cidr-utils = "0.6.1"
itertools = "0.13.0"
hickory-resolver = { version = "0.24.0", features = ["dns-over-rustls"] }
itertools = "0.14.0"
hickory-resolver = { version = "0.24.3", features = ["dns-over-rustls"] }
anyhow = "1.0.40"
subprocess = "0.2.6"
text_placeholder = { version = "0.5", features = ["struct_context"] }
once_cell = "1.20.3"
[dev-dependencies]
parameterized = "2.0.0"
wait-timeout = "0.2"
criterion = { version = "0.5", features = ["html_reports"] }
[package.metadata.deb]
depends = "$auto, nmap"
@@ -57,3 +58,10 @@ strip = true
[[bin]]
name = "rustscan"
path = "src/main.rs"
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(tarpaulin_include)"] }
[[bench]]
name = "benchmark_portscan"
harness = false
-25
View File
@@ -1,25 +0,0 @@
# Build Stage
FROM rust:alpine as builder
LABEL maintainer="RustScan <https://github.com/RustScan>"
RUN apk add --no-cache build-base
# Encourage some layer caching here rather then copying entire directory that includes docs to builder container ~CMN
WORKDIR /app/rustscan
COPY Cargo.toml Cargo.lock ./
COPY src/ src/
RUN cargo build --release
# Release Stage
FROM alpine:3.20.1 as release
LABEL author="Hydragyrum <https://github.com/Hydragyrum>"
LABEL author="LeoFVO <https://github.com/LeoFVO>"
RUN addgroup -S rustscan && \
adduser -S -G rustscan rustscan && \
ulimit -n 100000 && \
apk add --no-cache nmap nmap-scripts wget ca-certificates bind-tools
USER rustscan
COPY --from=builder /app/rustscan/target/release/rustscan /usr/local/bin/rustscan
ENTRYPOINT [ "/usr/local/bin/rustscan" ]
+29 -29
View File
@@ -9,16 +9,6 @@
![Arch Linux package][badge-1] ![Built with Rust][badge-2] ![GitHub All Releases][badge-3] ![Crates.io][badge-4] ![Discord][badge-5] ![Actions][badge-6]
---
| 🐋 `(Recommended)` | 👩‍💻 | 🏗️ | 🔧 |
| :---------------------------------------------------------: | :---------------------------: | :-------------------------: | :-------------------------: |
| [![Docker][DockerPic]][Docker] | [![Kali][Kali1]][Kali/Debian] | [![Arch][Arch]][Arch-Linux] | [![apple][apple]][Homebrew] |
| `docker pull rustscan/rustscan:latest`</br>[Docker][usage-0] | [Link to Documentation][kali] | `yay -S rustscan` | `brew install rustscan` |
---
</div>
# 🤔 What is this?
@@ -27,6 +17,32 @@
The Modern Port Scanner. **Find ports quickly (3 seconds at its fastest)**. Run scripts through our scripting engine (Python, Lua, Shell supported).
# 🛠️ Installation
You can install RustScan's binary from our [releases page](https://github.com/RustScan/RustScan/releases).
We would prefer you to install with a package manager so it is tested and works for your system.
RustScan is in many repositories already. Install it with whatever tools you wish:
[![Packaging status](https://repology.org/badge/vertical-allrepos/rustscan.svg)](https://repology.org/project/rustscan/versions)
RustScan only officially supports Cargo installations, if you want to use that please install Rust and then `cargo install rustscan`
Example installations include:
MacOS:
```
brew install rustscan
```
Arch:
```
yay rustscan
```
# ✨ Features
- Scans all 65k ports in **3 seconds**.
@@ -47,7 +63,6 @@ The Modern Port Scanner. **Find ports quickly (3 seconds at its fastest)**. Run
- 🐋 [Docker Usage][toc-docker-usage]
- 🦜 [Discord][discord]
- 🤸 [Usage][usage-1]
- 🎪 [Community][toc-community]
# 🔭 Why RustScan?
@@ -105,21 +120,6 @@ RustScan is one of the first penetration testing tools that aims to be entirely
RustScan has continuous integration testing that aims to ensure it is accessible, and we are constantly working on ways to improve our accessibility and ensure _everyone_ can use RustScan.
# 📖 Full Installation Guide
You can find our guide [here][install-1].
## 🦊 Community Distributions
Here are all of RustScan's community distributions.
If you maintain a community distribution and want it listed here, leave an issue / pull request / Discord message or however, you want to let us know.
- [Open Suse][distributions-1]
- [Fedora/CentOS][distributions-2]
[![Packaging status][rustscan-svg]][repology-1]
# 🤸 Usage
We have 2 usage guides. [Basic Usage][usage-1] and [Things you may want to do][usage-2].
@@ -145,7 +145,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://skerritt.blog"><img src="https://avatars3.githubusercontent.com/u/10378052?v=4" width="100px;" alt=""/><br /><sub><b>Brandon</b></sub></a><br /><a href="#infra-brandonskerritt" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/RustScan/RustScan/commits?author=brandonskerritt" title="Tests">⚠️</a> <a href="https://github.com/RustScan/RustScan/commits?author=brandonskerritt" title="Code">💻</a> <a href="#design-brandonskerritt" title="Design">🎨</a></td>
<td align="center"><a href="https://skerritt.blog"><img src="https://avatars3.githubusercontent.com/u/10378052?v=4" width="100px;" alt=""/><br /><sub><b>Bee</b></sub></a><br /><a href="#infra-beeskerritt" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/RustScan/RustScan/commits?author=beeskerritt" title="Tests">⚠️</a> <a href="https://github.com/RustScan/RustScan/commits?author=beesan" title="Code">💻</a> <a href="#design-beeskerritt" title="Design">🎨</a></td>
<td align="center"><a href="https://sakiir.ovh"><img src="https://avatars1.githubusercontent.com/u/9950578?v=4" width="100px;" alt=""/><br /><sub><b>SakiiR</b></sub></a><br /><a href="https://github.com/RustScan/RustScan/commits?author=SakiiR" title="Code">💻</a> <a href="https://github.com/RustScan/RustScan/issues?q=author%3ASakiiR" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/smackhack"><img src="https://avatars2.githubusercontent.com/u/48143394?v=4" width="100px;" alt=""/><br /><sub><b>smackhack</b></sub></a><br /><a href="#ideas-smackhack" title="Ideas, Planning, & Feedback">🤔</a> <a href="#example-smackhack" title="Examples">💡</a></td>
<td align="center"><a href="http://bernardoamc.github.io/"><img src="https://avatars0.githubusercontent.com/u/428984?v=4" width="100px;" alt=""/><br /><sub><b>Bernardo Araujo</b></sub></a><br /><a href="https://github.com/RustScan/RustScan/commits?author=bernardoamc" title="Code">💻</a> <a href="https://github.com/RustScan/RustScan/issues?q=author%3Abernardoamc" title="Bug reports">🐛</a> <a href="#design-bernardoamc" title="Design">🎨</a></td>
@@ -193,7 +193,7 @@ This project follows the [all-contributors](https://github.com/all-contributors/
[kali]: https://github.com/RustScan/RustScan/wiki/Installation-Guide#%EF%B8%8F-debian--kali "Read the install guide"
[Kali/Debian]: https://github.com/RustScan/RustScan/releases "Kali Debian"
[Arch-Linux]: https://archlinux.org/packages/extra/x86_64/rustscan/ "Arch Linux installation of Rustscan"
[Homebrew]: https://crates.io/crates/rustscan/ "Homebrew install of Rustscan"
[Homebrew]: https://formulae.brew.sh/formula/rustscan "Homebrew install of Rustscan"
[usage-1]: https://github.com/RustScan/RustScan/wiki/Usage "Basic Usage of Rustscan"
[usage-0]: https://github.com/RustScan/RustScan/wiki/Installation-Guide#docker-whale "Use Docker Rustscan"
[config-file-here]: https://github.com/RustScan/RustScan/wiki/Config-File "RustScan Configuration File"
@@ -232,4 +232,4 @@ This project follows the [all-contributors](https://github.com/all-contributors/
[badge-3]: https://img.shields.io/github/downloads/rustscan/rustscan/total?label=GitHub%20Downloads
[badge-4]: https://img.shields.io/crates/d/rustscan?label=Cargo%20Downloads
[badge-5]: https://img.shields.io/discord/754001738184392704
[badge-6]: https://github.com/RustScan/RustScan/workflows/Continuous%20integration/badge.svg?branch=master
[badge-6]: https://github.com/RustScan/RustScan/actions/workflows/build.yml/badge.svg?branch=master
+80
View File
@@ -0,0 +1,80 @@
use async_std::task::block_on;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rustscan::input::{PortRange, ScanOrder};
use rustscan::port_strategy::PortStrategy;
use rustscan::scanner::Scanner;
use std::net::IpAddr;
use std::time::Duration;
fn portscan_tcp(scanner: &Scanner) {
let _scan_result = block_on(scanner.run());
}
fn portscan_udp(scanner: &Scanner) {
let _scan_result = block_on(scanner.run());
}
fn bench_address() {
let _addrs = ["127.0.0.1".parse::<IpAddr>().unwrap()];
}
fn bench_port_strategy() {
let range = PortRange {
start: 1,
end: 1_000,
};
let _strategy = PortStrategy::pick(&Some(range.clone()), None, ScanOrder::Serial);
}
fn criterion_benchmark(c: &mut Criterion) {
let addrs = vec!["127.0.0.1".parse::<IpAddr>().unwrap()];
let range = PortRange {
start: 1,
end: 1_000,
};
let strategy_tcp = PortStrategy::pick(&Some(range.clone()), None, ScanOrder::Serial);
let strategy_udp = PortStrategy::pick(&Some(range.clone()), None, ScanOrder::Serial);
let scanner_tcp = Scanner::new(
&addrs,
10,
Duration::from_millis(10),
1,
false,
strategy_tcp,
true,
vec![],
false,
);
c.bench_function("portscan tcp", |b| {
b.iter(|| portscan_tcp(black_box(&scanner_tcp)))
});
let scanner_udp = Scanner::new(
&addrs,
10,
Duration::from_millis(10),
1,
false,
strategy_udp,
true,
vec![],
true,
);
let mut udp_group = c.benchmark_group("portscan udp");
udp_group.measurement_time(Duration::from_secs(20));
udp_group.bench_function("portscan udp", |b| {
b.iter(|| portscan_udp(black_box(&scanner_udp)))
});
udp_group.finish();
// Benching helper functions
c.bench_function("parse address", |b| b.iter(bench_address));
c.bench_function("port strategy", |b| b.iter(bench_port_strategy));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
+234
View File
@@ -0,0 +1,234 @@
use std::collections::BTreeMap;
use std::fs::{self, File};
use std::env;
use std::io::{BufReader, Read};
use std::path::PathBuf;
use std::process::Command;
// Reads in a file with payloads based on port
pub fn main() {
let mut file_path = env::current_dir().expect("cant find curr dir");
file_path.push("./nmap-payloads");
let mut data = String::new();
let file = File::open(&file_path).expect("File not found.");
let mut file_buf = BufReader::new(file);
file_buf
.read_to_string(&mut data)
.expect("unable to read file");
let mut fp_map: BTreeMap<i32, String> = BTreeMap::new();
let mut count = 0;
let mut capturing = false;
let mut curr = String::new();
for line in data.trim().split('\n') {
if line.contains('#') || line.is_empty() {
continue;
}
if line.starts_with("udp") {
if !curr.is_empty() {
fp_map.insert(count, curr);
curr = String::new();
}
capturing = true;
count += 1;
}
if capturing {
if !curr.is_empty() {
curr.push(' ');
}
curr.push_str(line);
}
}
let pb_linenr = ports_v(&fp_map);
let payb_linenr = payloads_v(&fp_map);
let map = port_payload_map(pb_linenr, payb_linenr);
generate_code(map);
}
/// Generates a file called Generated.rs and calls cargo fmt from the command line
///
/// # Arguments
///
/// * `port_payload_map` - A BTreeMap mapping port numbers to payload data
fn generate_code(port_payload_map: BTreeMap<Vec<u16>, Vec<u8>>) {
let dest_path = PathBuf::from("src/generated.rs");
let mut generated_code = String::new();
generated_code.push_str("use std::collections::BTreeMap;\n");
generated_code.push_str("use once_cell::sync::Lazy;\n\n");
generated_code.push_str("fn generated_data() -> BTreeMap<Vec<u16>, Vec<u8>> {\n");
generated_code.push_str(" let mut map = BTreeMap::new();\n");
for (ports, payloads) in port_payload_map {
generated_code.push_str(" map.insert(vec![");
generated_code.push_str(
&ports
.iter()
.map(|&p| p.to_string())
.collect::<Vec<_>>()
.join(","),
);
generated_code.push_str("], vec![");
generated_code.push_str(
&payloads
.iter()
.map(|&p| p.to_string())
.collect::<Vec<_>>()
.join(","),
);
generated_code.push_str("]);\n");
}
generated_code.push_str(" map\n");
generated_code.push_str("}\n\n");
generated_code.push_str(
"static PARSED_DATA: Lazy<BTreeMap<Vec<u16>, Vec<u8>>> = Lazy::new(generated_data);\n",
);
generated_code.push_str("pub fn get_parsed_data() -> &'static BTreeMap<Vec<u16>, Vec<u8>> {\n");
generated_code.push_str(" &PARSED_DATA\n");
generated_code.push_str("}\n");
fs::write(dest_path, generated_code).unwrap();
// format the generated code
Command::new("cargo")
.arg("fmt")
.arg("--all")
.output()
.expect("Failed to execute cargo fmt");
}
/// Creates a BTreeMap of line numbers mapped to a Vec<u16> of ports
///
/// # Arguments
///
/// * `fp_map` - A BTreeMap containing the parsed file data
///
/// # Returns
///
/// A BTreeMap where keys are line numbers and values are vectors of ports
fn ports_v(fp_map: &BTreeMap<i32, String>) -> BTreeMap<i32, Vec<u16>> {
let mut pb_linenr: BTreeMap<i32, Vec<u16>> = BTreeMap::new();
let mut port_list: Vec<u16> = Vec::new();
for (&line_nr, ports) in fp_map {
if ports.contains("udp ") {
let remain = &ports[4..];
let mut start = remain.split(' ');
let ports = start.next().unwrap();
let port_segments: Vec<&str> = ports.split(',').collect();
for segment in port_segments {
if segment.contains('-') {
let range: Vec<&str> = segment.trim().split('-').collect();
let start = range[0].parse::<u16>().unwrap();
let end = range[1].parse::<u16>().unwrap();
for port in start..end {
port_list.push(port);
}
} else if !segment.is_empty() {
match segment.parse::<u16>() {
Ok(port) => port_list.push(port),
Err(_) => println!("Error parsing port: {}", segment),
}
}
}
}
pb_linenr.insert(line_nr, port_list.clone());
port_list.clear();
}
pb_linenr
}
/// Parses out the Payloads into a BTreeMap of line numbers mapped to vectors of payload bytes
///
/// # Arguments
///
/// * `fp_map` - A BTreeMap containing the parsed file data
///
/// # Returns
///
/// A BTreeMap where keys are line numbers and values are vectors of payload bytes
fn payloads_v(fp_map: &BTreeMap<i32, String>) -> BTreeMap<i32, Vec<u8>> {
let mut payb_linenr: BTreeMap<i32, Vec<u8>> = BTreeMap::new();
for (&line_nr, data) in fp_map {
if data.contains('\"') {
let start = data.find('\"').expect("payload opening \" not found");
let payloads = &data[start + 1..];
payb_linenr.insert(line_nr, parser(payloads.trim()));
}
}
payb_linenr
}
/// Converts a hexadecimal string to a Vec<u8>
///
/// # Arguments
///
/// * `payload` - A string slice containing the hexadecimal payload
///
/// # Returns
///
/// A vector of bytes representing the decoded payload
fn parser(payload: &str) -> Vec<u8> {
let payload = payload.trim_matches('"');
let mut tmp_str = String::new();
let mut bytes: Vec<u8> = Vec::new();
for (idx, char) in payload.chars().enumerate() {
if char == '\\' && payload.chars().nth(idx + 1) == Some('x') {
continue;
} else if char.is_ascii_hexdigit() {
tmp_str.push(char);
if tmp_str.len() == 2 {
bytes.push(u8::from_str_radix(&tmp_str, 16).unwrap());
tmp_str.clear();
}
}
}
bytes
}
/// Combines the ports BTreeMap and the Payloads BTreeMap
///
/// # Arguments
///
/// * `pb_linenr` - A BTreeMap mapping line numbers to vectors of ports
/// * `payb_linenr` - A BTreeMap mapping line numbers to vectors of payload bytes
///
/// # Returns
///
/// A BTreeMap mapping vectors of ports to vectors of payload bytes
fn port_payload_map(
pb_linenr: BTreeMap<i32, Vec<u16>>,
payb_linenr: BTreeMap<i32, Vec<u8>>,
) -> BTreeMap<Vec<u16>, Vec<u8>> {
let mut ppm_fin: BTreeMap<Vec<u16>, Vec<u8>> = BTreeMap::new();
for (port_linenr, ports) in pb_linenr {
for (pay_linenr, payloads) in &payb_linenr {
if pay_linenr == &port_linenr {
ppm_fin.insert(ports.to_vec(), payloads.to_vec());
}
}
}
ppm_fin
}
+18
View File
@@ -0,0 +1,18 @@
test:
cargo nextest run
cargo clippy -- --deny warnings
cargo clippy --tests -- --deny warnings
cargo fmt --check
cargo doc --workspace --all-features --no-deps --document-private-items
fix:
cargo fmt
cargo clippy --fix
# release only runs if test runs
release: test
git checkout master
git pull
cargo generate-lockfile
cargo publish
git push
+500
View File
@@ -0,0 +1,500 @@
# Nmap nmap payload database -*- mode: fundamental; -*-
# $Id$
#
# These payloads are sent with every host discovery or port scan probe
# by default. This database should only include payloads that are
# unlikely to crash services, trip IDS alerts, or change state on the
# server. The idea behind these is to evoke a response using a payload.
# Some of them are taken from nmap-service-probes.
#
# This collection of data is (C) 1996-2022 by Nmap Software LLC. It
# is distributed under the Nmap Public Source license as provided in
# the LICENSE file of the source distribution or at
# https://nmap.org/npsl/. Note that this free license does not allow
# incorporation of Nmap or its data files within proprietary
# software. We sell a separate Nmap OEM for that as described
# (including pricing) at https://nmap.org/npsl/.
#
# Each entry begins with a protocol (only "udp" is supported) followed
# by a comma-separated list of ports, followed by one or more quoted
# strings containing the payload. These elements may be broken across
# several lines. For future expansion, additional keywords may follow
# the payload data. Any data following one of these keywords must be on
# the same line as the keyword so that unknown keywords can be ignored
# by the parser. Currently this file contains some entries with the
# "source" keyword to specify a desired source port, but it is not
# honored by Nmap.
#
# Multiple payloads may be defined for a single protocol and port, in
# which case they will be all be sent concurrently. There is a limit
# of 255 payloads per port.
#
# Lines longer than 1024 characters will be ignored.
#
# Example:
# udp 1234 "payloaddatapayloaddata"
# "payloaddatapayloaddata"
# source 5678
# GenericLines. Use for the echo service.
udp 7 "\x0D\x0A\x0D\x0A"
# DNSStatusRequest
# Sent for TFTP (69) as well due to its ability to provoke an error response
udp 53,69,5353,26198 "\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# DNS VER
udp 53,5353,26198
"\x77\x77\x01\x00\x00"
"\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03"
# DHCP INFORM
udp 67
"\x01\x01\x06\x00"
"\x01\x23\x45\x67\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x35\xd4\xd8\x51\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63\x35\x01"
"\x08\xff"
# TFTP GET
udp 69 "\x00\x01r7tftp.txt\x00octet\x00"
# QUIC packet with unsupported version Q999
# Also found on 443, but need to check whether DTLS or QUIC is more prevalent
udp 80 "\r12345678Q999\x00"
# RPCCheck
udp 111
"\x72\xFE\x1D\x13\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xA0"
"\x00\x01\x97\x7C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
# ONCRPC CALL
udp 111,2049,4045,32768-65535
"\x3e\xec\xe3\xca\x00\x00\x00\x00\x00\x00\x00\x02\x00"
"\xbc\x61\x4e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# NTPRequest
udp 123
"\xE3\x00\x04\xFA\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\xC5\x4F\x23\x4B\x71\xB1\x52\xF3"
# NTP REQ
udp 123
"\xd9\x00\x0a\xfa\x00\x00\x00"
"\x00\x00\x01\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6"
"\xf1\x5e\xdb\x78\x00\x00\x00"
# DCERPC CALL
udp 135,1025-1199
"\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00"
"\x00\x00\x01\x00\x00\x00\xb8\x10\xb8\x10\x00\x00\x00\x00\x01\x00\x00"
"\x00\x00\x00\x01\x00\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67"
"\x89\xab\xcd\xef\xe7\x03\x00\x00\xfe\xdc\xba\x98\x76\x54\x32\x10\x01"
"\x23\x45\x67\x89\xab\xcd\xef\xe7\x03\x00\x00"
# NBTStat
udp 137
"\x80\xF0\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00"
"\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01"
# CIFS NS NAME QUERY UC
udp 137
"\x01\x91\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01"
# CIFS NS NAME QUERY BC
udp 137
"\x01\x91\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00"
"\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01"
# SNMPv3GetRequest
udp 161,260,3401
"\x30\x3A\x02\x01\x03\x30\x0F\x02\x02\x4A\x69\x02\x03\x00\xFF\xE3"
"\x04\x01\x04\x02\x01\x03\x04\x10\x30\x0E\x04\x00\x02\x01\x00\x02"
"\x01\x00\x04\x00\x04\x00\x04\x00\x30\x12\x04\x00\x04\x00\xA0\x0C"
"\x02\x02\x37\xF0\x02\x01\x00\x02\x01\x00\x30\x00"
# SNMP PUBLIC WALK
udp 161,260,3401
"\x30\x1f\x02\x01\x00\x04\x06public\xa1\x12\x02\x01\x00\x02"
"\x01\x00\x02\x01\x00\x30\x07\x30\x05\x06\x01\x00\x05\x00"
# Sqlping - disabled because it trips a Snort rule with SID 2049
# ("MS-SQL ping attempt").
# udp 1434 "\x02"
# xdmcp - X Display Manager Control Protocol. Version 1, packet type
# Query (2), no authorization names. We expect a Willing or Unwilling
# packet in reply.
# http://cgit.freedesktop.org/xorg/doc/xorg-docs/plain/hardcopy/XDMCP/xdmcp.PS.gz
udp 177 "\x00\x01\x00\x02\x00\x01\x00"
# Connectionless LDAP - used by Microsoft Active Directory
udp 389
"\x30\x84\x00\x00\x00\x2d\x02\x01\x07\x63\x84\x00\x00\x00\x24\x04\x00"
"\x0a\x01\x00\x0a\x01\x00\x02\x01\x00\x02\x01\x64\x01\x01\x00\x87\x0b"
"objectClass0\x84\x00\x00\x00\x00"
# svrloc
udp 427
"\x02\x01\x00\x006 \x00\x00\x00\x00\x00\x01\x00\x02en\x00\x00\x00\x15"
"service:service-agent\x00\x07default\x00\x00\x00\x00"
# DTLS
udp 443,853,3391,4433,4740,5349,5684,5868,6514,6636,8232,10161,10162,12346,12446,12546,12646,12746,12846,12946,13046
# DTLS 1.0, length 52
"\x16\xfe\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x36"
# ClientHello, length 40, sequence 0, offset 0
"\x01\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00\x2a"
# DTLS 1.2
"\xfe\xfd"
# Random
"\x00\x00\x00\x00\x7c\x77\x40\x1e\x8a\xc8\x22\xa0\xa0\x18\xff\x93"
"\x08\xca\xac\x0a\x64\x2f\xc9\x22\x64\xbc\x08\xa8\x16\x89\x19\x3f"
# Session id length 0, cookie length 0
"\x00\x00"
# Cipher suites, mandatory TLS_RSA_WITH_AES_128_CBC_SHA
"\x00\x02\x00\x2f"
# Compressors (NULL)
"\x01\x00"
# Internet Key Exchange version 1, phase 1 Main Mode. We offer every
# combination of (DES, 3DES) and (MD5, SHA) in the hope that one of them will
# be acceptable. Because we use a fixed cookie, we set the association lifetime
# to 1 second to reduce the chance that repeated probes will look like
# retransmissions (and therefore not get a response). This payload comes from
# ike-scan --lifetime 1 --cookie 0011223344556677 --trans=5,2,1,2 --trans=5,1,1,2 --trans=1,2,1,2 --trans=1,1,1,2
# We expect another phase 1 message in response. This payload works better with
# a source port of 500 or a randomized initiator cookie.
udp 500
# Initiator cookie 0x0011223344556677, responder cookie 0x0000000000000000.
"\x00\x11\x22\x33\x44\x55\x66\x77\x00\x00\x00\x00\x00\x00\x00\x00"
# Version 1, Main Mode, flags 0x00, message ID 0x00000000, length 192.
"\x01\x10\x02\x00\x00\x00\x00\x00\x00\x00\x00\xC0"
# Security Association payload, length 164, IPSEC, IDENTITY.
"\x00\x00\x00\xA4\x00\x00\x00\x01\x00\x00\x00\x01"
# Proposal 1, length 152, ISAKMP, 4 transforms.
"\x00\x00\x00\x98\x01\x01\x00\x04"
# Transform 1, 3DES-CBC, SHA, PSK, group 2.
"\x03\x00\x00\x24\x01\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
# Transform 2, 3DES-CBC, MD5, PSK, group 2.
"\x03\x00\x00\x24\x02\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x01"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
# Transform 3, DES-CBC, SHA, PSK, group 2.
"\x03\x00\x00\x24\x03\x01\x00\x00\x80\x01\x00\x01\x80\x02\x00\x02"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
# Transform 4, DES-CBC, MD5, PSK, group 2.
"\x00\x00\x00\x24\x04\x01\x00\x00\x80\x01\x00\x01\x80\x02\x00\x01"
"\x80\x03\x00\x01\x80\x04\x00\x02"
"\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01"
# IPSEC START
udp 500,4500
"\x31\x27\xfc"
"\xb0\x38\x10\x9e\x89\x00\x00\x00\x00\x00\x00\x00\x00\x01\x10\x02\x00"
"\x00\x00\x00\x00\x00\x00\x00\xcc\x0d\x00\x00\x5c\x00\x00\x00\x01\x00"
"\x00\x00\x01\x00\x00\x00\x50\x01\x01\x00\x02\x03\x00\x00\x24\x01\x01"
"\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02\x80\x04\x00\x02\x80\x03\x00"
"\x03\x80\x0b\x00\x01\x00\x0c\x00\x04\x00\x00\x0e\x10\x00\x00\x00\x24"
"\x02\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x01\x80\x04\x00\x02\x80"
"\x03\x00\x03\x80\x0b\x00\x01\x00\x0c\x00\x04\x00\x00\x0e\x10\x0d\x00"
"\x00\x18\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4"
"\x61\x00\x00\x00\x04\x0d\x00\x00\x14\x40\x48\xb7\xd5\x6e\xbc\xe8\x85"
"\x25\xe7\xde\x7f\x00\xd6\xc2\xd3\x0d\x00\x00\x14\x90\xcb\x80\x91\x3e"
"\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f\x00\x00\x00\x14\x26\x24"
"\x4d\x38\xed\xdb\x61\xb3\x17\x2a\x36\xe3\xd0\xcf\xb8\x19"
# Routing Information Protocol version 1. Special-case request for the entire
# routing table (address family 0, address 0.0.0.0, metric 16). RFC 1058,
# section 3.4.1.
udp 520
"\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x10"
# RMCP ASF ping
udp 623
"\x06\x00\xff\x06" # RMCP version 6, sequence 0xff, normal RMCP class ASF
"\x00\x00\x11\xbe" # IAN ASF code 4542
"\x80\x00\x00\x00" # payload-less ASF presence ping
# IPMI
# RMCP Get Channel Auth Capabilities
udp 623
"\x06\x00\xff\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x20\x18"
"\xc8\x81\x00\x38\x8e\x04\xb5"
# serialnumberd. This service runs on Mac OS X Server. This probe
# requests the serial number of another server. In response we expect a
# packet starting with "SNRESPS:", followed by some data whose purpose
# is not known.
udp 626 "SNQUERY: 127.0.0.1:AAAAAA:xsvr"
# OpenVPN P_CONTROL_HARD_RESET_CLIENT_V2
# Byte 0; 0x38 opcode
# Byte 1-8: Session ID, random
# Byte 9: Message packet-id array length (0)
# Byte 10-13: Message packet-id (0)
udp 1194 "8d\xc1x\x01\xb8\x9b\xcb\x8f\0\0\0\0\0"
# OpenVPN when in PKI mode and without the "HMAC Firewall" setting enabled
# (tls-auth) should respond to the following probe, which is
# 0x38<8 random bytes><4 null bytes>
udp 1194
"\x38\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00\x00\x00"
# Citrix MetaFrame application browser service
# Original idea from http://sh0dan.org/oldfiles/hackingcitrix.html
# Payload contents copied from Wireshark capture of Citrix Program
# Neighborhood client application. The application uses this payload to
# locate Citrix servers on the local network. Response to this probe is
# a 48 byte UDP payload as shown here:
#
# 0000 30 00 02 31 02 fd a8 e3 02 00 06 44 c0 a8 80 55
# 0010 00 00 00 00 00 00 00 00 00 00 00 00 02 00 06 44
# 0020 c0 a8 80 56 00 00 00 00 00 00 00 00 00 00 00 00
#
# The first 12 bytes appear to be the same in all responses.
#
# Bytes 0x00 appears to be a packet length field
# Bytes 0x0C - 0x0F are the IP address of the server
# Bytes 0x10 - 0x13 may vary, 0x14 - 0x1F do not appear to
# Bytes 0x20 - 0x23 are the IP address of the primary system in a server farm
# configuration
# Bytes 0x24 - 0x27 can vary, 0x28 - 0x2F do not appear to
udp 1604
"\x1e\x00\x01\x30\x02\xfd\xa8\xe3\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# RADIUS Access-Request. This is a degenerate packet with no username or
# password; we expect an Access-Reject in response. The Identifier and Request
# Authenticator are both 0. It was generated by running
# echo 'User-Password = ""' | radclient <ip> auth ""
# and then manually stripping out the password.
#
# Section 2 of the RFC says "A request from a client for which the
# RADIUS server does not have a shared secret MUST be silently
# discarded." So this payload only works when the server is configured
# (or misconfigured) to know the scanning machine as a client.
#
# RFC 2865: "The early deployment of RADIUS was done using UDP port
# number 1645, which conflicts with the "datametrics" service. The
# officially assigned port number for RADIUS is 1812.
udp 1645,1812
"\x01\x00\x00\x14"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# L2TP ICRQ
udp 1701
"\xc8\x02"
"\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x80\x08\x00\x00\x00\x00\x00"
"\x01\x80\x08\x00\x00\x00\x02\x01\x00\x80\x0e\x00\x00\x00\x07"
"nxp-scan\x80\x0a\x00\x00\x00\x03\x00\x00\x00\x03\x80"
"\x08\x00\x00\x00\x09\x00\x00"
# UPNP MSEARCH
udp 1900
"M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\n"
"Man: \"ssdp:discover\"\r\nMX: 5\r\nST: ssdp:all\r\n\r\n"
# NFS version 2, RFC 1831. XID 0x00000000, program 100003 (NFS), procedure
# NFSPROC_NULL (does nothing, see section 2.2.1), null authentication (see
# section 9.1).
udp 2049
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xA3"
"\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"
# GPRS Tunneling Protocol (GTP)
udp 2123,2152
# GTPv1, protocol 1
"\x32"
# EchoRequest
"\x01"
# message length
"\x00\x04"
# Tunnel endpoint identifier
"\x00\x00\x42\x00"
# sequence number
"\x13\x37"
# N-PDU number
"\x00"
# next extension header type
"\x00"
# GPRS Tunneling Protocol (GTP) "prime" v2
# This same packet can be used for GTP v2 on ports 2123 and 2152 if you change
# the first byte from \x4e to \x40
udp 3386
# GTP'v2
"\x4e"
# EchoRequest
"\x01"
# message length
"\x00\x04"
# sequence number
"\xde\xfe\xc8\x00"
# Freelancer game server status query
# http://sourceforge.net/projects/gameq/
# (relevant files: games.ini, packets.ini, freelancer.php)
udp 2302 "\x00\x02\xf1\x26\x01\x26\xf0\x90\xa6\xf0\x26\x57\x4e\xac\xa0\xec\xf8\x68\xe4\x8d\x21"
# Apple Remote Desktop (ARD)
udp 3283 "\0\x14\0\x01\x03"
# STUN Binding request, see RFC 5389 Section 6
# message type = 0x001, Binding (see Section 18.1)
# message length = 0
# magic cookie = 0x2112a442
# transaction ID = "\x00"*12
udp 3478 "\x00\x01\x00\x00\x21\x12\xa4\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# Sun Service Tag Discovery protocol (stdiscover)
# http://arc.opensolaris.org/caselog/PSARC/2006/638/stdiscover_protocolv2.pdf
# Would work better with a varying cookie; the second and later sends of this
# probe will be interpreted as resends by the server and will be ignored.
udp 6481 "[PROBE] 0000"
# NAT-PMP external IP address request. See section 3.2 of
# http://files.dns-sd.org/draft-cheshire-nat-pmp.txt.
udp 5351 "\x00\x00"
# DNS Service Discovery (DNS-SD) service query, as used in Zeroconf.
# Transaction ID 0x0000, flags 0x0000, 1 question: PTR query for
# _services._dns-sd._udp.local. If the remote host supports DNS-SD it will send
# back a list of all its services. This is the same as a packet capture of
# dns-sd -B _services._dns-sd._udp .
# See section 9 of
# http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt.
# This first probe is a QU probe, meaning a unicast response is desired
udp 5353
"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x09_services\x07_dns-sd\x04_udp\x05local\x00\x00\x0C\x80\x01"
# This second probe is a QM probe, meaning a unicast response is desired
udp 5353
"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
"\x09_services\x07_dns-sd\x04_udp\x05local\x00\x00\x0C\x00\x01"
# PCANY STATUS
udp 5632 "ST"
# CoAP GET .well-known/core
udp 5683 "@\x01\x01\xce\xbb.well-known\x04core"
# UT2K PING
udp 7777 "None\x00"
# Ubiquiti Discovery Service - v1
udp 10001 "\x01\x00\x00\x00"
# Amanda backup service noop request. I think that this does nothing on the
# server but only asks it to send back its feature list. In reply we expect an
# ACK or (more likely) an ERROR. I couldn't find good online documentation of
# the Amanda network protocol. There is parsing code in the Amanda source at
# common-src/security-util.c. This is based on a packet capture of
# amcheck <config> <host>
udp 10080
"Amanda 2.6 REQ HANDLE 000-00000000 SEQ 0\n"
"SERVICE noop\n"
# VxWorks Wind River Debugger
udp 17185
# Random XID
"\x00\x00\x00\x00"
# RPC version 2 procedure call
"\x00\x00\x00\x00\x00\x00\x00\x02"
# WDB version 1
"\x55\x55\x55\x55\x00\x00\x00\x01"
# WDB_TARGET_PING
"\x00\x00\x00\x00"
# RPC Auth NULL
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# Checksum
"\xff\xff\x55\x13"
# WDB wrapper (length and sequence number)
"\x00\x00\x00\x30\x00\x00\x00\x01"
# Empty data?
"\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00"
# VXWORKS DEBUG (alternative?)
udp 17185
"\x72\x37\x72\x37\x00\x00\x00"
"\x00\x00\x00\x00\x02\x55\x55\x55\x55\x00\x00\x00\x01\x00\x00\x00\x01"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff"
"\xff\x55\x10\x00\x00\x00\x3c\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00"
"\x00\x00\x00\x00\x00\x00"
# Quake 2 and Quake 3 game servers (and servers of derived games like Nexuiz).
# Gets game information from the server (see probe responses in
# nmap-service-probes). These services typically run on a base port or a
# few numbers higher.
# Quake 2. Typical ports: 27910-27914.
udp 27910-27914 "\xff\xff\xff\xffstatus"
# Quake 3. Typical ports:
# 26000-26004: Nexuiz
# 27960-27964: Various games
# 30720-30724: Tremulous
# 44400: Warsow
udp 26000-26004,27960-27964,30720-30724,44400 "\xff\xff\xff\xffgetstatus"
# Murmur 1.2.X (Mumble server)
# UDP ping. "abcdefgh" is an identifier. See
# http://mumble.sourceforge.net/Protocol.
udp 64738 "\x00\x00\x00\x00abcdefgh"
# Ventrilo 2.1.2+
# UDP general status request (encrypted).
# See http://aluigi.altervista.org/papers.htm#ventrilo
udp 3784
"\x01\xe7\xe5\x75\x31\xa3\x17\x0b\x21\xcf\xbf\x2b\x99\x4e\xdd\x19\xac\xde\x08\x5f\x8b\x24\x0a\x11\x19\xb6\x73\x6f\xad\x28\x13\xd2\x0a\xb9\x12\x75"
# Kademlia (kad) as used by various P2P applications. Send a Kademlia ping
# 4665, 4666, 4672, 6429: eDonkey/eMule and variants
udp 4665,4666,4672,6429 "\xE4\x60"
# TeamSpeak 2
# UDP login request
# See http://wiki.wireshark.org/TeamSpeak2
udp 8767
"\xf4\xbe\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x002x\xba\x85\tTeamSpeak\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nWindows XP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00 \x00<\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08nickname\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# TS3INIT1
udp 9987
"TS3INIT1\x00\x65\x00\x00\x88\x0a\x39\x7b\x0f\x00\x5b\x55\x72\xef\xdc\x78\x32\x6b\x00\x00\x00\x00\x00\x00\x00\x00"
# TeamSpeak 3
# UDP login request (encrypted)
# http://seclists.org/nmap-dev/2013/q3/72
udp 9987
"\x05\xca\x7f\x16\x9c\x11\xf9\x89\x00\x00\x00\x00\x02\x9d\x74\x8b\x45\xaa\x7b\xef\xb9\x9e\xfe\xad\x08\x19\xba\xcf\x41\xe0\x16\xa2\x32\x6c\xf3\xcf\xf4\x8e\x3c\x44\x83\xc8\x8d\x51\x45\x6f\x90\x95\x23\x3e\x00\x97\x2b\x1c\x71\xb2\x4e\xc0\x61\xf1\xd7\x6f\xc5\x7e\xf6\x48\x52\xbf\x82\x6a\xa2\x3b\x65\xaa\x18\x7a\x17\x38\xc3\x81\x27\xc3\x47\xfc\xa7\x35\xba\xfc\x0f\x9d\x9d\x72\x24\x9d\xfc\x02\x17\x6d\x6b\xb1\x2d\x72\xc6\xe3\x17\x1c\x95\xd9\x69\x99\x57\xce\xdd\xdf\x05\xdc\x03\x94\x56\x04\x3a\x14\xe5\xad\x9a\x2b\x14\x30\x3a\x23\xa3\x25\xad\xe8\xe6\x39\x8a\x85\x2a\xc6\xdf\xe5\x5d\x2d\xa0\x2f\x5d\x9c\xd7\x2b\x24\xfb\xb0\x9c\xc2\xba\x89\xb4\x1b\x17\xa2\xb6"
# Memcached
# version request (shorter response than stats)
# https://github.com/memcached/memcached/blob/master/doc/protocol.txt
udp 11211
"\0\x01\0\0\0\x01\0\0version\r\n"
# Steam, typically using a port in 27015-27030. Send a "Source Engine query"
udp 27015-27030
"\xff\xff\xff\xffTSource Engine Query\x00"
# TRIN00 UNIX PING
udp 27444 "png l44adsl"
# BO PING
udp 31337
"\xce\x63\xd1\xd2\x16\xe7\x13\xcf\x38"
"\xa5\xa5\x86\xb2\x75\x4b\x99\xaa\x32\x58"
# TRIN00 WIN PING
udp 34555 "png []..Ks"
# Beckhoff ADS discovery request
# https://github.com/ONE75/adsclient/blob/master/src/AdsClient.Finder/DeviceFinder.cs#L49-L64
udp 48899
"\x03\x66\x14\x71\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x01\x10\x27\x00\x00\x00\x00"
+129 -17
View File
@@ -1,4 +1,5 @@
//! Provides functions to parse input IP addresses, CIDRs or files.
use std::collections::BTreeSet;
use std::fs::{self, File};
use std::io::{prelude::*, BufReader};
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
@@ -27,6 +28,8 @@ use crate::warning;
///
/// let ips = parse_addresses(&opts);
/// ```
///
/// Finally, any duplicates are removed to avoid excessive scans.
pub fn parse_addresses(input: &Opts) -> Vec<IpAddr> {
let mut ips: Vec<IpAddr> = Vec::new();
let mut unresolved_addresses: Vec<&str> = Vec::new();
@@ -66,6 +69,18 @@ pub fn parse_addresses(input: &Opts) -> Vec<IpAddr> {
}
}
// Finally, craft a list of addresses to be excluded from the scan.
let mut excluded_ips: BTreeSet<IpAddr> = BTreeSet::new();
if let Some(exclude_addresses) = &input.exclude_addresses {
for addr in exclude_addresses {
excluded_ips.extend(parse_address(addr, &backup_resolver));
}
}
// Remove duplicated/excluded IPs.
let mut seen = BTreeSet::new();
ips.retain(|ip| seen.insert(*ip) && !excluded_ips.contains(ip));
ips
}
@@ -87,7 +102,7 @@ pub fn parse_address(address: &str, resolver: &Resolver) -> Vec<IpAddr> {
.map(|cidr| cidr.iter().map(|c| c.address()).collect())
.ok()
.or_else(|| {
format!("{}:{}", &address, 80)
format!("{}:80", &address)
.to_socket_addrs()
.ok()
.map(|mut iter| vec![iter.next().unwrap().ip()])
@@ -187,8 +202,11 @@ mod tests {
#[test]
fn parse_correct_addresses() {
let mut opts = Opts::default();
opts.addresses = vec!["127.0.0.1".to_owned(), "192.168.0.0/30".to_owned()];
let opts = Opts {
addresses: vec!["127.0.0.1".to_owned(), "192.168.0.0/30".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(
@@ -203,10 +221,71 @@ mod tests {
);
}
#[test]
fn parse_addresses_with_address_exclusions() {
let opts = Opts {
addresses: vec!["192.168.0.0/30".to_owned()],
exclude_addresses: Some(vec!["192.168.0.1".to_owned()]),
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(
ips,
[
Ipv4Addr::new(192, 168, 0, 0),
Ipv4Addr::new(192, 168, 0, 2),
Ipv4Addr::new(192, 168, 0, 3)
]
);
}
#[test]
fn parse_addresses_with_cidr_exclusions() {
let opts = Opts {
addresses: vec!["192.168.0.0/29".to_owned()],
exclude_addresses: Some(vec!["192.168.0.0/30".to_owned()]),
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(
ips,
[
Ipv4Addr::new(192, 168, 0, 4),
Ipv4Addr::new(192, 168, 0, 5),
Ipv4Addr::new(192, 168, 0, 6),
Ipv4Addr::new(192, 168, 0, 7),
]
);
}
#[test]
fn parse_addresses_with_incorrect_address_exclusions() {
let opts = Opts {
addresses: vec!["192.168.0.0/30".to_owned()],
exclude_addresses: Some(vec!["192.168.0.1".to_owned()]),
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(
ips,
[
Ipv4Addr::new(192, 168, 0, 0),
Ipv4Addr::new(192, 168, 0, 2),
Ipv4Addr::new(192, 168, 0, 3)
]
);
}
#[test]
fn parse_correct_host_addresses() {
let mut opts = Opts::default();
opts.addresses = vec!["google.com".to_owned()];
let opts = Opts {
addresses: vec!["google.com".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(ips.len(), 1);
@@ -214,8 +293,11 @@ mod tests {
#[test]
fn parse_correct_and_incorrect_addresses() {
let mut opts = Opts::default();
opts.addresses = vec!["127.0.0.1".to_owned(), "im_wrong".to_owned()];
let opts = Opts {
addresses: vec!["127.0.0.1".to_owned(), "im_wrong".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(ips, [Ipv4Addr::new(127, 0, 0, 1),]);
@@ -223,39 +305,67 @@ mod tests {
#[test]
fn parse_incorrect_addresses() {
let mut opts = Opts::default();
opts.addresses = vec!["im_wrong".to_owned(), "300.10.1.1".to_owned()];
let opts = Opts {
addresses: vec!["im_wrong".to_owned(), "300.10.1.1".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert!(ips.is_empty());
}
#[test]
fn parse_hosts_file_and_incorrect_hosts() {
// Host file contains IP, Hosts, incorrect IPs, incorrect hosts
let mut opts = Opts::default();
opts.addresses = vec!["fixtures/hosts.txt".to_owned()];
let opts = Opts {
addresses: vec!["fixtures/hosts.txt".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(ips.len(), 3);
}
#[test]
fn parse_empty_hosts_file() {
// Host file contains IP, Hosts, incorrect IPs, incorrect hosts
let mut opts = Opts::default();
opts.addresses = vec!["fixtures/empty_hosts.txt".to_owned()];
let opts = Opts {
addresses: vec!["fixtures/empty_hosts.txt".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(ips.len(), 0);
}
#[test]
fn parse_naughty_host_file() {
// Host file contains IP, Hosts, incorrect IPs, incorrect hosts
let mut opts = Opts::default();
opts.addresses = vec!["fixtures/naughty_string.txt".to_owned()];
let opts = Opts {
addresses: vec!["fixtures/naughty_string.txt".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(ips.len(), 0);
}
#[test]
fn parse_duplicate_cidrs() {
let opts = Opts {
addresses: vec!["79.98.104.0/21".to_owned(), "79.98.104.0/24".to_owned()],
..Default::default()
};
let ips = parse_addresses(&opts);
assert_eq!(ips.len(), 2_048);
}
#[test]
fn resolver_default_cloudflare() {
let opts = Opts::default();
@@ -269,9 +379,11 @@ mod tests {
#[test]
fn resolver_args_google_dns() {
let mut opts = Opts::default();
// https://developers.google.com/speed/public-dns
opts.resolver = Some("8.8.8.8,8.8.4.4".to_owned());
let opts = Opts {
resolver: Some("8.8.8.8,8.8.4.4".to_owned()),
..Default::default()
};
let resolver = get_resolver(&opts.resolver);
let lookup = resolver.lookup_ip("www.example.com.").unwrap();
+15 -2
View File
@@ -89,6 +89,10 @@ pub struct Opts {
#[arg(short, long)]
pub no_config: bool,
/// Hide the banner
#[arg(long)]
pub no_banner: bool,
/// Custom path to config file
#[arg(short, long, value_parser)]
pub config_path: Option<PathBuf>,
@@ -151,6 +155,10 @@ pub struct Opts {
#[arg(short, long, value_delimiter = ',')]
pub exclude_ports: Option<Vec<u16>>,
/// A list of comma separated CIDRs, IPs, or hosts to be excluded from scanning.
#[arg(short = 'x', long = "exclude-addresses", value_delimiter = ',')]
pub exclude_addresses: Option<Vec<String>>,
/// UDP scanning mode, finds UDP ports that send back responses
#[arg(long)]
pub udp: bool,
@@ -217,7 +225,7 @@ impl Opts {
self.ports = Some(ports);
}
merge_optional!(range, resolver, ulimit, exclude_ports);
merge_optional!(range, resolver, ulimit, exclude_ports, exclude_addresses);
}
}
@@ -237,10 +245,12 @@ impl Default for Opts {
resolver: None,
scan_order: ScanOrder::Serial,
no_config: true,
no_banner: false,
top: false,
scripts: ScriptsRequired::Default,
config_path: None,
exclude_ports: None,
exclude_addresses: None,
udp: false,
}
}
@@ -266,11 +276,13 @@ pub struct Config {
command: Option<Vec<String>>,
scripts: Option<ScriptsRequired>,
exclude_ports: Option<Vec<u16>>,
exclude_addresses: Option<Vec<String>>,
udp: Option<bool>,
}
#[cfg(not(tarpaulin_include))]
#[allow(clippy::doc_link_with_quotes)]
#[allow(clippy::manual_unwrap_or_default)]
impl Config {
/// Reads the configuration file with TOML format and parses it into a
/// Config struct.
@@ -280,7 +292,7 @@ impl Config {
/// addresses = ["127.0.0.1", "127.0.0.1"]
/// ports = [80, 443, 8080]
/// greppable = true
/// scan_order: "Serial"
/// scan_order = "Serial"
/// exclude_ports = [8080, 9090, 80]
/// udp = false
///
@@ -339,6 +351,7 @@ mod tests {
scan_order: Some(ScanOrder::Random),
scripts: None,
exclude_ports: None,
exclude_addresses: None,
udp: Some(false),
}
}
+11 -11
View File
@@ -21,17 +21,17 @@
//! start: 1,
//! end: 1_000,
//! };
//! let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
//! let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random); // can be serial, random or manual https://github.com/RustScan/RustScan/blob/master/src/port_strategy/mod.rs
//! let scanner = Scanner::new(
//! &addrs,
//! 10,
//! Duration::from_millis(100),
//! 1,
//! true,
//! strategy,
//! true,
//! vec![9000],
//! false,
//! &addrs, // the addresses to scan
//! 10, // batch_size is how many ports at a time should be scanned
//! Duration::from_millis(100), //T imeout is the time RustScan should wait before declaring a port closed. As datatype Duration.
//! 1, // Tries, how many retries should RustScan do?
//! true, // greppable is whether or not RustScan should print things, or wait until the end to print only the ip
//! strategy, // the port strategy used
//! true, // accessible, should the output be A11Y compliant?
//! vec![9000], // What ports should RustScan exclude?
//! false, // is this a UDP scan?
//! );
//!
//! let scan_result = block_on(scanner.run());
@@ -55,4 +55,4 @@ pub mod scripts;
pub mod address;
pub mod udp_packets;
pub mod generated;
+41 -36
View File
@@ -35,6 +35,9 @@ extern crate log;
/// Faster Nmap scanning with Rust
/// If you're looking for the actual scanning, check out the module Scanner
fn main() {
#[cfg(not(unix))]
let _ = ansi_term::enable_ansi_support();
env_logger::init();
let mut benchmarks = Benchmark::init();
let mut rustscan_bench = NamedTimer::start("RustScan");
@@ -45,7 +48,7 @@ fn main() {
debug!("Main() `opts` arguments are {:?}", opts);
let scripts_to_run: Vec<ScriptFile> = match init_scripts(opts.scripts) {
let scripts_to_run: Vec<ScriptFile> = match init_scripts(&opts.scripts) {
Ok(scripts_to_run) => scripts_to_run,
Err(e) => {
warning!(
@@ -59,7 +62,7 @@ fn main() {
debug!("Scripts initialized {:?}", &scripts_to_run);
if !opts.greppable && !opts.accessible {
if !opts.greppable && !opts.accessible && !opts.no_banner {
print_opening(&opts);
}
@@ -80,11 +83,6 @@ fn main() {
#[cfg(not(unix))]
let batch_size: u16 = AVERAGE_BATCH_SIZE;
// Added by wasuaje - 01/26/2024:
// exclude_ports is an exclusion port list
//
// Added by brendanglancy - 5/19/2024:
// udp is an option to do a udp scan
let scanner = Scanner::new(
&ips,
batch_size,
@@ -197,22 +195,17 @@ fn main() {
#[allow(clippy::items_after_statements, clippy::needless_raw_string_hashes)]
fn print_opening(opts: &Opts) {
debug!("Printing opening");
let s = format!(
"{}\n{}\n{}\n{}\n{}",
r#".----. .-. .-. .----..---. .----. .---. .--. .-. .-."#,
r#"| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |"#,
r#"| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |"#,
r#"`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'"#,
r#"The Modern Day Port Scanner."#
);
let s = r#".----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner."#;
println!("{}", s.gradient(Color::Green).bold());
let info = format!(
"{}\n{}\n{}\n{}",
r#"________________________________________"#,
r#": http://discord.skerritt.blog :"#,
r#": https://github.com/RustScan/RustScan :"#,
r#" --------------------------------------"#
);
let info = r#"________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------"#;
println!("{}", info.gradient(Color::Yellow).bold());
funny_opening!();
@@ -302,8 +295,10 @@ mod tests {
#[test]
#[cfg(unix)]
fn batch_size_lowered() {
let mut opts = Opts::default();
opts.batch_size = 50_000;
let opts = Opts {
batch_size: 50_000,
..Default::default()
};
let batch_size = infer_batch_size(&opts, 120);
assert!(batch_size < opts.batch_size);
@@ -312,8 +307,10 @@ mod tests {
#[test]
#[cfg(unix)]
fn batch_size_lowered_average_size() {
let mut opts = Opts::default();
opts.batch_size = 50_000;
let opts = Opts {
batch_size: 50_000,
..Default::default()
};
let batch_size = infer_batch_size(&opts, 9_000);
assert!(batch_size == 3_000);
@@ -323,8 +320,10 @@ mod tests {
fn batch_size_equals_ulimit_lowered() {
// because ulimit and batch size are same size, batch size is lowered
// to ULIMIT - 100
let mut opts = Opts::default();
opts.batch_size = 50_000;
let opts = Opts {
batch_size: 50_000,
..Default::default()
};
let batch_size = infer_batch_size(&opts, 5_000);
assert!(batch_size == 4_900);
@@ -333,9 +332,11 @@ mod tests {
#[cfg(unix)]
fn batch_size_adjusted_2000() {
// ulimit == batch_size
let mut opts = Opts::default();
opts.batch_size = 50_000;
opts.ulimit = Some(2_000);
let opts = Opts {
batch_size: 50_000,
ulimit: Some(2_000),
..Default::default()
};
let batch_size = adjust_ulimit_size(&opts);
assert!(batch_size == 2_000);
@@ -344,9 +345,11 @@ mod tests {
#[test]
#[cfg(unix)]
fn test_high_ulimit_no_greppable_mode() {
let mut opts = Opts::default();
opts.batch_size = 10;
opts.greppable = false;
let opts = Opts {
batch_size: 10,
greppable: false,
..Default::default()
};
let batch_size = infer_batch_size(&opts, 1_000_000);
@@ -355,8 +358,10 @@ mod tests {
#[test]
fn test_print_opening_no_panic() {
let mut opts = Opts::default();
opts.ulimit = Some(2_000);
let opts = Opts {
ulimit: Some(2_000),
..Default::default()
};
// print opening should not panic
print_opening(&opts);
}
+5 -5
View File
@@ -1,8 +1,8 @@
//! Provides a means to hold configuration options specifically for port scanning.
mod range_iterator;
use crate::input::{PortRange, ScanOrder};
use rand::rng;
use rand::seq::SliceRandom;
use rand::thread_rng;
use range_iterator::RangeIterator;
/// Represents options of port scanning.
@@ -35,7 +35,7 @@ impl PortStrategy {
}
ScanOrder::Serial => PortStrategy::Manual(ports.unwrap()),
ScanOrder::Random => {
let mut rng = thread_rng();
let mut rng = rng();
let mut ports = ports.unwrap();
ports.shuffle(&mut rng);
PortStrategy::Manual(ports)
@@ -105,7 +105,7 @@ mod tests {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Serial);
let result = strategy.order();
let expected_range = (1..=100).into_iter().collect::<Vec<u16>>();
let expected_range = (1..=100).collect::<Vec<u16>>();
assert_eq!(expected_range, result);
}
#[test]
@@ -113,7 +113,7 @@ mod tests {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let mut result = strategy.order();
let expected_range = (1..=100).into_iter().collect::<Vec<u16>>();
let expected_range = (1..=100).collect::<Vec<u16>>();
assert_ne!(expected_range, result);
result.sort_unstable();
@@ -131,7 +131,7 @@ mod tests {
fn random_strategy_with_ports() {
let strategy = PortStrategy::pick(&None, Some((1..10).collect()), ScanOrder::Random);
let mut result = strategy.order();
let expected_range = (1..10).into_iter().collect::<Vec<u16>>();
let expected_range = (1..10).collect::<Vec<u16>>();
assert_ne!(expected_range, result);
result.sort_unstable();
+10 -10
View File
@@ -27,8 +27,8 @@ impl RangeIterator {
// Randomly choose a number within the range to be the first
// and assign it as a pick.
let mut rng = rand::thread_rng();
let normalized_first_pick = rng.gen_range(0..normalized_end);
let mut rng = rand::rng();
let normalized_first_pick = rng.random_range(0..normalized_end);
Self {
active: true,
@@ -83,14 +83,14 @@ fn pick_random_coprime(end: u32) -> u32 {
let range_boundary = end / 4;
let lower_range = range_boundary;
let upper_range = end - range_boundary;
let mut rng = rand::thread_rng();
let mut candidate = rng.gen_range(lower_range..upper_range);
let mut rng = rand::rng();
let mut candidate = rng.random_range(lower_range..upper_range);
for _ in 0..10 {
if end.gcd(candidate) == 1 {
return candidate;
}
candidate = rng.gen_range(lower_range..upper_range);
candidate = rng.random_range(lower_range..upper_range);
}
end - 1
@@ -103,23 +103,23 @@ mod tests {
#[test]
fn range_iterator_iterates_through_the_entire_range() {
let result = generate_sorted_range(1, 10);
let expected_range = (1..=10).into_iter().collect::<Vec<u16>>();
let expected_range = (1..=10).collect::<Vec<u16>>();
assert_eq!(expected_range, result);
let result = generate_sorted_range(1, 100);
let expected_range = (1..=100).into_iter().collect::<Vec<u16>>();
let expected_range = (1..=100).collect::<Vec<u16>>();
assert_eq!(expected_range, result);
let result = generate_sorted_range(1, 1000);
let expected_range = (1..=1000).into_iter().collect::<Vec<u16>>();
let expected_range = (1..=1000).collect::<Vec<u16>>();
assert_eq!(expected_range, result);
let result = generate_sorted_range(1, 65_535);
let expected_range = (1..=65_535).into_iter().collect::<Vec<u16>>();
let expected_range = (1..=65_535).collect::<Vec<u16>>();
assert_eq!(expected_range, result);
let result = generate_sorted_range(1000, 2000);
let expected_range = (1000..=2000).into_iter().collect::<Vec<u16>>();
let expected_range = (1000..=2000).collect::<Vec<u16>>();
assert_eq!(expected_range, result);
}
+39 -20
View File
@@ -1,6 +1,6 @@
//! Core functionality for actual scanning behaviour.
use crate::generated::get_parsed_data;
use crate::port_strategy::PortStrategy;
use crate::udp_packets::udp_payload::cust_payload;
use log::debug;
mod socket_iterator;
@@ -11,6 +11,7 @@ use async_std::prelude::*;
use async_std::{io, net::UdpSocket};
use colored::Colorize;
use futures::stream::FuturesUnordered;
use std::collections::BTreeMap;
use std::{
collections::HashSet,
net::{IpAddr, Shutdown, SocketAddr},
@@ -24,8 +25,6 @@ use std::{
/// batch_size is how many ports at a time should be scanned
/// Timeout is the time RustScan should wait before declaring a port closed. As datatype Duration.
/// greppable is whether or not RustScan should print things, or wait until the end to print only the ip and open ports.
/// Added by wasuaje - 01/26/2024:
/// exclude_ports is an exclusion port list
#[cfg(not(tarpaulin_include))]
#[derive(Debug)]
pub struct Scanner {
@@ -70,8 +69,6 @@ impl Scanner {
/// Runs scan_range with chunk sizes
/// If you want to run RustScan normally, this is the entry point used
/// Returns all open ports as `Vec<u16>`
/// Added by wasuaje - 01/26/2024:
/// Filtering port against exclude port list
pub async fn run(&self) -> Vec<SocketAddr> {
let ports: Vec<u16> = self
.port_strategy
@@ -84,10 +81,11 @@ impl Scanner {
let mut open_sockets: Vec<SocketAddr> = Vec::new();
let mut ftrs = FuturesUnordered::new();
let mut errors: HashSet<String> = HashSet::new();
let udp_map = get_parsed_data();
for _ in 0..self.batch_size {
if let Some(socket) = socket_iterator.next() {
ftrs.push(self.scan_socket(socket));
ftrs.push(self.scan_socket(socket, udp_map.clone()));
} else {
break;
}
@@ -101,7 +99,7 @@ impl Scanner {
while let Some(result) = ftrs.next().await {
if let Some(socket) = socket_iterator.next() {
ftrs.push(self.scan_socket(socket));
ftrs.push(self.scan_socket(socket, udp_map.clone()));
}
match result {
@@ -133,19 +131,13 @@ impl Scanner {
/// ```
///
/// Note: `self` must contain `self.ip`.
async fn scan_socket(&self, socket: SocketAddr) -> io::Result<SocketAddr> {
async fn scan_socket(
&self,
socket: SocketAddr,
udp_map: BTreeMap<Vec<u16>, Vec<u8>>,
) -> io::Result<SocketAddr> {
if self.udp {
let payload = cust_payload(socket.port());
let tries = self.tries.get();
for _ in 1..=tries {
match self.udp_scan(socket, &payload, self.timeout).await {
Ok(true) => return Ok(socket),
Ok(false) => continue,
Err(e) => return Err(e),
}
}
return Ok(socket);
return self.scan_udp_socket(socket, udp_map).await;
}
let tries = self.tries.get();
@@ -180,6 +172,33 @@ impl Scanner {
unreachable!();
}
async fn scan_udp_socket(
&self,
socket: SocketAddr,
udp_map: BTreeMap<Vec<u16>, Vec<u8>>,
) -> io::Result<SocketAddr> {
let mut payload: Vec<u8> = Vec::new();
for (key, value) in udp_map {
if key.contains(&socket.port()) {
payload = value;
}
}
let tries = self.tries.get();
for _ in 1..=tries {
match self.udp_scan(socket, &payload, self.timeout).await {
Ok(true) => return Ok(socket),
Ok(false) => continue,
Err(e) => return Err(e),
}
}
Err(io::Error::new(
io::ErrorKind::Other,
format!("UDP scan timed-out for all tries on socket {}", socket),
))
}
/// Performs the connection to the socket with timeout
/// # Example
///
@@ -203,7 +222,7 @@ impl Scanner {
Ok(stream)
}
/// Binds to a UDP socket so we can send and recieve packets
/// Binds to a UDP socket so we can send and receive packets
/// # Example
///
/// ```compile_fail
+1 -1
View File
@@ -30,7 +30,7 @@ impl<'s> SocketIterator<'s> {
}
#[allow(clippy::doc_link_with_quotes)]
impl<'s> Iterator for SocketIterator<'s> {
impl Iterator for SocketIterator<'_> {
type Item = SocketAddr;
/// Returns a socket based on the combination of one of the provided
+63 -39
View File
@@ -79,77 +79,70 @@ use crate::input::ScriptsRequired;
use anyhow::{anyhow, Result};
use log::debug;
use serde_derive::{Deserialize, Serialize};
use std::collections::HashSet;
use std::convert::TryInto;
use std::fs::{self, File};
use std::io::{self, prelude::*};
use std::net::IpAddr;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::string::ToString;
use subprocess::{Exec, ExitStatus};
use text_placeholder::Template;
#[cfg(unix)]
use std::os::unix::process::ExitStatusExt;
static DEFAULT: &str = r#"tags = ["core_approved", "RustScan", "default"]
developer = [ "RustScan", "https://github.com/RustScan" ]
ports_separator = ","
call_format = "nmap -vvv -p {{port}} {{ip}}"
call_format = "nmap -vvv -p {{port}} -{{ipversion}} {{ip}}"
"#;
#[cfg(not(tarpaulin_include))]
pub fn init_scripts(scripts: ScriptsRequired) -> Result<Vec<ScriptFile>> {
pub fn init_scripts(scripts: &ScriptsRequired) -> Result<Vec<ScriptFile>> {
let mut scripts_to_run: Vec<ScriptFile> = Vec::new();
match scripts {
ScriptsRequired::None => Ok(scripts_to_run),
ScriptsRequired::None => {}
ScriptsRequired::Default => {
let default_script =
toml::from_str::<ScriptFile>(DEFAULT).expect("Failed to parse Script file.");
scripts_to_run.push(default_script);
Ok(scripts_to_run)
}
ScriptsRequired::Custom => {
let Some(scripts_dir_base) = dirs::home_dir() else {
return Err(anyhow!("Could not infer scripts path."));
};
let script_paths = match find_scripts(scripts_dir_base) {
Ok(script_paths) => script_paths,
Err(e) => return Err(anyhow!(e)),
};
let scripts_dir_base =
dirs::home_dir().ok_or_else(|| anyhow!("Could not infer scripts path."))?;
let script_paths = find_scripts(scripts_dir_base)?;
debug!("Scripts paths \n{:?}", script_paths);
let parsed_scripts = parse_scripts(script_paths);
debug!("Scripts parsed \n{:?}", parsed_scripts);
let script_config = match ScriptConfig::read_config() {
Ok(script_config) => script_config,
Err(e) => return Err(anyhow!(e)),
};
let script_config = ScriptConfig::read_config()?;
debug!("Script config \n{:?}", script_config);
// Only Scripts that contain all the tags found in ScriptConfig will be selected.
if script_config.tags.is_some() {
let config_hashset: HashSet<String> =
script_config.tags.unwrap().into_iter().collect();
for script in &parsed_scripts {
if script.tags.is_some() {
let script_hashset: HashSet<String> =
script.tags.clone().unwrap().into_iter().collect();
if config_hashset.is_subset(&script_hashset) {
scripts_to_run.push(script.clone());
if let Some(config_hashset) = script_config.tags {
for script in parsed_scripts {
if let Some(script_hashset) = &script.tags {
if script_hashset
.iter()
.all(|tag| config_hashset.contains(tag))
{
scripts_to_run.push(script);
} else {
debug!(
"\nScript tags does not match config tags {:?} {}",
&script_hashset,
script.path.clone().unwrap().display()
script.path.unwrap().display()
);
}
}
}
}
debug!("\nScript(s) to run {:?}", scripts_to_run);
Ok(scripts_to_run)
}
}
Ok(scripts_to_run)
}
pub fn parse_scripts(scripts: Vec<PathBuf>) -> Vec<ScriptFile> {
@@ -193,12 +186,14 @@ struct ExecPartsScript {
script: String,
ip: String,
port: String,
ipversion: String,
}
#[derive(Serialize)]
struct ExecParts {
ip: String,
port: String,
ipversion: String,
}
impl Script {
@@ -253,17 +248,24 @@ impl Script {
script: self.path.unwrap().to_str().unwrap().to_string(),
ip: self.ip.to_string(),
port: ports_str,
ipversion: match &self.ip {
IpAddr::V4(_) => String::from("4"),
IpAddr::V6(_) => String::from("6"),
},
};
to_run = default_template.fill_with_struct(&exec_parts_script)?;
} else {
let exec_parts: ExecParts = ExecParts {
ip: self.ip.to_string(),
port: ports_str,
ipversion: match &self.ip {
IpAddr::V4(_) => String::from("4"),
IpAddr::V6(_) => String::from("6"),
},
};
to_run = default_template.fill_with_struct(&exec_parts)?;
}
debug!("\nScript format to run {}", to_run);
execute_script(&to_run)
}
}
@@ -271,19 +273,41 @@ impl Script {
#[cfg(not(tarpaulin_include))]
fn execute_script(script: &str) -> Result<String> {
debug!("\nScript arguments {}", script);
let process = Exec::shell(script);
match process.capture() {
Ok(c) => {
let es = match c.exit_status {
ExitStatus::Exited(c) => c.try_into().unwrap(),
ExitStatus::Signaled(c) => c.into(),
ExitStatus::Other(c) => c,
ExitStatus::Undetermined => -1,
let (cmd, arg) = if cfg!(unix) {
("sh", "-c")
} else {
("cmd.exe", "/c")
};
match Command::new(cmd)
.args([arg, script])
.stdin(Stdio::piped())
.stderr(Stdio::piped())
.output()
{
Ok(output) => {
let status = output.status;
let es = match status.code() {
Some(code) => code,
_ => {
#[cfg(unix)]
{
status.signal().unwrap()
}
#[cfg(windows)]
{
return Err(anyhow!("Unknown exit status"));
}
}
};
if es != 0 {
return Err(anyhow!("Exit code = {}", es));
}
Ok(c.stdout_str())
Ok(String::from_utf8_lossy(&output.stdout).into_owned())
}
Err(error) => {
debug!("Command error {}", error.to_string());
+2 -2
View File
@@ -68,7 +68,7 @@ macro_rules! output {
macro_rules! funny_opening {
// prints a funny quote / opening
() => {
use rand::seq::SliceRandom;
use rand::seq::IndexedRandom;
let quotes = vec![
"Nmap? More like slowmap.🐢",
"🌍HACK THE PLANET🌍",
@@ -98,7 +98,7 @@ macro_rules! funny_opening {
"TreadStone was here 🚀",
"With RustScan, I scan ports so fast, even my firewall gets whiplash 💨",
];
let random_quote = quotes.choose(&mut rand::thread_rng()).unwrap();
let random_quote = quotes.choose(&mut rand::rng()).unwrap();
println!("{}\n", random_quote);
};
-279
View File
@@ -1,279 +0,0 @@
pub mod udp_payload {
// const MAX_PAYLOAD_IPV4: usize = 65507; // 65,535 - 20 (IP header) - 8 (UDP header)
// const MAX_PAYLOAD_IPV6: usize = 65527; // 65,535 - 40 (IPv6 header) - 8 (UDP header)
/// From [RFC 768](https://www.rfc-editor.org/rfc/rfc768.txt)
/// We send blank UDP packets, unless the port is determined to be special.
///
/// ```text
/// HEADER Handled by the OS
/// 0 1 2 3
/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | Source Port | Destination Port |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | Length | Checksum |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// We append the data, based on the port the the header
/// DATA
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// | Data (based on port) |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// ```
///
/// # Fields
///
/// - **Source Port**: The source port number.
/// - **Destination Port**: The destination port number.
/// - **Length**: The length of the UDP header and data.
/// - **Checksum**: The checksum for error-checking.
/// - **Data**: The payload data, which can vary based on the port.
#[allow(clippy::match_single_binding)]
pub fn cust_payload(dst_prt: u16) -> Vec<u8> {
match dst_prt {
// 53 => craft_dns_query_packet(),
// 67 => craft_dhcpc_packet(),
// 123 => craft_ntp_packet(),
// 161 => craft_snmp_packet(),
_ => vec![],
}
}
pub fn craft_snmptrap_packet() -> Vec<u16> {
let version = vec![0x30, 0x82]; // SNMP version
let community_string = vec![0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63]; // Community string "public"
let pdu_type = vec![0xa4, 0x82]; // PDU type for SNMP Trap
let enterprise_oid = vec![0x06, 0x09, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00]; // Enterprise OID
// Combine the components into a single SNMP Trap packet
[version, community_string, pdu_type, enterprise_oid].concat()
}
/// From [RFC 1592](https://www.rfc-editor.org/rfc/rfc1592.txt)
/// Crafts an SNMP packet based on the structure from RFC 1592.
///
/// RFC 1592 defines the structure of an SNMP packet as follows
/// - **ASN.1 header**: 0x30
/// - **PDU length**: 37 + length of community name
/// - **SNMP version**: 0x02 0x01 0x00 (integer, length=1, value=0)
/// - **Community name**: A string of varying length
/// - **SNMP GET request**: 0xa0 0x1c (request type=0xa0, length=0x1c)
/// - **SNMP request ID**: 0x02 0x01 0x01 (integer, length=1, ID=1)
/// - **SNMP error status**: 0x02 0x01 0x00 (integer, length=1, error=0)
/// - **SNMP index**: 0x02 0x01 0x00 (integer, length=1, index=0)
/// - **VarBind list**: 0x30 0x11 (length=0x11)
/// - **VarBind**: 0x30 0x0f (length=0x0f)
/// - **Object ID**: 0x06 0x0b (length=0x0b)
/// - **Object instance**: 1.3.6.1.4.1.2.2.1.1.1.0
/// - **Null value**: 0x05 0x00 (length=0)
///
/// The PDU length formula:
/// ```text
/// PDU_length = length of version field and string tag (4 bytes)
/// + length of community length field (1 byte)
/// + length of community name (depends...)
/// + length of SNMP GET request (32 bytes)
/// ```
///
/// # Returns
///
/// A `Vec<u8>` representing the crafted SNMP packet.
pub fn craft_snmp_packet() -> Vec<u8> {
// TODO all versions of snmp
let v1 = vec![0x30, 0x29, 0x02, 0x01, 0x00];
let community_string = vec![0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63];
let pdu_type = vec![0xa0, 0x1c];
let request_id = vec![0x02, 0x04, 0x7a, 0x69, 0x67, 0x71];
let error_status = vec![0x02, 0x01, 0x00];
let error_index = vec![0x02, 0x01, 0x00];
let variable_bindings = vec![
0x30, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00,
0x05, 0x00,
];
let _basic_snmp = [
0x30, 0x26, 0x02, 0x01, 0x01, 0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0,
0x19, 0x02, 0x04, 0x71, 0x64, 0xfe, 0xf1, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x30,
0x0b, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x05, 0x00,
];
[
v1,
community_string,
pdu_type,
request_id,
error_status,
error_index,
variable_bindings,
]
.concat()
}
/// Constructs a DHCP packet based on the RFC 1541 Dynamic Host Configuration Protocol specification.
///
///
/// # Returns
///
/// A `Vec<u8>` representing the DHCP packet.
///
/// This function crafts a DHCP Discover packet with the following fields:
/// - **op**: BOOTREQUEST (1)
/// - **htype**: Ethernet (1)
/// - **hlen**: 6
/// - **hops**: 0
/// - **xid**: Random transaction ID
/// - **secs**: 0
/// - **flags**: 0x8000 (Broadcast)
/// - **ciaddr**: 0.0.0.0
/// - **yiaddr**: 0.0.0.0
/// - **siaddr**: 0.0.0.0
/// - **giaddr**: 0.0.0.0
/// - **chaddr**: 00:00:00:00:00:00 (Client MAC address)
/// - **sname**: Not given
/// - **file**: Not given
/// - **options**: DHCP options
pub fn craft_dhcpc_packet() -> Vec<u8> {
let mut packet = Vec::with_capacity(240);
// BOOTP message type: Boot Request (1)
packet.push(0x01);
// Hardware type: Ethernet (10Mb) (1)
packet.push(0x01);
// Hardware address length: 6
packet.push(0x06);
// Hops: 0
packet.push(0x00);
// Transaction ID: random (0x3903F326)
packet.extend(&[0x39, 0x03, 0xF3, 0x26]);
// Seconds elapsed: 0
packet.extend(&[0x00, 0x00]);
// Bootp flags: 0x8000 (Broadcast) (0x8000)
packet.extend(&[0x80, 0x00]);
// Client IP address: 0.0.0.0
packet.extend(&[0x00, 0x00, 0x00, 0x00]);
// Your (client) IP address: 0.0.0.0
packet.extend(&[0x00, 0x00, 0x00, 0x00]);
// Next server IP address: 0.0.0.0
packet.extend(&[0x00, 0x00, 0x00, 0x00]);
// Relay agent IP address: 0.0.0.0
packet.extend(&[0x00, 0x00, 0x00, 0x00]);
// Client MAC address: 00:00:00:00:00:00
packet.extend(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
// Client hardware address padding: 00000000000000000000
packet.extend(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
// Server host name not given
packet.extend(&[0x00; 64]);
// Boot file name not given
packet.extend(&[0x00; 128]);
// Magic cookie: DHCP
packet.extend(&[0x63, 0x82, 0x53, 0x63]);
// DHCP Message Type: DHCP Discover (1)
packet.extend(&[0x35, 0x01, 0x01]);
// DHCP Option: Parameter Request List
packet.extend(&[0x37, 0x04, 0x01, 0x03, 0x06, 0x2a]);
// End Option
packet.push(0xff);
packet
}
/// Constructs a DNS query packet.
///
/// The structure of the DNS packet is as follows:
///
/// ```text
/// +---------------------+
/// | Header |
/// +---------------------+
/// | Question | the question for the name server
/// +---------------------+
/// | Answer | RRs answering the question
/// +---------------------+
/// | Authority | RRs pointing toward an authority
/// +---------------------+
/// | Additional | RRs holding additional information
/// +---------------------+
/// ```
///
/// The function builds a DNS query packet with the following fields:
/// - **Header**: Contains the transaction ID and flags.
/// - **Question**: Specifies the query (e.g., the domain name to look up).
/// - **Answer**: Resource records that answer the question (empty for a query).
/// - **Authority**: Resource records that point toward an authority (empty for a query).
/// - **Additional**: Resource records holding additional information (empty for a query).
///
/// # Returns
///
/// A `Vec<u8>` representing the DNS query packet.
pub fn craft_dns_query_packet() -> Vec<u8> {
let mut packet = Vec::new();
// Transaction ID: Random
packet.extend(&[0x12, 0x34]);
// Flags: Standard query
packet.extend(&[0x01, 0x00]);
// Header ^
// Questions: 1
packet.extend(&[0x00, 0x01]);
// Answer RRs: 0
packet.extend(&[0x00, 0x00]);
// Authority RRs: 0
packet.extend(&[0x00, 0x00]);
// Additional RRs: 0
packet.extend(&[0x00, 0x00]);
// Query: www.google.com
let query_name = "www.google.com";
for part in query_name.split('.') {
packet.push(part.len() as u8);
packet.extend(part.as_bytes());
}
packet.push(0); // End of query name
// Query Type: A (host address)
packet.extend(&[0x00, 0x01]);
// Query Class: IN (internet)
packet.extend(&[0x00, 0x01]);
packet
}
/// Creates the simplest NTP packet possible
/// 0x1b followed by 47 0s, (Version = 3, Mode = 3)
pub fn craft_ntp_packet() -> Vec<u8> {
let mut packet = vec![0u8; 48];
packet[0] = 0x1b;
packet
}
// TODO add more packets for the top 1000 ports
// `sort -r -k3 /usr/share/nmap/nmap-services | grep udp | head -n 1000`
// There has to be a better way to structure this, maybe internal crate for packet payload
// creation
}