Содержание статьи
Если ты видишь Go впервые, начни с чтения предыдущей статьи «Go кодить», там я постарался объяснить базовые концепции, в особенности те, что отличают Go от других языков.
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Для начала создадим новый модуль:
mkdir portscan && cd $_go mod init portscan
touch main.go
В файл main. вставим следующий код:
package mainimport ( "fmt" "net" "os" "time")func main() { if len(os.Args) <= 1 { fmt.Fprintf(os.Stderr, "Target address not specified\n") os.Exit(1) } target := os.Args[1] if net.ParseIP(target) == nil { fmt.Fprintf(os.Stderr, "%s is not a valid address\n", target) os.Exit(1) } ports := []string{"21", "22", "25", "53", "80", "8080", "443", "110", "143", "3306", "3389"} timeout := 250 * time.Millisecond for _, port := range ports { addr := net.JoinHostPort(target, port) conn, err := net.DialTimeout("tcp", addr, timeout) if err != nil { continue } conn.Close() fmt.Printf("Port %s is open\n", port) } os.Exit(0)}Аргументы командной строки содержатся в срезе строк os., причем первый элемент — это имя самого исполняемого файла. Мы ожидаем, что адрес для сканирования будет передан как аргумент, поэтому проверяем количество элементов в срезе вызовом len(.
Также ты можешь видеть, как мы выводим текст в стандартный поток ошибок os. и возвращаем код выхода вызовом os. (ненулевой в случае ошибки или ноль при успешном завершении работы). Все эти возможности нам предоставляет пакет os — загляни в документацию, там еще много интересного!
info
Явно вызывать os. излишне, штатно завершающаяся программа в любом случае вернет код 0. Я добавил эту строку в код только для наглядности.
net
Подобно тому как os предоставляет средства взаимодействия с операционной системой, пакет net обеспечивает сетевой ввод‑вывод и множество вспомогательных функций. Одну из них мы используем для валидации введенного пользователем адреса: net. парсит строку и возвращает переменную типа IP, содержащую байты адреса, или nil при неудаче. Функция net. объединяет IP и порт в одну строку, а net. подключается по указанному адресу c указанным тайм‑аутом и возвращает открытое соединение, в которое можно писать и читать, или nil и ошибку.
Далее объявляем срез, содержащий номера портов, которые мы будем сканировать. Обрати внимание на синтаксис объявления: если бы мы указали размер ports :, то результатом был бы массив. Не указывая размер, мы получаем срез. В данном случае для нас нет особой разницы, но если бы мы в будущем собирались изменить размер этой коллекции динамически, то массив нам не подошел бы. Функцию make( мы здесь не использовали, поскольку сразу же инициализировали срез значениям.
time
Теперь поговорим еще об одном пакете, также входящем в стандартную библиотеку, — time. Он предоставляет функции для работы с временем, датами, интервалами и разные преобразования. Среди прочих интересностей в нем содержится тип time., позволяющий генерировать однократные события по истечении указанного времени, и time., генерирующий последовательность событий с определенным интервалом.
Для измерения длительностей (например, чтобы узнать, как долго выполнялся какой‑то код) полезна функция time.. Мы же используем определение time., чтобы задать желаемый тайм‑аут.
for
Наконец мы добрались до самого интересного. Аргумент (адрес целевого хоста) считан и валидирован, набор сканируемых портов определен, тайм‑аут попытки подключения задан. Теперь мы перебираем в цикле все порты и к каждому из них пробуем подключиться. Если попытка неудачна, переходим к следующему порту. В противном случае закрываем открывшееся соединение и выводим в консоль сообщение с номером порта.
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
