|
@@ -0,0 +1,205 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <stdint.h>
|
|
|
+#include <regex.h>
|
|
|
+#include <sys/socket.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <netinet/in.h>
|
|
|
+#include <netdb.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include "relay.h"
|
|
|
+#include "slitheen.h"
|
|
|
+#include "flow.h"
|
|
|
+#include "crypto.h"
|
|
|
+
|
|
|
+
|
|
|
+int replace_packet(flow *f, uint8_t *packet){
|
|
|
+ const struct ip_header *ip_hdr;
|
|
|
+ const struct tcp_header *tcp_hdr;
|
|
|
+
|
|
|
+ uint8_t *p = packet;
|
|
|
+
|
|
|
+ p += ETHER_HEADER_LEN; //skip ethernet header
|
|
|
+ ip_hdr = (struct ip_header*) p;
|
|
|
+ int size_ip = IP_HEADER_LEN(ip_hdr);
|
|
|
+
|
|
|
+ if (ip_hdr->proto != IPPROTO_TCP){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ p += size_ip; //skip IP header
|
|
|
+
|
|
|
+ tcp_hdr = (struct tcp_header*) p;
|
|
|
+ int size_tcp = TCP_HEADER_LEN(tcp_hdr);
|
|
|
+ p += size_tcp;
|
|
|
+
|
|
|
+ /*fprintf(stderr,"Flow: %d > %d (%s)\n", ip_hdr->src.s_addr, ip_hdr->dst.s_addr, (ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
|
|
|
+ fprintf(stderr,"ID number: %u\n", htonl(ip_hdr->id));
|
|
|
+ fprintf(stderr,"Sequence number: %u\n", htonl(tcp_hdr->sequence_num));
|
|
|
+ fprintf(stderr,"Acknowledgement number: %u\n", htonl(tcp_hdr->ack_num));*/
|
|
|
+ int app_data_len = htons(ip_hdr->len) - (size_ip + size_tcp);
|
|
|
+ if(app_data_len <= 0){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* if outgoing, decrypt and look at header */
|
|
|
+ if(ip_hdr->src.s_addr == f->src_ip.s_addr){
|
|
|
+ read_header(f, packet);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+int read_header(flow *f, uint8_t *packet){
|
|
|
+ const struct ip_header *ip_hdr;
|
|
|
+ const struct tcp_header *tcp_hdr;
|
|
|
+
|
|
|
+ uint8_t *p = packet;
|
|
|
+
|
|
|
+ p += ETHER_HEADER_LEN; //skip ethernet header
|
|
|
+ ip_hdr = (struct ip_header*) p;
|
|
|
+ int size_ip = IP_HEADER_LEN(ip_hdr);
|
|
|
+
|
|
|
+ if (ip_hdr->proto != IPPROTO_TCP){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ p += size_ip; //skip IP header
|
|
|
+
|
|
|
+ tcp_hdr = (struct tcp_header*) p;
|
|
|
+ int size_tcp = TCP_HEADER_LEN(tcp_hdr);
|
|
|
+ p += size_tcp;
|
|
|
+ int app_data_len = htons(ip_hdr->len) - (size_ip + size_tcp);
|
|
|
+
|
|
|
+ struct record_header *record_hdr = (struct record_header*) p;
|
|
|
+ uint32_t record_length = RECORD_LEN(record_hdr);
|
|
|
+ uint8_t *decrypted_data = calloc(1, app_data_len);
|
|
|
+
|
|
|
+ /*fprintf(stderr,"record:\n");
|
|
|
+ for(int i=0; i< RECORD_HEADER_LEN; i++){
|
|
|
+ fprintf(stderr,"%02x ", p[i]);
|
|
|
+ }
|
|
|
+ fprintf(stderr,"\n");*/
|
|
|
+ p+= RECORD_HEADER_LEN;
|
|
|
+
|
|
|
+ memcpy(decrypted_data, p, record_length);
|
|
|
+
|
|
|
+ if(!encrypt(f, decrypted_data, decrypted_data, record_length, 0, 0x17)){
|
|
|
+ fprintf(stderr,"decryption failed\n");
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ fprintf(stderr, "decryption succeeded!\n");
|
|
|
+ decrypted_data+= EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
|
|
+ fprintf(stderr, "request:");
|
|
|
+ fprintf(stderr,"%s\n ", decrypted_data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* search through decrypted data for x-ignore */
|
|
|
+ regex_t r;
|
|
|
+ const uint8_t *regex_text = "x-ignore";
|
|
|
+ const uint8_t *match = decrypted_data;
|
|
|
+ if(regcomp(&r, regex_text, REG_EXTENDED|REG_NEWLINE)){
|
|
|
+ printf("could not compile regex\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ regmatch_t m;
|
|
|
+ if(regexec(&r, match, 1, &m, 0)){
|
|
|
+ printf("no x-ignore found\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ uint8_t *message = decrypted_data;
|
|
|
+ //remove escape characters
|
|
|
+ for(int i=m.rm_eo+2; i< strlen(match); i++){
|
|
|
+ if(match[i] != '\\'){
|
|
|
+ *(message++) = match[i];
|
|
|
+ } else if (match[i+1] == 'r') {
|
|
|
+ *(message++) = '\r';
|
|
|
+ i++;
|
|
|
+ } else if (match[i+1] == 'n') {
|
|
|
+ *(message++) = '\n';
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ *message = '\0';
|
|
|
+ message = decrypted_data;
|
|
|
+
|
|
|
+ regex_t r2;
|
|
|
+ const uint8_t *regex_text2 = "host";
|
|
|
+ const uint8_t *match2 = decrypted_data;
|
|
|
+ regmatch_t m2;
|
|
|
+ if(regcomp(&r2, regex_text2, REG_EXTENDED|REG_NEWLINE)){
|
|
|
+ printf("could not compile regex\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if(regexec(&r2, match2, 1, &m2, 0)){
|
|
|
+ printf("no host found\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ uint8_t server[50];
|
|
|
+ for(int i=m2.rm_eo+2; i< strlen(match2); i++){
|
|
|
+ if(match2[i] != '\n'){
|
|
|
+ server[i-m2.rm_eo-2] = match2[i];
|
|
|
+ } else {
|
|
|
+ server[i-m2.rm_eo-2] = '\0';
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Send GET request to site */
|
|
|
+ printf("sending request to site: %s\n", server);
|
|
|
+
|
|
|
+ struct hostent *host;
|
|
|
+ host = gethostbyname((const char *) server);
|
|
|
+
|
|
|
+ if(host == NULL){
|
|
|
+ printf("gethostbyname failed\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ int32_t handle = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
+ if(handle < 0){
|
|
|
+ printf("error: constructing socket failed\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ printf("constructed socket\n");
|
|
|
+ struct sockaddr_in dest;
|
|
|
+ dest.sin_family = AF_INET;
|
|
|
+ dest.sin_port = htons(80);
|
|
|
+ dest.sin_addr = *((struct in_addr *) host->h_addr);
|
|
|
+ bzero (&(dest.sin_zero), 8);
|
|
|
+ printf("connecting...");
|
|
|
+ int32_t error = connect (handle, (struct sockaddr *) &dest, sizeof (struct sockaddr));
|
|
|
+ printf(" done\n");
|
|
|
+ if(error <0){
|
|
|
+ printf("error connecting\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ int32_t bytes_sent = send(handle, message, strlen(message), 0);
|
|
|
+ if( bytes_sent < 0){
|
|
|
+ printf("error sending request\n");
|
|
|
+ close(handle);
|
|
|
+ return 0;
|
|
|
+ } else if (bytes_sent < strlen(message)){
|
|
|
+ printf("send partial request\n");
|
|
|
+ close(handle);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("sent request!\n");
|
|
|
+ //change this to realloc and loop later
|
|
|
+ uint8_t *buf = calloc(1, 2048);
|
|
|
+ memset(buf, 0, 2048);
|
|
|
+ int32_t bytes_read = recv(handle, buf, 2048, 0);
|
|
|
+ printf("Received message:\n %s\n", buf);
|
|
|
+ for(int i=0; i< bytes_read; i++){
|
|
|
+ f->censored_queue[i] = buf[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ //for now, just close socket
|
|
|
+ close(handle);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+}
|