├── .gitignore ├── Protocol ├── Ethernet.cpp ├── Ethernet.h ├── IPv4.cpp ├── IPv4.h ├── Tcp.h └── Tcp.cpp ├── Makefile ├── PacketInjector.h ├── main.cpp ├── LICENSE ├── README.md └── PacketInjector.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | http_inject 3 | -------------------------------------------------------------------------------- /Protocol/Ethernet.cpp: -------------------------------------------------------------------------------- 1 | #include "Ethernet.h" 2 | 3 | Ethernet::Ethernet(const u_char* packet) { 4 | phdr = (Ethernet_Header *)packet; 5 | } 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | TARGET = http_inject 3 | OBJECTS = Protocol/Tcp.o Protocol/IPv4.o Protocol/Ethernet.o PacketInjector.o main.o 4 | 5 | all : $(TARGET) 6 | 7 | $(TARGET): $(OBJECTS) 8 | $(CC) -o $@ $^ -lpcap 9 | 10 | clean: 11 | rm -rf *.o Protocol/*.o http_inejct 12 | -------------------------------------------------------------------------------- /Protocol/Ethernet.h: -------------------------------------------------------------------------------- 1 | #ifndef ETHERNET_H 2 | #define ETHERNET_H 3 | 4 | #include 5 | 6 | #define ETHER_ADDR_LEN 6 7 | #define ETHER_HEAD_LEN 14 8 | #define ETHER_TYPE_IPv4 htons(0x0800) 9 | 10 | class Ethernet { 11 | private: 12 | struct Ethernet_Header { 13 | u_int8_t ether_dhost[ETHER_ADDR_LEN]; 14 | u_int8_t ether_shost[ETHER_ADDR_LEN]; 15 | u_int16_t ether_type; 16 | }; 17 | 18 | public: 19 | Ethernet_Header* phdr; 20 | Ethernet(const u_char* packet); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Protocol/IPv4.cpp: -------------------------------------------------------------------------------- 1 | #include "IPv4.h" 2 | 3 | IPv4::IPv4(const u_char* packet) { 4 | phdr = (IPv4_Header *)packet; 5 | } 6 | 7 | void IPv4::makeChecksum() { 8 | int chksum = 0; 9 | unsigned short *shorter = (unsigned short *)phdr; 10 | phdr->ip_checksum = 0; 11 | 12 | int len = phdr->ip_header_len << 1; 13 | 14 | for (int i = 0; i < len; ++i) { 15 | chksum += shorter[i]; 16 | } 17 | 18 | chksum = (chksum >> 16) + (chksum & 0xFFFF); 19 | chksum += (chksum >> 16); 20 | 21 | chksum ^= 0xFFFF; 22 | phdr->ip_checksum = chksum; 23 | } 24 | -------------------------------------------------------------------------------- /Protocol/IPv4.h: -------------------------------------------------------------------------------- 1 | #ifndef IPV4_H 2 | #define IPV4_H 3 | 4 | #include 5 | #include 6 | #define IP_PRTCL_TCP 6 7 | 8 | class IPv4 { 9 | private: 10 | struct IPv4_Header { 11 | u_int8_t ip_header_len:4; 12 | u_int8_t ip_version:4; 13 | u_int8_t ip_type; 14 | u_int16_t ip_len; 15 | u_int16_t ip_id; 16 | u_int16_t ip_offset; 17 | u_int8_t ip_ttl; 18 | u_int8_t ip_protocol; 19 | u_int16_t ip_checksum; 20 | struct in_addr ip_src, ip_dst; 21 | }; 22 | 23 | public: 24 | IPv4_Header* phdr; 25 | IPv4(const u_char* packet); 26 | 27 | void makeChecksum(); 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /PacketInjector.h: -------------------------------------------------------------------------------- 1 | #ifndef PACKET_INJECTOR_H 2 | #define PACKET_INJECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Protocol/Ethernet.h" 8 | #include "Protocol/IPv4.h" 9 | #include "Protocol/Tcp.h" 10 | 11 | #define BLOCK_MSG "HTTP/1.1 302 Found\nLocation: https://en.wikipedia.org/wiki/HTTP_302\n" 12 | 13 | class PacketInjector { 14 | private: 15 | pcap_t* handle; 16 | const unsigned char* packet; 17 | 18 | public: 19 | PacketInjector(pcap_t* p_handle); 20 | 21 | int run(const unsigned char* p_packet); 22 | int setProperty(IPv4& ip, TCP& tcp, unsigned short flags, const char *msg); 23 | int injectForward(IPv4& ip, TCP& tcp); 24 | int injectBackward(Ethernet& eth, IPv4& ip, TCP& tcp); 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /Protocol/Tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef TCP_H 2 | #define TCP_H 3 | 4 | #include 5 | #include 6 | #include "IPv4.h" 7 | 8 | #define TCP_PORT_HTTP htons(80) 9 | #define TCP_FLAG_FIN 1 10 | #define TCP_FLAG_RST 4 11 | 12 | class TCP { 13 | private: 14 | struct TCP_Header { 15 | u_int16_t tcp_sport, tcp_dport; 16 | u_int32_t tcp_seq_num; 17 | u_int32_t tcp_ack_num; 18 | u_int8_t tcp_reserved:4; 19 | u_int8_t tcp_header_len:4; 20 | u_int8_t tcp_flags; 21 | u_int16_t tcp_window; 22 | u_int16_t tcp_checksum; 23 | u_int16_t tcp_urgent; 24 | }; 25 | 26 | struct TCP_Data { 27 | u_int32_t length; 28 | const u_int8_t *data; 29 | }; 30 | 31 | public: 32 | TCP_Header *phdr; 33 | TCP_Data pdat; 34 | TCP(const u_char *packet, int seg_len); 35 | 36 | void makeChecksum(IPv4& ip); 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "PacketInjector.h" 4 | 5 | int main (int argc, char** argv) { 6 | char errbuf[PCAP_ERRBUF_SIZE]; 7 | char *dev = pcap_lookupdev(errbuf); 8 | 9 | if (dev == NULL) { 10 | std::cout << "[*] Couldn't find default device : " << errbuf << std::endl; 11 | return -1; 12 | } 13 | 14 | pcap_t *handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); 15 | if (handle == NULL) { 16 | std::cout << "[*] Couldn't open device : " << errbuf << std::endl; 17 | return -1; 18 | } 19 | 20 | struct pcap_pkthdr *header; 21 | const unsigned char *packet; 22 | PacketInjector pi = PacketInjector(handle); 23 | 24 | while (1) { 25 | int ret = pcap_next_ex(handle, &header, &packet); 26 | 27 | if (ret == 0) continue; 28 | else if (ret < 0) { 29 | std::cout << "[*] Couldn't receive packets." << std::endl; 30 | return -1; 31 | } 32 | 33 | pi.run(packet); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 YoungJoong Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Protocol/Tcp.cpp: -------------------------------------------------------------------------------- 1 | #include "Tcp.h" 2 | #include 3 | 4 | TCP::TCP(const u_char *packet, int seg_len) { 5 | phdr = (TCP_Header *)packet; 6 | 7 | int tcp_hdrlen = phdr->tcp_header_len << 2; 8 | pdat.length = seg_len - tcp_hdrlen; 9 | pdat.data = packet + tcp_hdrlen; 10 | } 11 | 12 | void TCP::makeChecksum(IPv4& ip) { 13 | int i, chksum = 0; 14 | int dlen = phdr->tcp_header_len << 1; 15 | unsigned short *shorter = (unsigned short *)phdr; 16 | 17 | phdr->tcp_checksum = 0; 18 | for (i = 0; i < dlen; ++i) { 19 | chksum += shorter[i]; 20 | } 21 | 22 | dlen = pdat.length >> 1; 23 | shorter = (unsigned short *)pdat.data; 24 | 25 | for (i = 0; i < dlen; ++i) { 26 | chksum += shorter[i]; 27 | } 28 | 29 | if (pdat.length & 1) { 30 | chksum += shorter[i] & 0x00ff; 31 | } 32 | 33 | shorter = (unsigned short *)&ip.phdr->ip_src; 34 | chksum += shorter[0] + shorter[1]; 35 | 36 | shorter = (unsigned short *)&ip.phdr->ip_dst; 37 | chksum += shorter[0] + shorter[1]; 38 | 39 | chksum += htons(6); 40 | chksum += htons((phdr->tcp_header_len << 2) + pdat.length); 41 | 42 | chksum = (chksum >> 16) + (chksum & 0xFFFF); 43 | chksum += (chksum >> 16); 44 | 45 | chksum ^= 0xFFFF; 46 | phdr->tcp_checksum = chksum; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Packet-Injection 2 | 3 | Detect specific packet and inject forward or backward 4 | 5 | 1. Detect specific packet : ex) HTTP GET 6 | ```cpp 7 | if (tcp.phdr->tcp_dport == TCP_PORT_HTTP) { 8 | if (tcp.pdat.length && !strncmp((char *)tcp.pdat.data, "GET", 3)) { 9 | char *tmp = strchr((char *)tcp.pdat.data, '\n'); 10 | 11 | if (tmp) *tmp = '\0'; 12 | std::cout << "[*] blocked : " << tcp.pdat.data << std::endl; 13 | 14 | injectForward(ip, tcp); 15 | injectBackward(eth, ip, tcp); 16 | } 17 | } 18 | ``` 19 | 20 | 2. inject forward or backward : ex) HTTP 302 redirect, fin or rst flag packet 21 | ```cpp 22 | int PacketInjector::injectForward(IPv4& ip, TCP& tcp) { 23 | u_int32_t seqtmp = tcp.phdr->tcp_seq_num; 24 | tcp.phdr->tcp_seq_num = htonl(ntohl(seqtmp) + tcp.pdat.length); 25 | 26 | int ip_len = setProperty(ip, tcp, TCP_FLAG_RST, ""); 27 | int total_len = ETHER_HEAD_LEN + ip_len; 28 | int result = pcap_sendpacket(handle, packet, total_len); 29 | 30 | tcp.phdr->tcp_seq_num = seqtmp; 31 | tcp.phdr->tcp_flags ^= TCP_FLAG_RST; 32 | 33 | return result; 34 | } 35 | ``` 36 | 37 | ```cpp 38 | int PacketInjector::injectBackward(Ethernet& eth, IPv4& ip, TCP& tcp) { 39 | for (int i = 0; i < ETHER_ADDR_LEN; ++i) { 40 | u_int8_t etmp = eth.phdr->ether_dhost[i]; 41 | eth.phdr->ether_dhost[i] = eth.phdr->ether_shost[i]; 42 | eth.phdr->ether_shost[i] = etmp; 43 | } 44 | 45 | struct in_addr itmp = ip.phdr->ip_dst; 46 | ip.phdr->ip_dst = ip.phdr->ip_src; 47 | ip.phdr->ip_src = itmp; 48 | 49 | u_int16_t ptmp = tcp.phdr->tcp_dport; 50 | tcp.phdr->tcp_dport = tcp.phdr->tcp_sport; 51 | tcp.phdr->tcp_sport = ptmp; 52 | 53 | u_int32_t atmp = tcp.phdr->tcp_ack_num; 54 | tcp.phdr->tcp_ack_num = htonl(ntohl(tcp.phdr->tcp_seq_num) + tcp.pdat.length); 55 | tcp.phdr->tcp_seq_num = atmp; 56 | 57 | int ip_len = setProperty(ip, tcp, TCP_FLAG_FIN, BLOCK_MSG); 58 | int total_len = ETHER_HEAD_LEN + ip_len; 59 | int result = pcap_sendpacket(handle, packet, total_len); 60 | 61 | return result; 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /PacketInjector.cpp: -------------------------------------------------------------------------------- 1 | #include "PacketInjector.h" 2 | 3 | PacketInjector::PacketInjector(pcap_t* p_handle) : handle(p_handle) 4 | {} 5 | 6 | int PacketInjector::run(const unsigned char* p_packet) { 7 | packet = p_packet; 8 | Ethernet eth = Ethernet(packet); 9 | 10 | if (eth.phdr->ether_type == ETHER_TYPE_IPv4) { 11 | IPv4 ip = IPv4(packet + ETHER_HEAD_LEN); 12 | 13 | if (ip.phdr->ip_protocol == IP_PRTCL_TCP) { 14 | int ip_len = ntohs(ip.phdr->ip_len); 15 | int ip_hdrlen = ip.phdr->ip_header_len << 2; 16 | 17 | TCP tcp = TCP(packet + ETHER_HEAD_LEN + ip_hdrlen, ip_len - ip_hdrlen); 18 | if (tcp.phdr->tcp_dport == TCP_PORT_HTTP) { 19 | if (tcp.pdat.length && !strncmp((char *)tcp.pdat.data, "GET", 3)) { 20 | char *tmp = strchr((char *)tcp.pdat.data, '\n'); 21 | if (tmp) *tmp = '\0'; 22 | std::cout << "[*] blocked : " << tcp.pdat.data << std::endl; 23 | 24 | injectForward(ip, tcp); 25 | injectBackward(eth, ip, tcp); 26 | } 27 | } 28 | } 29 | } 30 | } 31 | 32 | int PacketInjector::setProperty(IPv4& ip, TCP& tcp, unsigned short flag, const char* msg) { 33 | tcp.phdr->tcp_flags |= flag; 34 | 35 | int msg_len = strlen(msg); 36 | int tcp_hdrlen = tcp.phdr->tcp_header_len << 2; 37 | int ip_hdrlen = ip.phdr->ip_header_len << 2; 38 | int ip_len = ip_hdrlen + tcp_hdrlen + msg_len; 39 | 40 | ip.phdr->ip_len = htons(ip_len); 41 | strcpy((char *)tcp.pdat.data, msg); 42 | tcp.pdat.length = strlen(msg); 43 | 44 | ip.makeChecksum(); 45 | tcp.makeChecksum(ip); 46 | 47 | return ip_len; 48 | } 49 | 50 | int PacketInjector::injectForward(IPv4& ip, TCP& tcp) { 51 | u_int32_t seqtmp = tcp.phdr->tcp_seq_num; 52 | tcp.phdr->tcp_seq_num = htonl(ntohl(seqtmp) + tcp.pdat.length); 53 | 54 | int ip_len = setProperty(ip, tcp, TCP_FLAG_RST, ""); 55 | int total_len = ETHER_HEAD_LEN + ip_len; 56 | int result = pcap_sendpacket(handle, packet, total_len); 57 | 58 | tcp.phdr->tcp_seq_num = seqtmp; 59 | tcp.phdr->tcp_flags ^= TCP_FLAG_RST; 60 | 61 | return result; 62 | } 63 | 64 | int PacketInjector::injectBackward(Ethernet& eth, IPv4& ip, TCP& tcp) { 65 | for (int i = 0; i < ETHER_ADDR_LEN; ++i) { 66 | u_int8_t etmp = eth.phdr->ether_dhost[i]; 67 | eth.phdr->ether_dhost[i] = eth.phdr->ether_shost[i]; 68 | eth.phdr->ether_shost[i] = etmp; 69 | } 70 | 71 | struct in_addr itmp = ip.phdr->ip_dst; 72 | ip.phdr->ip_dst = ip.phdr->ip_src; 73 | ip.phdr->ip_src = itmp; 74 | 75 | u_int16_t ptmp = tcp.phdr->tcp_dport; 76 | tcp.phdr->tcp_dport = tcp.phdr->tcp_sport; 77 | tcp.phdr->tcp_sport = ptmp; 78 | 79 | u_int32_t atmp = tcp.phdr->tcp_ack_num; 80 | tcp.phdr->tcp_ack_num = htonl(ntohl(tcp.phdr->tcp_seq_num) + tcp.pdat.length); 81 | tcp.phdr->tcp_seq_num = atmp; 82 | 83 | int ip_len = setProperty(ip, tcp, TCP_FLAG_FIN, BLOCK_MSG); 84 | int total_len = ETHER_HEAD_LEN + ip_len; 85 | int result = pcap_sendpacket(handle, packet, total_len); 86 | 87 | return result; 88 | } 89 | --------------------------------------------------------------------------------