山东大学软件学院项目实训-创新实训-山大软院网络攻防靶场实验平台(二十一)-端口扫描工具


1.1、工具简介

端口扫描工具的主要功能就是用户输入一个IP地址,后端对其进行扫描,判断其端口的开放情况,如果开放,可能是什么服务。端口扫描这一工作主要是在渗透测试的信息收集阶段使用,通过扫描目标主机的端口开放情况,来进一步判断是否具有可利用的攻击点。信息收集在整个渗透测试过程中极其重要,直接关系到能否顺利渗透目标主机,信息收集的越全面,攻击者可利用的攻击点越多,越可能实现对目标主机的渗透。

功能介绍:

  • 对指定ip进行指定端口进行扫描,获取目的ip的端口开放情况
  • 扫描模式:TCP全连接扫描、TCP半连接扫描(待实现)
  • 通过发送空信息,获取开放端口对应服务的应答,获取指纹信息,从而判断服务类别
  • 端口开放情况会通过日志打印出来

输入:

  • ip地址或ip地址组,用逗号隔开
  • 待扫描的端口组:0-65535,左开右闭

输出:

  • 通过日志打印端口开放情况,并且返回数据到前端

1.2、后端实现代码

ScanApp.java:

扫描器启动类,接收前端请求的数据,启动Scanner类

package com.sducsrp.csrp.controller.ToolsController.ScanPort;

import com.sducsrp.csrp.common.Constants;
import com.sducsrp.csrp.common.Result;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;

/**
 * 扫描器启动类
 */
@RestController
@RequestMapping("/tools/")
public class ScanApp {
//    {ip='127.0.0.1', port=445, service='null', isOpen=true, banner='null'}
    public static String result;
    public int count = 0;
    @RequestMapping("/scan_port")
    public @ResponseBody Result scan(@RequestParam(value = "ips") String ips,
                                     @RequestParam(value = "ports") String ports,
                                     HttpServletResponse response){
        result="";
        // 待扫描的ip地址或ip地址组
        System.out.println(ips+" "+ports);
        Scanner.start(ips,ports);
        System.out.println("from ScanApp:"+result);

        Result res=new Result(Constants.CODE_200,null,result);
        return res;
    }
}

Scanner.java:

端口、指纹扫描器类

主要功能:

  1. 解析输入的ip地址、端口
  2. 新键扫描任务ScanJob扫描引擎进行端口扫描
  3. 两种扫描方式:TCP全连接扫描、TCP半连接扫描(未完成)

方法:

  • public static void start(String ips, String ports)

    开始方法:解析端口、IP地址

    @param ips 输入的待扫描ip列表

    @param ports 输入的待扫描端口

  • public static void scanAllPort(String ip, int portStart, int portEnd)

    扫描某ip的对应端口

    @param ip ip地址

    @param portStart 开始扫描的的端口

    @param portEnd 停止扫描的端口

  • public static void scan(String ip, int port)

    对ip:port进行扫描

    @param ip ip地址

    @param port 端口

