Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
/* Copyright (C) 2012 Philipp Winter (
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <>.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define TIME_OFFSET 11
#define RAND_OFFSET 15
#define RAND_LENGTH 28
/* A sample TLS client hello as sent by recent Tor clients
* (i.e. before March 2012).
* The cipher list inside the client hello should trigger
* chinese active scanning.
char client_hello[] = {
0x16, 0x03, 0x01, 0x00, 0xcc, 0x01, 0x00, 0x00, 0xc8,
0x03, 0x01, 0x4f, 0x12, 0xe5, 0x63, 0x3f, 0xef, 0x7d,
0x20, 0xb9, 0x94, 0xaa, 0x04, 0xb0, 0xc1, 0xd4, 0x8c,
0x50, 0xcd, 0xe2, 0xf9, 0x2f, 0xa9, 0xfb, 0x78, 0xca,
0x02, 0xa8, 0x73, 0xe7, 0x0e, 0xa8, 0xf9, 0x00, 0x00,
0x3a, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x39, 0x00, 0x38,
0xc0, 0x0f, 0xc0, 0x05, 0x00, 0x35, 0xc0, 0x07, 0xc0,
0x09, 0xc0, 0x11, 0xc0, 0x13, 0x00, 0x33, 0x00, 0x32,
0xc0, 0x0c, 0xc0, 0x0e, 0xc0, 0x02, 0xc0, 0x04, 0x00,
0x04, 0x00, 0x05, 0x00, 0x2f, 0xc0, 0x08, 0xc0, 0x12,
0x00, 0x16, 0x00, 0x13, 0xc0, 0x0d, 0xc0, 0x03, 0xfe,
0xff, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x65,
0x00, 0x00, 0x00, 0x1d, 0x00, 0x1b, 0x00, 0x00, 0x18,
0x77, 0x77, 0x77, 0x2e, 0x67, 0x6e, 0x6c, 0x69, 0x67,
0x78, 0x7a, 0x70, 0x79, 0x76, 0x6f, 0x35, 0x66, 0x76,
0x6b, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x0b, 0x00,
0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34,
0x00, 0x32, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08,
0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00,
0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11,
0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00,
0x16, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x23,
0x00, 0x00
int main( int argc, char **argv ) {
int sockfd = 0;
struct sockaddr_in srvaddr;
struct hostent *srv;
char buf[32];
int i = 0;
if (argc != 3) {
fprintf(stderr, "\nUsage: %s <host> <port>\n\n", argv[0]);
return 1;
/* update time */
*((time_t *) (client_hello+TIME_OFFSET)) = htonl(time(NULL));
/* update rand value */
for (i = 0; i < RAND_LENGTH; i++) {
*(client_hello + RAND_OFFSET + i) = rand();
/* update server_name extension */
for (i = 0; i < SERVER_NAME_LENGTH; i++) {
*(client_hello + SERVER_NAME_OFFSET + i) = (rand() % 26) + 97;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Error while calling socket():");
return 2;
srv = gethostbyname(argv[1]);
bzero((char *) &srvaddr, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
bcopy((char *) srv->h_addr, (char *) &srvaddr.sin_addr.s_addr,
srvaddr.sin_port = htons(atoi(argv[2]));
if (connect(sockfd, (struct sockaddr *) &srvaddr, sizeof(srvaddr)) == -1) {
perror("Error while calling connect():");
return 3;
/* send TLS client hello */
write(sockfd, client_hello, sizeof(client_hello));
/* wait for the reply so we don't close the connection immediately */
read(sockfd, buf, sizeof(buf));
return 0;