# LazyOwn Beacon Network Discovery and Port Scanning: A Technical Deep Dive

> Explore LazyOwn's beacon network discovery and port scanning capabilities. Learn how to perform ping sweeps, TCP port scans, and service detection without external tools directly from compromised hosts.

- Repository: [Grisuno/lazyown](https://github.com/grisuno/lazyown)
- Tags: deep-dive
- Published: 2026-03-02

---

**The LazyOwn C2 framework provides three built-in beacon commands—`hostdiscover`, `portdiscover`, and `portservicediscover`—that generate Bash scripts to perform ping sweeps, full TCP port scans, and service detection on compromised hosts without requiring external tools like nmap.**

The beacon network discovery and port scanning capabilities in LazyOwn enable operators to enumerate target networks directly from a compromised host. According to the grisuno/lazyown source code, these features are implemented as interactive CLI commands that dynamically generate Bash payloads for execution within the beacon's session. This approach eliminates dependencies on external scanning tools while providing manual execution guards to prevent accidental runs on the attacker's workstation.

## How Beacon Network Discovery Works in LazyOwn

LazyOwn implements beacon network discovery through three distinct methods in [`lazyown.py`](https://github.com/grisuno/lazyown/blob/main/lazyown.py), each designed for specific reconnaissance scenarios.

### hostdiscover: Subnet Ping Sweep

The `do_hostdiscover` method (lines 7808-7863 in [`lazyown.py`](https://github.com/grisuno/lazyown/blob/main/lazyown.py)) performs a classic ping sweep across a /24 subnet. It constructs a Bash script that iterates through the last octet (1-254), executing `ping -c 1` with a 1-second timeout to identify live hosts.

Key implementation details include:

- Reading the current `rhost` parameter to determine the subnet
- Generating a parallelized ping loop using background processes
- Outputting active hosts in real-time

### portdiscover: Full TCP Port Scanning

The `do_portdiscover` method (lines 7866-7924) scans all 65,535 TCP ports on a single target. It leverages the Bash `/dev/tcp` pseudo-device to attempt connections without installing additional tools.

The generated script:

- Loops through `seq 0 65535`
- Uses the redirection trick `(echo >/dev/tcp/$ip/$port)` to test connectivity
- Echoes only open ports to minimize output noise

### portservicediscover: Service-Aware Port Scanning

Extending the previous functionality, `do_portservicediscover` (lines 7966-8025) adds service identification. After detecting an open port, it executes `sudo lsof -i :$port` and parses the first field of the output to determine the listening service name.

This method requires elevated privileges on the beacon host to access the `lsof` service information.

## Execution Flow and Safety Controls

### Parameter Validation

All discovery commands rely on the `rhost` entry in `self.params`, typically set via `assign rhost <ip>`. The helper `check_rhost()` from [`utils.py`](https://github.com/grisuno/lazyown/blob/main/utils.py) validates the IP format before script generation.

### Interactive Execution Guard

After generating the Bash payload, the methods follow a strict safety protocol:

1. Display the complete script via `print_msg()`
2. Prompt the operator with `input("Do you want to execute? (yes/no): ")`
3. If **yes**: Execute via `self.cmd()` within the beacon session
4. If **no**: Copy to clipboard using `copy2clip` for manual review

This ensures the operator reviews the payload before it runs on the compromised host.

### Command Registration

Each function is decorated with `@cmd2.with_category(scanning_category)`, organizing them under the *Scanning* group in the LazyOwn interactive CLI.

## Practical Usage Examples

### Running a Host Discovery Scan

```text
> assign rhost 192.168.1.10
> hostdiscover
#!/bin/bash
for i in $(seq 1 254); do
    timeout 1 bash -c "ping -c 1 192.168.1.$i" &>/dev/null && echo "[+] Host 192.168.1.$i - active" &
done; wait
Do you want to execute? (yes/no): yes

```

### Performing a Full Port Scan

```text
> assign rhost 10.0.0.42
> portdiscover
#!/bin/bash
ip="10.0.0.42"
echo "Escaneo de puertos abiertos en curso..."
echo " "
for port in $(seq 0 65535); do
    (echo >/dev/tcp/$ip/$port) >/dev/null 2>&1 && echo "Puerto $port abierto"
done
Do you want to execute? (yes/no): yes

```

### Detecting Services on Open Ports

```text
> assign rhost 10.0.0.42
> portservicediscover
#!/bin/bash
ip="10.0.0.42"
echo "Escaneo de puertos y servicios abiertos en curso..."
echo " "
for port in $(seq 0 65535); do
    (echo >/dev/tcp/$ip/$port) >/dev/null 2>&1 && {
        service=$(echo "$(sudo lsof -i :$port)" | awk 'NR==2{print $1}')
        [ -n "$service" ] && echo "Puerto $port abierto - Servicio: $service"
    }
done
Do you want to execute? (yes/no): yes

```

## Summary

- **Three built-in commands** provide comprehensive beacon-side network reconnaissance: `hostdiscover` for ping sweeps, `portdiscover` for TCP scanning, and `portservicediscover` for service identification.
- **Bash script generation** eliminates dependencies on external tools like nmap or masscan, using native shell capabilities such as `/dev/tcp` redirection.
- **Safety mechanisms** require explicit operator confirmation before execution, with clipboard fallback for manual script review.
- **Source locations** are centralized in [`lazyown.py`](https://github.com/grisuno/lazyown/blob/main/lazyown.py) (lines 7808-8025) with helper utilities in [`utils.py`](https://github.com/grisuno/lazyown/blob/main/utils.py) for parameter validation and output formatting, and test coverage demonstrated in [`test_commands.py`](https://github.com/grisuno/lazyown/blob/main/test_commands.py) (line 100).
- **Execution context** runs entirely on the compromised beacon host, not the attacker's workstation, through the `self.cmd()` method.

## Frequently Asked Questions

### What is the difference between portdiscover and portservicediscover?

The `portdiscover` command performs a basic TCP connect scan across all 65,535 ports using Bash `/dev/tcp` redirection, reporting only open port numbers. The `portservicediscover` command extends this by executing `sudo lsof -i :$port` on each open port to identify the associated service name, though this requires root privileges on the beacon host.

### How does LazyOwn prevent accidental execution on the attacker's machine?

According to the source code in [`lazyown.py`](https://github.com/grisuno/lazyown/blob/main/lazyown.py), each discovery method implements an interactive execution guard. After generating the Bash script, the operator must explicitly respond **yes** to the prompt "Do you want to execute? (yes/no): ". If the operator selects **no**, the script is copied to the clipboard via `copy2clip` instead of being executed, preventing unintended runs on the wrong machine.

### Where are the beacon discovery commands defined in the source code?

The three discovery commands are implemented as methods in [`lazyown.py`](https://github.com/grisuno/lazyown/blob/main/lazyown.py): `do_hostdiscover` occupies lines 7808-7863, `do_portdiscover` spans lines 7866-7924, and `do_portservicediscover` covers lines 7966-8025. Supporting utilities including `check_rhost()`, `print_msg()`, and `copy2clip` are located in [`utils.py`](https://github.com/grisuno/lazyown/blob/main/utils.py).

### Does LazyOwn require external tools like nmap for network discovery?

No. The beacon network discovery functionality generates pure Bash scripts that rely on built-in shell utilities like `ping`, `timeout`, and `/dev/tcp` redirection. This design ensures reconnaissance capabilities remain available even on minimal compromised hosts that lack specialized scanning tools.