linux 使用syn扫描,用libnet和libpcap构建Linux下的SYN扫描程序

环境:ubuntu 8.04

需要用到的工具:libnet,libpcap,tcpdump

安装这些工具:sudo apt-get install libnet-dev libpcap-dev tcpdump

本程序在freebsd下测试没有通过。libnet发送包,libpcap接收包,很方便(特别是libpcap的过滤规则)。

先创建接收线程,再发送syn扫描数据包。如果采用单线程,先发送再接收,则收不到任何数据。

在用libnet和libpcap设置网络设备时,一定要是有“真实”ip的设备,即:用此ip能够与目标主机通信,在我的机器上是ppp0(我用的ADSL),用eth0则不行。

源代码

//编译: gcc synscan.c -o synscan -lnet -lpcap -lpthread

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define LOCALPORT 55555

#define ETHERNET_LEN 14

#define SLEEP_TIME 1

#define TH_SYN 0x02

#define TH_ACK 0x10

//在我的机子上,网络设备必须设置为ppp0;如果为NULL,则libnet和libpcap会自动查找合适的网络设备

#ifdef __GUZHOU

# define DEVICE "ppp0"

#else

# define DEVICE NULL

#endif

#define RECV_IPPACKET_SIZE 40

static unsigned char recvbuf[RECV_IPPACKET_SIZE]; //接收缓存

#define TH_FLAG 33 //TCP标志位在recvbuf中的位置

struct syn_scanner

{

uint32_t dst_ip;

uint16_t dst_port;

};

static struct syn_scanner scanner;

static uint32_t gethostip(const char *name)

{

struct hostent *hostinfo = NULL;

uint32_t *addr = NULL;

hostinfo = gethostbyname(name);

if (!hostinfo)

return -1;

if (AF_INET != hostinfo->h_addrtype)

return -1;

addr = (uint32_t *) (hostinfo->h_addr_list[0]);

return *addr;

}

static uint32_t flag; //用于判断recvbuf是否为收到的分组

static void *recv_packet(void *arg)

{

flag = 0;

char *dev, errbuf[PCAP_ERRBUF_SIZE];

pcap_t *handle;

struct bpf_program fp;

bpf_u_int32 mask, net;

struct pcap_pkthdr header;

const unsigned char *packet;

char filter_exp[100] = "src host ";

char tmp[100] = " and src port ", t[10];

const struct syn_scanner *ss;

struct in_addr addr;

ss = (const struct syn_scanner *)arg;

if (NULL == ss)

{

fprintf(stderr, "arg is NULL/n");

return NULL;

}

dev = DEVICE;

if (NULL == dev)

{

dev = pcap_lookupdev(errbuf);

if (NULL == dev)

{

fprintf(stderr, "pcap_lookupdev() error/n");

return NULL;

}

}

printf("pcap Network interface: %s/n", dev);

if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1)

{

fprintf(stderr, "pcap_lookupnet() error/n");

return NULL;

}

handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);

if (NULL == handle)

{

fprintf(stderr, "pcap_open_live() error/n");

return NULL;

}

addr.s_addr = ss->dst_ip;

strcat(filter_exp, inet_ntoa(addr));

sprintf(t, "%u", ss->dst_port);

strcat(tmp, t);

strcat(filter_exp, tmp);

printf("filter: %s/n", filter_exp); //打印过滤规则

if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1)

{

fprintf(stderr, "pcap_compiler() error/n");

return NULL;

}

if (pcap_setfilter(handle, &fp) == -1)

{

fprintf(stderr, "pcap_setfilter() error");

return NULL;

}

packet = pcap_next(handle, &header); //若没有分组传过来,则会阻塞

printf("Jacked a packet with length of [%d]/n", header.len);

//把收到的分组从ip头开始的ETHERNET_LEN存到recvbuf中

int i;

packet += ETHERNET_LEN;

for (i = 0; i < RECV_IPPACKET_SIZE; i++)

recvbuf[i] = packet[i];

flag = 1;

return NULL;

}

static int send_syn(const struct syn_scanner *ss)

{

uint32_t src_ip, dst_ip;

uint16_t dst_port;

libnet_t *l;

char errbuf[LIBNET_ERRBUF_SIZE];

pthread_t recv;

dst_ip = ss->dst_ip;

dst_port = ss->dst_port;

l = libnet_init(LIBNET_RAW4, DEVICE, errbuf);

if (NULL == l)

{

fprintf(stderr, "libnet_init() error/n");

return -1;

}

src_ip = libnet_get_ipaddr4(l);

if (-1 == src_ip || 0 == src_ip)

{

fprintf(stderr, "libent_get_ipaddr4() error/n");

return -1;

}

printf("dst ip: %s, port: %u/n", inet_ntoa(*(struct in_addr *)&dst_ip), dst_port);

printf("src ip: %s/n", inet_ntoa(*(struct in_addr *)&src_ip));

if (libnet_build_tcp(LOCALPORT, dst_port, 0, 0, TH_SYN, 0, 0, 0, LIBNET_TCP_H, NULL, 0, l, 0) == -1)

{

fprintf(stderr, "libnet_build_tcp() error/n");

return -1;

}

if (libnet_build_ipv4

(LIBNET_IPV4_H + LIBNET_TCP_H, 0, 242, 0, 64, IPPROTO_TCP, 0, src_ip, dst_ip, NULL, 0, l, 0) == -1)

{

fprintf(stderr, "libnet_build_ipv4() error/n");

return -1;

}

if (libnet_write(l) == -1)

{

fprintf(stderr, "libnet_write() error/n");

return -1;

}

libnet_destroy(l);

return 1;

}

//解析分组,这里我简单地打印分组的内容

static void parse_packet(const unsigned char *buf, const unsigned int len)

{

int i;

printf("The buffer is:/n");

for (i = 0; i < len; i++)

printf("%u ", buf[i]);

putchar('/n');

}

int main(int argc, char **argv)

{

pthread_t recv;

void *retval;

if (3 != argc)

{

fprintf(stderr, "Usage: %s dst_ip dst_port/n", argv[0]);

return -1;

}

scanner.dst_ip = gethostip(argv[1]);

sscanf(argv[2], "%u", &(scanner.dst_port));

if (scanner.dst_ip == -1)

{

fprintf(stderr, "gethostip() error/n");

return -1;

}

printf("Scanning.../n");

//创建接收线程

if (pthread_create(&recv, NULL, recv_packet, &scanner))

{

fprintf(stderr, "pthread_create() error/n");

return -1;

}

if (send_syn(&scanner) == -1)

{

fprintf(stderr, "send_syn() error/n");

return -1;

}

pthread_join(recv,&retval);

if ((recvbuf[TH_FLAG] & TH_SYN) && (recvbuf[TH_FLAG] & TH_ACK))

printf("%s: %s is opend/n", argv[1], argv[2]);

else

printf("%s: %s is closed/n", argv[1], argv[2]);

if (flag)

parse_packet(recvbuf, RECV_IPPACKET_SIZE);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值