Сокс5-бот Delphi (непонятка)

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Faost, 9 May 2010.

  1. Faost

    Faost New Member

    Joined:
    11 Jul 2009
    Messages:
    18
    Likes Received:
    3
    Reputations:
    0
    Здравствуйте, есть самый обыкновенный сокс-бот. Пускай, это opensc.ws/samples/9013-usocks5.html
    (ниже - копипаст этого кода в "боевом" варианте: прописываем в настройках для коннекта через сокс IP 127.0.0.1 и порт 8088)

    program BSSocks;
    {
    +-----------------------------------------------------------+
    |name: uSocks5 |
    |description: etablishes a SOCKS5 server, supporting AUTH |
    |Author: Hamtaro aka CorVu5 |
    |date: 16.10.09 / released: 24.10.09 |
    |History: first try |
    |ToDo: |
    |[*] Add support for Proxychains (!) & UDP (?) |
    |[*] Add support for IPv6 |
    +-----------------------------------------------------------+
    | This code can be changed or used without any restrictions |
    | Leben heiA~Y"t ein Bild malen, nicht eine Summe ziehen |
    +-----------------------------------------------------------+
    }
    uses Windows, WinSock;

    type
    TSocks5Config = record
    Port : Dword;
    UserName : String;
    Password : String;
    end;
    type PSocks5Config = ^TSocks5Config;
    type
    TSocks5MethodSel = record
    Version : Byte;
    nMethods : Byte;
    Methods : array[0..255] of Byte;
    end;

    type TSocks5Request = record
    ucVersion : byte;
    ucCommand : byte;
    ucRzv : byte;
    ucAtyp : byte;
    dwDestIp : dword;
    wDestPort : word;
    end;

    //function StartSocks5(conf : PSocks5Config) : Boolean; stdcall;
    var
    config : TSocks5Config;
    procedure SocksProc(sock : Cardinal); stdcall;
    var
    m : TSocks5MethodSel;
    req : TSocks5Request;
    auth :array[0..600] of Byte;
    buf :array[0..500] of Byte;
    buffer : array[0..4095] of Byte;//4kb
    recv_len : Integer;
    i : Integer;
    recvsock : TSocket;
    UserName, password : String;
    tunneladdr_in : sockaddr_in;
    tunneldomain : String;
    tunnelsock : TSocket;
    hostent : PHostEnt;
    tv : Ttimeval;
    fset : tfdset;
    self_addr : sockaddr_in;
    self_Len : Integer;
    begin
    recvsock := sock;
    if recv(recvsock,m,2,MSG_PEEK) > 0 then begin
    if m.Version = 5 then begin //it is socks5
    recv(recvsock,m, 2 + m.nMethods,0); //request complete Header
    for i := 0 to m.nMethods - 1 Do begin
    if (m.Methods = 2) then begin //password auth
    if (config.UserName = '') and (config.Password = '') then begin
    m.nMethods := $00;
    send(recvsock, m,2,0);
    end else begin
    m.nMethods := 2;
    send(recvsock, m,2,0);
    recv(recvsock, auth,SizeOf(auth),0);
    if auth[0] = 1 Then begin
    //get username
    SetString(username,Pchar(@auth[2]),auth[1]);
    //get password
    SetString(password,Pchar(Cardinal(@auth) + 3 + auth[1]),auth[2 + auth[1]]);
    if (config.UserName = UserName) and (config.Password = password) then begin //auth successful!
    auth[1] := 0;
    send(recvsock,auth,2,0);
    end else begin
    MessageBox(0,'auth fail','fffuuuuuuu-',0);
    auth[1] := $FF; //nothing but fail
    send(recvsock,auth,2,0);
    break;
    end;
    end;
    end;
    end else if (m.Methods = 0) Then begin
    if (config.password = '') and (config.UserName = '') Then begin
    m.nMethods := 0;
    send(recvsock,m,2,0);
    end else begin
    m.nMethods := $FF;
    send(recvsock,m,2,0);
    break;
    end;
    end else if i = m.nMethods then begin
    m.nMethods := $FF;
    send(recvsock,m,2,0);
    Break;
    end;
    recv(recvsock, req, sizeof(Tsocks5Request), MSG_PEEK);
    if req.ucCommand = 1 then begin //TCP Verbindung, ok
    Zeromemory(@tunneladdr_in,sizeof(tunneladdr_in));
    if req.ucAtyp = 1 Then begin //ip4
    recv(recvsock, req, sizeof(Tsocks5Request), 0);
    tunneladdr_in.sin_port := req.wDestPort;
    CopyMemory(@tunneladdr_in.sin_addr,@req.dwDestIp,sizeof(tunneladdr_in.sin_addr));
    end else if req.ucAtyp = 3 Then begin //domain name
    ZeroMemory(@buf,SizeOf(buf));
    recv(recvsock,buf,7 + Byte(req.dwDestIp),0);
    SetString(tunneldomain,PChar(Cardinal(@buf) + 5),Integer(Byte(req.dwDestIp)));
    hostent := gethostbyname(PChar(tunneldomain));
    PInteger(@tunneladdr_in.sin_addr.S_addr)^:=PInteger(HostEnt.h_addr^)^;
    tunneladdr_in.sin_port := htons(Word(Pointer(Cardinal(@buf) + 6 + Byte(req.dwDestIp))^));
    end; //todo: PIv6
    tunneladdr_in.sin_family := AF_INET;
    tunnelsock := socket(PF_INET, SOCK_STREAM, 0);
    if connect(tunnelsock,tunneladdr_in,sizeof(tunneladdr_in)) = 0 Then begin//success!
    req.ucCommand := 0; //success
    end else begin
    req.ucCommand := 1; //General Failure reporting in
    end;
    req.ucVersion := 5;
    req.ucRzv := 0;
    req.ucAtyp := 1;
    ZeroMemory(@self_addr,SizeOf(sockaddr_in));
    self_Len := SizeOf(sockaddr_in);
    getsockname(tunnelsock,self_addr,self_len);
    CopyMemory(@req.dwDestIp,@self_addr.sin_addr,sizeof(self_addr.sin_addr));
    req.wDestPort := self_addr.sin_port;
    send(recvsock,req,10,0);
    //now tunneling everything!
    tv.tv_sec := 5;
    while 1 =1 Do begin
    //waiting for incoming data
    FD_ZERO(fset);
    FD_SET(recvsock,fset);
    FD_SET(tunnelsock,fset);
    if select(0,@fset,nil,nil,nil) <> SOCKET_ERROR Then begin
    if FD_ISSET(tunnelsock,fset) THEN begin //data on the recvsock
    ZeroMemory(@buffer,sizeof(buffer));
    // MessageBoxa(0,'Data from the tunnelsock!','FF',0);
    recv_len := recv(tunnelsock, buffer,sizeof(buffer),0);
    if recv_len = SOCKET_ERROR Then break; //error?
    // messagebox(0,PChar('tunnel' + #13#10 + pchar(@buffer)),0,0);
    send(recvsock,buffer,recv_len,0);
    end;
    if FD_ISSET(recvsock,fset) THEN begin //data on the recvsock
    ZeroMemory(@buffer,sizeof(buffer));
    // MessageBoxa(0,'Data from the recvsock!','FF',0);
    recv_len := recv(recvsock, buffer,sizeof(buffer),0);
    if recv_len = SOCKET_ERROR Then break; //error?
    // messagebox(0,PChar('recv' + #13#10 + pchar(@buffer)),0,0);
    send(tunnelsock,buffer,recv_len,0);
    end;
    end;
    Sleep(150); //zzZZzzZZZZzz
    end;
    end;
    Break;
    end;
    end;
    end;
    // MessageBox(0,PChar('Error Code: ' + inttostr(WSAGetLastError)),'Error!',0);
    closesocket(recvsock);
    closesocket(tunnelsock);
    end;

    function GoSocks5(conf : PSocks5Config) : Boolean; stdcall;
    var
    wsaData : TWSAData;
    sock : TSOCKET;
    sockaddr: SockAddr_in;
    conn : Integer;
    client : TSockAddr;
    tid : Cardinal;
    size : Integer;
    begin
    result := false;
    Move(conf^,config,SizeOf(TSocks5Config));
    WSAStartup($101, wsaData);
    sock := socket(AF_INET,SOCK_STREAM,0);
    if (Sock = INVALID_SOCKET) then
    exit;
    ZeroMemory(@SockAddr, sizeof(SockAddr));
    sockaddr.sin_family := AF_INET;
    sockaddr.sin_port := htons(config.Port);
    sockaddr.sin_addr.S_addr := inet_addr('127.0.0.1');
    if bind (sock, sockaddr, SizeOf(sockaddr)) = 0 then
    if (listen(sock,SOMAXCONN) = 0) then begin
    while 1 = 1 Do begin
    size := SizeOf(client);
    conn := accept(sock,@client,@size);
    if conn <> SOCKET_ERROR then begin
    CreateThread(nil,0,@SocksProc,Pointer(conn),0,tid);
    end;
    Sleep(100);
    end;
    end;

    end;


    var
    configs : TSocks5config;
    tid: Cardinal;
    begin
    configs.Port := 8088;
    configs.UserName := pchar('');
    configs.Password := pchar('');
    CreateThread(0,0,@GoSocks5,@configs,0,tid);
    sleep(infinite);
    end.



    На первый взгляд, не смотря на то, что код немного "стремный", функционал по работе с сокс5 вроде правильный, и если прописывать настройки сокса в самом браузере (например, в firefox), то все работает как надо, но вот если прописать эти же настройки в каком-нибудь соксификаторе (FreeCap, Permeo Security Driver, Proxifier) и подогнать под него браузер, то при работе со страницами, где много контента (например, вконтакт), часть его не грузится, т.е. может загрузиться лишь часть фоток, картинок, также некоторые js скрипты могут не загрузиться и т.д.
    Собсно буду благодарен за любой намек и любую подсказку (только правильную, а не "я думаю, может..." =) ), т.к. времени оч.мало сейчас, а хотелось бы уж сделать. Из-за чего так, и как можно устранить данную проблему? (Причем, эту проблему наблюдал в нескольких сокс-ботах).
    А если еще приведете код, вообще будет хорошо (отблагодарю символической суммой вечнозеленых).
    Также, если уж здесь трудно устранить, буду благодарен за исходник бота, где этой проблемы нету. Спасибо.