From 72b3abe00749dca4d72ad7f52733d0aba5d0de58 Mon Sep 17 00:00:00 2001 From: ruti <> Date: Mon, 4 Mar 2024 04:49:08 +0300 Subject: [PATCH] Move methods to options, support multiple split positions --- desync.c | 186 +++++++++++++++++++++++++++-------------------------- main.c | 105 +++++++++++++++++------------- params.h | 11 +++- readme.txt | 40 ++++++------ 4 files changed, 184 insertions(+), 158 deletions(-) diff --git a/desync.c b/desync.c index 42b3c77..a1fd727 100644 --- a/desync.c +++ b/desync.c @@ -79,8 +79,8 @@ static inline void delay(long mk) #endif #ifndef _WIN32 -int fake_attack(int sfd, char *buffer, - size_t n, int cnt, int pos, int fa) +int send_fake(int sfd, char *buffer, + int cnt, long pos, int fa) { struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http; size_t psz = pkt.size; @@ -113,19 +113,12 @@ int fake_attack(int sfd, char *buffer, uniperror("sendfile"); break; } - struct timespec delay = { - .tv_nsec = params.sfdelay * 1000 - }; - nanosleep(&delay, 0); + delay(params.sfdelay); memcpy(p, buffer, pos); if (setttl(sfd, params.def_ttl, fa) < 0) { break; } - if (send(sfd, buffer + pos, n - pos, 0) < 0) { - uniperror("send"); - break; - } status = 0; } if (p) munmap(p, pos); @@ -134,8 +127,43 @@ int fake_attack(int sfd, char *buffer, } #endif -int disorder_attack(int sfd, char *buffer, - ssize_t n, int pos, int fa) +int send_oob(int sfd, char *buffer, + ssize_t n, long pos) +{ + ssize_t size = oob_data.size; + char *data = oob_data.data; + + if (pos + 1 < n) { + char rchar = buffer[pos]; + buffer[pos] = data[0]; + + if (send(sfd, buffer, pos + 1, MSG_OOB) < 0) { + uniperror("send"); + buffer[pos] = rchar; + return -1; + } + buffer[pos] = rchar; + size--; + data++; + if (size) { + delay(params.sfdelay); + } + } + for (long i = 0; i < size; i++) { + if (send(sfd, data + i, 1, MSG_OOB) < 0) { + uniperror("send"); + return -1; + } + if (size != 1) { + delay(params.sfdelay); + } + } + return 0; +} + + +int send_disorder(int sfd, + char *buffer, long pos, int fa) { int bttl = 1; if (setttl(sfd, bttl, fa) < 0) { @@ -148,53 +176,13 @@ int disorder_attack(int sfd, char *buffer, if (setttl(sfd, params.def_ttl, fa) < 0) { return -1; } - if (send(sfd, buffer + pos, n - pos, 0) < 0) { - uniperror("send"); - return -1; - } return 0; } -int oob_attack(int sfd, char *buffer, - ssize_t n, int pos, int fa) -{ - int size = oob_data.size - 1; - char *data = oob_data.data + 1; - - char rchar = buffer[pos]; - buffer[pos] = data[0]; - - if (send(sfd, buffer, pos + 1, MSG_OOB) < 0) { - uniperror("send"); - buffer[pos] = rchar; - return -1; - } - buffer[pos] = rchar; - if (size) { - delay(params.sfdelay); - } - for (int i = 0; i < size; i++) { - if (send(sfd, data + i, 1, MSG_OOB) < 0) { - uniperror("send"); - return -1; - } - if (size != 1) { - delay(params.sfdelay); - } - } - if (send(sfd, buffer + pos, n - pos, 0) < 0) { - uniperror("send"); - return -1; - } - return 0; -} - - int desync(int sfd, char *buffer, size_t bfsize, ssize_t n, struct sockaddr *dst) { - int pos = params.split; char *host = 0; int len = 0, type = 0; int fa = get_family(dst); @@ -228,52 +216,70 @@ int desync(int sfd, char *buffer, size_t bfsize, n = part_tls(buffer, bfsize, n, o); } - if (params.split_host) { - if (host) - pos += (host - buffer); - else - pos = 0; - } - else if (pos < 0) { - pos += n; - } - LOG(LOG_L, "split-pos=%d, n=%ld\n", pos, n); - if (params.custom_ttl) { if (setttl(sfd, params.def_ttl, fa) < 0) { return -1; } } - if (pos <= 0 || pos >= n || - params.attack == DESYNC_NONE || - (!type && params.de_known)) - { - if (send(sfd, buffer, n, 0) < 0) { + 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) + pos += (host - buffer); + else + pos = 0; + } + else if (pos < 0) { + pos += n; + } + if (pos <= 0 || pos >= n || pos <= lp) { + break; + } + LOG(LOG_S, "split: pos=%ld-%ld, m=%d\n", lp, pos, part->m); + + int s = 0; + switch (part->m) { + #ifndef _WIN32 + case DESYNC_FAKE: + s = send_fake(sfd, + buffer + lp, type, pos - lp, fa); + break; + #endif + case DESYNC_DISORDER: + s = send_disorder(sfd, + buffer + lp, pos - lp, fa); + break; + + case DESYNC_OOB: + s = send_oob(sfd, + buffer + lp, n - lp, pos - lp); + break; + + case DESYNC_SPLIT: + default: + if (send(sfd, buffer + lp, pos - lp, 0) < 0) { + uniperror("send"); + return -1; + } + } + if (s) { + return -1; + } + lp = pos; + part = part->next; + } + if (lp < n) { + LOG(LOG_S, "send: pos=%ld-%ld\n", lp, n); + if (send(sfd, buffer + lp, n - lp, 0) < 0) { uniperror("send"); return -1; } } - else switch (params.attack) { - #ifndef _WIN32 - case DESYNC_FAKE: - return fake_attack(sfd, buffer, n, type, pos, fa); - #endif - case DESYNC_DISORDER: - return disorder_attack(sfd, buffer, n, pos, fa); - - case DESYNC_OOB: - return oob_attack(sfd, buffer, n, pos, fa); - - case DESYNC_SPLIT: - default: - if (send(sfd, buffer, pos, 0) < 0) { - uniperror("send"); - return -1; - } - if (send(sfd, buffer + pos, n - pos, 0) < 0) { - uniperror("send"); - return -1; - } - } return 0; } diff --git a/main.c b/main.c index 507be26..486fcfc 100644 --- a/main.c +++ b/main.c @@ -40,9 +40,8 @@ oob_data = { struct params params = { .ttl = 8, - .split = 3, + .parts = 0, .sfdelay = 3000, - .attack = DESYNC_NONE, .split_host = 0, .def_ttl = 0, .custom_ttl = 0, @@ -74,17 +73,15 @@ 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" - #ifdef FAKE_SUPPORT - " -m, --method Desync method: split,disorder,oob,fake\n" - #else - " -m, --method Desync method: split,disorder,oob\n" - #endif - " -s, --split-pos Split position, default 3\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" #ifdef FAKE_SUPPORT + " -f, --fake Split and send fake packet\n" " -t, --ttl TTL of fake packets, default 8\n" " -l, --fake-tls \n" - " -o, --fake-http Set custom fake packet\n" + " -j, --fake-http Set custom fake packet\n" " -n, --tls-sni Change SNI in fake CH\n" #endif " -e, --oob-data Set custom oob bytes\n" @@ -108,12 +105,14 @@ const struct option options[] = { {"desync-known ", 0, 0, 'K'}, {"split-at-host", 0, 0, 'H'}, - {"method", 1, 0, 'm'}, - {"split-pos", 1, 0, 's'}, + {"split", 1, 0, 's'}, + {"disorder", 1, 0, 'd'}, + {"oob", 1, 0, 'o'}, + {"fake", 1, 0, 'f'}, {"ttl", 1, 0, 't'}, #ifdef FAKE_SUPPORT {"fake-tls", 1, 0, 'l'}, - {"fake-http", 1, 0, 'o'}, + {"fake-http", 1, 0, 'j'}, {"tls-sni", 1, 0, 'n'}, #endif {"oob-data", 1, 0, 'e'}, @@ -308,37 +307,57 @@ int main(int argc, char **argv) params.split_host = 1; break; - case 'm': - if (params.attack != DESYNC_NONE) { - fprintf(stderr, "methods incompatible\n"); - invalid = 1; - } - else switch (*optarg) { - case 's': - params.attack = DESYNC_SPLIT; - break; - case 'd': - params.attack = DESYNC_DISORDER; - break; - case 'o': - params.attack = DESYNC_OOB; - break; - #ifdef FAKE_SUPPORT - case 'f': - params.attack = DESYNC_FAKE; - break; - #endif - default: - invalid = 1; - } - break; - - case 's': + case 's': + case 'd': + case 'o': + case 'f': val = strtol(optarg, &end, 0); - if (val < INT_MIN || val > INT_MAX || *end) + if (*end) { invalid = 1; - else - params.split = val; + break; + } + struct part *part = malloc(sizeof(struct part)); + if (!part) { + uniperror("malloc"); + return -1; + } + switch (rez) { + case 's': part->m = DESYNC_SPLIT; + break; + case 'd': part->m = DESYNC_DISORDER; + break; + case 'o': part->m = DESYNC_OOB; + break; + case 'f': part->m = DESYNC_FAKE; + } + part->pos = val; + + if (!params.parts) { + params.parts = part; + } + else { + struct part *p = params.parts, *v = 0; + while (p) { + if (val < p->pos) { + if (v) { + part->next = p; + v->next = part; + } + else { + part->next = params.parts; + params.parts = part; + } + break; + } + if (!p->next) { + p->next = part; + part->next = 0; + break; + } + v = p; + p = p->next; + } + } break; case 't': @@ -365,7 +384,7 @@ int main(int argc, char **argv) } break; - case 'o': + case 'j': fake_http.data = ftob(optarg, &fake_http.size); if (!fake_http.data) { uniperror("read file"); @@ -456,7 +475,7 @@ int main(int argc, char **argv) if (b.sa.sa_family != AF_INET6) { params.ipv6 = 0; } - if (!params.def_ttl && params.attack != DESYNC_NONE) { + if (!params.def_ttl) { if ((params.def_ttl = get_default_ttl()) < 1) { return -1; } diff --git a/params.h b/params.h index 10969ed..99b2f95 100644 --- a/params.h +++ b/params.h @@ -14,13 +14,18 @@ enum demode { DESYNC_FAKE }; +struct part { + int m; + long pos; + struct part *next; +}; + struct params { char de_known; int ttl; - int split; - long sfdelay; - enum demode attack; + struct part *parts; char split_host; + long sfdelay; int def_ttl; char custom_ttl; int mod_http; diff --git a/readme.txt b/readme.txt index ca17b7f..3a2f09a 100644 --- a/readme.txt +++ b/readme.txt @@ -35,36 +35,32 @@ $ ./ciadpi --method disorder --split-pos 3 Отключить запутывание для нераспознанных протоколов Распознаваемые протоколы: HTTP и TLS с SNI --m, --method - Способ запутывания TCP, комбинировать нельзя: - split: - Разбить первый запрос на два по определённому смещению - disorder: - Как split, но части отправляются в обратном порядке - ! Поведение в Windows отлично: сначала отправляется вторая часть, затем целый запрос - fake: - ! В Windows не поддерживается - Как disorder, только перед первым запросом отправляется часть поддельного - Количество байт отправляемого из фейка равно значению split-pos, - поэтому рекомендуется использовать отрицательное значение или вкл. split-at-host - oob: - Как split, но после первой части отсылается несколько байт вне основного потока - ! Малоизученный метод - --s, --split-pos - Смещение, по которому будет разбит запрос, по умолчанию 3 - Если значение отрицательное, то оно будет считаться от конца - +-s, --split + Разбить запрос по указанному смещению + Можно указать несколько раз, например: -s 3 -s 10 + При указании отрицательного значения к нему прибавляется размер пакета + +-d, --disorder + Подобен --split, но части отправляются в обратном порядке + ! Поведение в Windows отлично: сначала отправляется лишь часть, но затем целый запрос + +-f, --fake + Подобен --disorder, только перед первым запросом отправляется часть поддельного + Количество байт отправляемого из фейка равно рамеру разбиваемой части + +-o, --oob + Подобен --split, но после offset отсылается несколько байт OOB данных + -H, --split-at-host Если найден SNI или Host, то считать смещение относительно позиции домена - При split-pos=0 запрос будет разбит прямо перед именем хоста + При offset=0 запрос будет разбит прямо перед именем хоста -t, --ttl TTL для поддельного пакета, по умолчанию 8 Необходимо подобрать такое значение, чтобы пакет не дошел до сервера, но был обработан DPI -l, --fake-tls --o, --fake-http +-j, --fake-http Указать свои поддельные пакеты, вместо дефолтных -e, --oob-data