package com.sducsrp.csrp.controller.ToolsController.ScanPort;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class Scanner {
    // 日志
    private static Logger logger = Logger.getLogger("Scanner");
    // 使用多线程扫描
    private static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(30,40,1000,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(5),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    /**
     * 开始方法
     * @param ips 输入的待扫描ip列表
     * @param ports 输入的待扫描端口
     */
    public static void start(String ips, String ports) {
        // 解析端口
        String[] portArray = ports.split("-");
        int portStart = Integer.parseInt(portArray[0]);
        int portEnd = Integer.parseInt(portArray[1]);
        logger.info("[-] Ports: " + ports);
        System.out.println("[-] Ports: " + ports);
        // 解析ip地址,并扫描
        if (ips.indexOf(',') != -1) {
            String[] ipList = ips.split(",");
            logger.info("[-] IP list: " + ipList.toString());
            System.out.println("[-] IP list: " + ipList.toString());
            for (String ip : ipList) {
                scanAllPort(ip,portStart,portEnd);
            }
        }else if (ips.indexOf('/') != -1){
            // TODO 支持ip地址网段的解析
            String[] ipArray = ips.split("/");
            String ipAddress = ipArray[0];
            int mask = Integer.parseInt(ipArray[1]);
            String[] ipSplit = ipAddress.split(".");

        }else {
            scanAllPort(ips,portStart,portEnd);
        }
        // 扫描任务都完成后,程序停止
        try{
            while(true){
                if(poolExecutor.getActiveCount() == 0){
                    logger.info("[-] Scan job all finish");
                    System.out.println("[-] Scan job all finish");
                    //System.exit(-1);
                    break;
                }
                Thread.sleep(1000);
            }
        }catch (Exception ex){
            logger.warning("End with exeception, ex: " + ex.getMessage());
            System.out.println("End with exeception, ex: " + ex.getMessage());
        }
        //System.exit(-1);

    }

    /**
     * 扫描某ip的对应端口
     * @param ip ip地址
     * @param portStart 开始扫描的的端口
     * @param portEnd 停止扫描的端口
     */
    public static void scanAllPort(String ip, int portStart, int portEnd){
        for (int port = portStart; port <= portEnd; port++){
            scan(ip,port);
        }
    }

    /**
     * 对ip:port进行扫描
     * @param ip ip地址
     * @param port 端口
     */
    public static void scan(String ip, int port){
        // 执行扫描任务
        poolExecutor.execute(new ScanJob(new ScanObject(ip,port), ScanEngine.TCP_FULL_CONNECT_SCAN));
    }
}

ScanJob.java:

扫描任务类,执行具体的扫描任务

package com.sducsrp.csrp.controller.ToolsController.ScanPort;

/**
 * 扫描任务类,执行具体的扫描任务
 */
public class ScanJob implements Runnable{
    // 扫描信息
    private ScanObject object;
    // 扫描类型
    private String scanType;

    public ScanJob(ScanObject object, String scanType) {
        this.object = object;
        this.scanType = scanType;

    }

    @Override
    public void run() {
        ScanEngine.scan(object, scanType);
    }
}

ScanEngine.java:

扫描器引擎

实现具体的扫描逻辑,提供扫描能力(TCP全连接和半连接扫描)

package com.sducsrp.csrp.controller.ToolsController.ScanPort;

import java.net.ConnectException;
import java.net.Socket;
import java.util.logging.Logger;

/**
 * 扫描器引擎
 * 实现具体的扫描逻辑,提供扫描能力(TCP全连接和半连接扫描)
 */
public class ScanEngine {
    private static Logger logger = Logger.getLogger("TCPFullConnectScan");
    public static final String TCP_FULL_CONNECT_SCAN = "TCP_FULL_CONNECT_SCAN";
    public static final String TCP_HALF_CONNECT_SCAN = "TCP_HALF_CONNECT_SCAN";

    public static ScanObject scan(ScanObject object, String scanEngine){
        switch (scanEngine){
            case TCP_FULL_CONNECT_SCAN:
                return tcpFullConnectScan(object);
            case TCP_HALF_CONNECT_SCAN:
                return tcpHalfConnectScan(object);
        }
        return tcpFullConnectScan(object);
    }

    /**
     * tcp全连接扫描
     * @param object
     * @return
     */
    private static ScanObject tcpFullConnectScan(ScanObject object){
        try{
            // 全连接扫描,发现可用服务
            Socket socket = new Socket(object.getIp(),object.getPort());
            object.setOpen(true);
            object.setService();
            logger.info("[-] Find service :"+ object);
            System.out.println("[-] Find service :"+ object);
            ScanApp.result=ScanApp.result+object;
            socket.close();
        } catch (ConnectException e) {

        } catch (Exception e){
            // 出现其他异常
            logger.info("[-] " + object.toString() + "end with unexecepted exeception:" + e.getMessage());
            System.out.println("[-] " + object.toString() + "end with unexecepted exeception:" + e.getMessage());
            ScanApp.result=ScanApp.result+object;
        }
        return object;

    }

    /**
     * TPC 半连接扫描
     * @param object
     * @return
     */
    private static ScanObject tcpHalfConnectScan(ScanObject object){
        // TODO 待实现tcp半连接扫描
        return object;
    }
}

ScanObject:

扫描信息实体

package com.sducsrp.csrp.controller.ToolsController.ScanPort;

import java.util.HashMap;
import java.util.Map;

/**
 * 扫描信息实体
 */
public class ScanObject {
     private String ip;
     private int port;
     private String service;
     private Boolean isOpen;
     private String banner;
     // 存放服务指纹和服务的对应关系 banner -> service
     private static Map<String,String> bannerMaps = new HashMap<>();
     // 存放常见端口与服务的对应关系 port -> service
     private static Map<Integer,String> portMaps = new HashMap<>();

     static {
         bannerMaps.put("ssh","SSH");
         portMaps.put(22,"SSH");
         bannerMaps.put("ftp","FTP");
         portMaps.put(21,"FTP");
         portMaps.put(20,"FTP");
         bannerMaps.put("smtp","SMTP");
         portMaps.put(25,"SMTP");
         bannerMaps.put("mysql","MySQL");
         portMaps.put(3306,"MySQL");
         bannerMaps.put("RemoteDesktop","RemoteDesktop");
         portMaps.put(3389,"RemoteDesktop");
     }

    public ScanObject(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    public Boolean getOpen() {
        return isOpen;
    }

    public void setOpen(Boolean open) {
        isOpen = open;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getService() {
        return service;
    }

    public void setService() {
         // 先根据port判断服务类型
        if (portMaps.containsKey(this.port)){
            this.service = portMaps.get(this.port);
        }
        if (banner != null && !banner.equals("")){
            for (String key : bannerMaps.keySet()) {
              if (banner.toLowerCase().contains(key)) {
                  this.service = bannerMaps.get(key);
                  break;
              }
            }
        }
    }

    public String getBanner() {
        return banner;
    }

    public void setBanner(String banner) {
        this.banner = banner;

    }

    @Override
    public String toString() {
        return ip +","+ port +"," + service +","  + isOpen +"," + banner+";";
    }
}

1.3、前端实现代码

<!--端口扫描工具-->
<!--把后端识别端口指纹的功能关闭掉了,不然太慢
1.设置响应时间更长
2.关闭指纹识别-->
<template>
  <div class="bf_form">
    <div class="bf_form_main">
      <h3 class="header blue lighter bigger">
        Please Enter Ips(Ip1,Ip2) And Ports(Port1-Ports2)
      </h3>
      <el-input v-model="ips" style="width: 250px;margin-right: 50px" placeholder="ips"></el-input>
      <el-input v-model="ports" style="width: 250px;margin-right: 50px" placeholder="ports"></el-input>
      <el-button @click="scan_start">scan</el-button>

    </div><!-- /.widget-main -->
  </div><!-- /.widget-body -->

  <el-card style="width: 40%;height: 500px;margin-left: 30%;margin-top: 5%">
    <p>返回结果:</p>
    <p>{{ myresult }}</p>
  </el-card>

</template>

<script>
// import router from '../../../router/index'
import request from "@/utils/request";

export default {
  data() {
    return {
      ips:'',
      ports:'',
      myresult:''
    }
  },
  methods:{
    scan_start(){
      request.get("/tools/scan_port",{
        params:{
          ips:this.ips,
          ports:this.ports
        }
      }).then(res =>{
        alert("1");
        this.myresult=res.data
      })
    }

  }
}
</script>

<style>
.wrapper {
  height: 100vh;
  background-image: linear-gradient(to bottom right, #000000, 	#483D8B);
  overflow: hidden;
}
</style>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌兮_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值