2017-10-31 5 views
1

C++의 RAW 소켓을 사용하여 모든 ICMP "도달 할 수없는 대상 - 포트 도달 불가능"메시지를 잡으려고합니다. 그런 다음 기본 UDP 프로토콜을 처리하여 대상에 도달 할 수없는 포트를 찾습니다. 지금까지 ICMP 메시지를 받고 그 유형과 코드에 따라 필터링했습니다. 그러나 udp 헤더에 액세스하는 데 어려움을 겪고 있습니다. 어느 하나 일ICMP 메시지에서 UDP로 액세스

*(struct udphdr*)(icmp + sizeof(struct icmphdr) + sizeof(struct iphdr)) 

struct iphdr *ip = (struct iphdr*)ether_frame; 
struct icmphdr *icmp = (struct icmphdr*)(ether_frame + ip->ihl*4); 
struct iphdr *ip2 = (struct iphdr*)(icmp + sizeof(struct icmphdr)) 
struct udphdr *udphdr = (struct udphdr*)(ip2 + ip2->ihl*4) 

그러나 : 지금까지 나는이 시도했다. 나는 그것이 단순한 포인터 산술 실수라고 확신하지만, 나는 그것을 이해할 수 없다. 그렇다면 제 질문은 다음과 같습니다. ICMP 응답으로 프로토콜을 정확히 구성하는 방법은 무엇입니까? 원시 icmp 응답에서 도달 할 수없는 포트 번호에 어떻게 액세스합니까?

EDIT : this->rcv_sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP를 사용하여 생성하고, 응답 ether_frame 크기 IP_MAXPACKETuint8_trecv(this->rcv_sd, ether_frame, IP_MAXPACKET, 0) 배열을 이용하여 수신되는 수신에 사용되는 소켓.

+1

"* 프로토콜은 얼마나 정확하게 ICMP 응답으로 구성되어 있습니까?"- Wireshark 또는 기타 유사한 패킷 스니퍼 + 분석기를 사용하여 실제 패킷 구조를 직접 확인하는 것이 좋습니다. –

+0

물론 그랬지 만, 내 첫 시도 (''struct udphdr *) (icmp + sizeof (struct icmphdr) + sizeof (struct iphdr)'')는 내가 본 것 wireshark. – sveatlo

+0

예, 그렇지 않은 경우 icmp의 유형 및 코드를 기반으로 필터링 할 수 없습니다. 나는 또한 gdb에서 그것들을 보았고 그들의 내용은 wireshark에서 본 것과 동일하다. – sveatlo

답변

3

(icmp + sizeof(struct icmphdr))(ip2 + ip2->ihl*4)과 같은 명령문은 실제로 struct 포인터에 바이트 수를 추가하여 pointer arithmetic을 사용하므로 잘못된 주소로 끝나게됩니다.

입력 된 포인터에 숫자를 추가 할 때 포인터는 기본 형식의 바이트 수에 지정된 수를 곱한 값으로 조정됩니다.

그래서,이 :

struct udphdr *udphdr = (struct udphdr*)(((uint8_t*)ip2) + (sizeof(*ip2) * (ip2->ihl*4))) 
0,123,516 :

struct udphdr *udphdr = (struct udphdr*)(ip2 + ip2->ihl*4) 

이하는 것과 같습니다

struct iphdr *ip2 = (struct iphdr*)(((uint8_t*)icmp) + (sizeof(*icmp) * sizeof(struct icmphdr))) 

을 그리고이 :

struct iphdr *ip2 = (struct iphdr*)(icmp + sizeof(struct icmphdr)) 

은 다음과 동일합니다 당신이 바이트가 아닌 요소하여 구조체 포인터를 상쇄하기 원하기 때문에

, 당신은 그들에게 바이트 수를 추가하기 전에 바이트 포인터로 구조체 포인터를 캐스팅 입력해야합니다

struct iphdr *ip2 = (struct iphdr*)(((uint8_t*)icmp) + sizeof(struct icmphdr)) 
// or simpler, using correct pointer arithmetic: 
// struct iphdr *ip2 = (struct iphdr*)(icmp + 1) 

struct udphdr *udphdr = (struct udphdr*)(((uint8_t*)ip2) + (ip2->ihl*4)) 

이 문제가없는 ether_frame이 포인터로 붕괴하는 uint8_t의 배열이기 때문에 ipicmp 포인터를 ether_frame 버퍼에서 할당 할 때.