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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
| #include <WinSock2.h>
#include <ws2tcpip.h>
#include <Ws2ipdef.h>
#include <windows.h>
#include <crtdbg.h>
#include <iostream>
using std::cout;
#pragma comment (lib,"ws2_32")
//#define TRACERT //если вместо пинга нужен трэйс
#define MANUAL //если надо сформировать IP заголовок вручную.
#ifdef MANUAL
#define PACKET_ FullPack
#else
#define PACKET_ Packet
#endif
typedef struct ip_hdr //заголовок IP
{
unsigned char verhlen;
unsigned char tos:6;
unsigned char additional:2;
unsigned short totallent;
unsigned short id;
unsigned short offset;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int source;
unsigned int destination;
}IpHeader;
typedef struct icmp_hdr //заголовок ICMP
{
unsigned char i_type;
unsigned char i_code;
unsigned short i_crc;
unsigned short i_seq;
unsigned short i_id;
}IcmpHeader;
USHORT crc2 (USHORT* addr, int count) //http://www.ietf.org/rfc/rfc1071.txt подсчет CRC
{
register long sum = 0;
while( count > 1 ) {
/* This is the inner loop */
sum += * (unsigned short*) addr++;
count -= 2;
}
/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
return (USHORT)(~sum);
}
unsigned int analize(char* data, SOCKADDR_IN* adr) //разбор ответа
{
char* Ip = "";
IpHeader *pHe = (IpHeader*)data;
char Name[NI_MAXHOST]={0};
char servInfo[NI_MAXSERV]={0};
getnameinfo((struct sockaddr *) adr,sizeof (struct sockaddr),Name, NI_MAXHOST, servInfo, NI_MAXSERV, NI_NUMERICSERV);
Ip = inet_ntoa(adr->sin_addr);
#ifdef TRACERT
IcmpHeader *ic = (IcmpHeader*)data;
cout<<"Reply from "<<" "<<Name<<" ["<<Ip<<"]\n";
return pHe->source;
#else
int TTL = (int)pHe->ttl;
data+=sizeof(IpHeader);
IcmpHeader *ic = (IcmpHeader*)data;
if(GetCurrentProcessId()==ic->i_id)//проверка что это мы слали.
cout<<"Reply from "<<Ip<<" TTL="<<TTL<<"\n";
else
cout<<"Fake packet\n";
return pHe->source;
#endif
}
int main()
{
_CrtSetDbgFlag(33);
const char* Ip = "213.180.204.3"; //сюда вбить пингуемый адрес, сейчас это ЯНДЕКС
const char* IpLocal = "тут ваш локальный адрес, для заголовка IPv4";
//удаленный адрес
SOCKADDR_IN list_adr = {0};
list_adr.sin_addr.S_un.S_addr = inet_addr(Ip);
list_adr.sin_family = AF_INET;
list_adr.sin_port = htons(6666);
//локальный адрес
SOCKADDR_IN bnd = {0};
bnd.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
bnd.sin_family = AF_INET;
bnd.sin_port = htons(6666);
WSADATA wsd = {0};
WSAStartup(0x202,&wsd);
SOCKET listn = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,0,0,WSA_FLAG_OVERLAPPED);
bind(listn,(sockaddr*)&bnd,sizeof(bnd));
IcmpHeader pac = {0};
int timeout = 3000;
setsockopt(listn,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)); //таймаут получения
pac.i_type = 8;
pac.i_code = 0;
pac.i_seq = 0x2;
pac.i_crc =0;
pac.i_id = (USHORT)GetCurrentProcessId();//записать в ICMP идентификатор процесса.
//создаем довесок из данных в 32 байта заполненый буквой Z, чтоб было похоже на настоящее
int size = sizeof(pac)+32;
char* Icmp = new char [size];
memcpy(Icmp,&pac,sizeof(pac));
memset(Icmp+sizeof(pac),'Z',32);
IcmpHeader *Packet = (IcmpHeader *)Icmp;
Packet->i_crc = crc2((USHORT*)Packet,size);//считаем контрольную сумму пакета, заголовок+данные
char bf [256] = {0};
int outlent = sizeof(SOCKADDR_IN);
SOCKADDR_IN out_ = {0};
out_.sin_family = AF_INET;
#ifdef MANUAL
//здесь формируем IP заголовок вручную
// и собираем пакет наш IP+Icmp+32байта данных
int icmp_size = sizeof(pac)+32;
size = sizeof(IpHeader)+sizeof(IcmpHeader)+32;
int param = 1;
setsockopt(listn,IPPROTO_IP,IP_HDRINCL,(char*)¶m,sizeof(param));//сообщаем что сами слепим заголовок
IpHeader IpHead = {0};
IpHead.verhlen = 69;
IpHead.ttl = 200;
IpHead.source = inet_addr(IpLocal );
IpHead.destination = inet_addr(Ip);
IpHead.totallent = size-icmp_size;
IpHead.proto = 1;
char* FullPack = new char [size];
memcpy(FullPack,&IpHead,sizeof(IpHeader));
memcpy(FullPack+sizeof(IpHeader),Packet,icmp_size);
//crc IP система посчитает сама, с ним можно не париться
//однако для ICMP расчет обязателен
#endif
#ifdef TRACERT
unsigned int control = list_adr.sin_addr.S_un.S_addr;
cout<<"TRACE route to >>> "<<Ip<<" with 20 hops\n";
for(int i=1;i<=20;++i)
{
#ifdef MANUAL
IpHeader* ipH = (IpHeader*)PACKET_;
ipH->ttl = i;
#else
setsockopt(listn,IPPROTO_IP,IP_TTL,(char*)&i,4);
#endif
int bytes =sendto(listn,(char*)PACKET_,size,0,(sockaddr*)&list_adr,sizeof(list_adr));
Sleep(1000);
if(recvfrom(listn,bf,256,0,(sockaddr*)&out_,&outlent)==SOCKET_ERROR)
{
if(WSAGetLastError()==WSAETIMEDOUT)
{
cout<<"Request timeout\n";
continue;
}
}
cout<<i<<" ";
if(analize(bf,&out_)==control)break;
memset(bf,0,0);
}
#else
//ПИНГИ
cout<<"Pinging address >) "<<Ip<<"\n";
for(int i = 0;i<4; ++i)
{
int bytes =sendto(listn,(char*)PACKET_,size,0,(sockaddr*)&list_adr,sizeof(list_adr));
Sleep(1000);
if(recvfrom(listn,bf,256,0,(sockaddr*)&out_,&outlent)==SOCKET_ERROR)
{
if(WSAGetLastError()==WSAETIMEDOUT)
{
cout<<"Request timeout\n";
continue;
}
}
analize(bf,&out_);
memset(bf,0,0);
}
#endif
delete [] Icmp;
#ifdef MANUAL
delete [] FullPack;
#endif
cout<<"COMLETE\n";
closesocket(listn);
WSACleanup();
system("Pause");
return 0;
} |