Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ fakehttp -h www.example.com -i eth0
```
Usage: fakehttp [options]

Basic Options:
-h <hostname> hostname for obfuscation
Interface Options:
-a work on all network interfaces (ignores -i)
-i <interface> work on specified network interface

Payload Options:
-b <file> use TCP payload from binary file
-e <hostname> hostname for HTTPS obfuscation
-h <hostname> hostname for HTTP obfuscation

General Options:
-0 process inbound connections
-1 process outbound connections
Expand All @@ -32,8 +37,6 @@ General Options:
-w <file> write log to <file> instead of stderr

Advanced Options:
-a work on all network interfaces (ignores -i)
-b <file> use TCP payload from binary file
-f skip firewall rules
-g disable hop count estimation
-m <mark> fwmark for bypassing the queue
Expand Down
2 changes: 1 addition & 1 deletion include/globvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
struct fh_context {
int exit;
FILE *logfp;
/* -b, -h */ struct payload_info *plinfo;
/* -b, -e, -h */ struct payload_info *plinfo;
/* -0 */ int inbound;
/* -1 */ int outbound;
/* -4 */ int use_ipv4;
Expand Down
1 change: 1 addition & 0 deletions include/payload.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
enum payload_type {
FH_PAYLOAD_END = 0,
FH_PAYLOAD_HTTP,
FH_PAYLOAD_HTTPS,
FH_PAYLOAD_CUSTOM
};

Expand Down
2 changes: 1 addition & 1 deletion src/globvar.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
struct fh_context g_ctx = {.exit = 0,
.logfp = NULL,

/* -b, -h */ .plinfo = NULL,
/* -b, -e, -h */ .plinfo = NULL,
/* -0 */ .inbound = 0,
/* -1 */ .outbound = 0,
/* -4 */ .use_ipv4 = 0,
Expand Down
16 changes: 11 additions & 5 deletions src/mainfun.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,15 @@ static void print_usage(const char *name)
static const char *usage_fmt =
"Usage: %s [options]\n"
"\n"
"Basic Options:\n"
" -h <hostname> hostname for obfuscation\n"
"Interface Options:\n"
" -a work on all network interfaces (ignores -i)\n"
" -i <interface> work on specified network interface\n"
"\n"
"Payload Options:\n"
" -b <file> use TCP payload from binary file\n"
" -e <hostname> hostname for HTTPS obfuscation\n"
" -h <hostname> hostname for HTTP obfuscation\n"
"\n"
"General Options:\n"
" -0 process inbound connections\n"
" -1 process outbound connections\n"
Expand All @@ -69,8 +74,6 @@ static void print_usage(const char *name)
" -w <file> write log to <file> instead of stderr\n"
"\n"
"Advanced Options:\n"
" -a work on all network interfaces (ignores -i)\n"
" -b <file> use TCP payload from binary file\n"
" -f skip firewall rules\n"
" -g disable hop count estimation\n"
" -m <mark> fwmark for bypassing the queue\n"
Expand Down Expand Up @@ -121,7 +124,7 @@ int main(int argc, char *argv[])

plinfo_cnt = iface_cnt = 0;

while ((opt = getopt(argc, argv, "0146ab:dfgh:i:km:n:r:st:w:x:y:z")) !=
while ((opt = getopt(argc, argv, "0146ab:de:fgh:i:km:n:r:st:w:x:y:z")) !=
-1) {
switch (opt) {
case '0':
Expand All @@ -145,6 +148,7 @@ int main(int argc, char *argv[])
break;

case 'b':
case 'e':
case 'h':
if (!optarg[0]) {
fprintf(stderr, "%s: value of -%c cannot be empty.\n",
Expand All @@ -169,6 +173,8 @@ int main(int argc, char *argv[])

g_ctx.plinfo[plinfo_cnt - 1].type = opt == 'b'
? FH_PAYLOAD_CUSTOM
: opt == 'e'
? FH_PAYLOAD_HTTPS
: FH_PAYLOAD_HTTP;
g_ctx.plinfo[plinfo_cnt - 1].info = optarg;
break;
Expand Down
127 changes: 127 additions & 0 deletions src/payload.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
#include "globvar.h"

#define BUFFLEN 1200
#define SET_BE16(a, u16) \
do { \
(a)[0] = (u16) >> (8); \
(a)[1] = (u16) & (0xff); \
} while (0)

struct payload_node {
uint8_t payload[BUFFLEN];
Expand All @@ -44,6 +49,60 @@ static const char *http_fmt =
"(KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\r\n"
"\r\n";

struct tls_ext_server_name_head {
uint8_t type[2];
uint8_t length[2];
uint8_t server_name_list_length[2];
uint8_t server_name_type;
uint8_t server_name_length[2];
};

struct tls_ext_padding_head {
uint8_t type[2];
uint8_t length[2];
};

static const struct tls_client_hello {
uint8_t data_01[11];
uint8_t random[32];
uint8_t session_id_length;
uint8_t session_id[32];
uint8_t data_02[39];
uint8_t data_sni[275];
} cli_hello_tmpl = {
.data_01 =
{
0x16, /* handshake */
0x03, 0x03, /* tlsv1.2 */
0x01, 0x81, /* length */
0x01, /* client hello */
0x00, 0x01, 0x7d, /* client hello length */
0x03, 0x03 /* tlsv1.2 */
},
.session_id_length = 32,
.data_02 =
{
0x00, 0x02, /* cipher suites length */
0xc0, 0x2b, /* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */
0x01, /* compression methods length */
0x00, /* null */
0x01, 0x32, /* extensions length */
0x00, 0x0a, /* ext. supported_groups */
0x00, 0x04, /* ext. length */
0x00, 0x02, /* list length */
0x00, 0x17, /* secp256r1 */
0x00, 0x0d, /* ext. signature_algorithms */
0x00, 0x04, /* ext. length */
0x00, 0x02, /* list length */
0x04, 0x03, /* ecdsa_secp256r1_sha256 */
0x00, 0x10, /* ext. alpn */
0x00, 0x0b, /* ext. length */
0x00, 0x09, /* alpn length */
0x08, /* alpn string length */
'h', 't', 't', 'p', '/', '1', '.', '1' /* alpn string */
},
};

static struct payload_node *current_node;

static int make_http_get(uint8_t *buffer, size_t *len, char *hostname)
Expand All @@ -67,6 +126,64 @@ static int make_http_get(uint8_t *buffer, size_t *len, char *hostname)
}


static int make_tls_client_hello(uint8_t *buffer, size_t *len, char *hostname)
{
int padding_len;
size_t i, buffsize;
struct tls_client_hello *tls_data;
struct tls_ext_server_name_head *server_name_head;
struct tls_ext_padding_head *padding_head;

buffsize = *len;

if (buffsize < (int) sizeof(*tls_data)) {
E("ERROR: buffer is too small");
return -1;
}

tls_data = (struct tls_client_hello *) buffer;
memcpy(tls_data, &cli_hello_tmpl, sizeof(cli_hello_tmpl));

for (i = 0; i < sizeof(tls_data->random); i++) {
tls_data->random[i] = rand();
}

for (i = 0; i < sizeof(tls_data->session_id); i++) {
tls_data->session_id[i] = rand();
}

size_t hostname_len = strlen(hostname);

padding_len = sizeof(tls_data->data_sni) -
sizeof(struct tls_ext_server_name_head) - strlen(hostname) -
sizeof(struct tls_ext_padding_head);

if (padding_len < 0) {
E("ERROR: hostname is too long");
return -1;
}

server_name_head = (struct tls_ext_server_name_head *) tls_data->data_sni;
SET_BE16(server_name_head->type, 0);
SET_BE16(server_name_head->length, hostname_len + 5);
SET_BE16(server_name_head->server_name_list_length, hostname_len + 3);
SET_BE16(server_name_head->server_name_length, hostname_len);
memcpy((uint8_t *) server_name_head + sizeof(*server_name_head), hostname,
hostname_len);

padding_head = (struct tls_ext_padding_head *) (tls_data->data_sni +
sizeof(*server_name_head) +
hostname_len);
SET_BE16(padding_head->type, 21);
SET_BE16(padding_head->length, padding_len);
memset((uint8_t *) padding_head + sizeof(*padding_head), 0, padding_len);

*len = sizeof(*tls_data);

return 0;
}


static int make_custom(uint8_t *buffer, size_t *len, char *filepath)
{
int res, len_, buffsize;
Expand Down Expand Up @@ -154,6 +271,16 @@ int fh_payload_setup(void)
node->payload_len = len;
break;

case FH_PAYLOAD_HTTPS:
len = sizeof(node->payload);
res = make_tls_client_hello(node->payload, &len, pinfo->info);
if (res < 0) {
E(T(make_custom));
goto cleanup;
}
node->payload_len = len;
break;

default:
E("ERROR: Unknown payload type");
goto cleanup;
Expand Down