// Simple TCP knock client - sends single SYN packets without retries // Compile: cl /W4 /O2 knock_client.c /ws2_32.lib #include #include #include #include #pragma comment(lib, "ws2_32.lib") void knock_port(const char* ip, int port) { SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { printf("socket failed: %d\n", WSAGetLastError()); return; } // Set socket to close immediately after connect attempt BOOL dontlinger = FALSE; setsockopt(s, SOL_SOCKET, SO_DONTLINGER, (char*)&dontlinger, sizeof(dontlinger)); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons((unsigned short)port); inet_pton(AF_INET, ip, &addr.sin_addr); printf("Knocking on port %d...\n", port); // Connect will send SYN, and we close immediately after int result = connect(s, (struct sockaddr*)&addr, sizeof(addr)); // Give it a moment to send the packet Sleep(100); // Close immediately without retrying closesocket(s); if (result == SOCKET_ERROR) { printf(" Connection refused (expected - no listener)\n"); } else { printf(" Connected!\n"); } } int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: %s [port1 port2 port3 ...]\n", argv[0]); printf("Default ports: 7000 8000 9000\n"); return 1; } const char* ip = argv[1]; int ports[10]; int num_ports; if (argc > 2) { num_ports = argc - 2; for (int i = 0; i < num_ports && i < 10; i++) { ports[i] = atoi(argv[i + 2]); } } else { num_ports = 3; ports[0] = 7000; ports[1] = 8000; ports[2] = 9000; } WSADATA wsa; if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("WSAStartup failed\n"); return 1; } printf("Knocking on %s: ", ip); for (int i = 0; i < num_ports; i++) { printf("%d ", ports[i]); } printf("\n\n"); for (int i = 0; i < num_ports; i++) { knock_port(ip, ports[i]); if (i < num_ports - 1) { // Wait between knocks Sleep(500); } } printf("\nKnock sequence complete!\n"); printf("Now try connecting to port 31337\n"); WSACleanup(); return 0; }