๐ ๊ณผ์ ๋ด์ฉ
๐งฉ ์ฝ๋ ๊ตฌ์ฑ ์ค๋ช
- ๊ตฌ์กฐ์ฒด
- struct Ethernet : 2๊ณ์ธต ์ด๋๋ท ํจํท์ ํค๋ ๊ตฌ์กฐ์ฒด
- strcut IP : 3๊ณ์ธต IP ํจํท์ ํค๋ ๊ตฌ์กฐ์ฒด
- struct TCP : 4๊ณ์ธต TCP ํจํท์ ํค๋ ๊ตฌ์กฐ์ฒด
- struct TCP_Payload : TCP ํ์ด๋ก๋๋ฅผ ์ ์ฅํ ๊ตฌ์กฐ์ฒด
- ํจ์
- void usage() : ์ฌ์ฉ๋ฒ์ ๋ํด ์ถ๋ ฅํด์ฃผ๋ ํจ์
- bool parse() : ์ธ์์ ๊ฐ์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ฐ์์ง๋ฉด True๋ฅผ ๋ฐํํ๋ ํจ์
- int main() :
- ์ธ์์ ๊ฐ์ ๊ฒ์ฌ
- ์๋ฌด ํจํท์ด ์บก์ณ๋์ง ์์์ ๋ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ
- ํจํท์ ์บก์ณํ๊ณ , TCP ํจํท์ธ์ง ํ์ธํ๊ณ ์ ๋ณด ์ถ๋ ฅ
๐ฅ๏ธ ์ฝ๋ & ์ค๋ช
#include <pcap.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>
// 2๊ณ์ธต ์ด๋๋ท ๊ตฌ์กฐ์ฒด ์ ์ธ : ์ด ๋ฐ์ดํธ๋ 14๋ฐ์ดํธ
struct Ethernet {
uint8_t dst_MAC[6];
uint8_t src_MAC[6];
uint16_t type;
} __attribute__ ((__packed__)); //#pragma pack 1๊ณผ ๋น์ทํ ์ญํ
// 3๊ณ์ธต IP ๊ตฌ์กฐ์ฒด ์ ์ธ
struct IP {
uint8_t IHL:4; // ์๋๋ Ver, IHL ์์์ด์ง๋ง, NBO์ ์ํด ์์๋ฅผ ๋ฐ๊ฟ ์ ์ธ
uint8_t Ver:4;
uint8_t Service;
uint16_t IP_total_length;
uint16_t Identification;
uint16_t Flags_FragOffset;
uint8_t TTL;
uint8_t Protocol;
uint16_t Header_checksum;
uint8_t src_IP[4];
uint8_t dst_IP[4];
} __attribute__ ((__packed__));
// 4๊ณ์ธต TCP ๊ตฌ์กฐ์ฒด ์ ์ธ
struct TCP {
uint16_t src_Port;
uint16_t dst_Port;
uint32_t Seq_Num;
uint32_t Ack_Num;
uint8_t Reserved:4; // ์๋๋ H_len, Reserved ์์์ด์ง๋ง, NBO์ ์ํด ์์๋ฅผ ๋ฐ๊ฟ ์ ์ธ
uint8_t H_len:4;
uint8_t Flags;
uint16_t Window;
uint16_t Checksum;
uint16_t Urgent_Pointer;
} __attribute__ ((__packed__));
// TCP Payload๋ฅผ ์ ์ฅํ ๊ตฌ์กฐ์ฒด ์ ์ธ
struct TCP_Payload {
uint8_t payload[16];
}__attribute__ ((__packed__));
void usage() {
printf("syntax: Pcap <interface>\n");
printf("sample: Pcap wlan0\n");
}
typedef struct {
char* dev_;
} Param;
Param param = {
.dev_ = NULL
};
// ์ธ์์ ๊ฐ์๊ฐ ์ ๋๋ก ๋ฐ์์ง๋ฉด True๋ฅผ ๋ฐํํ๋ ํจ์
bool parse(Param* param, int argc, char* argv[]) {
if (argc != 2) {
usage();
return false;
}
param->dev_ = argv[1]; // dev_๊ฐ argv[1]์ ์์น๋ฅผ ๊ฐ๋ฆฌํด
return true;
}
int main(int argc, char* argv[]) {
// ์ธ์ ๊ฐ์ ๊ฒ์ฌ
if (!parse(¶m, argc, argv))
return -1;
// PCAP_ERRBUF_SIZE : pcap ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋ฐ์ํ๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ์ฅํ๋ ๋ฒํผ์ ์ต๋ ํฌ๊ธฐ
// errbuf๋ ์ค๋ฅ ๋ฉ์ธ์ง๋ฅผ ๋ด์ ๋ฌธ์์ด
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* pcap = pcap_open_live(param.dev_, BUFSIZ, 1, 1000, errbuf);
// ์๋ฌด ํจํท์ด ์บก์ณ๋์ง ์์์ ๋ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ
if (pcap == NULL) {
fprintf(stderr, "pcap_open_live(%s) return null - %s\n", param.dev_, errbuf);
return -1;
}
// ๊ตฌ์กฐ์ฒด ๊ฐ์ฒด ์์ฑ
struct Ethernet *ethernet;
struct IP *ip;
struct TCP *tcp;
struct TCP_Payload *tcp_payload;
while (true) {
struct pcap_pkthdr* header;
const u_char* packet;
int res = pcap_next_ex(pcap, &header, &packet);
if (res == 0) continue;
if (res == PCAP_ERROR || res == PCAP_ERROR_BREAK) {
printf("pcap_next_ex return %d(%s)\n", res, pcap_geterr(pcap));
break;
}
// [์ด๋๋ท ํจํท] ํจํท์ ๋งจ ์ ์์น๋ถํฐ ๊ตฌ์กฐ์ฒด ํฌ๊ธฐ ๋งํผ ๋ฐ์ดํฐ๋ฅผ ํ ๋น
ethernet = (struct Ethernet *)packet;
// [ip ํจํท] ์ด๋๋ท ํค๋ ๋ค ์์น๋ถํฐ ๋ฐ์ดํฐ ํ ๋น
ip = (struct IP *)(packet + sizeof(struct Ethernet));
// [tcp ํจํท] ip ํค๋ ๋ค ์์น๋ถํฐ ๋ฐ์ดํฐ ํ ๋น
tcp = (struct TCP *)(packet + (sizeof(struct Ethernet)) + (ip->IHL * 4));
// [tcp ํ์ด๋ก๋] tcpํค๋ ๋ค ์์น๋ถํฐ ํ ๋น
tcp_payload = (struct TCP_Payload *)(packet + (sizeof(struct Ethernet) + (ip->IHL * 4) + (tcp->H_len * 4)));
// ์บก์ฒํ ํจํท์ด tcp ํจํท์ธ์ง ํ์ธ
if (ip->Protocol == 0x06 && ethernet->type == 0x0008) {
// ์ถ๋ฐ์ง MAC ์ฃผ์ ์ถ๋ ฅ
printf("Src MAC : ");
for (int i = 0; i < 6; i++) {
printf("%02X", ethernet->src_MAC[i]);
if (i <= 4)
printf(" : ");
else
printf("\n");
}
// ๋ชฉ์ ์ง MAC ์ฃผ์ ์ถ๋ ฅ
printf("Dst MAC : ");
for (int i = 0; i < 6; i++) {
printf("%02X", ethernet->dst_MAC[i]);
if (i <= 4)
printf(" : ");
else
printf("\n");
}
// ์ถ๋ฐ์ง IP ์ฃผ์ ์ถ๋ ฅ
printf("Src IP : ");
for (int i = 0; i < 4; i++) {
printf("%d", ip->src_IP[i]);
if (i <= 2)
printf(".");
else
printf("\n");
}
// ๋ชฉ์ ์ง IP ์ฃผ์ ์ถ๋ ฅ
printf("Dst IP : ");
for (int i = 0; i < 4; i++) {
printf("%d", ip->dst_IP[i]);
if (i <= 2)
printf(".");
else
printf("\n");
}
// ์ถ๋ฐ์ง ํฌํธ ์ถ๋ ฅ
printf("Src Port : %d\n", ntohs(tcp->src_Port));
// ๋ชฉ์ ์ง ํฌํธ ์ถ๋ ฅ
printf("Dst Port : %d\n", ntohs(tcp->dst_Port));
// ๋ฐ์ดํฐ ๊ธธ์ด ์ถ๋ ฅ
printf("Total Byte : %u\n", header->caplen);
// TCP ํ์ด๋ก๋ ์ถ๋ ฅ
int check_remain = header->caplen - (sizeof(struct Ethernet) + (ip->IHL * 4) + (tcp->H_len * 4));
if (check_remain != 0 ) {
printf("TCP Payload : ");
for (int i = 0; i < check_remain; i++) {
if (i == 16) break;
printf("%02X", tcp_payload->payload[i]);
printf(" ");
}
printf("\n");
}
printf("\n");
}
}
pcap_close(pcap);
}
โ ํจํท ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ธํด ์ฃผ๋ ๊ณผ์ ์์ ๋ฉค๋ฒ ๋ณ์ ์์๊ฐ ๋ฐ๋ ์ด์
์๋ IP ํจํท์ ํค๋ ์ ๊ฐ๋ค์ ์์๋ ์๋์ ๊ฐ๋ค
Version → Header Length→ Type of Service → Total Length → ...
ํ์ง๋ง ์ ์ฃผ์์ ๋ฌ์๋์ ๊ณณ์ ๋ณด๋ฉด
Header Length(IHL)๋ฅผ ๋จผ์ ์ ์ธํ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด๋ NBO(Network Byte Order) ๋๋ฌธ์ธ๋ฐ, ๋คํธ์ํฌ์์๋ ๋น ์๋์ธ ๋ฐฉ์์ ์ด์ฉํ๋ ํน์ฑ์ ์ํด
๋ฎ์ ์ฃผ์์์ ๋์ ์ฃผ์๋ก ๋ฐ์ดํฐ๋ฅผ ํํํ๊ฒ ๋๋ค.
NBO๊ฐ ๋ฐ์ดํธ์๋ง ์ํฅ์ ์ฃผ๋ ๊ฒ์ด ์๋๋ผ, ๋นํธ์๋ ์ํฅ์ ์ค๋ค.
์ค์ ๋ก NBO๊ฐ ๋ฐ์ดํธ์ ์ํฅ์ ์ฃผ๋ ๊ฒ์ wireshark์์ ํ์ธํด ๋ณด์.
๋น ์๋์ธ ์์ ๋๋ฌธ์ 5 → 4 ์์๋ก ๊ฐ์ด ๋ค์ด๊ฐ๋ฏ๋ก Header Length(IHL)์ ๋จผ์ ๊ฐ์ ๋ฃ์ด ์ฃผ์๋ค.
์ค์ ๋ก OS ๋ด์ฅ ํจ์์ ์ ์๋ TCP Header์๋ NBO ๋๋ฌธ์ ํธ์คํธ ํ๊ฒฝ์ ๋ฐ๋ผ ์๋์ธ์ ๊ฐ๋ ค์ ์ ๋ ฅ๋ฐ๋๋ค๊ณ ํ๋ค.
์๋์ 4๊ณ์ธต์ TCP ๊ตฌ์กฐ์ฒด ์ญ์ ์ด์ ๊ฐ์ ์ด์ ๋ก ์์๋ฅผ ๋ฐ๊ฟ ์ ์ธํด ์ฃผ์๋ค.
โ ํ์ด๋ก๋ ์ถ๋ ฅํ๊ธฐ
๋จผ์ TCP ํ์ด๋ก๋๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ check_remain ๋ณ์๋ฅผ ์ ์ธํด ์ฃผ์๋ค.
์ด ๋ณ์๋ TCP ํ์ด๋ก๋์ ๊ธธ์ด๋ฅผ ์ ์ฅํด ์ฃผ๋ ๋ณ์์ด๋ค.
TCP ํ์ด๋ก๋๋ TCP ํค๋์ ๋ค์ ์์นํ๊ณ ์๊ธฐ ๋๋ฌธ์,
์ ์ฒด ํจํท ๊ธธ์ด์์ ์ด๋๋ท, IP, TCP ํค๋์ ๊ธธ์ด๋ฅผ ๋นผ์ค ๊ฐ์ด ํ์ด๋ก๋์ ๊ธธ์ด๊ฐ ๋๋ค.
๋ฐ๋ผ์ ๋ง์ฝ ์ ์ฒด ํจํท์ ๊ธธ์ด๊ฐ 2, 3, 4 ๊ณ์ธต์ ํค๋์ ๊ธธ์ด๊ฐ ๊ฐ๋ค๋ฉด ํ์ด๋ก๋๊ฐ ์๋ค๋ ์๋ฏธ์ด๋ฏ๋ก ์ถ๋ ฅ์ ํ์ง ์๋๋ก ์ฝ๋๋ฅผ ์์ฑํด์๋ค.
ํ์ด๋ก๋๋ฅผ ์ถ๋ ฅํด ์ค ๋๋ ๊ธธ์ด๋งํผ๋ง ์ถ๋ ฅํด ์ฃผ๋๋ก for๋ฌธ์์ check_remain์ ๊ฐ๊ณผ ๋น๊ตํ๋๋ก ํ์๋ค.
ํ์ด๋ก๋์ ์ต๋ ์ถ๋ ฅ ๊ธธ์ด๋ 16byte์ด๋ฏ๋ก 16๋ฐ์ดํธ๊ฐ ์ถ๋ ฅ์ด ๋๋ฉด for ๋ฌธ์ break ํด์ฃผ์๋ค.
๐๏ธ ์ถ๋ ฅ ๊ฒฐ๊ณผ
๋จผ์ , ifconfig๋ก ์ธํฐํ์ด์ค๋ฅผ ํ์ธํด ์ค๋ค.
๋น๋ํ ํ์ผ์ ์คํํด ์ค๋ค. ์ด๋, ๋ด ์ธํฐํ์ด์ค์ธ ens33๋ ์ ๋ ฅํด ์ค๋ค.
ํจํท์ด ์บก์ฒ๋๊ณ , ํจํท์ ์ ๋ณด๋ค์ด ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.