mirror of
https://github.com/hufrea/byedpi.git
synced 2025-06-29 18:21:14 +00:00
Dynamic fake
This commit is contained in:
parent
c1bef73d42
commit
9eb9432af9
115
desync.c
115
desync.c
@ -95,14 +95,26 @@ static bool sock_has_notsent(int sfd)
|
|||||||
}
|
}
|
||||||
return tcpi.tcpi_notsent_bytes != 0;
|
return tcpi.tcpi_notsent_bytes != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *alloc_pktd(size_t n)
|
||||||
|
{
|
||||||
|
char *p = mmap(0, n, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||||
|
return p == MAP_FAILED ? 0 : p;
|
||||||
|
}
|
||||||
|
#define free_pktd(p, n) munmap(p, n)
|
||||||
#else
|
#else
|
||||||
#define sock_has_notsent(sfd) 0
|
#define sock_has_notsent(sfd) 0
|
||||||
|
|
||||||
|
#define alloc_pktd(n) malloc(n)
|
||||||
|
#define free_pktd(p, n) free(p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct packet get_tcp_fake(const char *buffer, size_t n,
|
|
||||||
|
static struct packet get_tcp_fake(const char *buffer, ssize_t n,
|
||||||
struct proto_info *info, const struct desync_params *opt)
|
struct proto_info *info, const struct desync_params *opt)
|
||||||
{
|
{
|
||||||
struct packet pkt;
|
struct packet pkt = { 0 };
|
||||||
if (opt->fake_data.data) {
|
if (opt->fake_data.data) {
|
||||||
pkt = opt->fake_data;
|
pkt = opt->fake_data;
|
||||||
}
|
}
|
||||||
@ -113,12 +125,50 @@ static struct packet get_tcp_fake(const char *buffer, size_t n,
|
|||||||
}
|
}
|
||||||
pkt = info->type == IS_HTTP ? fake_http : fake_tls;
|
pkt = info->type == IS_HTTP ? fake_http : fake_tls;
|
||||||
}
|
}
|
||||||
if (opt->fake_offset) {
|
if (info->type != IS_HTTP
|
||||||
if (pkt.size > opt->fake_offset) {
|
&& (opt->fake_mod || opt->fake_sni_count)) do {
|
||||||
pkt.size -= opt->fake_offset;
|
ssize_t ps = n > pkt.size ? n : pkt.size;
|
||||||
pkt.data += opt->fake_offset;
|
char *p = alloc_pktd(ps);
|
||||||
|
if (!p) {
|
||||||
|
uniperror("malloc/mmap");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const char *sni = 0;
|
||||||
|
if (opt->fake_sni_count) {
|
||||||
|
sni = opt->fake_sni_list[rand() % opt->fake_sni_count];
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if ((opt->fake_mod & FM_ORIG) && info->type == IS_HTTPS) {
|
||||||
|
memcpy(p, buffer, n);
|
||||||
|
|
||||||
|
if (!sni || !change_tls_sni(sni, p, n, n)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LOG(LOG_E, "change sni error\n");
|
||||||
|
}
|
||||||
|
memcpy(p, pkt.data, pkt.size);
|
||||||
|
if (sni && change_tls_sni(sni, p, pkt.size, n) < 0) {
|
||||||
|
free_pktd(p, ps);
|
||||||
|
p = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(0);
|
||||||
|
if (p) {
|
||||||
|
if (opt->fake_mod & FM_RAND) {
|
||||||
|
randomize_tls(p, ps);
|
||||||
|
}
|
||||||
|
pkt.data = p;
|
||||||
|
pkt.size = ps;
|
||||||
|
pkt.dynamic = 1;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (opt->fake_offset.m) {
|
||||||
|
pkt.off = gen_offset(opt->fake_offset.pos,
|
||||||
|
opt->fake_offset.flag, buffer, n, 0, info);
|
||||||
|
if (pkt.off > pkt.size || pkt.off < 0) {
|
||||||
|
pkt.off = 0;
|
||||||
}
|
}
|
||||||
else pkt.size = 0;
|
|
||||||
}
|
}
|
||||||
return pkt;
|
return pkt;
|
||||||
}
|
}
|
||||||
@ -155,24 +205,30 @@ static ssize_t send_fake(int sfd, const char *buffer,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
char *p = 0;
|
char *p = 0;
|
||||||
|
size_t ms = pos > pkt.size ? pos : pkt.size;
|
||||||
ssize_t ret = -1;
|
ssize_t ret = -1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
p = mmap(0, pos, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
if (pkt.dynamic) {
|
||||||
if (p == MAP_FAILED) {
|
p = pkt.data;
|
||||||
uniperror("mmap");
|
}
|
||||||
p = 0;
|
else {
|
||||||
break;
|
p = mmap(0, ms,
|
||||||
|
PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||||
|
if (p == MAP_FAILED) {
|
||||||
|
uniperror("mmap");
|
||||||
|
p = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(p, pkt.data, pkt.size);
|
||||||
}
|
}
|
||||||
memcpy(p, pkt.data, pkt.size < pos ? pkt.size : pos);
|
|
||||||
|
|
||||||
if (setttl(sfd, opt->ttl ? opt->ttl : DEFAULT_TTL) < 0) {
|
if (setttl(sfd, opt->ttl ? opt->ttl : DEFAULT_TTL) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (opt->md5sig && set_md5sig(sfd, 5)) {
|
if (opt->md5sig && set_md5sig(sfd, 5)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
struct iovec vec = { .iov_base = p, .iov_len = pos };
|
struct iovec vec = { .iov_base = p + pkt.off, .iov_len = pos };
|
||||||
|
|
||||||
ssize_t len = vmsplice(fds[1], &vec, 1, SPLICE_F_GIFT);
|
ssize_t len = vmsplice(fds[1], &vec, 1, SPLICE_F_GIFT);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
@ -184,7 +240,7 @@ static ssize_t send_fake(int sfd, const char *buffer,
|
|||||||
uniperror("splice");
|
uniperror("splice");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy(p, buffer, pos);
|
memcpy(p + pkt.off, buffer, pos);
|
||||||
|
|
||||||
if (setttl(sfd, params.def_ttl) < 0) {
|
if (setttl(sfd, params.def_ttl) < 0) {
|
||||||
break;
|
break;
|
||||||
@ -195,7 +251,9 @@ static ssize_t send_fake(int sfd, const char *buffer,
|
|||||||
ret = len;
|
ret = len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (p) munmap(p, pos);
|
if (!pkt.dynamic && p) {
|
||||||
|
munmap(p, ms);
|
||||||
|
}
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
return ret;
|
return ret;
|
||||||
@ -273,15 +331,15 @@ static ssize_t send_fake(int sfd, const char *buffer,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s->tfile = hfile;
|
s->tfile = hfile;
|
||||||
ssize_t len = -1;
|
ssize_t len = -1, ps = pkt.size - pkt.off;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
DWORD wrtcnt = 0;
|
DWORD wrtcnt = 0;
|
||||||
if (!WriteFile(hfile, pkt.data, pkt.size < pos ? pkt.size : pos, &wrtcnt, 0)) {
|
if (!WriteFile(hfile, pkt.data + pkt.off, ps < pos ? ps : pos, &wrtcnt, 0)) {
|
||||||
uniperror("WriteFile");
|
uniperror("WriteFile");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pkt.size < pos) {
|
if (ps < pos) {
|
||||||
if (SetFilePointer(hfile, pos, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
|
if (SetFilePointer(hfile, pos, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
|
||||||
uniperror("SetFilePointer");
|
uniperror("SetFilePointer");
|
||||||
break;
|
break;
|
||||||
@ -562,9 +620,14 @@ ssize_t desync(struct poolhd *pool,
|
|||||||
}
|
}
|
||||||
else switch (part.m) {
|
else switch (part.m) {
|
||||||
#ifdef FAKE_SUPPORT
|
#ifdef FAKE_SUPPORT
|
||||||
case DESYNC_FAKE:
|
case DESYNC_FAKE:;
|
||||||
|
struct packet pkt = get_tcp_fake(buffer, n, &info, &dp);
|
||||||
|
|
||||||
if (pos != lp) s = send_fake(sfd,
|
if (pos != lp) s = send_fake(sfd,
|
||||||
buffer + lp, pos - lp, &dp, get_tcp_fake(buffer, n, &info, &dp));
|
buffer + lp, pos - lp, &dp, pkt);
|
||||||
|
|
||||||
|
if (pkt.dynamic)
|
||||||
|
free_pktd(pkt.data, pkt.size);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case DESYNC_DISORDER:
|
case DESYNC_DISORDER:
|
||||||
@ -680,10 +743,10 @@ ssize_t desync_udp(int sfd, char *buffer,
|
|||||||
else {
|
else {
|
||||||
pkt = fake_udp;
|
pkt = fake_udp;
|
||||||
}
|
}
|
||||||
if (dp->fake_offset) {
|
if (dp->fake_offset.m) {
|
||||||
if (pkt.size > dp->fake_offset) {
|
if (pkt.size > dp->fake_offset.pos) {
|
||||||
pkt.size -= dp->fake_offset;
|
pkt.size -= dp->fake_offset.pos;
|
||||||
pkt.data += dp->fake_offset;
|
pkt.data += dp->fake_offset.pos;
|
||||||
}
|
}
|
||||||
else pkt.size = 0;
|
else pkt.size = 0;
|
||||||
}
|
}
|
||||||
|
3
desync.h
3
desync.h
@ -26,4 +26,7 @@ struct proto_info {
|
|||||||
char init, type;
|
char init, type;
|
||||||
int host_len, host_pos;
|
int host_len, host_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static long gen_offset(long pos, int flag,
|
||||||
|
const char *buffer, size_t n, long lp, struct proto_info *info);
|
||||||
#endif
|
#endif
|
||||||
|
58
main.c
58
main.c
@ -32,13 +32,13 @@ ASSERT(sizeof(struct in6_addr) == 16)
|
|||||||
|
|
||||||
|
|
||||||
struct packet fake_tls = {
|
struct packet fake_tls = {
|
||||||
sizeof(tls_data), tls_data
|
sizeof(tls_data), tls_data, 0, 0
|
||||||
},
|
},
|
||||||
fake_http = {
|
fake_http = {
|
||||||
sizeof(http_data), http_data
|
sizeof(http_data), http_data, 0, 0
|
||||||
},
|
},
|
||||||
fake_udp = {
|
fake_udp = {
|
||||||
sizeof(udp_data), udp_data
|
sizeof(udp_data), udp_data, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -106,11 +106,13 @@ static const char help_text[] = {
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
" -S, --md5sig Add MD5 Signature option for fake packets\n"
|
" -S, --md5sig Add MD5 Signature option for fake packets\n"
|
||||||
#endif
|
#endif
|
||||||
" -n, --tls-sni <str> Change SNI in fake ClientHello\n"
|
" -n, --fake-sni <str> Change SNI in fake\n"
|
||||||
|
" Replaced: ? - rand let, # - rand num, * - rand let/num\n"
|
||||||
#endif
|
#endif
|
||||||
" -t, --ttl <num> TTL of fake packets, default 8\n"
|
" -t, --ttl <num> TTL of fake packets, default 8\n"
|
||||||
" -O, --fake-offset <n> Fake data start offset\n"
|
" -O, --fake-offset <pos_t> Fake data start offset\n"
|
||||||
" -l, --fake-data <f|:str> Set custom fake packet\n"
|
" -l, --fake-data <f|:str> Set custom fake packet\n"
|
||||||
|
" -Q, --fake-tls-mod <r,o> Modify fake TLS CH: rand,orig\n"
|
||||||
" -e, --oob-data <char> Set custom OOB data\n"
|
" -e, --oob-data <char> Set custom OOB data\n"
|
||||||
" -M, --mod-http <h,d,r> Modify HTTP: hcsmix,dcsmix,rmspace\n"
|
" -M, --mod-http <h,d,r> Modify HTTP: hcsmix,dcsmix,rmspace\n"
|
||||||
" -r, --tlsrec <pos_t> Make TLS record at position\n"
|
" -r, --tlsrec <pos_t> Make TLS record at position\n"
|
||||||
@ -164,11 +166,12 @@ const struct option options[] = {
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{"md5sig", 0, 0, 'S'},
|
{"md5sig", 0, 0, 'S'},
|
||||||
#endif
|
#endif
|
||||||
{"tls-sni", 1, 0, 'n'},
|
{"fake-sni", 1, 0, 'n'},
|
||||||
#endif
|
#endif
|
||||||
{"ttl", 1, 0, 't'},
|
{"ttl", 1, 0, 't'},
|
||||||
{"fake-data", 1, 0, 'l'},
|
{"fake-data", 1, 0, 'l'},
|
||||||
{"fake-offset", 1, 0, 'O'},
|
{"fake-offset", 1, 0, 'O'},
|
||||||
|
{"fake-tls-mod", 1, 0, 'Q'},
|
||||||
{"oob-data", 1, 0, 'e'},
|
{"oob-data", 1, 0, 'e'},
|
||||||
{"mod-http", 1, 0, 'M'},
|
{"mod-http", 1, 0, 'M'},
|
||||||
{"tlsrec", 1, 0, 'r'},
|
{"tlsrec", 1, 0, 'r'},
|
||||||
@ -602,6 +605,10 @@ void clear_params(void)
|
|||||||
mem_destroy(s.ipset);
|
mem_destroy(s.ipset);
|
||||||
s.hosts = 0;
|
s.hosts = 0;
|
||||||
}
|
}
|
||||||
|
if (s.fake_sni_list != 0) {
|
||||||
|
free(s.fake_sni_list);
|
||||||
|
s.fake_sni_list = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(params.dp);
|
free(params.dp);
|
||||||
params.dp = 0;
|
params.dp = 0;
|
||||||
@ -916,20 +923,39 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'O':
|
case 'O':
|
||||||
val = strtol(optarg, &end, 0);
|
if (parse_offset(&dp->fake_offset, optarg)) {
|
||||||
if (val <= 0 || *end)
|
|
||||||
invalid = 1;
|
invalid = 1;
|
||||||
else
|
break;
|
||||||
dp->fake_offset = val;
|
} else dp->fake_offset.m = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'Q':
|
||||||
if (change_tls_sni(optarg, fake_tls.data, fake_tls.size)) {
|
end = optarg;
|
||||||
fprintf(stderr, "error chsni\n");
|
while (end && !invalid) {
|
||||||
clear_params();
|
switch (*end) {
|
||||||
return -1;
|
case 'r':
|
||||||
|
dp->fake_mod |= FM_RAND;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
dp->fake_mod |= FM_ORIG;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
invalid = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
end = strchr(end, ',');
|
||||||
|
if (end) end++;
|
||||||
}
|
}
|
||||||
printf("sni: %s\n", optarg);
|
break;
|
||||||
|
|
||||||
|
case 'n':;
|
||||||
|
const char **p = add((void *)&dp->fake_sni_list,
|
||||||
|
&dp->fake_sni_count, sizeof(optarg));
|
||||||
|
if (!p) {
|
||||||
|
invalid = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*p = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
|
238
packets.c
238
packets.c
@ -102,7 +102,7 @@ static size_t find_tls_ext_offset(uint16_t type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t chello_ext_offset(uint16_t type, const char *data, size_t size)
|
static size_t find_ext_block(const char *data, size_t size)
|
||||||
{
|
{
|
||||||
if (size < 44) {
|
if (size < 44) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -114,43 +114,184 @@ static size_t chello_ext_offset(uint16_t type, const char *data, size_t size)
|
|||||||
uint16_t cip_len = ANTOHS(data, 44 + sid_len);
|
uint16_t cip_len = ANTOHS(data, 44 + sid_len);
|
||||||
|
|
||||||
size_t skip = 44 + sid_len + 2 + cip_len + 2;
|
size_t skip = 44 + sid_len + 2 + cip_len + 2;
|
||||||
return find_tls_ext_offset(type, data, size, skip);
|
return skip > size ? 0 : skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int change_tls_sni(const char *host, char *buffer, size_t bsize)
|
static int merge_tls_records(char *buffer, ssize_t n)
|
||||||
{
|
{
|
||||||
size_t sni_offs, pad_offs;
|
if (n < 5) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t full_sz = 0;
|
||||||
|
uint16_t r_sz = ANTOHS(buffer, 3);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
if (!(sni_offs = chello_ext_offset(0x00, buffer, bsize))) {
|
while (1) {
|
||||||
|
full_sz += r_sz;
|
||||||
|
if (5 + full_sz > n - 5
|
||||||
|
|| buffer[5 + full_sz] != *buffer) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r_sz = ANTOHS(buffer, 5 + full_sz + 3);
|
||||||
|
|
||||||
|
if (full_sz + 10 + r_sz > n) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memmove(buffer + 5 + full_sz,
|
||||||
|
buffer + 10 + full_sz, n - (10 + full_sz));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
SHTONA(buffer, 3, full_sz);
|
||||||
|
SHTONA(buffer, 7, full_sz - 4);
|
||||||
|
return i * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void copy_name(char *out, const char *name, size_t out_len)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < out_len; i++) {
|
||||||
|
switch (name[i]) {
|
||||||
|
case '*':;
|
||||||
|
int r = rand() % (10 + 'z' - 'a' + 1);
|
||||||
|
out[i] = (r < 10 ? '0' : ('a' - 10)) + r;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
out[i] = 'a' + (rand() % ('z' - 'a' + 1));
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
out[i] = '0' + (rand() % 10);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
out[i] = name[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int remove_tls_ext(char *buffer,
|
||||||
|
ssize_t n, size_t skip, uint16_t type)
|
||||||
|
{
|
||||||
|
ssize_t ext_offs = find_tls_ext_offset(type, buffer, n, skip);
|
||||||
|
if (!ext_offs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t ext_sz = ANTOHS(buffer, ext_offs + 2);
|
||||||
|
ssize_t ext_end = ext_offs + 4 + ext_sz;
|
||||||
|
if (ext_end > n) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memmove(buffer + ext_offs, buffer + ext_end, n - ext_end);
|
||||||
|
return ext_sz + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int resize_ech_ext(char *buffer,
|
||||||
|
ssize_t n, size_t skip, int inc)
|
||||||
|
{
|
||||||
|
ssize_t ech_offs = find_tls_ext_offset(0xfe0d, buffer, n, skip);
|
||||||
|
if (!ech_offs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t ech_sz = ANTOHS(buffer, ech_offs + 2);
|
||||||
|
ssize_t ech_end = ech_offs + 4 + ech_sz;
|
||||||
|
|
||||||
|
if (ech_sz < 12 || ech_end > n) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint16_t enc_sz = ANTOHS(buffer, ech_offs + 4 + 6);
|
||||||
|
ssize_t pay_offs = ech_offs + 4 + 8 + enc_sz;
|
||||||
|
uint16_t pay_sz = ech_sz - (8 + enc_sz + 2);
|
||||||
|
|
||||||
|
if (pay_offs + 2 > n || pay_sz < -inc) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SHTONA(buffer, ech_offs + 2, ech_sz + inc);
|
||||||
|
SHTONA(buffer, pay_offs, pay_sz + inc);
|
||||||
|
|
||||||
|
memmove(buffer + ech_end + inc, buffer + ech_end, n - ech_end);
|
||||||
|
return inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void resize_sni(char *buffer, ssize_t n,
|
||||||
|
ssize_t sni_offs, ssize_t sni_sz, ssize_t new_sz)
|
||||||
|
{
|
||||||
|
SHTONA(buffer, sni_offs + 2, new_sz + 5);
|
||||||
|
SHTONA(buffer, sni_offs + 4, new_sz + 3);
|
||||||
|
SHTONA(buffer, sni_offs + 7, new_sz);
|
||||||
|
|
||||||
|
ssize_t sni_end = sni_offs + 4 + sni_sz;
|
||||||
|
memmove(buffer + sni_end + new_sz - (sni_sz - 5), buffer + sni_end, n - sni_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int change_tls_sni(const char *host, char *buffer, ssize_t n, ssize_t nn)
|
||||||
|
{
|
||||||
|
int avail = merge_tls_records(buffer, n);
|
||||||
|
avail += (nn - n);
|
||||||
|
|
||||||
|
uint16_t r_sz = ANTOHS(buffer, 3);
|
||||||
|
r_sz += avail;
|
||||||
|
|
||||||
|
size_t skip = find_ext_block(buffer, n);
|
||||||
|
if (!skip) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!(pad_offs = chello_ext_offset(0x15, buffer, bsize))) {
|
ssize_t sni_offs = find_tls_ext_offset(0x00, buffer, n, skip);
|
||||||
|
if (!sni_offs) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
char *sni = &buffer[sni_offs];
|
|
||||||
char *pad = &buffer[pad_offs];
|
|
||||||
|
|
||||||
uint16_t old_sz = ANTOHS(buffer, sni_offs + 2) - 5;
|
|
||||||
uint16_t free_sz = ANTOHS(buffer, pad_offs + 2);
|
|
||||||
uint16_t new_sz = strlen(host);
|
uint16_t new_sz = strlen(host);
|
||||||
|
uint16_t sni_sz = ANTOHS(buffer, sni_offs + 2);
|
||||||
|
|
||||||
ssize_t diff = new_sz - old_sz;
|
if (sni_offs + 4 + sni_sz > n) {
|
||||||
|
|
||||||
if ((free_sz != (bsize - pad_offs - 4))
|
|
||||||
|| free_sz < diff) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
SHTONA(sni, 2, old_sz + diff + 5);
|
int diff = (int )new_sz - (sni_sz - 5);
|
||||||
SHTONA(sni, 4, old_sz + diff + 3);
|
avail -= diff;
|
||||||
SHTONA(sni, 7, old_sz + diff);
|
|
||||||
SHTONA(pad, 2, free_sz - diff);
|
|
||||||
|
|
||||||
char *host_end = sni + 9 + old_sz;
|
if (diff < 0 && avail > 0) {
|
||||||
int oth_sz = bsize - (sni_offs + 9 + old_sz);
|
resize_sni(buffer, n, sni_offs, sni_sz, new_sz);
|
||||||
|
diff = 0;
|
||||||
|
}
|
||||||
|
if (avail) {
|
||||||
|
avail -= resize_ech_ext(buffer, n, skip, avail);
|
||||||
|
}
|
||||||
|
uint16_t exts[] = {
|
||||||
|
0x0015, // padding
|
||||||
|
0x0031, // post_handshake_auth
|
||||||
|
0x0010, // ALPN
|
||||||
|
0x001c, // record_size_limit
|
||||||
|
0x0023, // session_ticket
|
||||||
|
0x0005, // status_request
|
||||||
|
0x0022, // delegated_credentials
|
||||||
|
0x0012, // signed_certificate_timestamp
|
||||||
|
0x001b, // compress_certificate
|
||||||
|
0
|
||||||
|
};
|
||||||
|
for (uint16_t *e = exts; avail && avail < 4; e++) {
|
||||||
|
if (!*e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
avail += remove_tls_ext(buffer, n, skip, *e);
|
||||||
|
}
|
||||||
|
if (!(sni_offs = find_tls_ext_offset(0x00, buffer, n, skip))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (diff) {
|
||||||
|
resize_sni(buffer, n, sni_offs, sni_sz, new_sz);
|
||||||
|
}
|
||||||
|
copy_name(buffer + sni_offs + 9, host, new_sz);
|
||||||
|
|
||||||
memmove(host_end + diff, host_end, oth_sz);
|
if (avail >= 4) {
|
||||||
memcpy(sni + 9, host, new_sz);
|
SHTONA(buffer, 5 + r_sz - avail, 0x0015);
|
||||||
|
SHTONA(buffer, 5 + r_sz - avail + 2, avail - 4);
|
||||||
|
memset(buffer + 5 + r_sz - avail + 4, 0, avail - 4);
|
||||||
|
}
|
||||||
|
SHTONA(buffer, 3, r_sz);
|
||||||
|
SHTONA(buffer, 7, r_sz - 4);
|
||||||
|
SHTONA(buffer, skip, 5 + r_sz - skip - 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +309,11 @@ int parse_tls(const char *buffer, size_t bsize, char **hs)
|
|||||||
if (!is_tls_chello(buffer, bsize)) {
|
if (!is_tls_chello(buffer, bsize)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t sni_offs = chello_ext_offset(0x00, buffer, bsize);
|
size_t skip = find_ext_block(buffer, bsize);
|
||||||
|
if (!skip) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t sni_offs = find_tls_ext_offset(0x00, buffer, bsize, skip);
|
||||||
|
|
||||||
if (!sni_offs || (sni_offs + 12) >= bsize) {
|
if (!sni_offs || (sni_offs + 12) >= bsize) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -394,3 +539,48 @@ int part_tls(char *buffer, size_t bsize, ssize_t n, long pos)
|
|||||||
SHTONA(buffer, 5 + pos + 3, r_sz - pos);
|
SHTONA(buffer, 5 + pos + 3, r_sz - pos);
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void gen_rand_array(char *out, size_t len)
|
||||||
|
{
|
||||||
|
for (; len; len--, out++) {
|
||||||
|
uint8_t c = rand() % 256;
|
||||||
|
*((uint8_t *)out) = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void randomize_tls(char *buffer, ssize_t n)
|
||||||
|
{
|
||||||
|
if (n < 44) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t sid_len = buffer[43];
|
||||||
|
if (n < (44l + sid_len + 2)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gen_rand_array(buffer + 11, 32);
|
||||||
|
gen_rand_array(buffer + 44, sid_len);
|
||||||
|
|
||||||
|
size_t skip = find_ext_block(buffer, n);
|
||||||
|
if (!skip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ssize_t ks_offs = find_tls_ext_offset(0x0033, buffer, n, skip);
|
||||||
|
if (!ks_offs || ks_offs + 6 >= n) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int ks_sz = ANTOHS(buffer, ks_offs + 2);
|
||||||
|
if (ks_offs + 4 + ks_sz > n) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ssize_t g_offs = ks_offs + 4 + 2;
|
||||||
|
while (g_offs + 4 < ks_offs + 4 + ks_sz) {
|
||||||
|
uint16_t g_sz = ANTOHS(buffer, g_offs + 2);
|
||||||
|
if (ks_offs + 4 + g_sz > n) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gen_rand_array(buffer + g_offs + 4, g_sz);
|
||||||
|
g_offs += 4 + g_sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,7 +22,7 @@ extern char tls_data[517];
|
|||||||
extern char http_data[43];
|
extern char http_data[43];
|
||||||
extern char udp_data[64];
|
extern char udp_data[64];
|
||||||
|
|
||||||
int change_tls_sni(const char *host, char *buffer, size_t bsize);
|
int change_tls_sni(const char *host, char *buffer, ssize_t bsize, ssize_t nn);
|
||||||
|
|
||||||
bool is_tls_chello(const char *buffer, size_t bsize);
|
bool is_tls_chello(const char *buffer, size_t bsize);
|
||||||
|
|
||||||
@ -42,6 +42,8 @@ bool is_tls_shello(const char *buffer, size_t bsize);
|
|||||||
|
|
||||||
int part_tls(char *buffer, size_t bsize, ssize_t n, long pos);
|
int part_tls(char *buffer, size_t bsize, ssize_t n, long pos);
|
||||||
|
|
||||||
|
void randomize_tls(char *buffer, ssize_t n);
|
||||||
|
|
||||||
//bool is_dns_req(char *buffer, size_t n);
|
//bool is_dns_req(char *buffer, size_t n);
|
||||||
|
|
||||||
//bool is_quic_initial(char *buffer, size_t bsize);
|
//bool is_quic_initial(char *buffer, size_t bsize);
|
||||||
|
10
params.h
10
params.h
@ -37,6 +37,9 @@
|
|||||||
#define AUTO_NOBUFF -1
|
#define AUTO_NOBUFF -1
|
||||||
#define AUTO_NOSAVE 0
|
#define AUTO_NOSAVE 0
|
||||||
|
|
||||||
|
#define FM_RAND 1
|
||||||
|
#define FM_ORIG 2
|
||||||
|
|
||||||
enum demode {
|
enum demode {
|
||||||
DESYNC_NONE,
|
DESYNC_NONE,
|
||||||
DESYNC_SPLIT,
|
DESYNC_SPLIT,
|
||||||
@ -67,6 +70,8 @@ struct part {
|
|||||||
struct packet {
|
struct packet {
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
char *data;
|
char *data;
|
||||||
|
ssize_t off;
|
||||||
|
bool dynamic;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct desync_params {
|
struct desync_params {
|
||||||
@ -74,7 +79,10 @@ struct desync_params {
|
|||||||
bool md5sig;
|
bool md5sig;
|
||||||
struct packet fake_data;
|
struct packet fake_data;
|
||||||
int udp_fake_count;
|
int udp_fake_count;
|
||||||
int fake_offset;
|
struct part fake_offset;
|
||||||
|
int fake_sni_count;
|
||||||
|
const char **fake_sni_list;
|
||||||
|
int fake_mod;
|
||||||
bool drop_sack;
|
bool drop_sack;
|
||||||
char oob_char[2];
|
char oob_char[2];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user