diff --git a/desync.c b/desync.c index 89290ce..bf7da3c 100644 --- a/desync.c +++ b/desync.c @@ -25,6 +25,7 @@ #define memfd_create(name, flags) fileno(tmpfile()) #endif #else + #include #include #include #endif @@ -67,15 +68,15 @@ int setttl(int fd, int ttl, int family) { } #ifndef _WIN32 -static inline void delay(long mk) +static inline void delay(long ms) { struct timespec time = { - .tv_nsec = mk * 1000 + .tv_nsec = ms * 1000000 }; nanosleep(&time, 0); } #else -#define delay(mk) {} +#define delay(ms) Sleep(ms) #endif #ifndef _WIN32 @@ -204,27 +205,30 @@ int desync(int sfd, char *buffer, size_t bfsize, return -1; } } - else if (type == IS_HTTPS && params.tlsrec) { - struct part *part = params.tlsrec; - int i = 0; + else if (type == IS_HTTPS && params.tlsrec_n) { long lp = 0; - while (part) { - long pos = part->pos + i * 5; - if (params.tlsrec_sni) { + for (int i = 0; i < params.tlsrec_n; i++) { + struct part part = params.tlsrec[i]; + + long pos = part.pos + i * 5; + if (part.flag == OFFSET_SNI) { pos += (host - buffer - 5); } else if (pos < 0) { pos += n; } - LOG(LOG_S, "tlsrec: pos=%ld, n=%ld\n", pos, n); - if (!part_tls(buffer + lp, - bfsize - lp, n - lp, pos - lp)) { + if (pos < lp) { + LOG(LOG_E, "tlsrec cancel: %ld < %ld\n", pos, lp); break; } + if (!part_tls(buffer + lp, + bfsize - lp, n - lp, pos - lp)) { + LOG(LOG_E, "tlsrec error: pos=%ld, n=%ld\n", pos, n); + break; + } + LOG(LOG_S, "tlsrec: pos=%ld, n=%ld\n", pos, n); n += 5; lp = pos + 5; - i++; - part = part->next; } } @@ -233,30 +237,37 @@ int desync(int sfd, char *buffer, size_t bfsize, return -1; } } - struct part *part = params.parts; long lp = 0; if ((!type && params.de_known)) { - part = 0; } - while (part) { - long pos = part->pos; - if (params.split_host) { - if (host) + else for (int i = 0; i < params.parts_n; i++) { + struct part part = params.parts[i]; + + long pos = part.pos; + if (part.flag == OFFSET_SNI) { + if (type != IS_HTTPS) + break; + else + pos += (host - buffer); + } + else if (part.flag == OFFSET_HOST) { + if (type != IS_HTTP) + break; + else pos += (host - buffer); - else - pos = 0; } else if (pos < 0) { pos += n; } if (pos <= 0 || pos >= n || pos <= lp) { + LOG(LOG_E, "split cancel: pos=%ld-%ld, n=%ld\n", lp, pos, n); break; } - LOG(LOG_S, "split: pos=%ld-%ld, m=%d\n", lp, pos, part->m); + LOG(LOG_S, "split: pos=%ld-%ld, m=%d\n", lp, pos, part.m); int s = 0; - switch (part->m) { + switch (part.m) { #ifndef _WIN32 case DESYNC_FAKE: s = send_fake(sfd, @@ -284,7 +295,6 @@ int desync(int sfd, char *buffer, size_t bfsize, return -1; } lp = pos; - part = part->next; } if (lp < n) { LOG(LOG_S, "send: pos=%ld-%ld\n", lp, n); diff --git a/main.c b/main.c index 94e0aba..569319d 100644 --- a/main.c +++ b/main.c @@ -40,14 +40,14 @@ oob_data = { struct params params = { .ttl = 8, + .parts_n = 0, .parts = 0, - .sfdelay = 3000, - .split_host = 0, + .sfdelay = 3, .def_ttl = 0, .custom_ttl = 0, .mod_http = 0, .tlsrec = 0, - .tlsrec_sni = 0, + .tlsrec_n = 0, .de_known = 0, .ipv6 = 1, @@ -72,12 +72,11 @@ const char help_text[] = { " -g, --def-ttl TTL for all outgoing connections\n" // desync options " -K, --desync-known Desync only HTTP and TLS with SNI\n" - " -H, --split-at-host Add Host/SNI offset to split position\n" - " -s, --split Split packet at spec position\n" - " -s, --disorder Split and send reverse order\n" - " -o, --oob Split and send as OOB data\n" + " -s, --split Split packet at n, +s to add SNI offset\n" + " -s, --disorder Split and send reverse order\n" + " -o, --oob Split and send as OOB data\n" #ifdef FAKE_SUPPORT - " -f, --fake Split and send fake packet\n" + " -f, --fake Split and send fake packet\n" " -t, --ttl TTL of fake packets, default 8\n" " -l, --fake-tls \n" " -j, --fake-http Set custom fake packet\n" @@ -85,8 +84,7 @@ const char help_text[] = { #endif " -e, --oob-data Set custom OOB data\n" " -M, --mod-http Modify http: hcsmix,dcsmix,rmspace\n" - " -r, --tlsrec Make TLS record at offset\n" - " -L, --tlsrec-at-sni Add SNI offset to tlsrec position\n" + " -r, --tlsrec Make TLS record at offset\n" }; @@ -103,13 +101,12 @@ const struct option options[] = { {"debug", 1, 0, 'x'}, {"desync-known ", 0, 0, 'K'}, - {"split-at-host", 0, 0, 'H'}, {"split", 1, 0, 's'}, {"disorder", 1, 0, 'd'}, {"oob", 1, 0, 'o'}, + #ifdef FAKE_SUPPORT {"fake", 1, 0, 'f'}, {"ttl", 1, 0, 't'}, - #ifdef FAKE_SUPPORT {"fake-tls", 1, 0, 'l'}, {"fake-http", 1, 0, 'j'}, {"tls-sni", 1, 0, 'n'}, @@ -117,7 +114,6 @@ const struct option options[] = { {"oob-data", 1, 0, 'e'}, {"mod-http", 1, 0, 'M'}, {"tlsrec", 1, 0, 'r'}, - {"tlsrec-at-sni", 0, 0, 'L'}, {"def-ttl", 1, 0, 'g'}, {"delay", 1, 0, 'w'}, // @@ -195,41 +191,39 @@ int get_default_ttl() } -struct part *add_part(struct part **root, long val) +struct part *add_part(struct part **root, int *n) { - struct part *part = malloc(sizeof(struct part)); - if (!part) { - uniperror("malloc"); + struct part *p = realloc( + *root, sizeof(struct part) * (*n + 1)); + if (!p) { + uniperror("realloc"); return 0; } + *root = p; + *n = *n + 1; + return &((*root)[(*n) - 1]); +} + + +int parse_offset(struct part *part, const char *str) +{ + char *end = 0; + long val = strtol(str, &end, 0); + if (*end == '+') switch (*(end + 1)) { + case 's': + part->flag = OFFSET_SNI; + break; + case 'h': + part->flag = OFFSET_HOST; + break; + default: + return -1; + } + else if (*end) { + return -1; + } part->pos = val; - - struct part *p = *root, *v = 0; - if (!p) { - *root = part; - return part; - } - while (p) { - if (val < p->pos) { - if (v) { - part->next = p; - v->next = part; - } - else { - part->next = *root; - *root = part; - } - break; - } - if (!p->next) { - p->next = part; - part->next = 0; - break; - } - v = p; - p = p->next; - } - return part; + return 0; } @@ -265,9 +259,6 @@ int main(int argc, char **argv) } } - char daemon = 0; - char *pidfile = 0; - int rez; int invalid = 0; @@ -340,23 +331,20 @@ int main(int argc, char **argv) params.de_known = 1; break; - case 'H': - params.split_host = 1; - break; - case 's': case 'd': case 'o': case 'f': - val = strtol(optarg, &end, 0); - if (*end) { - invalid = 1; - break; - } - struct part *part = add_part(¶ms.parts, val); + ; + struct part *part = add_part( + ¶ms.parts, ¶ms.parts_n); if (!part) { return -1; } + if (parse_offset(part, optarg)) { + invalid = 1; + break; + } switch (rez) { case 's': part->m = DESYNC_SPLIT; break; @@ -431,19 +419,15 @@ int main(int argc, char **argv) break; case 'r': - val = strtol(optarg, &end, 0); - if (val > 0xffff || *end) { - invalid = 1; - break; - } - part = add_part(¶ms.tlsrec, val); + part = add_part(¶ms.tlsrec, ¶ms.tlsrec_n); if (!part) { return -1; } - break; - - case 'L': - params.tlsrec_sni = 1; + if (parse_offset(part, optarg) + || part->pos > 0xffff) { + invalid = 1; + break; + } break; case 'g': @@ -459,7 +443,7 @@ int main(int argc, char **argv) case 'w': // params.sfdelay = strtol(optarg, &end, 0); if (params.sfdelay < 0 || optarg == end - || params.sfdelay >= 1000000 || *end) + || params.sfdelay >= 1000 || *end) invalid = 1; break; diff --git a/params.h b/params.h index b185348..1497743 100644 --- a/params.h +++ b/params.h @@ -6,6 +6,9 @@ #include #endif +#define OFFSET_SNI 1 +#define OFFSET_HOST 2 + enum demode { DESYNC_NONE, DESYNC_SPLIT, @@ -16,21 +19,21 @@ enum demode { struct part { int m; + int flag; long pos; - struct part *next; }; struct params { char de_known; int ttl; + int parts_n; struct part *parts; - char split_host; long sfdelay; int def_ttl; char custom_ttl; int mod_http; + int tlsrec_n; struct part *tlsrec; - char tlsrec_sni; char ipv6; char resolve; diff --git a/readme.txt b/readme.txt index 1f227ac..0598b7f 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ -------------- Использование: -$ ./ciadpi --split 3 --disorder 10 +$ ./ciadpi --disorder 3+sni Описание аргументов: -i, --ip @@ -35,26 +35,25 @@ $ ./ciadpi --split 3 --disorder 10 Отключить запутывание для нераспознанных протоколов Распознаваемые протоколы: HTTP и TLS с SNI --s, --split +-s, --split Разбить запрос по указанному смещению + После числа можно добавить флаг: + +s: добавить смещение SNI + +h: добавить смещение Host Можно указывать несколько раз, чтобы разбить запрос по нескольким позициям При указании отрицательного значения к нему прибавляется размер пакета --d, --disorder +-d, --disorder Подобен --split, но части отправляются в обратном порядке ! Поведение в Windows отлично: сначала отправляется лишь часть, но затем целый запрос --f, --fake +-o, --oob + Подобен --split, но после offset отсылается один или несколько байт OOB данных + +-f, --fake Подобен --disorder, только перед отправкой первого куска отправляется часть поддельного Количество байт отправляемого из фейка равно рамеру разбиваемой части --o, --oob - Подобен --split, но после offset отсылается несколько байт OOB данных - --H, --split-at-host - Если найден SNI или Host, то считать смещение относительно позиции домена - При offset=0 запрос будет разбит прямо перед именем хоста - -t, --ttl TTL для поддельного пакета, по умолчанию 8 Необходимо подобрать такое значение, чтобы пакет не дошел до сервера, но был обработан DPI @@ -79,14 +78,10 @@ $ ./ciadpi --split 3 --disorder 10 rmspace: "Host: name" -> "Host:name\t" --r, --tlsrec +-r, --tlsrec Разделить ClientHello на отдельные записи по указанному смещению - Также возможен отсчет от конца при указании отрицательного значения Можно указывать несколько раз --L, --tlsrec-at-sni - Отсчитывать позицию tlsrec относительно SNI - ------- Сборка: Для сборки понадобится: