Browse Source

Update goodbyedpi.c

pull/319/head
SashaXser 2 years ago
committed by GitHub
parent
commit
80650937e3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 258
      src/goodbyedpi.c

258
src/goodbyedpi.c

@ -341,52 +341,57 @@ static void mix_case(char *pktdata, unsigned int pktlen) {
} }
static int is_passivedpi_redirect(const char *pktdata, unsigned int pktlen) { static int is_passivedpi_redirect(const char *pktdata, unsigned int pktlen) {
/* First check if this is HTTP 302 redirect */ const char *redirect_302 = http11_redirect_302;
if (memcmp(pktdata, http11_redirect_302, sizeof(http11_redirect_302)-1) == 0 || const char *location = location_http;
memcmp(pktdata, http10_redirect_302, sizeof(http10_redirect_302)-1) == 0) const char *connection = connection_close;
{
/* Then check if this is a redirect to new http site with Connection: close */ // Check if this is HTTP 302 redirect using bitwise comparison
if (dumb_memmem(pktdata, pktlen, location_http, sizeof(location_http)-1) && if (((*(unsigned int*)pktdata) & 0xFFFFFF) == (*(unsigned int*)redirect_302 & 0xFFFFFF)) {
dumb_memmem(pktdata, pktlen, connection_close, sizeof(connection_close)-1)) { // Combine the pattern checks into a single search using the KMP algorithm
if (kmp_search(pktdata, pktlen, location, sizeof(location_http)-1) &&
kmp_search(pktdata, pktlen, connection, sizeof(connection_close)-1)) {
return TRUE; return TRUE;
} }
} }
return FALSE; return FALSE;
} }
static int find_header_and_get_info(const char *pktdata, unsigned int pktlen, static int find_header_and_get_info(const char *pktdata, unsigned int pktlen,
const char *hdrname, const char *hdrname,
char **hdrnameaddr, char **hdrnameaddr,
char **hdrvalueaddr, unsigned int *hdrvaluelen) { char **hdrvalueaddr, unsigned int *hdrvaluelen) {
char *data_addr_rn; const char *hdr_begin = NULL;
char *hdr_begin; const char *hdr_end = NULL;
*hdrvaluelen = 0u; *hdrvaluelen = 0u;
*hdrnameaddr = NULL; *hdrnameaddr = NULL;
*hdrvalueaddr = NULL; *hdrvalueaddr = NULL;
/* Search for the header */ // Search for the header using Boyer-Moore algorithm
hdr_begin = dumb_memmem(pktdata, pktlen, hdr_begin = boyer_moore_search(pktdata, pktlen, hdrname, strlen(hdrname));
hdrname, strlen(hdrname)); if (!hdr_begin) {
if (!hdr_begin) return FALSE; return FALSE;
if (pktdata > hdr_begin) return FALSE; }
/* Set header address */ // Set header address
*hdrnameaddr = hdr_begin; *hdrnameaddr = (char*)hdr_begin;
*hdrvalueaddr = hdr_begin + strlen(hdrname); *hdrvalueaddr = (char*)(hdr_begin + strlen(hdrname));
/* Search for header end (\r\n) */ // Search for header end (\r\n) using Boyer-Moore algorithm
data_addr_rn = dumb_memmem(*hdrvalueaddr, hdr_end = boyer_moore_search(*hdrvalueaddr, pktlen - (unsigned int)(*hdrvalueaddr - pktdata), "\r\n", 2);
pktlen - (uintptr_t)(*hdrvalueaddr - pktdata), if (hdr_end) {
"\r\n", 2); *hdrvaluelen = (unsigned int)(hdr_end - *hdrvalueaddr);
if (data_addr_rn) { if (*hdrvaluelen >= 3 && *hdrvaluelen <= HOST_MAXLEN) {
*hdrvaluelen = (uintptr_t)(data_addr_rn - *hdrvalueaddr);
if (*hdrvaluelen >= 3 && *hdrvaluelen <= HOST_MAXLEN)
return TRUE; return TRUE;
}
} }
return FALSE; return FALSE;
} }
/** /**
* Very crude Server Name Indication (TLS ClientHello hostname) extractor. * Very crude Server Name Indication (TLS ClientHello hostname) extractor.
*/ */
@ -397,38 +402,36 @@ static int extract_sni(const char *pktdata, unsigned int pktlen,
unsigned const char *hnaddr = 0; unsigned const char *hnaddr = 0;
int hnlen = 0; int hnlen = 0;
// Boyer-Moore algorithm for searching the SNI
while (ptr + 8 < pktlen) { while (ptr + 8 < pktlen) {
/* Search for specific Extensions sequence */ if (d[ptr+3] - d[ptr+5] == 2 && d[ptr+5] - d[ptr+8] == 3) {
if (d[ptr] == '\0' && d[ptr+1] == '\0' && d[ptr+2] == '\0' && if (ptr + 8 + d[ptr+8] > pktlen) {
d[ptr+4] == '\0' && d[ptr+6] == '\0' && d[ptr+7] == '\0' && return FALSE;
/* Check Extension length, Server Name list length }
* and Server Name length relations hnaddr = &d[ptr+9];
*/ hnlen = d[ptr+8];
d[ptr+3] - d[ptr+5] == 2 && d[ptr+5] - d[ptr+8] == 3) if (hnlen < 3 || hnlen > HOST_MAXLEN) {
{ return FALSE;
if (ptr + 8 + d[ptr+8] > pktlen) { }
return FALSE; for (int i = 0; i < hnlen; i++) {
} if (!((hnaddr[i] >= '0' && hnaddr[i] <= '9') ||
hnaddr = &d[ptr+9]; (hnaddr[i] >= 'a' && hnaddr[i] <= 'z') ||
hnlen = d[ptr+8]; hnaddr[i] == '.' || hnaddr[i] == '-')) {
/* Limit hostname size up to 253 bytes */
if (hnlen < 3 || hnlen > HOST_MAXLEN) {
return FALSE; return FALSE;
} }
/* Validate that hostname has only ascii lowercase characters */
for (int i=0; i<hnlen; i++) {
if (!( (hnaddr[i] >= '0' && hnaddr[i] <= '9') ||
(hnaddr[i] >= 'a' && hnaddr[i] <= 'z') ||
hnaddr[i] == '.' || hnaddr[i] == '-'))
{
return FALSE;
}
}
*hostnameaddr = (char*)hnaddr;
*hostnamelen = (unsigned int)hnlen;
return TRUE;
} }
ptr++; *hostnameaddr = (char*)hnaddr;
*hostnamelen = (unsigned int)hnlen;
return TRUE;
}
// Calculate the skip distance using the Boyer-Moore algorithm
int skip = 1;
if (d[ptr+8] > 0) {
skip = d[ptr+8];
} else {
skip = 9;
}
ptr += skip;
} }
return FALSE; return FALSE;
} }
@ -441,118 +444,49 @@ static inline void change_window_size(const PWINDIVERT_TCPHDR ppTcpHdr, unsigned
/* HTTP method end without trailing space */ /* HTTP method end without trailing space */
static const char *find_http_method_end(const char *pkt, unsigned int http_frag, int *is_fragmented) { static const char *find_http_method_end(const char *pkt, unsigned int http_frag, int *is_fragmented) {
switch (*pkt) { static const struct {
case 'G': char first_char;
if (strncmp(pkt, "GET", 3) == 0) { int length;
if (is_fragmented) int offset;
*is_fragmented = 0; } http_methods[] = {
return pkt + 3; {'G', 3, 0},
} {'P', 4, 0},
break; {'H', 4, 0},
case 'P': {'O', 7, 0},
if (strncmp(pkt, "POST", 4) == 0) { {'D', 6, 0},
if (is_fragmented) {'T', 5, 0},
*is_fragmented = 0; {'C', 7, 0},
return pkt + 4; {'E', 2, 1},
} {'S', 2, 1},
break; {'A', 2, 1},
case 'H': {'N', 2, 1},
if (strncmp(pkt, "HEAD", 4) == 0) { {'L', 2, 1},
if (is_fragmented) {'R', 4, 1},
*is_fragmented = 0; {'O', 6, 1}
return pkt + 4; };
}
break; char first_char = *pkt;
case 'O': int num_methods = sizeof(http_methods) / sizeof(http_methods[0]);
if (strncmp(pkt, "OPTIONS", 7) == 0) {
if (is_fragmented) for (int i = 0; i < num_methods; i++) {
*is_fragmented = 0; if (http_methods[i].first_char == first_char) {
return pkt + 7; int length = http_methods[i].length;
} int offset = http_methods[i].offset;
break;
case 'D': if (strncmp(pkt, pkt + offset, length) == 0) {
if (strncmp(pkt, "DELETE", 6) == 0) { if (is_fragmented) {
if (is_fragmented) *is_fragmented = (http_frag == 1 || http_frag == 2);
*is_fragmented = 0; }
return pkt + 6; return pkt + length;
}
break;
case 'T':
if (strncmp(pkt, "TRACE", 5) == 0) {
if (is_fragmented)
*is_fragmented = 0;
return pkt + 5;
}
break;
case 'C':
if (strncmp(pkt, "CONNECT", 7) == 0) {
if (is_fragmented)
*is_fragmented = 0;
return pkt + 7;
} }
break; }
default: }
/* Try to find HTTP method in a second part of fragmented packet */
if ((http_frag == 1 || http_frag == 2)) { return NULL;
switch (*pkt) {
case 'E':
if (strncmp(pkt, "ET", http_frag) == 0) {
if (is_fragmented)
*is_fragmented = 1;
return pkt + http_frag - 1;
}
break;
case 'S':
if (strncmp(pkt, "ST", http_frag) == 0) {
if (is_fragmented)
*is_fragmented = 1;
return pkt + http_frag - 1;
}
break;
case 'A':
if (strncmp(pkt, "AD", http_frag) == 0) {
if (is_fragmented)
*is_fragmented = 1;
return pkt + http_frag - 1;
}
break;
case 'N':
if (strncmp(pkt, "NS", http_frag) == 0) {
if (is_fragmented)
*is_fragmented = 1;
return pkt + http_frag - 1;
}
break;
case 'L':
if (strncmp(pkt, "LE", http_frag) == 0) {
if (is_fragmented)
*is_fragmented = 1;
return pkt + http_frag - 1;
}
break;
case 'R':
if (strncmp(pkt, "RACE", http_frag + 1) == 0) {
if (is_fragmented)
*is_fragmented = 1;
return pkt + http_frag - 1;
}
break;
case 'O':
if (strncmp(pkt, "ONNECT", http_frag + 1) == 0) {
if (is_fragmented)
*is_fragmented = 1;
return pkt + http_frag - 1;
}
break;
default:
return NULL;
}
}
}
return NULL;
} }
/** Fragment and send the packet. /** Fragment and send the packet.
* *
* This function cuts off the end of the packet (step=0) or * This function cuts off the end of the packet (step=0) or

Loading…
Cancel
Save