Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Работа с цепочкой Socks-проксей. (https://forum.antichat.xyz/showthread.php?t=25613)

TaNkist 19.10.2006 13:06

Работа с цепочкой Socks-проксей.
 
Работа с цепочкой SOCKS-проксей.

Не мне тебе объяснять, что значит анонимность для хакера. Ты, наверное, не раз задумывался о лучшем способе ее сохранения. Не самый лучший, но, безусловно, самый популярный – это использование цепочки SOCKS-серверов. Ведь если хотя бы одно звено-сервер из этой цепи не пишет логов, то у взломщика остаются неплохие шансы сохранить анонимность.
Итак, как ты уже догадался сегодня мы познакомимся с работой по передаче данных в цепочке SOCKS-проксей. Для того чтобы Socks-сервер соединился с нужным нам сайтом необходимо указать адрес сайта и его порт. Но сначала придется поприветствовать сервер и пройти аутентификацию (она не обязательна, и на большинстве анонимных соксах отсутствует).
[Приветствие] На этом этапе нужно отправить специальный пакет:
  • 1 байт – номер версии
  • 1 байт – количество методов (N)
  • N байт – перечисление методов

Т.к. мы будем работать с соксами 5 версии, то нужно послать $05, следующий байт – число поддерживаемых методов соединения / аутенфикации. За ним последовательность байт, описывающих эти самые методы. Мы не будем заморачиваться с аутенфикацией, поэтому напишем тут 00.
На это приветствие сокс отвечает двумя байтами: номером своей версии и выбранным методом. Если соксу ничего не понравилось, то второй байт будет равняться $FF, если мы получим $00, то можно смело продолжить работу.
[Соединение] на следующем этапе мы должны указать серверу с кем соединиться. Для этого нужно отправить такой пакет.
  • 1 байт – номер версии
  • 1 байт – команда
  • 1 байт – зарезервировано до лучших времен
  • 1 байт – тип адреса
  • N байт – адрес
  • 2 байта – порт

Для заполнения этого пакета я создал специальную структуру:
PHP код:

  request record  
    version
:byte;
    
cmd:byte;
    
null:byte;
    
typeofaddr:byte;
    
addr:integer;
    
port:word;
    
end

Байт команды у нас будет равен $01, это значит, что мы просто хотим соединиться (о других значениях следует прочитать в RFC).
Следующий байт всегда равен нулю.
Типом адреса может быть:
  • $01 – ip v4 адрес, заданный 4 байтами
  • $03 – Нерезолвленное имя хоста (всегда лучше резолвить удаленно, т.к. иначе ты можешь пропалить свой DNS-сервер).
  • $04 –ip v6 адрес

На это сокс-сервер вернет пакет той же структуры, но с другими значениями. Например. нерезолвленный хост станет ip-шником.
Если все прошло нормально, то socks переходит в прозрачный режим и начинает передовать все данные по адресу.
[Составляем цепочку] Теперь на практике разбирем, то о чем говорилось выше и реализуем минимальный функционал socks-клиента.
Информацию о соксах будем хранить в следующей структуре.
PHP код:

server record  
    ip
:integer;
    
port:word
    
end

Нужно заполнить структуру SockAddrIn, указав данные о первом соксе.
PHP код:

SockAddrIn.sin_addr.S_addr:=socks[0].ip;
      
SockAddrIn.sin_port:=Socks[0].port

Коннектимся к первому серверу
PHP код:

connect(FSocket,SockAddrIn,SizeOf(SockAddrIn)); 

Затем в цикле запускаем коннект к следующем соксам.
PHP код:

For i:=1 to sockcount do
    
begin
    send
(Fsocket,hello,SizeOf(hello),0);
    
recv(FSocket,ans,Sizeof(ans),0);
    if (
ans[0]<>$05) or (ans[1]<>$FFthen halt;
    
//Заполняем структуру req
    
req.version:=$05;
    
req.cmd:=$01;
    
req.null:=0;
    
req.typeofaddr:=$01;
    
req.addr:=socks[i].ip;
    
req.port:=socks[i].port;
    
send(Fsocket,req,sizeof(req),0);
    
recv(Fsocket,req,sizeof(req),0);
    
end

Вот мы и написали в общем-то нехитрый код для работы с SOCKS-проксями. Для более подробного изучения рекомендую прочитать RFC 1928, в котором описан протокол SOCKS 5. Напоследок, я выложу полный исходный код со всеми подробными комментариями.
PHP код:

program Sock5clinet;

uses
  Windows
,
  
WinSock;

type server record   //Структура для описания адресов соксов
    
ip:integer;//ip-адрес
    
port:word//порт
    
end;
    
request record  // Пакет для соединения с сервером
    
version:byte;     // номер версии
    
cmd:byte;         // команда
    
null:byte;        // зарезервировано до лучших времен
    
typeofaddr:byte;  // тип адреса
    
addr:integer;     // адрес
    
port:word;        // порт
    
end;



var
    
socks:array [0..4of server;
    
FSocket:Tsocket;
    
WSAData:TWSADATA;

procedure connecttoSocks(sockcount:integer);
var
    
i:byte;
    
ans:array[0..1of byte//Буфер для ответов сервера
    
SockAddrInTSockAddrIn;
    
hello:array [0..2]of char;//Буфер приветсвия
    
req:request;  //Структура в которой содержиться запрос на соединение
begin
  hello
:=#050100;//Последовательность байт 05, 01, 00
  
SockAddrIn.sin_addr.S_addr:=socks[0].ip;
  
SockAddrIn.sin_port:=Socks[0].port;
  
connect(FSocket,SockAddrIn,SizeOf(SockAddrIn));
  For 
i:=1 to sockcount do
    
begin
    send
(Fsocket,hello,SizeOf(hello),0);
    
recv(FSocket,ans,Sizeof(ans),0);
    if (
ans[0]<>$05) or (ans[1]<>$FFthen halt;
    
//Заполняем структуру req
    
req.version:=$05;
    
req.cmd:=$01;
    
req.null:=0;
    
req.typeofaddr:=$01;
    
req.addr:=socks[i].ip;
    
req.port:=socks[i].port;
    
send(Fsocket,req,sizeof(req),0);
    
recv(Fsocket,req,sizeof(req),0);
    
end
end;


begin

//Первый сокс
socks[0].ip:=inet_addr('127.0.0.1');
socks[0].port:=htons(80);
//Второй сокс
socks[1].ip:=inet_addr('127.0.0.1');
socks[1].port:=htons(81);
//Третий сокс
socks[2].ip:=inet_addr('127.0.0.1');
socks[2].port:=htons(82);
//Четвертый сокс
socks[3].ip:=inet_addr('127.0.0.1');
socks[3].port:=htons(83);
//Хост куда нужно подключиться
socks[4].ip:=inet_addr('127.0.0.1');
socks[4].port:=htons(110);
//Инициализируем WinSock
WSAStartUp($202,WSAData);
//Подготавляиваем сокет
FSocket:=socket(PF_INETSOCK_STREAMIPPROTO_TCP);
//Соединяемся по цепочке соксов с нужным хостом
connecttoSocks(4);

end



Время: 18:14