У меня есть команда, которую я хочу запустить:
echo "Performing unicornscan on:" $target
unicornscan -Ivv $target:1-65535 | tee enum/uniscan-alltcp.txt
Это дает такой результат:
TCP open 192.168.0.102:443 ttl 128
connected 192.168.103.227:54487 -> 192.168.0.102:161
TCP open 192.168.0.102:161 ttl 128
connected 192.168.103.227:47765 -> 192.168.0.102:80
TCP open 192.168.0.102:80 ttl 128
connected 192.168.103.227:4267 -> 192.168.0.102:1884
TCP open 192.168.0.102:139 ttl 128
sender statistics 963.9 pps with 65536 packets sent total
listener statistics 131180 packets recieved 0 packets droped and 0 interface drops
TCP open http[ 80] from 192.168.0.102 ttl 128
TCP open netbios-ssn[ 139] from 192.168.0.102 ttl 128
TCP open snmp[ 161] from 192.168.0.102 ttl 128
TCP open https[ 443] from 192.168.0.102 ttl 128
TCP open microsoft-ds[ 445] from 192.168.0.102 ttl 128
Как я могу проанализировать этот вывод, чтобы получить все IP-адреса в списке, разделенном запятая, например:
80,139,161,443,445
Спасибо
Используйте sed
, чтобы сопоставить строки с TCP open.*\[
и взять число между [
и ]
.
Я написал сценарий, который может решить вашу проблему. Это напечатает весь вывод.
Следуй этим шагам:
Откройте answer.bash
(или как хотите назвать скрипт) в текстовом редакторе.
Введите или вставьте следующее:
Сценарий:
#!/bin/bash
# Store the command in a variable for easy changes
# Note: The command is not actually executed until the while loop
COMMAND = "unicornscan -Ivv $target:1-65535 | tee enum/uniscan-alltcp.txt"
PORTS=()
# For each line:
while read line; do
# The third token is either IP or protocol name with '['
token=`echo $line | awk '{print $3}'`
last_char_idx=$((${#token}-1))
last_char=${token:$last_char_idx:1}
# Case 1: It is the protocol name
if [[ "$last_char" = "[" ]]; then
# This is a protocol. Therefore, port is token 4
port=`echo $line | awk '{print $4}'`
# Shave off the last character
port=${port::-1}
else
# token is ip:port. Awk out the port
port=`echo $token | awk -F: '{print $2}'`
fi
PORTS+=("$port")
done < <($COMMAND | egrep "^TCP open")
# egrep is used to skip any lines that don't begin with TCP open
# 'tee' should still send full output to file
# Print all the ports we found
for p in "${PORTS[@]}"; do
echo -n "$p, "
done
echo
Сохраните файл.
Введите bash answer.bash
. Наблюдайте за желаемым результатом (надеюсь!)
Сценарий использует цикл while
для пошагового выполнения командной строки. На каждой итерации текущая строка устанавливается в переменную line
.
В цикле while я использую egrep
, чтобы получить ТОЛЬКО строки, начинающиеся с TCP open
. Я заметил, что третий токен каждой из этих строк либо содержит значение IP: Port, либо имя протокола, за которым следует символ [
. Сценарий предполагает последний случай для всего, что заканчивается на [
, и обрабатывает его соответствующим образом, используя awk
для получения имени порта из четвертого токена. Если это пара IP: Port, также можно использовать awk
с :
в качестве разделителя полей.
Каждый порт, полученный таким образом, сохраняется в массиве PORTS. В конце сценария печатается каждое значение массива портов, в результате чего получается следующий результат:
443, 161, 80, 139, 80, 139, 161, 443, 445,
Вы можете передать вывод этого сценария в файл или переменную или сохранить его в переменной прямо внутри сценария.
Пожалуйста, дайте мне знать, как это работает, и если у вас есть вопросы. Также приношу свои извинения за чрезмерное использование подоболочки.
Попробуйте что-нибудь вроде:
#!/bin/bash
declare -a ary
while read -r line; do
if [[ "$line" =~ \[\ *([0-9]+)\] ]]; then
ary+=("${BASH_REMATCH[1]}")
fi
done < "file.txt"
ifs_bak = "$IFS" # back up IFS
IFS=,; list = "${ary[*]}"
IFS = "$ifs_bak" # retrieve IFS
echo "$list"
[
и ]
и назначает ему ${BASH_REMATCH[1]}
.ary
.ary
печатается как значение, разделенное запятыми.
Вы хотите получить IP-адреса или порты? Вышеупомянутые
80,139,161,443,445
выглядят как порты.