보통은 패킷 라이브러리 단에서 기본적인 정보는 알아서 넣어주지만 경우에 따라 이더넷 패킷을 처음부터 끝까지 직접 작성하여 보내고 싶을 수 있습니다.
이 때 Npcap (舊 WinPcap)를 이용하면 쉽게 자신이 만들어둔 이더넷 패킷 데이터를 “보낼” 수 있습니다. 물론 도착지 관련 정보를 제대로 넣은게 아니면 도착은 못하지만 출발은 합니다.
핵심적인 코드를 먼저 보여드리면 다음과 같습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
pcap_t* pcap; pcap = pcap_open_live(device->name, capture_size, // capture size 1, // 1: capture all packet timeout, // Timeout [ms] errbuf); if (pcap == nullptr) { printError(__func__, __LINE__, "Failed to open the adapter"); return false; } std::vector<unsigned char> packet(std::begin(packetQuery), std::end(packetQuery)); if (pcap_sendpacket(pcap, packet.data(), packet.size()) != 0) { printError(__func__, __LINE__, ""); return false; } |
결국 pcap_open_live()로 현재 사용중인 네트워크 인터페이스를 선택하고, pcap_sendpacket()으로 자신이 미리 만들어둔 이더넷 패킷 데이터를 실어보내면 됩니다.
제 코드에서 std::vector를 이용했던 이유는 경우에 따라 각 정보를 따로 입력받고 조합해야 할 경우엔 배열보단 std::vector를 쓰는게 더 적합하기 때문인데, 보낼 데이터가 고정되어있으면 그냥 원시 배열을 써도 됩니다.
- 프로젝트 속성에서 C/C++ 추가 포함 디렉터리에 “npcap sdk 경로\Include” 폴더를 집어넣기
- 링커 추가 포함 디렉터리에 “npcap SDK 경로\Lib”폴더를 집어넣기
- 링커 입력 추가 종속성에 “wpcap.lib” 집어넣기
- \Debug 또는 \Release 폴더에 “wpcap.dll”과 “Packet.dll” 집어넣기 (NPcap SDK 말고 Installer를 설치하면 C:\Windows\[System32, SysWOW64]에 있음)
전체 코드는 다음과 같습니다:
<main.h>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#pragma once #include <iostream> #include <cstdlib> #include <vector> #include "pcap.h" bool sendRawEthernet(); void printError(const char* func, int line, const char* err); static const unsigned char packetQuery[] = { 0xde,0xad,0xbe,0xef,0xfe,0xed,0x34,0xe6,0xd7,0x33,0x6e,0x5d,0x08,0x00,0x45,0x00, 0x00,0x34,0x5e,0x41,0x40,0x00,0x80,0x06,0x00,0x00,0xc0,0xa8,0x01,0x01,0xc0,0xa8, 0x01,0x78,0x07,0x4f,0x01,0xf6,0x1c,0xab,0xe2,0x10,0x00,0x00,0x91,0x01,0x50,0x18, 0xff,0x00,0x83,0xf0,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x05,0x00,0x64, 0xff,0x00 }; |
<main.cpp>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
#include "main.h" int main(void) { if (sendRawEthernet() == false) { return 1; } else { return 0; } } bool sendRawEthernet() { pcap_if_t* allDevices = nullptr; pcap_if_t* device = nullptr; char errbuf[PCAP_ERRBUF_SIZE]; if (pcap_findalldevs(&allDevices, errbuf) == -1 || allDevices == nullptr) { printError(__func__, __LINE__, errbuf); return false; } int i = 0; for (device = allDevices; device != nullptr; device = device->next) { printf("%d. %s", i++, device->name); if (device->description) printf(" (%s)\n", device->description); else printf(" (No description available)\n"); } if (i == 0) { printError(__func__, __LINE__, "No interfaces found"); } const int select = 6; /* // If you want to choose device yourself int select = -1; do{ std::cout << "Device: #"; std::cin >> select; if (std::cin.fail()) { std::cin.clear(); std::cin.ignore(); select = -1; } } while (select == -1); */ i = 0; for (device = allDevices; device != nullptr; device = device->next) { if (i == select) { break; } i++; } if (device == nullptr) { printError(__func__, __LINE__, "Failed to get device"); return false; } pcap_t* pcap; pcap = pcap_open_live(device->name, 260, // capture size 1, // 1: capture all packet 1000, // Timeout ms errbuf); if (pcap == nullptr) { printError(__func__, __LINE__, "Failed to open the adapter"); return false; } std::vector<unsigned char> packet(std::begin(packetQuery), std::end(packetQuery)); if (pcap_sendpacket(pcap, packet.data(), packet.size()) != 0) { printError(__func__, __LINE__, ""); return false; } return true; } void printError(const char* func, int line, const char* err) { std::cerr << func << "@" << line << ":" << err << std::endl; } |