Предисловие
цензуры. Данный
материал
предназначен в
большей степени для
теоретической
подготовки. Практика
взлома чужого
компьютера остаётся
на совести того, кто
будет изучать эту
статью. Морально-этические
стороны вопроса
статья не
рассматривает. Желаем,
чтобы полученные
знания Вы направили в
конструктивное русло.
.:Интро:.
Итак,
приветствую тебя о
великий хацкер! Ты
наверное уже знаешь
что такое комп, инет и
т.п :), и наверное не
раз уже пытался
получить ко всему
этому неправомерный
доступ (то биш
взломать). Не
будем вдаваться в
подробности твоих
хакерских
приключений, а
перейдем
непосредственно к
теории.
.:Теория:.
Ты конечно
знаешь, что любой мало-мальски
серьезный взлом (я
имею в виду взлом
компа) начинается со
сбора информации о
жертве. А в свою
очередь важным
составляющим в сборе
инфы является
сканирование
удаленной машины на
предмет обнаружения
открытых портов, т.к.
через них можно
непосредственно
провести атаку на
жертву. Вот сканом
жертвы, а точнее
написанием
инструмента для этого,
мы сейчас и займемся
;)...
Для начала
тебе понадобятся кое-какие
инструменты:
1. Комп (куда
же без него :)
2. Сишный компилятор (если
ты предпочитаешь Delphi,
не беспокойся -
основные принципы
работы с сокетами у
них схожие.)
3. Одна, а лучше две
задействованных
извилины в сером
веществе
4. Прямые руки
И еще:
счастливым
обладателям Выньдос'95
жизненно необходима
библиотека со
вторым WinSock'ом,
которую можно стянуть
с сайта мелкомягких.
.:План
действий:.
Сам сканер
состоит из двух
частей: 1 - это сам
сканер, 2 - файл с
описанием портов
(пока что подойдет
стандартный NMap'овский
). В файле описания
портов (далее шаблоне
портов) инфа
распологается
следующим образом:
¦-----------¦------------------¦--------------¦
¦ сервис ¦ порт/tcp ¦ #
описание ¦
¦-----------¦------------------¦--------------¦
Сканер
просто считывает из
этого файла по строке,
вычисляет позицию
символа '/',
преобразует 'порт' в
число и выполняет
стандартный блок
соединения с
удаленной машиной по
заданному порту.
Перед этим сканер
проверяет введенный IP
адрес со стандартной
маской (xxx.xxx.xxx.xxx). При
соответствии IP'шника
маске пускает цикл
скана, а не
соответствии -
пытается при помощи
функции gethostbyname()
получить IP хоста.
Все
достаточно просто, но
нужно учесть один
очень важный момент: в шаблоне
портов содержаться
лишь данные о портах и
сервисах, принятые общими
соглашениями. Т.е.
например по дефолту
http демон крутится на 80 порту, а
если админ вдруг
решил поставить его
на 1234 или другой порт? Именно по
этому в нашем сканере
я предусмотрел еще и
режим скана по интервалу. Т.е.
задаешь интервал
портов, а сам идешь
пить кофе или что
больше нравится :).
Сканер все
сделает за тебя.
.:Подготовка
к кодингу:.
Не знаю как
ты, но я все свои
хакерские замыслы
воплощаю в M$ VC++ шестой или
седьмой версии (лучше
в 6'ой). Этот случай не
исключение . Для начала
создай новый
консольный проект и в
параметрах линковки включи в
проект следующие
библиотеки: kernel32.lib
ws2_32.lib libc.lib. Далее в
текстовом редакторе
создай файл portlist.dat со
следующим содержанием:
echo 7/tcp #
ftp 21/tcp # File
Transfer [Control]
ssh 22/tcp # Secure
Shell Login
telnet 23/tcp #
smtp 25/tcp # Simple
Mail Transfer
whois 43/tcp # nicname
domain 53/tcp # Domain
Name Server
http 80/tcp # World
Wide Web HTTP
pop-2 109/tcp #
PostOffice V.2
pop-3 110/tcp #
PostOffice V.3
Для начала
этого хватит.
Впоследствии можешь
заюзать файлик из NMap'a
(http://www.insecure.org/nmap).
.:Кодинг:.
/* eXpert Scaner v.2.0
- Copyright (C) NeTxXx
Description:
XScan is an advanced
console port scaner. It can work like
NMap (http://www.insecure.org/nmap) -
use external file with
ports and their descriptions or like a
simple range scaner - scan definite
ports range. Scaner
can write scanning results to log file
and work in the debug mode (-a || --all).
*/
#include <stdio.h>
#include <winsock.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#pragma comment(linker,"/MERGE:.rdata=.text")
//с помощью этих вроде
бы ничего не значущих
строк -->
#pragma comment(linker,"/FILEALIGN:512
/SECTION:.text,EWRX /IGNORE:4078")
//--> мы сделаем exe'шник
-->
#pragma comment(linker,"/NODEFAULTLIB")
//--> на несколько
килобайт поменьше
#define MARK '/' //символ
разделения (21/tcp)
int main(int argc,
char *argv[]) //начинаем
кодить....
{
int i;
SOCKET net; //
сокет
WSADATA wsadata;
struct sockaddr_in sa;
//структура с
описанием адреса
struct hostent *host;
//структура с
описанием хоста
FILE *ptr; //указатель
на файл
FILE *f;
char buf1[200]; //строковый
буффер
int c;
char *temp1;
char *temp2;
int open = 0; //число
открытых портов
time_t t; //переменная
типа time
ptr = fopen("portlist.dat","r");
//открываем файл с
описанием портов
if (ptr == NULL) //если
не открывается...
{
perror("ERROR:
portlist.dat"); //ошибка...
exit(1);
}
if (argc < 3) //если
сканер запустили без
необходимого
количества
параметров =>
{ //=>
показываем usage
printf("Usage:
xscan [-L] | [-R beginport endport] [hostname]
[options]");
printf("Params: -L(--LIST)
- get known ports from list");
printf("Params: -R(--RANGE)
- get ports from range");
printf("Options:
-a(--all) - show all messages");
printf("Options:
-l(--log) - write results to log file");
printf("---------------------------------");
printf("Example:
xscan -L 127.0.0.1");
printf("Example:
xscan -C 10 80 127.0.0.1");
exit(1); //и
выходим
}
if (WSAStartup(MAKEWORD(2,1),
&wsadata) != 0) //инициализация
WSADATA
{
printf("ERROR:
Initialization error.");
exit(0);
}
//============================LIST
SCANNING MODE==============================
//если
выбран режим
сканирования по
шаблону
if ((strcmp(argv[1],"-L")
== 0) || (strcmp(argv[1],"--LIST")
== 0))
{
printf("Starting
XScan v.2.0 (http://openweb.fatal.ru)");
printf("Press
Ctrl+C to abort....");
printf("Scanning
mode: list.");
printf("Accepted
ports on %s:", argv[2]);
printf("<Service>
<Port> <Comment>");
if (((argc >= 4)
&& ((strcmp(argv[3],"-l")
== 0) || (strcmp(argv[3],"--log")
== 0))) ||
(((argc > 4)
&& ((strcmp(argv[4],"-l")
== 0) || (strcmp(argv[4],"--log")
== 0))))) //если юзер хочет
вести LOG...
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
time(&t); //получаем
текущее время
fprintf(f,"#######################################################%s",ctime(&t));
fprintf(f,"Starting
XScan v.2.0 (http://openweb.fatal.ru)");
fprintf(f,"Scanning
mode: list.");
fprintf(f,"Accepted
ports on %s:",argv[2]);
fprintf(f,"<Service>
<Port> <Comment>");
fclose(f);
}
open = 0; //обнуляем
счетчик
while ((c = fgetc(ptr))
!= EOF) //если файл с
портами еще не
закончился
{
fgets(buf1,200,ptr);
//считываем очередную
строку
temp1 = strchr(buf1,MARK);
//помещаем указатель
строки temp1 на символ '/'
temp2 = temp1;
while (*temp2 != ' ')
//ищем первый пробел в
temp2
{
temp2--;
}
temp1++; //увеличиваем
temp1
if ((*temp1 == 't') ||
(*temp1 == 'T')) //если temp1
равен 't' (tcp)
i = atoi(temp2); //преобразуем
temp2 в число
else //если же
нет...
i = -1;
if (i > -1) //
проверка на вшивость
{
temp1 = (char *)buf1;
//присваиваем temp1
значение всей
считанной строки
strncpy((char *)&sa,"",sizeof(sa));
//выделяем память для
sock_addr
sa.sin_family =
AF_INET; //семейство: AF_INET
:)
if (isdigit(*argv[2]))
//проверка на
соответствие IP адресу
sa.sin_addr.s_addr =
inet_addr(argv[2]); //если да,
то преобразовываем
строку в unsigned long
else if ((host =
gethostbyname(argv[2])) != 0) //если
же нет, получаем инфу
о хосте =>
strncpy((char *)&sa.sin_addr,(char
*)host->h_addr,sizeof(sa.sin_addr));
//и получаеи его IPшник
else { //ошибка?
perror(argv[2]);
exit(1);
}
sa.sin_port = htons(i);
//порт для connect'a
net = socket(AF_INET,
SOCK_STREAM,0); //создаем
новый сокет
if (net ==
INVALID_SOCKET) //если сокет -
инвалид... :)
{
if (((argc >= 4)
&& ((strcmp(argv[3],"-l")
== 0) || (strcmp(argv[3],"--log")
== 0))) ||
(((argc > 4)
&& ((strcmp(argv[4],"-l")
== 0) || (strcmp(argv[4],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
time(&t);
fprintf(f,"#######################################################%s",ctime(&t));
fprintf(f,"Cannot
create socket!");
fclose(f);
}
perror("Cannot
create socket!");
exit(1); //завершаем
работу
}
if (connect(net,(sockaddr
*)&sa, sizeof(sa)) == 0) //есть
connect? ЕСТЬ!
{
printf("%s",temp1);
if (((argc >= 4)
&& ((strcmp(argv[3],"-l")
== 0) || (strcmp(argv[3],"--log")
== 0))) ||
(((argc > 4)
&& ((strcmp(argv[4],"-l")
== 0) || (strcmp(argv[4],"--log")
== 0))))) //пишем в лог
если надо
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
fprintf(f,"%s",temp1);
fclose(f);
}
shutdown(net,2); //разрываем
соединение shutdown()'ом
open++; //увеличиваем
счетчик
} else { //нет
коннекта?
if (((argc >= 4)
&& ((strcmp(argv[3],"-a")
== 0) || (strcmp(argv[3],"--all")
== 0))) ||
(((argc > 4)
&& ((strcmp(argv[4],"-a")
== 0) || (strcmp(argv[4],"--all")
== 0))))) //дебаг?
{
printf("%s: %-5d
%s",argv[2],i,strerror(errno));
if (((argc >= 4)
&& ((strcmp(argv[3],"-l")
== 0) || (strcmp(argv[3],"--log")
== 0))) ||
(((argc > 4)
&& ((strcmp(argv[4],"-l")
== 0) || (strcmp(argv[4],"--log")
== 0))))) //лог?
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
fprintf(f,"%s: [%-5d
%s]",argv[2],i,strerror(errno));
fclose(f);
}
}
fflush(stdout);
}
closesocket(net); //убиваем
созданный сокет
}
}
printf("Scanning
complete: %d ports opened on %s...",
open, argv[2]); //скан
завершен
if (((argc >= 4)
&& ((strcmp(argv[3],"-l")
== 0) || (strcmp(argv[3],"--log")
== 0))) ||
(((argc > 4)
&& ((strcmp(argv[4],"-l")
== 0) || (strcmp(argv[4],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
fprintf(f,"Scanning
complete: %d ports opened on %s...",
open, argv[2]);
fclose(f);
}
}
//===========================RANGE
SCANNING MODE===============================
//если
выбран режим
сканирования
интервалом
if ((strcmp(argv[1],"-R")
== 0) || (strcmp(argv[1],"--RANGE")
== 0))
{
int bport = atoi(argv[2]);
//начальный порт
int eport = atoi(argv[3]);
//конечный порт
int counter = bport;
if (bport > eport)
//проверка на вшивость
{
if (((argc >= 6)
&& ((strcmp(argv[5],"-l")
== 0) || (strcmp(argv[5],"--log")
== 0))) ||
(((argc > 6)
&& ((strcmp(argv[6],"-l")
== 0) || (strcmp(argv[6],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
time(&t);
fprintf(f,"%s:
ERROR: Invalid port range.",ctime(&t));
fclose(f);
}
perror("ERROR:
Invalid port range.");
exit(1);
}
printf("Starting
XScan v.2.0 (http://openweb.fatal.ru)");
printf("Press
Ctrl+C to abort....");
printf("Scanning
mode: range.");
printf("Ports
range: %d - %d", bport, eport);
printf("Accepted
ports on %s:", argv[4]);
if (((argc >= 6)
&& ((strcmp(argv[5],"-l")
== 0) || (strcmp(argv[5],"--log")
== 0))) ||
(((argc > 6)
&& ((strcmp(argv[6],"-l")
== 0) || (strcmp(argv[6],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
time(&t);
fprintf(f,"#######################################################%s",ctime(&t));
fprintf(f,"Starting
XScan v.2.0 (http://openweb.fatal.ru)");
fprintf(f,"Scanning
mode: range.",ctime(&t));
fprintf(f,"Ports
range: %d - %d",bport, eport);
fprintf(f,"Accepted
ports on %s:",argv[4]);
fclose(f);
}
open = 0;
for (counter = bport;
counter <= eport; counter++) //пускаем
цикл
{
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr(argv[4]);
sa.sin_port = htons(counter);
net = socket(AF_INET, SOCK_STREAM, 0);
if (net == INVALID_SOCKET)
{
if (((argc >= 6)
&& ((strcmp(argv[5],"-l")
== 0) || (strcmp(argv[5],"--log")
== 0))) ||
(((argc > 6)
&& ((strcmp(argv[6],"-l")
== 0) || (strcmp(argv[6],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
time(&t);
fprintf(f,"#######################################################%s",ctime(&t));
fprintf(f,"Cannot
create socket!");
fclose(f);
}
perror("Cannot
create socket!");
exit(1);
}
if (connect(net, (sockaddr*)&sa,
sizeof(sockaddr_in)) == 0) //есть
connect? ЕСТЬ!
{
printf("%s: %d -
opened!", argv[4], counter);
if (((argc >= 6)
&& ((strcmp(argv[5],"-l")
== 0) || (strcmp(argv[5],"--log")
== 0))) ||
(((argc > 6)
&& ((strcmp(argv[6],"-l")
== 0) || (strcmp(argv[6],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
fprintf(f,"%s: %d
- opened!",argv[4], counter);
fclose(f);
}
open++; //увеличиваем
счетчик
shutdown(net, 2); //разрываем
соединение shutdown()'ом
} else
{
if (((argc >= 6)
&& ((strcmp(argv[5],"-a")
== 0) || (strcmp(argv[5],"--all")
== 0))) ||
(((argc > 6)
&& ((strcmp(argv[6],"-a")
== 0) || (strcmp(argv[6],"--all")
== 0)))))
{
printf("%s:
%-5d%s",argv[4],counter,strerror(errno));
if (((argc >= 6)
&& ((strcmp(argv[5],"-l")
== 0) || (strcmp(argv[5],"--log")
== 0))) ||
(((argc > 6)
&& ((strcmp(argv[6],"-l")
== 0) || (strcmp(argv[6],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
fprintf(f,"%s:
%-5d %s",argv[4],counter,strerror(errno));
fclose(f);
}
}
fflush(stdout);
}
closesocket(net); //убиваем
созданный сокет
}
printf("Scanning
complete: %d ports opened on %s...",
open, argv[4]); //вывод
результатов
if (((argc >= 6)
&& ((strcmp(argv[5],"-l")
== 0) || (strcmp(argv[5],"--log")
== 0))) ||
(((argc > 6)
&& ((strcmp(argv[6],"-l")
== 0) || (strcmp(argv[6],"--log")
== 0)))))
{
if ((f = fopen("scan.log",
"a+")) == NULL)
{
perror("ERROR:
scan.log");
exit(1);
}
fprintf(f,"Scanning
complete: %d ports opened on %s...",
open, argv[4]);
fclose(f);
}
}
fflush(stdout);
WSACleanup(); //очищаем
WSAData
fclose(ptr); //закрываем
файл с портами
return 0;
} //ALL DONE!
.:Outro:.
Если ты уже
работал с сокетами, то
без труда сможешь
разобраться в этом
наборе строк, если же нет -
смотри комментарии к
коду. И
напоследок скажу: если
добавить в этот
примерчик
возможность скана по
UDP, пинг и определение
версии демонов или OS, то
можно с легкостью
составить
конкуренцию нашему
любимому NMap'у и
потеснить его на рынке
инет-сканеров ;).
Дерзай!
Автор:
NeTxXx Copyright
(C) 2003-2004 e-mail:
develop@list.ru
Размещено:
6.06.2005 |