以下是一个示例代码,实现了基本的子域名扫描工具功能:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class SubdomainScanner extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;
    private static final int MAX_THREADS = 200;
    private static final int MAX_RETRIES = 3;
    private static final int TIMEOUT = 5000;

    private JTextField urlField;
    private JButton startButton;
    private JButton pauseButton;
    private JButton stopButton;
    private JButton importButton;
    private JLabel statusLabel;
    private JLabel countLabel;
    private JList<String> resultList;
    private JScrollPane resultScrollPane;

    private ThreadGroup threadGroup;
    private List<ScannerThread> threads;
    private List<String> subdomains;
    private List<String> results;
    private int totalCount;
    private int processedCount;

    public SubdomainScanner() {
        super('Subdomain Scanner');

        // Initialize UI components
        JPanel urlPanel = new JPanel(new BorderLayout());
        urlPanel.setBorder(BorderFactory.createTitledBorder('Target URL'));
        urlField = new JTextField('example.com');
        urlPanel.add(urlField, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
        startButton = new JButton('Start');
        startButton.addActionListener(this);
        buttonPanel.add(startButton);
        pauseButton = new JButton('Pause');
        pauseButton.addActionListener(this);
        pauseButton.setEnabled(false);
        buttonPanel.add(pauseButton);
        stopButton = new JButton('Stop');
        stopButton.addActionListener(this);
        stopButton.setEnabled(false);
        buttonPanel.add(stopButton);
        importButton = new JButton('Import');
        importButton.addActionListener(this);
        buttonPanel.add(importButton);

        JPanel statusPanel = new JPanel(new BorderLayout());
        statusPanel.setBorder(BorderFactory.createTitledBorder('Status'));
        statusLabel = new JLabel('Ready', SwingConstants.CENTER);
        statusLabel.setFont(statusLabel.getFont().deriveFont(Font.BOLD));
        statusPanel.add(statusLabel, BorderLayout.CENTER);
        countLabel = new JLabel('Processed: 0 / Total: 0');
        statusPanel.add(countLabel, BorderLayout.SOUTH);

        JPanel resultPanel = new JPanel(new BorderLayout());
        resultPanel.setBorder(BorderFactory.createTitledBorder('Results'));
        resultList = new JList<>();
        resultList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        resultScrollPane = new JScrollPane(resultList);
        resultScrollPane.setBorder(new LineBorder(Color.GRAY));
        resultPanel.add(resultScrollPane, BorderLayout.CENTER);

        JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
        mainPanel.add(urlPanel, BorderLayout.NORTH);
        mainPanel.add(buttonPanel, BorderLayout.CENTER);
        mainPanel.add(statusPanel, BorderLayout.SOUTH);
        mainPanel.add(resultPanel, BorderLayout.EAST);
        add(mainPanel);

        // Initialize variables
        threadGroup = new ThreadGroup('ScannerThreads');
        threads = new ArrayList<>();
        subdomains = new ArrayList<>();
        results = new ArrayList<>();
        totalCount = 0;
        processedCount = 0;

        // Set window properties
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(800, 600);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == startButton) {
            startButton.setEnabled(false);
            pauseButton.setEnabled(true);
            stopButton.setEnabled(true);
            importButton.setEnabled(false);
            statusLabel.setText('Scanning');
            countLabel.setText('Processed: 0 / Total: 0');
            threads.clear();
            results.clear();
            totalCount = 0;
            processedCount = 0;
            loadSubdomains();
            startThreads();
        } else if (e.getSource() == pauseButton) {
            pauseThreads();
        } else if (e.getSource() == stopButton) {
            stopThreads();
        } else if (e.getSource() == importButton) {
            importSubdomains();
        }
    }

    private void loadSubdomains() {
        String url = urlField.getText().trim().toLowerCase();
        if (!url.startsWith('http://') && !url.startsWith('https://')) {
            url = 'http://' + url;
        }
        try {
            InetAddress.getByName(url);
        } catch (UnknownHostException ex) {
            JOptionPane.showMessageDialog(this, 'Invalid URL', 'Error', JOptionPane.ERROR_MESSAGE);
            return;
        }
        subdomains.clear();
        try {
            File file = new File('subdomains.txt');
            if (file.exists() && file.isFile()) {
                BufferedReader reader = new BufferedReader(new FileReader(file));
                String line;
                while ((line = reader.readLine()) != null) {
                    line = line.trim().toLowerCase();
                    if (!line.isEmpty() && !subdomains.contains(line)) {
                        subdomains.add(line);
                    }
                }
                reader.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        if (subdomains.isEmpty()) {
            subdomains.add('www');
        }
        Collections.shuffle(subdomains);
        totalCount = subdomains.size();
        countLabel.setText('Processed: 0 / Total: ' + totalCount);
    }

    private void startThreads() {
        int numThreads = Math.min(subdomains.size(), MAX_THREADS);
        for (int i = 0; i < numThreads; i++) {
            ScannerThread thread = new ScannerThread(i);
            threads.add(thread);
            thread.start();
        }
    }

    private void pauseThreads() {
        for (ScannerThread thread : threads) {
            thread.pauseThread();
        }
        statusLabel.setText('Paused');
        startButton.setEnabled(true);
        pauseButton.setEnabled(false);
        stopButton.setEnabled(true);
        importButton.setEnabled(true);
    }

    private void stopThreads() {
        for (ScannerThread thread : threads) {
            thread.stopThread();
        }
        statusLabel.setText('Stopped');
        startButton.setEnabled(true);
        pauseButton.setEnabled(false);
        stopButton.setEnabled(false);
        importButton.setEnabled(true);
    }

    private void importSubdomains() {
        JFileChooser chooser = new JFileChooser();
        int result = chooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            subdomains.clear();
            try {
                BufferedReader reader = new BufferedReader(new FileReader(file));
                String line;
                while ((line = reader.readLine()) != null) {
                    line = line.trim().toLowerCase();
                    if (!line.isEmpty() && !subdomains.contains(line)) {
                        subdomains.add(line);
                    }
                }
                reader.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if (subdomains.isEmpty()) {
                subdomains.add('www');
            }
            Collections.shuffle(subdomains);
            totalCount = subdomains.size();
            countLabel.setText('Processed: 0 / Total: ' + totalCount);
        }
    }

    private synchronized void addResult(String result) {
        results.add(result);
        resultList.setListData(results.toArray(new String[0]));
    }

    private synchronized void updateCount() {
        processedCount++;
        countLabel.setText('Processed: ' + processedCount + ' / Total: ' + totalCount);
        if (processedCount == totalCount) {
            statusLabel.setText('Done');
            startButton.setEnabled(true);
            pauseButton.setEnabled(false);
            stopButton.setEnabled(false);
            importButton.setEnabled(true);
        }
    }

    private class ScannerThread extends Thread {

        private int index;
        private boolean running;
        private boolean paused;

        public ScannerThread(int index) {
            super(threadGroup, 'ScannerThread-' + index);
            this.index = index;
            this.running = true;
            this.paused = false;
        }

        public void pauseThread() {
            paused = true;
        }

        public void resumeThread() {
            paused = false;
        }

        public void stopThread() {
            running = false;
            interrupt();
        }

        @Override
        public void run() {
            while (running && !subdomains.isEmpty()) {
                if (!paused) {
                    String subdomain = subdomains.remove(0);
                    String url = subdomain + '.' + urlField.getText().trim().toLowerCase();
                    try {
                        InetAddress.getByName(url);
                        addResult(url);
                    } catch (UnknownHostException ex) {
                        for (int i = 0; i < MAX_RETRIES; i++) {
                            try {
                                Thread.sleep(TIMEOUT);
                                InetAddress.getByName(url);
                                addResult(url);
                                break;
                            } catch (UnknownHostException | InterruptedException e) {
                                // Ignore and retry
                            }
                        }
                    } finally {
                        updateCount();
                    }
                } else {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        // Ignore and continue
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        new SubdomainScanner();
    }
}

该代码使用了 Java Swing 构建了一个基本的 UI 界面,其中包含了一个文本框用于输入目标域名,一个按钮用于开始扫描,一个按钮用于暂停扫描,一个按钮用于停止扫描,一个按钮用于导入子域名字典,一个标签用于显示扫描状态,一个标签用于显示已处理/总数信息,以及一个列表框用于显示扫描结果。

扫描过程中使用了多线程,每个线程负责处理一个子域名。每个线程在处理子域名时,会先尝试进行 DNS 解析,如果解析成功则将该子域名添加到结果列表中,否则会进行最多三次的重试。每次重试之间会有 5 秒的等待时间。在处理完一个子域名后,该线程会更新已处理/总数信息,并检查是否还有未处理的子域名,如果有则继续处理,否则该线程就结束。

在 UI 界面中,点击 Start 按钮会开始扫描,点击 Pause 按钮会暂停扫描,点击 Stop 按钮会停止扫描,点击 Import 按钮会导入子域名字典。在扫描过程中,扫描状态会实时更新,已处理/总数信息会实时更新,结果列表会实时显示。在扫描完毕后,所有按钮会恢复到初始状态,并且结果列表会显示所有扫描到的子域名。

Java Swing 子域名扫描工具 - 多线程、暂停、停止功能

原文地址: https://www.cveoy.top/t/topic/lDwN 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录