-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paths.c
executable file
·675 lines (615 loc) · 18.5 KB
/
s.c
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
/*
Copyright (C) sincoder
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
TCP Syn port scanner
By:sincoder
Blog:www.sincoder.com
*/
#include <stdio.h> //printf
#include <string.h> //memset
#include <stdlib.h> //for exit(0);
#include <sys/socket.h>
#include <errno.h> //For errno - the error number
#include <pthread.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <netdb.h> //hostend
#include <arpa/inet.h>
#include <netinet/tcp.h> //Provides declarations for tcp header
#include <netinet/ip.h> //Provides declarations for ip header
#define msg(fmt,arg...) do{printf(fmt,##arg);fflush(stdout);}while(0)
const char *logFileName = "result.txt";
int log_fd = 0; // for log
int bIsLogRet = 0 ;//is log scan result
uint32_t g_bind_ip = 0; // 绑定的本地ip
uint8_t g_port_list[0xFFFF] = {0}; //要扫描的端口相应的位会被置1
volatile int g_IsTimeToShutDown = 0;
volatile uint32_t g_open_port_count = 0 ;//扫描到的开发端口的 ip 的数量
enum IpSingType
{
IP_TYPE_RANGE,
IP_TYPE_SINGLE
};
typedef struct _IPSting
{
enum IpSingType type;
uint32_t start_ip;
uint32_t end_ip;
} IPString;
IPString *g_ScanIpList = NULL;
uint32_t g_IpCount = 0;
#pragma pack(push,1)
typedef struct _ip_header
{
unsigned char h_lenver; //4位首部长度+4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
uint32_t sourceIP; //32位源IP地址
uint32_t destIP; //32位目的IP地址
} IP_HEADER;
typedef struct _tcp_header //定义TCP首部
{
unsigned short th_sport; //16位源端口
unsigned short th_dport; //16位目的端口
uint32_t th_seq; //32位序列号
uint32_t th_ack; //32位确认号
unsigned char th_lenres; //4位首部长度/6位保留字
unsigned char th_flag; //6位标志位
unsigned short th_win; //16位窗口大小
unsigned short th_sum; //16位校验和
unsigned short th_urp; //16位紧急数据偏移量
} TCP_HEADER;
typedef struct _psd_header //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
} PSD_HEADER;
#pragma pack(pop)
static int start_sniffer();
/*
Get ip from domain name
*/
uint32_t hostname_to_ip(char *hostname)
{
struct hostent *he;
struct in_addr **addr_list;
int i;
//msg("%s:%s\n",__func__,hostname);
if ( (he = gethostbyname( hostname ) ) == NULL)
{
// get the host info
//herror("gethostbyname");
//use inet_ntoa
return inet_addr(hostname);
}
addr_list = (struct in_addr **) he->h_addr_list;
for (i = 0; addr_list[i] != NULL; i++)
{
//Return the first one;
return (*addr_list[i]).s_addr;
//return inet_ntoa(*addr_list[i]) ;
}
return 0;
}
unsigned short checkSum(void *buffer, int size)
{
unsigned long cksum = 0;
while (size > 1)
{
cksum += *(unsigned short *)buffer;
size -= sizeof(unsigned short);
buffer = (char *)buffer + sizeof(unsigned short);
}
if (size) cksum += *(unsigned char *) buffer;
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (unsigned short) (~cksum);
}
int buildSynPacket(char *buf, u_long saddr, u_long sport, u_long daddr, u_long dport)
{
int len = 0;
IP_HEADER ip_header;
TCP_HEADER tcp_header;
PSD_HEADER psd_header;
//填充IP首部
ip_header.h_lenver = (4 << 4 | sizeof(ip_header) / sizeof(unsigned long));
//高四位IP版本号,低四位首部长度
ip_header.total_len = htons(sizeof(IP_HEADER) + sizeof(TCP_HEADER)); //16位总长度(字节)
ip_header.ident = 1; //16位标识
ip_header.frag_and_flags = 0; //3位标志位
ip_header.ttl = 128; //8位生存时间TTL
ip_header.proto = IPPROTO_TCP; //8位协议(TCP,UDP…)
ip_header.checksum = 0; //16位IP首部校验和
ip_header.sourceIP = saddr; //32位源IP地址
ip_header.destIP = daddr; //32位目的IP地址
//填充TCP首部
tcp_header.th_sport = sport; //源端口号
tcp_header.th_lenres = (sizeof(TCP_HEADER) / 4 << 4 | 0); //TCP长度和保留位
tcp_header.th_win = htons(0x4000);
//填充TCP伪首部(用于计算校验和,并不真正发送)
psd_header.saddr = ip_header.sourceIP;
psd_header.daddr = ip_header.destIP;
psd_header.mbz = 0;
psd_header.ptcl = IPPROTO_TCP;
psd_header.tcpl = htons(sizeof(tcp_header));
tcp_header.th_dport = dport; //目的端口号
tcp_header.th_ack = 0; //ACK序列号置为0
tcp_header.th_flag = 2; //SYN 标志
tcp_header.th_seq = sport - 1; //SYN序列号随机
tcp_header.th_urp = 0; //偏移
tcp_header.th_sum = 0; //校验和
//计算TCP校验和,计算校验和时需要包括TCP pseudo header
memcpy(buf, &psd_header, sizeof(psd_header));
memcpy(buf + sizeof(psd_header), &tcp_header, sizeof(tcp_header));
tcp_header.th_sum = checkSum(buf, sizeof(psd_header) + sizeof(tcp_header));
//计算IP校验和
memcpy(buf, &ip_header, sizeof(ip_header));
memcpy(buf + sizeof(ip_header), &tcp_header, sizeof(tcp_header));
memset(buf + sizeof(ip_header) + sizeof(tcp_header), 0, 4);
len = sizeof(ip_header) + sizeof(tcp_header);
ip_header.checksum = checkSum(buf, len);
//填充发送缓冲区
memcpy(buf, &ip_header, sizeof(ip_header));
return len;
}
const char *TakeOutStringByChar(const char *Source, char *Dest, int buflen, char ch)
{
int i;
if (Source == NULL)
return NULL;
const char *p = strchr(Source, ch);
while (*Source == ' ')
Source++;
for (i = 0; i < buflen && *(Source + i) && *(Source + i) != ch; i++)
{
Dest[i] = *(Source + i);
}
if (i == 0)
return NULL;
else
Dest[i] = '\0';
const char *lpret = p ? p + 1 : Source + i;
while (Dest[i - 1] == ' ' && i > 0)
Dest[i-- -1] = '\0';
return lpret;
}
void InsertIntoIpList(enum IpSingType type, uint32_t start_ip, uint32_t end_ip)
{
// msg("%s:%x %x\n",__func__,start_ip,end_ip);
if (!g_ScanIpList)
{
g_ScanIpList = (IPString *)malloc(sizeof(IPString));
g_ScanIpList->end_ip = end_ip;
g_ScanIpList->start_ip = start_ip;
g_ScanIpList->type = type;
++g_IpCount ;
return ;
}
else
{
IPString *pTmp = (IPString *)malloc((g_IpCount + 1) * sizeof(IPString));
memcpy(pTmp, g_ScanIpList, g_IpCount * sizeof(IPString));
free(g_ScanIpList);
g_ScanIpList = pTmp;
g_ScanIpList[g_IpCount].end_ip = end_ip;
g_ScanIpList[g_IpCount].start_ip = start_ip;
g_ScanIpList[g_IpCount].type = type;
++g_IpCount;
return;
}
};
void DestoryIpList()
{
free(g_ScanIpList);
g_ScanIpList = NULL;
}
/*
典型的用法
uint32_t start = inet_addr("192.168.122.1");
uint32_t end = inet_addr("192.168.123.122");
uint32_t ip = start;
do
{
msg("%s\n",inet_ntoa(*(struct in_addr *)&ip));
} while ((ip = GetNextIpInRange(ip,end)));
*/
uint32_t GetNextIpInRange(uint32_t start, uint32_t end)
{
uint32_t pos = start;
pos = htonl(start ) + 1;
if (pos > htonl(end))
{
return 0;
}
pos = htonl(pos);
return pos;
}
int ParseIpString(const char *IpString)
{
const char *p = IpString;
char *slash = NULL;
char buff[256];
int count = 0;
while ((p = TakeOutStringByChar(p, buff, 256, ',')))
{
char startIpStr[256] = {0};
uint32_t start, end, range, submask;
start = end = range = submask = 0;
enum IpSingType type;
//msg("%s \n",buff);
if ((slash = strchr(buff, '/'))) //12.12.12.12/24
{
strncpy(startIpStr, buff, slash - buff );
int bit = atoi(slash + 1);
range = 0xFFFFFFFF >> bit;
submask = 0xFFFFFFFF << (32 - bit);
uint32_t ip = hostname_to_ip(startIpStr);
if (!ip)
continue;
start = (ip & ntohl(submask)) + ntohl(1);
end = (ip & ntohl(submask)) + ntohl(range - 1);
type = IP_TYPE_RANGE;
}
else if ((slash = strchr(buff, '-'))) //12.12.12.12 - 12.12.12.122
{
strncpy(startIpStr, buff, slash - buff );
start = hostname_to_ip(startIpStr);
end = hostname_to_ip(slash + 1);
type = IP_TYPE_RANGE;
}
else //12.12.12.12
{
start = hostname_to_ip(buff);
end = 0xFFFFFFFF;
type = IP_TYPE_SINGLE;
}
if ((start || end) && (htonl(start) < htonl(end)))
{
InsertIntoIpList(type, start, end);
count ++;
}
}
return count;
}
void GetNextScanIp(int (*callback)(uint32_t, void *), void *lparam)
{
uint32_t idx;
if (!g_ScanIpList)
{
msg("%s Ip list not init ?!\n", __func__);
return ;
}
for (idx = 0 ; idx < g_IpCount; idx ++)
{
switch (g_ScanIpList[idx].type)
{
case IP_TYPE_RANGE:
{
//msg("%s:%x %x\n",__func__,g_ScanIpList[idx].start_ip,g_ScanIpList[idx].end_ip);
uint32_t ip = g_ScanIpList[idx].start_ip;
do
{
callback(ip, lparam);
}while ((ip = GetNextIpInRange(ip, g_ScanIpList[idx].end_ip)));
}
break;
case IP_TYPE_SINGLE:
{
callback(g_ScanIpList[idx].start_ip, lparam);
}
break;
default:
msg("%s:%s", __func__, "unknow ip type \n");
break;
}
}
}
void ParsePortString(const char *ScanPortString)
{
const char *p = ScanPortString;
char buff[256];
int idx;
while ((p = TakeOutStringByChar(p, buff, 256, ',')))
{
uint16_t start, end;
char *slash = NULL;
char port[64] = {0};
if ((slash = strchr(buff, '-'))) //122-1111
{
strncpy(port, buff, slash - buff );
start = atoi(port);
end = atoi(slash + 1);
if (end < start)
{
continue;
}
for (idx = start; idx <= end; idx++)
{
g_port_list[idx] = 1;
}
}
else
{
start = atoi(buff);
g_port_list[start] = 1;
}
}
}
uint32_t GetScanPortCount()
{
int idx = 0 ;
uint32_t count = 0 ;
for (idx = 0 ; idx < 0xFFFF; idx++)
{
if (g_port_list[idx])
++count;
}
return count;
}
int help(char *app) //argc 3 4
{
printf("Usage: %s [Ip String] Ports [/Save]\n", app);
printf("Example: %s 12.12.12.12-12.12.12.254 80\n", app);
printf("Example: %s 12.12.12.12 1-65535\n", app);
printf("Example: %s 12.12.12.12/24 1-65535\n", app);
printf("Example: %s 12.12.12.12-12.12.12.254 21,80,3389\n", app);
return printf("Example: %s 12.12.12.12,12.12.12.122 21,80,3389-22233 /Save\n", app);
}
/*
Method to sniff incoming packets and look for Ack replies
*/
void *receive_ack( void *ptr )
{
int sock_raw = 0; // raw socket for sniff
int data_size;
socklen_t saddr_size;
struct sockaddr saddr;
unsigned char buffer[65536];// = (unsigned char *)malloc(65536); //Its Big!
//Create a raw socket that shall sniff
sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
if (sock_raw < 0)
{
printf("Socket Error\n");
fflush(stdout);
return 1;
}
saddr_size = sizeof(saddr);
while (!g_IsTimeToShutDown)
{
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , &saddr_size);
if (data_size < 0 )
{
msg("%s", "Recvfrom error , failed to get packets\n");
return 1;
}
//Now process the packet
process_packet(buffer , data_size);
}
close(sock_raw);
// msg("%s","Sniffer finished.");
return NULL;
}
/*
* 看看给定的一个 port 是不是我们要求检测的 port
* 在的话返回 1 否则返回 0
*/
int is_port_in_portlist(uint16_t port)
{
if (port < 0xFFFF)
return g_port_list[port];
return 0;
}
/*
* 处理收到的数据包 看看那些 Ip 的端口打开了
*/
void process_packet(unsigned char *buffer, int size)
{
//Get the IP Header part of this packet
char log_buff[256];
int len = 0;
IP_HEADER *iphdr = (IP_HEADER *)buffer;
TCP_HEADER *tcphdr = NULL;
if (iphdr->proto == IPPROTO_TCP)
{
/* retireve the position of the tcp header */
int ip_len = (iphdr->h_lenver & 0xf) * 4;
tcphdr = (TCP_HEADER *) (buffer + ip_len);
if (tcphdr->th_flag == 18) //ACK+SYN
{
//放到个队列中,使用 connect 函数验证下。
uint16_t port = ntohs(tcphdr->th_sport);
if (is_port_in_portlist(port))
{
g_open_port_count ++;
len = sprintf(log_buff, "%-16s%-8u \n",
inet_ntoa(*(struct in_addr *)&iphdr->sourceIP),
ntohs(tcphdr->th_sport));
if (bIsLogRet)
{
int ret = write(log_fd, log_buff, len);
if(ret < 0 )
{
msg("write result file failed !!\n");
}
}
msg("%s", log_buff);
}
}
}
}
/*
* 得到本地要绑定的 ip
*/
uint32_t get_local_ip (uint32_t ip)
{
int sock = socket ( AF_INET, SOCK_DGRAM, 0);
int dns_port = 53;
int err;
struct sockaddr_in serv;
struct sockaddr_in name;
socklen_t namelen = sizeof(name);
//msg("%s:%s \n",__func__,inet_ntoa(*(struct in_addr *)&ip));
memset( &serv, 0, sizeof(serv));
memset( &name, 0, sizeof(name));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = ip;//inet_addr(HostName);
//memcpy(&serv.sin_addr.s_addr,&ip,4);
serv.sin_port = htons( dns_port );
err = connect( sock , (const struct sockaddr *) &serv , sizeof(serv) );
err = getsockname(sock, (struct sockaddr *) &name, &namelen);
//const char *p = inet_ntop(AF_INET, &name.sin_addr, buffer, 100);
close(sock);
if (-1 == err)
{
msg("%s:%s", __func__, "getsockname failed\n");
return 0;
}
return name.sin_addr.s_addr;
}
/*
获取端口的 bunny
*/
int GetPortbunny(int socket,char *buff,uint32_t len)
{
unsigned char data[] = {"GET / HTTP/1.1\r\n\r\n"};
if(send(socket,data,sizeof(data),0) > 0)
{
int recv_bytes = 0;
unsigned buff[1024];
if((recv_bytes = recv(socket,buff,sizeof(buff),0) > 0))
{
}
}
}
int ip_callback(uint32_t ip, void *lparam)
{
static uint32_t seed = 0x2b;
uint32_t idx = 0;
int len = 0;
int s = (int)lparam;
struct sockaddr_in addr;
char buff[0x100];
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ip;
if (!g_bind_ip)
{
g_bind_ip = get_local_ip(ip);
msg("bind on ip : %s \n", inet_ntoa(*(struct in_addr *)&g_bind_ip));
}
for (idx = 0 ; idx < 0xFFFF; idx ++)
{
if (g_port_list[idx])
{
addr.sin_port = htons(idx);
msg("scanning %16s:%u found %8u host\r",
inet_ntoa(*(struct in_addr *)&ip),
idx,
g_open_port_count);
srandom(seed++);
len = buildSynPacket(buff, //
g_bind_ip, //src ip
htons(random() % 0xFFFF), //src port
ip, //dst ip
addr.sin_port);
if ( sendto (s, buff, len, 0 , (struct sockaddr *) &addr, sizeof (addr)) < 0)
{
printf ("Error sending syn packet. Error number : %d . Error message : %s \n" , errno , strerror(errno));
return 0;
}
}
}
return 1;
}
int main(int argc, char *argv[])
{
int s;
uint32_t ScanPortCount = 0;
msg("%s", "s syn port scanner\nBY:sincoder\nBlog:www.sincoder.com\n");
if (argc < 3 )
{
help(argv[0]);
return -1;
}
ParseIpString(argv[1]);
ParsePortString(argv[2]);
ScanPortCount = GetScanPortCount();
if (!ScanPortCount)
{
msg("%s", "No Ports !!\n");
return -1;
}
else
{
msg("About to scan %u ports\n", ScanPortCount);
}
if (argc == 4)
{
bIsLogRet = 1;
log_fd = open(logFileName, O_RDWR | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
if (log_fd == -1)
{
msg("Can not create log file .\n");
return -1;
}
}
//Create a raw socket
s = socket (AF_INET, SOCK_RAW , IPPROTO_TCP);
if (s < 0)
{
msg("Error creating socket. Error number : %d . Error message : %s \n" , errno , strerror(errno));
msg("s must be run as root !\n");
return -1;
}
//IP_HDRINCL to tell the kernel that headers are included in the packet
int one = 1;
const int *val = &one;
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
{
printf ("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n" , errno , strerror(errno));
close(s);
return -1;
}
msg("%s", "Starting sniffer thread...\n");
pthread_t sniffer_thread;
g_IsTimeToShutDown = 0;
if ( pthread_create( &sniffer_thread , NULL , receive_ack , NULL) < 0)
{
msg("Could not create sniffer thread. Error number : %d . Error message : %s \n" , errno , strerror(errno));
goto clean;
}
GetNextScanIp(ip_callback, (void *)s);
sleep(2);
g_IsTimeToShutDown = 1;
ip_callback(g_bind_ip, (void *)s); //send a packet to myself ,let me exit ^_^
msg("%s", "scan over!! \n");
pthread_join( sniffer_thread , NULL);
clean:
DestoryIpList();
if (bIsLogRet)
close(log_fd);
close(s);
return 0;
}