?? tcpip.cc
字號:
u32 seq, u32 ack, u8 reserved, u8 flags,u16 window, u16 urp, u8 *options, int optlen, char *data, u16 datalen) { unsigned int packetlen; int res = -1; u8 *packet = build_tcp_raw(source, victim, ttl, get_random_u16(), IP_TOS_DEFAULT, df, ipops, ipoptlen, sport, dport, seq, ack, reserved, flags, window, urp, options, optlen, data, datalen, &packetlen); if (!packet) return -1; res = send_ip_packet(sd, eth, packet, packetlen); free(packet); return res;}/* Create and send all fragments of a pre-built IPv4 packet * Minimal MTU for IPv4 is 68 and maximal IPv4 header size is 60 * which gives us a right to cut TCP header after 8th byte * (shouldn't we inflate the header to 60 bytes too?) */int send_frag_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetlen, unsigned int mtu){ struct ip *ip = (struct ip *) packet; int headerlen = ip->ip_hl * 4; // better than sizeof(struct ip) unsigned int datalen = packetlen - headerlen; int fdatalen = 0, res = 0; assert(headerlen <= (int) packetlen); assert(headerlen >= 20 && headerlen <= 60); // sanity check (RFC791) assert(mtu > 0 && mtu % 8 == 0); // otherwise, we couldn't set Fragment offset (ip->ip_off) correctly if (datalen <= mtu) { error("Warning: fragmentation (mtu=%i) requested but the payload is too small already (%i)", mtu, datalen); return send_ip_packet(sd, eth, packet, packetlen); } u8 *fpacket = (u8 *) safe_malloc(headerlen + mtu); memcpy(fpacket, packet, headerlen + mtu); ip = (struct ip *) fpacket; // create fragments and send them for (int fragment = 1; fragment * mtu < datalen + mtu; fragment++) { fdatalen = (fragment * mtu <= datalen ? mtu : datalen % mtu); ip->ip_len = htons(headerlen + fdatalen); ip->ip_off = htons((fragment-1) * mtu / 8); if ((fragment-1) * mtu + fdatalen < datalen) ip->ip_off |= htons(IP_MF);#if HAVE_IP_IP_SUM ip->ip_sum = in_cksum((unsigned short *)ip, headerlen);#endif if (fragment > 1) // copy data payload memcpy(fpacket + headerlen, packet + headerlen + (fragment - 1) * mtu, fdatalen); res = send_ip_packet(sd, eth, fpacket, headerlen + fdatalen); if (res == -1) break; } free(fpacket); return res;}static int Sendto(char *functionname, int sd, const unsigned char *packet, int len, unsigned int flags, struct sockaddr *to, int tolen) {struct sockaddr_in *sin = (struct sockaddr_in *) to;int res;int retries = 0;int sleeptime = 0;static int numerrors = 0;do { if ((res = sendto(sd, (const char *) packet, len, flags, to, tolen)) == -1) { int err = socket_errno(); numerrors++; if (o.debugging > 1 || numerrors <= 10) { error("sendto in %s: sendto(%d, packet, %d, 0, %s, %d) => %s", functionname, sd, len, inet_ntoa(sin->sin_addr), tolen, strerror(err)); error("Offending packet: %s", ippackethdrinfo(packet, len)); if (numerrors == 10) { error("Omitting future Sendto error messages now that %d have been shown. Use -d2 if you really want to see them.", numerrors); } }#if WIN32 return -1;#else if (retries > 2 || err == EPERM || err == EACCES || err == EADDRNOTAVAIL || err == EINVAL) return -1; sleeptime = 15 * (1 << (2 * retries)); error("Sleeping %d seconds then retrying", sleeptime); fflush(stderr); sleep(sleeptime);#endif } retries++;} while( res == -1); PacketTrace::trace(PacketTrace::SENT, packet, len); return res;}/* Send a pre-built IPv4 packet */int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetlen) { struct sockaddr_in sock; int res; struct ip *ip = (struct ip *) packet; struct tcphdr *tcp = NULL; udphdr_bsd *udp; u8 *eth_frame = NULL; eth_t *ethsd; bool ethsd_opened = false; assert(packet); assert( (int) packetlen > 0); // fragmentation requested && packet is bigger than MTU if (o.fragscan && ( packetlen - ip->ip_hl * 4 > (unsigned int) o.fragscan )) return send_frag_ip_packet(sd, eth, packet, packetlen, o.fragscan); if (eth) { eth_frame = (u8 *) safe_malloc(14 + packetlen); memcpy(eth_frame + 14, packet, packetlen); eth_pack_hdr(eth_frame, eth->dstmac, eth->srcmac, ETH_TYPE_IP); if (!eth->ethsd) { ethsd = eth_open_cached(eth->devname); if (!ethsd) fatal("send_ip_packet: Failed to open ethernet device (%s)", eth->devname); ethsd_opened = true; } else ethsd = eth->ethsd; res = eth_send(ethsd, eth_frame, 14 + packetlen); PacketTrace::trace(PacketTrace::SENT, packet, packetlen); /* No need to close ethsd due to caching */ free(eth_frame); eth_frame = NULL; return res; } assert(sd >= 0); memset(&sock, 0, sizeof(sock)); sock.sin_family = AF_INET;#if HAVE_SOCKADDR_SA_LEN sock.sin_len = sizeof(sock);#endif /* It is bogus that I need the address and port info when sending a RAW IP packet, but it doesn't seem to work w/o them */ if (packetlen >= 20) { sock.sin_addr.s_addr = ip->ip_dst.s_addr; if (ip->ip_p == IPPROTO_TCP && packetlen >= (unsigned int) ip->ip_hl * 4 + 20) { tcp = (struct tcphdr *) ((u8 *) ip + ip->ip_hl * 4); sock.sin_port = tcp->th_dport; } else if (ip->ip_p == IPPROTO_UDP && packetlen >= (unsigned int) ip->ip_hl * 4 + 8) { udp = (udphdr_bsd *) ((u8 *) ip + ip->ip_hl * 4); sock.sin_port = udp->uh_dport; } } /* Equally bogus is that the IP total len and IP fragment offset fields need to be in host byte order on certain BSD variants. I must deal with it here rather than when building the packet, because they should be in NBO when I'm sending over raw ethernet */#if FREEBSD || BSDI || NETBSD || DEC || MACOSX ip->ip_len = ntohs(ip->ip_len); ip->ip_off = ntohs(ip->ip_off);#endif res = Sendto("send_ip_packet", sd, packet, packetlen, 0, (struct sockaddr *)&sock, (int)sizeof(struct sockaddr_in)); return res;}/* Builds an ICMP packet (including an IP header) by packing the fields with the given information. It allocates a new buffer to store the packet contents, and then returns that buffer. The packet is not actually sent by this function. Caller must delete the buffer when finished with the packet. The packet length is returned in packetlen, which must be a valid int pointer. The id/seq will be converted to network byte order (if it differs from HBO) */u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim, int ttl, u16 ipid, u8 tos, bool df, u8 *ipopt, int ipoptlen, u16 seq, unsigned short id, u8 ptype, u8 pcode, char *data, u16 datalen, u32 *packetlen) {struct ppkt { u8 type; u8 code; u16 checksum; u16 id; u16 seq; u8 data[1500]; /* Note -- first 4-12 bytes can be used for ICMP header */} pingpkt;u32 *datastart = (u32 *) pingpkt.data;int dlen = sizeof(pingpkt.data); int icmplen=0;char *ping = (char *) &pingpkt; pingpkt.type = ptype; pingpkt.code = pcode; if (ptype == 8) /* echo request */ { icmplen = 8; } else if (ptype == 13 && pcode == 0) /* ICMP timestamp req */ { icmplen = 20; memset(datastart, 0, 12); datastart += 12; datalen -= 12; } else if (ptype == 17 && pcode == 0) /* icmp netmask req */ { icmplen = 12; *datastart++ = 0; datalen -= 4; } else fatal("Unknown icmp type/code (%d/%d) in build_icmp_raw", ptype, pcode); if (datalen > 0) { icmplen += MIN(dlen, datalen); memset(datastart, 0, MIN(dlen, datalen)); }/* Fill out the ping packet */ pingpkt.id = htons(id); pingpkt.seq = htons(seq);pingpkt.checksum = 0;pingpkt.checksum = in_cksum((unsigned short *)ping, icmplen);if ( o.badsum ) --pingpkt.checksum;return build_ip_raw(source, victim, IPPROTO_ICMP, o.ttl, get_random_u16(), tos, df, ipopt, ipoptlen, ping, icmplen, packetlen);}/* A simple function I wrote to help in debugging, shows the important fields of a TCP packet*/int readtcppacket(const u8 *packet, int readdata) {struct ip *ip = (struct ip *) packet;struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip));const unsigned char *data = packet + sizeof(struct ip) + sizeof(struct tcphdr);int tot_len;struct in_addr bullshit, bullshit2;char sourcehost[16];int i;int realfrag = 0;if (!packet) { fprintf(stderr, "readtcppacket: packet is NULL!\n"); return -1; }bullshit.s_addr = ip->ip_src.s_addr; bullshit2.s_addr = ip->ip_dst.s_addr;/* this is gay */realfrag = htons(ntohs(ip->ip_off) & 8191 /* 2^13 - 1 */);tot_len = htons(ip->ip_len);strncpy(sourcehost, inet_ntoa(bullshit), 16);i = 4 * (ntohs(ip->ip_hl) + ntohs(tcp->th_off));if (ip->ip_p== IPPROTO_TCP) { if (realfrag) printf("Packet is fragmented, offset field: %u\n", realfrag); else { printf("TCP packet: %s:%d -> %s:%d (total: %d bytes)\n", sourcehost, ntohs(tcp->th_sport), inet_ntoa(bullshit2), ntohs(tcp->th_dport), tot_len); printf("Flags: "); if (!tcp->th_flags) printf("(none)"); if (tcp->th_flags & TH_RST) printf("RST "); if (tcp->th_flags & TH_SYN) printf("SYN "); if (tcp->th_flags & TH_ACK) printf("ACK "); if (tcp->th_flags & TH_PUSH) printf("PSH "); if (tcp->th_flags & TH_FIN) printf("FIN "); if (tcp->th_flags & TH_URG) printf("URG "); printf("\n"); printf("ipid: %hu ttl: %hu ", ntohs(ip->ip_id), ip->ip_ttl); if (tcp->th_flags & (TH_SYN | TH_ACK)) printf("Seq: %u\tAck: %u\n", (unsigned int) ntohl(tcp->th_seq), (unsigned int) ntohl(tcp->th_ack)); else if (tcp->th_flags & TH_SYN) printf("Seq: %u\n", (unsigned int) ntohl(tcp->th_seq)); else if (tcp->th_flags & TH_ACK) printf("Ack: %u\n", (unsigned int) ntohl(tcp->th_ack)); }}if (readdata && i < tot_len) { printf("Data portion:\n"); while(i < tot_len) { printf("%2X%c", data[i], ((i+1) %16)? ' ' : '\n'); i++; } printf("\n");}return 0;}/* A simple function I wrote to help in debugging, shows the important fields of a UDP packet*/int readudppacket(const u8 *packet, int readdata) {struct ip *ip = (struct ip *) packet;udphdr_bsd *udp = (udphdr_bsd *) (packet + sizeof(struct ip));const unsigned char *data = packet + sizeof(struct ip) + sizeof(udphdr_bsd);int tot_len;struct in_addr bullshit, bullshit2;char sourcehost[16];int i;int realfrag = 0;if (!packet) { fprintf(stderr, "readudppacket: packet is NULL!\n"); return -1; }bullshit.s_addr = ip->ip_src.s_addr; bullshit2.s_addr = ip->ip_dst.s_addr;/* this is gay */realfrag = htons(ntohs(ip->ip_off) & 8191 /* 2^13 - 1 */);tot_len = htons(ip->ip_len);strncpy(sourcehost, inet_ntoa(bullshit), 16);i = 4 * (ntohs(ip->ip_hl)) + 8;if (ip->ip_p== IPPROTO_UDP) { if (realfrag) printf("Packet is fragmented, offset field: %u\n", realfrag); else { printf("UDP packet: %s:%d -> %s:%d (total: %d bytes)\n", sourcehost, ntohs(udp->uh_sport), inet_ntoa(bullshit2), ntohs(udp->uh_dport), tot_len); printf("ttl: %hu ", ip->ip_ttl); }} if (readdata && i < tot_len) { printf("Data portion:\n"); while(i < tot_len) { printf("%2X%c", data[i], ((i+1)%16)? ' ' : '\n'); i++; } printf("\n"); } return 0;}int send_udp_raw_decoys( int sd, struct eth_nfo *eth, const struct in_addr *victim, int ttl, u16 ipid, u8* ipops, int ipoptlen, u16 sport, u16 dport, char *data, u16 datalen) { int decoy; for(decoy = 0; decoy < o.numdecoys; decoy++) if (send_udp_raw(sd, eth, &o.decoys[decoy], victim, ttl, ipid, ipops, ipoptlen, sport, dport, data, datalen) == -1) return -1; return 0;}/* Builds a UDP packet (including an IP header) by packing the fields with the given information. It allocates a new buffer to store the packet contents, and then returns that buffer. The packet is not actually sent by this function. Caller must delete the buffer when finished with the packet. The packet length is returned in packetlen, which must be a valid int pointer. */u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim, int ttl, u16 ipid, u8 tos, bool df, u8 *ipopt, int ipoptlen, u16 sport, u16 dport, char *data, u16 datalen, u32 *outpacketlen) { int packetlen = sizeof(struct ip) + ipoptlen + sizeof(udphdr_bsd) + datalen; u8 *packet = (u8 *) safe_malloc(packetlen); struct ip *ip = (struct ip *) packet; udphdr_bsd *udp = (udphdr_bsd *) ((u8*)ip + sizeof(struct ip) + ipoptlen); static int myttl = 0; struct pseudo_udp_hdr { struct in_addr source; struct in_addr dest; u8 zer0; u8 proto; u16 length; } *pseudo = (struct pseudo_udp_hdr *) ((u8 *)udp - sizeof(struct pseudo_udp_hdr)); /* check that required fields are there and not too silly */ assert(victim);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -