|
|
@ -7,181 +7,217 @@ |
|
|
|
|
|
|
|
struct ng_session *debug_socket; |
|
|
|
|
|
|
|
uint16_t packet_length = 100; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// pseudo header needed for tcp header checksum calculation |
|
|
|
struct pseudo_header |
|
|
|
{ |
|
|
|
u_int32_t source_address; |
|
|
|
u_int32_t dest_address; |
|
|
|
u_int8_t placeholder; |
|
|
|
u_int8_t protocol; |
|
|
|
u_int16_t tcp_length; |
|
|
|
}; |
|
|
|
|
|
|
|
int open_debug_socket(const struct arguments *args, int epoll_fd) { |
|
|
|
#define DATAGRAM_LEN 4096 |
|
|
|
#define OPT_SIZE 20 |
|
|
|
|
|
|
|
void *saddr; |
|
|
|
void *daddr; |
|
|
|
char source[INET6_ADDRSTRLEN + 1]; |
|
|
|
char dest[INET6_ADDRSTRLEN + 1]; |
|
|
|
unsigned short checksum(const char *buf, unsigned size) |
|
|
|
{ |
|
|
|
unsigned sum = 0, i; |
|
|
|
|
|
|
|
int version = 4; |
|
|
|
int uid = 0; |
|
|
|
|
|
|
|
uint16_t mss = get_default_mss(version); |
|
|
|
uint8_t ws = 8; |
|
|
|
|
|
|
|
int send_window = ntohs(65535); |
|
|
|
int sequence_number = ntohs(5000); |
|
|
|
|
|
|
|
int sport = ntohs(40404); |
|
|
|
int dport = ntohs(50508); |
|
|
|
|
|
|
|
|
|
|
|
int packet = 2; |
|
|
|
|
|
|
|
struct allowed *redirect = NULL; |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "%d new debug session mss %u ws %u window %u", |
|
|
|
packet, mss, ws, send_window << ws); |
|
|
|
|
|
|
|
// Register session |
|
|
|
struct ng_session *s = ng_malloc(sizeof(struct ng_session), "tcp session"); |
|
|
|
s->protocol = IPPROTO_TCP; |
|
|
|
|
|
|
|
s->tcp.time = time(NULL); |
|
|
|
s->tcp.uid = uid; |
|
|
|
s->tcp.version = version; |
|
|
|
s->tcp.mss = mss; |
|
|
|
s->tcp.recv_scale = ws; |
|
|
|
s->tcp.send_scale = ws; |
|
|
|
s->tcp.send_window = ((uint32_t) send_window) << ws; |
|
|
|
|
|
|
|
|
|
|
|
s->tcp.unconfirmed = 0; |
|
|
|
s->tcp.remote_seq = (uint32_t) sequence_number; // probably should change hardcoded seq # |
|
|
|
//s->tcp.remote_seq = ntohl(tcphdr->seq); // ISN remote |
|
|
|
s->tcp.local_seq = (uint32_t) rand(); // ISN local |
|
|
|
s->tcp.remote_start = s->tcp.remote_seq; |
|
|
|
s->tcp.local_start = s->tcp.local_seq; |
|
|
|
s->tcp.acked = 0; |
|
|
|
s->tcp.last_keep_alive = 0; |
|
|
|
s->tcp.sent = 0; |
|
|
|
s->tcp.received = 0; |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "got to change address.."); |
|
|
|
|
|
|
|
if (version == 4) { |
|
|
|
inet_aton("10.1.10.1", &s->tcp.saddr.ip4); |
|
|
|
inet_aton("some_server_ip", &s->tcp.daddr.ip4); |
|
|
|
/* Accumulate checksum */ |
|
|
|
for (i = 0; i < size - 1; i += 2) |
|
|
|
{ |
|
|
|
unsigned short word16 = *(unsigned short *) &buf[i]; |
|
|
|
sum += word16; |
|
|
|
} |
|
|
|
|
|
|
|
saddr = &s->tcp.saddr.ip4; |
|
|
|
daddr = &s->tcp.daddr.ip4; |
|
|
|
|
|
|
|
inet_ntop(AF_INET, saddr, source, sizeof(source)); |
|
|
|
inet_ntop(AF_INET, daddr, dest, sizeof(dest)); |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "new debug IP packet has source: %s, dest: %s", source, dest); |
|
|
|
|
|
|
|
s->tcp.source = sport; //tcphdr->source; |
|
|
|
s->tcp.dest = dport; // tcphdr->dest; |
|
|
|
s->tcp.state = TCP_LISTEN; |
|
|
|
s->tcp.socks5 = SOCKS5_NONE; |
|
|
|
s->tcp.forward = NULL; |
|
|
|
s->next = NULL; |
|
|
|
|
|
|
|
/* Handle odd-sized case */ |
|
|
|
if (size & 1) |
|
|
|
{ |
|
|
|
unsigned short word16 = (unsigned char) buf[i]; |
|
|
|
sum += word16; |
|
|
|
} |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "got to data with source:"); |
|
|
|
/* Fold to get the ones-complement result */ |
|
|
|
while (sum >> 16) sum = (sum & 0xFFFF)+(sum >> 16); |
|
|
|
|
|
|
|
/* |
|
|
|
if (datalen) { |
|
|
|
log_android(ANDROID_LOG_WARN, "%s SYN data", packet); |
|
|
|
s->tcp.forward = ng_malloc(sizeof(struct segment), "syn segment"); |
|
|
|
s->tcp.forward->seq = s->tcp.remote_seq; |
|
|
|
s->tcp.forward->len = datalen; |
|
|
|
s->tcp.forward->sent = 0; |
|
|
|
s->tcp.forward->psh = tcphdr->psh; |
|
|
|
s->tcp.forward->data = ng_malloc(datalen, "syn segment data"); |
|
|
|
memcpy(s->tcp.forward->data, data, datalen); |
|
|
|
s->tcp.forward->next = NULL; |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "got to open socket with sport: %d, dport %d", sport, dport); |
|
|
|
// Open socket |
|
|
|
s->socket = open_tcp_socket(args, &s->tcp, redirect); |
|
|
|
if (s->socket < 0) { |
|
|
|
// Remote might retry |
|
|
|
ng_free(s, __FILE__, __LINE__); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
/* Invert to get the negative in ones-complement arithmetic */ |
|
|
|
return ~sum; |
|
|
|
} |
|
|
|
|
|
|
|
void create_syn_packet(char** out_packet, int* out_packet_len) |
|
|
|
{ |
|
|
|
// datagram to represent the packet |
|
|
|
char *datagram = calloc(DATAGRAM_LEN, sizeof(char)); |
|
|
|
|
|
|
|
// required structs for IP and TCP header |
|
|
|
struct iphdr *iph = (struct iphdr*)datagram; |
|
|
|
struct tcphdr *tcph = (struct tcphdr*)(datagram + sizeof(struct iphdr)); |
|
|
|
struct pseudo_header psh; |
|
|
|
|
|
|
|
char source_ip[32]; |
|
|
|
struct sockaddr_in sin; |
|
|
|
|
|
|
|
//some address resolution |
|
|
|
strcpy(source_ip , ""); // cli ip |
|
|
|
sin.sin_family = AF_INET; |
|
|
|
sin.sin_port = htons(50508); // server port |
|
|
|
sin.sin_addr.s_addr = inet_addr (""); // server ip |
|
|
|
|
|
|
|
|
|
|
|
// IP header configuration |
|
|
|
iph->ihl = 5; |
|
|
|
iph->version = 4; |
|
|
|
iph->tos = 0; |
|
|
|
iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE); |
|
|
|
iph->id = htons(54321); |
|
|
|
iph->frag_off = 0; |
|
|
|
iph->ttl = 64; |
|
|
|
iph->protocol = IPPROTO_TCP; |
|
|
|
iph->check = 0; // do calc later |
|
|
|
iph->saddr = inet_addr ( source_ip ); |
|
|
|
iph->daddr = sin.sin_addr.s_addr; |
|
|
|
|
|
|
|
// TCP header configuration |
|
|
|
tcph->source = htons (40405); |
|
|
|
tcph->dest = htons (50508); |
|
|
|
tcph->seq = htonl(rand() % 4294967295); |
|
|
|
tcph->ack_seq = htonl(0); |
|
|
|
tcph->doff = 10; // tcp header size |
|
|
|
tcph->fin = 0; |
|
|
|
tcph->syn = 1; |
|
|
|
tcph->rst = 0; |
|
|
|
tcph->psh = 0; |
|
|
|
tcph->ack = 0; |
|
|
|
tcph->urg = 0; |
|
|
|
tcph->check = 0; |
|
|
|
tcph->window = htons(5840); // window size |
|
|
|
tcph->urg_ptr = 0; |
|
|
|
|
|
|
|
// TCP pseudo header for checksum calculation |
|
|
|
psh.source_address = inet_addr ( source_ip ); |
|
|
|
psh.dest_address = sin.sin_addr.s_addr; |
|
|
|
psh.placeholder = 0; |
|
|
|
psh.protocol = IPPROTO_TCP; |
|
|
|
psh.tcp_length = htons(sizeof(struct tcphdr) + OPT_SIZE); |
|
|
|
int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + OPT_SIZE; |
|
|
|
// fill pseudo packet |
|
|
|
char* pseudogram = malloc(psize); |
|
|
|
memcpy(pseudogram, (char*)&psh, sizeof(struct pseudo_header)); |
|
|
|
memcpy(pseudogram + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr) + OPT_SIZE); |
|
|
|
|
|
|
|
// TCP options are only set in the SYN packet |
|
|
|
// ---- set mss ---- |
|
|
|
datagram[40] = 0x02; |
|
|
|
datagram[41] = 0x04; |
|
|
|
int16_t mss = htons(48); // mss value |
|
|
|
memcpy(datagram + 42, &mss, sizeof(int16_t)); |
|
|
|
// ---- enable SACK ---- |
|
|
|
datagram[44] = 0x04; |
|
|
|
datagram[45] = 0x02; |
|
|
|
// do the same for the pseudo header |
|
|
|
pseudogram[32] = 0x02; |
|
|
|
pseudogram[33] = 0x04; |
|
|
|
memcpy(pseudogram + 34, &mss, sizeof(int16_t)); |
|
|
|
pseudogram[36] = 0x04; |
|
|
|
pseudogram[37] = 0x02; |
|
|
|
|
|
|
|
tcph->check = checksum((const char*)pseudogram, psize); |
|
|
|
iph->check = checksum((const char*)datagram, iph->tot_len); |
|
|
|
|
|
|
|
*out_packet = datagram; |
|
|
|
*out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE; |
|
|
|
free(pseudogram); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
s->tcp.recv_window = get_receive_window(s); |
|
|
|
log_android(ANDROID_LOG_DEBUG, "TCP socket %d lport %d", |
|
|
|
s->socket, get_local_port(s->socket)); |
|
|
|
|
|
|
|
|
|
|
|
int open_debug_packet(const struct arguments *args, int epoll_fd) { |
|
|
|
|
|
|
|
// send SYN |
|
|
|
char* packet; |
|
|
|
int packet_len; |
|
|
|
create_syn_packet(&packet, &packet_len); |
|
|
|
|
|
|
|
// Monitor events |
|
|
|
memset(&s->ev, 0, sizeof(struct epoll_event)); |
|
|
|
s->ev.events = EPOLLOUT | EPOLLERR; |
|
|
|
s->ev.data.ptr = s; |
|
|
|
//handle_debug_ip(args, buffer, packet_length, epoll_fd); |
|
|
|
handle_ip(args, packet, (size_t) packet_len, epoll_fd, 10, 200); |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "DEBUG adding epoll monitor events: %d", epoll_fd); |
|
|
|
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s->socket, &s->ev)) |
|
|
|
log_android(ANDROID_LOG_ERROR, "epoll add tcp error %d: %s", |
|
|
|
errno, strerror(errno)); |
|
|
|
|
|
|
|
|
|
|
|
s->next = args->ctx->ng_session; |
|
|
|
//args->ctx->ng_session->next = s; |
|
|
|
debug_socket = s; |
|
|
|
int debug_socket_init(const struct arguments *args, int epoll_fd) { |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "init debug socket"); |
|
|
|
open_debug_packet(args, epoll_fd); |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct ng_session *get_debug_session() { |
|
|
|
|
|
|
|
if (debug_socket == NULL) { |
|
|
|
log_android(ANDROID_LOG_ERROR, "found null debug session..."); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void debug_socket_init(const struct arguments *args, int epoll_fd) { |
|
|
|
// TODO: Init the socket. Initialize this socket kind of like what happens |
|
|
|
// in tcp.c for open_tcp_socket. |
|
|
|
// debug_socket = open() |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "initalizing debug socket"); |
|
|
|
open_debug_socket(args, epoll_fd); |
|
|
|
|
|
|
|
|
|
|
|
return debug_socket; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
void read_debug_socket() { |
|
|
|
// TODO: Figure out what needs to be passed as parameters to this function |
|
|
|
return ; |
|
|
|
} |
|
|
|
|
|
|
|
void write_debug_socket(const struct arguments *args, const uint8_t *buffer, size_t length) { |
|
|
|
void write_debug_socket(const struct arguments *args, const uint8_t *buffer, size_t length, char* dest_ip) { |
|
|
|
// TODO: This function is modelled after write_pcap_ret so I made |
|
|
|
// parameters for this function the same since we basically want to do the same thing. |
|
|
|
|
|
|
|
//struct tcp_session *cur = &debug_socket->tcp; |
|
|
|
struct tcp_session *cur = &debug_socket->tcp; |
|
|
|
|
|
|
|
|
|
|
|
// test write to the debug socket |
|
|
|
//write_data(args, cur, buffer, length); |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "debug tcp port: %d", cur->source); |
|
|
|
|
|
|
|
int is_debug_server = strcmp(dest_ip, ""); |
|
|
|
|
|
|
|
if (is_debug_server != 0) { |
|
|
|
|
|
|
|
int res = write_ack(args, &debug_socket->tcp); |
|
|
|
|
|
|
|
// Forward to tun |
|
|
|
if (write_data(args, &debug_socket->tcp, buffer, length) >= 0) { |
|
|
|
log_android(ANDROID_LOG_ERROR, "write ack result %d", res); |
|
|
|
|
|
|
|
log_android(ANDROID_LOG_ERROR, "Writing to debug socket with length: %d", length); |
|
|
|
debug_socket->tcp.local_seq += length; |
|
|
|
debug_socket->tcp.unconfirmed++; |
|
|
|
|
|
|
|
/* |
|
|
|
log_android(ANDROID_LOG_ERROR, "writing debug packet to %s with length: %d", dest_ip, length); |
|
|
|
|
|
|
|
// Forward to tun |
|
|
|
if (write_data(args, &debug_socket->tcp, buffer, length) >= 0) { |
|
|
|
log_android(ANDROID_LOG_ERROR, "Successfully wrote to debug socket with length: %d", length); |
|
|
|
debug_socket->tcp.local_seq += length; |
|
|
|
debug_socket->tcp.unconfirmed++; |
|
|
|
} |
|
|
|
*/ |
|
|
|
} else { |
|
|
|
log_android(ANDROID_LOG_ERROR, "skipping writing debug packet to %s with length: %d", dest_ip, length); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|