// CLIENT_SK5_V2 std::string hex_string(std::string hexstr) { std::string str = ""; str.resize((hexstr.size() + 1) / 2); for (size_t i = 0, j = 0; i < str.size(); i++, j++) { char at = '@'; str[i] = (hexstr[j] & at ? hexstr[j] + 9 : hexstr[j]) << 4, j++; str[i] |= (hexstr[j] & at ? hexstr[j] + 9 : hexstr[j]) & 0xF; } return str; } std::string string_hex(std::string str, const bool capital = false) { std::string hexstr = ""; hexstr.resize(str.size() * 2); static const char a = capital ? 0x40 : 0x60; for (size_t i = 0; i < str.size(); i++) { char c = (str[i] >> 4) & 0xF; hexstr[i * 2] = c > 9 ? (c - 9) | a : c | '0'; hexstr[i * 2 + 1] = (str[i] & 0xF) > 9 ? (str[i] - 9) & 0xF | a : str[i] & 0xF | '0'; } return hexstr; } std::string char_to_string(char x[], int size_recv) { int num_car = 0; int stop_while = size_recv; std::string output = ""; while (stop_while > 0) { output += x[num_car]; if (num_car < size_recv) { num_car++; } stop_while--; } return output; } long int hex_to_dec(std::string x) { return strtol(x.data(), NULL, 16); } typedef struct { SOCKET x; SOCKET y; BOOL VERBOSE_mode; int timeout_sec; int buf_size; } threaddata; void set_fds(int sock1, int sock2, fd_set* fds) { FD_ZERO(fds); FD_SET(sock1, fds); FD_SET(sock2, fds); } // MSG SOCKS5 char msg_auth_ok[] = { 0X05, 0X00 }; // VERSION SOCKS, AUTH MODE, OK char msg_ipv6_nok[] = { 0X05, 0X08, 0X00, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 }; // IPv6 not compt char msg_request_co_ok[] = { 0X05, 0X00, 0X00, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 }; // Request connect OK DWORD WINAPI sock5_gen(void* param) { threaddata* sub = (threaddata*)param; SOCKET sock_SK5 = sub->x; BOOL VERBOSE_mode = sub->VERBOSE_mode; int timeout_sec = sub->timeout_sec; int buf_size = sub->buf_size; char buf[5016]; // If changed, line 25 in main.cpp is a change too int version_sock = 0; // 5, 4, 0, ?? // Phase A = Version Socks, Send Msg Auth memset(buf, 0, sizeof(buf)); // Get Version Socks int size_recv_PA = recv(sock_SK5, buf, sizeof(buf), 0); if (size_recv_PA <= 0) { printf(EC("[!] size_recv_PA <= 0\n")); closesocket(sock_SK5); return 1; } version_sock = buf[0]; if (version_sock != 5) { printf(EC("[!] version_sock != 5\n")); closesocket(sock_SK5); return 1; } // Send msg_auth_ok int size_send_PA = send(sock_SK5, msg_auth_ok, sizeof(msg_auth_ok), 0); if (size_send_PA <= 0) { printf(EC("[!] size_send_PA <= 0\n")); closesocket(sock_SK5); return 1; } // Phase B = Mode Connect & Type Addr & Addr/Port memset(buf, 0, sizeof(buf)); int size_recv_PB = recv(sock_SK5, buf, sizeof(buf), 0); if (size_recv_PB <= 0) { printf(EC("[!] size_recv_PB <= 0\n")); closesocket(sock_SK5); return 1; } int mode_cmd = buf[1]; // Connect = 1, Bind = 2, UDP = 3 int type_addr = buf[3]; // IPv4 = 01, Domain Name = 03, IPv6 = 04 if (mode_cmd != 1) { printf(EC("[!] Bind/UDP not supported\n")); closesocket(sock_SK5); return 1; } std::string dest_ip = ""; // IP dest int dest_port = 0; // Port dest if (type_addr == 1) // IPv4 { std::string raw_demand = char_to_string(buf, size_recv_PB); // convert to string std::string str_ip_dest = raw_demand.substr(4, 11); // get IPv4 std::string str_port_dest = raw_demand.substr(8, 10); // get Port sockaddr_in svr = { 0 }; svr.sin_family = AF_INET; svr.sin_addr.s_addr = MAKELONG(MAKEWORD((buf[4] & 0xff), (buf[5] & 0xff)), MAKEWORD((buf[6] & 0xff), (buf[7] & 0xff))); dest_ip = inet_ntoa(svr.sin_addr); // IPv4 dest in string dest_port = hex_to_dec(string_hex(str_port_dest)); // port dest in long } if (type_addr == 3) // Domain Name { std::string raw_demand = char_to_string(buf, size_recv_PB); // convert to string int size_domain_name = buf[4]; // Get size Domain Name std::string str_domain_name; std::string str_port_dest; try { str_domain_name = raw_demand.substr(5, size_domain_name); // get domain_name str_port_dest = raw_demand.substr(5 + size_domain_name, 5 + size_domain_name + 2); // get Port dest_port = hex_to_dec(string_hex(str_port_dest)); // port dest in long } catch (const std::out_of_range& e) { printf(EC("[!] Out of Range\n")); } struct hostent* he_a; he_a = gethostbyname(str_domain_name.c_str()); if (he_a == NULL) // Error gethostbyname { printf(EC("[!] gethostbyname\n")); closesocket(sock_SK5); return 12; } else // Ok gethostbyname { dest_ip = inet_ntoa(*((struct in_addr*)he_a->h_addr_list[0])); } } if (type_addr == 4) // IPv6 { printf(EC("[!] IPv6 not supported\n")); int size_send_IPNOK = send(sock_SK5, msg_ipv6_nok, sizeof(msg_ipv6_nok), 0); if (size_send_IPNOK <= 0) // Send msg_ipv6_nok { closesocket(sock_SK5); return 1; } closesocket(sock_SK5); return 1; } // Phase C = Send Request Addr OK & Recv Request & Connect to TARGET SERVER int size_send_PC = send(sock_SK5, msg_request_co_ok, sizeof(msg_request_co_ok), 0); if (size_send_PC <= 0) // Send msg_request_co_ok { printf(EC("[!] size_send_PC <= 0\n")); closesocket(sock_SK5); return 1; } memset(buf, 0, sizeof(buf)); int size_recv_PC = recv(sock_SK5, buf, sizeof(buf), 0); if (size_recv_PC <= 0) { printf(EC("[!] size_recv_PC <= 0\n")); closesocket(sock_SK5); return 1; } SOCKET client_TARGET; // Socket Connection for TARGET struct sockaddr_in serveraddra_a; if ((client_TARGET = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) //open socket printf(EC("[!] socket() failed\n")); //connect memset(&serveraddra_a, 0, sizeof(serveraddra_a)); serveraddra_a.sin_family = AF_INET; serveraddra_a.sin_addr.s_addr = inet_addr(dest_ip.c_str()); serveraddra_a.sin_port = htons((unsigned short)dest_port); if (connect(client_TARGET, (struct sockaddr*)&serveraddra_a, sizeof(serveraddra_a)) == SOCKET_ERROR) { printf(EC("[!] connect() failed\n")); closesocket(sock_SK5); return 1; } if (send(client_TARGET, buf, size_recv_PC, 0) != size_recv_PC) printf(EC("[!] send() sent a different number of bytes than expected\n")); fd_set readfds; int result, nfds = max(sock_SK5, client_TARGET) + 1; set_fds(sock_SK5, client_TARGET, &readfds); // Set timeout for select timeval tv; tv.tv_sec = timeout_sec; tv.tv_usec = 0; memset(buf, 0, sizeof(buf)); while (TRUE) // SK5_BASE <-> SERVER_TARGET { if ((result = select(nfds, &readfds, 0, 0, &tv)) > 0) { if (FD_ISSET(sock_SK5, &readfds)) // SK5_BASE -> SERVER_TARGET { int recvd_A = 0; recvd_A = recv(sock_SK5, buf, buf_size, 0); if (recvd_A <= 0) { printf(EC("[!] recvd_A (%i) <= 0\n"), recvd_A); closesocket(sock_SK5); return 1; } int sendd_A = 0; send(client_TARGET, buf, recvd_A, 0); // SERVER_TARGET if (VERBOSE_mode) printf(EC("[+] A DATA RECV = %i | DATA SEND = %i\n"), recvd_A, sendd_A); } if (FD_ISSET(client_TARGET, &readfds)) // SERVER_TARGET -> SK5_BASE { int recvd_B = recv(client_TARGET, buf, buf_size, 0); if (recvd_B <= 0) { printf(EC("[!] recvd_B (%i) <= 0\n"), recvd_B); closesocket(sock_SK5); return 1; } int sendd_B = 0; sendd_B = send(sock_SK5, buf, recvd_B, 0); if (VERBOSE_mode) printf(EC("[+] B DATA RECV = %i | DATA SEND = %i\n"), recvd_B, sendd_B); } set_fds(sock_SK5, client_TARGET, &readfds); } else { printf(EC("[!] select > 0\n")); shutdown(client_TARGET, 2); closesocket(client_TARGET); closesocket(sock_SK5); return 12; } } shutdown(client_TARGET, 2); closesocket(client_TARGET); closesocket(sock_SK5); return 0; } static int create_sock_thread(void* s) { HANDLE handle; if (!(handle = CreateThread(NULL, 0, sock5_gen, s, 0, 0))) return 0; CloseHandle(handle); return 1; }