Created
November 5, 2023 13:10
-
-
Save annmuor/bfb15ca97868344777967b1e0dfc3876 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This file was cut from original server code | |
// Use this for eudcational purporses | |
// (C) and so on | |
#define _FLAG_FIN 0x01 | |
#define _FLAG_SYN 0x02 | |
#define _FLAG_RST 0x04 | |
#define _FLAG_PSH 0x08 | |
#define _FLAG_ACK 0x10 | |
#define _FLAG_URG 0x20 | |
struct ip_hdr { | |
#if __BYTE_ORDER == __LITTLE_ENDIAN | |
u8 ihl:4; | |
u8 ver:4; | |
#elif __BYTE_ORDER == __BIG_ENDIAN | |
u8 ver:4; | |
u8 ihl:4; | |
#else | |
# error "Please fix <bits/endian.h>" | |
#endif | |
u8 dscp:6; | |
u8 ecn:2; | |
u16 len; | |
u16 id; | |
u16 frag_off; | |
u8 ttl; | |
u8 proto; | |
u16 checksum; | |
u32 src; | |
u32 dst; | |
}; | |
struct fakeiphdr { | |
u32 src; | |
u32 dst; | |
u8 zero; | |
u8 proto; | |
u16 next_proto_len; | |
}; | |
struct tcp_hdr { | |
u16 sport; | |
u16 dport; | |
u32 seq; | |
u32 ack; | |
#if __BYTE_ORDER == __LITTLE_ENDIAN | |
u8 rsv:4; | |
u8 doff:4; | |
#elif __BYTE_ORDER == __BIG_ENDIAN | |
u8 doff:4; | |
u8 rsv:4; | |
#else | |
# error "Please fix <bits/endian.h>" | |
#endif | |
u8 flags; | |
u16 win; | |
u16 checksum; | |
u16 urgptr; | |
}; | |
static int send_socket; | |
static int recv_socket; | |
const char *ipv4_str(u32 addr) { | |
static char ret[16]; | |
char *repr = (char *)&addr; | |
memset(ret, 0, sizeof(ret)); | |
snprintf(ret, sizeof(ret), "%u.%u.%u.%u", (*repr)&0xff, (*(repr+1)&0xff), (*(repr+2)&0xff), (*(repr+3)&0xff)); | |
return ret; | |
} | |
void init_sockets() { | |
if((send_socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) | |
perror("send_socket failed"); | |
if((recv_socket = socket(PF_PACKET, SOCK_DGRAM, htons(0x0800))) < 0) | |
perror("recv_socket failed"); | |
} | |
static unsigned short compute_checksum(u_short *addr, u_int count, int final) { | |
static unsigned long sum = 0; | |
while (count > 1) { | |
sum += * addr++; | |
count -= 2; | |
} | |
//if any bytes left, pad the bytes and add | |
if(count > 0) { | |
sum += ((*addr)&htons(0xFF00)); | |
} | |
if(final) { | |
unsigned long new_sum = 0; | |
while (sum>>16) { | |
sum = (sum & 0xffff) + (sum >> 16); | |
} | |
new_sum = ~sum; | |
sum = 0; | |
return ((unsigned short)new_sum); | |
} | |
return 0; | |
} | |
// All data in NETWORK format already | |
int send_packet(u32 src, u32 dst, u16 sport, u16 dport, u32 seq, u32 ack, u8 flags, u16 window) { | |
struct fakeiphdr ip = { | |
.src = src, | |
.dst = dst, | |
.zero = 0, | |
.proto = 6, | |
.next_proto_len = htons(20), | |
}; | |
struct tcp_hdr tcp = { | |
.sport = sport, | |
.dport = dport, | |
.seq = seq, | |
.ack = ack, | |
.doff = 5, | |
.rsv = 0, | |
.flags = flags, | |
.win = window, | |
.checksum = 0, | |
.urgptr = 0, | |
}; | |
struct sockaddr_in sin = { | |
.sin_family = AF_INET, | |
.sin_addr.s_addr = src, | |
.sin_port = tcp.dport, | |
}; | |
compute_checksum((u16 *)&ip, sizeof(ip), 0); | |
tcp.checksum = compute_checksum((u16 *)&tcp, sizeof(tcp), 1); | |
return sendto(send_socket, (void *)&tcp, sizeof(tcp), 0, (struct sockaddr *)&sin, sizeof(sin)); | |
} | |
void main() { | |
u8 *packet = malloc(1500); // magic constant - MAX MTU | |
struct sockaddr_in inc; | |
socklen_t inc_size; | |
init_sockets(); | |
init_clients(); | |
memset(packet, 0, 1500); | |
while(1) { | |
size_t len; | |
struct ip_hdr *ip; | |
struct tcp_hdr *tcp; | |
u8 *data; | |
CLIENT *c; // inner struct | |
if((len = recvfrom(recv_socket, packet, 1500, 0, (struct sockaddr *)&inc, &inc_size)) < 0) { | |
perror("recvfrom"); | |
continue; | |
} | |
ip = (struct ip_hdr *)packet; | |
if(len < 40 || ip->ver != 4 || ip->proto != 6) { | |
continue; | |
} | |
tcp = (struct tcp_hdr *)(packet + (ip->ihl*4)); | |
if(tcp->dport != service_port) { | |
continue; | |
} | |
data = packet + (ip->ihl*4) + (tcp->doff*4); | |
c = find_client(ip->src, tcp->sport); // find client status | |
// ....... | |
if(tcp->flags == _FLAG_RST || tcp->flags == (_FLAG_RST|_FLAG_ACK)) { | |
// Connection drop | |
continue; | |
} | |
if(tcp->flags == _FLAG_FIN || tcp->flags == (_FLAG_ACK|_FLAG_FIN)) { | |
// Connection drop | |
continue; | |
} | |
if(tcp->flags == _FLAG_SYN && tcp->win != 0) { | |
// Connection drop | |
continue; | |
} | |
switch(c->state) { | |
case _STATE_NEW: | |
if(tcp->flags == _FLAG_SYN) { | |
// Send SYN|ACK | |
} else { | |
// Connection drop | |
} | |
break; | |
case _STATE_ACK: | |
if(tcp->flags == _FLAG_ACK) { | |
// Connection established | |
state = _STATE_RMS; | |
} else if(tcp->flags == _FLAG_SYN) { | |
// Resend SYN+ACK | |
} else { | |
// Connection drop | |
} | |
break; | |
case _STATE_RMS: | |
{ | |
char *b = (char *)&tcp->win; | |
for(u8 i = 0; i < 2; i++) { | |
if(*(b+i) == 0) { | |
c->eof = 1; | |
// we finished the message | |
break; | |
} else { | |
if(c->msg_size < sizeof(c->msg)) { | |
c->msg[c->msg_size++] = *(b+i); | |
} else { | |
c->eof = 1; | |
// message > 256 - we finished the message | |
break; | |
} | |
} | |
} | |
if(c->eof) { | |
if(is_flag_command(c)) { // checking if message has "getflag" | |
send_flag(c); // and send flag | |
} | |
memset(c->msg, 0, sizeof(c->msg)); | |
c->msg_size = 0; | |
c->eof = 0; // reset | |
} | |
} | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment