|
这是个基于B/S的端口扫描程序,服务端为linux,但以下代码却只能扫描服务器本身 扫服务器时 能正确扫描 也能返回到浏览器 扫外面的IP则没有反应 不知道是怎么回事 请大家帮忙分析分析吧 先谢谢大家了
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
/* use a bigger value if you have a slow machine or slow connection and
* you notive packet-loss. Value is interpreted as microseconds, and if
* it's set to zero it will just give up the process' timeslice.
*/
#define USLEEP_MS 0
int usage(char *p)
{
fprintf(stderr, "usage: %s <src-ip> <dst-ip> [portrange]\n\n", p);
fprintf(stderr, "dst-ip\t\tcan be ip-address or hostname\n");
fprintf(stderr, "portrange\tstart-end, e.g. 1024-1500\n");
return 1;
}
/* this function parses a statement like "1024-1500" into a high value
* and a low value. If the users messes this up on commandline, he's
* got a problem, because this function won't switch them :-)
*/
void parse_portrange(unsigned short *lo, unsigned short *hi, char *s)
{
char *p;
p = s;
while(*s && *s != '-')
s++;
*(s++) = '\0';
*lo = atoi(p);
*hi = atoi(s);
}
/* this function calculates the checksum for the IP and TCP header */
u_short in_cksum(u_short *addr, int len)
{
u_short i = 0, *word = addr;
u_long acc = 0;
while(i++ < len / 2)
acc += *(word++);
return ~(*(u_short*)&acc + *((u_short*)&acc + 1));
}
/* this function calculates the TCP-checksum with its pseudo-header as
* described in RFC 793.
*/
u_short tcp_cksum(struct iphdr *ip, struct tcphdr *tcp)
{
char header[32], *p = header;
/* the pseudo-header includes the source-address, the destination-
* address (each 32 bit), 8 bit set to zero, 8 bit with the protocol
* and 16 bit with the TCP-packet's length. The rest of the header
* is the 'real' TCP-header.
*/
*(unsigned long*)p = ip->saddr;
p += 4;
*(unsigned long*)p = ip->daddr;
p += 4;
*p = 0;
p++;
*p = ip->protocol;
p++;
*(unsigned short*)p = htons(4 * tcp->doff);
p += 2;
memcpy(p, tcp, 4 * tcp->doff);
return in_cksum((unsigned short*)header, 32);
}
/* this function sends the SYN-packets out to the net */
int do_scan(int s, unsigned long src, unsigned long dst,
unsigned short lo, unsigned short hi)
{
struct iphdr *ip;
struct tcphdr *tcp;
char packet[sizeof(*ip) + sizeof(*tcp)];
struct sockaddr_in to;
unsigned short i;
ip = (struct iphdr*) packet;
tcp = (struct tcphdr*) (packet + sizeof(*ip));
memset(packet, 0, sizeof(packet));
ip->ihl = 5;
ip->version = 4; /* still IPv4 */
ip->tot_len = htons(sizeof(packet));
ip->ttl = 64;
ip->protocol = IPPROTO_TCP;
ip->saddr = src;
ip->daddr = dst;
ip->check = in_cksum((unsigned short*)ip, sizeof(*ip));
to.sin_addr.s_addr = dst;
to.sin_family = AF_INET;
to.sin_port = 0; /* irrelevant */
tcp->doff = 5;
tcp->source = htons(1024);
tcp->seq = rand();
tcp->syn = 1;
tcp->window = htons(1024);
for(i = lo; i <= hi; i++)
{
usleep(USLEEP_MS);
tcp->dest = htons(i);
tcp->check = 0;
tcp->check = tcp_cksum(ip, tcp);
if (sendto(s, packet, sizeof(packet), 0,
(struct sockaddr*)&to, sizeof(to)) == -1)
{
perror("sendto() failed");
return 1;
}
}
close(s);
return 0;
}
/* this function is called when a packed is received. First it checks whether
* it's a packet for our purposes or not, then it examines it further.
*/
int got_packet(char *packet, int len, unsigned long target,
unsigned short lo, unsigned short hi)
{
struct iphdr *ip;
struct tcphdr *tcp;
struct servent *srv;
char *name;
double prcnt;
unsigned short port;
int ret = 0;
ip = (struct iphdr*) packet;
tcp = (struct tcphdr*) (packet + sizeof(*ip));
/* our packet? */
if (ip->saddr != target)
return 0;
port = htons(tcp->source);
/* a bit statistic information for the inpatient user */
prcnt = (port -lo) /((hi - lo) / 100.0);
//printf("%i (%.1f%%)\r", port, prcnt);
fflush(stdout);
/* finished? */
if (port == hi)
ret = 1;
/* not a SYN|ACK? */
if (!(tcp->syn && tcp->ack))
return ret;
/* what service is it? */
if ( (srv = getservbyport(tcp->source, "tcp")) == NULL)
name = "unknown";
else
name = srv->s_name;
/* and tell the user about it */
printf("%i (%s) \n", port, name);
return ret;
}
/* the main-function that does all the rest */
int main(int argc, char *argv[])
{
int s, on, pid, bytes;
unsigned short lo, hi;
unsigned long target;
struct hostent *host;
char buffer[4096];
if (argc < 3)
return usage(argv[0]);
/* create the socket */
if ( (s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
{
perror("socket() failed");
return 2;
}
/* set the IP_HDRINCL option */
on = 1;
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1)
{
perror("setsockopt() for IP_HDRINCL failed");
return 3;
}
/* user-defined ports or builtin range? */
if (argc > 3)
parse_portrange(&lo, &hi, argv[3]);
else
{
lo = 1;
hi = 1024;
}
/* resolve hostname if needed */
if ((target = inet_addr(argv[2])) == -1)
{
host = gethostbyname(argv[2]);
if (!host)
{
herror("gethostbyname() failed");
return 4;
}
target = ((struct in_addr*)host->h_addr)->s_addr;
}
printf("SYN-scanning %s (%s), ports %i - %i\n", argv[2],
inet_ntoa(*(struct in_addr*)&target), lo, hi);
if ( (pid = fork()) == -1)
{
perror("fork() failed");
return 5;
}
/* the child sends the packets */
if (pid == 0)
exit(do_scan(s, inet_addr(argv[1]), target, lo, hi));
/* the parent receives them and prints out the results */
while( (bytes = read(s, buffer, sizeof(buffer)) > 0))
if (got_packet(buffer, bytes, target, lo, hi))
break;
close(s);
return 0;
} |
|