简体   繁体   English

尝试使用boost :: asio连接到SOCKS 5服务器,但我的连接请求格式错误

[英]Trying to connect to a SOCKS 5 server using boost::asio but my connection request turns out malformed

I'm trying to establish a SOCKS 5 connection (to a tor proxy) in my code but my connection request (after greeting and auth method choose) is completely malformed for some reason. 我正在尝试在我的代码中建立SOCKS 5连接(到tor代理),但是由于某种原因,我的连接请求(在greeting和auth方法选择之后)完全错误。

I tried using gdb to look at values in-memory but that looks fine. 我尝试使用gdb来查看内存中的值,但这看起来还不错。 also tried printing info to console which gave me nothing too. 还尝试将信息打印到控制台,这也没有给我任何帮助。

(the onion site address is just an example) (洋葱站点地址仅是示例)

main.cpp https://pastebin.com/zjHb7vg3 main.cpp https://pastebin.com/zjHb7vg3

socks5.hpp https://pastebin.com/pksnqmfa Or jsut the func creating the packet socks5.hpp https://pastebin.com/pksnqmfa或jsut创建数据包的功能

std::vector<boost::asio::const_buffer> conn(unsigned char cmd, unsigned char type, std::string hostname, int port) {
            int cmd_ = 0x04;
            int type_ = 0x03;
            std::vector<boost::asio::const_buffer> buffers = {
                //{
                    boost::asio::buffer(&version, 1),
                    boost::asio::buffer(&cmd_, 1),
                    boost::asio::buffer(&null_byte, 1),
                    boost::asio::buffer(&type_, 1)
                //}
            };

            std::cout << "Conn:" << cmd << std::endl << "type:" << type << std::endl;

            if (type_ == IPv4) {
                int byte1=0x5d, byte2=0xb8, byte3=0xd8, byte4=0x22;
                char dot;
                std::istringstream s(hostname);  // input stream that now contains the ip address string

                //s >> byte1 >> dot >> byte2 >> dot >> byte3 >> dot >> byte4 >> dot;
                // buffers.push_back(boost::asio::buffer({
                //     (unsigned char)byte1,
                //     (unsigned char)byte2,
                //     (unsigned char)byte3,
                //     (unsigned char)byte4
                // }));
                buffers.push_back(boost::asio::buffer(&byte1, 1));    
                buffers.push_back(boost::asio::buffer(&byte2, 1));            
                buffers.push_back(boost::asio::buffer(&byte3, 1));            
                buffers.push_back(boost::asio::buffer(&byte4, 1));            

            } else if (type_ == IPv6) {
                int byte1,
                    byte2,
                    byte3,
                    byte4,
                    byte5,
                    byte6,
                    byte7,
                    byte8,
                    byte9,
                    byte10,
                    byte11,
                    byte12,
                    byte13,
                    byte14,
                    byte15,
                    byte16;
                char sep;
                std::istringstream s(hostname);  // input stream that now contains the ip address string

                s >> 
                    byte1 >> sep >>
                    byte2 >> sep >>
                    byte3 >> sep >>
                    byte4 >> sep >>
                    byte5 >> sep >>
                    byte6 >> sep >>
                    byte7 >> sep >>
                    byte8 >> sep >>
                    byte9 >> sep >>
                    byte10 >> sep >>
                    byte11 >> sep >>
                    byte12 >> sep >>
                    byte13 >> sep >>
                    byte14 >> sep >>
                    byte15 >> sep >>
                    byte16;

                buffers.push_back(boost::asio::buffer({
                    (unsigned char)byte1,
                    (unsigned char)byte2,
                    (unsigned char)byte3,
                    (unsigned char)byte4,
                    (unsigned char)byte5,
                    (unsigned char)byte6,
                    (unsigned char)byte7,
                    (unsigned char)byte8,
                    (unsigned char)byte9,
                    (unsigned char)byte10,
                    (unsigned char)byte11,
                    (unsigned char)byte12,
                    (unsigned char)byte13,
                    (unsigned char)byte14,
                    (unsigned char)byte15,
                    (unsigned char)byte16
                }));
            } else if (type_ == Domain) {
                int hostnameLen = hostname.length();
                buffers.push_back(boost::asio::buffer(&hostnameLen, 1));
                buffers.push_back(boost::asio::buffer(hostname, 255));

                std::cout << hostnameLen << std::endl << hostname << std::endl;
            }

            unsigned char port_high_byte_ = (port >> 8) & 0xff;
            unsigned char port_low_byte_ = port & 0xff;

            buffers.push_back(boost::asio::buffer(&port_high_byte_, 1));
            buffers.push_back(boost::asio::buffer(&port_low_byte_, 1));

            std::cout << buffers[0].data();
            return buffers;
        }            

};

