|
Эксплоит в разрезе
Xakep, номер #047, стр. 047-084-2 fprintf(stderr,"Attacking sphere : "); Дальше идет сердце эксплоита - вся его паразитическая сущность сосредоточилась в следующих нескольких строчках: for (;;) { int sock; sock = Connect(inet_addr(argv[1]),(argc>2)?(atoi(argv[2])):3128); if (sock<0) { sleep(10); continue; } fprintf(stderr, ".*"); } for (;;) - запускает бесконечный цикл, то есть явного выхода из него нет. int sock - новая переменная для сокета. Следующая строка вызывает функцию Connect. В ней мы коннектимся на адрес, содержащийся в первом параметре вызова, и в порт 3128, если эксплоит был вызван с двумя параметрами, в противном случае (параметров больше двух) коннектимся на порт, номер которого лежит во втором параметре вызова. Именно об этом говорит конструкция: (argc>2)?(atoi(argv[2])):3128; Следует обратить внимание на две тонкости: во всем тексте программы мы проверили, сколько аргументов (если меньше двух, сразу вылетаем). Также обрати внимание на функцию atoi(). Она переводит строку в целое число. Мы ее используем потому, что параметры вызова считываются программой как строки, а не числа. После того как данные получены, нужно произвести проверку на удачность действий. Если переменная sock меньше нуля, то sleep (10) - происходит пауза в 10 миллисекунд и повтор следующей попытки - continue; Строчка fprintf(stderr, ".*") рисует на экране звездочку - своеобразный индикатор атаки. Один раз приконнектились - нарисовали звездочку. Функция Connect Теперь давай проанализируем функцию Connect(). int Connect(int ip, int port) Функция возвращает тип int. В данном случае это код ошибки, который может возникнуть по ходу работы программы. Теперь далее, о самом коде. На вход она получает ip-адрес атакуемого сервера (или имя хоста) и номер порта, с которым будет происходить соединение. В самом начале снова объявляются две переменные: int fd; struct sockaddr_in box; Далее инициализируется сокет: fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (fd<0) return -1; Первая строка снова отвечает за выбор сокета. Далее идет проверка, если не удалось подготовить сокет (fd<0), то возвращаем -1. После повторной инициализации новой переменной можно переходить к коннекту. memset(&tgt,0,sizeof(struct sockaddr_in)); tgt.sin_port = htons(port); //Указываем порт сервера tgt.sin_family = AF_INET; //Тип протокола tgt.sin_addr.s_addr = ip; //Адрес сервера Вызов функции memset затирает структуру tgt нулями. Дело в том, что дальше по коду мы будем использовать сокетовую структуру (это и есть tgt - сокращение от английского слова "target", что означает "цель"), а для этого нужно ее очистить (затереть нулями), чтобы в неинициализированных компонентах не осталось никакого мусора. Далее заполняем структуру, а именно: 1. Заносим в структуру номер порта, куда будем соединяться. 2. Указываем на семейство используемой адресации, в нашем случае это асинхронная работа. 3. Заносим адрес сервера, с которым мы хотим соединяться. После того, как сокетовая структура была инициализирована нужными значениями, мы вызываем функцию connect(), с помощью которой происходит соединение (сокет становится готовым к эксплуатации). |