69 lines
3.2 KiB
Bash
69 lines
3.2 KiB
Bash
#!/bin/bash
|
||
|
||
# --- 配置 ---
|
||
NETWORK_PREFIX="192.168.112"
|
||
PORT_TO_SCAN=22
|
||
NETWORK_RANGE="${NETWORK_PREFIX}.1-254" # nmap 需要的范围格式
|
||
|
||
echo "正在使用 nmap 扫描网络范围: ${NETWORK_RANGE}"
|
||
echo "查找TCP端口 ${PORT_TO_SCAN} 打开的主机, 并立即查询其 MAC 地址 (macOS)..."
|
||
echo "--------------------------------------------------"
|
||
printf "%-18s %-20s\n" "IP 地址" "MAC 地址"
|
||
echo "--------------------------------------------------"
|
||
|
||
# nmap -oG - 的输出格式为: Host: <IP> (<Hostname>) Status: Up Ports: <Port>/open/...
|
||
# 我们需要匹配 "Status: Up" 和包含指定开放端口的行
|
||
# awk 使用 fflush() 来确保其输出被立即发送到管道
|
||
nmap -n -Pn -p "${PORT_TO_SCAN}" --open "${NETWORK_RANGE}" -oG - | \
|
||
awk -v port="${PORT_TO_SCAN}" '/Status: Up/ && $0 ~ ("/" port "\\/open\\/") {print $2; fflush()}' | \
|
||
while read -r ip_address; do
|
||
# 移除 awk 输出可能带来的前后空格 (通常 $2 不会,但保险起见)
|
||
ip_address=$(echo "$ip_address" | tr -d '[:space:]')
|
||
|
||
if [[ -z "$ip_address" || ! "$ip_address" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||
# 这个检查在 awk 条件加强后,触发概率降低,但作为安全措施保留
|
||
echo "警告: 从 nmap/awk 管道获取到无效的 IP 格式: '$ip_address'" >&2
|
||
continue
|
||
fi
|
||
|
||
mac_address="N/A (未获取到)" # 默认值
|
||
|
||
# 对每个 IP 地址使用 arp 查询 MAC 地址 (macOS 特定)
|
||
# macOS arp -n <ip> 输出示例:
|
||
# ? (192.168.112.1) at 0:1:2:3:4:5 on en0 ifscope [ethernet]
|
||
# ? (192.168.112.130) at (incomplete) on en0 ifscope [ethernet]
|
||
# ? (192.168.112.254) -- no entry
|
||
arp_result=$(arp -n "$ip_address" 2>/dev/null)
|
||
|
||
if [[ -n "$arp_result" ]]; then
|
||
if echo "$arp_result" | grep -q -- "-- no entry"; then
|
||
mac_address="N/A (no ARP entry)"
|
||
elif echo "$arp_result" | grep -q "at (incomplete)"; then
|
||
mac_address="N/A (incomplete)"
|
||
else
|
||
# 更精确地提取 MAC 地址,确保是针对当前 IP 的
|
||
# awk 字段: $1=?, $2=(<ip_address>), $3=at, $4=<mac_address>
|
||
# 注意 macOS的arp输出中IP地址是带括号的
|
||
potential_mac=$(echo "$arp_result" | awk -v ip_with_paren="(${ip_address})" '$2 == ip_with_paren && $3 == "at" {print $4}')
|
||
|
||
if [[ "$potential_mac" =~ ^([0-9a-fA-F]{1,2}:){5}[0-9a-fA-F]{1,2}$ ]]; then
|
||
mac_address="$potential_mac"
|
||
elif [[ -n "$potential_mac" ]]; then # awk 输出了东西,但格式不对
|
||
mac_address="N/A (ARP parse error: $potential_mac)"
|
||
else # awk 没有输出 (可能 arp_result 格式不符合预期或未找到匹配行)
|
||
mac_address="N/A (ARP parse logic fail)"
|
||
fi
|
||
fi
|
||
else
|
||
mac_address="N/A (no ARP output)"
|
||
fi
|
||
|
||
# 显示 IP 和 MAC 地址
|
||
printf "%-18s %-20s\n" "$ip_address" "$mac_address"
|
||
done
|
||
|
||
echo "--------------------------------------------------"
|
||
echo "扫描完成。"
|
||
echo "提示: MAC 地址的获取依赖于本地 ARP 缓存。"
|
||
echo "如果某些条目显示 N/A,目标可能刚刚响应 nmap 但尚未进入 ARP 缓存,"
|
||
echo "或者目标不可达/arp 查询失败,或 ARP 表中无该条目。" |