Skip to content

Commit b48f06e

Browse files
feat: Add fake HTTPS support
1 parent fccdefa commit b48f06e

File tree

6 files changed

+148
-11
lines changed

6 files changed

+148
-11
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,15 @@ fakehttp -h www.example.com -i eth0
1717
```
1818
Usage: fakehttp [options]
1919
20-
Basic Options:
21-
-h <hostname> hostname for obfuscation
20+
Interface Options:
21+
-a work on all network interfaces (ignores -i)
2222
-i <interface> work on specified network interface
2323
24+
Payload Options:
25+
-b <file> use TCP payload from binary file
26+
-e <hostname> hostname for HTTPS obfuscation
27+
-h <hostname> hostname for HTTP obfuscation
28+
2429
General Options:
2530
-0 process inbound connections
2631
-1 process outbound connections
@@ -32,8 +37,6 @@ General Options:
3237
-w <file> write log to <file> instead of stderr
3338
3439
Advanced Options:
35-
-a work on all network interfaces (ignores -i)
36-
-b <file> use TCP payload from binary file
3740
-f skip firewall rules
3841
-g disable hop count estimation
3942
-m <mark> fwmark for bypassing the queue

include/globvar.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
struct fh_context {
2929
int exit;
3030
FILE *logfp;
31-
/* -b, -h */ struct payload_info *plinfo;
31+
/* -b, -e, -h */ struct payload_info *plinfo;
3232
/* -0 */ int inbound;
3333
/* -1 */ int outbound;
3434
/* -4 */ int use_ipv4;

include/payload.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
enum payload_type {
2727
FH_PAYLOAD_END = 0,
2828
FH_PAYLOAD_HTTP,
29+
FH_PAYLOAD_HTTPS,
2930
FH_PAYLOAD_CUSTOM
3031
};
3132

src/globvar.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
struct fh_context g_ctx = {.exit = 0,
2727
.logfp = NULL,
2828

29-
/* -b, -h */ .plinfo = NULL,
29+
/* -b, -e, -h */ .plinfo = NULL,
3030
/* -0 */ .inbound = 0,
3131
/* -1 */ .outbound = 0,
3232
/* -4 */ .use_ipv4 = 0,

src/mainfun.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,15 @@ static void print_usage(const char *name)
5454
static const char *usage_fmt =
5555
"Usage: %s [options]\n"
5656
"\n"
57-
"Basic Options:\n"
58-
" -h <hostname> hostname for obfuscation\n"
57+
"Interface Options:\n"
58+
" -a work on all network interfaces (ignores -i)\n"
5959
" -i <interface> work on specified network interface\n"
6060
"\n"
61+
"Payload Options:\n"
62+
" -b <file> use TCP payload from binary file\n"
63+
" -e <hostname> hostname for HTTPS obfuscation\n"
64+
" -h <hostname> hostname for HTTP obfuscation\n"
65+
"\n"
6166
"General Options:\n"
6267
" -0 process inbound connections\n"
6368
" -1 process outbound connections\n"
@@ -69,8 +74,6 @@ static void print_usage(const char *name)
6974
" -w <file> write log to <file> instead of stderr\n"
7075
"\n"
7176
"Advanced Options:\n"
72-
" -a work on all network interfaces (ignores -i)\n"
73-
" -b <file> use TCP payload from binary file\n"
7477
" -f skip firewall rules\n"
7578
" -g disable hop count estimation\n"
7679
" -m <mark> fwmark for bypassing the queue\n"
@@ -121,7 +124,7 @@ int main(int argc, char *argv[])
121124

122125
plinfo_cnt = iface_cnt = 0;
123126

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

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

170174
g_ctx.plinfo[plinfo_cnt - 1].type = opt == 'b'
171175
? FH_PAYLOAD_CUSTOM
176+
: opt == 'e'
177+
? FH_PAYLOAD_HTTPS
172178
: FH_PAYLOAD_HTTP;
173179
g_ctx.plinfo[plinfo_cnt - 1].info = optarg;
174180
break;

src/payload.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
#include "globvar.h"
3030

3131
#define BUFFLEN 1200
32+
#define SET_BE16(a, u16) \
33+
do { \
34+
(a)[0] = (u16) >> (8); \
35+
(a)[1] = (u16) & (0xff); \
36+
} while (0)
3237

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

52+
struct tls_ext_server_name_head {
53+
uint8_t type[2];
54+
uint8_t length[2];
55+
uint8_t server_name_list_length[2];
56+
uint8_t server_name_type;
57+
uint8_t server_name_length[2];
58+
};
59+
60+
struct tls_ext_padding_head {
61+
uint8_t type[2];
62+
uint8_t length[2];
63+
};
64+
65+
static const struct tls_client_hello {
66+
uint8_t data_01[11];
67+
uint8_t random[32];
68+
uint8_t session_id_length;
69+
uint8_t session_id[32];
70+
uint8_t data_02[39];
71+
uint8_t data_sni[275];
72+
} cli_hello_tmpl = {
73+
.data_01 =
74+
{
75+
0x16, /* handshake */
76+
0x03, 0x03, /* tlsv1.2 */
77+
0x01, 0x81, /* length */
78+
0x01, /* client hello */
79+
0x00, 0x01, 0x7d, /* client hello length */
80+
0x03, 0x03 /* tlsv1.2 */
81+
},
82+
.session_id_length = 32,
83+
.data_02 =
84+
{
85+
0x00, 0x02, /* cipher suites length */
86+
0xc0, 0x2b, /* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */
87+
0x01, /* compression methods length */
88+
0x00, /* null */
89+
0x01, 0x32, /* extensions length */
90+
0x00, 0x0a, /* ext. supported_groups */
91+
0x00, 0x04, /* ext. length */
92+
0x00, 0x02, /* list length */
93+
0x00, 0x17, /* secp256r1 */
94+
0x00, 0x0d, /* ext. signature_algorithms */
95+
0x00, 0x04, /* ext. length */
96+
0x00, 0x02, /* list length */
97+
0x04, 0x03, /* ecdsa_secp256r1_sha256 */
98+
0x00, 0x10, /* ext. alpn */
99+
0x00, 0x0b, /* ext. length */
100+
0x00, 0x09, /* alpn length */
101+
0x08, /* alpn string length */
102+
'h', 't', 't', 'p', '/', '1', '.', '1' /* alpn string */
103+
},
104+
};
105+
47106
static struct payload_node *current_node;
48107

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

69128

129+
static int make_tls_client_hello(uint8_t *buffer, size_t *len, char *hostname)
130+
{
131+
int padding_len;
132+
size_t i, buffsize;
133+
struct tls_client_hello *tls_data;
134+
struct tls_ext_server_name_head *server_name_head;
135+
struct tls_ext_padding_head *padding_head;
136+
137+
buffsize = *len;
138+
139+
if (buffsize < (int) sizeof(*tls_data)) {
140+
E("ERROR: buffer is too small");
141+
return -1;
142+
}
143+
144+
tls_data = (struct tls_client_hello *) buffer;
145+
memcpy(tls_data, &cli_hello_tmpl, sizeof(cli_hello_tmpl));
146+
147+
for (i = 0; i < sizeof(tls_data->random); i++) {
148+
tls_data->random[i] = rand();
149+
}
150+
151+
for (i = 0; i < sizeof(tls_data->session_id); i++) {
152+
tls_data->session_id[i] = rand();
153+
}
154+
155+
size_t hostname_len = strlen(hostname);
156+
157+
padding_len = sizeof(tls_data->data_sni) -
158+
sizeof(struct tls_ext_server_name_head) - strlen(hostname) -
159+
sizeof(struct tls_ext_padding_head);
160+
161+
if (padding_len < 0) {
162+
E("ERROR: hostname is too long");
163+
return -1;
164+
}
165+
166+
server_name_head = (struct tls_ext_server_name_head *) tls_data->data_sni;
167+
SET_BE16(server_name_head->type, 0);
168+
SET_BE16(server_name_head->length, hostname_len + 5);
169+
SET_BE16(server_name_head->server_name_list_length, hostname_len + 3);
170+
SET_BE16(server_name_head->server_name_length, hostname_len);
171+
memcpy((uint8_t *) server_name_head + sizeof(*server_name_head), hostname,
172+
hostname_len);
173+
174+
padding_head = (struct tls_ext_padding_head *) (tls_data->data_sni +
175+
sizeof(*server_name_head) +
176+
hostname_len);
177+
SET_BE16(padding_head->type, 21);
178+
SET_BE16(padding_head->length, padding_len);
179+
memset((uint8_t *) padding_head + sizeof(*padding_head), 0, padding_len);
180+
181+
*len = sizeof(*tls_data);
182+
183+
return 0;
184+
}
185+
186+
70187
static int make_custom(uint8_t *buffer, size_t *len, char *filepath)
71188
{
72189
int res, len_, buffsize;
@@ -154,6 +271,16 @@ int fh_payload_setup(void)
154271
node->payload_len = len;
155272
break;
156273

274+
case FH_PAYLOAD_HTTPS:
275+
len = sizeof(node->payload);
276+
res = make_tls_client_hello(node->payload, &len, pinfo->info);
277+
if (res < 0) {
278+
E(T(make_custom));
279+
goto cleanup;
280+
}
281+
node->payload_len = len;
282+
break;
283+
157284
default:
158285
E("ERROR: Unknown payload type");
159286
goto cleanup;

0 commit comments

Comments
 (0)