|
@@ -31,8 +31,10 @@
|
|
|
* 0 on success, 1 on failure
|
|
|
*/
|
|
|
int replace_packet(flow *f, struct packet_info *info){
|
|
|
+ printf("Enter replace_packet\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
- if (info->tcp_hdr == NULL){
|
|
|
+ if (info == NULL || info->tcp_hdr == NULL){
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -61,6 +63,10 @@ int replace_packet(flow *f, struct packet_info *info){
|
|
|
uint32_t offset = htonl(info->tcp_hdr->sequence_num) - f->seq_num;
|
|
|
if(offset == 0)
|
|
|
f->seq_num += info->app_data_len;
|
|
|
+ else
|
|
|
+ printf("Offset is nonzero\n");
|
|
|
+
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
|
|
|
process_downstream(f, offset, info);
|
|
@@ -79,6 +85,8 @@ int replace_packet(flow *f, struct packet_info *info){
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
+ printf("Done replace_packet\n");
|
|
|
+ fflush(stdout);
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
@@ -101,6 +109,9 @@ int replace_packet(flow *f, struct packet_info *info){
|
|
|
int read_header(flow *f, struct packet_info *info){
|
|
|
uint8_t *p = info->app_data;
|
|
|
|
|
|
+ printf("IN read_header\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
if (info->tcp_hdr == NULL){
|
|
|
return 0;
|
|
|
}
|
|
@@ -108,17 +119,26 @@ int read_header(flow *f, struct packet_info *info){
|
|
|
struct record_header *record_hdr = (struct record_header*) p;
|
|
|
uint32_t record_length = RECORD_LEN(record_hdr);
|
|
|
|
|
|
+ printf("HERE\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
uint8_t *decrypted_data = calloc(1, info->app_data_len);
|
|
|
|
|
|
+ printf("HERE2\n");
|
|
|
+ fflush(stdout);
|
|
|
p+= RECORD_HEADER_LEN;
|
|
|
|
|
|
memcpy(decrypted_data, p, record_length);
|
|
|
+ printf("HERE3\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
if(!encrypt(f, decrypted_data, decrypted_data, record_length, 0, record_hdr->type, 0)){
|
|
|
fprintf(stdout,"upstream decryption failed\n");
|
|
|
+ fflush(stdout);
|
|
|
return 0;
|
|
|
} else {
|
|
|
fprintf(stdout, "upstream decryption succeeded\n");
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
|
|
|
if(record_hdr->type == 0x15){
|
|
@@ -129,9 +149,13 @@ int read_header(flow *f, struct packet_info *info){
|
|
|
fflush(stdout);
|
|
|
}
|
|
|
|
|
|
+ printf("Upstream data:\n");
|
|
|
+ printf("%s\n", decrypted_data+EVP_GCM_TLS_EXPLICIT_IV_LEN);
|
|
|
+
|
|
|
|
|
|
|
|
|
char *header_ptr = strstr((const char *) decrypted_data, "X-Slitheen");
|
|
|
+
|
|
|
uint8_t *upstream_data;
|
|
|
if(header_ptr == NULL){
|
|
|
printf("UPSTREAM: No x-slitheen header found\n");
|
|
@@ -142,64 +166,174 @@ int read_header(flow *f, struct packet_info *info){
|
|
|
fprintf(stdout, "Sequence number: %d\n", info->tcp_hdr->sequence_num);
|
|
|
|
|
|
header_ptr += strlen("X-Slitheen: ");
|
|
|
+ int32_t num_messages = 1;
|
|
|
+ char *messages[50];
|
|
|
+ messages[0] = header_ptr;
|
|
|
char *c = header_ptr;
|
|
|
while(*c != '\r'){
|
|
|
+ if(*c == ' '){
|
|
|
+ *c = '\0';
|
|
|
+ messages[num_messages] = c+1;
|
|
|
+ num_messages ++;
|
|
|
+ }
|
|
|
c++;
|
|
|
}
|
|
|
c++;
|
|
|
*c = '\0';
|
|
|
- printf("upstream data: %s\n", header_ptr);
|
|
|
-
|
|
|
-
|
|
|
- int32_t decode_len = strlen(header_ptr);
|
|
|
- if(header_ptr[decode_len-2] == '='){
|
|
|
- decode_len = decode_len*3/4 - 2;
|
|
|
- } else if(header_ptr[decode_len-1] == '='){
|
|
|
- decode_len = decode_len*3/4 - 1;
|
|
|
- } else {
|
|
|
- decode_len = decode_len*3/4;
|
|
|
- }
|
|
|
+ printf("upstream data (%d messages):\n", num_messages);
|
|
|
|
|
|
- upstream_data = calloc(1, decode_len + 1);
|
|
|
+ for(int i=0; i< num_messages-1; i++){
|
|
|
+ char *message = messages[i];
|
|
|
+ printf("Message (%d bytes): %s\n", strlen(message), message);
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
- BIO *bio, *b64;
|
|
|
- bio = BIO_new_mem_buf(header_ptr, -1);
|
|
|
- b64 = BIO_new(BIO_f_base64());
|
|
|
- bio = BIO_push(b64, bio);
|
|
|
- BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
|
|
|
+
|
|
|
+ int32_t decode_len = strlen(message);
|
|
|
+ if(message[decode_len-2] == '='){
|
|
|
+ decode_len = decode_len*3/4 - 2;
|
|
|
+ } else if(message[decode_len-1] == '='){
|
|
|
+ decode_len = decode_len*3/4 - 1;
|
|
|
+ } else {
|
|
|
+ decode_len = decode_len*3/4;
|
|
|
+ }
|
|
|
|
|
|
- int32_t output_len = BIO_read(bio, upstream_data, strlen(header_ptr));
|
|
|
- if(output_len != decode_len)
|
|
|
- printf("UH OH, lens dont match\n");
|
|
|
+ upstream_data = calloc(1, decode_len + 1);
|
|
|
+ printf("HERE\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
- printf("Decoded to get %d bytes:\n", output_len);
|
|
|
- for(int i=0; i< output_len; i++){
|
|
|
- printf("%02x ", upstream_data[i]);
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
- uint8_t stream_id = upstream_data[0];
|
|
|
- p = upstream_data +1;
|
|
|
+ BIO *bio, *b64;
|
|
|
+ bio = BIO_new_mem_buf(message, -1);
|
|
|
+ printf("HERE 2\n");
|
|
|
+ fflush(stdout);
|
|
|
+ b64 = BIO_new(BIO_f_base64());
|
|
|
+ printf("HERE 3\n");
|
|
|
+ fflush(stdout);
|
|
|
+ bio = BIO_push(b64, bio);
|
|
|
+ printf("HERE 4\n");
|
|
|
+ fflush(stdout);
|
|
|
+ BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
|
|
|
+ printf("HERE 5\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
- printf("Received bytes with stream id %d\n", stream_id);
|
|
|
+ int32_t output_len = BIO_read(bio, upstream_data, strlen(message));
|
|
|
+ printf("HERE 6\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
-
|
|
|
-
|
|
|
+ BIO_free_all(bio);
|
|
|
+ if(output_len != decode_len)
|
|
|
+ printf("UH OH, lens dont match\n. %d != %d", decode_len, output_len);
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
-
|
|
|
- pthread_t *proxy_thread = calloc(1, sizeof(pthread_t));
|
|
|
- int32_t pipefd[2];
|
|
|
- if(pipe(pipefd) < 0){
|
|
|
- printf("Failed to create pipe for new thread\n");
|
|
|
- return 1;
|
|
|
- }
|
|
|
+ printf("Decoded to get %d bytes:\n", output_len);
|
|
|
+ for(int i=0; i< output_len; i++){
|
|
|
+ printf("%02x ", upstream_data[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
- struct proxy_thread_data *thread_data =
|
|
|
- calloc(1, sizeof(struct proxy_thread_data));
|
|
|
- thread_data->initial_data = upstream_data;
|
|
|
- thread_data->f = f;
|
|
|
- thread_data->pipefd = pipefd[0];
|
|
|
-
|
|
|
- pthread_create(proxy_thread, NULL, proxy_covert_site, (void *) thread_data);
|
|
|
+ p = upstream_data;
|
|
|
+
|
|
|
+ while(output_len > 0){
|
|
|
+ printf("Bytes left to process: %d\n", output_len);
|
|
|
+ fflush(stdout);
|
|
|
+ struct sl_up_hdr *sl_hdr = (struct sl_up_hdr *) p;
|
|
|
+ uint8_t stream_id = sl_hdr->stream_id;
|
|
|
+ uint16_t stream_len = ntohs(sl_hdr->len);
|
|
|
+
|
|
|
+ p += sizeof(struct sl_up_hdr);
|
|
|
+ output_len -= sizeof(struct sl_up_hdr);
|
|
|
+ if(stream_len > output_len)
|
|
|
+ printf("UH OH missing part of stream\n");
|
|
|
+
|
|
|
+ printf("Received bytes with stream id %d of len %d\n", stream_id, stream_len);
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+
|
|
|
+ int32_t stream_pipe = -1;
|
|
|
+ if(streams->first != NULL){
|
|
|
+ stream *last = streams->first;
|
|
|
+ if(last->stream_id == stream_id){
|
|
|
+ printf("Found stream in table!\n");
|
|
|
+ fflush(stdout);
|
|
|
+ stream_pipe = last->pipefd;
|
|
|
+ }
|
|
|
+ while(last->next != NULL){
|
|
|
+ last = last->next;
|
|
|
+ if(last->stream_id == stream_id){
|
|
|
+ printf("Found stream in table!\n");
|
|
|
+ fflush(stdout);
|
|
|
+ stream_pipe = last->pipefd;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(stream_pipe != -1){
|
|
|
+ int32_t bytes_sent = write(stream_pipe, p, stream_len);
|
|
|
+ if(bytes_sent < 0){
|
|
|
+ printf("Error writing to stream pipe\n");
|
|
|
+ fflush(stdout);
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ printf("Stream not found\n");
|
|
|
+ printf("Adding thread\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+
|
|
|
+ pthread_t *proxy_thread = calloc(1, sizeof(pthread_t));
|
|
|
+ int32_t pipefd[2];
|
|
|
+ if(pipe(pipefd) < 0){
|
|
|
+ printf("Failed to create pipe for new thread\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ uint8_t *initial_data = calloc(1,stream_len);
|
|
|
+ memcpy(initial_data, p, stream_len);
|
|
|
+
|
|
|
+ struct proxy_thread_data *thread_data =
|
|
|
+ calloc(1, sizeof(struct proxy_thread_data));
|
|
|
+ thread_data->initial_data = initial_data;
|
|
|
+ thread_data->initial_len = stream_len;
|
|
|
+ thread_data->f = f;
|
|
|
+ thread_data->stream_id = stream_id;
|
|
|
+ thread_data->pipefd = pipefd[0];
|
|
|
+
|
|
|
+ pthread_create(proxy_thread, NULL, proxy_covert_site, (void *) thread_data);
|
|
|
+
|
|
|
+
|
|
|
+ stream *new_stream = calloc(1, sizeof(stream));
|
|
|
+ new_stream->stream_id = stream_id;
|
|
|
+ new_stream->pipefd = pipefd[1];
|
|
|
+
|
|
|
+ if(streams->first == NULL){
|
|
|
+ streams->first = new_stream;
|
|
|
+ } else {
|
|
|
+ stream *last = streams->first;
|
|
|
+ while(last->next != NULL){
|
|
|
+ last = last->next;
|
|
|
+ }
|
|
|
+ last->next = new_stream;
|
|
|
+ }
|
|
|
+ printf("Added new stream to table\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+ }
|
|
|
+ printf("Finished processing %d data\n", stream_len);
|
|
|
+ fflush(stdout);
|
|
|
+ output_len -= stream_len;
|
|
|
+ p += stream_len;
|
|
|
+ printf("Done adding thread\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+ }
|
|
|
+ printf("Finished processing bytes\n");
|
|
|
+ fflush(stdout);
|
|
|
+ printf("Freeing %p\n", upstream_data);
|
|
|
+ fflush(stdout);
|
|
|
+ free(upstream_data);
|
|
|
+ }
|
|
|
+ printf("Finished processing messages\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
|
|
|
|
|
@@ -209,13 +343,19 @@ int read_header(flow *f, struct packet_info *info){
|
|
|
if(bytes_written < strlen( (const char *) message)){
|
|
|
printf("failed to write all bytes to pipe\n");
|
|
|
}*/
|
|
|
+ free(decrypted_data);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
err:
|
|
|
if(upstream_data != NULL){
|
|
|
+ printf("Freeing %p\n", upstream_data);
|
|
|
+ fflush(stdout);
|
|
|
free(upstream_data);
|
|
|
}
|
|
|
+ if(decrypted_data != NULL){
|
|
|
+ free(decrypted_data);
|
|
|
+ }
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -239,14 +379,21 @@ void *proxy_covert_site(void *data){
|
|
|
flow *f = thread_data->f;
|
|
|
|
|
|
uint8_t *p = thread_data->initial_data;
|
|
|
- uint8_t stream_id = p[0];
|
|
|
- p++;
|
|
|
+ uint8_t stream_id = thread_data->stream_id;
|
|
|
+
|
|
|
+ printf("request: ");
|
|
|
+ for(int i=0; i< sizeof(struct socks_req); i++){
|
|
|
+ printf("%02x ", p[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
struct socks_req *clnt_req = (struct socks_req *) p;
|
|
|
p += 4;
|
|
|
|
|
|
|
|
|
if(clnt_req->cmd != 0x01){
|
|
|
printf("Error: issued a non-connect command\n");
|
|
|
+ fflush(stdout);
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
@@ -259,6 +406,7 @@ void *proxy_covert_site(void *data){
|
|
|
|
|
|
dest.sin_addr.s_addr = *((uint32_t*) p);
|
|
|
printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
|
|
|
+ fflush(stdout);
|
|
|
p += 4;
|
|
|
break;
|
|
|
|
|
@@ -273,8 +421,11 @@ void *proxy_covert_site(void *data){
|
|
|
host = gethostbyname((const char *) domain_name);
|
|
|
dest.sin_addr = *((struct in_addr *) host->h_addr);
|
|
|
printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
p += domain_len;
|
|
|
+ printf("Freeing %p\n", domain_name);
|
|
|
+ fflush(stdout);
|
|
|
free(domain_name);
|
|
|
break;
|
|
|
case 0x04:
|
|
@@ -286,10 +437,12 @@ void *proxy_covert_site(void *data){
|
|
|
|
|
|
dest.sin_port = *((uint16_t *) p);
|
|
|
printf("destination port: %d\n", ntohs(dest.sin_port));
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
int32_t handle = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
if(handle < 0){
|
|
|
printf("error: constructing socket failed\n");
|
|
|
+ fflush(stdout);
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
@@ -300,6 +453,7 @@ void *proxy_covert_site(void *data){
|
|
|
|
|
|
if(error <0){
|
|
|
printf("error connecting\n");
|
|
|
+ fflush(stdout);
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
@@ -320,6 +474,7 @@ void *proxy_covert_site(void *data){
|
|
|
printf("%02x ", response[i]);
|
|
|
}
|
|
|
printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
queue_block *new_block = calloc(1, sizeof(queue_block));
|
|
|
printf("Inserting new block into queue: %p\n", new_block);
|
|
@@ -340,9 +495,10 @@ void *proxy_covert_site(void *data){
|
|
|
last = last->next;
|
|
|
last->next = new_block;
|
|
|
}
|
|
|
- return 0;
|
|
|
|
|
|
-
|
|
|
+ uint8_t *buffer = calloc(1, BUFSIZ);
|
|
|
+ int32_t buffer_len = BUFSIZ;
|
|
|
+
|
|
|
for(;;){
|
|
|
fd_set readfds;
|
|
|
fd_set writefds;
|
|
@@ -359,26 +515,34 @@ void *proxy_covert_site(void *data){
|
|
|
|
|
|
if (select(nfds, &readfds, &writefds, NULL, NULL) < 0){
|
|
|
printf("select error\n");
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
|
|
|
if(FD_ISSET(thread_data->pipefd, &readfds) && FD_ISSET(handle, &writefds)){
|
|
|
|
|
|
printf("Passing along upstream data\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
int32_t bytes_read = read(thread_data->pipefd, buffer, buffer_len);
|
|
|
- buffer[buffer_len] = '\0';
|
|
|
- printf("Read from pipe:\n %s\n", buffer);
|
|
|
+ printf("Read from stream pipe:\n");
|
|
|
+ for(int i=0; i< bytes_read; i++){
|
|
|
+ printf("%02x ", buffer[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
if(bytes_read > 0){
|
|
|
int32_t bytes_sent = send(handle, buffer,
|
|
|
bytes_read, 0);
|
|
|
if( bytes_sent < 0){
|
|
|
printf("error sending request\n");
|
|
|
+ fflush(stdout);
|
|
|
break;
|
|
|
} else if (bytes_sent < bytes_read){
|
|
|
|
|
|
|
|
|
printf("sent less than full upstream bytes\n");
|
|
|
+ fflush(stdout);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -386,42 +550,60 @@ void *proxy_covert_site(void *data){
|
|
|
}
|
|
|
|
|
|
if (FD_ISSET(handle, &readfds)){
|
|
|
+ printf("Received downstream data\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
int32_t bytes_read;
|
|
|
- uint8_t *buf = calloc(1, BUFSIZ);
|
|
|
- bytes_read = recv(handle, buf, BUFSIZ, 0);
|
|
|
+ bytes_read = recv(handle, buffer, buffer_len, 0);
|
|
|
if(bytes_read <= 0){
|
|
|
break;
|
|
|
}
|
|
|
if(bytes_read > 0){
|
|
|
+ printf("Stream %d read %d downstream bytes:\n", stream_id, bytes_read);
|
|
|
+ for(int i=0; i< bytes_read; i++){
|
|
|
+ printf("%02x ", buffer[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
+ uint8_t *new_data = calloc(1, bytes_read);
|
|
|
+ memcpy(new_data, buffer, bytes_read);
|
|
|
|
|
|
|
|
|
new_block = calloc(1, sizeof(queue_block));
|
|
|
+ printf("Inserting new block into queue: %p\n", new_block);
|
|
|
+ fflush(stdout);
|
|
|
new_block->len = bytes_read;
|
|
|
new_block->offset = 0;
|
|
|
- new_block->data = buf;
|
|
|
+ new_block->data = new_data;
|
|
|
new_block->next = NULL;
|
|
|
- if(f->censored_queue == NULL)
|
|
|
- f->censored_queue = new_block;
|
|
|
+ new_block->stream_id = stream_id;
|
|
|
+ printf("downstream_queue is at %p\n", downstream_queue);
|
|
|
+ fflush(stdout);
|
|
|
+ if(downstream_queue->first_block == NULL){
|
|
|
+ downstream_queue->first_block = new_block;
|
|
|
+ }
|
|
|
else{
|
|
|
- queue_block *last = f->censored_queue;
|
|
|
+ queue_block *last = downstream_queue->first_block;
|
|
|
while(last->next != NULL)
|
|
|
last = last->next;
|
|
|
last->next = new_block;
|
|
|
}
|
|
|
} else {
|
|
|
printf("read 0 bytes\n");
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
+ printf("Freeing: %p, %p\n", thread_data, buffer);
|
|
|
free(thread_data);
|
|
|
free(buffer);
|
|
|
close(handle);
|
|
|
- */
|
|
|
return 0;
|
|
|
err:
|
|
|
if(thread_data->initial_data != NULL){
|
|
|
+ printf("Freeing %p\n", thread_data->initial_data);
|
|
|
+ fflush(stdout);
|
|
|
free(thread_data->initial_data);
|
|
|
}
|
|
|
close(handle);
|
|
@@ -444,6 +626,8 @@ err:
|
|
|
* Returns 0 on sucess
|
|
|
*/
|
|
|
int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
+ printf("Enter process_downstream\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
printf("Processing downstream data\n");
|
|
|
uint8_t changed = 0;
|
|
@@ -457,10 +641,35 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
if(f->remaining_record_len > 0){
|
|
|
|
|
|
if(f->remaining_record_len > remaining_packet_len){
|
|
|
+ if(f->outbox_len > 0){
|
|
|
+ changed = 1;
|
|
|
+ printf("First byte to copy: %02x %02x\n", f->outbox[f->outbox_offset], f->outbox[f->outbox_offset+1]);
|
|
|
+ memcpy(p, f->outbox + f->outbox_offset, remaining_packet_len);
|
|
|
+ f->outbox_len -= remaining_packet_len;
|
|
|
+ f->outbox_offset += remaining_packet_len;
|
|
|
+ printf("Copied %d bytes from outbox %p at offset %d, %d bytes left to ignore\n", remaining_packet_len, f->outbox, f->outbox_offset, f->outbox_len);
|
|
|
+
|
|
|
+ }
|
|
|
f->remaining_record_len -= remaining_packet_len;
|
|
|
- printf("Ignoring %d bytes, %d bytes left to ignore\n", remaining_packet_len, f->remaining_record_len);
|
|
|
+ printf("Ignored/copied %d bytes, %d bytes left to ignore\n", remaining_packet_len, f->remaining_record_len);
|
|
|
remaining_packet_len -= remaining_packet_len;
|
|
|
} else {
|
|
|
+ if(f->outbox_len > 0){
|
|
|
+ changed = 1;
|
|
|
+ memcpy(p, f->outbox + f->outbox_offset, f->remaining_record_len);
|
|
|
+ if(f->outbox_len != f->remaining_record_len){
|
|
|
+ printf("UH OH: outbox (%d bytes left) and record (%d bytes left) did not align\n", f->outbox_len, f->remaining_record_len);
|
|
|
+ }
|
|
|
+ printf("Copied %d bytes from outbox, 0 bytes left to ignore\n", f->remaining_record_len);
|
|
|
+ printf("Copied %d bytes from outbox %p at offset %d, %d bytes left to ignore\n", f->remaining_record_len, f->outbox, f->outbox_offset, 0);
|
|
|
+ printf("First byte copied: %02x %02x\n", p[0], p[1]);
|
|
|
+ f->outbox_len = 0;
|
|
|
+ f->outbox_offset=0;
|
|
|
+ printf("Freeing %p\n", f->outbox);
|
|
|
+ fflush(stdout);
|
|
|
+ free(f->outbox);
|
|
|
+ }
|
|
|
+
|
|
|
p += f->remaining_record_len;
|
|
|
printf("Ignoring %d bytes\n", f->remaining_record_len);
|
|
|
remaining_packet_len -= f->remaining_record_len;
|
|
@@ -482,6 +691,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
printf("%02x ", p[i]);
|
|
|
}
|
|
|
printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
p += RECORD_HEADER_LEN;
|
|
|
remaining_packet_len -= RECORD_HEADER_LEN;
|
|
@@ -490,42 +700,86 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
uint32_t remaining_record_len = record_len;
|
|
|
|
|
|
if(record_len > remaining_packet_len){
|
|
|
-
|
|
|
printf("Record is too long\n");
|
|
|
+ fflush(stdout);
|
|
|
f->remaining_record_len = record_len - remaining_packet_len;
|
|
|
- remaining_packet_len -= remaining_packet_len;
|
|
|
|
|
|
if(f->httpstate == PARSE_HEADER || f->httpstate == BEGIN_CHUNK || f->httpstate == END_CHUNK){
|
|
|
f->httpstate = FORFEIT_REST;
|
|
|
} else if( f->httpstate == MID_CONTENT || f->httpstate == MID_CHUNK){
|
|
|
f->remaining_response_len -= record_len - 24;
|
|
|
printf("remaining response len: %d\n", f->remaining_response_len);
|
|
|
+ fflush(stdout);
|
|
|
+ if(f->remaining_response_len >= 0 && f->replace_response){
|
|
|
+ printf("Should be replacing this\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+
|
|
|
+ f->outbox = calloc(1, record_len+1);
|
|
|
+ f->outbox_len = record_len;
|
|
|
+ f->outbox_offset = 0;
|
|
|
+ fill_with_downstream(f, f->outbox + EVP_GCM_TLS_EXPLICIT_IV_LEN , record_len - (EVP_GCM_TLS_EXPLICIT_IV_LEN+ 16));
|
|
|
+
|
|
|
+ printf("Encrypting outbox\n");
|
|
|
+ fflush(stdout);
|
|
|
+ int32_t n = encrypt(f, f->outbox, f->outbox,
|
|
|
+ record_len - 16, 1,
|
|
|
+ record_hdr->type, 1);
|
|
|
+ if(n < 0){
|
|
|
+ fprintf(stdout,"outbox encryption failed\n");
|
|
|
+ fflush(stdout);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ printf("Record len was: %d. Outbox len is: %d\n", record_len, n);
|
|
|
+ fflush(stdout);
|
|
|
+ memcpy(p, f->outbox, remaining_packet_len);
|
|
|
+ changed = 1;
|
|
|
+ f->outbox_len -= remaining_packet_len;
|
|
|
+ f->outbox_offset += remaining_packet_len;
|
|
|
+ printf("Copied %d from outbox. Offset is at %d\n", remaining_packet_len, f->outbox_offset);
|
|
|
+ fflush(stdout);
|
|
|
+ }
|
|
|
+ printf("Outbox encryption successful!\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+
|
|
|
+ } else if(f->replace_response){
|
|
|
+ printf("record_len exceeds response len by %d\n", f->remaining_response_len);
|
|
|
+ fflush(stdout);
|
|
|
+ }
|
|
|
if(f->remaining_response_len == 0){
|
|
|
if(f->httpstate == MID_CHUNK)
|
|
|
f->httpstate = END_CHUNK;
|
|
|
- else
|
|
|
- f->httpstate = END_BODY;
|
|
|
+ else {
|
|
|
+ printf("END_CONTENT\n");
|
|
|
+ fflush(stdout);
|
|
|
+ f->httpstate = PARSE_HEADER;
|
|
|
+ }
|
|
|
}
|
|
|
if(f->remaining_response_len < 0){
|
|
|
f->remaining_response_len = 0;
|
|
|
f->httpstate = FORFEIT_REST;
|
|
|
}
|
|
|
}
|
|
|
+ remaining_packet_len -= remaining_packet_len;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
printf("Decrypting record\n");
|
|
|
+ fflush(stdout);
|
|
|
int32_t n = encrypt(f, record_ptr, record_ptr, record_len, 1,
|
|
|
record_hdr->type, 0);
|
|
|
if(n < 0){
|
|
|
|
|
|
fprintf(stdout,"application decryption failed\n");
|
|
|
+ fflush(stdout);
|
|
|
return 0;
|
|
|
}
|
|
|
changed = 1;
|
|
|
printf("Decryption succeeded\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
printf("Bytes:\n");
|
|
|
for(int i=0; i< n; i++){
|
|
@@ -534,6 +788,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
printf("\n");
|
|
|
printf("Text:\n");
|
|
|
printf("%s\n", record_ptr+EVP_GCM_TLS_EXPLICIT_IV_LEN);
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
char *len_ptr, *needle;
|
|
@@ -546,10 +801,31 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
|
|
|
case PARSE_HEADER:
|
|
|
|
|
|
+ printf("IN PARSE HEADER\n");
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
+ len_ptr = strstr((const char *) p, "Content-Type: image");
|
|
|
+ if(len_ptr != NULL){
|
|
|
+ printf("SLITHEEN: replaceable content\n");
|
|
|
+ fflush(stdout);
|
|
|
+ f->replace_response = 1;
|
|
|
+ memcpy(len_ptr + 14, "slitheen", 8);
|
|
|
+ char *c = len_ptr + 14+8;
|
|
|
+ while(c[0] != '\r'){
|
|
|
+ c[0] = ' ';
|
|
|
+ c++;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ printf("SLITHEEN: non-replaceable content\n");
|
|
|
+ fflush(stdout);
|
|
|
+ f->replace_response = 0;
|
|
|
+ }
|
|
|
+
|
|
|
len_ptr = strstr((const char *) p, "Transfer-Encoding");
|
|
|
if(len_ptr != NULL){
|
|
|
if(!memcmp(len_ptr + 19, "chunked", 7)){
|
|
|
printf("SLITHEEN: transfer chunked\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
|
|
|
len_ptr = strstr((const char *) p, "\r\n\r\n");
|
|
@@ -558,6 +834,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
remaining_record_len -= (((uint8_t *)len_ptr - p) + 4);
|
|
|
p = (uint8_t *) len_ptr + 4;
|
|
|
printf("remaining record len: %d\n", remaining_record_len);
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
@@ -566,14 +843,17 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
len_ptr += 15;
|
|
|
f->remaining_response_len = strtol((const char *) len_ptr, NULL, 10);
|
|
|
printf("SLITHEEN: Content-Length: %d\n", f->remaining_response_len);
|
|
|
+ fflush(stdout);
|
|
|
len_ptr = strstr((const char *) p, "\r\n\r\n");
|
|
|
if(len_ptr != NULL){
|
|
|
f->httpstate = MID_CONTENT;
|
|
|
remaining_record_len -= (((uint8_t *)len_ptr - p) + 4);
|
|
|
p = (uint8_t *) len_ptr + 4;
|
|
|
printf("remaining record len: %d\n", remaining_record_len);
|
|
|
+ fflush(stdout);
|
|
|
} else {
|
|
|
printf("UH OH\n");
|
|
|
+ fflush(stdout);
|
|
|
remaining_record_len = 0;
|
|
|
f->httpstate = FORFEIT_REST;
|
|
|
}
|
|
@@ -583,40 +863,31 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- len_ptr = strstr((const char *) record_ptr, "Content-Type: image");
|
|
|
- if(len_ptr != NULL){
|
|
|
- printf("SLITHEEN: replaceable content\n");
|
|
|
- f->replace_response = 1;
|
|
|
- memcpy(len_ptr + 14, "slitheen", 8);
|
|
|
- char *c = len_ptr + 14+8;
|
|
|
- while(c[0] != '\r'){
|
|
|
- c[0] = ' ';
|
|
|
- c++;
|
|
|
- }
|
|
|
- } else {
|
|
|
- printf("SLITHEEN: non-replaceable content\n");
|
|
|
- f->replace_response = 0;
|
|
|
- }
|
|
|
break;
|
|
|
|
|
|
case MID_CONTENT:
|
|
|
|
|
|
printf("In MID_CONTENT\n");
|
|
|
+ fflush(stdout);
|
|
|
if(f->remaining_response_len > remaining_record_len){
|
|
|
if(f->replace_response){
|
|
|
fill_with_downstream(f, p, remaining_record_len);
|
|
|
printf("Replaced with:\n");
|
|
|
+ fflush(stdout);
|
|
|
for(int i=0; i< remaining_record_len; i++){
|
|
|
printf("%02x ", p[i]);
|
|
|
}
|
|
|
printf("\n");
|
|
|
+ } else {
|
|
|
+ printf("Non-replaceable content\n");
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
f->remaining_response_len -= remaining_record_len;
|
|
|
p += remaining_record_len;
|
|
|
|
|
|
remaining_record_len = 0;
|
|
|
printf("%d bytes left of body\n", f->remaining_response_len);
|
|
|
+ fflush(stdout);
|
|
|
} else {
|
|
|
if(f->replace_response){
|
|
|
fill_with_downstream(f, p, remaining_record_len);
|
|
@@ -625,20 +896,27 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
printf("%02x ", p[i]);
|
|
|
}
|
|
|
printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
+ } else {
|
|
|
+ printf("Non-replaceable content\n");
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
remaining_record_len -= f->remaining_response_len;
|
|
|
p += f->remaining_response_len;
|
|
|
f->httpstate = PARSE_HEADER;
|
|
|
f->remaining_response_len = 0;
|
|
|
printf("rem. response len = %d\n", f->remaining_response_len);
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case BEGIN_CHUNK:
|
|
|
printf("In BEGIN_CHUNK\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
int32_t chunk_size = strtol((const char *) p, NULL, 16);
|
|
|
printf("chunk size: %x\n", chunk_size);
|
|
|
+ fflush(stdout);
|
|
|
if(chunk_size == 0){
|
|
|
f->httpstate = END_BODY;
|
|
|
} else {
|
|
@@ -650,8 +928,10 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
remaining_record_len -= ((uint8_t *) needle - p + 2);
|
|
|
p = (uint8_t *) needle + 2;
|
|
|
printf("remaining_record len = %d\n", remaining_record_len);
|
|
|
+ fflush(stdout);
|
|
|
} else {
|
|
|
printf("UH OH\n");
|
|
|
+ fflush(stdout);
|
|
|
remaining_record_len = 0;
|
|
|
f->httpstate = FORFEIT_REST;
|
|
|
}
|
|
@@ -659,6 +939,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
|
|
|
case MID_CHUNK:
|
|
|
printf("In MID_CHUNK\n");
|
|
|
+ fflush(stdout);
|
|
|
if(f->remaining_response_len > remaining_record_len){
|
|
|
if(f->replace_response){
|
|
|
fill_with_downstream(f, p, remaining_record_len);
|
|
@@ -667,12 +948,14 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
printf("%02x ", p[i]);
|
|
|
}
|
|
|
printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
f->remaining_response_len -= remaining_record_len;
|
|
|
p += remaining_record_len;
|
|
|
|
|
|
remaining_record_len = 0;
|
|
|
printf("%d bytes left of chunk\n", f->remaining_response_len);
|
|
|
+ fflush(stdout);
|
|
|
} else {
|
|
|
if(f->replace_response){
|
|
|
fill_with_downstream(f, p, remaining_record_len);
|
|
@@ -681,16 +964,19 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
printf("%02x ", p[i]);
|
|
|
}
|
|
|
printf("\n");
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
remaining_record_len -= f->remaining_response_len;
|
|
|
p += f->remaining_response_len;
|
|
|
f->httpstate = END_CHUNK;
|
|
|
printf("rem. record len = %d\n", f->remaining_record_len);
|
|
|
+ fflush(stdout);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case END_CHUNK:
|
|
|
printf("In END_CHUNK\n");
|
|
|
+ fflush(stdout);
|
|
|
needle = strstr((const char *) p, "\r\n");
|
|
|
if(needle != NULL){
|
|
|
f->httpstate = BEGIN_CHUNK;
|
|
@@ -698,6 +984,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
remaining_record_len -= 2;
|
|
|
} else {
|
|
|
printf("UH OH\n");
|
|
|
+ fflush(stdout);
|
|
|
remaining_record_len = 0;
|
|
|
f->httpstate = FORFEIT_REST;
|
|
|
}
|
|
@@ -705,6 +992,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
|
|
|
case END_BODY:
|
|
|
printf("In END_BODY\n");
|
|
|
+ fflush(stdout);
|
|
|
needle = strstr((const char *) p, "\r\n");
|
|
|
if(needle != NULL){
|
|
|
f->httpstate = PARSE_HEADER;
|
|
@@ -712,6 +1000,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
remaining_record_len -= 2;
|
|
|
} else {
|
|
|
printf("UH OH\n");
|
|
|
+ fflush(stdout);
|
|
|
remaining_record_len = 0;
|
|
|
f->httpstate = FORFEIT_REST;
|
|
|
}
|
|
@@ -719,6 +1008,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
|
|
|
case FORFEIT_REST:
|
|
|
printf("In FORFEIT_REST\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
case USE_REST:
|
|
|
remaining_record_len = 0;
|
|
@@ -760,6 +1050,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
|
|
|
*/
|
|
|
printf("Re-encrypting record\n");
|
|
|
+ fflush(stdout);
|
|
|
if((n = encrypt(f, record_ptr, record_ptr,
|
|
|
n + EVP_GCM_TLS_EXPLICIT_IV_LEN, 1, record_hdr->type,
|
|
|
1)) < 0){
|
|
@@ -767,6 +1058,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
|
|
|
return 0;
|
|
|
}
|
|
|
printf("Encryption successful!\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
p = record_ptr + record_len;
|
|
|
remaining_packet_len -= record_len;
|
|
@@ -1025,15 +1317,19 @@ reencrypt:
|
|
|
*/
|
|
|
|
|
|
if(changed){
|
|
|
- tcp_checksum(info);
|
|
|
- printf("Computing checksum\n");
|
|
|
+ uint16_t sum = tcp_checksum(info);
|
|
|
+ printf("Computed checksum: %u\n", sum);
|
|
|
fflush(stdout);
|
|
|
}
|
|
|
|
|
|
+ printf("Done process_downstream\n");
|
|
|
+ fflush(stdout);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
|
|
|
+ printf("Enter filling with ds data\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
uint8_t *p = data;
|
|
|
int32_t remaining = length;
|
|
@@ -1048,7 +1344,7 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
|
|
|
|
|
|
printf("Censored queue is at %p.\n", first_block);
|
|
|
printf("This block has %d bytes left\n", block_length - offset);
|
|
|
- printf("We need %d bytes\n", remaining);
|
|
|
+ printf("We need %d bytes\n", remaining - SLITHEEN_HEADER_LEN);
|
|
|
|
|
|
|
|
|
sl_hdr = (struct slitheen_header *) p;
|
|
@@ -1069,15 +1365,26 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
|
|
|
|
|
|
memcpy(p, first_block->data+offset, block_length - offset);
|
|
|
|
|
|
+ printf("Freeing first block data (%p)\n", first_block->data);
|
|
|
+ fflush(stdout);
|
|
|
free(first_block->data);
|
|
|
+ printf("Freed first block data\n");
|
|
|
+ fflush(stdout);
|
|
|
downstream_queue->first_block = first_block->next;
|
|
|
free(first_block);
|
|
|
+ printf("Freed first block\n");
|
|
|
+ fflush(stdout);
|
|
|
|
|
|
p += (block_length - offset);
|
|
|
sl_hdr->len = (block_length - offset);
|
|
|
remaining -= (block_length - offset);
|
|
|
}
|
|
|
sl_hdr->len = htons(sl_hdr->len);
|
|
|
+ printf("DWNSTRM: slitheen header: ");
|
|
|
+ for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
|
|
|
+ printf("%02x ",((uint8_t *) sl_hdr)[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
}
|
|
|
|
|
|
if(remaining > SLITHEEN_HEADER_LEN ){
|
|
@@ -1085,11 +1392,18 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
|
|
|
sl_hdr = (struct slitheen_header *) p;
|
|
|
sl_hdr->stream_id = 0x00;
|
|
|
remaining -= SLITHEEN_HEADER_LEN;
|
|
|
- sl_hdr->len = remaining;
|
|
|
- sl_hdr->garbage = remaining;
|
|
|
+ sl_hdr->len = htons(remaining);
|
|
|
+ sl_hdr->garbage = htons(remaining);
|
|
|
+ printf("DWNSTRM: slitheen header: ");
|
|
|
+ for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
|
|
|
+ printf("%02x ", p[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
p += SLITHEEN_HEADER_LEN;
|
|
|
memset(p, 'A', remaining);
|
|
|
}
|
|
|
+ printf("Done filling with ds data\n");
|
|
|
+ fflush(stdout);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1140,8 +1454,10 @@ uint16_t tcp_checksum(struct packet_info *info){
|
|
|
if(info->app_data_len %2 != 0){
|
|
|
sum += (uint16_t) (p[info->app_data_len - 1]) << 8;
|
|
|
}
|
|
|
+
|
|
|
|
|
|
sum = (sum >> 16) + (sum & 0xFFFF);
|
|
|
+ sum += sum >>16;
|
|
|
|
|
|
sum = 0xFFFF - sum;
|
|
|
|