class reply {

    private:
        int hostnameLen;
        int hostname;
        int port_nbo;

        enum state {
            AUTH_CHOICE = 0,
            PASSWORD = 1,
            CONNECT = 2
        };

        state state;

    public:

        unsigned char ver;
        unsigned char auth;
        unsigned char auth_ver;
        unsigned char status_;
        addr_type type;

        bool success() {
            return ver == version &&
                (state == AUTH_CHOICE ? state == NO_AUTH || state == PASSWORD : true) &&
                (state == PASSWORD ? status_ == 0x00 : true) &&
                (state == CONNECT ? status_ == 0x00 : true);
        }

        std::string status() const {
            if (state == AUTH_CHOICE) {
                if (auth == 0xFF) {
                    return "No acceptable auth methods";
                }
            } else if (state == PASSWORD) {
                return status_ == 0x00 ? "Auth success" : "Auth error: "+std::to_string(status_);
            } else if (state == CONNECT) {
                return status_ == 0x00 ? "Connect success" : "Connect error: "+std::to_string(status_);
            }
            return "";
        }

        std::array<boost::asio::mutable_buffer, 5> auth_choice() {
            state = AUTH_CHOICE;
            return {
                {
                    boost::asio::buffer(&ver, 1),
                    boost::asio::buffer(&auth, 1)
                }
            };
        }

        std::array<boost::asio::mutable_buffer, 5> password_verif() {
            state = PASSWORD;
            return {
                {
                    boost::asio::buffer(&auth_ver, 1),
                    boost::asio::buffer(&status_, 1)
                }
            };
        }

        std::vector<boost::asio::mutable_buffer> connect_reply() {
            state = CONNECT;
            std::vector<boost::asio::mutable_buffer> buffers = {
                {
                    boost::asio::buffer(&ver, 1),
                    boost::asio::buffer(&status_, 1),
                    boost::asio::buffer(&null_byte, 1),
                    boost::asio::buffer(&type, 1)
                }
            };

            if (type == IPv4) {
                buffers.push_back(boost::asio::buffer(&hostname, 4));
            } else if (type == IPv6) {
                buffers.push_back(boost::asio::buffer(&hostname, 16));
            } else if (type == Domain) {
                buffers.push_back(boost::asio::buffer(&hostnameLen, 1));
                buffers.push_back(boost::asio::buffer(&hostname, 255));
            }

            buffers.push_back(boost::asio::buffer(&port_nbo, 2));

            return buffers;
        }         

wireshark capture: (use the view filter "socks") https://quickfileshare.org/1Kjr/socks-capture.pcapng wirehark捕获:(使用视图过滤器“ socks”) https://quickfileshare.org/1Kjr/socks-capture.pcapng

boost::asio::write(socket, socks_request.conn(socks5::request::connect, socks5::addr_type::Domain, hostname, port));

we can split this code into: 我们可以将此代码拆分为:

[1] get buffers
std::vector<boost::asio::const_buffer> buffs = 
socks_request.conn(socks5::request::connect, socks5::addr_type::Domain, hostname, port);
[2] send data
boost::asio::write(socket, buffs);

in conn we have a lot local variables, which are passed into boost::asio::buffer . conn我们有很多局部变量,这些变量被传递给boost::asio::buffer What does buffer do ? buffer什么作用? It returns wrapper for data details here , which consists of pointer to data and length of data. 在此处返回包装器以获取数据详细信息 ,该包装器由pointer to datapointer to data长度组成。 No data are copied . 没有数据被复制 So when conn ends, you have vector of buffers which refer to data which was destroyed - undefined behaviour. 因此,当conn结束时,您将拥有缓冲区向量,这些向量引用了被破坏的数据-未定义的行为。

You need to find new approach to send data, or provide that data are valid when boost::asio::write uses buffer to them. 您需要找到一种发送数据的新方法,或者在boost::asio::write对它们使用缓冲区时提供有效的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM