Skip to content

Instantly share code, notes, and snippets.

@annmuor
Created November 5, 2023 13:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save annmuor/bfb15ca97868344777967b1e0dfc3876 to your computer and use it in GitHub Desktop.
Save annmuor/bfb15ca97868344777967b1e0dfc3876 to your computer and use it in GitHub Desktop.
// 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