An open API service indexing awesome lists of open source software.

https://github.com/li1553770945/synscan

SYN scanner
https://github.com/li1553770945/synscan

handshake tcp

Last synced: 5 months ago
JSON representation

SYN scanner

Awesome Lists containing this project

README

          

# SYNScan
计网实验要求我们实现一个端口扫描器,可以扫描指定IP段的指定端口,写的过程中遇到了一些问题,在此记录一下。

## 端口扫描的三种方式

TCP端口扫描有三种方法:

1. 全TCP连接,这种方法使用三次握手与目标主机建立标准的tcp连接。但是这种方法跟容易被发现,被目标主机记录,而且效率较低。

2. SYN扫描,扫描主机自动向目标主机的指定端口发送SYN数据段,表示发送建立连接请求。如果目标主机的回应报文SYN=1,ACK=1.则说明该端口是活动的,接着扫描主机发送回一个RST给目标主机拒绝连接。导致三次握手失败。如果目标主机回应是RST则端口是“死的”。

3. FIN扫描,发送一个FIN=1的报文到一个关闭的窗口该报文将丢失并返回一个RST,如果该FIN报文发送到活动窗口则报文丢失,不会有任何反应。缺点是在部分OS上,表现可能不一样。

综合考虑,我最终使用了第二种方法。

## 介绍

+ 运行环境:ubuntu 20.04验证正常,wsl1会失败

## 使用方法

修改main.cpp中的

```cpp
string my_ip = "192.168.1.116";
string des_host = "192.168.1.1";
int mask = 24;
int min_port = 80;
int max_port = 8000;
```
如果需要扫描ip范围,则main中调用ScanRange(),如果要扫描特定ip,则main中调用ScanOneIp()。

然后直接运行build.sh,会自动编译并运行,需要输入一次密码。

## 步骤

### 创建socket

```cpp
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
int on = 1;
int opt = setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
if(sock < 0)
{
cout<<"sock:"<ip_dst.s_addr != inet_addr(my_ip))//不是发给自己的或者是127.0.0.1
{
continue;
}
if(ips.find(htonl(ip_ptr->ip_src.s_addr)) == ips.end())//不是要ping的ip
{
continue;
}

if(tcp_ptr->syn&&tcp_ptr->ack)
{
//cout<ip_src.s_addr))<<":"<source)<<"->"<ip_dst.s_addr))<<":"<dest)<syn<<" tcp.ack:"<ack<<" tcp.rst:"<rst<ip_src.s_addr)].insert(htons(tcp_ptr->source));
mtx.unlock();
}
// sleep(5);
}
```

由于接收是同步操作,而且recvfrom会把所有的符合条件的包都接收,不针对特定ip,因此我们只需要全局开一个接收线程即可。

## 遇到的问题

### wsl1下无法发送数据

这个问题很坑,我用的ubuntu18.04的发行版,但是不行,和真正的ubuntu18.04表现不一样。

### 大小端问题

注意发送的数据中ip和端口都是要经过htonl或htons转换的。